From eaaaeef392cb245e415c31d480ed2d5a466fd88f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 14 Jun 2010 15:16:53 +0900 Subject: sh: Add kprobe-based event tracer. This follows the x86/ppc changes for kprobe-based event tracing on sh. While kprobes is only supported on 32-bit sh, we provide the API for HAVE_REGS_AND_STACK_ACCESS_API for both 32 and 64-bit. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 + arch/sh/include/asm/kprobes.h | 1 - arch/sh/include/asm/processor_32.h | 3 -- arch/sh/include/asm/processor_64.h | 3 -- arch/sh/include/asm/ptrace.h | 89 ++++++++++++++++++++++++++++++++++++-- arch/sh/kernel/Makefile | 2 +- arch/sh/kernel/ptrace.c | 33 ++++++++++++++ arch/sh/kernel/ptrace_32.c | 27 ++++++++++++ arch/sh/kernel/ptrace_64.c | 79 +++++++++++++++++++++++++++++++++ 9 files changed, 227 insertions(+), 11 deletions(-) create mode 100644 arch/sh/kernel/ptrace.c diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 573fca1fbd9b..e6b1f207f7ab 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -23,6 +23,7 @@ config SUPERH select HAVE_KERNEL_LZMA select HAVE_KERNEL_LZO select HAVE_SYSCALL_TRACEPOINTS + select HAVE_REGS_AND_STACK_ACCESS_API select RTC_LIB select GENERIC_ATOMIC64 help diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h index 036c3311233c..134f3980e44a 100644 --- a/arch/sh/include/asm/kprobes.h +++ b/arch/sh/include/asm/kprobes.h @@ -16,7 +16,6 @@ typedef insn_size_t kprobe_opcode_t; ? (MAX_STACK_SIZE) \ : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) -#define regs_return_value(_regs) ((_regs)->regs[0]) #define flush_insn_slot(p) do { } while (0) #define kretprobe_blacklist_size 0 diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index 61a445d2d02a..46d5179c9f49 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h @@ -13,7 +13,6 @@ #include #include #include -#include #include /* @@ -194,8 +193,6 @@ extern unsigned long get_wchan(struct task_struct *p); #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) #define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[15]) -#define user_stack_pointer(_regs) ((_regs)->regs[15]) - #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4) #define PREFETCH_STRIDE L1_CACHE_BYTES #define ARCH_HAS_PREFETCH diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h index 621bc4618c6b..2a541ddb5a1b 100644 --- a/arch/sh/include/asm/processor_64.h +++ b/arch/sh/include/asm/processor_64.h @@ -17,7 +17,6 @@ #include #include #include -#include #include /* @@ -231,7 +230,5 @@ extern unsigned long get_wchan(struct task_struct *p); #define KSTK_EIP(tsk) ((tsk)->thread.pc) #define KSTK_ESP(tsk) ((tsk)->thread.sp) -#define user_stack_pointer(_regs) ((_regs)->regs[15]) - #endif /* __ASSEMBLY__ */ #endif /* __ASM_SH_PROCESSOR_64_H */ diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h index 2168fde25611..33b3f37dcdbb 100644 --- a/arch/sh/include/asm/ptrace.h +++ b/arch/sh/include/asm/ptrace.h @@ -1,6 +1,8 @@ #ifndef __ASM_SH_PTRACE_H #define __ASM_SH_PTRACE_H +#include + /* * Copyright (C) 1999, 2000 Niibe Yutaka * @@ -14,6 +16,13 @@ struct pt_regs { unsigned long long tregs[8]; unsigned long long pad[2]; }; + +#define MAX_REG_OFFSET offsetof(struct pt_regs, tregs[7]) +#define regs_return_value(regs) ((regs)->regs[3]) + +#define TREGS_OFFSET_NAME(num) \ + {.name = __stringify(tr##num), .offset = offsetof(struct pt_regs, tregs[num])} + #else /* * GCC defines register number like this: @@ -66,6 +75,9 @@ struct pt_regs { long tra; }; +#define MAX_REG_OFFSET offsetof(struct pt_regs, tra) +#define regs_return_value(regs) ((regs)->regs[0]) + /* * This struct defines the way the DSP registers are stored on the * kernel stack during a system call or other kernel entry. @@ -113,16 +125,87 @@ struct pt_dspregs { #include #define user_mode(regs) (((regs)->sr & 0x40000000)==0) +#define user_stack_pointer(regs) ((unsigned long)(regs)->regs[15]) +#define kernel_stack_pointer(regs) ((unsigned long)(regs)->regs[15]) #define instruction_pointer(regs) ((unsigned long)(regs)->pc) extern void show_regs(struct pt_regs *); +#define arch_has_single_step() (1) + /* - * These are defined as per linux/ptrace.h. + * kprobe-based event tracer support */ -struct task_struct; +#include +#include -#define arch_has_single_step() (1) +struct pt_regs_offset { + const char *name; + int offset; +}; + +#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} +#define REGS_OFFSET_NAME(num) \ + {.name = __stringify(r##num), .offset = offsetof(struct pt_regs, regs[num])} +#define REG_OFFSET_END {.name = NULL, .offset = 0} + +/* Query offset/name of register from its name/offset */ +extern int regs_query_register_offset(const char *name); +extern const char *regs_query_register_name(unsigned int offset); + +extern const struct pt_regs_offset regoffset_table[]; + +/** + * regs_get_register() - get register value from its offset + * @regs: pt_regs from which register value is gotten. + * @offset: offset number of the register. + * + * regs_get_register returns the value of a register. The @offset is the + * offset of the register in struct pt_regs address which specified by @regs. + * If @offset is bigger than MAX_REG_OFFSET, this returns 0. + */ +static inline unsigned long regs_get_register(struct pt_regs *regs, + unsigned int offset) +{ + if (unlikely(offset > MAX_REG_OFFSET)) + return 0; + return *(unsigned long *)((unsigned long)regs + offset); +} + +/** + * regs_within_kernel_stack() - check the address in the stack + * @regs: pt_regs which contains kernel stack pointer. + * @addr: address which is checked. + * + * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). + * If @addr is within the kernel stack, it returns true. If not, returns false. + */ +static inline int regs_within_kernel_stack(struct pt_regs *regs, + unsigned long addr) +{ + return ((addr & ~(THREAD_SIZE - 1)) == + (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); +} + +/** + * regs_get_kernel_stack_nth() - get Nth entry of the stack + * @regs: pt_regs which contains kernel stack pointer. + * @n: stack entry number. + * + * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which + * is specified by @regs. If the @n th entry is NOT in the kernel stack, + * this returns 0. + */ +static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, + unsigned int n) +{ + unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); + addr += n; + if (regs_within_kernel_stack(regs, (unsigned long)addr)) + return *addr; + else + return 0; +} struct perf_event; struct perf_sample_data; diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index e25f3c69525d..1086ba1abdab 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -14,7 +14,7 @@ CFLAGS_REMOVE_return_address.o = -pg obj-y := clkdev.o debugtraps.o dma-nommu.o dumpstack.o \ idle.o io.o irq.o \ irq_$(BITS).o machvec.o nmi_debug.o process.o \ - process_$(BITS).o ptrace_$(BITS).o \ + process_$(BITS).o ptrace.o ptrace_$(BITS).o \ reboot.o return_address.o \ setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ syscalls_$(BITS).o time.o topology.o traps.o \ diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c new file mode 100644 index 000000000000..0a05983633ca --- /dev/null +++ b/arch/sh/kernel/ptrace.c @@ -0,0 +1,33 @@ +#include + +/** + * regs_query_register_offset() - query register offset from its name + * @name: the name of a register + * + * regs_query_register_offset() returns the offset of a register in struct + * pt_regs from its name. If the name is invalid, this returns -EINVAL; + */ +int regs_query_register_offset(const char *name) +{ + const struct pt_regs_offset *roff; + for (roff = regoffset_table; roff->name != NULL; roff++) + if (!strcmp(roff->name, name)) + return roff->offset; + return -EINVAL; +} + +/** + * regs_query_register_name() - query register name from its offset + * @offset: the offset of a register in struct pt_regs. + * + * regs_query_register_name() returns the name of a register from its + * offset in struct pt_regs. If the @offset is invalid, this returns NULL; + */ +const char *regs_query_register_name(unsigned int offset) +{ + const struct pt_regs_offset *roff; + for (roff = regoffset_table; roff->name != NULL; roff++) + if (roff->offset == offset) + return roff->name; + return NULL; +} diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index 6c4bbba2a675..2cd42b58cb20 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -274,6 +274,33 @@ static int dspregs_active(struct task_struct *target, } #endif +const struct pt_regs_offset regoffset_table[] = { + REGS_OFFSET_NAME(0), + REGS_OFFSET_NAME(1), + REGS_OFFSET_NAME(2), + REGS_OFFSET_NAME(3), + REGS_OFFSET_NAME(4), + REGS_OFFSET_NAME(5), + REGS_OFFSET_NAME(6), + REGS_OFFSET_NAME(7), + REGS_OFFSET_NAME(8), + REGS_OFFSET_NAME(9), + REGS_OFFSET_NAME(10), + REGS_OFFSET_NAME(11), + REGS_OFFSET_NAME(12), + REGS_OFFSET_NAME(13), + REGS_OFFSET_NAME(14), + REGS_OFFSET_NAME(15), + REG_OFFSET_NAME(pc), + REG_OFFSET_NAME(pr), + REG_OFFSET_NAME(sr), + REG_OFFSET_NAME(gbr), + REG_OFFSET_NAME(mach), + REG_OFFSET_NAME(macl), + REG_OFFSET_NAME(tra), + REG_OFFSET_END, +}; + /* * These are our native regset flavours. */ diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index 5fd644da7f02..b97817016b6a 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c @@ -252,6 +252,85 @@ static int fpregs_active(struct task_struct *target, } #endif +const struct pt_regs_offset regoffset_table[] = { + REG_OFFSET_NAME(pc), + REG_OFFSET_NAME(sr), + REG_OFFSET_NAME(syscall_nr), + REGS_OFFSET_NAME(0), + REGS_OFFSET_NAME(1), + REGS_OFFSET_NAME(2), + REGS_OFFSET_NAME(3), + REGS_OFFSET_NAME(4), + REGS_OFFSET_NAME(5), + REGS_OFFSET_NAME(6), + REGS_OFFSET_NAME(7), + REGS_OFFSET_NAME(8), + REGS_OFFSET_NAME(9), + REGS_OFFSET_NAME(10), + REGS_OFFSET_NAME(11), + REGS_OFFSET_NAME(12), + REGS_OFFSET_NAME(13), + REGS_OFFSET_NAME(14), + REGS_OFFSET_NAME(15), + REGS_OFFSET_NAME(16), + REGS_OFFSET_NAME(17), + REGS_OFFSET_NAME(18), + REGS_OFFSET_NAME(19), + REGS_OFFSET_NAME(20), + REGS_OFFSET_NAME(21), + REGS_OFFSET_NAME(22), + REGS_OFFSET_NAME(23), + REGS_OFFSET_NAME(24), + REGS_OFFSET_NAME(25), + REGS_OFFSET_NAME(26), + REGS_OFFSET_NAME(27), + REGS_OFFSET_NAME(28), + REGS_OFFSET_NAME(29), + REGS_OFFSET_NAME(30), + REGS_OFFSET_NAME(31), + REGS_OFFSET_NAME(32), + REGS_OFFSET_NAME(33), + REGS_OFFSET_NAME(34), + REGS_OFFSET_NAME(35), + REGS_OFFSET_NAME(36), + REGS_OFFSET_NAME(37), + REGS_OFFSET_NAME(38), + REGS_OFFSET_NAME(39), + REGS_OFFSET_NAME(40), + REGS_OFFSET_NAME(41), + REGS_OFFSET_NAME(42), + REGS_OFFSET_NAME(43), + REGS_OFFSET_NAME(44), + REGS_OFFSET_NAME(45), + REGS_OFFSET_NAME(46), + REGS_OFFSET_NAME(47), + REGS_OFFSET_NAME(48), + REGS_OFFSET_NAME(49), + REGS_OFFSET_NAME(50), + REGS_OFFSET_NAME(51), + REGS_OFFSET_NAME(52), + REGS_OFFSET_NAME(53), + REGS_OFFSET_NAME(54), + REGS_OFFSET_NAME(55), + REGS_OFFSET_NAME(56), + REGS_OFFSET_NAME(57), + REGS_OFFSET_NAME(58), + REGS_OFFSET_NAME(59), + REGS_OFFSET_NAME(60), + REGS_OFFSET_NAME(61), + REGS_OFFSET_NAME(62), + REGS_OFFSET_NAME(63), + TREGS_OFFSET_NAME(0), + TREGS_OFFSET_NAME(1), + TREGS_OFFSET_NAME(2), + TREGS_OFFSET_NAME(3), + TREGS_OFFSET_NAME(4), + TREGS_OFFSET_NAME(5), + TREGS_OFFSET_NAME(6), + TREGS_OFFSET_NAME(7), + REG_OFFSET_END, +}; + /* * These are our native regset flavours. */ -- cgit v1.2.3-59-g8ed1b From da28c597996a964a195529595c37f7aacd6dad09 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 14 Jun 2010 16:02:47 +0900 Subject: sh: split out ptrace header for _32/_64 variants. asm/ptrace.h is getting a bit messy, with the _32/_64-specific changes being fairly insular. This splits out the header accordingly. Signed-off-by: Paul Mundt --- arch/sh/include/asm/Kbuild | 2 + arch/sh/include/asm/ptrace.h | 110 +++++----------------------------------- arch/sh/include/asm/ptrace_32.h | 83 ++++++++++++++++++++++++++++++ arch/sh/include/asm/ptrace_64.h | 20 ++++++++ 4 files changed, 117 insertions(+), 98 deletions(-) create mode 100644 arch/sh/include/asm/ptrace_32.h create mode 100644 arch/sh/include/asm/ptrace_64.h diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index 46cb93477bcb..b4d3462f1dc3 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild @@ -8,3 +8,5 @@ unifdef-y += unistd_32.h unifdef-y += unistd_64.h unifdef-y += posix_types_32.h unifdef-y += posix_types_64.h +unifdef-y += ptrace_32.h +unifdef-y += ptrace_64.h diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h index 33b3f37dcdbb..f6edc10aa0d3 100644 --- a/arch/sh/include/asm/ptrace.h +++ b/arch/sh/include/asm/ptrace.h @@ -1,104 +1,9 @@ #ifndef __ASM_SH_PTRACE_H #define __ASM_SH_PTRACE_H -#include - /* * Copyright (C) 1999, 2000 Niibe Yutaka - * - */ -#if defined(__SH5__) -struct pt_regs { - unsigned long long pc; - unsigned long long sr; - long long syscall_nr; - unsigned long long regs[63]; - unsigned long long tregs[8]; - unsigned long long pad[2]; -}; - -#define MAX_REG_OFFSET offsetof(struct pt_regs, tregs[7]) -#define regs_return_value(regs) ((regs)->regs[3]) - -#define TREGS_OFFSET_NAME(num) \ - {.name = __stringify(tr##num), .offset = offsetof(struct pt_regs, tregs[num])} - -#else -/* - * GCC defines register number like this: - * ----------------------------- - * 0 - 15 are integer registers - * 17 - 22 are control/special registers - * 24 - 39 fp registers - * 40 - 47 xd registers - * 48 - fpscr register - * ----------------------------- - * - * We follows above, except: - * 16 --- program counter (PC) - * 22 --- syscall # - * 23 --- floating point communication register - */ -#define REG_REG0 0 -#define REG_REG15 15 - -#define REG_PC 16 - -#define REG_PR 17 -#define REG_SR 18 -#define REG_GBR 19 -#define REG_MACH 20 -#define REG_MACL 21 - -#define REG_SYSCALL 22 - -#define REG_FPREG0 23 -#define REG_FPREG15 38 -#define REG_XFREG0 39 -#define REG_XFREG15 54 - -#define REG_FPSCR 55 -#define REG_FPUL 56 - -/* - * This struct defines the way the registers are stored on the - * kernel stack during a system call or other kernel entry. - */ -struct pt_regs { - unsigned long regs[16]; - unsigned long pc; - unsigned long pr; - unsigned long sr; - unsigned long gbr; - unsigned long mach; - unsigned long macl; - long tra; -}; - -#define MAX_REG_OFFSET offsetof(struct pt_regs, tra) -#define regs_return_value(regs) ((regs)->regs[0]) - -/* - * This struct defines the way the DSP registers are stored on the - * kernel stack during a system call or other kernel entry. */ -struct pt_dspregs { - unsigned long a1; - unsigned long a0g; - unsigned long a1g; - unsigned long m0; - unsigned long m1; - unsigned long a0; - unsigned long x0; - unsigned long x1; - unsigned long y0; - unsigned long y1; - unsigned long dsr; - unsigned long rs; - unsigned long re; - unsigned long mod; -}; -#endif #define PTRACE_GETREGS 12 /* General registers */ #define PTRACE_SETREGS 13 @@ -119,7 +24,17 @@ struct pt_dspregs { #define PT_DATA_ADDR 248 /* &(struct user)->start_data */ #define PT_TEXT_LEN 252 +#if defined(__SH5__) || defined(CONFIG_CPU_SH5) +#include "ptrace_64.h" +#else +#include "ptrace_32.h" +#endif + #ifdef __KERNEL__ + +#include +#include +#include #include #include #include @@ -136,9 +51,6 @@ extern void show_regs(struct pt_regs *); /* * kprobe-based event tracer support */ -#include -#include - struct pt_regs_offset { const char *name; int offset; @@ -147,6 +59,8 @@ struct pt_regs_offset { #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} #define REGS_OFFSET_NAME(num) \ {.name = __stringify(r##num), .offset = offsetof(struct pt_regs, regs[num])} +#define TREGS_OFFSET_NAME(num) \ + {.name = __stringify(tr##num), .offset = offsetof(struct pt_regs, tregs[num])} #define REG_OFFSET_END {.name = NULL, .offset = 0} /* Query offset/name of register from its name/offset */ diff --git a/arch/sh/include/asm/ptrace_32.h b/arch/sh/include/asm/ptrace_32.h new file mode 100644 index 000000000000..35d9e257558c --- /dev/null +++ b/arch/sh/include/asm/ptrace_32.h @@ -0,0 +1,83 @@ +#ifndef __ASM_SH_PTRACE_32_H +#define __ASM_SH_PTRACE_32_H + +/* + * GCC defines register number like this: + * ----------------------------- + * 0 - 15 are integer registers + * 17 - 22 are control/special registers + * 24 - 39 fp registers + * 40 - 47 xd registers + * 48 - fpscr register + * ----------------------------- + * + * We follows above, except: + * 16 --- program counter (PC) + * 22 --- syscall # + * 23 --- floating point communication register + */ +#define REG_REG0 0 +#define REG_REG15 15 + +#define REG_PC 16 + +#define REG_PR 17 +#define REG_SR 18 +#define REG_GBR 19 +#define REG_MACH 20 +#define REG_MACL 21 + +#define REG_SYSCALL 22 + +#define REG_FPREG0 23 +#define REG_FPREG15 38 +#define REG_XFREG0 39 +#define REG_XFREG15 54 + +#define REG_FPSCR 55 +#define REG_FPUL 56 + +/* + * This struct defines the way the registers are stored on the + * kernel stack during a system call or other kernel entry. + */ +struct pt_regs { + unsigned long regs[16]; + unsigned long pc; + unsigned long pr; + unsigned long sr; + unsigned long gbr; + unsigned long mach; + unsigned long macl; + long tra; +}; + +/* + * This struct defines the way the DSP registers are stored on the + * kernel stack during a system call or other kernel entry. + */ +struct pt_dspregs { + unsigned long a1; + unsigned long a0g; + unsigned long a1g; + unsigned long m0; + unsigned long m1; + unsigned long a0; + unsigned long x0; + unsigned long x1; + unsigned long y0; + unsigned long y1; + unsigned long dsr; + unsigned long rs; + unsigned long re; + unsigned long mod; +}; + +#ifdef __KERNEL__ + +#define MAX_REG_OFFSET offsetof(struct pt_regs, tra) +#define regs_return_value(regs) ((regs)->regs[0]) + +#endif /* __KERNEL__ */ + +#endif /* __ASM_SH_PTRACE_32_H */ diff --git a/arch/sh/include/asm/ptrace_64.h b/arch/sh/include/asm/ptrace_64.h new file mode 100644 index 000000000000..d43c1cb0bbe7 --- /dev/null +++ b/arch/sh/include/asm/ptrace_64.h @@ -0,0 +1,20 @@ +#ifndef __ASM_SH_PTRACE_64_H +#define __ASM_SH_PTRACE_64_H + +struct pt_regs { + unsigned long long pc; + unsigned long long sr; + long long syscall_nr; + unsigned long long regs[63]; + unsigned long long tregs[8]; + unsigned long long pad[2]; +}; + +#ifdef __KERNEL__ + +#define MAX_REG_OFFSET offsetof(struct pt_regs, tregs[7]) +#define regs_return_value(regs) ((regs)->regs[3]) + +#endif /* __KERNEL__ */ + +#endif /* __ASM_SH_PTRACE_64_H */ -- cgit v1.2.3-59-g8ed1b From 57fcfdf9b2bbe8ea47771ffc16c418a20e4173c6 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 14 Jun 2010 17:06:10 +0900 Subject: sh: kprobes SMP support. Presently kprobes support relies on several saved opcode variables for saving and restoring state, without any specific locking. This is inherently racy on SMP, and given that we already use per-CPU variables for everything else, convert these over too. Signed-off-by: Paul Mundt --- arch/sh/kernel/kprobes.c | 100 +++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/arch/sh/kernel/kprobes.c b/arch/sh/kernel/kprobes.c index 4049d99f76e1..1208b09e95c3 100644 --- a/arch/sh/kernel/kprobes.c +++ b/arch/sh/kernel/kprobes.c @@ -20,9 +20,9 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); -static struct kprobe saved_current_opcode; -static struct kprobe saved_next_opcode; -static struct kprobe saved_next_opcode2; +static DEFINE_PER_CPU(struct kprobe, saved_current_opcode); +static DEFINE_PER_CPU(struct kprobe, saved_next_opcode); +static DEFINE_PER_CPU(struct kprobe, saved_next_opcode2); #define OPCODE_JMP(x) (((x) & 0xF0FF) == 0x402b) #define OPCODE_JSR(x) (((x) & 0xF0FF) == 0x400b) @@ -102,16 +102,21 @@ int __kprobes kprobe_handle_illslot(unsigned long pc) void __kprobes arch_remove_kprobe(struct kprobe *p) { - if (saved_next_opcode.addr != 0x0) { + struct kprobe *saved = &__get_cpu_var(saved_next_opcode); + + if (saved->addr) { arch_disarm_kprobe(p); - arch_disarm_kprobe(&saved_next_opcode); - saved_next_opcode.addr = 0x0; - saved_next_opcode.opcode = 0x0; - - if (saved_next_opcode2.addr != 0x0) { - arch_disarm_kprobe(&saved_next_opcode2); - saved_next_opcode2.addr = 0x0; - saved_next_opcode2.opcode = 0x0; + arch_disarm_kprobe(saved); + + saved->addr = NULL; + saved->opcode = 0; + + saved = &__get_cpu_var(saved_next_opcode2); + if (saved->addr) { + arch_disarm_kprobe(saved); + + saved->addr = NULL; + saved->opcode = 0; } } } @@ -141,57 +146,59 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, */ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) { - kprobe_opcode_t *addr = NULL; - saved_current_opcode.addr = (kprobe_opcode_t *) (regs->pc); - addr = saved_current_opcode.addr; + __get_cpu_var(saved_current_opcode).addr = (kprobe_opcode_t *)regs->pc; if (p != NULL) { + struct kprobe *op1, *op2; + arch_disarm_kprobe(p); + op1 = &__get_cpu_var(saved_next_opcode); + op2 = &__get_cpu_var(saved_next_opcode2); + if (OPCODE_JSR(p->opcode) || OPCODE_JMP(p->opcode)) { unsigned int reg_nr = ((p->opcode >> 8) & 0x000F); - saved_next_opcode.addr = - (kprobe_opcode_t *) regs->regs[reg_nr]; + op1->addr = (kprobe_opcode_t *) regs->regs[reg_nr]; } else if (OPCODE_BRA(p->opcode) || OPCODE_BSR(p->opcode)) { unsigned long disp = (p->opcode & 0x0FFF); - saved_next_opcode.addr = + op1->addr = (kprobe_opcode_t *) (regs->pc + 4 + disp * 2); } else if (OPCODE_BRAF(p->opcode) || OPCODE_BSRF(p->opcode)) { unsigned int reg_nr = ((p->opcode >> 8) & 0x000F); - saved_next_opcode.addr = + op1->addr = (kprobe_opcode_t *) (regs->pc + 4 + regs->regs[reg_nr]); } else if (OPCODE_RTS(p->opcode)) { - saved_next_opcode.addr = (kprobe_opcode_t *) regs->pr; + op1->addr = (kprobe_opcode_t *) regs->pr; } else if (OPCODE_BF(p->opcode) || OPCODE_BT(p->opcode)) { unsigned long disp = (p->opcode & 0x00FF); /* case 1 */ - saved_next_opcode.addr = p->addr + 1; + op1->addr = p->addr + 1; /* case 2 */ - saved_next_opcode2.addr = + op2->addr = (kprobe_opcode_t *) (regs->pc + 4 + disp * 2); - saved_next_opcode2.opcode = *(saved_next_opcode2.addr); - arch_arm_kprobe(&saved_next_opcode2); + op2->opcode = *(op2->addr); + arch_arm_kprobe(op2); } else if (OPCODE_BF_S(p->opcode) || OPCODE_BT_S(p->opcode)) { unsigned long disp = (p->opcode & 0x00FF); /* case 1 */ - saved_next_opcode.addr = p->addr + 2; + op1->addr = p->addr + 2; /* case 2 */ - saved_next_opcode2.addr = + op2->addr = (kprobe_opcode_t *) (regs->pc + 4 + disp * 2); - saved_next_opcode2.opcode = *(saved_next_opcode2.addr); - arch_arm_kprobe(&saved_next_opcode2); + op2->opcode = *(op2->addr); + arch_arm_kprobe(op2); } else { - saved_next_opcode.addr = p->addr + 1; + op1->addr = p->addr + 1; } - saved_next_opcode.opcode = *(saved_next_opcode.addr); - arch_arm_kprobe(&saved_next_opcode); + op1->opcode = *(op1->addr); + arch_arm_kprobe(op1); } } @@ -376,21 +383,23 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs) cur->post_handler(cur, regs, 0); } - if (saved_next_opcode.addr != 0x0) { - arch_disarm_kprobe(&saved_next_opcode); - saved_next_opcode.addr = 0x0; - saved_next_opcode.opcode = 0x0; + p = &__get_cpu_var(saved_next_opcode); + if (p->addr) { + arch_disarm_kprobe(p); + p->addr = NULL; + p->opcode = 0; - addr = saved_current_opcode.addr; - saved_current_opcode.addr = 0x0; + addr = __get_cpu_var(saved_current_opcode).addr; + __get_cpu_var(saved_current_opcode).addr = NULL; p = get_kprobe(addr); arch_arm_kprobe(p); - if (saved_next_opcode2.addr != 0x0) { - arch_disarm_kprobe(&saved_next_opcode2); - saved_next_opcode2.addr = 0x0; - saved_next_opcode2.opcode = 0x0; + p = &__get_cpu_var(saved_next_opcode2); + if (p->addr) { + arch_disarm_kprobe(p); + p->addr = NULL; + p->opcode = 0; } } @@ -572,14 +581,5 @@ static struct kprobe trampoline_p = { int __init arch_init_kprobes(void) { - saved_next_opcode.addr = 0x0; - saved_next_opcode.opcode = 0x0; - - saved_current_opcode.addr = 0x0; - saved_current_opcode.opcode = 0x0; - - saved_next_opcode2.addr = 0x0; - saved_next_opcode2.opcode = 0x0; - return register_kprobe(&trampoline_p); } -- cgit v1.2.3-59-g8ed1b From 9a9fcfa04e86d26dd6129eb08165b696d602a118 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 14 Jun 2010 18:02:13 +0900 Subject: sh: update the FDPIC relocations. Now that the FDPIC relocations have been given fixed numbers upstream, switch to using those. The previous values only applied to experimental toolchains that never made it in to the wild, so the impact remains minimal. Signed-off-by: Paul Mundt --- arch/sh/include/asm/elf.h | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/arch/sh/include/asm/elf.h b/arch/sh/include/asm/elf.h index ce830faeebbf..f38112be67d2 100644 --- a/arch/sh/include/asm/elf.h +++ b/arch/sh/include/asm/elf.h @@ -50,25 +50,14 @@ #define R_SH_GOTPC 167 /* FDPIC relocs */ -#define R_SH_GOT20 70 -#define R_SH_GOTOFF20 71 -#define R_SH_GOTFUNCDESC 72 -#define R_SH_GOTFUNCDESC20 73 -#define R_SH_GOTOFFFUNCDESC 74 -#define R_SH_GOTOFFFUNCDESC20 75 -#define R_SH_FUNCDESC 76 -#define R_SH_FUNCDESC_VALUE 77 - -#if 0 /* XXX - later .. */ -#define R_SH_GOT20 198 -#define R_SH_GOTOFF20 199 -#define R_SH_GOTFUNCDESC 200 -#define R_SH_GOTFUNCDESC20 201 -#define R_SH_GOTOFFFUNCDESC 202 -#define R_SH_GOTOFFFUNCDESC20 203 -#define R_SH_FUNCDESC 204 -#define R_SH_FUNCDESC_VALUE 205 -#endif +#define R_SH_GOT20 201 +#define R_SH_GOTOFF20 202 +#define R_SH_GOTFUNCDESC 203 +#define R_SH_GOTFUNCDESC20 204 +#define R_SH_GOTOFFFUNCDESC 205 +#define R_SH_GOTOFFFUNCDESC20 206 +#define R_SH_FUNCDESC 207 +#define R_SH_FUNCDESC_VALUE 208 /* SHmedia relocs */ #define R_SH_IMM_LOW16 246 -- cgit v1.2.3-59-g8ed1b From 3a598264436e94c410c413088a7873fcad33616c Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Mon, 21 Jun 2010 15:10:51 +0900 Subject: sh: SH-2007 board support. This patch series adds support for ITO Co., Ltd.'s SH-2007 reference platform (A PC-104 based SH7780 platform). This is a direct port of the out-of-tree board support from the vendor's kernel, originally located at: http://ms-n.org/sh-linux/kernel/ More information on the board and the vendor can be obtained from the vendor's site at: http://www.itonet.co.jp/ Presently supported peripherals are CF and ethernet, with support for the on-board IDE still pending further testing. Reviewed-by: Nobuhiro Iwamatsu Reviewed-by: Magnus Damm Signed-off-by: Hitoshi Mitake Signed-off-by: Paul Mundt --- arch/sh/boards/Kconfig | 11 + arch/sh/boards/Makefile | 1 + arch/sh/boards/board-sh2007.c | 133 +++ arch/sh/configs/sh2007_defconfig | 1357 +++++++++++++++++++++++++++++ arch/sh/include/mach-common/mach/sh2007.h | 117 +++ arch/sh/tools/mach-types | 1 + drivers/serial/sh-sci.h | 17 +- 7 files changed, 1633 insertions(+), 4 deletions(-) create mode 100644 arch/sh/boards/board-sh2007.c create mode 100644 arch/sh/configs/sh2007_defconfig create mode 100644 arch/sh/include/mach-common/mach/sh2007.h diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 07b35ca2f644..65abfd41bd79 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -309,6 +309,17 @@ config SH_POLARIS help Select if configuring for an SMSC Polaris development board +config SH_SH2007 + bool "SH-2007 board" + select NO_IOPORT + depends on CPU_SUBTYPE_SH7780 + help + SH-2007 is a single-board computer based around SH7780 chip + intended for embedded applications. + It has an Ethernet interface (SMC9118), direct connected + Compact Flash socket, two serial ports and PC-104 bus. + More information at . + endmenu source "arch/sh/boards/mach-r2d/Kconfig" diff --git a/arch/sh/boards/Makefile b/arch/sh/boards/Makefile index 4f90f9b7a922..2049d95feaaa 100644 --- a/arch/sh/boards/Makefile +++ b/arch/sh/boards/Makefile @@ -2,6 +2,7 @@ # Specific board support, not covered by a mach group. # obj-$(CONFIG_SH_MAGIC_PANEL_R2) += board-magicpanelr2.o +obj-$(CONFIG_SH_SH2007) += board-sh2007.o obj-$(CONFIG_SH_SH7785LCR) += board-sh7785lcr.o obj-$(CONFIG_SH_URQUELL) += board-urquell.o obj-$(CONFIG_SH_SHMIN) += board-shmin.o diff --git a/arch/sh/boards/board-sh2007.c b/arch/sh/boards/board-sh2007.c new file mode 100644 index 000000000000..b90b78f6a829 --- /dev/null +++ b/arch/sh/boards/board-sh2007.c @@ -0,0 +1,133 @@ +/* + * SH-2007 board support. + * + * Copyright (C) 2003, 2004 SUGIOKA Toshinobu + * Copyright (C) 2010 Hitoshi Mitake + */ +#include +#include +#include +#include +#include +#include +#include +#include + +struct smsc911x_platform_config smc911x_info = { + .flags = SMSC911X_USE_32BIT, + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, +}; + +static struct resource smsc9118_0_resources[] = { + [0] = { + .start = SMC0_BASE, + .end = SMC0_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = evt2irq(0x240), + .end = evt2irq(0x240), + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource smsc9118_1_resources[] = { + [0] = { + .start = SMC1_BASE, + .end = SMC1_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = evt2irq(0x280), + .end = evt2irq(0x280), + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device smsc9118_0_device = { + .name = "smsc911x", + .id = 0, + .num_resources = ARRAY_SIZE(smsc9118_0_resources), + .resource = smsc9118_0_resources, + .dev = { + .platform_data = &smc911x_info, + }, +}; + +static struct platform_device smsc9118_1_device = { + .name = "smsc911x", + .id = 1, + .num_resources = ARRAY_SIZE(smsc9118_1_resources), + .resource = smsc9118_1_resources, + .dev = { + .platform_data = &smc911x_info, + }, +}; + +static struct resource cf_resources[] = { + [0] = { + .start = CF_BASE + CF_OFFSET, + .end = CF_BASE + CF_OFFSET + 0x0f, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = CF_BASE + CF_OFFSET + 0x206, + .end = CF_BASE + CF_OFFSET + 0x20f, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = evt2irq(0x2c0), + .end = evt2irq(0x2c0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cf_device = { + .name = "pata_platform", + .id = 0, + .num_resources = ARRAY_SIZE(cf_resources), + .resource = cf_resources, +}; + +static struct platform_device *sh2007_devices[] __initdata = { + &smsc9118_0_device, + &smsc9118_1_device, + &cf_device, +}; + +static int __init sh2007_io_init(void) +{ + platform_add_devices(sh2007_devices, ARRAY_SIZE(sh2007_devices)); + return 0; +} +subsys_initcall(sh2007_io_init); + +static void __init sh2007_init_irq(void) +{ + plat_irq_setup_pins(IRQ_MODE_IRQ); +} + +/* + * Initialize the board + */ +static void __init sh2007_setup(char **cmdline_p) +{ + printk(KERN_INFO "SH-2007 Setup..."); + + /* setup wait control registers for area 5 */ + __raw_writel(CS5BCR_D, CS5BCR); + __raw_writel(CS5WCR_D, CS5WCR); + __raw_writel(CS5PCR_D, CS5PCR); + + printk(KERN_INFO " done.\n"); +} + +/* + * The Machine Vector + */ +struct sh_machine_vector mv_sh2007 __initmv = { + .mv_setup = sh2007_setup, + .mv_name = "sh2007", + .mv_init_irq = sh2007_init_irq, +}; diff --git a/arch/sh/configs/sh2007_defconfig b/arch/sh/configs/sh2007_defconfig new file mode 100644 index 000000000000..adf7a6b05814 --- /dev/null +++ b/arch/sh/configs/sh2007_defconfig @@ -0,0 +1,1357 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.35-rc2 +# Fri Jun 18 19:46:14 2010 +# +CONFIG_SUPERH=y +CONFIG_SUPERH32=y +# CONFIG_SUPERH64 is not set +CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig" +CONFIG_RWSEM_GENERIC_SPINLOCK=y +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_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y +# CONFIG_GENERIC_GPIO is not set +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +# CONFIG_ARCH_SUSPEND_POSSIBLE is not set +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_SYS_SUPPORTS_TMU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_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_HAS_DEFAULT_IDLE=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_NO_IOPORT=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_TREE=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_TINY_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +# CONFIG_IKCONFIG_PROC is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +# CONFIG_MODULES is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# System type +# +CONFIG_CPU_SH4=y +CONFIG_CPU_SH4A=y +# CONFIG_CPU_SUBTYPE_SH7619 is not set +# CONFIG_CPU_SUBTYPE_SH7201 is not set +# CONFIG_CPU_SUBTYPE_SH7203 is not set +# CONFIG_CPU_SUBTYPE_SH7206 is not set +# CONFIG_CPU_SUBTYPE_SH7263 is not set +# CONFIG_CPU_SUBTYPE_MXG is not set +# CONFIG_CPU_SUBTYPE_SH7705 is not set +# CONFIG_CPU_SUBTYPE_SH7706 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7710 is not set +# CONFIG_CPU_SUBTYPE_SH7712 is not set +# CONFIG_CPU_SUBTYPE_SH7720 is not set +# CONFIG_CPU_SUBTYPE_SH7721 is not set +# CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set +# CONFIG_CPU_SUBTYPE_SH7723 is not set +# CONFIG_CPU_SUBTYPE_SH7724 is not set +# CONFIG_CPU_SUBTYPE_SH7757 is not set +# CONFIG_CPU_SUBTYPE_SH7763 is not set +# CONFIG_CPU_SUBTYPE_SH7770 is not set +CONFIG_CPU_SUBTYPE_SH7780=y +# CONFIG_CPU_SUBTYPE_SH7785 is not set +# CONFIG_CPU_SUBTYPE_SH7786 is not set +# CONFIG_CPU_SUBTYPE_SHX3 is not set +# CONFIG_CPU_SUBTYPE_SH7343 is not set +# CONFIG_CPU_SUBTYPE_SH7722 is not set +# CONFIG_CPU_SUBTYPE_SH7366 is not set + +# +# Memory management options +# +CONFIG_QUICKLIST=y +CONFIG_MMU=y +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_MEMORY_START=0x08000000 +CONFIG_MEMORY_SIZE=0x08000000 +CONFIG_29BIT=y +# CONFIG_PMB is not set +# CONFIG_VSYSCALL is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_MAX_ACTIVE_REGIONS=1 +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_NR_QUICK=1 +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 + +# +# Cache configuration +# +CONFIG_CACHE_WRITEBACK=y +# CONFIG_CACHE_WRITETHROUGH is not set +# CONFIG_CACHE_OFF is not set + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SH_FPU=y +# CONFIG_SH_STORE_QUEUES is not set +# CONFIG_SPECULATIVE_EXECUTION is not set +CONFIG_CPU_HAS_INTEVT=y +CONFIG_CPU_HAS_SR_RB=y +CONFIG_CPU_HAS_FPU=y + +# +# Board support +# +# CONFIG_SH_7780_SOLUTION_ENGINE is not set +# CONFIG_SH_SDK7780 is not set +# CONFIG_SH_HIGHLANDER is not set +CONFIG_SH_SH2007=y + +# +# Timer and clock configuration +# +CONFIG_SH_TIMER_TMU=y +CONFIG_SH_PCLK_FREQ=50000000 +CONFIG_SH_CLK_CPG=y +CONFIG_SH_CLK_CPG_LEGACY=y +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# DMA support +# +CONFIG_SH_DMA=y +CONFIG_SH_DMA_IRQ_MULTI=y +CONFIG_SH_DMA_API=y +CONFIG_NR_ONCHIP_DMA_CHANNELS=12 +CONFIG_NR_DMA_CHANNELS_BOOL=y +CONFIG_NR_DMA_CHANNELS=12 + +# +# Companion Chips +# + +# +# Additional SuperH Device Drivers +# +# CONFIG_HEARTBEAT is not set +# CONFIG_PUSH_SWITCH is not set + +# +# Kernel features +# +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_SECCOMP is not set +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_GUSA=y +# CONFIG_INTC_USERIMASK is not set + +# +# Boot options +# +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +CONFIG_ENTRY_OFFSET=0x00001000 +CONFIG_CMDLINE_OVERWRITE=y +# CONFIG_CMDLINE_EXTEND is not set +CONFIG_CMDLINE="console=ttySC1,115200 ip=dhcp root=/dev/nfs rw nfsroot=/nfs/rootfs,rsize=1024,wsize=1024 earlyprintk=sh-sci.1" + +# +# Bus options +# +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCCARD=y +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y + +# +# PC-card bridges +# + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options (EXPERIMENTAL) +# +# CONFIG_PM is not set +# CONFIG_CPU_IDLE is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +CONFIG_XFRM_MIGRATE=y +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +CONFIG_NET_IPIP=y +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +CONFIG_NETWORK_SECMARK=y +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +CONFIG_NET_PKTGEN=y +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# + +# +# Some wireless drivers require a rate control algorithm +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MISC_DEVICES is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +CONFIG_RAID_ATTRS=y +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +CONFIG_SCSI_TGT=y +CONFIG_SCSI_NETLINK=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=y +CONFIG_SCSI_FC_ATTRS=y +# CONFIG_SCSI_FC_TGT_ATTRS is not set +CONFIG_SCSI_ISCSI_ATTRS=y +# CONFIG_SCSI_SAS_LIBSAS is not set +CONFIG_SCSI_SRP_ATTRS=y +# CONFIG_SCSI_SRP_TGT_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +CONFIG_EQUALIZER=y +CONFIG_TUN=y +CONFIG_VETH=y +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_STNIC is not set +# CONFIG_SMC91X is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +CONFIG_SMSC911X=y +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_NET_PCMCIA is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=y +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_DEVKMEM is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SH_SCI=y +CONFIG_SERIAL_SH_SCI_NR_UARTS=2 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_IPWIRELESS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_SH_WDT=y +# CONFIG_SH_WDT_MMAP is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=y +CONFIG_SSB_PCMCIAHOST_POSSIBLE=y +# CONFIG_SSB_PCMCIAHOST is not set +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +CONFIG_MFD_SUPPORT=y +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SH_MOBILE_SDHI is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SH_MOBILE_LCDC is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_LOGO_SUPERH_MONO=y +CONFIG_LOGO_SUPERH_VGA16=y +CONFIG_LOGO_SUPERH_CLUT224=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +CONFIG_LEDS_TRIGGERS=y + +# +# LED Triggers +# +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +# CONFIG_RTC_DRV_TEST is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_SH is not set +# CONFIG_RTC_DRV_GENERIC is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_TIMB_DMA=y +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_GENERIC_ACL=y + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=932 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=y +CONFIG_NLS_CODEPAGE_775=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_CODEPAGE_852=y +CONFIG_NLS_CODEPAGE_855=y +CONFIG_NLS_CODEPAGE_857=y +CONFIG_NLS_CODEPAGE_860=y +CONFIG_NLS_CODEPAGE_861=y +CONFIG_NLS_CODEPAGE_862=y +CONFIG_NLS_CODEPAGE_863=y +CONFIG_NLS_CODEPAGE_864=y +CONFIG_NLS_CODEPAGE_865=y +CONFIG_NLS_CODEPAGE_866=y +CONFIG_NLS_CODEPAGE_869=y +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_CODEPAGE_932=y +CONFIG_NLS_CODEPAGE_949=y +CONFIG_NLS_CODEPAGE_874=y +CONFIG_NLS_ISO8859_8=y +CONFIG_NLS_CODEPAGE_1250=y +CONFIG_NLS_CODEPAGE_1251=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_ISO8859_3=y +CONFIG_NLS_ISO8859_4=y +CONFIG_NLS_ISO8859_5=y +CONFIG_NLS_ISO8859_6=y +CONFIG_NLS_ISO8859_7=y +CONFIG_NLS_ISO8859_9=y +CONFIG_NLS_ISO8859_13=y +CONFIG_NLS_ISO8859_14=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_KOI8_R=y +CONFIG_NLS_KOI8_U=y +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DETECT_SOFTLOCKUP is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_LKDTM is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_FTRACE_SYSCALLS is not set +# CONFIG_BOOT_TRACER is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_SH_STANDARD_BIOS=y +# CONFIG_STACK_DEBUG is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_4KSTACKS is not set +CONFIG_DUMP_CODE=y +# CONFIG_DWARF_UNWINDER is not set +# CONFIG_SH_NO_BSS_INIT is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_LRW=y +CONFIG_CRYPTO_PCBC=y +CONFIG_CRYPTO_XTS=y + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=y +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TGR192=y +CONFIG_CRYPTO_WP512=y + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ANUBIS=y +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_CAMELLIA=y +CONFIG_CRYPTO_CAST5=y +CONFIG_CRYPTO_CAST6=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_FCRYPT=y +CONFIG_CRYPTO_KHAZAD=y +# CONFIG_CRYPTO_SALSA20 is not set +CONFIG_CRYPTO_SEED=y +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_TEA=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_DMA=y +CONFIG_HAVE_LMB=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y diff --git a/arch/sh/include/mach-common/mach/sh2007.h b/arch/sh/include/mach-common/mach/sh2007.h new file mode 100644 index 000000000000..48180b9aa03d --- /dev/null +++ b/arch/sh/include/mach-common/mach/sh2007.h @@ -0,0 +1,117 @@ +#ifndef __MACH_SH2007_H +#define __MACH_SH2007_H + +#define CS5BCR 0xff802050 +#define CS5WCR 0xff802058 +#define CS5PCR 0xff802070 + +#define BUS_SZ8 1 +#define BUS_SZ16 2 +#define BUS_SZ32 3 + +#define PCMCIA_IODYN 1 +#define PCMCIA_ATA 0 +#define PCMCIA_IO8 2 +#define PCMCIA_IO16 3 +#define PCMCIA_COMM8 4 +#define PCMCIA_COMM16 5 +#define PCMCIA_ATTR8 6 +#define PCMCIA_ATTR16 7 + +#define TYPE_SRAM 0 +#define TYPE_PCMCIA 4 + +/* write-read/write-write delay (0-7:0,1,2,3,4,5,6,7) */ +#define IWW5 0 +#define IWW6 3 +/* different area, read-write delay (0-7:0,1,2,3,4,5,6,7) */ +#define IWRWD5 2 +#define IWRWD6 2 +/* same area, read-write delay (0-7:0,1,2,3,4,5,6,7) */ +#define IWRWS5 2 +#define IWRWS6 2 +/* different area, read-read delay (0-7:0,1,2,3,4,5,6,7) */ +#define IWRRD5 2 +#define IWRRD6 2 +/* same area, read-read delay (0-7:0,1,2,3,4,5,6,7) */ +#define IWRRS5 0 +#define IWRRS6 2 +/* burst count (0-3:4,8,16,32) */ +#define BST5 0 +#define BST6 0 +/* bus size */ +#define SZ5 BUS_SZ16 +#define SZ6 BUS_SZ16 +/* RD hold for SRAM (0-1:0,1) */ +#define RDSPL5 0 +#define RDSPL6 0 +/* Burst pitch (0-7:0,1,2,3,4,5,6,7) */ +#define BW5 0 +#define BW6 0 +/* Multiplex (0-1:0,1) */ +#define MPX5 0 +#define MPX6 0 +/* device type */ +#define TYPE5 TYPE_PCMCIA +#define TYPE6 TYPE_PCMCIA +/* address setup before assert CSn for SRAM (0-7:0,1,2,3,4,5,6,7) */ +#define ADS5 0 +#define ADS6 0 +/* address hold after negate CSn for SRAM (0-7:0,1,2,3,4,5,6,7) */ +#define ADH5 0 +#define ADH6 0 +/* CSn assert to RD assert delay for SRAM (0-7:0,1,2,3,4,5,6,7) */ +#define RDS5 0 +#define RDS6 0 +/* RD negate to CSn negate delay for SRAM (0-7:0,1,2,3,4,5,6,7) */ +#define RDH5 0 +#define RDH6 0 +/* CSn assert to WE assert delay for SRAM (0-7:0,1,2,3,4,5,6,7) */ +#define WTS5 0 +#define WTS6 0 +/* WE negate to CSn negate delay for SRAM (0-7:0,1,2,3,4,5,6,7) */ +#define WTH5 0 +#define WTH6 0 +/* BS hold (0-1:1,2) */ +#define BSH5 0 +#define BSH6 0 +/* wait cycle (0-15:0,1,2,3,4,5,6,7,8,9,11,13,15,17,21,25) */ +#define IW5 6 /* 60ns PIO mode 4 */ +#define IW6 15 /* 250ns */ + +#define SAA5 PCMCIA_IODYN /* IDE area b4000000-b5ffffff */ +#define SAB5 PCMCIA_IODYN /* CF area b6000000-b7ffffff */ +#define PCWA5 0 /* additional wait A (0-3:0,15,30,50) */ +#define PCWB5 0 /* additional wait B (0-3:0,15,30,50) */ +/* wait B (0-15:0,1,2,3,4,5,6,7,8,9,11,13,15,17,21,25) */ +#define PCIW5 12 +/* Address->OE/WE assert delay A (0-7:0,1,2,3,6,9,12,15) */ +#define TEDA5 2 +/* Address->OE/WE assert delay B (0-7:0,1,2,3,6,9,12,15) */ +#define TEDB5 4 +/* OE/WE negate->Address delay A (0-7:0,1,2,3,6,9,12,15) */ +#define TEHA5 2 +/* OE/WE negate->Address delay B (0-7:0,1,2,3,6,9,12,15) */ +#define TEHB5 3 + +#define CS5BCR_D ((IWW5<<28)|(IWRWD5<<24)|(IWRWS5<<20)| \ + (IWRRD5<<16)|(IWRRS5<<12)|(BST5<<10)| \ + (SZ5<<8)|(RDSPL5<<7)|(BW5<<4)|(MPX5<<3)|TYPE5) +#define CS5WCR_D ((ADS5<<28)|(ADH5<<24)|(RDS5<<20)| \ + (RDH5<<16)|(WTS5<<12)|(WTH5<<8)|(BSH5<<4)|IW5) +#define CS5PCR_D ((SAA5<<28)|(SAB5<<24)|(PCWA5<<22)| \ + (PCWB5<<20)|(PCIW5<<16)|(TEDA5<<12)| \ + (TEDB5<<8)|(TEHA5<<4)|TEHB5) + +#define SMC0_BASE 0xb0800000 /* eth0 */ +#define SMC1_BASE 0xb0900000 /* eth1 */ +#define CF_BASE 0xb6100000 /* Compact Flash (I/O area) */ +#define IDE_BASE 0xb4000000 /* IDE */ +#define PC104_IO_BASE 0xb8000000 +#define PC104_MEM_BASE 0xba000000 +#define SMC_IO_SIZE 0x100 + +#define CF_OFFSET 0x1f0 +#define IDE_OFFSET 0x170 + +#endif /* __MACH_SH2007_H */ diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index b25aa554ee5e..120a211d40a8 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -52,6 +52,7 @@ MIGOR SH_MIGOR RSK7201 SH_RSK7201 RSK7203 SH_RSK7203 AP325RXA SH_AP325RXA +SH2007 SH_SH2007 SH7763RDP SH_SH7763RDP SH7785LCR SH_SH7785LCR SH7785LCR_PT SH_SH7785LCR_PT diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index f70c49f915fa..eb7ef4951e07 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -140,7 +140,15 @@ # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ # define SCSPTR1 0xffe10024 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* Overrun error bit */ -# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ + +#if defined(CONFIG_SH_SH2007) +/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=0 */ +# define SCSCR_INIT(port) 0x38 +#else +/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=1 */ +# define SCSCR_INIT(port) 0x3a +#endif + #elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \ defined(CONFIG_CPU_SUBTYPE_SH7786) # define SCSPTR0 0xffea0024 /* 16 bit SCIF */ @@ -599,9 +607,10 @@ static inline int sci_rxd_in(struct uart_port *port) * -- Mitch Davis - 15 Jul 2000 */ -#if defined(CONFIG_CPU_SUBTYPE_SH7780) || \ - defined(CONFIG_CPU_SUBTYPE_SH7785) || \ - defined(CONFIG_CPU_SUBTYPE_SH7786) +#if (defined(CONFIG_CPU_SUBTYPE_SH7780) || \ + defined(CONFIG_CPU_SUBTYPE_SH7785) || \ + defined(CONFIG_CPU_SUBTYPE_SH7786)) && \ + !defined(CONFIG_SH_SH2007) #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1) #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ -- cgit v1.2.3-59-g8ed1b From 7210ed74a1ab9ce148a66798fbeec88d27f42070 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 21 Jun 2010 16:23:03 +0900 Subject: sh: fix up an off-by-1 in the number of early ioremap fixmaps. There was an off-by-1 in the begin/end of the ioremap fixmaps, leaving us with a spurious entry. In practice this wasn't a problem since we aligned on a PMD boundary anyways, but this makes it consistent with the intention and the other fixmaps. Signed-off-by: Paul Mundt --- arch/sh/include/asm/fixmap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/include/asm/fixmap.h b/arch/sh/include/asm/fixmap.h index 6e7cea453895..bd7e79a12653 100644 --- a/arch/sh/include/asm/fixmap.h +++ b/arch/sh/include/asm/fixmap.h @@ -58,7 +58,7 @@ enum fixed_addresses { #ifdef CONFIG_HIGHMEM FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ - FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, + FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1, #endif #ifdef CONFIG_IOREMAP_FIXED @@ -69,7 +69,7 @@ enum fixed_addresses { */ #define FIX_N_IOREMAPS 32 FIX_IOREMAP_BEGIN, - FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS, + FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS - 1, #endif __end_of_fixed_addresses -- cgit v1.2.3-59-g8ed1b From 598ee698d9db7beb06e12f4ea9d9a5fbc03a3a77 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 21 Jun 2010 16:26:27 +0900 Subject: sh: Fix up PUD trampling in ranged page table init for X2TLB. page_table_range_init() presently allocates a PUD page for the 3-level page table case on X2 TLB configurations on each successive call. This results in the previous PUD page being trampled when PMDs with an overlapping PUD are initialized. This case was triggered by putting persistent kmaps immediately below the fixmap range for highmem. Signed-off-by: Paul Mundt --- arch/sh/mm/init.c | 52 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 46f84de62469..82d46096e531 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -47,7 +47,6 @@ static pte_t *__get_pte_phys(unsigned long addr) pgd_t *pgd; pud_t *pud; pmd_t *pmd; - pte_t *pte; pgd = pgd_offset_k(addr); if (pgd_none(*pgd)) { @@ -67,8 +66,7 @@ static pte_t *__get_pte_phys(unsigned long addr) return NULL; } - pte = pte_offset_kernel(pmd, addr); - return pte; + return pte_offset_kernel(pmd, addr); } static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot) @@ -125,13 +123,45 @@ void __clear_fixmap(enum fixed_addresses idx, pgprot_t prot) clear_pte_phys(address, prot); } +static pmd_t * __init one_md_table_init(pud_t *pud) +{ + if (pud_none(*pud)) { + pmd_t *pmd; + + pmd = alloc_bootmem_pages(PAGE_SIZE); + pud_populate(&init_mm, pud, pmd); + BUG_ON(pmd != pmd_offset(pud, 0)); + } + + return pmd_offset(pud, 0); +} + +static pte_t * __init one_page_table_init(pmd_t *pmd) +{ + if (pmd_none(*pmd)) { + pte_t *pte; + + pte = alloc_bootmem_pages(PAGE_SIZE); + pmd_populate_kernel(&init_mm, pmd, pte); + BUG_ON(pte != pte_offset_kernel(pmd, 0)); + } + + return pte_offset_kernel(pmd, 0); +} + +static pte_t * __init page_table_kmap_check(pte_t *pte, pmd_t *pmd, + unsigned long vaddr, pte_t *lastpte) +{ + return pte; +} + void __init page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base) { pgd_t *pgd; pud_t *pud; pmd_t *pmd; - pte_t *pte; + pte_t *pte = NULL; int i, j, k; unsigned long vaddr; @@ -144,19 +174,13 @@ void __init page_table_range_init(unsigned long start, unsigned long end, for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { pud = (pud_t *)pgd; for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) { -#ifdef __PAGETABLE_PMD_FOLDED - pmd = (pmd_t *)pud; -#else - pmd = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE); - pud_populate(&init_mm, pud, pmd); + pmd = one_md_table_init(pud); +#ifndef __PAGETABLE_PMD_FOLDED pmd += k; #endif for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) { - if (pmd_none(*pmd)) { - pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); - pmd_populate_kernel(&init_mm, pmd, pte); - BUG_ON(pte != pte_offset_kernel(pmd, 0)); - } + pte = page_table_kmap_check(one_page_table_init(pmd), + pmd, vaddr, pte); vaddr += PMD_SIZE; } k = 0; -- cgit v1.2.3-59-g8ed1b From 3b554c33dcde9d67efcb8d0a5acca201afd44730 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sat, 19 Jun 2010 00:01:03 +0100 Subject: sh: Fix typos in PCI initialization message This typo seems to have been copy and pasted in the PCI initialization code. Replace 'intialization' with 'initialization'. Signed-off-by: Matt Fleming --- arch/sh/drivers/pci/pci-sh7751.c | 2 +- arch/sh/drivers/pci/pci-sh7780.c | 2 +- arch/sh/drivers/pci/pcie-sh7786.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c index f98141b3b7d7..86adb1e235cd 100644 --- a/arch/sh/drivers/pci/pci-sh7751.c +++ b/arch/sh/drivers/pci/pci-sh7751.c @@ -81,7 +81,7 @@ static int __init sh7751_pci_init(void) unsigned int id; u32 word, reg; - printk(KERN_NOTICE "PCI: Starting intialization.\n"); + printk(KERN_NOTICE "PCI: Starting initialization.\n"); chan->reg_base = 0xfe200000; diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c index ffdcbf10b95e..edb7cca14882 100644 --- a/arch/sh/drivers/pci/pci-sh7780.c +++ b/arch/sh/drivers/pci/pci-sh7780.c @@ -246,7 +246,7 @@ static int __init sh7780_pci_init(void) const char *type; int ret, i; - printk(KERN_NOTICE "PCI: Starting intialization.\n"); + printk(KERN_NOTICE "PCI: Starting initialization.\n"); chan->reg_base = 0xfe040000; diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index 68cb9b0ac9d2..78f378731858 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -392,7 +392,7 @@ static int __init sh7786_pcie_init(void) { int ret = 0, i; - printk(KERN_NOTICE "PCI: Starting intialization.\n"); + printk(KERN_NOTICE "PCI: Starting initialization.\n"); sh7786_pcie_hwops = &sh7786_65nm_pcie_hwops; -- cgit v1.2.3-59-g8ed1b From 7974891db234467eaf1fec613ec0129cb4ac2332 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 28 Jun 2010 14:15:54 +0200 Subject: x86: Always use irq stacks IRQ stacks provide much better safety against unexpected stack use from interrupts, at the minimal downside of slightly higher memory usage. Enable irq stacks also for the default 8k stack on 32-bit kernels to minimize the problem of stack overflows through interrupt activity. This is what the 64-bit kernel and various other architectures already do. Signed-off-by: Christoph Hellwig LKML-Reference: <20100628121554.GA6605@lst.de> Signed-off-by: Thomas Gleixner --- Documentation/x86/x86_64/kernel-stacks | 6 +++--- arch/x86/Kconfig.debug | 3 +-- arch/x86/include/asm/irq.h | 12 +++++------- arch/x86/kernel/irq_32.c | 6 ------ 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/Documentation/x86/x86_64/kernel-stacks b/Documentation/x86/x86_64/kernel-stacks index 5ad65d51fb95..a01eec5d1d0b 100644 --- a/Documentation/x86/x86_64/kernel-stacks +++ b/Documentation/x86/x86_64/kernel-stacks @@ -18,9 +18,9 @@ specialized stacks contain no useful data. The main CPU stacks are: Used for external hardware interrupts. If this is the first external hardware interrupt (i.e. not a nested hardware interrupt) then the kernel switches from the current task to the interrupt stack. Like - the split thread and interrupt stacks on i386 (with CONFIG_4KSTACKS), - this gives more room for kernel interrupt processing without having - to increase the size of every per thread stack. + the split thread and interrupt stacks on i386, this gives more room + for kernel interrupt processing without having to increase the size + of every per thread stack. The interrupt stack is also used when processing a softirq. diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 75085080b63e..badda8e20e78 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -128,8 +128,7 @@ config 4KSTACKS If you say Y here the kernel will use a 4Kb stacksize for the kernel stack attached to each process/thread. This facilitates running more threads on a system and also reduces the pressure - on the VM subsystem for higher order allocations. This option - will also use IRQ stacks to compensate for the reduced stackspace. + on the VM subsystem for higher order allocations. config DOUBLEFAULT default y diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 5458380b6ef8..0bf5b0083650 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -19,18 +19,16 @@ static inline int irq_canonicalize(int irq) # define ARCH_HAS_NMI_WATCHDOG #endif -#ifdef CONFIG_4KSTACKS - extern void irq_ctx_init(int cpu); - extern void irq_ctx_exit(int cpu); -# define __ARCH_HAS_DO_SOFTIRQ +#ifdef CONFIG_X86_32 +extern void irq_ctx_init(int cpu); +extern void irq_ctx_exit(int cpu); #else # define irq_ctx_init(cpu) do { } while (0) # define irq_ctx_exit(cpu) do { } while (0) -# ifdef CONFIG_X86_64 -# define __ARCH_HAS_DO_SOFTIRQ -# endif #endif +#define __ARCH_HAS_DO_SOFTIRQ + #ifdef CONFIG_HOTPLUG_CPU #include extern void fixup_irqs(void); diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 10709f29d166..67f5f9f5299f 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -49,7 +49,6 @@ static inline int check_stack_overflow(void) { return 0; } static inline void print_stack_overflow(void) { } #endif -#ifdef CONFIG_4KSTACKS /* * per-CPU IRQ handling contexts (thread information and stack) */ @@ -187,11 +186,6 @@ asmlinkage void do_softirq(void) local_irq_restore(flags); } -#else -static inline int -execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; } -#endif - bool handle_irq(unsigned irq, struct pt_regs *regs) { struct irq_desc *desc; -- cgit v1.2.3-59-g8ed1b From dcfa726280116dd31adad37da940f542663567d0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 28 Jun 2010 14:16:14 +0200 Subject: x86: Remove CONFIG_4KSTACKS These days 4 kilobytes of stack just aren't enough for reliably operation, and people using lots of threads have long switched to 64-bit kernels, so remove the CONFIG_4KSTACKS option. Signed-off-by: Christoph Hellwig LKML-Reference: <20100628121614.GB6605@lst.de> Signed-off-by: Thomas Gleixner --- arch/x86/Kconfig.debug | 9 --------- arch/x86/include/asm/module.h | 7 +------ arch/x86/include/asm/page_32_types.h | 4 ---- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index badda8e20e78..7f1530838bc8 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -121,15 +121,6 @@ config DEBUG_NX_TEST and the software setup of this feature. If in doubt, say "N" -config 4KSTACKS - bool "Use 4Kb for kernel stacks instead of 8Kb" - depends on X86_32 - ---help--- - If you say Y here the kernel will use a 4Kb stacksize for the - kernel stack attached to each process/thread. This facilitates - running more threads on a system and also reduces the pressure - on the VM subsystem for higher order allocations. - config DOUBLEFAULT default y bool "Enable doublefault exception handler" if EMBEDDED diff --git a/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h index 3e2ce58a31a3..67763c5d8b4e 100644 --- a/arch/x86/include/asm/module.h +++ b/arch/x86/include/asm/module.h @@ -60,12 +60,7 @@ #endif #ifdef CONFIG_X86_32 -# ifdef CONFIG_4KSTACKS -# define MODULE_STACKSIZE "4KSTACKS " -# else -# define MODULE_STACKSIZE "" -# endif -# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE +# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY #endif #endif /* _ASM_X86_MODULE_H */ diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h index 6f1b7331313f..ade619ff9e2a 100644 --- a/arch/x86/include/asm/page_32_types.h +++ b/arch/x86/include/asm/page_32_types.h @@ -15,11 +15,7 @@ */ #define __PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL) -#ifdef CONFIG_4KSTACKS -#define THREAD_ORDER 0 -#else #define THREAD_ORDER 1 -#endif #define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER) #define STACKFAULT_STACK 0 -- cgit v1.2.3-59-g8ed1b From ae9b12c72f831a2f956a5b30fd999f3018c43a89 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 7 Jun 2010 11:16:36 +0000 Subject: dmaengine: initialise DMA engine before MMC To use DMA engine based DMA with MMC in a non-modular build, the DMA engine has to initialise before MMC. Signed-off-by: Guennadi Liakhovetski Acked-by: Dan Williams Signed-off-by: Paul Mundt --- drivers/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/Makefile b/drivers/Makefile index 91874e048552..b713e75cee71 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -92,6 +92,7 @@ obj-$(CONFIG_EISA) += eisa/ obj-y += lguest/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_CPU_IDLE) += cpuidle/ +obj-$(CONFIG_DMA_ENGINE) += dma/ obj-$(CONFIG_MMC) += mmc/ obj-$(CONFIG_MEMSTICK) += memstick/ obj-$(CONFIG_NEW_LEDS) += leds/ @@ -102,7 +103,6 @@ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ obj-$(CONFIG_ARCH_SHMOBILE) += sh/ obj-$(CONFIG_GENERIC_TIME) += clocksource/ -obj-$(CONFIG_DMA_ENGINE) += dma/ obj-$(CONFIG_DCA) += dca/ obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_PPC_PS3) += ps3/ -- cgit v1.2.3-59-g8ed1b From 59615ecdb516cf218c3699b02d87d9827dc3e0c7 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 2 Jul 2010 15:44:09 +0900 Subject: sh: Provide a global TLB flush for U/I-TLB clear. This provides a sledgehammer approach for clearing the TLBs, only to be used in cases where we know we will never want to use the mappings again and have no interest in preserving state. This also destroys wired entries. The primary use for this is when we are either entering or exiting the kernel completely, in the latter case as a precursor for CPU reset by MMU. Signed-off-by: Paul Mundt --- arch/sh/include/asm/tlbflush.h | 2 ++ arch/sh/kernel/reboot.c | 4 ++++ arch/sh/mm/tlbflush_32.c | 16 ++++++++++++++++ arch/sh/mm/tlbflush_64.c | 5 +++++ 4 files changed, 27 insertions(+) diff --git a/arch/sh/include/asm/tlbflush.h b/arch/sh/include/asm/tlbflush.h index e0ac97221ae6..0df66f0c7284 100644 --- a/arch/sh/include/asm/tlbflush.h +++ b/arch/sh/include/asm/tlbflush.h @@ -21,6 +21,8 @@ extern void local_flush_tlb_kernel_range(unsigned long start, unsigned long end); extern void local_flush_tlb_one(unsigned long asid, unsigned long page); +extern void __flush_tlb_global(void); + #ifdef CONFIG_SMP extern void flush_tlb_all(void); diff --git a/arch/sh/kernel/reboot.c b/arch/sh/kernel/reboot.c index b1fca66bb92e..ca6a5ca64015 100644 --- a/arch/sh/kernel/reboot.c +++ b/arch/sh/kernel/reboot.c @@ -9,6 +9,7 @@ #include #include #include +#include void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); @@ -25,6 +26,9 @@ static void native_machine_restart(char * __unused) { local_irq_disable(); + /* Destroy all of the TLBs in preparation for reset by MMU */ + __flush_tlb_global(); + /* Address error with SR.BL=1 first. */ trigger_address_error(); diff --git a/arch/sh/mm/tlbflush_32.c b/arch/sh/mm/tlbflush_32.c index 3fbe03ce8fe3..a6a20d6de4c0 100644 --- a/arch/sh/mm/tlbflush_32.c +++ b/arch/sh/mm/tlbflush_32.c @@ -119,3 +119,19 @@ void local_flush_tlb_mm(struct mm_struct *mm) local_irq_restore(flags); } } + +void __flush_tlb_global(void) +{ + unsigned long flags; + + local_irq_save(flags); + + /* + * This is the most destructive of the TLB flushing options, + * and will tear down all of the UTLB/ITLB mappings, including + * wired entries. + */ + __raw_writel(__raw_readl(MMUCR) | MMUCR_TI, MMUCR); + + local_irq_restore(flags); +} diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c index 03db41cc1268..7f5810f5dfdc 100644 --- a/arch/sh/mm/tlbflush_64.c +++ b/arch/sh/mm/tlbflush_64.c @@ -455,6 +455,11 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) flush_tlb_all(); } +void __flush_tlb_global(void) +{ + flush_tlb_all(); +} + void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) { } -- cgit v1.2.3-59-g8ed1b From 358aa7031d90fc3c7c1dbf1fd248a7e3af3c4b11 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Tue, 8 Jun 2010 02:00:13 +0000 Subject: sh: Drop dependence for 29bit mode of trigger_address_error() When CONFIG_PMB enable, ITLB is not cleared by reset of watchdog timer. This should use trigger_address_error(). Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- arch/sh/include/asm/system_32.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/sh/include/asm/system_32.h b/arch/sh/include/asm/system_32.h index 51296b36770e..9bd2684f908e 100644 --- a/arch/sh/include/asm/system_32.h +++ b/arch/sh/include/asm/system_32.h @@ -216,13 +216,12 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, static inline void trigger_address_error(void) { - if (__in_29bit_mode()) - __asm__ __volatile__ ( - "ldc %0, sr\n\t" - "mov.l @%1, %0" - : - : "r" (0x10000000), "r" (0x80000001) - ); + __asm__ __volatile__ ( + "ldc %0, sr\n\t" + "mov.l @%1, %0" + : + : "r" (0x10000000), "r" (0x80000001) + ); } asmlinkage void do_address_error(struct pt_regs *regs, -- cgit v1.2.3-59-g8ed1b From c45f6f10263ab53574f54de0caf0299b7d7c06a8 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 25 Jun 2010 07:20:29 +0000 Subject: sh: move a debug printk() to a more meaningful location in the clock driver To actually output the _new_ clock rate it first has to be set. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- drivers/sh/clk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/sh/clk.c b/drivers/sh/clk.c index 5d84adac9ec4..936c93aaef11 100644 --- a/drivers/sh/clk.c +++ b/drivers/sh/clk.c @@ -354,10 +354,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent) ret = clk_reparent(clk, parent); if (ret == 0) { - pr_debug("clock: set parent of %s to %s (new rate %ld)\n", - clk->name, clk->parent->name, clk->rate); if (clk->ops->recalc) clk->rate = clk->ops->recalc(clk); + pr_debug("clock: set parent of %s to %s (new rate %ld)\n", + clk->name, clk->parent->name, clk->rate); propagate_rate(clk); } } else -- cgit v1.2.3-59-g8ed1b From 088bcc2aff25f31f1497f8196fa02c8cd2a43f68 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 25 Jun 2010 07:19:39 +0000 Subject: sh: remove bogus highest / lowest logic from clock rate rounding The use of highest and lowest in clk_rate_table_round() is completely bogus and superfluous. Remove it. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- drivers/sh/clk.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/sh/clk.c b/drivers/sh/clk.c index 936c93aaef11..cede14e34507 100644 --- a/drivers/sh/clk.c +++ b/drivers/sh/clk.c @@ -73,22 +73,14 @@ long clk_rate_table_round(struct clk *clk, { unsigned long rate_error, rate_error_prev = ~0UL; unsigned long rate_best_fit = rate; - unsigned long highest, lowest; int i; - highest = lowest = 0; - for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned long freq = freq_table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; - if (freq > highest) - highest = freq; - if (freq < lowest) - lowest = freq; - rate_error = abs(freq - rate); if (rate_error < rate_error_prev) { rate_best_fit = freq; @@ -99,11 +91,6 @@ long clk_rate_table_round(struct clk *clk, break; } - if (rate >= highest) - rate_best_fit = highest; - if (rate <= lowest) - rate_best_fit = lowest; - return rate_best_fit; } -- cgit v1.2.3-59-g8ed1b From b32f1fef4fd7bdfb4f1c466393e7f3e3f359c5e0 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 6 Jul 2010 04:32:40 +0000 Subject: sh: modify NR_IRQS from 256 to 512 Newer parts need NR_IRQS > 256, so simply bump this up to 512 across the board. At this point sparseirq is used unconditionally across all CPUs, so this introduces minimal overhead. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/include/asm/irq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/include/asm/irq.h b/arch/sh/include/asm/irq.h index 02c2f0102cfa..45d08b6a5ef7 100644 --- a/arch/sh/include/asm/irq.h +++ b/arch/sh/include/asm/irq.h @@ -9,7 +9,7 @@ * advised to cap this at the hard limit that they're interested in * through the machvec. */ -#define NR_IRQS 256 +#define NR_IRQS 512 #define NR_IRQS_LEGACY 8 /* Legacy external IRQ0-7 */ /* -- cgit v1.2.3-59-g8ed1b From e81e5ce23f8950bd9f5b9f1846be49ac078f2d11 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 6 Jul 2010 04:31:29 +0000 Subject: sh: change PVR of SH7757 for 2nd cut All 1st cut silicon in the wild has been replaced by the 2nd cut, so it's safe to replace all of the 1st cut references and support. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4/probe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index d180f16281ed..b93458f33b74 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c @@ -150,7 +150,7 @@ void __cpuinit cpu_probe(void) boot_cpu_data.type = CPU_SH7724; boot_cpu_data.flags |= CPU_HAS_L2_CACHE; break; - case 0x50: + case 0x10: boot_cpu_data.type = CPU_SH7757; break; } -- cgit v1.2.3-59-g8ed1b From a7f5551cae9a9f667ed80174ac1a20f780310977 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 6 Jul 2010 04:31:40 +0000 Subject: sh: fix the id of scif in setup-sh7757 Because the value of CONFIG_SERIAL_SH_SCI_NR_UARTS is 3. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7757.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index 444aca95b20d..93b7aa4776e8 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c @@ -26,7 +26,7 @@ static struct plat_sci_port scif2_platform_data = { static struct platform_device scif2_device = { .name = "sh-sci", - .id = 2, + .id = 0, .dev = { .platform_data = &scif2_platform_data, }, @@ -41,7 +41,7 @@ static struct plat_sci_port scif3_platform_data = { static struct platform_device scif3_device = { .name = "sh-sci", - .id = 3, + .id = 1, .dev = { .platform_data = &scif3_platform_data, }, @@ -56,7 +56,7 @@ static struct plat_sci_port scif4_platform_data = { static struct platform_device scif4_device = { .name = "sh-sci", - .id = 4, + .id = 2, .dev = { .platform_data = &scif4_platform_data, }, -- cgit v1.2.3-59-g8ed1b From c3721d5bbecad670d35589756ad2a15eaf592bd4 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 6 Jul 2010 04:31:47 +0000 Subject: sh: add some INTC_VECT for setup-sh7757 Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7757.c | 216 ++++++++++++++++++++++----------- 1 file changed, 147 insertions(+), 69 deletions(-) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index 93b7aa4776e8..749c6388d5a5 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c @@ -163,39 +163,23 @@ enum { IRL4_HHLL, IRL4_HHLH, IRL4_HHHL, IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, - SDHI, - DVC, - IRQ8, IRQ9, IRQ10, - WDT0, - TMU0, TMU1, TMU2, TMU2_TICPI, + SDHI, DVC, + IRQ8, IRQ9, IRQ11, IRQ10, IRQ12, IRQ13, IRQ14, IRQ15, + TMU0, TMU1, TMU2, TMU2_TICPI, TMU3, TMU4, TMU5, HUDI, - ARC4, - DMAC0, - IRQ11, - SCIF2, - DMAC1_6, - USB0, - IRQ12, + DMAC0_5, DMAC6_7, DMAC8_11, + SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, + USB0, USB1, JMC, - SPI1, - IRQ13, IRQ14, - USB1, + SPI0, SPI1, TMR01, TMR23, TMR45, - WDT1, FRT, - LPC, - SCIF0, SCIF1, SCIF3, - PECI0I, PECI1I, PECI2I, - IRQ15, + LPC, LPC5, LPC6, LPC7, LPC8, + PECI0, PECI1, PECI2, PECI3, PECI4, PECI5, ETHERC, - SPI0, - ADC1, - DMAC1_8, + ADC0, ADC1, SIM, - TMU3, TMU4, TMU5, - ADC0, - SCIF4, IIC0_0, IIC0_1, IIC0_2, IIC0_3, IIC1_0, IIC1_1, IIC1_2, IIC1_3, IIC2_0, IIC2_1, IIC2_2, IIC2_3, @@ -206,9 +190,23 @@ enum { IIC7_0, IIC7_1, IIC7_2, IIC7_3, IIC8_0, IIC8_1, IIC8_2, IIC8_3, IIC9_0, IIC9_1, IIC9_2, IIC9_3, - PCIINTA, - PCIE, + ONFICTL, + MMC1, MMC2, + ECCU, + PCIC, + G200, + RSPI, SGPIO, + DMINT12, DMINT13, DMINT14, DMINT15, DMINT16, DMINT17, DMINT18, DMINT19, + DMINT20, DMINT21, DMINT22, DMINT23, + DDRECC, + TSIP, + PCIE_BRIDGE, + WDT0B, WDT1B, WDT2B, WDT3B, WDT4B, WDT5B, WDT6B, WDT7B, WDT8B, + GETHER0, GETHER1, GETHER2, + PBIA, PBIB, PBIC, + DMAE2, DMAE3, + SERMUX2, SERMUX3, /* interrupt groups */ @@ -221,19 +219,18 @@ static struct intc_vect vectors[] __initdata = { INTC_VECT(DVC, 0x4e0), INTC_VECT(IRQ8, 0x500), INTC_VECT(IRQ9, 0x520), INTC_VECT(IRQ10, 0x540), - INTC_VECT(WDT0, 0x560), INTC_VECT(TMU0, 0x580), INTC_VECT(TMU1, 0x5a0), INTC_VECT(TMU2, 0x5c0), INTC_VECT(TMU2_TICPI, 0x5e0), INTC_VECT(HUDI, 0x600), INTC_VECT(ARC4, 0x620), - INTC_VECT(DMAC0, 0x640), INTC_VECT(DMAC0, 0x660), - INTC_VECT(DMAC0, 0x680), INTC_VECT(DMAC0, 0x6a0), - INTC_VECT(DMAC0, 0x6c0), + INTC_VECT(DMAC0_5, 0x640), INTC_VECT(DMAC0_5, 0x660), + INTC_VECT(DMAC0_5, 0x680), INTC_VECT(DMAC0_5, 0x6a0), + INTC_VECT(DMAC0_5, 0x6c0), INTC_VECT(IRQ11, 0x6e0), INTC_VECT(SCIF2, 0x700), INTC_VECT(SCIF2, 0x720), INTC_VECT(SCIF2, 0x740), INTC_VECT(SCIF2, 0x760), - INTC_VECT(DMAC0, 0x780), INTC_VECT(DMAC0, 0x7a0), - INTC_VECT(DMAC1_6, 0x7c0), INTC_VECT(DMAC1_6, 0x7e0), + INTC_VECT(DMAC0_5, 0x780), INTC_VECT(DMAC0_5, 0x7a0), + INTC_VECT(DMAC6_7, 0x7c0), INTC_VECT(DMAC6_7, 0x7e0), INTC_VECT(USB0, 0x840), INTC_VECT(IRQ12, 0x880), INTC_VECT(JMC, 0x8a0), @@ -242,7 +239,6 @@ static struct intc_vect vectors[] __initdata = { INTC_VECT(USB1, 0x920), INTC_VECT(TMR01, 0xa00), INTC_VECT(TMR23, 0xa20), INTC_VECT(TMR45, 0xa40), - INTC_VECT(WDT1, 0xa60), INTC_VECT(FRT, 0xa80), INTC_VECT(LPC, 0xaa0), INTC_VECT(LPC, 0xac0), INTC_VECT(LPC, 0xae0), INTC_VECT(LPC, 0xb00), @@ -250,14 +246,14 @@ static struct intc_vect vectors[] __initdata = { INTC_VECT(SCIF0, 0xb40), INTC_VECT(SCIF1, 0xb60), INTC_VECT(SCIF3, 0xb80), INTC_VECT(SCIF3, 0xba0), INTC_VECT(SCIF3, 0xbc0), INTC_VECT(SCIF3, 0xbe0), - INTC_VECT(PECI0I, 0xc00), INTC_VECT(PECI1I, 0xc20), - INTC_VECT(PECI2I, 0xc40), + INTC_VECT(PECI0, 0xc00), INTC_VECT(PECI1, 0xc20), + INTC_VECT(PECI2, 0xc40), INTC_VECT(IRQ15, 0xc60), INTC_VECT(ETHERC, 0xc80), INTC_VECT(ETHERC, 0xca0), INTC_VECT(SPI0, 0xcc0), INTC_VECT(ADC1, 0xce0), - INTC_VECT(DMAC1_8, 0xd00), INTC_VECT(DMAC1_8, 0xd20), - INTC_VECT(DMAC1_8, 0xd40), INTC_VECT(DMAC1_8, 0xd60), + INTC_VECT(DMAC8_11, 0xd00), INTC_VECT(DMAC8_11, 0xd20), + INTC_VECT(DMAC8_11, 0xd40), INTC_VECT(DMAC8_11, 0xd60), INTC_VECT(SIM, 0xd80), INTC_VECT(SIM, 0xda0), INTC_VECT(SIM, 0xdc0), INTC_VECT(SIM, 0xde0), INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20), @@ -278,17 +274,47 @@ static struct intc_vect vectors[] __initdata = { INTC_VECT(IIC5_0, 0x1860), INTC_VECT(IIC5_1, 0x1880), INTC_VECT(IIC5_2, 0x18a0), INTC_VECT(IIC5_3, 0x18c0), INTC_VECT(IIC6_0, 0x18e0), INTC_VECT(IIC6_1, 0x1900), - INTC_VECT(IIC6_2, 0x1920), INTC_VECT(IIC6_3, 0x1980), + INTC_VECT(IIC6_2, 0x1920), + INTC_VECT(ONFICTL, 0x1960), + INTC_VECT(IIC6_3, 0x1980), INTC_VECT(IIC7_0, 0x19a0), INTC_VECT(IIC7_1, 0x1a00), INTC_VECT(IIC7_2, 0x1a20), INTC_VECT(IIC7_3, 0x1a40), INTC_VECT(IIC8_0, 0x1a60), INTC_VECT(IIC8_1, 0x1a80), INTC_VECT(IIC8_2, 0x1aa0), INTC_VECT(IIC8_3, 0x1b40), INTC_VECT(IIC9_0, 0x1b60), INTC_VECT(IIC9_1, 0x1b80), INTC_VECT(IIC9_2, 0x1c00), INTC_VECT(IIC9_3, 0x1c20), - INTC_VECT(PCIINTA, 0x1ce0), - INTC_VECT(PCIE, 0x1e00), - INTC_VECT(SGPIO, 0x1f80), - INTC_VECT(SGPIO, 0x1fa0), + INTC_VECT(MMC1, 0x1c60), INTC_VECT(MMC2, 0x1c80), + INTC_VECT(ECCU, 0x1cc0), + INTC_VECT(PCIC, 0x1ce0), + INTC_VECT(G200, 0x1d00), + INTC_VECT(RSPI, 0x1d80), INTC_VECT(RSPI, 0x1da0), + INTC_VECT(RSPI, 0x1dc0), INTC_VECT(RSPI, 0x1de0), + INTC_VECT(PECI3, 0x1ec0), INTC_VECT(PECI4, 0x1ee0), + INTC_VECT(PECI5, 0x1f00), + INTC_VECT(SGPIO, 0x1f80), INTC_VECT(SGPIO, 0x1fa0), + INTC_VECT(SGPIO, 0x1fc0), + INTC_VECT(DMINT12, 0x2400), INTC_VECT(DMINT13, 0x2420), + INTC_VECT(DMINT14, 0x2440), INTC_VECT(DMINT15, 0x2460), + INTC_VECT(DMINT16, 0x2480), INTC_VECT(DMINT17, 0x24e0), + INTC_VECT(DMINT18, 0x2500), INTC_VECT(DMINT19, 0x2520), + INTC_VECT(DMINT20, 0x2540), INTC_VECT(DMINT21, 0x2560), + INTC_VECT(DMINT22, 0x2580), INTC_VECT(DMINT23, 0x2600), + INTC_VECT(DDRECC, 0x2620), + INTC_VECT(TSIP, 0x2640), + INTC_VECT(PCIE_BRIDGE, 0x27c0), + INTC_VECT(WDT0B, 0x2800), INTC_VECT(WDT1B, 0x2820), + INTC_VECT(WDT2B, 0x2840), INTC_VECT(WDT3B, 0x2860), + INTC_VECT(WDT4B, 0x2880), INTC_VECT(WDT5B, 0x28a0), + INTC_VECT(WDT6B, 0x28c0), INTC_VECT(WDT7B, 0x28e0), + INTC_VECT(WDT8B, 0x2900), + INTC_VECT(GETHER0, 0x2960), INTC_VECT(GETHER1, 0x2980), + INTC_VECT(GETHER2, 0x29a0), + INTC_VECT(PBIA, 0x2a00), INTC_VECT(PBIB, 0x2a20), + INTC_VECT(PBIC, 0x2a40), + INTC_VECT(DMAE2, 0x2a60), INTC_VECT(DMAE3, 0x2a80), + INTC_VECT(SERMUX2, 0x2aa0), INTC_VECT(SERMUX3, 0x2b40), + INTC_VECT(LPC5, 0x2b60), INTC_VECT(LPC6, 0x2b80), + INTC_VECT(LPC7, 0x2c00), INTC_VECT(LPC8, 0x2c20), }; static struct intc_group groups[] __initdata = { @@ -312,31 +338,45 @@ static struct intc_mask_reg mask_registers[] __initdata = { { 0xffd40038, 0xffd4003c, 32, /* INT2MSKR / INT2MSKCR */ { 0, 0, 0, 0, 0, 0, 0, 0, - 0, DMAC1_8, 0, PECI0I, LPC, FRT, WDT1, TMR45, - TMR23, TMR01, 0, 0, 0, 0, 0, DMAC0, - HUDI, 0, WDT0, SCIF3, SCIF2, SDHI, TMU345, TMU012 + 0, DMAC8_11, 0, PECI0, LPC, FRT, 0, TMR45, + TMR23, TMR01, 0, 0, 0, 0, 0, DMAC0_5, + HUDI, 0, 0, SCIF3, SCIF2, SDHI, TMU345, TMU012 } }, { 0xffd400d0, 0xffd400d4, 32, /* INT2MSKR1 / INT2MSKCR1 */ { IRQ15, IRQ14, IRQ13, IRQ12, IRQ11, IRQ10, SCIF4, ETHERC, IRQ9, IRQ8, SCIF1, SCIF0, USB0, 0, 0, USB1, - ADC1, 0, DMAC1_6, ADC0, SPI0, SIM, PECI2I, PECI1I, + ADC1, 0, DMAC6_7, ADC0, SPI0, SIM, PECI2, PECI1, ARC4, 0, SPI1, JMC, 0, 0, 0, DVC } }, { 0xffd10038, 0xffd1003c, 32, /* INT2MSKR2 / INT2MSKCR2 */ - { IIC4_1, IIC4_2, IIC5_0, 0, 0, 0, SGPIO, 0, - 0, 0, 0, IIC9_2, IIC8_2, IIC8_1, IIC8_0, IIC7_3, + { IIC4_1, IIC4_2, IIC5_0, ONFICTL, 0, 0, SGPIO, 0, + 0, G200, 0, IIC9_2, IIC8_2, IIC8_1, IIC8_0, IIC7_3, IIC7_2, IIC7_1, IIC6_3, IIC0_0, IIC0_1, IIC0_2, IIC0_3, IIC3_1, - IIC2_3, 0, IIC2_1, IIC9_1, IIC3_3, IIC1_0, PCIE, IIC2_2 + IIC2_3, 0, IIC2_1, IIC9_1, IIC3_3, IIC1_0, 0, IIC2_2 } }, - { 0xffd100d0, 0xff1400d4, 32, /* INT2MSKR3 / INT2MSKCR4 */ - { 0, IIC6_1, IIC6_0, IIC5_1, IIC3_2, IIC2_0, 0, 0, + { 0xffd100d0, 0xffd100d4, 32, /* INT2MSKR3 / INT2MSKCR3 */ + { MMC1, IIC6_1, IIC6_0, IIC5_1, IIC3_2, IIC2_0, PECI5, MMC2, IIC1_3, IIC1_2, IIC9_0, IIC8_3, IIC4_3, IIC7_0, 0, IIC6_2, - PCIINTA, 0, IIC4_0, 0, 0, 0, 0, IIC9_3, + PCIC, 0, IIC4_0, 0, ECCU, RSPI, 0, IIC9_3, IIC3_0, 0, IIC5_3, IIC5_2, 0, 0, 0, IIC1_1 } }, + + { 0xffd20038, 0xffd2003c, 32, /* INT2MSKR4 / INT2MSKCR4 */ + { WDT0B, WDT1B, WDT3B, GETHER0, 0, 0, 0, 0, + 0, 0, 0, LPC7, SERMUX2, DMAE3, DMAE2, PBIC, + PBIB, PBIA, GETHER1, DMINT12, DMINT13, DMINT14, DMINT15, TSIP, + DMINT23, 0, DMINT21, LPC6, 0, DMINT16, 0, DMINT22 + } }, + + { 0xffd200d0, 0xffd200d4, 32, /* INT2MSKR5 / INT2MSKCR5 */ + { 0, WDT8B, WDT7B, WDT4B, 0, DMINT20, 0, 0, + DMINT19, DMINT18, LPC5, SERMUX3, WDT2B, GETHER2, 0, 0, + 0, 0, PCIE_BRIDGE, 0, 0, 0, 0, LPC8, + DDRECC, 0, WDT6B, WDT5B, 0, 0, 0, DMINT17 + } }, }; #define INTPRI 0xffd00010 @@ -372,6 +412,22 @@ static struct intc_mask_reg mask_registers[] __initdata = { #define INT2PRI29 0xffd100b4 #define INT2PRI30 0xffd100b8 #define INT2PRI31 0xffd100bc +#define INT2PRI32 0xffd20000 +#define INT2PRI33 0xffd20004 +#define INT2PRI34 0xffd20008 +#define INT2PRI35 0xffd2000c +#define INT2PRI36 0xffd20010 +#define INT2PRI37 0xffd20014 +#define INT2PRI38 0xffd20018 +#define INT2PRI39 0xffd2001c +#define INT2PRI40 0xffd200a0 +#define INT2PRI41 0xffd200a4 +#define INT2PRI42 0xffd200a8 +#define INT2PRI43 0xffd200ac +#define INT2PRI44 0xffd200b0 +#define INT2PRI45 0xffd200b4 +#define INT2PRI46 0xffd200b8 +#define INT2PRI47 0xffd200bc static struct intc_prio_reg prio_registers[] __initdata = { { INTPRI, 0, 32, 4, { IRQ0, IRQ1, IRQ2, IRQ3, @@ -379,39 +435,61 @@ static struct intc_prio_reg prio_registers[] __initdata = { { INT2PRI0, 0, 32, 8, { TMU0, TMU1, TMU2, TMU2_TICPI } }, { INT2PRI1, 0, 32, 8, { TMU3, TMU4, TMU5, SDHI } }, - { INT2PRI2, 0, 32, 8, { SCIF2, SCIF3, WDT0, IRQ8 } }, - { INT2PRI3, 0, 32, 8, { HUDI, DMAC0, ADC0, IRQ9 } }, + { INT2PRI2, 0, 32, 8, { SCIF2, SCIF3, 0, IRQ8 } }, + { INT2PRI3, 0, 32, 8, { HUDI, DMAC0_5, ADC0, IRQ9 } }, { INT2PRI4, 0, 32, 8, { IRQ10, 0, TMR01, TMR23 } }, - { INT2PRI5, 0, 32, 8, { TMR45, WDT1, FRT, LPC } }, - { INT2PRI6, 0, 32, 8, { PECI0I, ETHERC, DMAC1_8, 0 } }, + { INT2PRI5, 0, 32, 8, { TMR45, 0, FRT, LPC } }, + { INT2PRI6, 0, 32, 8, { PECI0, ETHERC, DMAC8_11, 0 } }, { INT2PRI7, 0, 32, 8, { SCIF4, 0, IRQ11, IRQ12 } }, { INT2PRI8, 0, 32, 8, { 0, 0, 0, DVC } }, { INT2PRI9, 0, 32, 8, { ARC4, 0, SPI1, JMC } }, - { INT2PRI10, 0, 32, 8, { SPI0, SIM, PECI2I, PECI1I } }, - { INT2PRI11, 0, 32, 8, { ADC1, IRQ13, DMAC1_6, IRQ14 } }, + { INT2PRI10, 0, 32, 8, { SPI0, SIM, PECI2, PECI1 } }, + { INT2PRI11, 0, 32, 8, { ADC1, IRQ13, DMAC6_7, IRQ14 } }, { INT2PRI12, 0, 32, 8, { USB0, 0, IRQ15, USB1 } }, { INT2PRI13, 0, 32, 8, { 0, 0, SCIF1, SCIF0 } }, { INT2PRI16, 0, 32, 8, { IIC2_2, 0, 0, 0 } }, - { INT2PRI17, 0, 32, 8, { PCIE, 0, 0, IIC1_0 } }, + { INT2PRI17, 0, 32, 8, { 0, 0, 0, IIC1_0 } }, { INT2PRI18, 0, 32, 8, { IIC3_3, IIC9_1, IIC2_1, IIC1_2 } }, { INT2PRI19, 0, 32, 8, { IIC2_3, IIC3_1, 0, IIC1_3 } }, { INT2PRI20, 0, 32, 8, { IIC2_0, IIC6_3, IIC7_1, IIC7_2 } }, { INT2PRI21, 0, 32, 8, { IIC7_3, IIC8_0, IIC8_1, IIC8_2 } }, - { INT2PRI22, 0, 32, 8, { IIC9_2, 0, 0, 0 } }, - { INT2PRI23, 0, 32, 8, { 0, SGPIO, IIC3_2, IIC5_1 } }, - { INT2PRI24, 0, 32, 8, { 0, 0, 0, IIC1_1 } }, + { INT2PRI22, 0, 32, 8, { IIC9_2, MMC2, G200, 0 } }, + { INT2PRI23, 0, 32, 8, { PECI5, SGPIO, IIC3_2, IIC5_1 } }, + { INT2PRI24, 0, 32, 8, { PECI4, PECI3, 0, IIC1_1 } }, { INT2PRI25, 0, 32, 8, { IIC3_0, 0, IIC5_3, IIC5_2 } }, - { INT2PRI26, 0, 32, 8, { 0, 0, 0, IIC9_3 } }, - { INT2PRI27, 0, 32, 8, { PCIINTA, IIC6_0, IIC4_0, IIC6_1 } }, - { INT2PRI28, 0, 32, 8, { IIC4_3, IIC7_0, 0, IIC6_2 } }, + { INT2PRI26, 0, 32, 8, { ECCU, RSPI, 0, IIC9_3 } }, + { INT2PRI27, 0, 32, 8, { PCIC, IIC6_0, IIC4_0, IIC6_1 } }, + { INT2PRI28, 0, 32, 8, { IIC4_3, IIC7_0, MMC1, IIC6_2 } }, { INT2PRI29, 0, 32, 8, { 0, 0, IIC9_0, IIC8_3 } }, - { INT2PRI30, 0, 32, 8, { IIC4_1, IIC4_2, IIC5_0, 0 } }, + { INT2PRI30, 0, 32, 8, { IIC4_1, IIC4_2, IIC5_0, ONFICTL } }, { INT2PRI31, 0, 32, 8, { IIC0_0, IIC0_1, IIC0_2, IIC0_3 } }, + { INT2PRI32, 0, 32, 8, { DMINT22, 0, 0, 0 } }, + { INT2PRI33, 0, 32, 8, { 0, 0, 0, DMINT16 } }, + { INT2PRI34, 0, 32, 8, { 0, LPC6, DMINT21, DMINT18 } }, + { INT2PRI35, 0, 32, 8, { DMINT23, TSIP, 0, DMINT19 } }, + { INT2PRI36, 0, 32, 8, { DMINT20, GETHER1, PBIA, PBIB } }, + { INT2PRI37, 0, 32, 8, { PBIC, DMAE2, DMAE3, SERMUX2 } }, + { INT2PRI38, 0, 32, 8, { LPC7, 0, 0, 0 } }, + { INT2PRI39, 0, 32, 8, { 0, 0, 0, WDT4B } }, + { INT2PRI40, 0, 32, 8, { 0, 0, 0, DMINT17 } }, + { INT2PRI41, 0, 32, 8, { DDRECC, 0, WDT6B, WDT5B } }, + { INT2PRI42, 0, 32, 8, { 0, 0, 0, LPC8 } }, + { INT2PRI43, 0, 32, 8, { 0, WDT7B, PCIE_BRIDGE, WDT8B } }, + { INT2PRI44, 0, 32, 8, { WDT2B, GETHER2, 0, 0 } }, + { INT2PRI45, 0, 32, 8, { 0, 0, LPC5, SERMUX3 } }, + { INT2PRI46, 0, 32, 8, { WDT0B, WDT1B, WDT3B, GETHER0 } }, + { INT2PRI47, 0, 32, 8, { DMINT12, DMINT13, DMINT14, DMINT15 } }, +}; + +static struct intc_sense_reg sense_registers_irq8to15[] __initdata = { + { 0xffd100f8, 32, 2, /* ICR2 */ { IRQ15, IRQ14, IRQ13, IRQ12, + IRQ11, IRQ10, IRQ9, IRQ8 } }, }; static DECLARE_INTC_DESC(intc_desc, "sh7757", vectors, groups, - mask_registers, prio_registers, NULL); + mask_registers, prio_registers, + sense_registers_irq8to15); /* Support for external interrupt pins in IRQ mode */ static struct intc_vect vectors_irq0123[] __initdata = { -- cgit v1.2.3-59-g8ed1b From 3810e96056ffddf68305f6d11d2d5103ec1f605d Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 6 Jul 2010 04:31:57 +0000 Subject: sh: modify pinmux for SH7757 2nd cut Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/include/cpu-sh4/cpu/sh7757.h | 301 +++--- arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c | 1582 ++++++++++++++++++------------- 2 files changed, 1081 insertions(+), 802 deletions(-) diff --git a/arch/sh/include/cpu-sh4/cpu/sh7757.h b/arch/sh/include/cpu-sh4/cpu/sh7757.h index f4d267efad71..15f3de11c55a 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7757.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7757.h @@ -3,241 +3,252 @@ enum { /* PTA */ - GPIO_PTA7, GPIO_PTA6, GPIO_PTA5, GPIO_PTA4, - GPIO_PTA3, GPIO_PTA2, GPIO_PTA1, GPIO_PTA0, + GPIO_PTA0, GPIO_PTA1, GPIO_PTA2, GPIO_PTA3, + GPIO_PTA4, GPIO_PTA5, GPIO_PTA6, GPIO_PTA7, /* PTB */ - GPIO_PTB7, GPIO_PTB6, GPIO_PTB5, GPIO_PTB4, - GPIO_PTB3, GPIO_PTB2, GPIO_PTB1, GPIO_PTB0, + GPIO_PTB0, GPIO_PTB1, GPIO_PTB2, GPIO_PTB3, + GPIO_PTB4, GPIO_PTB5, GPIO_PTB6, GPIO_PTB7, /* PTC */ - GPIO_PTC7, GPIO_PTC6, GPIO_PTC5, GPIO_PTC4, - GPIO_PTC3, GPIO_PTC2, GPIO_PTC1, GPIO_PTC0, + GPIO_PTC0, GPIO_PTC1, GPIO_PTC2, GPIO_PTC3, + GPIO_PTC4, GPIO_PTC5, GPIO_PTC6, GPIO_PTC7, /* PTD */ - GPIO_PTD7, GPIO_PTD6, GPIO_PTD5, GPIO_PTD4, - GPIO_PTD3, GPIO_PTD2, GPIO_PTD1, GPIO_PTD0, + GPIO_PTD0, GPIO_PTD1, GPIO_PTD2, GPIO_PTD3, + GPIO_PTD4, GPIO_PTD5, GPIO_PTD6, GPIO_PTD7, /* PTE */ - GPIO_PTE7, GPIO_PTE6, GPIO_PTE5, GPIO_PTE4, - GPIO_PTE3, GPIO_PTE2, GPIO_PTE1, GPIO_PTE0, + GPIO_PTE0, GPIO_PTE1, GPIO_PTE2, GPIO_PTE3, + GPIO_PTE4, GPIO_PTE5, GPIO_PTE6, GPIO_PTE7, /* PTF */ - GPIO_PTF7, GPIO_PTF6, GPIO_PTF5, GPIO_PTF4, - GPIO_PTF3, GPIO_PTF2, GPIO_PTF1, GPIO_PTF0, + GPIO_PTF0, GPIO_PTF1, GPIO_PTF2, GPIO_PTF3, + GPIO_PTF4, GPIO_PTF5, GPIO_PTF6, GPIO_PTF7, /* PTG */ - GPIO_PTG7, GPIO_PTG6, GPIO_PTG5, GPIO_PTG4, - GPIO_PTG3, GPIO_PTG2, GPIO_PTG1, GPIO_PTG0, + GPIO_PTG0, GPIO_PTG1, GPIO_PTG2, GPIO_PTG3, + GPIO_PTG4, GPIO_PTG5, GPIO_PTG6, GPIO_PTG7, /* PTH */ - GPIO_PTH7, GPIO_PTH6, GPIO_PTH5, GPIO_PTH4, - GPIO_PTH3, GPIO_PTH2, GPIO_PTH1, GPIO_PTH0, + GPIO_PTH0, GPIO_PTH1, GPIO_PTH2, GPIO_PTH3, + GPIO_PTH4, GPIO_PTH5, GPIO_PTH6, GPIO_PTH7, /* PTI */ - GPIO_PTI7, GPIO_PTI6, GPIO_PTI5, GPIO_PTI4, - GPIO_PTI3, GPIO_PTI2, GPIO_PTI1, GPIO_PTI0, + GPIO_PTI0, GPIO_PTI1, GPIO_PTI2, GPIO_PTI3, + GPIO_PTI4, GPIO_PTI5, GPIO_PTI6, GPIO_PTI7, /* PTJ */ - GPIO_PTJ7, GPIO_PTJ6, GPIO_PTJ5, GPIO_PTJ4, - GPIO_PTJ3, GPIO_PTJ2, GPIO_PTJ1, GPIO_PTJ0, + GPIO_PTJ0, GPIO_PTJ1, GPIO_PTJ2, GPIO_PTJ3, + GPIO_PTJ4, GPIO_PTJ5, GPIO_PTJ6, GPIO_PTJ7_RESV, /* PTK */ - GPIO_PTK7, GPIO_PTK6, GPIO_PTK5, GPIO_PTK4, - GPIO_PTK3, GPIO_PTK2, GPIO_PTK1, GPIO_PTK0, + GPIO_PTK0, GPIO_PTK1, GPIO_PTK2, GPIO_PTK3, + GPIO_PTK4, GPIO_PTK5, GPIO_PTK6, GPIO_PTK7, /* PTL */ - GPIO_PTL7, GPIO_PTL6, GPIO_PTL5, GPIO_PTL4, - GPIO_PTL3, GPIO_PTL2, GPIO_PTL1, GPIO_PTL0, + GPIO_PTL0, GPIO_PTL1, GPIO_PTL2, GPIO_PTL3, + GPIO_PTL4, GPIO_PTL5, GPIO_PTL6, GPIO_PTL7_RESV, /* PTM */ - GPIO_PTM6, GPIO_PTM5, GPIO_PTM4, - GPIO_PTM3, GPIO_PTM2, GPIO_PTM1, GPIO_PTM0, + GPIO_PTM0, GPIO_PTM1, GPIO_PTM2, GPIO_PTM3, + GPIO_PTM4, GPIO_PTM5, GPIO_PTM6, GPIO_PTM7, /* PTN */ - GPIO_PTN7, GPIO_PTN6, GPIO_PTN5, GPIO_PTN4, - GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0, + GPIO_PTN0, GPIO_PTN1, GPIO_PTN2, GPIO_PTN3, + GPIO_PTN4, GPIO_PTN5, GPIO_PTN6, GPIO_PTN7_RESV, /* PTO */ - GPIO_PTO7, GPIO_PTO6, GPIO_PTO5, GPIO_PTO4, - GPIO_PTO3, GPIO_PTO2, GPIO_PTO1, GPIO_PTO0, + GPIO_PTO0, GPIO_PTO1, GPIO_PTO2, GPIO_PTO3, + GPIO_PTO4, GPIO_PTO5, GPIO_PTO6, GPIO_PTO7, /* PTP */ - GPIO_PTP6, GPIO_PTP5, GPIO_PTP4, - GPIO_PTP3, GPIO_PTP2, GPIO_PTP1, GPIO_PTP0, + GPIO_PTP0, GPIO_PTP1, GPIO_PTP2, GPIO_PTP3, + GPIO_PTP4, GPIO_PTP5, GPIO_PTP6, GPIO_PTP7, /* PTQ */ - GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4, - GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0, + GPIO_PTQ0, GPIO_PTQ1, GPIO_PTQ2, GPIO_PTQ3, + GPIO_PTQ4, GPIO_PTQ5, GPIO_PTQ6, GPIO_PTQ7_RESV, /* PTR */ - GPIO_PTR7, GPIO_PTR6, GPIO_PTR5, GPIO_PTR4, - GPIO_PTR3, GPIO_PTR2, GPIO_PTR1, GPIO_PTR0, + GPIO_PTR0, GPIO_PTR1, GPIO_PTR2, GPIO_PTR3, + GPIO_PTR4, GPIO_PTR5, GPIO_PTR6, GPIO_PTR7, /* PTS */ - GPIO_PTS7, GPIO_PTS6, GPIO_PTS5, GPIO_PTS4, - GPIO_PTS3, GPIO_PTS2, GPIO_PTS1, GPIO_PTS0, + GPIO_PTS0, GPIO_PTS1, GPIO_PTS2, GPIO_PTS3, + GPIO_PTS4, GPIO_PTS5, GPIO_PTS6, GPIO_PTS7, /* PTT */ - GPIO_PTT5, GPIO_PTT4, - GPIO_PTT3, GPIO_PTT2, GPIO_PTT1, GPIO_PTT0, + GPIO_PTT0, GPIO_PTT1, GPIO_PTT2, GPIO_PTT3, + GPIO_PTT4, GPIO_PTT5, GPIO_PTT6, GPIO_PTT7, /* PTU */ - GPIO_PTU7, GPIO_PTU6, GPIO_PTU5, GPIO_PTU4, - GPIO_PTU3, GPIO_PTU2, GPIO_PTU1, GPIO_PTU0, + GPIO_PTU0, GPIO_PTU1, GPIO_PTU2, GPIO_PTU3, + GPIO_PTU4, GPIO_PTU5, GPIO_PTU6, GPIO_PTU7, /* PTV */ - GPIO_PTV7, GPIO_PTV6, GPIO_PTV5, GPIO_PTV4, - GPIO_PTV3, GPIO_PTV2, GPIO_PTV1, GPIO_PTV0, + GPIO_PTV0, GPIO_PTV1, GPIO_PTV2, GPIO_PTV3, + GPIO_PTV4, GPIO_PTV5, GPIO_PTV6, GPIO_PTV7, /* PTW */ - GPIO_PTW7, GPIO_PTW6, GPIO_PTW5, GPIO_PTW4, - GPIO_PTW3, GPIO_PTW2, GPIO_PTW1, GPIO_PTW0, + GPIO_PTW0, GPIO_PTW1, GPIO_PTW2, GPIO_PTW3, + GPIO_PTW4, GPIO_PTW5, GPIO_PTW6, GPIO_PTW7, /* PTX */ - GPIO_PTX7, GPIO_PTX6, GPIO_PTX5, GPIO_PTX4, - GPIO_PTX3, GPIO_PTX2, GPIO_PTX1, GPIO_PTX0, + GPIO_PTX0, GPIO_PTX1, GPIO_PTX2, GPIO_PTX3, + GPIO_PTX4, GPIO_PTX5, GPIO_PTX6, GPIO_PTX7, /* PTY */ - GPIO_PTY7, GPIO_PTY6, GPIO_PTY5, GPIO_PTY4, - GPIO_PTY3, GPIO_PTY2, GPIO_PTY1, GPIO_PTY0, + GPIO_PTY0, GPIO_PTY1, GPIO_PTY2, GPIO_PTY3, + GPIO_PTY4, GPIO_PTY5, GPIO_PTY6, GPIO_PTY7, /* PTZ */ - GPIO_PTZ7, GPIO_PTZ6, GPIO_PTZ5, GPIO_PTZ4, - GPIO_PTZ3, GPIO_PTZ2, GPIO_PTZ1, GPIO_PTZ0, + GPIO_PTZ0, GPIO_PTZ1, GPIO_PTZ2, GPIO_PTZ3, + GPIO_PTZ4, GPIO_PTZ5, GPIO_PTZ6, GPIO_PTZ7, - /* PTA (mobule: LBSC, CPG, LPC) */ + /* PTA (mobule: LBSC, RGMII) */ GPIO_FN_BS, GPIO_FN_RDWR, GPIO_FN_WE1, GPIO_FN_RDY, - GPIO_FN_MD10, GPIO_FN_MD9, GPIO_FN_MD8, - GPIO_FN_LGPIO7, GPIO_FN_LGPIO6, GPIO_FN_LGPIO5, GPIO_FN_LGPIO4, - GPIO_FN_LGPIO3, GPIO_FN_LGPIO2, GPIO_FN_LGPIO1, GPIO_FN_LGPIO0, - - /* PTB (mobule: LBSC, EtherC, SIM, LPC) */ - GPIO_FN_D15, GPIO_FN_D14, GPIO_FN_D13, GPIO_FN_D12, - GPIO_FN_D11, GPIO_FN_D10, GPIO_FN_D9, GPIO_FN_D8, - GPIO_FN_ET0_MDC, GPIO_FN_ET0_MDIO, - GPIO_FN_ET1_MDC, GPIO_FN_ET1_MDIO, - GPIO_FN_SIM_D, GPIO_FN_SIM_CLK, GPIO_FN_SIM_RST, - GPIO_FN_WPSZ1, GPIO_FN_WPSZ0, GPIO_FN_FWID, GPIO_FN_FLSHSZ, - GPIO_FN_LPC_SPIEN, GPIO_FN_BASEL, + GPIO_FN_ET0_MDC, GPIO_FN_ET0_MDIO, + GPIO_FN_ET1_MDC, GPIO_FN_ET1_MDIO, - /* PTC (mobule: SD) */ - GPIO_FN_SD_WP, GPIO_FN_SD_CD, GPIO_FN_SD_CLK, GPIO_FN_SD_CMD, - GPIO_FN_SD_D3, GPIO_FN_SD_D2, GPIO_FN_SD_D1, GPIO_FN_SD_D0, + /* PTB (mobule: INTC, ONFI, TMU) */ + GPIO_FN_IRQ15, GPIO_FN_IRQ14, GPIO_FN_IRQ13, GPIO_FN_IRQ12, + GPIO_FN_IRQ11, GPIO_FN_IRQ10, GPIO_FN_IRQ9, GPIO_FN_IRQ8, + GPIO_FN_ON_NRE, GPIO_FN_ON_NWE, GPIO_FN_ON_NWP, GPIO_FN_ON_NCE0, + GPIO_FN_ON_R_B0, GPIO_FN_ON_ALE, GPIO_FN_ON_CLE, + GPIO_FN_TCLK, - /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */ + /* PTC (mobule: IRQ, PWMU) */ GPIO_FN_IRQ7, GPIO_FN_IRQ6, GPIO_FN_IRQ5, GPIO_FN_IRQ4, GPIO_FN_IRQ3, GPIO_FN_IRQ2, GPIO_FN_IRQ1, GPIO_FN_IRQ0, - GPIO_FN_MD6, GPIO_FN_MD5, GPIO_FN_MD3, GPIO_FN_MD2, - GPIO_FN_MD1, GPIO_FN_MD0, GPIO_FN_ADTRG1, GPIO_FN_ADTRG0, - - /* PTE (mobule: EtherC) */ - GPIO_FN_ET0_CRS_DV, GPIO_FN_ET0_TXD1, - GPIO_FN_ET0_TXD0, GPIO_FN_ET0_TX_EN, - GPIO_FN_ET0_REF_CLK, GPIO_FN_ET0_RXD1, - GPIO_FN_ET0_RXD0, GPIO_FN_ET0_RX_ER, - - /* PTF (mobule: EtherC) */ - GPIO_FN_ET1_CRS_DV, GPIO_FN_ET1_TXD1, - GPIO_FN_ET1_TXD0, GPIO_FN_ET1_TX_EN, - GPIO_FN_ET1_REF_CLK, GPIO_FN_ET1_RXD1, - GPIO_FN_ET1_RXD0, GPIO_FN_ET1_RX_ER, - - /* PTG (mobule: SYSTEM, PWMX, LPC) */ - GPIO_FN_STATUS0, GPIO_FN_STATUS1, - GPIO_FN_PWX0, GPIO_FN_PWX1, GPIO_FN_PWX2, GPIO_FN_PWX3, - GPIO_FN_SERIRQ, GPIO_FN_CLKRUN, GPIO_FN_LPCPD, GPIO_FN_LDRQ, - - /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */ - GPIO_FN_TCLK, GPIO_FN_RXD4, GPIO_FN_TXD4, + GPIO_FN_PWMU0, GPIO_FN_PWMU1, GPIO_FN_PWMU2, GPIO_FN_PWMU3, + GPIO_FN_PWMU4, GPIO_FN_PWMU5, + + /* PTD (mobule: SPI0, DMAC) */ + GPIO_FN_SP0_MOSI, GPIO_FN_SP0_MISO, GPIO_FN_SP0_SCK, + GPIO_FN_SP0_SCK_FB, GPIO_FN_SP0_SS0, GPIO_FN_SP0_SS1, + GPIO_FN_SP0_SS2, GPIO_FN_SP0_SS3, GPIO_FN_DREQ0, + GPIO_FN_DACK0, GPIO_FN_TEND0, + + /* PTE (mobule: RMII) */ + GPIO_FN_RMII0_CRS_DV, GPIO_FN_RMII0_TXD1, GPIO_FN_RMII0_TXD0, + GPIO_FN_RMII0_TXEN, GPIO_FN_RMII0_REFCLK, GPIO_FN_RMII0_RXD1, + GPIO_FN_RMII0_RXD0, GPIO_FN_RMII0_RX_ER, + + /* PTF (mobule: RMII, SerMux) */ + GPIO_FN_RMII1_CRS_DV, GPIO_FN_RMII1_TXD1, GPIO_FN_RMII1_TXD0, + GPIO_FN_RMII1_TXEN, GPIO_FN_RMII1_REFCLK, GPIO_FN_RMII1_RXD1, + GPIO_FN_RMII1_RXD0, GPIO_FN_RMII1_RX_ER, GPIO_FN_RAC_RI, + + /* PTG (mobule: system, LBSC, LPC, WDT, LPC, eMMC) */ + GPIO_FN_BOOTFMS, GPIO_FN_BOOTWP, + GPIO_FN_A25, GPIO_FN_A24, GPIO_FN_SERIRQ, GPIO_FN_WDTOVF, + GPIO_FN_LPCPD, GPIO_FN_LDRQ, GPIO_FN_MMCCLK, GPIO_FN_MMCCMD, + + /* PTH (mobule: SPI1, LPC, DMAC, ADC) */ GPIO_FN_SP1_MOSI, GPIO_FN_SP1_MISO, GPIO_FN_SP1_SCK, GPIO_FN_SP1_SCK_FB, GPIO_FN_SP1_SS0, GPIO_FN_SP1_SS1, - GPIO_FN_SP0_SS1, - - /* PTI (mobule: INTC) */ - GPIO_FN_IRQ15, GPIO_FN_IRQ14, GPIO_FN_IRQ13, GPIO_FN_IRQ12, - GPIO_FN_IRQ11, GPIO_FN_IRQ10, GPIO_FN_IRQ9, GPIO_FN_IRQ8, - - /* PTJ (mobule: SCIF234, SERMUX) */ - GPIO_FN_RXD3, GPIO_FN_TXD3, GPIO_FN_RXD2, GPIO_FN_TXD2, - GPIO_FN_COM1_TXD, GPIO_FN_COM1_RXD, - GPIO_FN_COM1_RTS, GPIO_FN_COM1_CTS, - - /* PTK (mobule: SERMUX) */ - GPIO_FN_COM2_TXD, GPIO_FN_COM2_RXD, - GPIO_FN_COM2_RTS, GPIO_FN_COM2_CTS, - GPIO_FN_COM2_DTR, GPIO_FN_COM2_DSR, - GPIO_FN_COM2_DCD, GPIO_FN_COM2_RI, + GPIO_FN_WP, GPIO_FN_FMS0, GPIO_FN_TEND1, GPIO_FN_DREQ1, + GPIO_FN_DACK1, GPIO_FN_ADTRG1, GPIO_FN_ADTRG0, - /* PTL (mobule: SERMUX) */ - GPIO_FN_RAC_TXD, GPIO_FN_RAC_RXD, - GPIO_FN_RAC_RTS, GPIO_FN_RAC_CTS, - GPIO_FN_RAC_DTR, GPIO_FN_RAC_DSR, - GPIO_FN_RAC_DCD, GPIO_FN_RAC_RI, + /* PTI (mobule: LBSC, SDHI) */ + GPIO_FN_D15, GPIO_FN_D14, GPIO_FN_D13, GPIO_FN_D12, + GPIO_FN_D11, GPIO_FN_D10, GPIO_FN_D9, GPIO_FN_D8, + GPIO_FN_SD_WP, GPIO_FN_SD_CD, GPIO_FN_SD_CLK, GPIO_FN_SD_CMD, + GPIO_FN_SD_D3, GPIO_FN_SD_D2, GPIO_FN_SD_D1, GPIO_FN_SD_D0, - /* PTM (mobule: IIC, LPC) */ + /* PTJ (mobule: SCIF234) */ + GPIO_FN_RTS3, GPIO_FN_CTS3, GPIO_FN_TXD3, GPIO_FN_RXD3, + GPIO_FN_RTS4, GPIO_FN_RXD4, GPIO_FN_TXD4, + + /* PTK (mobule: SERMUX, LBSC, SCIF) */ + GPIO_FN_COM2_TXD, GPIO_FN_COM2_RXD, GPIO_FN_COM2_RTS, + GPIO_FN_COM2_CTS, GPIO_FN_COM2_DTR, GPIO_FN_COM2_DSR, + GPIO_FN_COM2_DCD, GPIO_FN_CLKOUT, + GPIO_FN_SCK2, GPIO_FN_SCK4, GPIO_FN_SCK3, + + /* PTL (mobule: SERMUX, SCIF, LBSC, AUD) */ + GPIO_FN_RAC_RXD, GPIO_FN_RAC_RTS, GPIO_FN_RAC_CTS, + GPIO_FN_RAC_DTR, GPIO_FN_RAC_DSR, GPIO_FN_RAC_DCD, + GPIO_FN_RAC_TXD, GPIO_FN_RXD2, GPIO_FN_CS5, + GPIO_FN_CS6, GPIO_FN_AUDSYNC, GPIO_FN_AUDCK, + GPIO_FN_TXD2, + + /* PTM (mobule: LBSC, IIC) */ + GPIO_FN_CS4, GPIO_FN_RD, GPIO_FN_WE0, GPIO_FN_CS0, GPIO_FN_SDA6, GPIO_FN_SCL6, GPIO_FN_SDA7, GPIO_FN_SCL7, - GPIO_FN_WP, GPIO_FN_FMS0, GPIO_FN_FMS1, - - /* PTN (mobule: SCIF234, EVC) */ - GPIO_FN_SCK2, GPIO_FN_RTS4, GPIO_FN_RTS3, GPIO_FN_RTS2, - GPIO_FN_CTS4, GPIO_FN_CTS3, GPIO_FN_CTS2, - GPIO_FN_EVENT7, GPIO_FN_EVENT6, GPIO_FN_EVENT5, GPIO_FN_EVENT4, - GPIO_FN_EVENT3, GPIO_FN_EVENT2, GPIO_FN_EVENT1, GPIO_FN_EVENT0, - /* PTO (mobule: SGPIO) */ - GPIO_FN_SGPIO0_CLK, GPIO_FN_SGPIO0_LOAD, - GPIO_FN_SGPIO0_DI, GPIO_FN_SGPIO0_DO, - GPIO_FN_SGPIO1_CLK, GPIO_FN_SGPIO1_LOAD, - GPIO_FN_SGPIO1_DI, GPIO_FN_SGPIO1_DO, + /* PTN (mobule: USB, JMC, SGPIO, WDT) */ + GPIO_FN_VBUS_EN, GPIO_FN_VBUS_OC, GPIO_FN_JMCTCK, + GPIO_FN_JMCTMS, GPIO_FN_JMCTDO, GPIO_FN_JMCTDI, + GPIO_FN_JMCTRST, + GPIO_FN_SGPIO1_CLK, GPIO_FN_SGPIO1_LOAD, GPIO_FN_SGPIO1_DI, + GPIO_FN_SGPIO1_DO, GPIO_FN_SUB_CLKIN, - /* PTP (mobule: JMC, SCIF234) */ - GPIO_FN_JMCTCK, GPIO_FN_JMCTMS, GPIO_FN_JMCTDO, GPIO_FN_JMCTDI, - GPIO_FN_JMCRST, GPIO_FN_SCK4, GPIO_FN_SCK3, + /* PTO (mobule: SGPIO, SerMux) */ + GPIO_FN_SGPIO0_CLK, GPIO_FN_SGPIO0_LOAD, GPIO_FN_SGPIO0_DI, + GPIO_FN_SGPIO0_DO, GPIO_FN_SGPIO2_CLK, GPIO_FN_SGPIO2_LOAD, + GPIO_FN_SGPIO2_DI, GPIO_FN_SGPIO2_DO, GPIO_FN_COM1_TXD, + GPIO_FN_COM1_RXD, GPIO_FN_COM1_RTS, GPIO_FN_COM1_CTS, /* PTQ (mobule: LPC) */ GPIO_FN_LAD3, GPIO_FN_LAD2, GPIO_FN_LAD1, GPIO_FN_LAD0, GPIO_FN_LFRAME, GPIO_FN_LRESET, GPIO_FN_LCLK, /* PTR (mobule: GRA, IIC) */ - GPIO_FN_DDC3, GPIO_FN_DDC2, - GPIO_FN_SDA8, GPIO_FN_SCL8, GPIO_FN_SDA2, GPIO_FN_SCL2, + GPIO_FN_DDC3, GPIO_FN_DDC2, GPIO_FN_SDA2, GPIO_FN_SCL2, GPIO_FN_SDA1, GPIO_FN_SCL1, GPIO_FN_SDA0, GPIO_FN_SCL0, + GPIO_FN_SDA8, GPIO_FN_SCL8, /* PTS (mobule: GRA, IIC) */ - GPIO_FN_DDC1, GPIO_FN_DDC0, - GPIO_FN_SDA9, GPIO_FN_SCL9, GPIO_FN_SDA5, GPIO_FN_SCL5, + GPIO_FN_DDC1, GPIO_FN_DDC0, GPIO_FN_SDA5, GPIO_FN_SCL5, GPIO_FN_SDA4, GPIO_FN_SCL4, GPIO_FN_SDA3, GPIO_FN_SCL3, + GPIO_FN_SDA9, GPIO_FN_SCL9, - /* PTT (mobule: SYSTEM, PWMX) */ - GPIO_FN_AUDSYNC, GPIO_FN_AUDCK, - GPIO_FN_AUDATA3, GPIO_FN_AUDATA2, - GPIO_FN_AUDATA1, GPIO_FN_AUDATA0, - GPIO_FN_PWX7, GPIO_FN_PWX6, GPIO_FN_PWX5, GPIO_FN_PWX4, + /* PTT (mobule: PWMX, AUD) */ + GPIO_FN_PWMX7, GPIO_FN_PWMX6, GPIO_FN_PWMX5, GPIO_FN_PWMX4, + GPIO_FN_PWMX3, GPIO_FN_PWMX2, GPIO_FN_PWMX1, GPIO_FN_PWMX0, + GPIO_FN_AUDATA3, GPIO_FN_AUDATA2, GPIO_FN_AUDATA1, + GPIO_FN_AUDATA0, GPIO_FN_STATUS1, GPIO_FN_STATUS0, - /* PTU (mobule: LBSC, DMAC) */ - GPIO_FN_CS6, GPIO_FN_CS5, GPIO_FN_CS4, GPIO_FN_CS0, - GPIO_FN_RD, GPIO_FN_WE0, GPIO_FN_A25, GPIO_FN_A24, - GPIO_FN_DREQ0, GPIO_FN_DACK0, + /* PTU (mobule: LPC, APM) */ + GPIO_FN_LGPIO7, GPIO_FN_LGPIO6, GPIO_FN_LGPIO5, GPIO_FN_LGPIO4, + GPIO_FN_LGPIO3, GPIO_FN_LGPIO2, GPIO_FN_LGPIO1, GPIO_FN_LGPIO0, + GPIO_FN_APMONCTL_O, GPIO_FN_APMPWBTOUT_O, GPIO_FN_APMSCI_O, + GPIO_FN_APMVDDON, GPIO_FN_APMSLPBTN, GPIO_FN_APMPWRBTN, + GPIO_FN_APMS5N, GPIO_FN_APMS3N, - /* PTV (mobule: LBSC, DMAC) */ + /* PTV (mobule: LBSC, SerMux, R-SPI, EVC, GRA) */ GPIO_FN_A23, GPIO_FN_A22, GPIO_FN_A21, GPIO_FN_A20, GPIO_FN_A19, GPIO_FN_A18, GPIO_FN_A17, GPIO_FN_A16, - GPIO_FN_TEND0, GPIO_FN_DREQ1, GPIO_FN_DACK1, GPIO_FN_TEND1, + GPIO_FN_COM2_RI, GPIO_FN_R_SPI_MOSI, GPIO_FN_R_SPI_MISO, + GPIO_FN_R_SPI_RSPCK, GPIO_FN_R_SPI_SSL0, GPIO_FN_R_SPI_SSL1, + GPIO_FN_EVENT7, GPIO_FN_EVENT6, GPIO_FN_VBIOS_DI, + GPIO_FN_VBIOS_DO, GPIO_FN_VBIOS_CLK, GPIO_FN_VBIOS_CS, - /* PTW (mobule: LBSC) */ + /* PTW (mobule: LBSC, EVC, SCIF) */ GPIO_FN_A15, GPIO_FN_A14, GPIO_FN_A13, GPIO_FN_A12, GPIO_FN_A11, GPIO_FN_A10, GPIO_FN_A9, GPIO_FN_A8, + GPIO_FN_EVENT5, GPIO_FN_EVENT4, GPIO_FN_EVENT3, GPIO_FN_EVENT2, + GPIO_FN_EVENT1, GPIO_FN_EVENT0, GPIO_FN_CTS4, GPIO_FN_CTS2, - /* PTX (mobule: LBSC) */ + /* PTX (mobule: LBSC, SCIF, SIM) */ GPIO_FN_A7, GPIO_FN_A6, GPIO_FN_A5, GPIO_FN_A4, GPIO_FN_A3, GPIO_FN_A2, GPIO_FN_A1, GPIO_FN_A0, + GPIO_FN_RTS2, GPIO_FN_SIM_D, GPIO_FN_SIM_CLK, GPIO_FN_SIM_RST, /* PTY (mobule: LBSC) */ GPIO_FN_D7, GPIO_FN_D6, GPIO_FN_D5, GPIO_FN_D4, GPIO_FN_D3, GPIO_FN_D2, GPIO_FN_D1, GPIO_FN_D0, + + /* PTZ (mobule: eMMC, ONFI) */ + GPIO_FN_MMCDAT7, GPIO_FN_MMCDAT6, GPIO_FN_MMCDAT5, + GPIO_FN_MMCDAT4, GPIO_FN_MMCDAT3, GPIO_FN_MMCDAT2, + GPIO_FN_MMCDAT1, GPIO_FN_MMCDAT0, + GPIO_FN_ON_DQ7, GPIO_FN_ON_DQ6, GPIO_FN_ON_DQ5, GPIO_FN_ON_DQ4, + GPIO_FN_ON_DQ3, GPIO_FN_ON_DQ2, GPIO_FN_ON_DQ1, GPIO_FN_ON_DQ0, }; #endif /* __ASM_SH7757_H__ */ diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c index ed23b155c097..4c74bd04bba4 100644 --- a/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c @@ -1,11 +1,11 @@ /* - * SH7757 (A0 step) Pinmux + * SH7757 (B0 step) Pinmux * - * Copyright (C) 2009 Renesas Solutions Corp. + * Copyright (C) 2009-2010 Renesas Solutions Corp. * * Author : Yoshihiro Shimoda * - * Based on SH7757 Pinmux + * Based on SH7723 Pinmux * Copyright (C) 2008 Magnus Damm * * This file is subject to the terms and conditions of the GNU General Public @@ -40,27 +40,27 @@ enum { PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA, PTI7_DATA, PTI6_DATA, PTI5_DATA, PTI4_DATA, PTI3_DATA, PTI2_DATA, PTI1_DATA, PTI0_DATA, - PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA, + PTJ6_DATA, PTJ5_DATA, PTJ4_DATA, PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA, PTK7_DATA, PTK6_DATA, PTK5_DATA, PTK4_DATA, PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA, - PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA, + PTL6_DATA, PTL5_DATA, PTL4_DATA, PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA, - PTM6_DATA, PTM5_DATA, PTM4_DATA, + PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA, PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA, - PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA, + PTN6_DATA, PTN5_DATA, PTN4_DATA, PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA, PTO7_DATA, PTO6_DATA, PTO5_DATA, PTO4_DATA, PTO3_DATA, PTO2_DATA, PTO1_DATA, PTO0_DATA, - PTP6_DATA, PTP5_DATA, PTP4_DATA, + PTP7_DATA, PTP6_DATA, PTP5_DATA, PTP4_DATA, PTP3_DATA, PTP2_DATA, PTP1_DATA, PTP0_DATA, - PTQ6_DATA, PTQ5_DATA, PTQ4_DATA, + PTQ6_DATA, PTQ5_DATA, PTQ4_DATA, PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA, PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA, PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA, PTS7_DATA, PTS6_DATA, PTS5_DATA, PTS4_DATA, PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA, - PTT5_DATA, PTT4_DATA, + PTT7_DATA, PTT6_DATA, PTT5_DATA, PTT4_DATA, PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA, PTU7_DATA, PTU6_DATA, PTU5_DATA, PTU4_DATA, PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA, @@ -95,27 +95,27 @@ enum { PTH3_IN, PTH2_IN, PTH1_IN, PTH0_IN, PTI7_IN, PTI6_IN, PTI5_IN, PTI4_IN, PTI3_IN, PTI2_IN, PTI1_IN, PTI0_IN, - PTJ7_IN, PTJ6_IN, PTJ5_IN, PTJ4_IN, + PTJ6_IN, PTJ5_IN, PTJ4_IN, PTJ3_IN, PTJ2_IN, PTJ1_IN, PTJ0_IN, PTK7_IN, PTK6_IN, PTK5_IN, PTK4_IN, PTK3_IN, PTK2_IN, PTK1_IN, PTK0_IN, - PTL7_IN, PTL6_IN, PTL5_IN, PTL4_IN, + PTL6_IN, PTL5_IN, PTL4_IN, PTL3_IN, PTL2_IN, PTL1_IN, PTL0_IN, - PTM6_IN, PTM5_IN, PTM4_IN, + PTM7_IN, PTM6_IN, PTM5_IN, PTM4_IN, PTM3_IN, PTM2_IN, PTM1_IN, PTM0_IN, - PTN7_IN, PTN6_IN, PTN5_IN, PTN4_IN, + PTN6_IN, PTN5_IN, PTN4_IN, PTN3_IN, PTN2_IN, PTN1_IN, PTN0_IN, PTO7_IN, PTO6_IN, PTO5_IN, PTO4_IN, PTO3_IN, PTO2_IN, PTO1_IN, PTO0_IN, - PTP6_IN, PTP5_IN, PTP4_IN, + PTP7_IN, PTP6_IN, PTP5_IN, PTP4_IN, PTP3_IN, PTP2_IN, PTP1_IN, PTP0_IN, - PTQ6_IN, PTQ5_IN, PTQ4_IN, + PTQ6_IN, PTQ5_IN, PTQ4_IN, PTQ3_IN, PTQ2_IN, PTQ1_IN, PTQ0_IN, PTR7_IN, PTR6_IN, PTR5_IN, PTR4_IN, PTR3_IN, PTR2_IN, PTR1_IN, PTR0_IN, PTS7_IN, PTS6_IN, PTS5_IN, PTS4_IN, PTS3_IN, PTS2_IN, PTS1_IN, PTS0_IN, - PTT5_IN, PTT4_IN, + PTT7_IN, PTT6_IN, PTT5_IN, PTT4_IN, PTT3_IN, PTT2_IN, PTT1_IN, PTT0_IN, PTU7_IN, PTU6_IN, PTU5_IN, PTU4_IN, PTU3_IN, PTU2_IN, PTU1_IN, PTU0_IN, @@ -132,16 +132,43 @@ enum { PINMUX_INPUT_END, PINMUX_INPUT_PULLUP_BEGIN, + PTA7_IN_PU, PTA6_IN_PU, PTA5_IN_PU, PTA4_IN_PU, + PTA3_IN_PU, PTA2_IN_PU, PTA1_IN_PU, PTA0_IN_PU, + PTD7_IN_PU, PTD6_IN_PU, PTD5_IN_PU, PTD4_IN_PU, + PTD3_IN_PU, PTD2_IN_PU, PTD1_IN_PU, PTD0_IN_PU, + PTE7_IN_PU, PTE6_IN_PU, PTE5_IN_PU, PTE4_IN_PU, + PTE3_IN_PU, PTE2_IN_PU, PTE1_IN_PU, PTE0_IN_PU, + PTF7_IN_PU, PTF6_IN_PU, PTF5_IN_PU, PTF4_IN_PU, + PTF3_IN_PU, PTF2_IN_PU, PTF1_IN_PU, PTF0_IN_PU, + PTG7_IN_PU, PTG6_IN_PU, PTG4_IN_PU, + PTH7_IN_PU, PTH6_IN_PU, PTH5_IN_PU, PTH4_IN_PU, + PTH3_IN_PU, PTH2_IN_PU, PTH1_IN_PU, PTH0_IN_PU, + PTI7_IN_PU, PTI6_IN_PU, PTI4_IN_PU, + PTI3_IN_PU, PTI2_IN_PU, PTI1_IN_PU, PTI0_IN_PU, + PTJ6_IN_PU, PTJ5_IN_PU, PTJ4_IN_PU, + PTJ3_IN_PU, PTJ2_IN_PU, PTJ1_IN_PU, PTJ0_IN_PU, + PTK7_IN_PU, PTK6_IN_PU, PTK5_IN_PU, PTK4_IN_PU, + PTK3_IN_PU, PTK2_IN_PU, PTK1_IN_PU, PTK0_IN_PU, + PTL6_IN_PU, PTL5_IN_PU, PTL4_IN_PU, + PTL3_IN_PU, PTL2_IN_PU, PTL1_IN_PU, PTL0_IN_PU, + PTM7_IN_PU, PTM6_IN_PU, PTM5_IN_PU, PTM4_IN_PU, + PTN4_IN_PU, + PTN3_IN_PU, PTN2_IN_PU, PTN1_IN_PU, PTN0_IN_PU, + PTO7_IN_PU, PTO6_IN_PU, PTO5_IN_PU, PTO4_IN_PU, + PTO3_IN_PU, PTO2_IN_PU, PTO1_IN_PU, PTO0_IN_PU, + PTT7_IN_PU, PTT6_IN_PU, PTT5_IN_PU, PTT4_IN_PU, + PTT3_IN_PU, PTT2_IN_PU, PTT1_IN_PU, PTT0_IN_PU, PTU7_IN_PU, PTU6_IN_PU, PTU5_IN_PU, PTU4_IN_PU, PTU3_IN_PU, PTU2_IN_PU, PTU1_IN_PU, PTU0_IN_PU, PTV7_IN_PU, PTV6_IN_PU, PTV5_IN_PU, PTV4_IN_PU, - PTV3_IN_PU, PTV2_IN_PU, PTV1_IN_PU, PTV0_IN_PU, - PTW7_IN_PU, PTW6_IN_PU, PTW5_IN_PU, PTW4_IN_PU, - PTW3_IN_PU, PTW2_IN_PU, PTW1_IN_PU, PTW0_IN_PU, + PTV3_IN_PU, PTV2_IN_PU, + PTW1_IN_PU, PTW0_IN_PU, PTX7_IN_PU, PTX6_IN_PU, PTX5_IN_PU, PTX4_IN_PU, PTX3_IN_PU, PTX2_IN_PU, PTX1_IN_PU, PTX0_IN_PU, PTY7_IN_PU, PTY6_IN_PU, PTY5_IN_PU, PTY4_IN_PU, PTY3_IN_PU, PTY2_IN_PU, PTY1_IN_PU, PTY0_IN_PU, + PTZ7_IN_PU, PTZ6_IN_PU, PTZ5_IN_PU, PTZ4_IN_PU, + PTZ3_IN_PU, PTZ2_IN_PU, PTZ1_IN_PU, PTZ0_IN_PU, PINMUX_INPUT_PULLUP_END, PINMUX_OUTPUT_BEGIN, @@ -163,27 +190,27 @@ enum { PTH3_OUT, PTH2_OUT, PTH1_OUT, PTH0_OUT, PTI7_OUT, PTI6_OUT, PTI5_OUT, PTI4_OUT, PTI3_OUT, PTI2_OUT, PTI1_OUT, PTI0_OUT, - PTJ7_OUT, PTJ6_OUT, PTJ5_OUT, PTJ4_OUT, + PTJ6_OUT, PTJ5_OUT, PTJ4_OUT, PTJ3_OUT, PTJ2_OUT, PTJ1_OUT, PTJ0_OUT, PTK7_OUT, PTK6_OUT, PTK5_OUT, PTK4_OUT, PTK3_OUT, PTK2_OUT, PTK1_OUT, PTK0_OUT, - PTL7_OUT, PTL6_OUT, PTL5_OUT, PTL4_OUT, + PTL6_OUT, PTL5_OUT, PTL4_OUT, PTL3_OUT, PTL2_OUT, PTL1_OUT, PTL0_OUT, - PTM6_OUT, PTM5_OUT, PTM4_OUT, + PTM7_OUT, PTM6_OUT, PTM5_OUT, PTM4_OUT, PTM3_OUT, PTM2_OUT, PTM1_OUT, PTM0_OUT, - PTN7_OUT, PTN6_OUT, PTN5_OUT, PTN4_OUT, + PTN6_OUT, PTN5_OUT, PTN4_OUT, PTN3_OUT, PTN2_OUT, PTN1_OUT, PTN0_OUT, PTO7_OUT, PTO6_OUT, PTO5_OUT, PTO4_OUT, PTO3_OUT, PTO2_OUT, PTO1_OUT, PTO0_OUT, - PTP6_OUT, PTP5_OUT, PTP4_OUT, + PTP7_OUT, PTP6_OUT, PTP5_OUT, PTP4_OUT, PTP3_OUT, PTP2_OUT, PTP1_OUT, PTP0_OUT, - PTQ6_OUT, PTQ5_OUT, PTQ4_OUT, + PTQ6_OUT, PTQ5_OUT, PTQ4_OUT, PTQ3_OUT, PTQ2_OUT, PTQ1_OUT, PTQ0_OUT, PTR7_OUT, PTR6_OUT, PTR5_OUT, PTR4_OUT, PTR3_OUT, PTR2_OUT, PTR1_OUT, PTR0_OUT, PTS7_OUT, PTS6_OUT, PTS5_OUT, PTS4_OUT, PTS3_OUT, PTS2_OUT, PTS1_OUT, PTS0_OUT, - PTT5_OUT, PTT4_OUT, + PTT7_OUT, PTT6_OUT, PTT5_OUT, PTT4_OUT, PTT3_OUT, PTT2_OUT, PTT1_OUT, PTT0_OUT, PTU7_OUT, PTU6_OUT, PTU5_OUT, PTU4_OUT, PTU3_OUT, PTU2_OUT, PTU1_OUT, PTU0_OUT, @@ -218,27 +245,27 @@ enum { PTH3_FN, PTH2_FN, PTH1_FN, PTH0_FN, PTI7_FN, PTI6_FN, PTI5_FN, PTI4_FN, PTI3_FN, PTI2_FN, PTI1_FN, PTI0_FN, - PTJ7_FN, PTJ6_FN, PTJ5_FN, PTJ4_FN, + PTJ6_FN, PTJ5_FN, PTJ4_FN, PTJ3_FN, PTJ2_FN, PTJ1_FN, PTJ0_FN, PTK7_FN, PTK6_FN, PTK5_FN, PTK4_FN, PTK3_FN, PTK2_FN, PTK1_FN, PTK0_FN, - PTL7_FN, PTL6_FN, PTL5_FN, PTL4_FN, + PTL6_FN, PTL5_FN, PTL4_FN, PTL3_FN, PTL2_FN, PTL1_FN, PTL0_FN, - PTM6_FN, PTM5_FN, PTM4_FN, + PTM7_FN, PTM6_FN, PTM5_FN, PTM4_FN, PTM3_FN, PTM2_FN, PTM1_FN, PTM0_FN, - PTN7_FN, PTN6_FN, PTN5_FN, PTN4_FN, + PTN6_FN, PTN5_FN, PTN4_FN, PTN3_FN, PTN2_FN, PTN1_FN, PTN0_FN, PTO7_FN, PTO6_FN, PTO5_FN, PTO4_FN, PTO3_FN, PTO2_FN, PTO1_FN, PTO0_FN, - PTP6_FN, PTP5_FN, PTP4_FN, + PTP7_FN, PTP6_FN, PTP5_FN, PTP4_FN, PTP3_FN, PTP2_FN, PTP1_FN, PTP0_FN, - PTQ6_FN, PTQ5_FN, PTQ4_FN, + PTQ6_FN, PTQ5_FN, PTQ4_FN, PTQ3_FN, PTQ2_FN, PTQ1_FN, PTQ0_FN, PTR7_FN, PTR6_FN, PTR5_FN, PTR4_FN, PTR3_FN, PTR2_FN, PTR1_FN, PTR0_FN, PTS7_FN, PTS6_FN, PTS5_FN, PTS4_FN, PTS3_FN, PTS2_FN, PTS1_FN, PTS0_FN, - PTT5_FN, PTT4_FN, + PTT7_FN, PTT6_FN, PTT5_FN, PTT4_FN, PTT3_FN, PTT2_FN, PTT1_FN, PTT0_FN, PTU7_FN, PTU6_FN, PTU5_FN, PTU4_FN, PTU3_FN, PTU2_FN, PTU1_FN, PTU0_FN, @@ -253,181 +280,248 @@ enum { PTZ7_FN, PTZ6_FN, PTZ5_FN, PTZ4_FN, PTZ3_FN, PTZ2_FN, PTZ1_FN, PTZ0_FN, - PS0_15_FN1, PS0_15_FN3, - PS0_14_FN1, PS0_14_FN3, - PS0_13_FN1, PS0_13_FN3, - PS0_12_FN1, PS0_12_FN3, + PS0_15_FN1, PS0_15_FN2, + PS0_14_FN1, PS0_14_FN2, + PS0_13_FN1, PS0_13_FN2, + PS0_12_FN1, PS0_12_FN2, + PS0_11_FN1, PS0_11_FN2, + PS0_10_FN1, PS0_10_FN2, + PS0_9_FN1, PS0_9_FN2, + PS0_8_FN1, PS0_8_FN2, PS0_7_FN1, PS0_7_FN2, PS0_6_FN1, PS0_6_FN2, PS0_5_FN1, PS0_5_FN2, PS0_4_FN1, PS0_4_FN2, PS0_3_FN1, PS0_3_FN2, PS0_2_FN1, PS0_2_FN2, - PS0_1_FN1, PS0_1_FN2, - PS1_7_FN1, PS1_7_FN3, - PS1_6_FN1, PS1_6_FN3, + PS1_10_FN1, PS1_10_FN2, + PS1_9_FN1, PS1_9_FN2, + PS1_8_FN1, PS1_8_FN2, + PS1_2_FN1, PS1_2_FN2, + + PS2_13_FN1, PS2_13_FN2, + PS2_12_FN1, PS2_12_FN2, + PS2_7_FN1, PS2_7_FN2, + PS2_6_FN1, PS2_6_FN2, + PS2_5_FN1, PS2_5_FN2, + PS2_4_FN1, PS2_4_FN2, + PS2_2_FN1, PS2_2_FN2, + + PS3_15_FN1, PS3_15_FN2, + PS3_14_FN1, PS3_14_FN2, + PS3_13_FN1, PS3_13_FN2, + PS3_12_FN1, PS3_12_FN2, + PS3_11_FN1, PS3_11_FN2, + PS3_10_FN1, PS3_10_FN2, + PS3_9_FN1, PS3_9_FN2, + PS3_8_FN1, PS3_8_FN2, + PS3_7_FN1, PS3_7_FN2, + PS3_2_FN1, PS3_2_FN2, + PS3_1_FN1, PS3_1_FN2, - PS2_13_FN1, PS2_13_FN3, - PS2_12_FN1, PS2_12_FN3, - PS2_1_FN1, PS2_1_FN2, - PS2_0_FN1, PS2_0_FN2, - - PS4_15_FN1, PS4_15_FN2, PS4_14_FN1, PS4_14_FN2, PS4_13_FN1, PS4_13_FN2, PS4_12_FN1, PS4_12_FN2, - PS4_11_FN1, PS4_11_FN2, PS4_10_FN1, PS4_10_FN2, PS4_9_FN1, PS4_9_FN2, + PS4_8_FN1, PS4_8_FN2, + PS4_4_FN1, PS4_4_FN2, PS4_3_FN1, PS4_3_FN2, PS4_2_FN1, PS4_2_FN2, PS4_1_FN1, PS4_1_FN2, PS4_0_FN1, PS4_0_FN2, + PS5_11_FN1, PS5_11_FN2, + PS5_10_FN1, PS5_10_FN2, PS5_9_FN1, PS5_9_FN2, PS5_8_FN1, PS5_8_FN2, PS5_7_FN1, PS5_7_FN2, PS5_6_FN1, PS5_6_FN2, PS5_5_FN1, PS5_5_FN2, PS5_4_FN1, PS5_4_FN2, - - /* AN15 to 8 : EVENT15 to 8 */ - PS6_7_FN_AN, PS6_7_FN_EV, - PS6_6_FN_AN, PS6_6_FN_EV, - PS6_5_FN_AN, PS6_5_FN_EV, - PS6_4_FN_AN, PS6_4_FN_EV, - PS6_3_FN_AN, PS6_3_FN_EV, - PS6_2_FN_AN, PS6_2_FN_EV, - PS6_1_FN_AN, PS6_1_FN_EV, - PS6_0_FN_AN, PS6_0_FN_EV, - + PS5_3_FN1, PS5_3_FN2, + PS5_2_FN1, PS5_2_FN2, + + PS6_15_FN1, PS6_15_FN2, + PS6_14_FN1, PS6_14_FN2, + PS6_13_FN1, PS6_13_FN2, + PS6_12_FN1, PS6_12_FN2, + PS6_11_FN1, PS6_11_FN2, + PS6_10_FN1, PS6_10_FN2, + PS6_9_FN1, PS6_9_FN2, + PS6_8_FN1, PS6_8_FN2, + PS6_7_FN1, PS6_7_FN2, + PS6_6_FN1, PS6_6_FN2, + PS6_5_FN1, PS6_5_FN2, + PS6_4_FN1, PS6_4_FN2, + PS6_3_FN1, PS6_3_FN2, + PS6_2_FN1, PS6_2_FN2, + PS6_1_FN1, PS6_1_FN2, + PS6_0_FN1, PS6_0_FN2, + + PS7_15_FN1, PS7_15_FN2, + PS7_14_FN1, PS7_14_FN2, + PS7_13_FN1, PS7_13_FN2, + PS7_12_FN1, PS7_12_FN2, + PS7_11_FN1, PS7_11_FN2, + PS7_10_FN1, PS7_10_FN2, + PS7_9_FN1, PS7_9_FN2, + PS7_8_FN1, PS7_8_FN2, + PS7_7_FN1, PS7_7_FN2, + PS7_6_FN1, PS7_6_FN2, + PS7_5_FN1, PS7_5_FN2, + PS7_4_FN1, PS7_4_FN2, + + PS8_15_FN1, PS8_15_FN2, + PS8_14_FN1, PS8_14_FN2, + PS8_13_FN1, PS8_13_FN2, + PS8_12_FN1, PS8_12_FN2, + PS8_11_FN1, PS8_11_FN2, + PS8_10_FN1, PS8_10_FN2, + PS8_9_FN1, PS8_9_FN2, + PS8_8_FN1, PS8_8_FN2, PINMUX_FUNCTION_END, PINMUX_MARK_BEGIN, - /* PTA (mobule: LBSC, CPG, LPC) */ + /* PTA (mobule: LBSC, RGMII) */ BS_MARK, RDWR_MARK, WE1_MARK, RDY_MARK, - MD10_MARK, MD9_MARK, MD8_MARK, - LGPIO7_MARK, LGPIO6_MARK, LGPIO5_MARK, LGPIO4_MARK, - LGPIO3_MARK, LGPIO2_MARK, LGPIO1_MARK, LGPIO0_MARK, - - /* PTB (mobule: LBSC, EtherC, SIM, LPC) */ - D15_MARK, D14_MARK, D13_MARK, D12_MARK, - D11_MARK, D10_MARK, D9_MARK, D8_MARK, ET0_MDC_MARK, ET0_MDIO_MARK, ET1_MDC_MARK, ET1_MDIO_MARK, - SIM_D_MARK, SIM_CLK_MARK, SIM_RST_MARK, - WPSZ1_MARK, WPSZ0_MARK, FWID_MARK, FLSHSZ_MARK, - LPC_SPIEN_MARK, BASEL_MARK, - /* PTC (mobule: SD) */ - SD_WP_MARK, SD_CD_MARK, SD_CLK_MARK, SD_CMD_MARK, - SD_D3_MARK, SD_D2_MARK, SD_D1_MARK, SD_D0_MARK, + /* PTB (mobule: INTC, ONFI, TMU) */ + IRQ15_MARK, IRQ14_MARK, IRQ13_MARK, IRQ12_MARK, + IRQ11_MARK, IRQ10_MARK, IRQ9_MARK, IRQ8_MARK, + ON_NRE_MARK, ON_NWE_MARK, ON_NWP_MARK, ON_NCE0_MARK, + ON_R_B0_MARK, ON_ALE_MARK, ON_CLE_MARK, TCLK_MARK, - /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */ + /* PTC (mobule: IRQ, PWMU) */ IRQ7_MARK, IRQ6_MARK, IRQ5_MARK, IRQ4_MARK, IRQ3_MARK, IRQ2_MARK, IRQ1_MARK, IRQ0_MARK, - MD6_MARK, MD5_MARK, MD3_MARK, MD2_MARK, - MD1_MARK, MD0_MARK, ADTRG1_MARK, ADTRG0_MARK, - - /* PTE (mobule: EtherC) */ - ET0_CRS_DV_MARK, ET0_TXD1_MARK, - ET0_TXD0_MARK, ET0_TX_EN_MARK, - ET0_REF_CLK_MARK, ET0_RXD1_MARK, - ET0_RXD0_MARK, ET0_RX_ER_MARK, - - /* PTF (mobule: EtherC) */ - ET1_CRS_DV_MARK, ET1_TXD1_MARK, - ET1_TXD0_MARK, ET1_TX_EN_MARK, - ET1_REF_CLK_MARK, ET1_RXD1_MARK, - ET1_RXD0_MARK, ET1_RX_ER_MARK, - - /* PTG (mobule: SYSTEM, PWMX, LPC) */ - STATUS0_MARK, STATUS1_MARK, - PWX0_MARK, PWX1_MARK, PWX2_MARK, PWX3_MARK, - SERIRQ_MARK, CLKRUN_MARK, LPCPD_MARK, LDRQ_MARK, - - /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */ - TCLK_MARK, RXD4_MARK, TXD4_MARK, + PWMU0_MARK, PWMU1_MARK, PWMU2_MARK, PWMU3_MARK, + PWMU4_MARK, PWMU5_MARK, + + /* PTD (mobule: SPI0, DMAC) */ + SP0_MOSI_MARK, SP0_MISO_MARK, SP0_SCK_MARK, SP0_SCK_FB_MARK, + SP0_SS0_MARK, SP0_SS1_MARK, SP0_SS2_MARK, SP0_SS3_MARK, + DREQ0_MARK, DACK0_MARK, TEND0_MARK, + + /* PTE (mobule: RMII) */ + RMII0_CRS_DV_MARK, RMII0_TXD1_MARK, + RMII0_TXD0_MARK, RMII0_TXEN_MARK, + RMII0_REFCLK_MARK, RMII0_RXD1_MARK, + RMII0_RXD0_MARK, RMII0_RX_ER_MARK, + + /* PTF (mobule: RMII, SerMux) */ + RMII1_CRS_DV_MARK, RMII1_TXD1_MARK, + RMII1_TXD0_MARK, RMII1_TXEN_MARK, + RMII1_REFCLK_MARK, RMII1_RXD1_MARK, + RMII1_RXD0_MARK, RMII1_RX_ER_MARK, + RAC_RI_MARK, + + /* PTG (mobule: system, LBSC, LPC, WDT, LPC, eMMC) */ + BOOTFMS_MARK, BOOTWP_MARK, A25_MARK, A24_MARK, + SERIRQ_MARK, WDTOVF_MARK, LPCPD_MARK, LDRQ_MARK, + MMCCLK_MARK, MMCCMD_MARK, + + /* PTH (mobule: SPI1, LPC, DMAC, ADC) */ SP1_MOSI_MARK, SP1_MISO_MARK, SP1_SCK_MARK, SP1_SCK_FB_MARK, - SP1_SS0_MARK, SP1_SS1_MARK, SP0_SS1_MARK, + SP1_SS0_MARK, SP1_SS1_MARK, WP_MARK, FMS0_MARK, + TEND1_MARK, DREQ1_MARK, DACK1_MARK, ADTRG1_MARK, + ADTRG0_MARK, - /* PTI (mobule: INTC) */ - IRQ15_MARK, IRQ14_MARK, IRQ13_MARK, IRQ12_MARK, - IRQ11_MARK, IRQ10_MARK, IRQ9_MARK, IRQ8_MARK, + /* PTI (mobule: LBSC, SDHI) */ + D15_MARK, D14_MARK, D13_MARK, D12_MARK, + D11_MARK, D10_MARK, D9_MARK, D8_MARK, + SD_WP_MARK, SD_CD_MARK, SD_CLK_MARK, SD_CMD_MARK, + SD_D3_MARK, SD_D2_MARK, SD_D1_MARK, SD_D0_MARK, - /* PTJ (mobule: SCIF234, SERMUX) */ - RXD3_MARK, TXD3_MARK, RXD2_MARK, TXD2_MARK, - COM1_TXD_MARK, COM1_RXD_MARK, COM1_RTS_MARK, COM1_CTS_MARK, + /* PTJ (mobule: SCIF234) */ + RTS3_MARK, CTS3_MARK, TXD3_MARK, RXD3_MARK, + RTS4_MARK, RXD4_MARK, TXD4_MARK, - /* PTK (mobule: SERMUX) */ + /* PTK (mobule: SERMUX, LBSC, SCIF) */ COM2_TXD_MARK, COM2_RXD_MARK, COM2_RTS_MARK, COM2_CTS_MARK, - COM2_DTR_MARK, COM2_DSR_MARK, COM2_DCD_MARK, COM2_RI_MARK, + COM2_DTR_MARK, COM2_DSR_MARK, COM2_DCD_MARK, CLKOUT_MARK, + SCK2_MARK, SCK4_MARK, SCK3_MARK, - /* PTL (mobule: SERMUX) */ - RAC_TXD_MARK, RAC_RXD_MARK, RAC_RTS_MARK, RAC_CTS_MARK, - RAC_DTR_MARK, RAC_DSR_MARK, RAC_DCD_MARK, RAC_RI_MARK, + /* PTL (mobule: SERMUX, SCIF, LBSC, AUD) */ + RAC_RXD_MARK, RAC_RTS_MARK, RAC_CTS_MARK, RAC_DTR_MARK, + RAC_DSR_MARK, RAC_DCD_MARK, RAC_TXD_MARK, RXD2_MARK, + CS5_MARK, CS6_MARK, AUDSYNC_MARK, AUDCK_MARK, + TXD2_MARK, - /* PTM (mobule: IIC, LPC) */ + /* PTM (mobule: LBSC, IIC) */ + CS4_MARK, RD_MARK, WE0_MARK, CS0_MARK, SDA6_MARK, SCL6_MARK, SDA7_MARK, SCL7_MARK, - WP_MARK, FMS0_MARK, FMS1_MARK, - /* PTN (mobule: SCIF234, EVC) */ - SCK2_MARK, RTS4_MARK, RTS3_MARK, RTS2_MARK, - CTS4_MARK, CTS3_MARK, CTS2_MARK, - EVENT7_MARK, EVENT6_MARK, EVENT5_MARK, EVENT4_MARK, - EVENT3_MARK, EVENT2_MARK, EVENT1_MARK, EVENT0_MARK, + /* PTN (mobule: USB, JMC, SGPIO, WDT) */ + VBUS_EN_MARK, VBUS_OC_MARK, JMCTCK_MARK, JMCTMS_MARK, + JMCTDO_MARK, JMCTDI_MARK, JMCTRST_MARK, + SGPIO1_CLK_MARK, SGPIO1_LOAD_MARK, SGPIO1_DI_MARK, + SGPIO1_DO_MARK, SUB_CLKIN_MARK, - /* PTO (mobule: SGPIO) */ - SGPIO0_CLK_MARK, SGPIO0_LOAD_MARK, - SGPIO0_DI_MARK, SGPIO0_DO_MARK, - SGPIO1_CLK_MARK, SGPIO1_LOAD_MARK, - SGPIO1_DI_MARK, SGPIO1_DO_MARK, - - /* PTP (mobule: JMC, SCIF234) */ - JMCTCK_MARK, JMCTMS_MARK, JMCTDO_MARK, JMCTDI_MARK, - JMCRST_MARK, SCK4_MARK, SCK3_MARK, + /* PTO (mobule: SGPIO, SerMux) */ + SGPIO0_CLK_MARK, SGPIO0_LOAD_MARK, SGPIO0_DI_MARK, + SGPIO0_DO_MARK, SGPIO2_CLK_MARK, SGPIO2_LOAD_MARK, + SGPIO2_DI_MARK, SGPIO2_DO_MARK, + COM1_TXD_MARK, COM1_RXD_MARK, COM1_RTS_MARK, COM1_CTS_MARK, /* PTQ (mobule: LPC) */ LAD3_MARK, LAD2_MARK, LAD1_MARK, LAD0_MARK, LFRAME_MARK, LRESET_MARK, LCLK_MARK, /* PTR (mobule: GRA, IIC) */ - DDC3_MARK, DDC2_MARK, - SDA8_MARK, SCL8_MARK, SDA2_MARK, SCL2_MARK, + DDC3_MARK, DDC2_MARK, SDA2_MARK, SCL2_MARK, SDA1_MARK, SCL1_MARK, SDA0_MARK, SCL0_MARK, + SDA8_MARK, SCL8_MARK, /* PTS (mobule: GRA, IIC) */ - DDC1_MARK, DDC0_MARK, - SDA9_MARK, SCL9_MARK, SDA5_MARK, SCL5_MARK, + DDC1_MARK, DDC0_MARK, SDA5_MARK, SCL5_MARK, SDA4_MARK, SCL4_MARK, SDA3_MARK, SCL3_MARK, + SDA9_MARK, SCL9_MARK, - /* PTT (mobule: SYSTEM, PWMX) */ - AUDSYNC_MARK, AUDCK_MARK, - AUDATA3_MARK, AUDATA2_MARK, - AUDATA1_MARK, AUDATA0_MARK, - PWX7_MARK, PWX6_MARK, PWX5_MARK, PWX4_MARK, + /* PTT (mobule: PWMX, AUD) */ + PWMX7_MARK, PWMX6_MARK, PWMX5_MARK, PWMX4_MARK, + PWMX3_MARK, PWMX2_MARK, PWMX1_MARK, PWMX0_MARK, + AUDATA3_MARK, AUDATA2_MARK, AUDATA1_MARK, AUDATA0_MARK, + STATUS1_MARK, STATUS0_MARK, - /* PTU (mobule: LBSC, DMAC) */ - CS6_MARK, CS5_MARK, CS4_MARK, CS0_MARK, - RD_MARK, WE0_MARK, A25_MARK, A24_MARK, - DREQ0_MARK, DACK0_MARK, + /* PTU (mobule: LPC, APM) */ + LGPIO7_MARK, LGPIO6_MARK, LGPIO5_MARK, LGPIO4_MARK, + LGPIO3_MARK, LGPIO2_MARK, LGPIO1_MARK, LGPIO0_MARK, + APMONCTL_O_MARK, APMPWBTOUT_O_MARK, APMSCI_O_MARK, + APMVDDON_MARK, APMSLPBTN_MARK, APMPWRBTN_MARK, APMS5N_MARK, + APMS3N_MARK, - /* PTV (mobule: LBSC, DMAC) */ + /* PTV (mobule: LBSC, SerMux, R-SPI, EVC, GRA) */ A23_MARK, A22_MARK, A21_MARK, A20_MARK, A19_MARK, A18_MARK, A17_MARK, A16_MARK, - TEND0_MARK, DREQ1_MARK, DACK1_MARK, TEND1_MARK, + COM2_RI_MARK, R_SPI_MOSI_MARK, R_SPI_MISO_MARK, + R_SPI_RSPCK_MARK, R_SPI_SSL0_MARK, R_SPI_SSL1_MARK, + EVENT7_MARK, EVENT6_MARK, VBIOS_DI_MARK, VBIOS_DO_MARK, + VBIOS_CLK_MARK, VBIOS_CS_MARK, - /* PTW (mobule: LBSC) */ + /* PTW (mobule: LBSC, EVC, SCIF) */ A15_MARK, A14_MARK, A13_MARK, A12_MARK, A11_MARK, A10_MARK, A9_MARK, A8_MARK, + EVENT5_MARK, EVENT4_MARK, EVENT3_MARK, EVENT2_MARK, + EVENT1_MARK, EVENT0_MARK, CTS4_MARK, CTS2_MARK, - /* PTX (mobule: LBSC) */ + /* PTX (mobule: LBSC, SCIF, SIM) */ A7_MARK, A6_MARK, A5_MARK, A4_MARK, A3_MARK, A2_MARK, A1_MARK, A0_MARK, + RTS2_MARK, SIM_D_MARK, SIM_CLK_MARK, SIM_RST_MARK, /* PTY (mobule: LBSC) */ D7_MARK, D6_MARK, D5_MARK, D4_MARK, D3_MARK, D2_MARK, D1_MARK, D0_MARK, + + /* PTZ (mobule: eMMC, ONFI) */ + MMCDAT7_MARK, MMCDAT6_MARK, MMCDAT5_MARK, MMCDAT4_MARK, + MMCDAT3_MARK, MMCDAT2_MARK, MMCDAT1_MARK, MMCDAT0_MARK, + ON_DQ7_MARK, ON_DQ6_MARK, ON_DQ5_MARK, ON_DQ4_MARK, + ON_DQ3_MARK, ON_DQ2_MARK, ON_DQ1_MARK, ON_DQ0_MARK, + PINMUX_MARK_END, }; @@ -473,6 +567,8 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT), /* PTE GPIO */ + PINMUX_DATA(PTE7_DATA, PTE7_IN, PTE7_OUT), + PINMUX_DATA(PTE6_DATA, PTE6_IN, PTE6_OUT), PINMUX_DATA(PTE5_DATA, PTE5_IN, PTE5_OUT), PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT), PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT), @@ -521,7 +617,6 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PTI0_DATA, PTI0_IN, PTI0_OUT), /* PTJ GPIO */ - PINMUX_DATA(PTJ7_DATA, PTJ7_IN, PTJ7_OUT), PINMUX_DATA(PTJ6_DATA, PTJ6_IN, PTJ6_OUT), PINMUX_DATA(PTJ5_DATA, PTJ5_IN, PTJ5_OUT), PINMUX_DATA(PTJ4_DATA, PTJ4_IN, PTJ4_OUT), @@ -541,7 +636,6 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PTK0_DATA, PTK0_IN, PTK0_OUT), /* PTL GPIO */ - PINMUX_DATA(PTL7_DATA, PTL7_IN, PTL7_OUT), PINMUX_DATA(PTL6_DATA, PTL6_IN, PTL6_OUT), PINMUX_DATA(PTL5_DATA, PTL5_IN, PTL5_OUT), PINMUX_DATA(PTL4_DATA, PTL4_IN, PTL4_OUT), @@ -560,7 +654,6 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PTM0_DATA, PTM0_IN, PTM0_OUT), /* PTN GPIO */ - PINMUX_DATA(PTN7_DATA, PTN7_IN, PTN7_OUT), PINMUX_DATA(PTN6_DATA, PTN6_IN, PTN6_OUT), PINMUX_DATA(PTN5_DATA, PTN5_IN, PTN5_OUT), PINMUX_DATA(PTN4_DATA, PTN4_IN, PTN4_OUT), @@ -609,6 +702,8 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT), /* PTT GPIO */ + PINMUX_DATA(PTT7_DATA, PTT7_IN, PTT7_OUT), + PINMUX_DATA(PTT6_DATA, PTT6_IN, PTT6_OUT), PINMUX_DATA(PTT5_DATA, PTT5_IN, PTT5_OUT), PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT), PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT), @@ -677,186 +772,204 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PTZ0_DATA, PTZ0_IN, PTZ0_OUT), /* PTA FN */ - PINMUX_DATA(BS_MARK, PS0_15_FN1, PTA7_FN), - PINMUX_DATA(LGPIO7_MARK, PS0_15_FN3, PTA7_FN), - PINMUX_DATA(RDWR_MARK, PS0_14_FN1, PTA6_FN), - PINMUX_DATA(LGPIO6_MARK, PS0_14_FN3, PTA6_FN), - PINMUX_DATA(WE1_MARK, PS0_13_FN1, PTA5_FN), - PINMUX_DATA(LGPIO5_MARK, PS0_13_FN3, PTA5_FN), - PINMUX_DATA(RDY_MARK, PS0_12_FN1, PTA4_FN), - PINMUX_DATA(LGPIO4_MARK, PS0_12_FN3, PTA4_FN), - PINMUX_DATA(LGPIO3_MARK, PTA3_FN), - PINMUX_DATA(LGPIO2_MARK, PTA2_FN), - PINMUX_DATA(LGPIO1_MARK, PTA1_FN), - PINMUX_DATA(LGPIO0_MARK, PTA0_FN), + PINMUX_DATA(BS_MARK, PTA7_FN), + PINMUX_DATA(RDWR_MARK, PTA6_FN), + PINMUX_DATA(WE1_MARK, PTA5_FN), + PINMUX_DATA(RDY_MARK, PTA4_FN), + PINMUX_DATA(ET0_MDC_MARK, PTA3_FN), + PINMUX_DATA(ET0_MDIO_MARK, PTA2_FN), + PINMUX_DATA(ET1_MDC_MARK, PTA1_FN), + PINMUX_DATA(ET1_MDIO_MARK, PTA0_FN), /* PTB FN */ - PINMUX_DATA(D15_MARK, PS0_7_FN1, PTB7_FN), - PINMUX_DATA(ET0_MDC_MARK, PS0_7_FN2, PTB7_FN), - PINMUX_DATA(D14_MARK, PS0_6_FN1, PTB6_FN), - PINMUX_DATA(ET0_MDIO_MARK, PS0_6_FN2, PTB6_FN), - PINMUX_DATA(D13_MARK, PS0_5_FN1, PTB5_FN), - PINMUX_DATA(ET1_MDC_MARK, PS0_5_FN2, PTB5_FN), - PINMUX_DATA(D12_MARK, PS0_4_FN1, PTB4_FN), - PINMUX_DATA(ET1_MDIO_MARK, PS0_4_FN2, PTB4_FN), - PINMUX_DATA(D11_MARK, PS0_3_FN1, PTB3_FN), - PINMUX_DATA(SIM_D_MARK, PS0_3_FN2, PTB3_FN), - PINMUX_DATA(D10_MARK, PS0_2_FN1, PTB2_FN), - PINMUX_DATA(SIM_CLK_MARK, PS0_2_FN2, PTB2_FN), - PINMUX_DATA(D9_MARK, PS0_1_FN1, PTB1_FN), - PINMUX_DATA(SIM_RST_MARK, PS0_1_FN2, PTB1_FN), - PINMUX_DATA(D8_MARK, PTB0_FN), + PINMUX_DATA(IRQ15_MARK, PS0_15_FN1, PTB7_FN), + PINMUX_DATA(ON_NRE_MARK, PS0_15_FN2, PTB7_FN), + PINMUX_DATA(IRQ14_MARK, PS0_14_FN1, PTB6_FN), + PINMUX_DATA(ON_NWE_MARK, PS0_14_FN2, PTB6_FN), + PINMUX_DATA(IRQ13_MARK, PS0_13_FN1, PTB5_FN), + PINMUX_DATA(ON_NWP_MARK, PS0_13_FN2, PTB5_FN), + PINMUX_DATA(IRQ12_MARK, PS0_12_FN1, PTB4_FN), + PINMUX_DATA(ON_NCE0_MARK, PS0_12_FN2, PTB4_FN), + PINMUX_DATA(IRQ11_MARK, PS0_11_FN1, PTB3_FN), + PINMUX_DATA(ON_R_B0_MARK, PS0_11_FN2, PTB3_FN), + PINMUX_DATA(IRQ10_MARK, PS0_10_FN1, PTB2_FN), + PINMUX_DATA(ON_ALE_MARK, PS0_10_FN2, PTB2_FN), + PINMUX_DATA(IRQ9_MARK, PS0_9_FN1, PTB1_FN), + PINMUX_DATA(ON_CLE_MARK, PS0_9_FN2, PTB1_FN), + PINMUX_DATA(IRQ8_MARK, PS0_8_FN1, PTB0_FN), + PINMUX_DATA(TCLK_MARK, PS0_8_FN2, PTB0_FN), /* PTC FN */ - PINMUX_DATA(SD_WP_MARK, PTC7_FN), - PINMUX_DATA(SD_CD_MARK, PTC6_FN), - PINMUX_DATA(SD_CLK_MARK, PTC5_FN), - PINMUX_DATA(SD_CMD_MARK, PTC4_FN), - PINMUX_DATA(SD_D3_MARK, PTC3_FN), - PINMUX_DATA(SD_D2_MARK, PTC2_FN), - PINMUX_DATA(SD_D1_MARK, PTC1_FN), - PINMUX_DATA(SD_D0_MARK, PTC0_FN), + PINMUX_DATA(IRQ7_MARK, PS0_7_FN1, PTC7_FN), + PINMUX_DATA(PWMU0_MARK, PS0_7_FN2, PTC7_FN), + PINMUX_DATA(IRQ6_MARK, PS0_6_FN1, PTC6_FN), + PINMUX_DATA(PWMU1_MARK, PS0_6_FN2, PTC6_FN), + PINMUX_DATA(IRQ5_MARK, PS0_5_FN1, PTC5_FN), + PINMUX_DATA(PWMU2_MARK, PS0_5_FN2, PTC5_FN), + PINMUX_DATA(IRQ4_MARK, PS0_4_FN1, PTC5_FN), + PINMUX_DATA(PWMU3_MARK, PS0_4_FN2, PTC4_FN), + PINMUX_DATA(IRQ3_MARK, PS0_3_FN1, PTC3_FN), + PINMUX_DATA(PWMU4_MARK, PS0_3_FN2, PTC3_FN), + PINMUX_DATA(IRQ2_MARK, PS0_2_FN1, PTC2_FN), + PINMUX_DATA(PWMU5_MARK, PS0_2_FN2, PTC2_FN), + PINMUX_DATA(IRQ1_MARK, PTC1_FN), + PINMUX_DATA(IRQ0_MARK, PTC0_FN), /* PTD FN */ - PINMUX_DATA(IRQ7_MARK, PS1_7_FN1, PTD7_FN), - PINMUX_DATA(ADTRG1_MARK, PS1_7_FN3, PTD7_FN), - PINMUX_DATA(IRQ6_MARK, PS1_6_FN1, PTD6_FN), - PINMUX_DATA(ADTRG0_MARK, PS1_6_FN3, PTD6_FN), - PINMUX_DATA(IRQ5_MARK, PTD5_FN), - PINMUX_DATA(IRQ4_MARK, PTD4_FN), - PINMUX_DATA(IRQ3_MARK, PTD3_FN), - PINMUX_DATA(IRQ2_MARK, PTD2_FN), - PINMUX_DATA(IRQ1_MARK, PTD1_FN), - PINMUX_DATA(IRQ0_MARK, PTD0_FN), + PINMUX_DATA(SP0_MOSI_MARK, PTD7_FN), + PINMUX_DATA(SP0_MISO_MARK, PTD6_FN), + PINMUX_DATA(SP0_SCK_MARK, PTD5_FN), + PINMUX_DATA(SP0_SCK_FB_MARK, PTD4_FN), + PINMUX_DATA(SP0_SS0_MARK, PTD3_FN), + PINMUX_DATA(SP0_SS1_MARK, PS1_10_FN1, PTD2_FN), + PINMUX_DATA(DREQ0_MARK, PS1_10_FN2, PTD2_FN), + PINMUX_DATA(SP0_SS2_MARK, PS1_9_FN1, PTD1_FN), + PINMUX_DATA(DACK0_MARK, PS1_9_FN2, PTD1_FN), + PINMUX_DATA(SP0_SS3_MARK, PS1_8_FN1, PTD0_FN), + PINMUX_DATA(TEND0_MARK, PS1_8_FN2, PTD0_FN), /* PTE FN */ - PINMUX_DATA(ET0_CRS_DV_MARK, PTE7_FN), - PINMUX_DATA(ET0_TXD1_MARK, PTE6_FN), - PINMUX_DATA(ET0_TXD0_MARK, PTE5_FN), - PINMUX_DATA(ET0_TX_EN_MARK, PTE4_FN), - PINMUX_DATA(ET0_REF_CLK_MARK, PTE3_FN), - PINMUX_DATA(ET0_RXD1_MARK, PTE2_FN), - PINMUX_DATA(ET0_RXD0_MARK, PTE1_FN), - PINMUX_DATA(ET0_RX_ER_MARK, PTE0_FN), + PINMUX_DATA(RMII0_CRS_DV_MARK, PTE7_FN), + PINMUX_DATA(RMII0_TXD1_MARK, PTE6_FN), + PINMUX_DATA(RMII0_TXD0_MARK, PTE5_FN), + PINMUX_DATA(RMII0_TXEN_MARK, PTE4_FN), + PINMUX_DATA(RMII0_REFCLK_MARK, PTE3_FN), + PINMUX_DATA(RMII0_RXD1_MARK, PTE2_FN), + PINMUX_DATA(RMII0_RXD0_MARK, PTE1_FN), + PINMUX_DATA(RMII0_RX_ER_MARK, PTE0_FN), /* PTF FN */ - PINMUX_DATA(ET1_CRS_DV_MARK, PTF7_FN), - PINMUX_DATA(ET1_TXD1_MARK, PTF6_FN), - PINMUX_DATA(ET1_TXD0_MARK, PTF5_FN), - PINMUX_DATA(ET1_TX_EN_MARK, PTF4_FN), - PINMUX_DATA(ET1_REF_CLK_MARK, PTF3_FN), - PINMUX_DATA(ET1_RXD1_MARK, PTF2_FN), - PINMUX_DATA(ET1_RXD0_MARK, PTF1_FN), - PINMUX_DATA(ET1_RX_ER_MARK, PTF0_FN), + PINMUX_DATA(RMII1_CRS_DV_MARK, PTF7_FN), + PINMUX_DATA(RMII1_TXD1_MARK, PTF6_FN), + PINMUX_DATA(RMII1_TXD0_MARK, PTF5_FN), + PINMUX_DATA(RMII1_TXEN_MARK, PTF4_FN), + PINMUX_DATA(RMII1_REFCLK_MARK, PTF3_FN), + PINMUX_DATA(RMII1_RXD1_MARK, PS1_2_FN1, PTF2_FN), + PINMUX_DATA(RAC_RI_MARK, PS1_2_FN2, PTF2_FN), + PINMUX_DATA(RMII1_RXD0_MARK, PTF1_FN), + PINMUX_DATA(RMII1_RX_ER_MARK, PTF0_FN), /* PTG FN */ - PINMUX_DATA(PWX0_MARK, PTG7_FN), - PINMUX_DATA(PWX1_MARK, PTG6_FN), - PINMUX_DATA(STATUS0_MARK, PS2_13_FN1, PTG5_FN), - PINMUX_DATA(PWX2_MARK, PS2_13_FN3, PTG5_FN), - PINMUX_DATA(STATUS1_MARK, PS2_12_FN1, PTG4_FN), - PINMUX_DATA(PWX3_MARK, PS2_12_FN3, PTG4_FN), + PINMUX_DATA(BOOTFMS_MARK, PTG7_FN), + PINMUX_DATA(BOOTWP_MARK, PTG6_FN), + PINMUX_DATA(A25_MARK, PS2_13_FN1, PTG5_FN), + PINMUX_DATA(MMCCLK_MARK, PS2_13_FN2, PTG5_FN), + PINMUX_DATA(A24_MARK, PS2_12_FN1, PTG4_FN), + PINMUX_DATA(MMCCMD_MARK, PS2_12_FN2, PTG4_FN), PINMUX_DATA(SERIRQ_MARK, PTG3_FN), - PINMUX_DATA(CLKRUN_MARK, PTG2_FN), + PINMUX_DATA(WDTOVF_MARK, PTG2_FN), PINMUX_DATA(LPCPD_MARK, PTG1_FN), PINMUX_DATA(LDRQ_MARK, PTG0_FN), /* PTH FN */ - PINMUX_DATA(SP1_MOSI_MARK, PTH7_FN), - PINMUX_DATA(SP1_MISO_MARK, PTH6_FN), - PINMUX_DATA(SP1_SCK_MARK, PTH5_FN), - PINMUX_DATA(SP1_SCK_FB_MARK, PTH4_FN), + PINMUX_DATA(SP1_MOSI_MARK, PS2_7_FN1, PTH7_FN), + PINMUX_DATA(TEND1_MARK, PS2_7_FN2, PTH7_FN), + PINMUX_DATA(SP1_MISO_MARK, PS2_6_FN1, PTH6_FN), + PINMUX_DATA(DREQ1_MARK, PS2_6_FN2, PTH6_FN), + PINMUX_DATA(SP1_SCK_MARK, PS2_5_FN1, PTH5_FN), + PINMUX_DATA(DACK1_MARK, PS2_5_FN2, PTH5_FN), + PINMUX_DATA(SP1_SCK_FB_MARK, PS2_4_FN1, PTH4_FN), + PINMUX_DATA(ADTRG1_MARK, PS2_4_FN2, PTH4_FN), PINMUX_DATA(SP1_SS0_MARK, PTH3_FN), - PINMUX_DATA(TCLK_MARK, PTH2_FN), - PINMUX_DATA(RXD4_MARK, PS2_1_FN1, PTH1_FN), - PINMUX_DATA(SP1_SS1_MARK, PS2_1_FN2, PTH1_FN), - PINMUX_DATA(TXD4_MARK, PS2_0_FN1, PTH0_FN), - PINMUX_DATA(SP0_SS1_MARK, PS2_0_FN2, PTH0_FN), + PINMUX_DATA(SP1_SS1_MARK, PS2_2_FN1, PTH2_FN), + PINMUX_DATA(ADTRG0_MARK, PS2_2_FN2, PTH2_FN), + PINMUX_DATA(WP_MARK, PTH1_FN), + PINMUX_DATA(FMS0_MARK, PTH0_FN), /* PTI FN */ - PINMUX_DATA(IRQ15_MARK, PTI7_FN), - PINMUX_DATA(IRQ14_MARK, PTI6_FN), - PINMUX_DATA(IRQ13_MARK, PTI5_FN), - PINMUX_DATA(IRQ12_MARK, PTI4_FN), - PINMUX_DATA(IRQ11_MARK, PTI3_FN), - PINMUX_DATA(IRQ10_MARK, PTI2_FN), - PINMUX_DATA(IRQ9_MARK, PTI1_FN), - PINMUX_DATA(IRQ8_MARK, PTI0_FN), + PINMUX_DATA(D15_MARK, PS3_15_FN1, PTI7_FN), + PINMUX_DATA(SD_WP_MARK, PS3_15_FN2, PTI7_FN), + PINMUX_DATA(D14_MARK, PS3_14_FN1, PTI6_FN), + PINMUX_DATA(SD_CD_MARK, PS3_14_FN2, PTI6_FN), + PINMUX_DATA(D13_MARK, PS3_13_FN1, PTI5_FN), + PINMUX_DATA(SD_CLK_MARK, PS3_13_FN2, PTI5_FN), + PINMUX_DATA(D12_MARK, PS3_12_FN1, PTI4_FN), + PINMUX_DATA(SD_CMD_MARK, PS3_12_FN2, PTI4_FN), + PINMUX_DATA(D11_MARK, PS3_11_FN1, PTI3_FN), + PINMUX_DATA(SD_D3_MARK, PS3_11_FN2, PTI3_FN), + PINMUX_DATA(D10_MARK, PS3_10_FN1, PTI2_FN), + PINMUX_DATA(SD_D2_MARK, PS3_10_FN2, PTI2_FN), + PINMUX_DATA(D9_MARK, PS3_9_FN1, PTI1_FN), + PINMUX_DATA(SD_D1_MARK, PS3_9_FN2, PTI1_FN), + PINMUX_DATA(D8_MARK, PS3_8_FN1, PTI0_FN), + PINMUX_DATA(SD_D0_MARK, PS3_8_FN2, PTI0_FN), /* PTJ FN */ - PINMUX_DATA(RXD3_MARK, PTJ7_FN), - PINMUX_DATA(TXD3_MARK, PTJ6_FN), - PINMUX_DATA(RXD2_MARK, PTJ5_FN), - PINMUX_DATA(TXD2_MARK, PTJ4_FN), - PINMUX_DATA(COM1_TXD_MARK, PTJ3_FN), - PINMUX_DATA(COM1_RXD_MARK, PTJ2_FN), - PINMUX_DATA(COM1_RTS_MARK, PTJ1_FN), - PINMUX_DATA(COM1_CTS_MARK, PTJ0_FN), + PINMUX_DATA(RTS3_MARK, PTJ6_FN), + PINMUX_DATA(CTS3_MARK, PTJ5_FN), + PINMUX_DATA(TXD3_MARK, PTJ4_FN), + PINMUX_DATA(RXD3_MARK, PTJ3_FN), + PINMUX_DATA(RTS4_MARK, PTJ2_FN), + PINMUX_DATA(RXD4_MARK, PTJ1_FN), + PINMUX_DATA(TXD4_MARK, PTJ0_FN), /* PTK FN */ - PINMUX_DATA(COM2_TXD_MARK, PTK7_FN), + PINMUX_DATA(COM2_TXD_MARK, PS3_7_FN1, PTK7_FN), + PINMUX_DATA(SCK2_MARK, PS3_7_FN2, PTK7_FN), PINMUX_DATA(COM2_RXD_MARK, PTK6_FN), PINMUX_DATA(COM2_RTS_MARK, PTK5_FN), PINMUX_DATA(COM2_CTS_MARK, PTK4_FN), PINMUX_DATA(COM2_DTR_MARK, PTK3_FN), - PINMUX_DATA(COM2_DSR_MARK, PTK2_FN), - PINMUX_DATA(COM2_DCD_MARK, PTK1_FN), - PINMUX_DATA(COM2_RI_MARK, PTK0_FN), + PINMUX_DATA(COM2_DSR_MARK, PS3_2_FN1, PTK2_FN), + PINMUX_DATA(SCK4_MARK, PS3_2_FN2, PTK2_FN), + PINMUX_DATA(COM2_DCD_MARK, PS3_1_FN1, PTK1_FN), + PINMUX_DATA(SCK3_MARK, PS3_1_FN2, PTK1_FN), + PINMUX_DATA(CLKOUT_MARK, PTK0_FN), /* PTL FN */ - PINMUX_DATA(RAC_TXD_MARK, PTL7_FN), - PINMUX_DATA(RAC_RXD_MARK, PTL6_FN), - PINMUX_DATA(RAC_RTS_MARK, PTL5_FN), - PINMUX_DATA(RAC_CTS_MARK, PTL4_FN), + PINMUX_DATA(RAC_RXD_MARK, PS4_14_FN1, PTL6_FN), + PINMUX_DATA(RXD2_MARK, PS4_14_FN2, PTL6_FN), + PINMUX_DATA(RAC_RTS_MARK, PS4_13_FN1, PTL5_FN), + PINMUX_DATA(CS5_MARK, PS4_13_FN2, PTL5_FN), + PINMUX_DATA(RAC_CTS_MARK, PS4_12_FN1, PTL4_FN), + PINMUX_DATA(CS6_MARK, PS4_12_FN2, PTL4_FN), PINMUX_DATA(RAC_DTR_MARK, PTL3_FN), - PINMUX_DATA(RAC_DSR_MARK, PTL2_FN), - PINMUX_DATA(RAC_DCD_MARK, PTL1_FN), - PINMUX_DATA(RAC_RI_MARK, PTL0_FN), + PINMUX_DATA(RAC_DSR_MARK, PS4_10_FN1, PTL2_FN), + PINMUX_DATA(AUDSYNC_MARK, PS4_10_FN2, PTL2_FN), + PINMUX_DATA(RAC_DCD_MARK, PS4_9_FN1, PTL1_FN), + PINMUX_DATA(AUDCK_MARK, PS4_9_FN2, PTL1_FN), + PINMUX_DATA(RAC_TXD_MARK, PS4_8_FN1, PTL0_FN), + PINMUX_DATA(TXD2_MARK, PS4_8_FN1, PTL0_FN), /* PTM FN */ - PINMUX_DATA(WP_MARK, PTM6_FN), - PINMUX_DATA(FMS0_MARK, PTM5_FN), - PINMUX_DATA(FMS1_MARK, PTM4_FN), + PINMUX_DATA(CS4_MARK, PTM7_FN), + PINMUX_DATA(RD_MARK, PTM6_FN), + PINMUX_DATA(WE0_MARK, PTM7_FN), + PINMUX_DATA(CS0_MARK, PTM4_FN), PINMUX_DATA(SDA6_MARK, PTM3_FN), PINMUX_DATA(SCL6_MARK, PTM2_FN), PINMUX_DATA(SDA7_MARK, PTM1_FN), PINMUX_DATA(SCL7_MARK, PTM0_FN), /* PTN FN */ - PINMUX_DATA(SCK2_MARK, PS4_15_FN1, PTN7_FN), - PINMUX_DATA(EVENT7_MARK, PS4_15_FN2, PTN7_FN), - PINMUX_DATA(RTS4_MARK, PS4_14_FN1, PTN6_FN), - PINMUX_DATA(EVENT6_MARK, PS4_14_FN2, PTN6_FN), - PINMUX_DATA(RTS3_MARK, PS4_13_FN1, PTN5_FN), - PINMUX_DATA(EVENT5_MARK, PS4_13_FN2, PTN5_FN), - PINMUX_DATA(RTS2_MARK, PS4_12_FN1, PTN4_FN), - PINMUX_DATA(EVENT4_MARK, PS4_12_FN2, PTN4_FN), - PINMUX_DATA(CTS4_MARK, PS4_11_FN1, PTN3_FN), - PINMUX_DATA(EVENT3_MARK, PS4_11_FN2, PTN3_FN), - PINMUX_DATA(CTS3_MARK, PS4_10_FN1, PTN2_FN), - PINMUX_DATA(EVENT2_MARK, PS4_10_FN2, PTN2_FN), - PINMUX_DATA(CTS2_MARK, PS4_9_FN1, PTN1_FN), - PINMUX_DATA(EVENT1_MARK, PS4_9_FN2, PTN1_FN), - PINMUX_DATA(EVENT0_MARK, PTN0_FN), + PINMUX_DATA(VBUS_EN_MARK, PTN6_FN), + PINMUX_DATA(VBUS_OC_MARK, PTN5_FN), + PINMUX_DATA(JMCTCK_MARK, PS4_4_FN1, PTN4_FN), + PINMUX_DATA(SGPIO1_CLK_MARK, PS4_4_FN2, PTN4_FN), + PINMUX_DATA(JMCTMS_MARK, PS4_3_FN1, PTN5_FN), + PINMUX_DATA(SGPIO1_LOAD_MARK, PS4_3_FN2, PTN5_FN), + PINMUX_DATA(JMCTDO_MARK, PS4_2_FN1, PTN2_FN), + PINMUX_DATA(SGPIO1_DO_MARK, PS4_2_FN2, PTN2_FN), + PINMUX_DATA(JMCTDI_MARK, PS4_1_FN1, PTN1_FN), + PINMUX_DATA(SGPIO1_DI_MARK, PS4_1_FN2, PTN1_FN), + PINMUX_DATA(JMCTRST_MARK, PS4_0_FN1, PTN0_FN), + PINMUX_DATA(SUB_CLKIN_MARK, PS4_0_FN2, PTN0_FN), /* PTO FN */ PINMUX_DATA(SGPIO0_CLK_MARK, PTO7_FN), PINMUX_DATA(SGPIO0_LOAD_MARK, PTO6_FN), PINMUX_DATA(SGPIO0_DI_MARK, PTO5_FN), PINMUX_DATA(SGPIO0_DO_MARK, PTO4_FN), - PINMUX_DATA(SGPIO1_CLK_MARK, PTO3_FN), - PINMUX_DATA(SGPIO1_LOAD_MARK, PTO2_FN), - PINMUX_DATA(SGPIO1_DI_MARK, PTO1_FN), - PINMUX_DATA(SGPIO1_DO_MARK, PTO0_FN), + PINMUX_DATA(SGPIO2_CLK_MARK, PS5_11_FN1, PTO3_FN), + PINMUX_DATA(COM1_TXD_MARK, PS5_11_FN2, PTO3_FN), + PINMUX_DATA(SGPIO2_LOAD_MARK, PS5_10_FN1, PTO2_FN), + PINMUX_DATA(COM1_RXD_MARK, PS5_10_FN2, PTO2_FN), + PINMUX_DATA(SGPIO2_DI_MARK, PS5_9_FN1, PTO1_FN), + PINMUX_DATA(COM1_RTS_MARK, PS5_9_FN2, PTO1_FN), + PINMUX_DATA(SGPIO2_DO_MARK, PS5_8_FN1, PTO0_FN), + PINMUX_DATA(COM1_CTS_MARK, PS5_8_FN2, PTO0_FN), /* PTP FN */ - PINMUX_DATA(JMCTCK_MARK, PTP6_FN), - PINMUX_DATA(JMCTMS_MARK, PTP5_FN), - PINMUX_DATA(JMCTDO_MARK, PTP4_FN), - PINMUX_DATA(JMCTDI_MARK, PTP3_FN), - PINMUX_DATA(JMCRST_MARK, PTP2_FN), - PINMUX_DATA(SCK4_MARK, PTP1_FN), - PINMUX_DATA(SCK3_MARK, PTP0_FN), /* PTQ FN */ PINMUX_DATA(LAD3_MARK, PTQ6_FN), @@ -864,8 +977,8 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(LAD1_MARK, PTQ4_FN), PINMUX_DATA(LAD0_MARK, PTQ3_FN), PINMUX_DATA(LFRAME_MARK, PTQ2_FN), - PINMUX_DATA(SCK4_MARK, PTQ1_FN), - PINMUX_DATA(SCK3_MARK, PTQ0_FN), + PINMUX_DATA(LRESET_MARK, PTQ1_FN), + PINMUX_DATA(LCLK_MARK, PTQ0_FN), /* PTR FN */ PINMUX_DATA(SDA8_MARK, PTR7_FN), /* DDC3? */ @@ -888,58 +1001,84 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(SCL3_MARK, PTS0_FN), /* PTT FN */ - PINMUX_DATA(AUDSYNC_MARK, PTS5_FN), - PINMUX_DATA(AUDCK_MARK, PTS4_FN), - PINMUX_DATA(AUDATA3_MARK, PS4_3_FN1, PTS3_FN), - PINMUX_DATA(PWX7_MARK, PS4_3_FN2, PTS3_FN), - PINMUX_DATA(AUDATA2_MARK, PS4_2_FN1, PTS2_FN), - PINMUX_DATA(PWX6_MARK, PS4_2_FN2, PTS2_FN), - PINMUX_DATA(AUDATA1_MARK, PS4_1_FN1, PTS1_FN), - PINMUX_DATA(PWX5_MARK, PS4_1_FN2, PTS1_FN), - PINMUX_DATA(AUDATA0_MARK, PS4_0_FN1, PTS0_FN), - PINMUX_DATA(PWX4_MARK, PS4_0_FN2, PTS0_FN), + PINMUX_DATA(PWMX7_MARK, PS5_7_FN1, PTT7_FN), + PINMUX_DATA(AUDATA3_MARK, PS5_7_FN2, PTT7_FN), + PINMUX_DATA(PWMX6_MARK, PS5_6_FN1, PTT6_FN), + PINMUX_DATA(AUDATA2_MARK, PS5_6_FN2, PTT6_FN), + PINMUX_DATA(PWMX5_MARK, PS5_5_FN1, PTT5_FN), + PINMUX_DATA(AUDATA1_MARK, PS5_5_FN2, PTT5_FN), + PINMUX_DATA(PWMX4_MARK, PS5_4_FN1, PTT4_FN), + PINMUX_DATA(AUDATA0_MARK, PS5_4_FN2, PTT4_FN), + PINMUX_DATA(PWMX3_MARK, PS5_3_FN1, PTT3_FN), + PINMUX_DATA(STATUS1_MARK, PS5_3_FN2, PTT3_FN), + PINMUX_DATA(PWMX2_MARK, PS5_2_FN1, PTT2_FN), + PINMUX_DATA(STATUS0_MARK, PS5_2_FN2, PTT2_FN), + PINMUX_DATA(PWMX1_MARK, PTT1_FN), + PINMUX_DATA(PWMX0_MARK, PTT0_FN), /* PTU FN */ - PINMUX_DATA(CS6_MARK, PTU7_FN), - PINMUX_DATA(CS5_MARK, PTU6_FN), - PINMUX_DATA(CS4_MARK, PTU5_FN), - PINMUX_DATA(CS0_MARK, PTU4_FN), - PINMUX_DATA(RD_MARK, PTU3_FN), - PINMUX_DATA(WE0_MARK, PTU2_FN), - PINMUX_DATA(A25_MARK, PS5_9_FN1, PTU1_FN), - PINMUX_DATA(DREQ0_MARK, PS5_9_FN2, PTU1_FN), - PINMUX_DATA(A24_MARK, PS5_8_FN1, PTU0_FN), - PINMUX_DATA(DACK0_MARK, PS5_8_FN2, PTU0_FN), + PINMUX_DATA(LGPIO7_MARK, PS6_15_FN1, PTU7_FN), + PINMUX_DATA(APMONCTL_O_MARK, PS6_15_FN2, PTU7_FN), + PINMUX_DATA(LGPIO6_MARK, PS6_14_FN1, PTU6_FN), + PINMUX_DATA(APMPWBTOUT_O_MARK, PS6_14_FN2, PTU6_FN), + PINMUX_DATA(LGPIO5_MARK, PS6_13_FN1, PTU5_FN), + PINMUX_DATA(APMSCI_O_MARK, PS6_13_FN2, PTU5_FN), + PINMUX_DATA(LGPIO4_MARK, PS6_12_FN1, PTU4_FN), + PINMUX_DATA(APMVDDON_MARK, PS6_12_FN2, PTU4_FN), + PINMUX_DATA(LGPIO3_MARK, PS6_11_FN1, PTU3_FN), + PINMUX_DATA(APMSLPBTN_MARK, PS6_11_FN2, PTU3_FN), + PINMUX_DATA(LGPIO2_MARK, PS6_10_FN1, PTU2_FN), + PINMUX_DATA(APMPWRBTN_MARK, PS6_10_FN2, PTU2_FN), + PINMUX_DATA(LGPIO1_MARK, PS6_9_FN1, PTU1_FN), + PINMUX_DATA(APMS5N_MARK, PS6_9_FN2, PTU1_FN), + PINMUX_DATA(LGPIO0_MARK, PS6_8_FN1, PTU0_FN), + PINMUX_DATA(APMS3N_MARK, PS6_8_FN2, PTU0_FN), /* PTV FN */ - PINMUX_DATA(A23_MARK, PS5_7_FN1, PTV7_FN), - PINMUX_DATA(TEND0_MARK, PS5_7_FN2, PTV7_FN), - PINMUX_DATA(A22_MARK, PS5_6_FN1, PTV6_FN), - PINMUX_DATA(DREQ1_MARK, PS5_6_FN2, PTV6_FN), - PINMUX_DATA(A21_MARK, PS5_5_FN1, PTV5_FN), - PINMUX_DATA(DACK1_MARK, PS5_5_FN2, PTV5_FN), - PINMUX_DATA(A20_MARK, PS5_4_FN1, PTV4_FN), - PINMUX_DATA(TEND1_MARK, PS5_4_FN2, PTV4_FN), - PINMUX_DATA(A19_MARK, PTV3_FN), - PINMUX_DATA(A18_MARK, PTV2_FN), - PINMUX_DATA(A17_MARK, PTV1_FN), - PINMUX_DATA(A16_MARK, PTV0_FN), + PINMUX_DATA(A23_MARK, PS6_7_FN1, PTV7_FN), + PINMUX_DATA(COM2_RI_MARK, PS6_7_FN2, PTV7_FN), + PINMUX_DATA(A22_MARK, PS6_6_FN1, PTV6_FN), + PINMUX_DATA(R_SPI_MOSI_MARK, PS6_6_FN2, PTV6_FN), + PINMUX_DATA(A21_MARK, PS6_5_FN1, PTV5_FN), + PINMUX_DATA(R_SPI_MISO_MARK, PS6_5_FN2, PTV5_FN), + PINMUX_DATA(A20_MARK, PS6_4_FN1, PTV4_FN), + PINMUX_DATA(R_SPI_RSPCK_MARK, PS6_4_FN2, PTV4_FN), + PINMUX_DATA(A19_MARK, PS6_3_FN1, PTV3_FN), + PINMUX_DATA(R_SPI_SSL0_MARK, PS6_3_FN2, PTV3_FN), + PINMUX_DATA(A18_MARK, PS6_2_FN1, PTV2_FN), + PINMUX_DATA(R_SPI_SSL1_MARK, PS6_2_FN2, PTV2_FN), + PINMUX_DATA(A17_MARK, PS6_1_FN1, PTV1_FN), + PINMUX_DATA(EVENT7_MARK, PS6_1_FN2, PTV1_FN), + PINMUX_DATA(A16_MARK, PS6_0_FN1, PTV0_FN), + PINMUX_DATA(EVENT6_MARK, PS6_0_FN1, PTV0_FN), /* PTW FN */ - PINMUX_DATA(A15_MARK, PTW7_FN), - PINMUX_DATA(A14_MARK, PTW6_FN), - PINMUX_DATA(A13_MARK, PTW5_FN), - PINMUX_DATA(A12_MARK, PTW4_FN), - PINMUX_DATA(A11_MARK, PTW3_FN), - PINMUX_DATA(A10_MARK, PTW2_FN), - PINMUX_DATA(A9_MARK, PTW1_FN), - PINMUX_DATA(A8_MARK, PTW0_FN), + PINMUX_DATA(A15_MARK, PS7_15_FN1, PTW7_FN), + PINMUX_DATA(EVENT5_MARK, PS7_15_FN2, PTW7_FN), + PINMUX_DATA(A14_MARK, PS7_14_FN1, PTW6_FN), + PINMUX_DATA(EVENT4_MARK, PS7_14_FN2, PTW6_FN), + PINMUX_DATA(A13_MARK, PS7_13_FN1, PTW5_FN), + PINMUX_DATA(EVENT3_MARK, PS7_13_FN2, PTW5_FN), + PINMUX_DATA(A12_MARK, PS7_12_FN1, PTW4_FN), + PINMUX_DATA(EVENT2_MARK, PS7_12_FN2, PTW4_FN), + PINMUX_DATA(A11_MARK, PS7_11_FN1, PTW3_FN), + PINMUX_DATA(EVENT1_MARK, PS7_11_FN2, PTW3_FN), + PINMUX_DATA(A10_MARK, PS7_10_FN1, PTW2_FN), + PINMUX_DATA(EVENT0_MARK, PS7_10_FN2, PTW2_FN), + PINMUX_DATA(A9_MARK, PS7_9_FN1, PTW1_FN), + PINMUX_DATA(CTS4_MARK, PS7_9_FN2, PTW1_FN), + PINMUX_DATA(A8_MARK, PS7_8_FN1, PTW0_FN), + PINMUX_DATA(CTS2_MARK, PS7_8_FN2, PTW0_FN), /* PTX FN */ - PINMUX_DATA(A7_MARK, PTX7_FN), - PINMUX_DATA(A6_MARK, PTX6_FN), - PINMUX_DATA(A5_MARK, PTX5_FN), - PINMUX_DATA(A4_MARK, PTX4_FN), + PINMUX_DATA(A7_MARK, PS7_7_FN1, PTX7_FN), + PINMUX_DATA(RTS2_MARK, PS7_7_FN2, PTX7_FN), + PINMUX_DATA(A6_MARK, PS7_6_FN1, PTX6_FN), + PINMUX_DATA(SIM_D_MARK, PS7_6_FN2, PTX6_FN), + PINMUX_DATA(A5_MARK, PS7_5_FN1, PTX5_FN), + PINMUX_DATA(SIM_CLK_MARK, PS7_5_FN2, PTX5_FN), + PINMUX_DATA(A4_MARK, PS7_4_FN1, PTX4_FN), + PINMUX_DATA(SIM_RST_MARK, PS7_4_FN2, PTX4_FN), PINMUX_DATA(A3_MARK, PTX3_FN), PINMUX_DATA(A2_MARK, PTX2_FN), PINMUX_DATA(A1_MARK, PTX1_FN), @@ -954,6 +1093,24 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(D2_MARK, PTY2_FN), PINMUX_DATA(D1_MARK, PTY1_FN), PINMUX_DATA(D0_MARK, PTY0_FN), + + /* PTZ FN */ + PINMUX_DATA(MMCDAT7_MARK, PS8_15_FN1, PTZ7_FN), + PINMUX_DATA(ON_DQ7_MARK, PS8_15_FN2, PTZ7_FN), + PINMUX_DATA(MMCDAT6_MARK, PS8_14_FN1, PTZ6_FN), + PINMUX_DATA(ON_DQ6_MARK, PS8_14_FN2, PTZ6_FN), + PINMUX_DATA(MMCDAT5_MARK, PS8_13_FN1, PTZ5_FN), + PINMUX_DATA(ON_DQ5_MARK, PS8_13_FN2, PTZ5_FN), + PINMUX_DATA(MMCDAT4_MARK, PS8_12_FN1, PTZ4_FN), + PINMUX_DATA(ON_DQ4_MARK, PS8_12_FN2, PTZ4_FN), + PINMUX_DATA(MMCDAT3_MARK, PS8_11_FN1, PTZ3_FN), + PINMUX_DATA(ON_DQ3_MARK, PS8_11_FN2, PTZ3_FN), + PINMUX_DATA(MMCDAT2_MARK, PS8_10_FN1, PTZ2_FN), + PINMUX_DATA(ON_DQ2_MARK, PS8_10_FN2, PTZ2_FN), + PINMUX_DATA(MMCDAT1_MARK, PS8_9_FN1, PTZ1_FN), + PINMUX_DATA(ON_DQ1_MARK, PS8_9_FN2, PTZ1_FN), + PINMUX_DATA(MMCDAT0_MARK, PS8_8_FN1, PTZ0_FN), + PINMUX_DATA(ON_DQ0_MARK, PS8_8_FN2, PTZ0_FN), }; static struct pinmux_gpio pinmux_gpios[] = { @@ -1048,7 +1205,6 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_PTI0, PTI0_DATA), /* PTJ */ - PINMUX_GPIO(GPIO_PTJ7, PTJ7_DATA), PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA), PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA), PINMUX_GPIO(GPIO_PTJ4, PTJ4_DATA), @@ -1068,7 +1224,6 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_PTK0, PTK0_DATA), /* PTL */ - PINMUX_GPIO(GPIO_PTL7, PTL7_DATA), PINMUX_GPIO(GPIO_PTL6, PTL6_DATA), PINMUX_GPIO(GPIO_PTL5, PTL5_DATA), PINMUX_GPIO(GPIO_PTL4, PTL4_DATA), @@ -1078,6 +1233,7 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_PTL0, PTL0_DATA), /* PTM */ + PINMUX_GPIO(GPIO_PTM7, PTM7_DATA), PINMUX_GPIO(GPIO_PTM6, PTM6_DATA), PINMUX_GPIO(GPIO_PTM5, PTM5_DATA), PINMUX_GPIO(GPIO_PTM4, PTM4_DATA), @@ -1087,7 +1243,6 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_PTM0, PTM0_DATA), /* PTN */ - PINMUX_GPIO(GPIO_PTN7, PTN7_DATA), PINMUX_GPIO(GPIO_PTN6, PTN6_DATA), PINMUX_GPIO(GPIO_PTN5, PTN5_DATA), PINMUX_GPIO(GPIO_PTN4, PTN4_DATA), @@ -1107,6 +1262,7 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_PTO0, PTO0_DATA), /* PTP */ + PINMUX_GPIO(GPIO_PTP7, PTP7_DATA), PINMUX_GPIO(GPIO_PTP6, PTP6_DATA), PINMUX_GPIO(GPIO_PTP5, PTP5_DATA), PINMUX_GPIO(GPIO_PTP4, PTP4_DATA), @@ -1145,6 +1301,8 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_PTS0, PTS0_DATA), /* PTT */ + PINMUX_GPIO(GPIO_PTT7, PTT7_DATA), + PINMUX_GPIO(GPIO_PTT6, PTT6_DATA), PINMUX_GPIO(GPIO_PTT5, PTT5_DATA), PINMUX_GPIO(GPIO_PTT4, PTT4_DATA), PINMUX_GPIO(GPIO_PTT3, PTT3_DATA), @@ -1212,54 +1370,35 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA), PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA), - /* PTA (mobule: LBSC, CPG, LPC) */ + /* PTA (mobule: LBSC, RGMII) */ PINMUX_GPIO(GPIO_FN_BS, BS_MARK), PINMUX_GPIO(GPIO_FN_RDWR, RDWR_MARK), PINMUX_GPIO(GPIO_FN_WE1, WE1_MARK), PINMUX_GPIO(GPIO_FN_RDY, RDY_MARK), - PINMUX_GPIO(GPIO_FN_MD10, MD10_MARK), - PINMUX_GPIO(GPIO_FN_MD9, MD9_MARK), - PINMUX_GPIO(GPIO_FN_MD8, MD8_MARK), - PINMUX_GPIO(GPIO_FN_LGPIO7, LGPIO7_MARK), - PINMUX_GPIO(GPIO_FN_LGPIO6, LGPIO6_MARK), - PINMUX_GPIO(GPIO_FN_LGPIO5, LGPIO5_MARK), - PINMUX_GPIO(GPIO_FN_LGPIO4, LGPIO4_MARK), - PINMUX_GPIO(GPIO_FN_LGPIO3, LGPIO3_MARK), - PINMUX_GPIO(GPIO_FN_LGPIO2, LGPIO2_MARK), - PINMUX_GPIO(GPIO_FN_LGPIO1, LGPIO1_MARK), - PINMUX_GPIO(GPIO_FN_LGPIO0, LGPIO0_MARK), - - /* PTB (mobule: LBSC, EtherC, SIM, LPC) */ - PINMUX_GPIO(GPIO_FN_D15, D15_MARK), - PINMUX_GPIO(GPIO_FN_D14, D14_MARK), - PINMUX_GPIO(GPIO_FN_D13, D13_MARK), - PINMUX_GPIO(GPIO_FN_D12, D12_MARK), - PINMUX_GPIO(GPIO_FN_D11, D11_MARK), - PINMUX_GPIO(GPIO_FN_D10, D10_MARK), - PINMUX_GPIO(GPIO_FN_D9, D9_MARK), - PINMUX_GPIO(GPIO_FN_D8, D8_MARK), PINMUX_GPIO(GPIO_FN_ET0_MDC, ET0_MDC_MARK), - PINMUX_GPIO(GPIO_FN_ET0_MDIO, ET0_MDIO_MARK), + PINMUX_GPIO(GPIO_FN_ET0_MDIO, ET0_MDC_MARK), PINMUX_GPIO(GPIO_FN_ET1_MDC, ET1_MDC_MARK), - PINMUX_GPIO(GPIO_FN_ET1_MDIO, ET1_MDIO_MARK), - PINMUX_GPIO(GPIO_FN_WPSZ1, WPSZ1_MARK), - PINMUX_GPIO(GPIO_FN_WPSZ0, WPSZ0_MARK), - PINMUX_GPIO(GPIO_FN_FWID, FWID_MARK), - PINMUX_GPIO(GPIO_FN_FLSHSZ, FLSHSZ_MARK), - PINMUX_GPIO(GPIO_FN_LPC_SPIEN, LPC_SPIEN_MARK), - PINMUX_GPIO(GPIO_FN_BASEL, BASEL_MARK), - - /* PTC (mobule: SD) */ - PINMUX_GPIO(GPIO_FN_SD_WP, SD_WP_MARK), - PINMUX_GPIO(GPIO_FN_SD_CD, SD_CD_MARK), - PINMUX_GPIO(GPIO_FN_SD_CLK, SD_CLK_MARK), - PINMUX_GPIO(GPIO_FN_SD_CMD, SD_CMD_MARK), - PINMUX_GPIO(GPIO_FN_SD_D3, SD_D3_MARK), - PINMUX_GPIO(GPIO_FN_SD_D2, SD_D2_MARK), - PINMUX_GPIO(GPIO_FN_SD_D1, SD_D1_MARK), - PINMUX_GPIO(GPIO_FN_SD_D0, SD_D0_MARK), + PINMUX_GPIO(GPIO_FN_ET1_MDIO, ET1_MDC_MARK), - /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */ + /* PTB (mobule: INTC, ONFI, TMU) */ + PINMUX_GPIO(GPIO_FN_IRQ15, IRQ15_MARK), + PINMUX_GPIO(GPIO_FN_IRQ14, IRQ14_MARK), + PINMUX_GPIO(GPIO_FN_IRQ13, IRQ13_MARK), + PINMUX_GPIO(GPIO_FN_IRQ12, IRQ12_MARK), + PINMUX_GPIO(GPIO_FN_IRQ11, IRQ11_MARK), + PINMUX_GPIO(GPIO_FN_IRQ10, IRQ10_MARK), + PINMUX_GPIO(GPIO_FN_IRQ9, IRQ9_MARK), + PINMUX_GPIO(GPIO_FN_IRQ8, IRQ8_MARK), + PINMUX_GPIO(GPIO_FN_ON_NRE, ON_NRE_MARK), + PINMUX_GPIO(GPIO_FN_ON_NWE, ON_NWE_MARK), + PINMUX_GPIO(GPIO_FN_ON_NWP, ON_NWP_MARK), + PINMUX_GPIO(GPIO_FN_ON_NCE0, ON_NCE0_MARK), + PINMUX_GPIO(GPIO_FN_ON_R_B0, ON_R_B0_MARK), + PINMUX_GPIO(GPIO_FN_ON_ALE, ON_ALE_MARK), + PINMUX_GPIO(GPIO_FN_ON_CLE, ON_CLE_MARK), + PINMUX_GPIO(GPIO_FN_TCLK, TCLK_MARK), + + /* PTC (mobule: IRQ, PWMU) */ PINMUX_GPIO(GPIO_FN_IRQ7, IRQ7_MARK), PINMUX_GPIO(GPIO_FN_IRQ6, IRQ6_MARK), PINMUX_GPIO(GPIO_FN_IRQ5, IRQ5_MARK), @@ -1268,80 +1407,102 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_FN_IRQ2, IRQ2_MARK), PINMUX_GPIO(GPIO_FN_IRQ1, IRQ1_MARK), PINMUX_GPIO(GPIO_FN_IRQ0, IRQ0_MARK), - PINMUX_GPIO(GPIO_FN_MD6, MD6_MARK), - PINMUX_GPIO(GPIO_FN_MD5, MD5_MARK), - PINMUX_GPIO(GPIO_FN_MD3, MD3_MARK), - PINMUX_GPIO(GPIO_FN_MD2, MD2_MARK), - PINMUX_GPIO(GPIO_FN_MD1, MD1_MARK), - PINMUX_GPIO(GPIO_FN_MD0, MD0_MARK), - PINMUX_GPIO(GPIO_FN_ADTRG1, ADTRG1_MARK), - PINMUX_GPIO(GPIO_FN_ADTRG0, ADTRG0_MARK), + PINMUX_GPIO(GPIO_FN_PWMU0, PWMU0_MARK), + PINMUX_GPIO(GPIO_FN_PWMU1, PWMU1_MARK), + PINMUX_GPIO(GPIO_FN_PWMU2, PWMU2_MARK), + PINMUX_GPIO(GPIO_FN_PWMU3, PWMU3_MARK), + PINMUX_GPIO(GPIO_FN_PWMU4, PWMU4_MARK), + PINMUX_GPIO(GPIO_FN_PWMU5, PWMU5_MARK), + + /* PTD (mobule: SPI0, DMAC) */ + PINMUX_GPIO(GPIO_FN_SP0_MOSI, SP0_MOSI_MARK), + PINMUX_GPIO(GPIO_FN_SP0_MISO, SP0_MISO_MARK), + PINMUX_GPIO(GPIO_FN_SP0_SCK, SP0_SCK_MARK), + PINMUX_GPIO(GPIO_FN_SP0_SCK_FB, SP0_SCK_FB_MARK), + PINMUX_GPIO(GPIO_FN_SP0_SS0, SP0_SS0_MARK), + PINMUX_GPIO(GPIO_FN_SP0_SS1, SP0_SS1_MARK), + PINMUX_GPIO(GPIO_FN_SP0_SS2, SP0_SS2_MARK), + PINMUX_GPIO(GPIO_FN_SP0_SS3, SP0_SS3_MARK), + PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK), + PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK), + PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK), - /* PTE (mobule: EtherC) */ - PINMUX_GPIO(GPIO_FN_ET0_CRS_DV, ET0_CRS_DV_MARK), - PINMUX_GPIO(GPIO_FN_ET0_TXD1, ET0_TXD1_MARK), - PINMUX_GPIO(GPIO_FN_ET0_TXD0, ET0_TXD0_MARK), - PINMUX_GPIO(GPIO_FN_ET0_TX_EN, ET0_TX_EN_MARK), - PINMUX_GPIO(GPIO_FN_ET0_REF_CLK, ET0_REF_CLK_MARK), - PINMUX_GPIO(GPIO_FN_ET0_RXD1, ET0_RXD1_MARK), - PINMUX_GPIO(GPIO_FN_ET0_RXD0, ET0_RXD0_MARK), - PINMUX_GPIO(GPIO_FN_ET0_RX_ER, ET0_RX_ER_MARK), - - /* PTF (mobule: EtherC) */ - PINMUX_GPIO(GPIO_FN_ET1_CRS_DV, ET1_CRS_DV_MARK), - PINMUX_GPIO(GPIO_FN_ET1_TXD1, ET1_TXD1_MARK), - PINMUX_GPIO(GPIO_FN_ET1_TXD0, ET1_TXD0_MARK), - PINMUX_GPIO(GPIO_FN_ET1_TX_EN, ET1_TX_EN_MARK), - PINMUX_GPIO(GPIO_FN_ET1_REF_CLK, ET1_REF_CLK_MARK), - PINMUX_GPIO(GPIO_FN_ET1_RXD1, ET1_RXD1_MARK), - PINMUX_GPIO(GPIO_FN_ET1_RXD0, ET1_RXD0_MARK), - PINMUX_GPIO(GPIO_FN_ET1_RX_ER, ET1_RX_ER_MARK), - - /* PTG (mobule: SYSTEM, PWMX, LPC) */ - PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK), - PINMUX_GPIO(GPIO_FN_STATUS1, STATUS1_MARK), - PINMUX_GPIO(GPIO_FN_PWX0, PWX0_MARK), - PINMUX_GPIO(GPIO_FN_PWX1, PWX1_MARK), - PINMUX_GPIO(GPIO_FN_PWX2, PWX2_MARK), - PINMUX_GPIO(GPIO_FN_PWX3, PWX3_MARK), + /* PTE (mobule: RMII) */ + PINMUX_GPIO(GPIO_FN_RMII0_CRS_DV, RMII0_CRS_DV_MARK), + PINMUX_GPIO(GPIO_FN_RMII0_TXD1, RMII0_TXD1_MARK), + PINMUX_GPIO(GPIO_FN_RMII0_TXD0, RMII0_TXD0_MARK), + PINMUX_GPIO(GPIO_FN_RMII0_TXEN, RMII0_TXEN_MARK), + PINMUX_GPIO(GPIO_FN_RMII0_REFCLK, RMII0_REFCLK_MARK), + PINMUX_GPIO(GPIO_FN_RMII0_RXD1, RMII0_RXD1_MARK), + PINMUX_GPIO(GPIO_FN_RMII0_RXD0, RMII0_RXD0_MARK), + PINMUX_GPIO(GPIO_FN_RMII0_RX_ER, RMII0_RX_ER_MARK), + + /* PTF (mobule: RMII, SerMux) */ + PINMUX_GPIO(GPIO_FN_RMII1_CRS_DV, RMII1_CRS_DV_MARK), + PINMUX_GPIO(GPIO_FN_RMII1_TXD1, RMII1_TXD1_MARK), + PINMUX_GPIO(GPIO_FN_RMII1_TXD0, RMII1_TXD0_MARK), + PINMUX_GPIO(GPIO_FN_RMII1_TXEN, RMII1_TXEN_MARK), + PINMUX_GPIO(GPIO_FN_RMII1_REFCLK, RMII1_REFCLK_MARK), + PINMUX_GPIO(GPIO_FN_RMII1_RXD1, RMII1_RXD1_MARK), + PINMUX_GPIO(GPIO_FN_RMII1_RXD0, RMII1_RXD0_MARK), + PINMUX_GPIO(GPIO_FN_RMII1_RX_ER, RMII1_RX_ER_MARK), + PINMUX_GPIO(GPIO_FN_RAC_RI, RAC_RI_MARK), + + /* PTG (mobule: system, LBSC, LPC, WDT, LPC, eMMC) */ + PINMUX_GPIO(GPIO_FN_BOOTFMS, BOOTFMS_MARK), + PINMUX_GPIO(GPIO_FN_BOOTWP, BOOTWP_MARK), + PINMUX_GPIO(GPIO_FN_A25, A25_MARK), + PINMUX_GPIO(GPIO_FN_A24, A24_MARK), PINMUX_GPIO(GPIO_FN_SERIRQ, SERIRQ_MARK), - PINMUX_GPIO(GPIO_FN_CLKRUN, CLKRUN_MARK), + PINMUX_GPIO(GPIO_FN_WDTOVF, WDTOVF_MARK), PINMUX_GPIO(GPIO_FN_LPCPD, LPCPD_MARK), PINMUX_GPIO(GPIO_FN_LDRQ, LDRQ_MARK), + PINMUX_GPIO(GPIO_FN_MMCCLK, MMCCLK_MARK), + PINMUX_GPIO(GPIO_FN_MMCCMD, MMCCMD_MARK), - /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */ - PINMUX_GPIO(GPIO_FN_TCLK, TCLK_MARK), - PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK), - PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK), + /* PTH (mobule: SPI1, LPC, DMAC, ADC) */ PINMUX_GPIO(GPIO_FN_SP1_MOSI, SP1_MOSI_MARK), PINMUX_GPIO(GPIO_FN_SP1_MISO, SP1_MISO_MARK), PINMUX_GPIO(GPIO_FN_SP1_SCK, SP1_SCK_MARK), PINMUX_GPIO(GPIO_FN_SP1_SCK_FB, SP1_SCK_FB_MARK), PINMUX_GPIO(GPIO_FN_SP1_SS0, SP1_SS0_MARK), PINMUX_GPIO(GPIO_FN_SP1_SS1, SP1_SS1_MARK), - PINMUX_GPIO(GPIO_FN_SP0_SS1, SP0_SS1_MARK), + PINMUX_GPIO(GPIO_FN_WP, WP_MARK), + PINMUX_GPIO(GPIO_FN_FMS0, FMS0_MARK), + PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK), + PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK), + PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK), + PINMUX_GPIO(GPIO_FN_ADTRG1, ADTRG1_MARK), + PINMUX_GPIO(GPIO_FN_ADTRG0, ADTRG0_MARK), - /* PTI (mobule: INTC) */ - PINMUX_GPIO(GPIO_FN_IRQ15, IRQ15_MARK), - PINMUX_GPIO(GPIO_FN_IRQ14, IRQ14_MARK), - PINMUX_GPIO(GPIO_FN_IRQ13, IRQ13_MARK), - PINMUX_GPIO(GPIO_FN_IRQ12, IRQ12_MARK), - PINMUX_GPIO(GPIO_FN_IRQ11, IRQ11_MARK), - PINMUX_GPIO(GPIO_FN_IRQ10, IRQ10_MARK), - PINMUX_GPIO(GPIO_FN_IRQ9, IRQ9_MARK), - PINMUX_GPIO(GPIO_FN_IRQ8, IRQ8_MARK), + /* PTI (mobule: LBSC, SDHI) */ + PINMUX_GPIO(GPIO_FN_D15, D15_MARK), + PINMUX_GPIO(GPIO_FN_D14, D14_MARK), + PINMUX_GPIO(GPIO_FN_D13, D13_MARK), + PINMUX_GPIO(GPIO_FN_D12, D12_MARK), + PINMUX_GPIO(GPIO_FN_D11, D11_MARK), + PINMUX_GPIO(GPIO_FN_D10, D10_MARK), + PINMUX_GPIO(GPIO_FN_D9, D9_MARK), + PINMUX_GPIO(GPIO_FN_D8, D8_MARK), + PINMUX_GPIO(GPIO_FN_SD_WP, SD_WP_MARK), + PINMUX_GPIO(GPIO_FN_SD_CD, SD_CD_MARK), + PINMUX_GPIO(GPIO_FN_SD_CLK, SD_CLK_MARK), + PINMUX_GPIO(GPIO_FN_SD_CMD, SD_CMD_MARK), + PINMUX_GPIO(GPIO_FN_SD_D3, SD_D3_MARK), + PINMUX_GPIO(GPIO_FN_SD_D2, SD_D2_MARK), + PINMUX_GPIO(GPIO_FN_SD_D1, SD_D1_MARK), + PINMUX_GPIO(GPIO_FN_SD_D0, SD_D0_MARK), /* PTJ (mobule: SCIF234, SERMUX) */ - PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK), + PINMUX_GPIO(GPIO_FN_RTS3, RTS3_MARK), + PINMUX_GPIO(GPIO_FN_CTS3, CTS3_MARK), PINMUX_GPIO(GPIO_FN_TXD3, TXD3_MARK), - PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK), - PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK), - PINMUX_GPIO(GPIO_FN_COM1_TXD, COM1_TXD_MARK), - PINMUX_GPIO(GPIO_FN_COM1_RXD, COM1_RXD_MARK), - PINMUX_GPIO(GPIO_FN_COM1_RTS, COM1_RTS_MARK), - PINMUX_GPIO(GPIO_FN_COM1_CTS, COM1_CTS_MARK), + PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK), + PINMUX_GPIO(GPIO_FN_RTS4, RTS4_MARK), + PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK), + PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK), - /* PTK (mobule: SERMUX) */ + /* PTK (mobule: SERMUX, LBSC, SCIF) */ PINMUX_GPIO(GPIO_FN_COM2_TXD, COM2_TXD_MARK), PINMUX_GPIO(GPIO_FN_COM2_RXD, COM2_RXD_MARK), PINMUX_GPIO(GPIO_FN_COM2_RTS, COM2_RTS_MARK), @@ -1349,62 +1510,65 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_FN_COM2_DTR, COM2_DTR_MARK), PINMUX_GPIO(GPIO_FN_COM2_DSR, COM2_DSR_MARK), PINMUX_GPIO(GPIO_FN_COM2_DCD, COM2_DCD_MARK), - PINMUX_GPIO(GPIO_FN_COM2_RI, COM2_RI_MARK), + PINMUX_GPIO(GPIO_FN_CLKOUT, CLKOUT_MARK), + PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK), + PINMUX_GPIO(GPIO_FN_SCK4, SCK4_MARK), + PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK), - /* PTL (mobule: SERMUX) */ - PINMUX_GPIO(GPIO_FN_RAC_TXD, RAC_TXD_MARK), + /* PTL (mobule: SERMUX, SCIF, LBSC, AUD) */ PINMUX_GPIO(GPIO_FN_RAC_RXD, RAC_RXD_MARK), PINMUX_GPIO(GPIO_FN_RAC_RTS, RAC_RTS_MARK), PINMUX_GPIO(GPIO_FN_RAC_CTS, RAC_CTS_MARK), PINMUX_GPIO(GPIO_FN_RAC_DTR, RAC_DTR_MARK), PINMUX_GPIO(GPIO_FN_RAC_DSR, RAC_DSR_MARK), PINMUX_GPIO(GPIO_FN_RAC_DCD, RAC_DCD_MARK), - PINMUX_GPIO(GPIO_FN_RAC_RI, RAC_RI_MARK), + PINMUX_GPIO(GPIO_FN_RAC_TXD, RAC_TXD_MARK), + PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK), + PINMUX_GPIO(GPIO_FN_CS5, CS5_MARK), + PINMUX_GPIO(GPIO_FN_CS6, CS6_MARK), + PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK), + PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK), + PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK), - /* PTM (mobule: IIC, LPC) */ + /* PTM (mobule: LBSC, IIC) */ + PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK), + PINMUX_GPIO(GPIO_FN_RD, RD_MARK), + PINMUX_GPIO(GPIO_FN_WE0, WE0_MARK), + PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK), PINMUX_GPIO(GPIO_FN_SDA6, SDA6_MARK), PINMUX_GPIO(GPIO_FN_SCL6, SCL6_MARK), PINMUX_GPIO(GPIO_FN_SDA7, SDA7_MARK), PINMUX_GPIO(GPIO_FN_SCL7, SCL7_MARK), - PINMUX_GPIO(GPIO_FN_WP, WP_MARK), - PINMUX_GPIO(GPIO_FN_FMS0, FMS0_MARK), - PINMUX_GPIO(GPIO_FN_FMS1, FMS1_MARK), - /* PTN (mobule: SCIF234, EVC) */ - PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK), - PINMUX_GPIO(GPIO_FN_RTS4, RTS4_MARK), - PINMUX_GPIO(GPIO_FN_RTS3, RTS3_MARK), - PINMUX_GPIO(GPIO_FN_RTS2, RTS2_MARK), - PINMUX_GPIO(GPIO_FN_CTS4, CTS4_MARK), - PINMUX_GPIO(GPIO_FN_CTS3, CTS3_MARK), - PINMUX_GPIO(GPIO_FN_CTS2, CTS2_MARK), - PINMUX_GPIO(GPIO_FN_EVENT7, EVENT7_MARK), - PINMUX_GPIO(GPIO_FN_EVENT6, EVENT6_MARK), - PINMUX_GPIO(GPIO_FN_EVENT5, EVENT5_MARK), - PINMUX_GPIO(GPIO_FN_EVENT4, EVENT4_MARK), - PINMUX_GPIO(GPIO_FN_EVENT3, EVENT3_MARK), - PINMUX_GPIO(GPIO_FN_EVENT2, EVENT2_MARK), - PINMUX_GPIO(GPIO_FN_EVENT1, EVENT1_MARK), - PINMUX_GPIO(GPIO_FN_EVENT0, EVENT0_MARK), + /* PTN (mobule: USB, JMC, SGPIO, WDT) */ + PINMUX_GPIO(GPIO_FN_VBUS_EN, VBUS_EN_MARK), + PINMUX_GPIO(GPIO_FN_VBUS_OC, VBUS_OC_MARK), + PINMUX_GPIO(GPIO_FN_JMCTCK, JMCTCK_MARK), + PINMUX_GPIO(GPIO_FN_JMCTMS, JMCTMS_MARK), + PINMUX_GPIO(GPIO_FN_JMCTDO, JMCTDO_MARK), + PINMUX_GPIO(GPIO_FN_JMCTDI, JMCTDI_MARK), + PINMUX_GPIO(GPIO_FN_JMCTRST, JMCTRST_MARK), + PINMUX_GPIO(GPIO_FN_SGPIO1_CLK, SGPIO1_CLK_MARK), + PINMUX_GPIO(GPIO_FN_SGPIO1_LOAD, SGPIO1_LOAD_MARK), + PINMUX_GPIO(GPIO_FN_SGPIO1_DI, SGPIO1_DI_MARK), + PINMUX_GPIO(GPIO_FN_SGPIO1_DO, SGPIO1_DO_MARK), + PINMUX_GPIO(GPIO_FN_SUB_CLKIN, SUB_CLKIN_MARK), - /* PTO (mobule: SGPIO) */ + /* PTO (mobule: SGPIO, SerMux) */ PINMUX_GPIO(GPIO_FN_SGPIO0_CLK, SGPIO0_CLK_MARK), PINMUX_GPIO(GPIO_FN_SGPIO0_LOAD, SGPIO0_LOAD_MARK), PINMUX_GPIO(GPIO_FN_SGPIO0_DI, SGPIO0_DI_MARK), PINMUX_GPIO(GPIO_FN_SGPIO0_DO, SGPIO0_DO_MARK), - PINMUX_GPIO(GPIO_FN_SGPIO1_CLK, SGPIO1_CLK_MARK), - PINMUX_GPIO(GPIO_FN_SGPIO1_LOAD, SGPIO1_LOAD_MARK), - PINMUX_GPIO(GPIO_FN_SGPIO1_DI, SGPIO1_DI_MARK), - PINMUX_GPIO(GPIO_FN_SGPIO1_DO, SGPIO1_DO_MARK), + PINMUX_GPIO(GPIO_FN_SGPIO2_CLK, SGPIO2_CLK_MARK), + PINMUX_GPIO(GPIO_FN_SGPIO2_LOAD, SGPIO2_LOAD_MARK), + PINMUX_GPIO(GPIO_FN_SGPIO2_DI, SGPIO2_DI_MARK), + PINMUX_GPIO(GPIO_FN_SGPIO2_DO, SGPIO2_DO_MARK), + PINMUX_GPIO(GPIO_FN_COM1_TXD, COM1_TXD_MARK), + PINMUX_GPIO(GPIO_FN_COM1_RXD, COM1_RXD_MARK), + PINMUX_GPIO(GPIO_FN_COM1_RTS, COM1_RTS_MARK), + PINMUX_GPIO(GPIO_FN_COM1_CTS, COM1_CTS_MARK), - /* PTP (mobule: JMC, SCIF234) */ - PINMUX_GPIO(GPIO_FN_JMCTCK, JMCTCK_MARK), - PINMUX_GPIO(GPIO_FN_JMCTMS, JMCTMS_MARK), - PINMUX_GPIO(GPIO_FN_JMCTDO, JMCTDO_MARK), - PINMUX_GPIO(GPIO_FN_JMCTDI, JMCTDI_MARK), - PINMUX_GPIO(GPIO_FN_JMCRST, JMCRST_MARK), - PINMUX_GPIO(GPIO_FN_SCK4, SCK4_MARK), - PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK), + /* PTP (mobule: EVC, ADC) */ /* PTQ (mobule: LPC) */ PINMUX_GPIO(GPIO_FN_LAD3, LAD3_MARK), @@ -1439,31 +1603,41 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_FN_SDA3, SDA3_MARK), PINMUX_GPIO(GPIO_FN_SCL3, SCL3_MARK), - /* PTT (mobule: SYSTEM, PWMX) */ - PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK), - PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK), + /* PTT (mobule: PWMX, AUD) */ + PINMUX_GPIO(GPIO_FN_PWMX7, PWMX7_MARK), + PINMUX_GPIO(GPIO_FN_PWMX6, PWMX6_MARK), + PINMUX_GPIO(GPIO_FN_PWMX5, PWMX5_MARK), + PINMUX_GPIO(GPIO_FN_PWMX4, PWMX4_MARK), + PINMUX_GPIO(GPIO_FN_PWMX3, PWMX3_MARK), + PINMUX_GPIO(GPIO_FN_PWMX2, PWMX2_MARK), + PINMUX_GPIO(GPIO_FN_PWMX1, PWMX1_MARK), + PINMUX_GPIO(GPIO_FN_PWMX0, PWMX0_MARK), PINMUX_GPIO(GPIO_FN_AUDATA3, AUDATA3_MARK), PINMUX_GPIO(GPIO_FN_AUDATA2, AUDATA2_MARK), PINMUX_GPIO(GPIO_FN_AUDATA1, AUDATA1_MARK), PINMUX_GPIO(GPIO_FN_AUDATA0, AUDATA0_MARK), - PINMUX_GPIO(GPIO_FN_PWX7, PWX7_MARK), - PINMUX_GPIO(GPIO_FN_PWX6, PWX6_MARK), - PINMUX_GPIO(GPIO_FN_PWX5, PWX5_MARK), - PINMUX_GPIO(GPIO_FN_PWX4, PWX4_MARK), - - /* PTU (mobule: LBSC, DMAC) */ - PINMUX_GPIO(GPIO_FN_CS6, CS6_MARK), - PINMUX_GPIO(GPIO_FN_CS5, CS5_MARK), - PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK), - PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK), - PINMUX_GPIO(GPIO_FN_RD, RD_MARK), - PINMUX_GPIO(GPIO_FN_WE0, WE0_MARK), - PINMUX_GPIO(GPIO_FN_A25, A25_MARK), - PINMUX_GPIO(GPIO_FN_A24, A24_MARK), - PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK), - PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK), + PINMUX_GPIO(GPIO_FN_STATUS1, STATUS1_MARK), + PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK), - /* PTV (mobule: LBSC, DMAC) */ + /* PTU (mobule: LPC, APM) */ + PINMUX_GPIO(GPIO_FN_LGPIO7, LGPIO7_MARK), + PINMUX_GPIO(GPIO_FN_LGPIO6, LGPIO6_MARK), + PINMUX_GPIO(GPIO_FN_LGPIO5, LGPIO5_MARK), + PINMUX_GPIO(GPIO_FN_LGPIO4, LGPIO4_MARK), + PINMUX_GPIO(GPIO_FN_LGPIO3, LGPIO3_MARK), + PINMUX_GPIO(GPIO_FN_LGPIO2, LGPIO2_MARK), + PINMUX_GPIO(GPIO_FN_LGPIO1, LGPIO1_MARK), + PINMUX_GPIO(GPIO_FN_LGPIO0, LGPIO0_MARK), + PINMUX_GPIO(GPIO_FN_APMONCTL_O, APMONCTL_O_MARK), + PINMUX_GPIO(GPIO_FN_APMPWBTOUT_O, APMPWBTOUT_O_MARK), + PINMUX_GPIO(GPIO_FN_APMSCI_O, APMSCI_O_MARK), + PINMUX_GPIO(GPIO_FN_APMVDDON, APMVDDON_MARK), + PINMUX_GPIO(GPIO_FN_APMSLPBTN, APMSLPBTN_MARK), + PINMUX_GPIO(GPIO_FN_APMPWRBTN, APMPWRBTN_MARK), + PINMUX_GPIO(GPIO_FN_APMS5N, APMS5N_MARK), + PINMUX_GPIO(GPIO_FN_APMS3N, APMS3N_MARK), + + /* PTV (mobule: LBSC, SerMux, R-SPI, EVC, GRA) */ PINMUX_GPIO(GPIO_FN_A23, A23_MARK), PINMUX_GPIO(GPIO_FN_A22, A22_MARK), PINMUX_GPIO(GPIO_FN_A21, A21_MARK), @@ -1472,12 +1646,20 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_FN_A18, A18_MARK), PINMUX_GPIO(GPIO_FN_A17, A17_MARK), PINMUX_GPIO(GPIO_FN_A16, A16_MARK), - PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK), - PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK), - PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK), - PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK), + PINMUX_GPIO(GPIO_FN_COM2_RI, COM2_RI_MARK), + PINMUX_GPIO(GPIO_FN_R_SPI_MOSI, R_SPI_MOSI_MARK), + PINMUX_GPIO(GPIO_FN_R_SPI_MISO, R_SPI_MISO_MARK), + PINMUX_GPIO(GPIO_FN_R_SPI_RSPCK, R_SPI_RSPCK_MARK), + PINMUX_GPIO(GPIO_FN_R_SPI_SSL0, R_SPI_SSL0_MARK), + PINMUX_GPIO(GPIO_FN_R_SPI_SSL1, R_SPI_SSL1_MARK), + PINMUX_GPIO(GPIO_FN_EVENT7, EVENT7_MARK), + PINMUX_GPIO(GPIO_FN_EVENT6, EVENT6_MARK), + PINMUX_GPIO(GPIO_FN_VBIOS_DI, VBIOS_DI_MARK), + PINMUX_GPIO(GPIO_FN_VBIOS_DO, VBIOS_DO_MARK), + PINMUX_GPIO(GPIO_FN_VBIOS_CLK, VBIOS_CLK_MARK), + PINMUX_GPIO(GPIO_FN_VBIOS_CS, VBIOS_CS_MARK), - /* PTW (mobule: LBSC) */ + /* PTW (mobule: LBSC, EVC, SCIF) */ PINMUX_GPIO(GPIO_FN_A16, A16_MARK), PINMUX_GPIO(GPIO_FN_A15, A15_MARK), PINMUX_GPIO(GPIO_FN_A14, A14_MARK), @@ -1487,6 +1669,14 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_FN_A10, A10_MARK), PINMUX_GPIO(GPIO_FN_A9, A9_MARK), PINMUX_GPIO(GPIO_FN_A8, A8_MARK), + PINMUX_GPIO(GPIO_FN_EVENT5, EVENT5_MARK), + PINMUX_GPIO(GPIO_FN_EVENT4, EVENT4_MARK), + PINMUX_GPIO(GPIO_FN_EVENT3, EVENT3_MARK), + PINMUX_GPIO(GPIO_FN_EVENT2, EVENT2_MARK), + PINMUX_GPIO(GPIO_FN_EVENT1, EVENT1_MARK), + PINMUX_GPIO(GPIO_FN_EVENT0, EVENT0_MARK), + PINMUX_GPIO(GPIO_FN_CTS4, CTS4_MARK), + PINMUX_GPIO(GPIO_FN_CTS2, CTS2_MARK), /* PTX (mobule: LBSC) */ PINMUX_GPIO(GPIO_FN_A7, A7_MARK), @@ -1497,6 +1687,10 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_FN_A2, A2_MARK), PINMUX_GPIO(GPIO_FN_A1, A1_MARK), PINMUX_GPIO(GPIO_FN_A0, A0_MARK), + PINMUX_GPIO(GPIO_FN_RTS2, RTS2_MARK), + PINMUX_GPIO(GPIO_FN_SIM_D, SIM_D_MARK), + PINMUX_GPIO(GPIO_FN_SIM_CLK, SIM_CLK_MARK), + PINMUX_GPIO(GPIO_FN_SIM_RST, SIM_RST_MARK), /* PTY (mobule: LBSC) */ PINMUX_GPIO(GPIO_FN_D7, D7_MARK), @@ -1507,18 +1701,36 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_FN_D2, D2_MARK), PINMUX_GPIO(GPIO_FN_D1, D1_MARK), PINMUX_GPIO(GPIO_FN_D0, D0_MARK), + + /* PTZ (mobule: eMMC, ONFI) */ + PINMUX_GPIO(GPIO_FN_MMCDAT7, MMCDAT7_MARK), + PINMUX_GPIO(GPIO_FN_MMCDAT6, MMCDAT6_MARK), + PINMUX_GPIO(GPIO_FN_MMCDAT5, MMCDAT5_MARK), + PINMUX_GPIO(GPIO_FN_MMCDAT4, MMCDAT4_MARK), + PINMUX_GPIO(GPIO_FN_MMCDAT3, MMCDAT3_MARK), + PINMUX_GPIO(GPIO_FN_MMCDAT2, MMCDAT2_MARK), + PINMUX_GPIO(GPIO_FN_MMCDAT1, MMCDAT1_MARK), + PINMUX_GPIO(GPIO_FN_MMCDAT0, MMCDAT0_MARK), + PINMUX_GPIO(GPIO_FN_ON_DQ7, ON_DQ7_MARK), + PINMUX_GPIO(GPIO_FN_ON_DQ6, ON_DQ6_MARK), + PINMUX_GPIO(GPIO_FN_ON_DQ5, ON_DQ5_MARK), + PINMUX_GPIO(GPIO_FN_ON_DQ4, ON_DQ4_MARK), + PINMUX_GPIO(GPIO_FN_ON_DQ3, ON_DQ3_MARK), + PINMUX_GPIO(GPIO_FN_ON_DQ2, ON_DQ2_MARK), + PINMUX_GPIO(GPIO_FN_ON_DQ1, ON_DQ1_MARK), + PINMUX_GPIO(GPIO_FN_ON_DQ0, ON_DQ0_MARK), }; static struct pinmux_cfg_reg pinmux_config_regs[] = { { PINMUX_CFG_REG("PACR", 0xffec0000, 16, 2) { - PTA7_FN, PTA7_OUT, PTA7_IN, 0, - PTA6_FN, PTA6_OUT, PTA6_IN, 0, - PTA5_FN, PTA5_OUT, PTA5_IN, 0, - PTA4_FN, PTA4_OUT, PTA4_IN, 0, - PTA3_FN, PTA3_OUT, PTA3_IN, 0, - PTA2_FN, PTA2_OUT, PTA2_IN, 0, - PTA1_FN, PTA1_OUT, PTA1_IN, 0, - PTA0_FN, PTA0_OUT, PTA0_IN, 0 } + PTA7_FN, PTA7_OUT, PTA7_IN, PTA7_IN_PU, + PTA6_FN, PTA6_OUT, PTA6_IN, PTA6_IN_PU, + PTA5_FN, PTA5_OUT, PTA5_IN, PTA5_IN_PU, + PTA4_FN, PTA4_OUT, PTA4_IN, PTA4_IN_PU, + PTA3_FN, PTA3_OUT, PTA3_IN, PTA3_IN_PU, + PTA2_FN, PTA2_OUT, PTA2_IN, PTA2_IN_PU, + PTA1_FN, PTA1_OUT, PTA1_IN, PTA1_IN_PU, + PTA0_FN, PTA0_OUT, PTA0_IN, PTA0_IN_PU } }, { PINMUX_CFG_REG("PBCR", 0xffec0002, 16, 2) { PTB7_FN, PTB7_OUT, PTB7_IN, 0, @@ -1541,125 +1753,126 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = { PTC0_FN, PTC0_OUT, PTC0_IN, 0 } }, { PINMUX_CFG_REG("PDCR", 0xffec0006, 16, 2) { - PTD7_FN, PTD7_OUT, PTD7_IN, 0, - PTD6_FN, PTD6_OUT, PTD6_IN, 0, - PTD5_FN, PTD5_OUT, PTD5_IN, 0, - PTD4_FN, PTD4_OUT, PTD4_IN, 0, - PTD3_FN, PTD3_OUT, PTD3_IN, 0, - PTD2_FN, PTD2_OUT, PTD2_IN, 0, - PTD1_FN, PTD1_OUT, PTD1_IN, 0, - PTD0_FN, PTD0_OUT, PTD0_IN, 0 } + PTD7_FN, PTD7_OUT, PTD7_IN, PTD7_IN_PU, + PTD6_FN, PTD6_OUT, PTD6_IN, PTD6_IN_PU, + PTD5_FN, PTD5_OUT, PTD5_IN, PTD5_IN_PU, + PTD4_FN, PTD4_OUT, PTD4_IN, PTD4_IN_PU, + PTD3_FN, PTD3_OUT, PTD3_IN, PTD3_IN_PU, + PTD2_FN, PTD2_OUT, PTD2_IN, PTD2_IN_PU, + PTD1_FN, PTD1_OUT, PTD1_IN, PTD1_IN_PU, + PTD0_FN, PTD0_OUT, PTD0_IN, PTD0_IN_PU } }, { PINMUX_CFG_REG("PECR", 0xffec0008, 16, 2) { - PTE7_FN, PTE7_OUT, PTE7_IN, 0, - PTE6_FN, PTE6_OUT, PTE6_IN, 0, - PTE5_FN, PTE5_OUT, PTE5_IN, 0, - PTE4_FN, PTE4_OUT, PTE4_IN, 0, - PTE3_FN, PTE3_OUT, PTE3_IN, 0, - PTE2_FN, PTE2_OUT, PTE2_IN, 0, - PTE1_FN, PTE1_OUT, PTE1_IN, 0, - PTE0_FN, PTE0_OUT, PTE0_IN, 0 } + PTE7_FN, PTE7_OUT, PTE7_IN, PTE7_IN_PU, + PTE6_FN, PTE6_OUT, PTE6_IN, PTE6_IN_PU, + PTE5_FN, PTE5_OUT, PTE5_IN, PTE5_IN_PU, + PTE4_FN, PTE4_OUT, PTE4_IN, PTE4_IN_PU, + PTE3_FN, PTE3_OUT, PTE3_IN, PTE3_IN_PU, + PTE2_FN, PTE2_OUT, PTE2_IN, PTE2_IN_PU, + PTE1_FN, PTE1_OUT, PTE1_IN, PTE1_IN_PU, + PTE0_FN, PTE0_OUT, PTE0_IN, PTE0_IN_PU } }, { PINMUX_CFG_REG("PFCR", 0xffec000a, 16, 2) { - PTF7_FN, PTF7_OUT, PTF7_IN, 0, - PTF6_FN, PTF6_OUT, PTF6_IN, 0, - PTF5_FN, PTF5_OUT, PTF5_IN, 0, - PTF4_FN, PTF4_OUT, PTF4_IN, 0, - PTF3_FN, PTF3_OUT, PTF3_IN, 0, - PTF2_FN, PTF2_OUT, PTF2_IN, 0, - PTF1_FN, PTF1_OUT, PTF1_IN, 0, - PTF0_FN, PTF0_OUT, PTF0_IN, 0 } + PTF7_FN, PTF7_OUT, PTF7_IN, PTF7_IN_PU, + PTF6_FN, PTF6_OUT, PTF6_IN, PTF6_IN_PU, + PTF5_FN, PTF5_OUT, PTF5_IN, PTF5_IN_PU, + PTF4_FN, PTF4_OUT, PTF4_IN, PTF4_IN_PU, + PTF3_FN, PTF3_OUT, PTF3_IN, PTF3_IN_PU, + PTF2_FN, PTF2_OUT, PTF2_IN, PTF2_IN_PU, + PTF1_FN, PTF1_OUT, PTF1_IN, PTF1_IN_PU, + PTF0_FN, PTF0_OUT, PTF0_IN, PTF0_IN_PU } }, { PINMUX_CFG_REG("PGCR", 0xffec000c, 16, 2) { - PTG7_FN, PTG7_OUT, PTG7_IN, 0, - PTG6_FN, PTG6_OUT, PTG6_IN, 0, + PTG7_FN, PTG7_OUT, PTG7_IN, PTG7_IN_PU , + PTG6_FN, PTG6_OUT, PTG6_IN, PTG6_IN_PU , PTG5_FN, PTG5_OUT, PTG5_IN, 0, - PTG4_FN, PTG4_OUT, PTG4_IN, 0, + PTG4_FN, PTG4_OUT, PTG4_IN, PTG4_IN_PU , PTG3_FN, PTG3_OUT, PTG3_IN, 0, PTG2_FN, PTG2_OUT, PTG2_IN, 0, PTG1_FN, PTG1_OUT, PTG1_IN, 0, PTG0_FN, PTG0_OUT, PTG0_IN, 0 } }, { PINMUX_CFG_REG("PHCR", 0xffec000e, 16, 2) { - PTH7_FN, PTH7_OUT, PTH7_IN, 0, - PTH6_FN, PTH6_OUT, PTH6_IN, 0, - PTH5_FN, PTH5_OUT, PTH5_IN, 0, - PTH4_FN, PTH4_OUT, PTH4_IN, 0, - PTH3_FN, PTH3_OUT, PTH3_IN, 0, - PTH2_FN, PTH2_OUT, PTH2_IN, 0, - PTH1_FN, PTH1_OUT, PTH1_IN, 0, - PTH0_FN, PTH0_OUT, PTH0_IN, 0 } + PTH7_FN, PTH7_OUT, PTH7_IN, PTH7_IN_PU, + PTH6_FN, PTH6_OUT, PTH6_IN, PTH6_IN_PU, + PTH5_FN, PTH5_OUT, PTH5_IN, PTH5_IN_PU, + PTH4_FN, PTH4_OUT, PTH4_IN, PTH4_IN_PU, + PTH3_FN, PTH3_OUT, PTH3_IN, PTH3_IN_PU, + PTH2_FN, PTH2_OUT, PTH2_IN, PTH2_IN_PU, + PTH1_FN, PTH1_OUT, PTH1_IN, PTH1_IN_PU, + PTH0_FN, PTH0_OUT, PTH0_IN, PTH0_IN_PU } }, { PINMUX_CFG_REG("PICR", 0xffec0010, 16, 2) { - PTI7_FN, PTI7_OUT, PTI7_IN, 0, - PTI6_FN, PTI6_OUT, PTI6_IN, 0, + PTI7_FN, PTI7_OUT, PTI7_IN, PTI7_IN_PU, + PTI6_FN, PTI6_OUT, PTI6_IN, PTI6_IN_PU, PTI5_FN, PTI5_OUT, PTI5_IN, 0, - PTI4_FN, PTI4_OUT, PTI4_IN, 0, - PTI3_FN, PTI3_OUT, PTI3_IN, 0, - PTI2_FN, PTI2_OUT, PTI2_IN, 0, - PTI1_FN, PTI1_OUT, PTI1_IN, 0, - PTI0_FN, PTI0_OUT, PTI0_IN, 0 } + PTI4_FN, PTI4_OUT, PTI4_IN, PTI4_IN_PU, + PTI3_FN, PTI3_OUT, PTI3_IN, PTI3_IN_PU, + PTI2_FN, PTI2_OUT, PTI2_IN, PTI2_IN_PU, + PTI1_FN, PTI1_OUT, PTI1_IN, PTI1_IN_PU, + PTI0_FN, PTI0_OUT, PTI0_IN, PTI0_IN_PU } }, { PINMUX_CFG_REG("PJCR", 0xffec0012, 16, 2) { - PTJ7_FN, PTJ7_OUT, PTJ7_IN, 0, - PTJ6_FN, PTJ6_OUT, PTJ6_IN, 0, - PTJ5_FN, PTJ5_OUT, PTJ5_IN, 0, - PTJ4_FN, PTJ4_OUT, PTJ4_IN, 0, - PTJ3_FN, PTJ3_OUT, PTJ3_IN, 0, - PTJ2_FN, PTJ2_OUT, PTJ2_IN, 0, - PTJ1_FN, PTJ1_OUT, PTJ1_IN, 0, - PTJ0_FN, PTJ0_OUT, PTJ0_IN, 0 } + 0, 0, 0, 0, /* reserved: always set 1 */ + PTJ6_FN, PTJ6_OUT, PTJ6_IN, PTJ6_IN_PU, + PTJ5_FN, PTJ5_OUT, PTJ5_IN, PTJ5_IN_PU, + PTJ4_FN, PTJ4_OUT, PTJ4_IN, PTJ4_IN_PU, + PTJ3_FN, PTJ3_OUT, PTJ3_IN, PTJ3_IN_PU, + PTJ2_FN, PTJ2_OUT, PTJ2_IN, PTJ2_IN_PU, + PTJ1_FN, PTJ1_OUT, PTJ1_IN, PTJ1_IN_PU, + PTJ0_FN, PTJ0_OUT, PTJ0_IN, PTJ0_IN_PU } }, { PINMUX_CFG_REG("PKCR", 0xffec0014, 16, 2) { - PTK7_FN, PTK7_OUT, PTK7_IN, 0, - PTK6_FN, PTK6_OUT, PTK6_IN, 0, - PTK5_FN, PTK5_OUT, PTK5_IN, 0, - PTK4_FN, PTK4_OUT, PTK4_IN, 0, - PTK3_FN, PTK3_OUT, PTK3_IN, 0, - PTK2_FN, PTK2_OUT, PTK2_IN, 0, - PTK1_FN, PTK1_OUT, PTK1_IN, 0, - PTK0_FN, PTK0_OUT, PTK0_IN, 0 } + PTK7_FN, PTK7_OUT, PTK7_IN, PTK7_IN_PU, + PTK6_FN, PTK6_OUT, PTK6_IN, PTK6_IN_PU, + PTK5_FN, PTK5_OUT, PTK5_IN, PTK5_IN_PU, + PTK4_FN, PTK4_OUT, PTK4_IN, PTK4_IN_PU, + PTK3_FN, PTK3_OUT, PTK3_IN, PTK3_IN_PU, + PTK2_FN, PTK2_OUT, PTK2_IN, PTK2_IN_PU, + PTK1_FN, PTK1_OUT, PTK1_IN, PTK1_IN_PU, + PTK0_FN, PTK0_OUT, PTK0_IN, PTK0_IN_PU } }, { PINMUX_CFG_REG("PLCR", 0xffec0016, 16, 2) { - PTL7_FN, PTL7_OUT, PTL7_IN, 0, - PTL6_FN, PTL6_OUT, PTL6_IN, 0, - PTL5_FN, PTL5_OUT, PTL5_IN, 0, - PTL4_FN, PTL4_OUT, PTL4_IN, 0, - PTL3_FN, PTL3_OUT, PTL3_IN, 0, - PTL2_FN, PTL2_OUT, PTL2_IN, 0, - PTL1_FN, PTL1_OUT, PTL1_IN, 0, - PTL0_FN, PTL0_OUT, PTL0_IN, 0 } + 0, 0, 0, 0, /* reserved: always set 1 */ + PTL6_FN, PTL6_OUT, PTL6_IN, PTL6_IN_PU, + PTL5_FN, PTL5_OUT, PTL5_IN, PTL5_IN_PU, + PTL4_FN, PTL4_OUT, PTL4_IN, PTL4_IN_PU, + PTL3_FN, PTL3_OUT, PTL3_IN, PTL3_IN_PU, + PTL2_FN, PTL2_OUT, PTL2_IN, PTL2_IN_PU, + PTL1_FN, PTL1_OUT, PTL1_IN, PTL1_IN_PU, + PTL0_FN, PTL0_OUT, PTL0_IN, PTL0_IN_PU } }, { PINMUX_CFG_REG("PMCR", 0xffec0018, 16, 2) { - 0, 0, 0, 0, /* reserved: always set 1 */ - PTM6_FN, PTM6_OUT, PTM6_IN, 0, - PTM5_FN, PTM5_OUT, PTM5_IN, 0, - PTM4_FN, PTM4_OUT, PTM4_IN, 0, + PTM7_FN, PTM7_OUT, PTM7_IN, PTM7_IN_PU, + PTM6_FN, PTM6_OUT, PTM6_IN, PTM6_IN_PU, + PTM5_FN, PTM5_OUT, PTM5_IN, PTM5_IN_PU, + PTM4_FN, PTM4_OUT, PTM4_IN, PTM4_IN_PU, PTM3_FN, PTM3_OUT, PTM3_IN, 0, PTM2_FN, PTM2_OUT, PTM2_IN, 0, PTM1_FN, PTM1_OUT, PTM1_IN, 0, PTM0_FN, PTM0_OUT, PTM0_IN, 0 } }, { PINMUX_CFG_REG("PNCR", 0xffec001a, 16, 2) { - PTN7_FN, PTN7_OUT, PTN7_IN, 0, + 0, 0, 0, 0, /* reserved: always set 1 */ PTN6_FN, PTN6_OUT, PTN6_IN, 0, PTN5_FN, PTN5_OUT, PTN5_IN, 0, - PTN4_FN, PTN4_OUT, PTN4_IN, 0, - PTN3_FN, PTN3_OUT, PTN3_IN, 0, - PTN2_FN, PTN2_OUT, PTN2_IN, 0, - PTN1_FN, PTN1_OUT, PTN1_IN, 0, - PTN0_FN, PTN0_OUT, PTN0_IN, 0 } + PTN4_FN, PTN4_OUT, PTN4_IN, PTN4_IN_PU, + PTN3_FN, PTN3_OUT, PTN3_IN, PTN3_IN_PU, + PTN2_FN, PTN2_OUT, PTN2_IN, PTN2_IN_PU, + PTN1_FN, PTN1_OUT, PTN1_IN, PTN1_IN_PU, + PTN0_FN, PTN0_OUT, PTN0_IN, PTN0_IN_PU } }, { PINMUX_CFG_REG("POCR", 0xffec001c, 16, 2) { - PTO7_FN, PTO7_OUT, PTO7_IN, 0, - PTO6_FN, PTO6_OUT, PTO6_IN, 0, - PTO5_FN, PTO5_OUT, PTO5_IN, 0, - PTO4_FN, PTO4_OUT, PTO4_IN, 0, - PTO3_FN, PTO3_OUT, PTO3_IN, 0, - PTO2_FN, PTO2_OUT, PTO2_IN, 0, - PTO1_FN, PTO1_OUT, PTO1_IN, 0, - PTO0_FN, PTO0_OUT, PTO0_IN, 0 } + PTO7_FN, PTO7_OUT, PTO7_IN, PTO7_IN_PU, + PTO6_FN, PTO6_OUT, PTO6_IN, PTO6_IN_PU, + PTO5_FN, PTO5_OUT, PTO5_IN, PTO5_IN_PU, + PTO4_FN, PTO4_OUT, PTO4_IN, PTO4_IN_PU, + PTO3_FN, PTO3_OUT, PTO3_IN, PTO3_IN_PU, + PTO2_FN, PTO2_OUT, PTO2_IN, PTO2_IN_PU, + PTO1_FN, PTO1_OUT, PTO1_IN, PTO1_IN_PU, + PTO0_FN, PTO0_OUT, PTO0_IN, PTO0_IN_PU } }, +#if 0 /* FIXME: Remove it? */ { PINMUX_CFG_REG("PPCR", 0xffec001e, 16, 2) { 0, 0, 0, 0, /* reserved: always set 1 */ PTP6_FN, PTP6_OUT, PTP6_IN, 0, @@ -1670,6 +1883,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = { PTP1_FN, PTP1_OUT, PTP1_IN, 0, PTP0_FN, PTP0_OUT, PTP0_IN, 0 } }, +#endif { PINMUX_CFG_REG("PQCR", 0xffec0020, 16, 2) { 0, 0, 0, 0, /* reserved: always set 1 */ PTQ6_FN, PTQ6_OUT, PTQ6_IN, 0, @@ -1701,14 +1915,14 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = { PTS0_FN, PTS0_OUT, PTS0_IN, 0 } }, { PINMUX_CFG_REG("PTCR", 0xffec0026, 16, 2) { - 0, 0, 0, 0, /* reserved: always set 1 */ - 0, 0, 0, 0, /* reserved: always set 1 */ - PTT5_FN, PTT5_OUT, PTT5_IN, 0, - PTT4_FN, PTT4_OUT, PTT4_IN, 0, - PTT3_FN, PTT3_OUT, PTT3_IN, 0, - PTT2_FN, PTT2_OUT, PTT2_IN, 0, - PTT1_FN, PTT1_OUT, PTT1_IN, 0, - PTT0_FN, PTT0_OUT, PTT0_IN, 0 } + PTT7_FN, PTT7_OUT, PTT7_IN, PTO7_IN_PU, + PTT6_FN, PTT6_OUT, PTT6_IN, PTO6_IN_PU, + PTT5_FN, PTT5_OUT, PTT5_IN, PTO5_IN_PU, + PTT4_FN, PTT4_OUT, PTT4_IN, PTO4_IN_PU, + PTT3_FN, PTT3_OUT, PTT3_IN, PTO3_IN_PU, + PTT2_FN, PTT2_OUT, PTT2_IN, PTO2_IN_PU, + PTT1_FN, PTT1_OUT, PTT1_IN, PTO1_IN_PU, + PTT0_FN, PTT0_OUT, PTT0_IN, PTO0_IN_PU } }, { PINMUX_CFG_REG("PUCR", 0xffec0028, 16, 2) { PTU7_FN, PTU7_OUT, PTU7_IN, PTU7_IN_PU, @@ -1727,16 +1941,16 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = { PTV4_FN, PTV4_OUT, PTV4_IN, PTV4_IN_PU, PTV3_FN, PTV3_OUT, PTV3_IN, PTV3_IN_PU, PTV2_FN, PTV2_OUT, PTV2_IN, PTV2_IN_PU, - PTV1_FN, PTV1_OUT, PTV1_IN, PTV1_IN_PU, - PTV0_FN, PTV0_OUT, PTV0_IN, PTV0_IN_PU } + PTV1_FN, PTV1_OUT, PTV1_IN, 0, + PTV0_FN, PTV0_OUT, PTV0_IN, 0 } }, { PINMUX_CFG_REG("PWCR", 0xffec002c, 16, 2) { - PTW7_FN, PTW7_OUT, PTW7_IN, PTW7_IN_PU, - PTW6_FN, PTW6_OUT, PTW6_IN, PTW6_IN_PU, - PTW5_FN, PTW5_OUT, PTW5_IN, PTW5_IN_PU, - PTW4_FN, PTW4_OUT, PTW4_IN, PTW4_IN_PU, - PTW3_FN, PTW3_OUT, PTW3_IN, PTW3_IN_PU, - PTW2_FN, PTW2_OUT, PTW2_IN, PTW2_IN_PU, + PTW7_FN, PTW7_OUT, PTW7_IN, 0, + PTW6_FN, PTW6_OUT, PTW6_IN, 0, + PTW5_FN, PTW5_OUT, PTW5_IN, 0, + PTW4_FN, PTW4_OUT, PTW4_IN, 0, + PTW3_FN, PTW3_OUT, PTW3_IN, 0, + PTW2_FN, PTW2_OUT, PTW2_IN, 0, PTW1_FN, PTW1_OUT, PTW1_IN, PTW1_IN_PU, PTW0_FN, PTW0_OUT, PTW0_IN, PTW0_IN_PU } }, @@ -1761,32 +1975,32 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = { PTY0_FN, PTY0_OUT, PTY0_IN, PTY0_IN_PU } }, { PINMUX_CFG_REG("PZCR", 0xffec0032, 16, 2) { - 0, PTZ7_OUT, PTZ7_IN, 0, - 0, PTZ6_OUT, PTZ6_IN, 0, - 0, PTZ5_OUT, PTZ5_IN, 0, - 0, PTZ4_OUT, PTZ4_IN, 0, - 0, PTZ3_OUT, PTZ3_IN, 0, - 0, PTZ2_OUT, PTZ2_IN, 0, - 0, PTZ1_OUT, PTZ1_IN, 0, - 0, PTZ0_OUT, PTZ0_IN, 0 } + PTZ7_FN, PTZ7_OUT, PTZ7_IN, 0, + PTZ6_FN, PTZ6_OUT, PTZ6_IN, 0, + PTZ5_FN, PTZ5_OUT, PTZ5_IN, 0, + PTZ4_FN, PTZ4_OUT, PTZ4_IN, 0, + PTZ3_FN, PTZ3_OUT, PTZ3_IN, 0, + PTZ2_FN, PTZ2_OUT, PTZ2_IN, 0, + PTZ1_FN, PTZ1_OUT, PTZ1_IN, 0, + PTZ0_FN, PTZ0_OUT, PTZ0_IN, 0 } }, { PINMUX_CFG_REG("PSEL0", 0xffec0070, 16, 1) { - PS0_15_FN3, PS0_15_FN1, - PS0_14_FN3, PS0_14_FN1, - PS0_13_FN3, PS0_13_FN1, - PS0_12_FN3, PS0_12_FN1, - 0, 0, - 0, 0, + PS0_15_FN1, PS0_15_FN2, + PS0_14_FN1, PS0_14_FN2, + PS0_13_FN1, PS0_13_FN2, + PS0_12_FN1, PS0_12_FN2, + PS0_11_FN1, PS0_11_FN2, + PS0_10_FN1, PS0_10_FN2, + PS0_9_FN1, PS0_9_FN2, + PS0_8_FN1, PS0_8_FN2, + PS0_7_FN1, PS0_7_FN2, + PS0_6_FN1, PS0_6_FN2, + PS0_5_FN1, PS0_5_FN2, + PS0_4_FN1, PS0_4_FN2, + PS0_3_FN1, PS0_3_FN2, + PS0_2_FN1, PS0_2_FN2, 0, 0, - 0, 0, - PS0_7_FN2, PS0_7_FN1, - PS0_6_FN2, PS0_6_FN1, - PS0_5_FN2, PS0_5_FN1, - PS0_4_FN2, PS0_4_FN1, - PS0_3_FN2, PS0_3_FN1, - PS0_2_FN2, PS0_2_FN1, - PS0_1_FN2, PS0_1_FN1, 0, 0, } }, { PINMUX_CFG_REG("PSEL1", 0xffec0072, 16, 1) { @@ -1795,73 +2009,136 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, 0, 0, + PS1_10_FN1, PS1_10_FN2, + PS1_9_FN1, PS1_9_FN2, + PS1_8_FN1, PS1_8_FN2, 0, 0, 0, 0, 0, 0, - PS1_7_FN1, PS1_7_FN3, - PS1_6_FN1, PS1_6_FN3, - 0, 0, - 0, 0, 0, 0, 0, 0, + PS1_2_FN1, PS1_2_FN2, 0, 0, 0, 0, } }, { PINMUX_CFG_REG("PSEL2", 0xffec0074, 16, 1) { 0, 0, 0, 0, - PS2_13_FN3, PS2_13_FN1, - PS2_12_FN3, PS2_12_FN1, + PS2_13_FN1, PS2_13_FN2, + PS2_12_FN1, PS2_12_FN2, 0, 0, 0, 0, 0, 0, 0, 0, + PS2_7_FN1, PS2_7_FN2, + PS2_6_FN1, PS2_6_FN2, + PS2_5_FN1, PS2_5_FN2, + PS2_4_FN1, PS2_4_FN2, 0, 0, + PS2_2_FN1, PS2_2_FN2, 0, 0, + 0, 0, } + }, + { PINMUX_CFG_REG("PSEL3", 0xffec0076, 16, 1) { + PS3_15_FN1, PS3_15_FN2, + PS3_14_FN1, PS3_14_FN2, + PS3_13_FN1, PS3_13_FN2, + PS3_12_FN1, PS3_12_FN2, + PS3_11_FN1, PS3_11_FN2, + PS3_10_FN1, PS3_10_FN2, + PS3_9_FN1, PS3_9_FN2, + PS3_8_FN1, PS3_8_FN2, + PS3_7_FN1, PS3_7_FN2, 0, 0, 0, 0, 0, 0, 0, 0, - PS2_1_FN1, PS2_1_FN2, - PS2_0_FN1, PS2_0_FN2, } + PS3_2_FN1, PS3_2_FN2, + PS3_1_FN1, PS3_1_FN2, + 0, 0, } }, + { PINMUX_CFG_REG("PSEL4", 0xffec0078, 16, 1) { - PS4_15_FN2, PS4_15_FN1, - PS4_14_FN2, PS4_14_FN1, - PS4_13_FN2, PS4_13_FN1, - PS4_12_FN2, PS4_12_FN1, - PS4_11_FN2, PS4_11_FN1, - PS4_10_FN2, PS4_10_FN1, - PS4_9_FN2, PS4_9_FN1, 0, 0, + PS4_14_FN1, PS4_14_FN2, + PS4_13_FN1, PS4_13_FN2, + PS4_12_FN1, PS4_12_FN2, 0, 0, + PS4_10_FN1, PS4_10_FN2, + PS4_9_FN1, PS4_9_FN2, + PS4_8_FN1, PS4_8_FN2, 0, 0, 0, 0, 0, 0, - PS4_3_FN2, PS4_3_FN1, - PS4_2_FN2, PS4_2_FN1, - PS4_1_FN2, PS4_1_FN1, - PS4_0_FN2, PS4_0_FN1, } + PS4_4_FN1, PS4_4_FN2, + PS4_3_FN1, PS4_3_FN2, + PS4_2_FN1, PS4_2_FN2, + PS4_1_FN1, PS4_1_FN2, + PS4_0_FN1, PS4_0_FN2, } }, { PINMUX_CFG_REG("PSEL5", 0xffec007a, 16, 1) { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, + PS5_11_FN1, PS5_11_FN2, + PS5_10_FN1, PS5_10_FN2, PS5_9_FN1, PS5_9_FN2, PS5_8_FN1, PS5_8_FN2, PS5_7_FN1, PS5_7_FN2, PS5_6_FN1, PS5_6_FN2, PS5_5_FN1, PS5_5_FN2, + PS5_4_FN1, PS5_4_FN2, + PS5_3_FN1, PS5_3_FN2, + PS5_2_FN1, PS5_2_FN2, + 0, 0, + 0, 0, } + }, + { PINMUX_CFG_REG("PSEL6", 0xffec007c, 16, 1) { + PS6_15_FN1, PS6_15_FN2, + PS6_14_FN1, PS6_14_FN2, + PS6_13_FN1, PS6_13_FN2, + PS6_12_FN1, PS6_12_FN2, + PS6_11_FN1, PS6_11_FN2, + PS6_10_FN1, PS6_10_FN2, + PS6_9_FN1, PS6_9_FN2, + PS6_8_FN1, PS6_8_FN2, + PS6_7_FN1, PS6_7_FN2, + PS6_6_FN1, PS6_6_FN2, + PS6_5_FN1, PS6_5_FN2, + PS6_4_FN1, PS6_4_FN2, + PS6_3_FN1, PS6_3_FN2, + PS6_2_FN1, PS6_2_FN2, + PS6_1_FN1, PS6_1_FN2, + PS6_0_FN1, PS6_0_FN2, } + }, + { PINMUX_CFG_REG("PSEL7", 0xffec0082, 16, 1) { + PS7_15_FN1, PS7_15_FN2, + PS7_14_FN1, PS7_14_FN2, + PS7_13_FN1, PS7_13_FN2, + PS7_12_FN1, PS7_12_FN2, + PS7_11_FN1, PS7_11_FN2, + PS7_10_FN1, PS7_10_FN2, + PS7_9_FN1, PS7_9_FN2, + PS7_8_FN1, PS7_8_FN2, + PS7_7_FN1, PS7_7_FN2, + PS7_6_FN1, PS7_6_FN2, + PS7_5_FN1, PS7_5_FN2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }, - { PINMUX_CFG_REG("PSEL6", 0xffec007c, 16, 1) { + { PINMUX_CFG_REG("PSEL8", 0xffec0084, 16, 1) { + PS8_15_FN1, PS8_15_FN2, + PS8_14_FN1, PS8_14_FN2, + PS8_13_FN1, PS8_13_FN2, + PS8_12_FN1, PS8_12_FN2, + PS8_11_FN1, PS8_11_FN2, + PS8_10_FN1, PS8_10_FN2, + PS8_9_FN1, PS8_9_FN2, + PS8_8_FN1, PS8_8_FN2, 0, 0, 0, 0, 0, 0, @@ -1869,15 +2146,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, 0, 0, - 0, 0, - PS6_7_FN_AN, PS6_7_FN_EV, - PS6_6_FN_AN, PS6_6_FN_EV, - PS6_5_FN_AN, PS6_5_FN_EV, - PS6_4_FN_AN, PS6_4_FN_EV, - PS6_3_FN_AN, PS6_3_FN_EV, - PS6_2_FN_AN, PS6_2_FN_EV, - PS6_1_FN_AN, PS6_1_FN_EV, - PS6_0_FN_AN, PS6_0_FN_EV, } + 0, 0, } }, {} }; @@ -1920,7 +2189,7 @@ static struct pinmux_data_reg pinmux_data_regs[] = { PTI3_DATA, PTI2_DATA, PTI1_DATA, PTI0_DATA } }, { PINMUX_DATA_REG("PJDR", 0xffec0046, 8) { - PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA, + 0, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA, PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA } }, { PINMUX_DATA_REG("PKDR", 0xffec0048, 8) { @@ -1928,15 +2197,15 @@ static struct pinmux_data_reg pinmux_data_regs[] = { PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA } }, { PINMUX_DATA_REG("PLDR", 0xffec004a, 8) { - PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA, + 0, PTL6_DATA, PTL5_DATA, PTL4_DATA, PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA } }, { PINMUX_DATA_REG("PMDR", 0xffec004c, 8) { - 0, PTM6_DATA, PTM5_DATA, PTM4_DATA, + PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA, PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA } }, { PINMUX_DATA_REG("PNDR", 0xffec004e, 8) { - PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA, + 0, PTN6_DATA, PTN5_DATA, PTN4_DATA, PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA } }, { PINMUX_DATA_REG("PODR", 0xffec0050, 8) { @@ -1944,7 +2213,7 @@ static struct pinmux_data_reg pinmux_data_regs[] = { PTO3_DATA, PTO2_DATA, PTO1_DATA, PTO0_DATA } }, { PINMUX_DATA_REG("PPDR", 0xffec0052, 8) { - 0, PTP6_DATA, PTP5_DATA, PTP4_DATA, + PTP7_DATA, PTP6_DATA, PTP5_DATA, PTP4_DATA, PTP3_DATA, PTP2_DATA, PTP1_DATA, PTP0_DATA } }, { PINMUX_DATA_REG("PQDR", 0xffec0054, 8) { @@ -1960,7 +2229,7 @@ static struct pinmux_data_reg pinmux_data_regs[] = { PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA } }, { PINMUX_DATA_REG("PTDR", 0xffec005a, 8) { - 0, 0, PTT5_DATA, PTT4_DATA, + PTT7_DATA, PTT6_DATA, PTT5_DATA, PTT4_DATA, PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA } }, { PINMUX_DATA_REG("PUDR", 0xffec005c, 8) { @@ -2000,8 +2269,8 @@ static struct pinmux_info sh7757_pinmux_info = { .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END }, .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, - .first_gpio = GPIO_PTA7, - .last_gpio = GPIO_FN_D0, + .first_gpio = GPIO_PTA0, + .last_gpio = GPIO_FN_ON_DQ0, .gpios = pinmux_gpios, .cfg_regs = pinmux_config_regs, @@ -2015,5 +2284,4 @@ static int __init plat_pinmux_setup(void) { return register_pinmux(&sh7757_pinmux_info); } - arch_initcall(plat_pinmux_setup); -- cgit v1.2.3-59-g8ed1b From 56c52986b163575402c2db83b2fec60234ace1e9 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 6 Jul 2010 04:32:05 +0000 Subject: sh: modify clock framework of SH7757 Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7757.c | 199 ++++++++++++++++++--------------- 2 files changed, 112 insertions(+), 89 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index e6b1f207f7ab..4b5a1d53704d 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -573,7 +573,7 @@ config SH_CLK_CPG config SH_CLK_CPG_LEGACY depends on SH_CLK_CPG def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE && \ - !CPU_SUBTYPE_SH7786 + !CPU_SUBTYPE_SH7786 && !CPU_SUBTYPE_SH7757 config SH_CLK_MD int "CPU Mode Pin Setting" diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c index 0a752bd324ac..ce39a2ae8c6c 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c @@ -3,7 +3,7 @@ * * SH7757 support for the clock framework * - * Copyright (C) 2009 Renesas Solutions Corp. + * Copyright (C) 2009-2010 Renesas Solutions Corp. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -16,124 +16,147 @@ #include #include -static int ifc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1, - 16, 1, 1, 32, 1, 1, 1, 1 }; -static int sfc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1, - 16, 1, 1, 32, 1, 1, 1, 1 }; -static int bfc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1, - 16, 1, 1, 32, 1, 1, 1, 1 }; -static int p1fc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1, - 16, 1, 1, 32, 1, 1, 1, 1 }; +/* + * Default rate for the root input clock, reset this with clk_set_rate() + * from the platform code. + */ +static struct clk extal_clk = { + .rate = 48000000, +}; -static void master_clk_init(struct clk *clk) +static unsigned long pll_recalc(struct clk *clk) { - clk->rate = CONFIG_SH_PCLK_FREQ * 16; -} + int multiplier; -static struct clk_ops sh7757_master_clk_ops = { - .init = master_clk_init, -}; + multiplier = test_mode_pin(MODE_PIN0) ? 24 : 16; -static void module_clk_recalc(struct clk *clk) -{ - int idx = __raw_readl(FRQCR) & 0x0000000f; - clk->rate = clk->parent->rate / p1fc_divisors[idx]; + return clk->parent->rate * multiplier; } -static struct clk_ops sh7757_module_clk_ops = { - .recalc = module_clk_recalc, +static struct clk_ops pll_clk_ops = { + .recalc = pll_recalc, }; -static void bus_clk_recalc(struct clk *clk) -{ - int idx = (__raw_readl(FRQCR) >> 8) & 0x0000000f; - clk->rate = clk->parent->rate / bfc_divisors[idx]; -} +static struct clk pll_clk = { + .ops = &pll_clk_ops, + .parent = &extal_clk, + .flags = CLK_ENABLE_ON_INIT, +}; -static struct clk_ops sh7757_bus_clk_ops = { - .recalc = bus_clk_recalc, +static struct clk *clks[] = { + &extal_clk, + &pll_clk, }; -static void cpu_clk_recalc(struct clk *clk) -{ - int idx = (__raw_readl(FRQCR) >> 20) & 0x0000000f; - clk->rate = clk->parent->rate / ifc_divisors[idx]; -} +static unsigned int div2[] = { 1, 1, 2, 1, 1, 4, 1, 6, + 1, 1, 1, 16, 1, 24, 1, 1 }; -static struct clk_ops sh7757_cpu_clk_ops = { - .recalc = cpu_clk_recalc, +static struct clk_div_mult_table div4_div_mult_table = { + .divisors = div2, + .nr_divisors = ARRAY_SIZE(div2), }; -static struct clk_ops *sh7757_clk_ops[] = { - &sh7757_master_clk_ops, - &sh7757_module_clk_ops, - &sh7757_bus_clk_ops, - &sh7757_cpu_clk_ops, +static struct clk_div4_table div4_table = { + .div_mult_table = &div4_div_mult_table, }; -void __init arch_init_clk_ops(struct clk_ops **ops, int idx) -{ - if (idx < ARRAY_SIZE(sh7757_clk_ops)) - *ops = sh7757_clk_ops[idx]; -} +enum { DIV4_I, DIV4_SH, DIV4_P, DIV4_NR }; -static void shyway_clk_recalc(struct clk *clk) -{ - int idx = (__raw_readl(FRQCR) >> 12) & 0x0000000f; - clk->rate = clk->parent->rate / sfc_divisors[idx]; -} - -static struct clk_ops sh7757_shyway_clk_ops = { - .recalc = shyway_clk_recalc, -}; +#define DIV4(_bit, _mask, _flags) \ + SH_CLK_DIV4(&pll_clk, FRQCR, _bit, _mask, _flags) -static struct clk sh7757_shyway_clk = { - .flags = CLK_ENABLE_ON_INIT, - .ops = &sh7757_shyway_clk_ops, +struct clk div4_clks[DIV4_NR] = { + /* + * P clock is always enable, because some P clock modules is used + * by Host PC. + */ + [DIV4_P] = DIV4(0, 0x2800, CLK_ENABLE_ON_INIT), + [DIV4_SH] = DIV4(12, 0x00a0, CLK_ENABLE_ON_INIT), + [DIV4_I] = DIV4(20, 0x0004, CLK_ENABLE_ON_INIT), }; -/* - * Additional sh7757-specific on-chip clocks that aren't already part of the - * clock framework - */ -static struct clk *sh7757_onchip_clocks[] = { - &sh7757_shyway_clk, +#define MSTPCR0 0xffc80030 +#define MSTPCR1 0xffc80034 + +enum { MSTP004, MSTP000, MSTP114, MSTP113, MSTP112, + MSTP111, MSTP110, MSTP103, MSTP102, + MSTP_NR }; + +static struct clk mstp_clks[MSTP_NR] = { + /* MSTPCR0 */ + [MSTP004] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 4, 0), + [MSTP000] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 0, 0), + + /* MSTPCR1 */ + [MSTP114] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 14, 0), + [MSTP113] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 13, 0), + [MSTP112] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 12, 0), + [MSTP111] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 11, 0), + [MSTP110] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 10, 0), + [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0), + [MSTP102] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 2, 0), }; #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { /* main clocks */ - CLKDEV_CON_ID("shyway_clk", &sh7757_shyway_clk), + CLKDEV_CON_ID("extal", &extal_clk), + CLKDEV_CON_ID("pll_clk", &pll_clk), + + /* DIV4 clocks */ + CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), + CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]), + CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), + + /* MSTP32 clocks */ + CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]), + CLKDEV_CON_ID("riic", &mstp_clks[MSTP000]), + { + /* TMU0 */ + .dev_id = "sh_tmu.0", + .con_id = "tmu_fck", + .clk = &mstp_clks[MSTP113], + }, { + /* TMU1 */ + .dev_id = "sh_tmu.1", + .con_id = "tmu_fck", + .clk = &mstp_clks[MSTP114], + }, + { + /* SCIF4 (But, ID is 2) */ + .dev_id = "sh-sci.2", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP112], + }, { + /* SCIF3 */ + .dev_id = "sh-sci.1", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP111], + }, { + /* SCIF2 */ + .dev_id = "sh-sci.0", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP110], + }, + CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]), }; -static int __init sh7757_clk_init(void) +int __init arch_clk_init(void) { - struct clk *clk = clk_get(NULL, "master_clk"); - int i; - - for (i = 0; i < ARRAY_SIZE(sh7757_onchip_clocks); i++) { - struct clk *clkp = sh7757_onchip_clocks[i]; + int i, ret = 0; - clkp->parent = clk; - clk_register(clkp); - clk_enable(clkp); - } + for (i = 0; i < ARRAY_SIZE(clks); i++) + ret |= clk_register(clks[i]); + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); - /* - * Now that we have the rest of the clocks registered, we need to - * force the parent clock to propagate so that these clocks will - * automatically figure out their rate. We cheat by handing the - * parent clock its current rate and forcing child propagation. - */ - clk_set_rate(clk, clk_get_rate(clk)); + if (!ret) + ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), + &div4_table); + if (!ret) + ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); - clk_put(clk); - - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - - return 0; + return ret; } -arch_initcall(sh7757_clk_init); - -- cgit v1.2.3-59-g8ed1b From 36239c6704b71da7fb8e2a9429e159a84d0c5a3e Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 6 Jul 2010 04:32:16 +0000 Subject: sh: add sh7757lcr board support This adds preliminary support for the sh7757lcr board. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/boards/Kconfig | 5 + arch/sh/boards/Makefile | 1 + arch/sh/boards/board-sh7757lcr.c | 374 ++++++++++++ arch/sh/configs/sh7757lcr_defconfig | 1126 +++++++++++++++++++++++++++++++++++ arch/sh/tools/mach-types | 1 + 5 files changed, 1507 insertions(+) create mode 100644 arch/sh/boards/board-sh7757lcr.c create mode 100644 arch/sh/configs/sh7757lcr_defconfig diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 65abfd41bd79..90ed1ec6921d 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -165,6 +165,11 @@ config SH_HIGHLANDER select SYS_SUPPORTS_PCI select IO_TRAPPED if MMU +config SH_SH7757LCR + bool "SH7757LCR" + depends on CPU_SUBTYPE_SH7757 + select ARCH_REQUIRE_GPIOLIB + config SH_SH7785LCR bool "SH7785LCR" depends on CPU_SUBTYPE_SH7785 diff --git a/arch/sh/boards/Makefile b/arch/sh/boards/Makefile index 2049d95feaaa..38ef655cc0f0 100644 --- a/arch/sh/boards/Makefile +++ b/arch/sh/boards/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_SH_EDOSK7760) += board-edosk7760.o obj-$(CONFIG_SH_ESPT) += board-espt.o obj-$(CONFIG_SH_POLARIS) += board-polaris.o obj-$(CONFIG_SH_TITAN) += board-titan.o +obj-$(CONFIG_SH_SH7757LCR) += board-sh7757lcr.o diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c new file mode 100644 index 000000000000..c475f1056ab4 --- /dev/null +++ b/arch/sh/boards/board-sh7757lcr.c @@ -0,0 +1,374 @@ +/* + * Renesas R0P7757LC0012RL Support. + * + * Copyright (C) 2009 - 2010 Renesas Solutions Corp. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct resource heartbeat_resource = { + .start = 0xffec005c, /* PUDR */ + .end = 0xffec005c, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_8BIT, +}; + +static unsigned char heartbeat_bit_pos[] = { 0, 1, 2, 3 }; + +static struct heartbeat_data heartbeat_data = { + .bit_pos = heartbeat_bit_pos, + .nr_bits = ARRAY_SIZE(heartbeat_bit_pos), + .flags = HEARTBEAT_INVERTED, +}; + +static struct platform_device heartbeat_device = { + .name = "heartbeat", + .id = -1, + .dev = { + .platform_data = &heartbeat_data, + }, + .num_resources = 1, + .resource = &heartbeat_resource, +}; + +/* Fast Ethernet */ +static struct resource sh_eth0_resources[] = { + { + .start = 0xfef00000, + .end = 0xfef001ff, + .flags = IORESOURCE_MEM, + }, { + .start = 84, + .end = 84, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct sh_eth_plat_data sh7757_eth0_pdata = { + .phy = 1, + .edmac_endian = EDMAC_LITTLE_ENDIAN, +}; + +static struct platform_device sh7757_eth0_device = { + .name = "sh-eth", + .resource = sh_eth0_resources, + .id = 0, + .num_resources = ARRAY_SIZE(sh_eth0_resources), + .dev = { + .platform_data = &sh7757_eth0_pdata, + }, +}; + +static struct resource sh_eth1_resources[] = { + { + .start = 0xfef00800, + .end = 0xfef009ff, + .flags = IORESOURCE_MEM, + }, { + .start = 84, + .end = 84, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct sh_eth_plat_data sh7757_eth1_pdata = { + .phy = 1, + .edmac_endian = EDMAC_LITTLE_ENDIAN, +}; + +static struct platform_device sh7757_eth1_device = { + .name = "sh-eth", + .resource = sh_eth1_resources, + .id = 1, + .num_resources = ARRAY_SIZE(sh_eth1_resources), + .dev = { + .platform_data = &sh7757_eth1_pdata, + }, +}; + +static struct platform_device *sh7757lcr_devices[] __initdata = { + &heartbeat_device, + &sh7757_eth0_device, + &sh7757_eth1_device, +}; + +static int __init sh7757lcr_devices_setup(void) +{ + /* RGMII (PTA) */ + gpio_request(GPIO_FN_ET0_MDC, NULL); + gpio_request(GPIO_FN_ET0_MDIO, NULL); + gpio_request(GPIO_FN_ET1_MDC, NULL); + gpio_request(GPIO_FN_ET1_MDIO, NULL); + + /* ONFI (PTB, PTZ) */ + gpio_request(GPIO_FN_ON_NRE, NULL); + gpio_request(GPIO_FN_ON_NWE, NULL); + gpio_request(GPIO_FN_ON_NWP, NULL); + gpio_request(GPIO_FN_ON_NCE0, NULL); + gpio_request(GPIO_FN_ON_R_B0, NULL); + gpio_request(GPIO_FN_ON_ALE, NULL); + gpio_request(GPIO_FN_ON_CLE, NULL); + + gpio_request(GPIO_FN_ON_DQ7, NULL); + gpio_request(GPIO_FN_ON_DQ6, NULL); + gpio_request(GPIO_FN_ON_DQ5, NULL); + gpio_request(GPIO_FN_ON_DQ4, NULL); + gpio_request(GPIO_FN_ON_DQ3, NULL); + gpio_request(GPIO_FN_ON_DQ2, NULL); + gpio_request(GPIO_FN_ON_DQ1, NULL); + gpio_request(GPIO_FN_ON_DQ0, NULL); + + /* IRQ8 to 0 (PTB, PTC) */ + gpio_request(GPIO_FN_IRQ8, NULL); + gpio_request(GPIO_FN_IRQ7, NULL); + gpio_request(GPIO_FN_IRQ6, NULL); + gpio_request(GPIO_FN_IRQ5, NULL); + gpio_request(GPIO_FN_IRQ4, NULL); + gpio_request(GPIO_FN_IRQ3, NULL); + gpio_request(GPIO_FN_IRQ2, NULL); + gpio_request(GPIO_FN_IRQ1, NULL); + gpio_request(GPIO_FN_IRQ0, NULL); + + /* SPI0 (PTD) */ + gpio_request(GPIO_FN_SP0_MOSI, NULL); + gpio_request(GPIO_FN_SP0_MISO, NULL); + gpio_request(GPIO_FN_SP0_SCK, NULL); + gpio_request(GPIO_FN_SP0_SCK_FB, NULL); + gpio_request(GPIO_FN_SP0_SS0, NULL); + gpio_request(GPIO_FN_SP0_SS1, NULL); + gpio_request(GPIO_FN_SP0_SS2, NULL); + gpio_request(GPIO_FN_SP0_SS3, NULL); + + /* RMII 0/1 (PTE, PTF) */ + gpio_request(GPIO_FN_RMII0_CRS_DV, NULL); + gpio_request(GPIO_FN_RMII0_TXD1, NULL); + gpio_request(GPIO_FN_RMII0_TXD0, NULL); + gpio_request(GPIO_FN_RMII0_TXEN, NULL); + gpio_request(GPIO_FN_RMII0_REFCLK, NULL); + gpio_request(GPIO_FN_RMII0_RXD1, NULL); + gpio_request(GPIO_FN_RMII0_RXD0, NULL); + gpio_request(GPIO_FN_RMII0_RX_ER, NULL); + gpio_request(GPIO_FN_RMII1_CRS_DV, NULL); + gpio_request(GPIO_FN_RMII1_TXD1, NULL); + gpio_request(GPIO_FN_RMII1_TXD0, NULL); + gpio_request(GPIO_FN_RMII1_TXEN, NULL); + gpio_request(GPIO_FN_RMII1_REFCLK, NULL); + gpio_request(GPIO_FN_RMII1_RXD1, NULL); + gpio_request(GPIO_FN_RMII1_RXD0, NULL); + gpio_request(GPIO_FN_RMII1_RX_ER, NULL); + + /* eMMC (PTG) */ + gpio_request(GPIO_FN_MMCCLK, NULL); + gpio_request(GPIO_FN_MMCCMD, NULL); + gpio_request(GPIO_FN_MMCDAT7, NULL); + gpio_request(GPIO_FN_MMCDAT6, NULL); + gpio_request(GPIO_FN_MMCDAT5, NULL); + gpio_request(GPIO_FN_MMCDAT4, NULL); + gpio_request(GPIO_FN_MMCDAT3, NULL); + gpio_request(GPIO_FN_MMCDAT2, NULL); + gpio_request(GPIO_FN_MMCDAT1, NULL); + gpio_request(GPIO_FN_MMCDAT0, NULL); + + /* LPC (PTG, PTH, PTQ, PTU) */ + gpio_request(GPIO_FN_SERIRQ, NULL); + gpio_request(GPIO_FN_LPCPD, NULL); + gpio_request(GPIO_FN_LDRQ, NULL); + gpio_request(GPIO_FN_WP, NULL); + gpio_request(GPIO_FN_FMS0, NULL); + gpio_request(GPIO_FN_LAD3, NULL); + gpio_request(GPIO_FN_LAD2, NULL); + gpio_request(GPIO_FN_LAD1, NULL); + gpio_request(GPIO_FN_LAD0, NULL); + gpio_request(GPIO_FN_LFRAME, NULL); + gpio_request(GPIO_FN_LRESET, NULL); + gpio_request(GPIO_FN_LCLK, NULL); + gpio_request(GPIO_FN_LGPIO7, NULL); + gpio_request(GPIO_FN_LGPIO6, NULL); + gpio_request(GPIO_FN_LGPIO5, NULL); + gpio_request(GPIO_FN_LGPIO4, NULL); + + /* SPI1 (PTH) */ + gpio_request(GPIO_FN_SP1_MOSI, NULL); + gpio_request(GPIO_FN_SP1_MISO, NULL); + gpio_request(GPIO_FN_SP1_SCK, NULL); + gpio_request(GPIO_FN_SP1_SCK_FB, NULL); + gpio_request(GPIO_FN_SP1_SS0, NULL); + gpio_request(GPIO_FN_SP1_SS1, NULL); + + /* SDHI (PTI) */ + gpio_request(GPIO_FN_SD_WP, NULL); + gpio_request(GPIO_FN_SD_CD, NULL); + gpio_request(GPIO_FN_SD_CLK, NULL); + gpio_request(GPIO_FN_SD_CMD, NULL); + gpio_request(GPIO_FN_SD_D3, NULL); + gpio_request(GPIO_FN_SD_D2, NULL); + gpio_request(GPIO_FN_SD_D1, NULL); + gpio_request(GPIO_FN_SD_D0, NULL); + + /* SCIF3/4 (PTJ, PTW) */ + gpio_request(GPIO_FN_RTS3, NULL); + gpio_request(GPIO_FN_CTS3, NULL); + gpio_request(GPIO_FN_TXD3, NULL); + gpio_request(GPIO_FN_RXD3, NULL); + gpio_request(GPIO_FN_RTS4, NULL); + gpio_request(GPIO_FN_RXD4, NULL); + gpio_request(GPIO_FN_TXD4, NULL); + gpio_request(GPIO_FN_CTS4, NULL); + + /* SERMUX (PTK, PTL, PTO, PTV) */ + gpio_request(GPIO_FN_COM2_TXD, NULL); + gpio_request(GPIO_FN_COM2_RXD, NULL); + gpio_request(GPIO_FN_COM2_RTS, NULL); + gpio_request(GPIO_FN_COM2_CTS, NULL); + gpio_request(GPIO_FN_COM2_DTR, NULL); + gpio_request(GPIO_FN_COM2_DSR, NULL); + gpio_request(GPIO_FN_COM2_DCD, NULL); + gpio_request(GPIO_FN_COM2_RI, NULL); + gpio_request(GPIO_FN_RAC_RXD, NULL); + gpio_request(GPIO_FN_RAC_RTS, NULL); + gpio_request(GPIO_FN_RAC_CTS, NULL); + gpio_request(GPIO_FN_RAC_DTR, NULL); + gpio_request(GPIO_FN_RAC_DSR, NULL); + gpio_request(GPIO_FN_RAC_DCD, NULL); + gpio_request(GPIO_FN_RAC_TXD, NULL); + gpio_request(GPIO_FN_COM1_TXD, NULL); + gpio_request(GPIO_FN_COM1_RXD, NULL); + gpio_request(GPIO_FN_COM1_RTS, NULL); + gpio_request(GPIO_FN_COM1_CTS, NULL); + + writeb(0x10, 0xfe470000); /* SMR0: SerMux mode 0 */ + + /* IIC (PTM, PTR, PTS) */ + gpio_request(GPIO_FN_SDA7, NULL); + gpio_request(GPIO_FN_SCL7, NULL); + gpio_request(GPIO_FN_SDA6, NULL); + gpio_request(GPIO_FN_SCL6, NULL); + gpio_request(GPIO_FN_SDA5, NULL); + gpio_request(GPIO_FN_SCL5, NULL); + gpio_request(GPIO_FN_SDA4, NULL); + gpio_request(GPIO_FN_SCL4, NULL); + gpio_request(GPIO_FN_SDA3, NULL); + gpio_request(GPIO_FN_SCL3, NULL); + gpio_request(GPIO_FN_SDA2, NULL); + gpio_request(GPIO_FN_SCL2, NULL); + gpio_request(GPIO_FN_SDA1, NULL); + gpio_request(GPIO_FN_SCL1, NULL); + gpio_request(GPIO_FN_SDA0, NULL); + gpio_request(GPIO_FN_SCL0, NULL); + + /* USB (PTN) */ + gpio_request(GPIO_FN_VBUS_EN, NULL); + gpio_request(GPIO_FN_VBUS_OC, NULL); + + /* SGPIO1/0 (PTN, PTO) */ + gpio_request(GPIO_FN_SGPIO1_CLK, NULL); + gpio_request(GPIO_FN_SGPIO1_LOAD, NULL); + gpio_request(GPIO_FN_SGPIO1_DI, NULL); + gpio_request(GPIO_FN_SGPIO1_DO, NULL); + gpio_request(GPIO_FN_SGPIO0_CLK, NULL); + gpio_request(GPIO_FN_SGPIO0_LOAD, NULL); + gpio_request(GPIO_FN_SGPIO0_DI, NULL); + gpio_request(GPIO_FN_SGPIO0_DO, NULL); + + /* WDT (PTN) */ + gpio_request(GPIO_FN_SUB_CLKIN, NULL); + + /* System (PTT) */ + gpio_request(GPIO_FN_STATUS1, NULL); + gpio_request(GPIO_FN_STATUS0, NULL); + + /* PWMX (PTT) */ + gpio_request(GPIO_FN_PWMX1, NULL); + gpio_request(GPIO_FN_PWMX0, NULL); + + /* R-SPI (PTV) */ + gpio_request(GPIO_FN_R_SPI_MOSI, NULL); + gpio_request(GPIO_FN_R_SPI_MISO, NULL); + gpio_request(GPIO_FN_R_SPI_RSPCK, NULL); + gpio_request(GPIO_FN_R_SPI_SSL0, NULL); + gpio_request(GPIO_FN_R_SPI_SSL1, NULL); + + /* EVC (PTV, PTW) */ + gpio_request(GPIO_FN_EVENT7, NULL); + gpio_request(GPIO_FN_EVENT6, NULL); + gpio_request(GPIO_FN_EVENT5, NULL); + gpio_request(GPIO_FN_EVENT4, NULL); + gpio_request(GPIO_FN_EVENT3, NULL); + gpio_request(GPIO_FN_EVENT2, NULL); + gpio_request(GPIO_FN_EVENT1, NULL); + gpio_request(GPIO_FN_EVENT0, NULL); + + /* LED for heartbeat */ + gpio_request(GPIO_PTU3, NULL); + gpio_direction_output(GPIO_PTU3, 1); + gpio_request(GPIO_PTU2, NULL); + gpio_direction_output(GPIO_PTU2, 1); + gpio_request(GPIO_PTU1, NULL); + gpio_direction_output(GPIO_PTU1, 1); + gpio_request(GPIO_PTU0, NULL); + gpio_direction_output(GPIO_PTU0, 1); + + /* control for MDIO of Gigabit Ethernet */ + gpio_request(GPIO_PTT4, NULL); + gpio_direction_output(GPIO_PTT4, 1); + + /* control for eMMC */ + gpio_request(GPIO_PTT7, NULL); /* eMMC_RST# */ + gpio_direction_output(GPIO_PTT7, 0); + gpio_request(GPIO_PTT6, NULL); /* eMMC_INDEX# */ + gpio_direction_output(GPIO_PTT6, 0); + gpio_request(GPIO_PTT5, NULL); /* eMMC_PRST# */ + gpio_direction_output(GPIO_PTT5, 1); + + /* General platform */ + return platform_add_devices(sh7757lcr_devices, + ARRAY_SIZE(sh7757lcr_devices)); +} +arch_initcall(sh7757lcr_devices_setup); + +/* Initialize IRQ setting */ +void __init init_sh7757lcr_IRQ(void) +{ + plat_irq_setup_pins(IRQ_MODE_IRQ7654); + plat_irq_setup_pins(IRQ_MODE_IRQ3210); +} + +/* Initialize the board */ +static void __init sh7757lcr_setup(char **cmdline_p) +{ + printk(KERN_INFO "Renesas R0P7757LC0012RL support.\n"); +} + +static int sh7757lcr_mode_pins(void) +{ + int value = 0; + + /* These are the factory default settings of S3 (Low active). + * If you change these dip switches then you will need to + * adjust the values below as well. + */ + value |= MODE_PIN0; /* Clock Mode: 1 */ + + return value; +} + +/* The Machine Vector */ +static struct sh_machine_vector mv_sh7757lcr __initmv = { + .mv_name = "SH7757LCR", + .mv_setup = sh7757lcr_setup, + .mv_init_irq = init_sh7757lcr_IRQ, + .mv_mode_pins = sh7757lcr_mode_pins, +}; + diff --git a/arch/sh/configs/sh7757lcr_defconfig b/arch/sh/configs/sh7757lcr_defconfig new file mode 100644 index 000000000000..635933e76e31 --- /dev/null +++ b/arch/sh/configs/sh7757lcr_defconfig @@ -0,0 +1,1126 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.35-rc3 +# Mon Jul 5 20:42:01 2010 +# +CONFIG_SUPERH=y +CONFIG_SUPERH32=y +# CONFIG_SUPERH64 is not set +CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig" +CONFIG_RWSEM_GENERIC_SPINLOCK=y +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_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +# CONFIG_ARCH_SUSPEND_POSSIBLE is not set +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_SYS_SUPPORTS_TMU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_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_HAS_DEFAULT_IDLE=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_TINY_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y + +# +# GCOV-based kernel profiling +# +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# System type +# +CONFIG_CPU_SH4=y +CONFIG_CPU_SH4A=y +CONFIG_CPU_SHX2=y +# CONFIG_CPU_SUBTYPE_SH7619 is not set +# CONFIG_CPU_SUBTYPE_SH7201 is not set +# CONFIG_CPU_SUBTYPE_SH7203 is not set +# CONFIG_CPU_SUBTYPE_SH7206 is not set +# CONFIG_CPU_SUBTYPE_SH7263 is not set +# CONFIG_CPU_SUBTYPE_MXG is not set +# CONFIG_CPU_SUBTYPE_SH7705 is not set +# CONFIG_CPU_SUBTYPE_SH7706 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7710 is not set +# CONFIG_CPU_SUBTYPE_SH7712 is not set +# CONFIG_CPU_SUBTYPE_SH7720 is not set +# CONFIG_CPU_SUBTYPE_SH7721 is not set +# CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set +# CONFIG_CPU_SUBTYPE_SH7723 is not set +# CONFIG_CPU_SUBTYPE_SH7724 is not set +CONFIG_CPU_SUBTYPE_SH7757=y +# CONFIG_CPU_SUBTYPE_SH7763 is not set +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set +# CONFIG_CPU_SUBTYPE_SH7785 is not set +# CONFIG_CPU_SUBTYPE_SH7786 is not set +# CONFIG_CPU_SUBTYPE_SHX3 is not set +# CONFIG_CPU_SUBTYPE_SH7343 is not set +# CONFIG_CPU_SUBTYPE_SH7722 is not set +# CONFIG_CPU_SUBTYPE_SH7366 is not set + +# +# Memory management options +# +CONFIG_QUICKLIST=y +CONFIG_MMU=y +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_MEMORY_START=0x40000000 +CONFIG_MEMORY_SIZE=0x0f000000 +# CONFIG_29BIT is not set +CONFIG_32BIT=y +CONFIG_PMB=y +CONFIG_X2TLB=y +CONFIG_VSYSCALL=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_MAX_ACTIVE_REGIONS=1 +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_NR_QUICK=1 +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 + +# +# Cache configuration +# +CONFIG_CACHE_WRITEBACK=y +# CONFIG_CACHE_WRITETHROUGH is not set +# CONFIG_CACHE_OFF is not set + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SH_FPU=y +# CONFIG_SH_STORE_QUEUES is not set +CONFIG_CPU_HAS_INTEVT=y +CONFIG_CPU_HAS_SR_RB=y +CONFIG_CPU_HAS_FPU=y + +# +# Board support +# +CONFIG_SH_SH7757LCR=y + +# +# Timer and clock configuration +# +CONFIG_SH_TIMER_TMU=y +CONFIG_SH_CLK_CPG=y +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# DMA support +# +# CONFIG_SH_DMA is not set + +# +# Companion Chips +# + +# +# Additional SuperH Device Drivers +# +CONFIG_HEARTBEAT=y +# CONFIG_PUSH_SWITCH is not set + +# +# Kernel features +# +# CONFIG_HZ_100 is not set +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_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 +CONFIG_GUSA=y +# CONFIG_INTC_USERIMASK is not set + +# +# Boot options +# +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +CONFIG_ENTRY_OFFSET=0x00001000 +CONFIG_CMDLINE_OVERWRITE=y +# CONFIG_CMDLINE_EXTEND is not set +CONFIG_CMDLINE="console=ttySC2,115200 root=/dev/nfs ip=dhcp" + +# +# Bus options +# +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options (EXPERIMENTAL) +# +# CONFIG_PM is not set +# CONFIG_CPU_IDLE is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +CONFIG_VITESSE_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +CONFIG_MDIO_BITBANG=y +# CONFIG_MDIO_GPIO is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_STNIC is not set +CONFIG_SH_ETH=y +# CONFIG_SMC91X is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_NETDEV_1000=y +# CONFIG_NETDEV_10000 is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_SH_KEYSC is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SH_SCI=y +CONFIG_SERIAL_SH_SCI_NR_UARTS=3 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# +# CONFIG_GPIO_IT8761E is not set + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_MFD_SUPPORT=y +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SH_MOBILE_SDHI is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set +# CONFIG_HID_PID is not set + +# +# Special HID drivers +# +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_XATTRS is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=y +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DETECT_SOFTLOCKUP is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_FRAME_POINTER is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_STACK_DEBUG is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_4KSTACKS is not set +# CONFIG_DUMP_CODE is not set +# CONFIG_DWARF_UNWINDER is not set +# CONFIG_SH_NO_BSS_INIT is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_HAVE_LMB=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index 120a211d40a8..9f56eb978024 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -53,6 +53,7 @@ RSK7201 SH_RSK7201 RSK7203 SH_RSK7203 AP325RXA SH_AP325RXA SH2007 SH_SH2007 +SH7757LCR SH_SH7757LCR SH7763RDP SH_SH7763RDP SH7785LCR SH_SH7785LCR SH7785LCR_PT SH_SH7785LCR_PT -- cgit v1.2.3-59-g8ed1b From 25897374297906eeebef8864299406bdcb5859c3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 27 Jul 2010 14:13:13 +0200 Subject: x86-32: Align IRQ stacks properly As suggested by Steven Rostedt we need to align the IRQ stacks to the stack size, not just the page size to make them work for stack traces and other things that depend on finding the stack slot itself with 8k stacks. Signed-off-by: Christoph Hellwig LKML-Reference: <20100727121313.GA19976@lst.de> Signed-off-by: H. Peter Anvin --- arch/x86/kernel/irq_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 67f5f9f5299f..3b5609f54c4b 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -55,7 +55,7 @@ static inline void print_stack_overflow(void) { } union irq_ctx { struct thread_info tinfo; u32 stack[THREAD_SIZE/sizeof(u32)]; -} __attribute__((aligned(PAGE_SIZE))); +} __attribute__((aligned(THREAD_SIZE))); static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx); static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx); -- cgit v1.2.3-59-g8ed1b From 1813a68457bb45b378d5bbec615b167deff3bcfc Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 20 Jul 2010 15:22:54 -0700 Subject: x86: Move alloc_desk_mask variables inside ifdef They are only useful with CONFIG_CPUMASK_OFFSTACK Avoids hundreds of warnings with a gcc 4.6 -Wall build. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index c03243ad84b4..fff1d77c3753 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -439,12 +439,12 @@ extern int set_irq_msi(unsigned int irq, struct msi_desc *entry); static inline bool alloc_desc_masks(struct irq_desc *desc, int node, bool boot) { +#ifdef CONFIG_CPUMASK_OFFSTACK gfp_t gfp = GFP_ATOMIC; if (boot) gfp = GFP_NOWAIT; -#ifdef CONFIG_CPUMASK_OFFSTACK if (!alloc_cpumask_var_node(&desc->affinity, gfp, node)) return false; -- cgit v1.2.3-59-g8ed1b From e9a4c4a1a1ad0ac50a4f6db870f8215272aebca0 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Wed, 28 Jul 2010 13:08:19 +0000 Subject: sh: Add sh7724 BEU resources Signed-off-by: Phil Edworthy Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7724.c | 66 ++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index 79c556e56262..828c9657eb52 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -524,6 +524,70 @@ static struct platform_device veu1_device = { }, }; +/* BEU0 */ +static struct uio_info beu0_platform_data = { + .name = "BEU0", + .version = "0", + .irq = evt2irq(0x8A0), +}; + +static struct resource beu0_resources[] = { + [0] = { + .name = "BEU0", + .start = 0xfe930000, + .end = 0xfe933400, + .flags = IORESOURCE_MEM, + }, + [1] = { + /* place holder for contiguous memory */ + }, +}; + +static struct platform_device beu0_device = { + .name = "uio_pdrv_genirq", + .id = 6, + .dev = { + .platform_data = &beu0_platform_data, + }, + .resource = beu0_resources, + .num_resources = ARRAY_SIZE(beu0_resources), + .archdata = { + .hwblk_id = HWBLK_BEU0, + }, +}; + +/* BEU1 */ +static struct uio_info beu1_platform_data = { + .name = "BEU1", + .version = "0", + .irq = evt2irq(0xA00), +}; + +static struct resource beu1_resources[] = { + [0] = { + .name = "BEU1", + .start = 0xfe940000, + .end = 0xfe943400, + .flags = IORESOURCE_MEM, + }, + [1] = { + /* place holder for contiguous memory */ + }, +}; + +static struct platform_device beu1_device = { + .name = "uio_pdrv_genirq", + .id = 7, + .dev = { + .platform_data = &beu1_platform_data, + }, + .resource = beu1_resources, + .num_resources = ARRAY_SIZE(beu1_resources), + .archdata = { + .hwblk_id = HWBLK_BEU1, + }, +}; + static struct sh_timer_config cmt_platform_data = { .channel_offset = 0x60, .timer_bit = 5, @@ -857,6 +921,8 @@ static struct platform_device *sh7724_devices[] __initdata = { &vpu_device, &veu0_device, &veu1_device, + &beu0_device, + &beu1_device, &jpu_device, &spu0_device, &spu1_device, -- cgit v1.2.3-59-g8ed1b From 7b42176a2969bc913cd2949e7edd935466745b11 Mon Sep 17 00:00:00 2001 From: Markus Pietrek Date: Wed, 4 Aug 2010 15:59:50 +0900 Subject: sound/soc/sh/siu: Fixed undefined dma_length of scatter gather list Without this patch, an undefined/random sg->dma_length is used and the sound will be played/captured wrongly. Signed-off-by: Markus Pietrek Signed-off-by: Paul Mundt --- sound/soc/sh/siu_pcm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 36170be15aa7..b0ccd0b862fc 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -127,6 +127,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info, sg_init_table(&sg, 1); sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)), size, offset_in_page(buff)); + sg_dma_len(&sg) = size; sg_dma_address(&sg) = buff; desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan, @@ -176,6 +177,7 @@ static int siu_pcm_rd_set(struct siu_port *port_info, sg_init_table(&sg, 1); sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)), size, offset_in_page(buff)); + sg_dma_len(&sg) = size; sg_dma_address(&sg) = buff; desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan, -- cgit v1.2.3-59-g8ed1b From 43809473b9d5fa9f82bf64ddeb3c21fe1140ef0e Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 4 Aug 2010 04:31:38 +0000 Subject: clocksource: sh_cmt: One-off clockevent fix V2 Fix a one-off error in the CMT driver V2. The match register should be programmed with the period minus one. Many thanks to Eiraku-san for tracking down this issue. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/clocksource/sh_cmt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 717305d30444..ed8e07b97e27 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -308,7 +308,7 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) * isr before we end up here. */ if (p->flags & FLAG_CLOCKSOURCE) - p->total_cycles += p->match_value; + p->total_cycles += p->match_value + 1; if (!(p->flags & FLAG_REPROGRAM)) p->next_match_value = p->max_match_value; @@ -403,7 +403,7 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs) raw = sh_cmt_get_counter(p, &has_wrapped); if (unlikely(has_wrapped)) - raw += p->match_value; + raw += p->match_value + 1; spin_unlock_irqrestore(&p->lock, flags); return value + raw; @@ -478,7 +478,7 @@ static void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic) ced->min_delta_ns = clockevent_delta2ns(0x1f, ced); if (periodic) - sh_cmt_set_next(p, (p->rate + HZ/2) / HZ); + sh_cmt_set_next(p, ((p->rate + HZ/2) / HZ) - 1); else sh_cmt_set_next(p, p->max_match_value); } @@ -523,9 +523,9 @@ static int sh_cmt_clock_event_next(unsigned long delta, BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT); if (likely(p->flags & FLAG_IRQCONTEXT)) - p->next_match_value = delta; + p->next_match_value = delta - 1; else - sh_cmt_set_next(p, delta); + sh_cmt_set_next(p, delta - 1); return 0; } -- cgit v1.2.3-59-g8ed1b From 38409d726bc6413d39f082f60bc803f52d8b5849 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 2 Aug 2010 09:24:05 +0000 Subject: clocksource: sh_cmt: Rate calculation fix Fix the rate calculation in the CMT driver. Without this fix the clocksource runs way too fast and we get a divide-by-zero error. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/clocksource/sh_cmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index ed8e07b97e27..a44611652282 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -445,7 +445,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p, /* clk_get_rate() needs an enabled clock */ clk_enable(p->clk); - p->rate = clk_get_rate(p->clk) / (p->width == 16) ? 512 : 8; + p->rate = clk_get_rate(p->clk) / ((p->width == 16) ? 512 : 8); clk_disable(p->clk); /* TODO: calculate good shift from rate and counter bit width */ -- cgit v1.2.3-59-g8ed1b From 32dfab3ced3a3d2bb0ac2ed6fd7ac395edf02e88 Mon Sep 17 00:00:00 2001 From: Kulikov Vasiliy Date: Wed, 28 Jul 2010 16:39:26 +0000 Subject: sh: dma: check return value of create_proc_read_entry() create_proc_read_entry() may fail, if so return -ENOMEM. Signed-off-by: Kulikov Vasiliy Signed-off-by: Paul Mundt --- arch/sh/drivers/dma/dma-api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c index 4a277224a871..f46848f088e4 100644 --- a/arch/sh/drivers/dma/dma-api.c +++ b/arch/sh/drivers/dma/dma-api.c @@ -412,8 +412,8 @@ EXPORT_SYMBOL(unregister_dmac); static int __init dma_api_init(void) { printk(KERN_NOTICE "DMA: Registering DMA API.\n"); - create_proc_read_entry("dma", 0, 0, dma_read_proc, 0); - return 0; + return create_proc_read_entry("dma", 0, 0, dma_read_proc, 0) + ? 0 : -ENOMEM; } subsys_initcall(dma_api_init); -- cgit v1.2.3-59-g8ed1b From 82b20d8bae03406e954d8b7d0f6f734967088b17 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 2 Aug 2010 07:16:37 +0000 Subject: i2c: i2c-sh_mobile irq rollback fix Update the i2c-sh_mobile driver to properly free interrupts. The function sh_mobile_i2c_hook_irqs() is fixed so module both unload and load are working as expected. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/i2c/busses/i2c-sh_mobile.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index ffb405d7c6f2..97b84b80d0ff 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -497,15 +497,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook) { struct resource *res; int ret = -ENXIO; - int q, m; - int k = 0; - int n = 0; + int n, k = 0; while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) { for (n = res->start; hook && n <= res->end; n++) { if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED, - dev_name(&dev->dev), dev)) + dev_name(&dev->dev), dev)) { + for (n--; n >= res->start; n--) + free_irq(n, dev); + goto rollback; + } } k++; } @@ -513,16 +515,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook) if (hook) return k > 0 ? 0 : -ENOENT; - k--; ret = 0; rollback: - for (q = k; k >= 0; k--) { - for (m = n; m >= res->start; m--) - free_irq(m, dev); + k--; + + while (k >= 0) { + res = platform_get_resource(dev, IORESOURCE_IRQ, k); + for (n = res->start; n <= res->end; n++) + free_irq(n, dev); - res = platform_get_resource(dev, IORESOURCE_IRQ, k - 1); - m = res->end; + k--; } return ret; -- cgit v1.2.3-59-g8ed1b From 57682827b9a5edb52e33af0be9082b51bffcd5c7 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 4 Aug 2010 16:38:35 +0900 Subject: sh: Use __GFP_ZERO for dma_generic_alloc_coherent(). This follows the x86 change off of memset() and on to an unconditional __GFP_ZERO for wrapping in to optimized page clearing by way of clear_highpage(). Signed-off-by: Andrew Murray Signed-off-by: Paul Mundt --- arch/sh/mm/consistent.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index c86a08540258..038793286990 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -38,11 +38,12 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, void *ret, *ret_nocache; int order = get_order(size); + gfp |= __GFP_ZERO; + ret = (void *)__get_free_pages(gfp, order); if (!ret) return NULL; - memset(ret, 0, size); /* * Pages from the page allocator may have data present in * cache. So flush the cache before using uncached memory. -- cgit v1.2.3-59-g8ed1b From 9a76f1ff6e299fbb04149fe15aff061351fd0dab Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Aug 2010 13:20:59 +0100 Subject: ASoC: Add initial WM8962 CODEC driver The WM8962 is a low power, high performance stereo CODEC designed for portable digital audio applications. This initial driver release supports the key audio paths of the WM8962. Extended functionality, such as microphone detection, digital microphones and the advanced DSP signal enhancements provided by the device are not yet supported. Signed-off-by: Mark Brown --- include/sound/wm8962.h | 23 + sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/wm8962-tables.c | 42299 +++++++++++++++++++++++++++++++++++++ sound/soc/codecs/wm8962.c | 1933 ++ sound/soc/codecs/wm8962.h | 3790 ++++ 6 files changed, 48051 insertions(+) create mode 100644 include/sound/wm8962.h create mode 100644 sound/soc/codecs/wm8962-tables.c create mode 100644 sound/soc/codecs/wm8962.c create mode 100644 sound/soc/codecs/wm8962.h diff --git a/include/sound/wm8962.h b/include/sound/wm8962.h new file mode 100644 index 000000000000..f70258e3471c --- /dev/null +++ b/include/sound/wm8962.h @@ -0,0 +1,23 @@ +/* + * wm8962.h -- WM8962 Soc Audio driver platform data + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _WM8962_PDATA_H +#define _WM8962_PDATA_H + +#define WM8962_MAX_GPIO 6 + +/* Use to set GPIO default values to zero */ +#define WM8962_GPIO_SET 0x10000 + +struct wm8962_pdata { + u32 gpio_init[WM8962_MAX_GPIO]; + + bool spk_mono; /* Speaker outputs tied together as mono */ +}; + +#endif diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 83f5c67d3c41..bfdd92b78fb6 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -61,6 +61,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8955 if I2C select SND_SOC_WM8960 if I2C select SND_SOC_WM8961 if I2C + select SND_SOC_WM8962 if I2C select SND_SOC_WM8971 if I2C select SND_SOC_WM8974 if I2C select SND_SOC_WM8978 if I2C @@ -248,6 +249,9 @@ config SND_SOC_WM8960 config SND_SOC_WM8961 tristate +config SND_SOC_WM8962 + tristate + config SND_SOC_WM8971 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 53524095759c..9c3c39fd99ad 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -46,6 +46,7 @@ snd-soc-wm8940-objs := wm8940.o snd-soc-wm8955-objs := wm8955.o snd-soc-wm8960-objs := wm8960.o snd-soc-wm8961-objs := wm8961.o +snd-soc-wm8962-objs := wm8962.o wm8962-tables.o snd-soc-wm8971-objs := wm8971.o snd-soc-wm8974-objs := wm8974.o snd-soc-wm8978-objs := wm8978.o @@ -115,6 +116,7 @@ obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o obj-$(CONFIG_SND_SOC_WM8955) += snd-soc-wm8955.o obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o +obj-$(CONFIG_SND_SOC_WM8962) += snd-soc-wm8962.o obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o diff --git a/sound/soc/codecs/wm8962-tables.c b/sound/soc/codecs/wm8962-tables.c new file mode 100644 index 000000000000..f21a8c1b9d47 --- /dev/null +++ b/sound/soc/codecs/wm8962-tables.c @@ -0,0 +1,42299 @@ +/* + * wm8962-tables.c -- WM8962 ASoC driver + * + * Copyright 2010 Wolfson Microelectronics, plc + * + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "wm8962.h" + +const u16 wm8962_reg[WM8962_MAX_REGISTER + 1] = { + 0x009F, /* R0 - Left Input volume */ + 0x049F, /* R1 - Right Input volume */ + 0x0000, /* R2 - HPOUTL volume */ + 0x0000, /* R3 - HPOUTR volume */ + 0x0020, /* R4 - Clocking1 */ + 0x0018, /* R5 - ADC & DAC Control 1 */ + 0x2008, /* R6 - ADC & DAC Control 2 */ + 0x000A, /* R7 - Audio Interface 0 */ + 0x01E4, /* R8 - Clocking2 */ + 0x0300, /* R9 - Audio Interface 1 */ + 0x00C0, /* R10 - Left DAC volume */ + 0x00C0, /* R11 - Right DAC volume */ + 0x0000, /* R12 */ + 0x0000, /* R13 */ + 0x0040, /* R14 - Audio Interface 2 */ + 0x6243, /* R15 - Software Reset */ + 0x0000, /* R16 */ + 0x007B, /* R17 - ALC1 */ + 0x0000, /* R18 - ALC2 */ + 0x1C32, /* R19 - ALC3 */ + 0x3200, /* R20 - Noise Gate */ + 0x00C0, /* R21 - Left ADC volume */ + 0x00C0, /* R22 - Right ADC volume */ + 0x0160, /* R23 - Additional control(1) */ + 0x0000, /* R24 - Additional control(2) */ + 0x0000, /* R25 - Pwr Mgmt (1) */ + 0x0000, /* R26 - Pwr Mgmt (2) */ + 0x0010, /* R27 - Additional Control (3) */ + 0x0000, /* R28 - Anti-pop */ + 0x0000, /* R29 */ + 0x005E, /* R30 - Clocking 3 */ + 0x0000, /* R31 - Input mixer control (1) */ + 0x0145, /* R32 - Left input mixer volume */ + 0x0145, /* R33 - Right input mixer volume */ + 0x0009, /* R34 - Input mixer control (2) */ + 0x0003, /* R35 - Input bias control */ + 0x0000, /* R36 */ + 0x0008, /* R37 - Left input PGA control */ + 0x0008, /* R38 - Right input PGA control */ + 0x0000, /* R39 */ + 0x0000, /* R40 - SPKOUTL volume */ + 0x0000, /* R41 - SPKOUTR volume */ + 0x0000, /* R42 */ + 0x0000, /* R43 */ + 0x0000, /* R44 */ + 0x0000, /* R45 */ + 0x0000, /* R46 */ + 0x0000, /* R47 - Thermal Shutdown Status */ + 0x8027, /* R48 - Additional Control (4) */ + 0x0010, /* R49 - Class D Control 1 */ + 0x0000, /* R50 */ + 0x0003, /* R51 - Class D Control 2 */ + 0x0000, /* R52 */ + 0x0000, /* R53 */ + 0x0000, /* R54 */ + 0x0000, /* R55 */ + 0x0506, /* R56 - Clocking 4 */ + 0x0000, /* R57 - DAC DSP Mixing (1) */ + 0x0000, /* R58 - DAC DSP Mixing (2) */ + 0x0000, /* R59 */ + 0x0300, /* R60 - DC Servo 0 */ + 0x0300, /* R61 - DC Servo 1 */ + 0x0000, /* R62 */ + 0x0000, /* R63 */ + 0x0810, /* R64 - DC Servo 4 */ + 0x0000, /* R65 */ + 0x0000, /* R66 - DC Servo 6 */ + 0x0000, /* R67 */ + 0x001B, /* R68 - Analogue PGA Bias */ + 0x0000, /* R69 - Analogue HP 0 */ + 0x0000, /* R70 */ + 0x01FB, /* R71 - Analogue HP 2 */ + 0x0000, /* R72 - Charge Pump 1 */ + 0x0000, /* R73 */ + 0x0000, /* R74 */ + 0x0000, /* R75 */ + 0x0000, /* R76 */ + 0x0000, /* R77 */ + 0x0000, /* R78 */ + 0x0000, /* R79 */ + 0x0000, /* R80 */ + 0x0000, /* R81 */ + 0x0004, /* R82 - Charge Pump B */ + 0x0000, /* R83 */ + 0x0000, /* R84 */ + 0x0000, /* R85 */ + 0x0000, /* R86 */ + 0x0000, /* R87 - Write Sequencer Control 1 */ + 0x0000, /* R88 */ + 0x0000, /* R89 */ + 0x0000, /* R90 - Write Sequencer Control 2 */ + 0x0000, /* R91 */ + 0x0000, /* R92 */ + 0x0000, /* R93 - Write Sequencer Control 3 */ + 0x0000, /* R94 - Control Interface */ + 0x0000, /* R95 */ + 0x0000, /* R96 */ + 0x0000, /* R97 */ + 0x0000, /* R98 */ + 0x0000, /* R99 - Mixer Enables */ + 0x0000, /* R100 - Headphone Mixer (1) */ + 0x0000, /* R101 - Headphone Mixer (2) */ + 0x013F, /* R102 - Headphone Mixer (3) */ + 0x013F, /* R103 - Headphone Mixer (4) */ + 0x0000, /* R104 */ + 0x0000, /* R105 - Speaker Mixer (1) */ + 0x0000, /* R106 - Speaker Mixer (2) */ + 0x013F, /* R107 - Speaker Mixer (3) */ + 0x013F, /* R108 - Speaker Mixer (4) */ + 0x0003, /* R109 - Speaker Mixer (5) */ + 0x0002, /* R110 - Beep Generator (1) */ + 0x0000, /* R111 */ + 0x0000, /* R112 */ + 0x0000, /* R113 */ + 0x0000, /* R114 */ + 0x0006, /* R115 - Oscillator Trim (3) */ + 0x0026, /* R116 - Oscillator Trim (4) */ + 0x0000, /* R117 */ + 0x0000, /* R118 */ + 0x0000, /* R119 - Oscillator Trim (7) */ + 0x0000, /* R120 */ + 0x0000, /* R121 */ + 0x0000, /* R122 */ + 0x0000, /* R123 */ + 0x0011, /* R124 - Analogue Clocking1 */ + 0x004B, /* R125 - Analogue Clocking2 */ + 0x000D, /* R126 - Analogue Clocking3 */ + 0x0000, /* R127 - PLL Software Reset */ + 0x0000, /* R128 */ + 0x0000, /* R129 - PLL2 */ + 0x0000, /* R130 */ + 0x0000, /* R131 - PLL 4 */ + 0x0000, /* R132 */ + 0x0000, /* R133 */ + 0x0000, /* R134 */ + 0x0000, /* R135 */ + 0x0067, /* R136 - PLL 9 */ + 0x001C, /* R137 - PLL 10 */ + 0x0071, /* R138 - PLL 11 */ + 0x00C7, /* R139 - PLL 12 */ + 0x0067, /* R140 - PLL 13 */ + 0x0048, /* R141 - PLL 14 */ + 0x0022, /* R142 - PLL 15 */ + 0x0097, /* R143 - PLL 16 */ + 0x0000, /* R144 */ + 0x0000, /* R145 */ + 0x0000, /* R146 */ + 0x0000, /* R147 */ + 0x0000, /* R148 */ + 0x0000, /* R149 */ + 0x0000, /* R150 */ + 0x0000, /* R151 */ + 0x0000, /* R152 */ + 0x0000, /* R153 */ + 0x0000, /* R154 */ + 0x000C, /* R155 - FLL Control (1) */ + 0x0039, /* R156 - FLL Control (2) */ + 0x0180, /* R157 - FLL Control (3) */ + 0x0000, /* R158 */ + 0x0032, /* R159 - FLL Control (5) */ + 0x0018, /* R160 - FLL Control (6) */ + 0x007D, /* R161 - FLL Control (7) */ + 0x0008, /* R162 - FLL Control (8) */ + 0x0000, /* R163 */ + 0x0000, /* R164 */ + 0x0000, /* R165 */ + 0x0000, /* R166 */ + 0x0000, /* R167 */ + 0x0000, /* R168 */ + 0x0000, /* R169 */ + 0x0000, /* R170 */ + 0x0000, /* R171 */ + 0x0000, /* R172 */ + 0x0000, /* R173 */ + 0x0000, /* R174 */ + 0x0000, /* R175 */ + 0x0000, /* R176 */ + 0x0000, /* R177 */ + 0x0000, /* R178 */ + 0x0000, /* R179 */ + 0x0000, /* R180 */ + 0x0000, /* R181 */ + 0x0000, /* R182 */ + 0x0000, /* R183 */ + 0x0000, /* R184 */ + 0x0000, /* R185 */ + 0x0000, /* R186 */ + 0x0000, /* R187 */ + 0x0000, /* R188 */ + 0x0000, /* R189 */ + 0x0000, /* R190 */ + 0x0000, /* R191 */ + 0x0000, /* R192 */ + 0x0000, /* R193 */ + 0x0000, /* R194 */ + 0x0000, /* R195 */ + 0x0000, /* R196 */ + 0x0000, /* R197 */ + 0x0000, /* R198 */ + 0x0000, /* R199 */ + 0x0000, /* R200 */ + 0x0000, /* R201 */ + 0x0000, /* R202 */ + 0x0000, /* R203 */ + 0x0000, /* R204 */ + 0x0000, /* R205 */ + 0x0000, /* R206 */ + 0x0000, /* R207 */ + 0x0000, /* R208 */ + 0x0000, /* R209 */ + 0x0000, /* R210 */ + 0x0000, /* R211 */ + 0x0000, /* R212 */ + 0x0000, /* R213 */ + 0x0000, /* R214 */ + 0x0000, /* R215 */ + 0x0000, /* R216 */ + 0x0000, /* R217 */ + 0x0000, /* R218 */ + 0x0000, /* R219 */ + 0x0000, /* R220 */ + 0x0000, /* R221 */ + 0x0000, /* R222 */ + 0x0000, /* R223 */ + 0x0000, /* R224 */ + 0x0000, /* R225 */ + 0x0000, /* R226 */ + 0x0000, /* R227 */ + 0x0000, /* R228 */ + 0x0000, /* R229 */ + 0x0000, /* R230 */ + 0x0000, /* R231 */ + 0x0000, /* R232 */ + 0x0000, /* R233 */ + 0x0000, /* R234 */ + 0x0000, /* R235 */ + 0x0000, /* R236 */ + 0x0000, /* R237 */ + 0x0000, /* R238 */ + 0x0000, /* R239 */ + 0x0000, /* R240 */ + 0x0000, /* R241 */ + 0x0000, /* R242 */ + 0x0000, /* R243 */ + 0x0000, /* R244 */ + 0x0000, /* R245 */ + 0x0000, /* R246 */ + 0x0000, /* R247 */ + 0x0000, /* R248 */ + 0x0000, /* R249 */ + 0x0000, /* R250 */ + 0x0000, /* R251 */ + 0x0005, /* R252 - General test 1 */ + 0x0000, /* R253 */ + 0x0000, /* R254 */ + 0x0000, /* R255 */ + 0x0000, /* R256 - DF1 */ + 0x0000, /* R257 - DF2 */ + 0x0000, /* R258 - DF3 */ + 0x0000, /* R259 - DF4 */ + 0x0000, /* R260 - DF5 */ + 0x0000, /* R261 - DF6 */ + 0x0000, /* R262 - DF7 */ + 0x0000, /* R263 */ + 0x0000, /* R264 - LHPF1 */ + 0x0000, /* R265 - LHPF2 */ + 0x0000, /* R266 */ + 0x0000, /* R267 */ + 0x0000, /* R268 - THREED1 */ + 0x0000, /* R269 - THREED2 */ + 0x0000, /* R270 - THREED3 */ + 0x0000, /* R271 - THREED4 */ + 0x0000, /* R272 */ + 0x0000, /* R273 */ + 0x0000, /* R274 */ + 0x0000, /* R275 */ + 0x000C, /* R276 - DRC 1 */ + 0x0925, /* R277 - DRC 2 */ + 0x0000, /* R278 - DRC 3 */ + 0x0000, /* R279 - DRC 4 */ + 0x0000, /* R280 - DRC 5 */ + 0x0000, /* R281 */ + 0x0000, /* R282 */ + 0x0000, /* R283 */ + 0x0000, /* R284 */ + 0x0000, /* R285 - Tloopback */ + 0x0000, /* R286 */ + 0x0000, /* R287 */ + 0x0000, /* R288 */ + 0x0000, /* R289 */ + 0x0000, /* R290 */ + 0x0000, /* R291 */ + 0x0000, /* R292 */ + 0x0000, /* R293 */ + 0x0000, /* R294 */ + 0x0000, /* R295 */ + 0x0000, /* R296 */ + 0x0000, /* R297 */ + 0x0000, /* R298 */ + 0x0000, /* R299 */ + 0x0000, /* R300 */ + 0x0000, /* R301 */ + 0x0000, /* R302 */ + 0x0000, /* R303 */ + 0x0000, /* R304 */ + 0x0000, /* R305 */ + 0x0000, /* R306 */ + 0x0000, /* R307 */ + 0x0000, /* R308 */ + 0x0000, /* R309 */ + 0x0000, /* R310 */ + 0x0000, /* R311 */ + 0x0000, /* R312 */ + 0x0000, /* R313 */ + 0x0000, /* R314 */ + 0x0000, /* R315 */ + 0x0000, /* R316 */ + 0x0000, /* R317 */ + 0x0000, /* R318 */ + 0x0000, /* R319 */ + 0x0000, /* R320 */ + 0x0000, /* R321 */ + 0x0000, /* R322 */ + 0x0000, /* R323 */ + 0x0000, /* R324 */ + 0x0000, /* R325 */ + 0x0000, /* R326 */ + 0x0000, /* R327 */ + 0x0000, /* R328 */ + 0x0000, /* R329 */ + 0x0000, /* R330 */ + 0x0000, /* R331 */ + 0x0000, /* R332 */ + 0x0000, /* R333 */ + 0x0000, /* R334 */ + 0x0004, /* R335 - EQ1 */ + 0x6318, /* R336 - EQ2 */ + 0x6300, /* R337 - EQ3 */ + 0x0FCA, /* R338 - EQ4 */ + 0x0400, /* R339 - EQ5 */ + 0x00D8, /* R340 - EQ6 */ + 0x1EB5, /* R341 - EQ7 */ + 0xF145, /* R342 - EQ8 */ + 0x0B75, /* R343 - EQ9 */ + 0x01C5, /* R344 - EQ10 */ + 0x1C58, /* R345 - EQ11 */ + 0xF373, /* R346 - EQ12 */ + 0x0A54, /* R347 - EQ13 */ + 0x0558, /* R348 - EQ14 */ + 0x168E, /* R349 - EQ15 */ + 0xF829, /* R350 - EQ16 */ + 0x07AD, /* R351 - EQ17 */ + 0x1103, /* R352 - EQ18 */ + 0x0564, /* R353 - EQ19 */ + 0x0559, /* R354 - EQ20 */ + 0x4000, /* R355 - EQ21 */ + 0x6318, /* R356 - EQ22 */ + 0x6300, /* R357 - EQ23 */ + 0x0FCA, /* R358 - EQ24 */ + 0x0400, /* R359 - EQ25 */ + 0x00D8, /* R360 - EQ26 */ + 0x1EB5, /* R361 - EQ27 */ + 0xF145, /* R362 - EQ28 */ + 0x0B75, /* R363 - EQ29 */ + 0x01C5, /* R364 - EQ30 */ + 0x1C58, /* R365 - EQ31 */ + 0xF373, /* R366 - EQ32 */ + 0x0A54, /* R367 - EQ33 */ + 0x0558, /* R368 - EQ34 */ + 0x168E, /* R369 - EQ35 */ + 0xF829, /* R370 - EQ36 */ + 0x07AD, /* R371 - EQ37 */ + 0x1103, /* R372 - EQ38 */ + 0x0564, /* R373 - EQ39 */ + 0x0559, /* R374 - EQ40 */ + 0x4000, /* R375 - EQ41 */ + 0x0000, /* R376 */ + 0x0000, /* R377 */ + 0x0000, /* R378 */ + 0x0000, /* R379 */ + 0x0000, /* R380 */ + 0x0000, /* R381 */ + 0x0000, /* R382 */ + 0x0000, /* R383 */ + 0x0000, /* R384 */ + 0x0000, /* R385 */ + 0x0000, /* R386 */ + 0x0000, /* R387 */ + 0x0000, /* R388 */ + 0x0000, /* R389 */ + 0x0000, /* R390 */ + 0x0000, /* R391 */ + 0x0000, /* R392 */ + 0x0000, /* R393 */ + 0x0000, /* R394 */ + 0x0000, /* R395 */ + 0x0000, /* R396 */ + 0x0000, /* R397 */ + 0x0000, /* R398 */ + 0x0000, /* R399 */ + 0x0000, /* R400 */ + 0x0000, /* R401 */ + 0x0000, /* R402 */ + 0x0000, /* R403 */ + 0x0000, /* R404 */ + 0x0000, /* R405 */ + 0x0000, /* R406 */ + 0x0000, /* R407 */ + 0x0000, /* R408 */ + 0x0000, /* R409 */ + 0x0000, /* R410 */ + 0x0000, /* R411 */ + 0x0000, /* R412 */ + 0x0000, /* R413 */ + 0x0000, /* R414 */ + 0x0000, /* R415 */ + 0x0000, /* R416 */ + 0x0000, /* R417 */ + 0x0000, /* R418 */ + 0x0000, /* R419 */ + 0x0000, /* R420 */ + 0x0000, /* R421 */ + 0x0000, /* R422 */ + 0x0000, /* R423 */ + 0x0000, /* R424 */ + 0x0000, /* R425 */ + 0x0000, /* R426 */ + 0x0000, /* R427 */ + 0x0000, /* R428 */ + 0x0000, /* R429 */ + 0x0000, /* R430 */ + 0x0000, /* R431 */ + 0x0000, /* R432 */ + 0x0000, /* R433 */ + 0x0000, /* R434 */ + 0x0000, /* R435 */ + 0x0000, /* R436 */ + 0x0000, /* R437 */ + 0x0000, /* R438 */ + 0x0000, /* R439 */ + 0x0000, /* R440 */ + 0x0000, /* R441 */ + 0x0000, /* R442 */ + 0x0000, /* R443 */ + 0x0000, /* R444 */ + 0x0000, /* R445 */ + 0x0000, /* R446 */ + 0x0000, /* R447 */ + 0x0000, /* R448 */ + 0x0000, /* R449 */ + 0x0000, /* R450 */ + 0x0000, /* R451 */ + 0x0000, /* R452 */ + 0x0000, /* R453 */ + 0x0000, /* R454 */ + 0x0000, /* R455 */ + 0x0000, /* R456 */ + 0x0000, /* R457 */ + 0x0000, /* R458 */ + 0x0000, /* R459 */ + 0x0000, /* R460 */ + 0x0000, /* R461 */ + 0x0000, /* R462 */ + 0x0000, /* R463 */ + 0x0000, /* R464 */ + 0x0000, /* R465 */ + 0x0000, /* R466 */ + 0x0000, /* R467 */ + 0x0000, /* R468 */ + 0x0000, /* R469 */ + 0x0000, /* R470 */ + 0x0000, /* R471 */ + 0x0000, /* R472 */ + 0x0000, /* R473 */ + 0x0000, /* R474 */ + 0x0000, /* R475 */ + 0x0000, /* R476 */ + 0x0000, /* R477 */ + 0x0000, /* R478 */ + 0x0000, /* R479 */ + 0x0000, /* R480 */ + 0x0000, /* R481 */ + 0x0000, /* R482 */ + 0x0000, /* R483 */ + 0x0000, /* R484 */ + 0x0000, /* R485 */ + 0x0000, /* R486 */ + 0x0000, /* R487 */ + 0x0000, /* R488 */ + 0x0000, /* R489 */ + 0x0000, /* R490 */ + 0x0000, /* R491 */ + 0x0000, /* R492 */ + 0x0000, /* R493 */ + 0x0000, /* R494 */ + 0x0000, /* R495 */ + 0x0000, /* R496 */ + 0x0000, /* R497 */ + 0x0000, /* R498 */ + 0x0000, /* R499 */ + 0x0000, /* R500 */ + 0x0000, /* R501 */ + 0x0000, /* R502 */ + 0x0000, /* R503 */ + 0x0000, /* R504 */ + 0x0000, /* R505 */ + 0x0000, /* R506 */ + 0x0000, /* R507 */ + 0x0000, /* R508 */ + 0x0000, /* R509 */ + 0x0000, /* R510 */ + 0x0000, /* R511 */ + 0x0000, /* R512 */ + 0x0000, /* R513 - GPIO 2 */ + 0x0000, /* R514 - GPIO 3 */ + 0x0000, /* R515 */ + 0x8100, /* R516 - GPIO 5 */ + 0x8100, /* R517 - GPIO 6 */ + 0x0000, /* R518 */ + 0x0000, /* R519 */ + 0x0000, /* R520 */ + 0x0000, /* R521 */ + 0x0000, /* R522 */ + 0x0000, /* R523 */ + 0x0000, /* R524 */ + 0x0000, /* R525 */ + 0x0000, /* R526 */ + 0x0000, /* R527 */ + 0x0000, /* R528 */ + 0x0000, /* R529 */ + 0x0000, /* R530 */ + 0x0000, /* R531 */ + 0x0000, /* R532 */ + 0x0000, /* R533 */ + 0x0000, /* R534 */ + 0x0000, /* R535 */ + 0x0000, /* R536 */ + 0x0000, /* R537 */ + 0x0000, /* R538 */ + 0x0000, /* R539 */ + 0x0000, /* R540 */ + 0x0000, /* R541 */ + 0x0000, /* R542 */ + 0x0000, /* R543 */ + 0x0000, /* R544 */ + 0x0000, /* R545 */ + 0x0000, /* R546 */ + 0x0000, /* R547 */ + 0x0000, /* R548 */ + 0x0000, /* R549 */ + 0x0000, /* R550 */ + 0x0000, /* R551 */ + 0x0000, /* R552 */ + 0x0000, /* R553 */ + 0x0000, /* R554 */ + 0x0000, /* R555 */ + 0x0000, /* R556 */ + 0x0000, /* R557 */ + 0x0000, /* R558 */ + 0x0000, /* R559 */ + 0x0000, /* R560 - Interrupt Status 1 */ + 0x0000, /* R561 - Interrupt Status 2 */ + 0x0000, /* R562 */ + 0x0000, /* R563 */ + 0x0000, /* R564 */ + 0x0000, /* R565 */ + 0x0000, /* R566 */ + 0x0000, /* R567 */ + 0x0030, /* R568 - Interrupt Status 1 Mask */ + 0xFFED, /* R569 - Interrupt Status 2 Mask */ + 0x0000, /* R570 */ + 0x0000, /* R571 */ + 0x0000, /* R572 */ + 0x0000, /* R573 */ + 0x0000, /* R574 */ + 0x0000, /* R575 */ + 0x0000, /* R576 - Interrupt Control */ + 0x0000, /* R577 */ + 0x0000, /* R578 */ + 0x0000, /* R579 */ + 0x0000, /* R580 */ + 0x0000, /* R581 */ + 0x0000, /* R582 */ + 0x0000, /* R583 */ + 0x002D, /* R584 - IRQ Debounce */ + 0x0000, /* R585 */ + 0x0000, /* R586 - MICINT Source Pol */ + 0x0000, /* R587 */ + 0x0000, /* R588 */ + 0x0000, /* R589 */ + 0x0000, /* R590 */ + 0x0000, /* R591 */ + 0x0000, /* R592 */ + 0x0000, /* R593 */ + 0x0000, /* R594 */ + 0x0000, /* R595 */ + 0x0000, /* R596 */ + 0x0000, /* R597 */ + 0x0000, /* R598 */ + 0x0000, /* R599 */ + 0x0000, /* R600 */ + 0x0000, /* R601 */ + 0x0000, /* R602 */ + 0x0000, /* R603 */ + 0x0000, /* R604 */ + 0x0000, /* R605 */ + 0x0000, /* R606 */ + 0x0000, /* R607 */ + 0x0000, /* R608 */ + 0x0000, /* R609 */ + 0x0000, /* R610 */ + 0x0000, /* R611 */ + 0x0000, /* R612 */ + 0x0000, /* R613 */ + 0x0000, /* R614 */ + 0x0000, /* R615 */ + 0x0000, /* R616 */ + 0x0000, /* R617 */ + 0x0000, /* R618 */ + 0x0000, /* R619 */ + 0x0000, /* R620 */ + 0x0000, /* R621 */ + 0x0000, /* R622 */ + 0x0000, /* R623 */ + 0x0000, /* R624 */ + 0x0000, /* R625 */ + 0x0000, /* R626 */ + 0x0000, /* R627 */ + 0x0000, /* R628 */ + 0x0000, /* R629 */ + 0x0000, /* R630 */ + 0x0000, /* R631 */ + 0x0000, /* R632 */ + 0x0000, /* R633 */ + 0x0000, /* R634 */ + 0x0000, /* R635 */ + 0x0000, /* R636 */ + 0x0000, /* R637 */ + 0x0000, /* R638 */ + 0x0000, /* R639 */ + 0x0000, /* R640 */ + 0x0000, /* R641 */ + 0x0000, /* R642 */ + 0x0000, /* R643 */ + 0x0000, /* R644 */ + 0x0000, /* R645 */ + 0x0000, /* R646 */ + 0x0000, /* R647 */ + 0x0000, /* R648 */ + 0x0000, /* R649 */ + 0x0000, /* R650 */ + 0x0000, /* R651 */ + 0x0000, /* R652 */ + 0x0000, /* R653 */ + 0x0000, /* R654 */ + 0x0000, /* R655 */ + 0x0000, /* R656 */ + 0x0000, /* R657 */ + 0x0000, /* R658 */ + 0x0000, /* R659 */ + 0x0000, /* R660 */ + 0x0000, /* R661 */ + 0x0000, /* R662 */ + 0x0000, /* R663 */ + 0x0000, /* R664 */ + 0x0000, /* R665 */ + 0x0000, /* R666 */ + 0x0000, /* R667 */ + 0x0000, /* R668 */ + 0x0000, /* R669 */ + 0x0000, /* R670 */ + 0x0000, /* R671 */ + 0x0000, /* R672 */ + 0x0000, /* R673 */ + 0x0000, /* R674 */ + 0x0000, /* R675 */ + 0x0000, /* R676 */ + 0x0000, /* R677 */ + 0x0000, /* R678 */ + 0x0000, /* R679 */ + 0x0000, /* R680 */ + 0x0000, /* R681 */ + 0x0000, /* R682 */ + 0x0000, /* R683 */ + 0x0000, /* R684 */ + 0x0000, /* R685 */ + 0x0000, /* R686 */ + 0x0000, /* R687 */ + 0x0000, /* R688 */ + 0x0000, /* R689 */ + 0x0000, /* R690 */ + 0x0000, /* R691 */ + 0x0000, /* R692 */ + 0x0000, /* R693 */ + 0x0000, /* R694 */ + 0x0000, /* R695 */ + 0x0000, /* R696 */ + 0x0000, /* R697 */ + 0x0000, /* R698 */ + 0x0000, /* R699 */ + 0x0000, /* R700 */ + 0x0000, /* R701 */ + 0x0000, /* R702 */ + 0x0000, /* R703 */ + 0x0000, /* R704 */ + 0x0000, /* R705 */ + 0x0000, /* R706 */ + 0x0000, /* R707 */ + 0x0000, /* R708 */ + 0x0000, /* R709 */ + 0x0000, /* R710 */ + 0x0000, /* R711 */ + 0x0000, /* R712 */ + 0x0000, /* R713 */ + 0x0000, /* R714 */ + 0x0000, /* R715 */ + 0x0000, /* R716 */ + 0x0000, /* R717 */ + 0x0000, /* R718 */ + 0x0000, /* R719 */ + 0x0000, /* R720 */ + 0x0000, /* R721 */ + 0x0000, /* R722 */ + 0x0000, /* R723 */ + 0x0000, /* R724 */ + 0x0000, /* R725 */ + 0x0000, /* R726 */ + 0x0000, /* R727 */ + 0x0000, /* R728 */ + 0x0000, /* R729 */ + 0x0000, /* R730 */ + 0x0000, /* R731 */ + 0x0000, /* R732 */ + 0x0000, /* R733 */ + 0x0000, /* R734 */ + 0x0000, /* R735 */ + 0x0000, /* R736 */ + 0x0000, /* R737 */ + 0x0000, /* R738 */ + 0x0000, /* R739 */ + 0x0000, /* R740 */ + 0x0000, /* R741 */ + 0x0000, /* R742 */ + 0x0000, /* R743 */ + 0x0000, /* R744 */ + 0x0000, /* R745 */ + 0x0000, /* R746 */ + 0x0000, /* R747 */ + 0x0000, /* R748 */ + 0x0000, /* R749 */ + 0x0000, /* R750 */ + 0x0000, /* R751 */ + 0x0000, /* R752 */ + 0x0000, /* R753 */ + 0x0000, /* R754 */ + 0x0000, /* R755 */ + 0x0000, /* R756 */ + 0x0000, /* R757 */ + 0x0000, /* R758 */ + 0x0000, /* R759 */ + 0x0000, /* R760 */ + 0x0000, /* R761 */ + 0x0000, /* R762 */ + 0x0000, /* R763 */ + 0x0000, /* R764 */ + 0x0000, /* R765 */ + 0x0000, /* R766 */ + 0x0000, /* R767 */ + 0x1C00, /* R768 - DSP2 Power Management */ + 0x0000, /* R769 */ + 0x0000, /* R770 */ + 0x0000, /* R771 */ + 0x0000, /* R772 */ + 0x0000, /* R773 */ + 0x0000, /* R774 */ + 0x0000, /* R775 */ + 0x0000, /* R776 */ + 0x0000, /* R777 */ + 0x0000, /* R778 */ + 0x0000, /* R779 */ + 0x0000, /* R780 */ + 0x0000, /* R781 */ + 0x0000, /* R782 */ + 0x0000, /* R783 */ + 0x0000, /* R784 */ + 0x0000, /* R785 */ + 0x0000, /* R786 */ + 0x0000, /* R787 */ + 0x0000, /* R788 */ + 0x0000, /* R789 */ + 0x0000, /* R790 */ + 0x0000, /* R791 */ + 0x0000, /* R792 */ + 0x0000, /* R793 */ + 0x0000, /* R794 */ + 0x0000, /* R795 */ + 0x0000, /* R796 */ + 0x0000, /* R797 */ + 0x0000, /* R798 */ + 0x0000, /* R799 */ + 0x0000, /* R800 */ + 0x0000, /* R801 */ + 0x0000, /* R802 */ + 0x0000, /* R803 */ + 0x0000, /* R804 */ + 0x0000, /* R805 */ + 0x0000, /* R806 */ + 0x0000, /* R807 */ + 0x0000, /* R808 */ + 0x0000, /* R809 */ + 0x0000, /* R810 */ + 0x0000, /* R811 */ + 0x0000, /* R812 */ + 0x0000, /* R813 */ + 0x0000, /* R814 */ + 0x0000, /* R815 */ + 0x0000, /* R816 */ + 0x0000, /* R817 */ + 0x0000, /* R818 */ + 0x0000, /* R819 */ + 0x0000, /* R820 */ + 0x0000, /* R821 */ + 0x0000, /* R822 */ + 0x0000, /* R823 */ + 0x0000, /* R824 */ + 0x0000, /* R825 */ + 0x0000, /* R826 */ + 0x0000, /* R827 */ + 0x0000, /* R828 */ + 0x0000, /* R829 */ + 0x0000, /* R830 */ + 0x0000, /* R831 */ + 0x0000, /* R832 */ + 0x0000, /* R833 */ + 0x0000, /* R834 */ + 0x0000, /* R835 */ + 0x0000, /* R836 */ + 0x0000, /* R837 */ + 0x0000, /* R838 */ + 0x0000, /* R839 */ + 0x0000, /* R840 */ + 0x0000, /* R841 */ + 0x0000, /* R842 */ + 0x0000, /* R843 */ + 0x0000, /* R844 */ + 0x0000, /* R845 */ + 0x0000, /* R846 */ + 0x0000, /* R847 */ + 0x0000, /* R848 */ + 0x0000, /* R849 */ + 0x0000, /* R850 */ + 0x0000, /* R851 */ + 0x0000, /* R852 */ + 0x0000, /* R853 */ + 0x0000, /* R854 */ + 0x0000, /* R855 */ + 0x0000, /* R856 */ + 0x0000, /* R857 */ + 0x0000, /* R858 */ + 0x0000, /* R859 */ + 0x0000, /* R860 */ + 0x0000, /* R861 */ + 0x0000, /* R862 */ + 0x0000, /* R863 */ + 0x0000, /* R864 */ + 0x0000, /* R865 */ + 0x0000, /* R866 */ + 0x0000, /* R867 */ + 0x0000, /* R868 */ + 0x0000, /* R869 */ + 0x0000, /* R870 */ + 0x0000, /* R871 */ + 0x0000, /* R872 */ + 0x0000, /* R873 */ + 0x0000, /* R874 */ + 0x0000, /* R875 */ + 0x0000, /* R876 */ + 0x0000, /* R877 */ + 0x0000, /* R878 */ + 0x0000, /* R879 */ + 0x0000, /* R880 */ + 0x0000, /* R881 */ + 0x0000, /* R882 */ + 0x0000, /* R883 */ + 0x0000, /* R884 */ + 0x0000, /* R885 */ + 0x0000, /* R886 */ + 0x0000, /* R887 */ + 0x0000, /* R888 */ + 0x0000, /* R889 */ + 0x0000, /* R890 */ + 0x0000, /* R891 */ + 0x0000, /* R892 */ + 0x0000, /* R893 */ + 0x0000, /* R894 */ + 0x0000, /* R895 */ + 0x0000, /* R896 */ + 0x0000, /* R897 */ + 0x0000, /* R898 */ + 0x0000, /* R899 */ + 0x0000, /* R900 */ + 0x0000, /* R901 */ + 0x0000, /* R902 */ + 0x0000, /* R903 */ + 0x0000, /* R904 */ + 0x0000, /* R905 */ + 0x0000, /* R906 */ + 0x0000, /* R907 */ + 0x0000, /* R908 */ + 0x0000, /* R909 */ + 0x0000, /* R910 */ + 0x0000, /* R911 */ + 0x0000, /* R912 */ + 0x0000, /* R913 */ + 0x0000, /* R914 */ + 0x0000, /* R915 */ + 0x0000, /* R916 */ + 0x0000, /* R917 */ + 0x0000, /* R918 */ + 0x0000, /* R919 */ + 0x0000, /* R920 */ + 0x0000, /* R921 */ + 0x0000, /* R922 */ + 0x0000, /* R923 */ + 0x0000, /* R924 */ + 0x0000, /* R925 */ + 0x0000, /* R926 */ + 0x0000, /* R927 */ + 0x0000, /* R928 */ + 0x0000, /* R929 */ + 0x0000, /* R930 */ + 0x0000, /* R931 */ + 0x0000, /* R932 */ + 0x0000, /* R933 */ + 0x0000, /* R934 */ + 0x0000, /* R935 */ + 0x0000, /* R936 */ + 0x0000, /* R937 */ + 0x0000, /* R938 */ + 0x0000, /* R939 */ + 0x0000, /* R940 */ + 0x0000, /* R941 */ + 0x0000, /* R942 */ + 0x0000, /* R943 */ + 0x0000, /* R944 */ + 0x0000, /* R945 */ + 0x0000, /* R946 */ + 0x0000, /* R947 */ + 0x0000, /* R948 */ + 0x0000, /* R949 */ + 0x0000, /* R950 */ + 0x0000, /* R951 */ + 0x0000, /* R952 */ + 0x0000, /* R953 */ + 0x0000, /* R954 */ + 0x0000, /* R955 */ + 0x0000, /* R956 */ + 0x0000, /* R957 */ + 0x0000, /* R958 */ + 0x0000, /* R959 */ + 0x0000, /* R960 */ + 0x0000, /* R961 */ + 0x0000, /* R962 */ + 0x0000, /* R963 */ + 0x0000, /* R964 */ + 0x0000, /* R965 */ + 0x0000, /* R966 */ + 0x0000, /* R967 */ + 0x0000, /* R968 */ + 0x0000, /* R969 */ + 0x0000, /* R970 */ + 0x0000, /* R971 */ + 0x0000, /* R972 */ + 0x0000, /* R973 */ + 0x0000, /* R974 */ + 0x0000, /* R975 */ + 0x0000, /* R976 */ + 0x0000, /* R977 */ + 0x0000, /* R978 */ + 0x0000, /* R979 */ + 0x0000, /* R980 */ + 0x0000, /* R981 */ + 0x0000, /* R982 */ + 0x0000, /* R983 */ + 0x0000, /* R984 */ + 0x0000, /* R985 */ + 0x0000, /* R986 */ + 0x0000, /* R987 */ + 0x0000, /* R988 */ + 0x0000, /* R989 */ + 0x0000, /* R990 */ + 0x0000, /* R991 */ + 0x0000, /* R992 */ + 0x0000, /* R993 */ + 0x0000, /* R994 */ + 0x0000, /* R995 */ + 0x0000, /* R996 */ + 0x0000, /* R997 */ + 0x0000, /* R998 */ + 0x0000, /* R999 */ + 0x0000, /* R1000 */ + 0x0000, /* R1001 */ + 0x0000, /* R1002 */ + 0x0000, /* R1003 */ + 0x0000, /* R1004 */ + 0x0000, /* R1005 */ + 0x0000, /* R1006 */ + 0x0000, /* R1007 */ + 0x0000, /* R1008 */ + 0x0000, /* R1009 */ + 0x0000, /* R1010 */ + 0x0000, /* R1011 */ + 0x0000, /* R1012 */ + 0x0000, /* R1013 */ + 0x0000, /* R1014 */ + 0x0000, /* R1015 */ + 0x0000, /* R1016 */ + 0x0000, /* R1017 */ + 0x0000, /* R1018 */ + 0x0000, /* R1019 */ + 0x0000, /* R1020 */ + 0x0000, /* R1021 */ + 0x0000, /* R1022 */ + 0x0000, /* R1023 */ + 0x0000, /* R1024 */ + 0x0000, /* R1025 */ + 0x0000, /* R1026 */ + 0x0000, /* R1027 */ + 0x0000, /* R1028 */ + 0x0000, /* R1029 */ + 0x0000, /* R1030 */ + 0x0000, /* R1031 */ + 0x0000, /* R1032 */ + 0x0000, /* R1033 */ + 0x0000, /* R1034 */ + 0x0000, /* R1035 */ + 0x0000, /* R1036 */ + 0x0000, /* R1037 - DSP2_ExecControl */ + 0x0000, /* R1038 */ + 0x0000, /* R1039 */ + 0x0000, /* R1040 */ + 0x0000, /* R1041 */ + 0x0000, /* R1042 */ + 0x0000, /* R1043 */ + 0x0000, /* R1044 */ + 0x0000, /* R1045 */ + 0x0000, /* R1046 */ + 0x0000, /* R1047 */ + 0x0000, /* R1048 */ + 0x0000, /* R1049 */ + 0x0000, /* R1050 */ + 0x0000, /* R1051 */ + 0x0000, /* R1052 */ + 0x0000, /* R1053 */ + 0x0000, /* R1054 */ + 0x0000, /* R1055 */ + 0x0000, /* R1056 */ + 0x0000, /* R1057 */ + 0x0000, /* R1058 */ + 0x0000, /* R1059 */ + 0x0000, /* R1060 */ + 0x0000, /* R1061 */ + 0x0000, /* R1062 */ + 0x0000, /* R1063 */ + 0x0000, /* R1064 */ + 0x0000, /* R1065 */ + 0x0000, /* R1066 */ + 0x0000, /* R1067 */ + 0x0000, /* R1068 */ + 0x0000, /* R1069 */ + 0x0000, /* R1070 */ + 0x0000, /* R1071 */ + 0x0000, /* R1072 */ + 0x0000, /* R1073 */ + 0x0000, /* R1074 */ + 0x0000, /* R1075 */ + 0x0000, /* R1076 */ + 0x0000, /* R1077 */ + 0x0000, /* R1078 */ + 0x0000, /* R1079 */ + 0x0000, /* R1080 */ + 0x0000, /* R1081 */ + 0x0000, /* R1082 */ + 0x0000, /* R1083 */ + 0x0000, /* R1084 */ + 0x0000, /* R1085 */ + 0x0000, /* R1086 */ + 0x0000, /* R1087 */ + 0x0000, /* R1088 */ + 0x0000, /* R1089 */ + 0x0000, /* R1090 */ + 0x0000, /* R1091 */ + 0x0000, /* R1092 */ + 0x0000, /* R1093 */ + 0x0000, /* R1094 */ + 0x0000, /* R1095 */ + 0x0000, /* R1096 */ + 0x0000, /* R1097 */ + 0x0000, /* R1098 */ + 0x0000, /* R1099 */ + 0x0000, /* R1100 */ + 0x0000, /* R1101 */ + 0x0000, /* R1102 */ + 0x0000, /* R1103 */ + 0x0000, /* R1104 */ + 0x0000, /* R1105 */ + 0x0000, /* R1106 */ + 0x0000, /* R1107 */ + 0x0000, /* R1108 */ + 0x0000, /* R1109 */ + 0x0000, /* R1110 */ + 0x0000, /* R1111 */ + 0x0000, /* R1112 */ + 0x0000, /* R1113 */ + 0x0000, /* R1114 */ + 0x0000, /* R1115 */ + 0x0000, /* R1116 */ + 0x0000, /* R1117 */ + 0x0000, /* R1118 */ + 0x0000, /* R1119 */ + 0x0000, /* R1120 */ + 0x0000, /* R1121 */ + 0x0000, /* R1122 */ + 0x0000, /* R1123 */ + 0x0000, /* R1124 */ + 0x0000, /* R1125 */ + 0x0000, /* R1126 */ + 0x0000, /* R1127 */ + 0x0000, /* R1128 */ + 0x0000, /* R1129 */ + 0x0000, /* R1130 */ + 0x0000, /* R1131 */ + 0x0000, /* R1132 */ + 0x0000, /* R1133 */ + 0x0000, /* R1134 */ + 0x0000, /* R1135 */ + 0x0000, /* R1136 */ + 0x0000, /* R1137 */ + 0x0000, /* R1138 */ + 0x0000, /* R1139 */ + 0x0000, /* R1140 */ + 0x0000, /* R1141 */ + 0x0000, /* R1142 */ + 0x0000, /* R1143 */ + 0x0000, /* R1144 */ + 0x0000, /* R1145 */ + 0x0000, /* R1146 */ + 0x0000, /* R1147 */ + 0x0000, /* R1148 */ + 0x0000, /* R1149 */ + 0x0000, /* R1150 */ + 0x0000, /* R1151 */ + 0x0000, /* R1152 */ + 0x0000, /* R1153 */ + 0x0000, /* R1154 */ + 0x0000, /* R1155 */ + 0x0000, /* R1156 */ + 0x0000, /* R1157 */ + 0x0000, /* R1158 */ + 0x0000, /* R1159 */ + 0x0000, /* R1160 */ + 0x0000, /* R1161 */ + 0x0000, /* R1162 */ + 0x0000, /* R1163 */ + 0x0000, /* R1164 */ + 0x0000, /* R1165 */ + 0x0000, /* R1166 */ + 0x0000, /* R1167 */ + 0x0000, /* R1168 */ + 0x0000, /* R1169 */ + 0x0000, /* R1170 */ + 0x0000, /* R1171 */ + 0x0000, /* R1172 */ + 0x0000, /* R1173 */ + 0x0000, /* R1174 */ + 0x0000, /* R1175 */ + 0x0000, /* R1176 */ + 0x0000, /* R1177 */ + 0x0000, /* R1178 */ + 0x0000, /* R1179 */ + 0x0000, /* R1180 */ + 0x0000, /* R1181 */ + 0x0000, /* R1182 */ + 0x0000, /* R1183 */ + 0x0000, /* R1184 */ + 0x0000, /* R1185 */ + 0x0000, /* R1186 */ + 0x0000, /* R1187 */ + 0x0000, /* R1188 */ + 0x0000, /* R1189 */ + 0x0000, /* R1190 */ + 0x0000, /* R1191 */ + 0x0000, /* R1192 */ + 0x0000, /* R1193 */ + 0x0000, /* R1194 */ + 0x0000, /* R1195 */ + 0x0000, /* R1196 */ + 0x0000, /* R1197 */ + 0x0000, /* R1198 */ + 0x0000, /* R1199 */ + 0x0000, /* R1200 */ + 0x0000, /* R1201 */ + 0x0000, /* R1202 */ + 0x0000, /* R1203 */ + 0x0000, /* R1204 */ + 0x0000, /* R1205 */ + 0x0000, /* R1206 */ + 0x0000, /* R1207 */ + 0x0000, /* R1208 */ + 0x0000, /* R1209 */ + 0x0000, /* R1210 */ + 0x0000, /* R1211 */ + 0x0000, /* R1212 */ + 0x0000, /* R1213 */ + 0x0000, /* R1214 */ + 0x0000, /* R1215 */ + 0x0000, /* R1216 */ + 0x0000, /* R1217 */ + 0x0000, /* R1218 */ + 0x0000, /* R1219 */ + 0x0000, /* R1220 */ + 0x0000, /* R1221 */ + 0x0000, /* R1222 */ + 0x0000, /* R1223 */ + 0x0000, /* R1224 */ + 0x0000, /* R1225 */ + 0x0000, /* R1226 */ + 0x0000, /* R1227 */ + 0x0000, /* R1228 */ + 0x0000, /* R1229 */ + 0x0000, /* R1230 */ + 0x0000, /* R1231 */ + 0x0000, /* R1232 */ + 0x0000, /* R1233 */ + 0x0000, /* R1234 */ + 0x0000, /* R1235 */ + 0x0000, /* R1236 */ + 0x0000, /* R1237 */ + 0x0000, /* R1238 */ + 0x0000, /* R1239 */ + 0x0000, /* R1240 */ + 0x0000, /* R1241 */ + 0x0000, /* R1242 */ + 0x0000, /* R1243 */ + 0x0000, /* R1244 */ + 0x0000, /* R1245 */ + 0x0000, /* R1246 */ + 0x0000, /* R1247 */ + 0x0000, /* R1248 */ + 0x0000, /* R1249 */ + 0x0000, /* R1250 */ + 0x0000, /* R1251 */ + 0x0000, /* R1252 */ + 0x0000, /* R1253 */ + 0x0000, /* R1254 */ + 0x0000, /* R1255 */ + 0x0000, /* R1256 */ + 0x0000, /* R1257 */ + 0x0000, /* R1258 */ + 0x0000, /* R1259 */ + 0x0000, /* R1260 */ + 0x0000, /* R1261 */ + 0x0000, /* R1262 */ + 0x0000, /* R1263 */ + 0x0000, /* R1264 */ + 0x0000, /* R1265 */ + 0x0000, /* R1266 */ + 0x0000, /* R1267 */ + 0x0000, /* R1268 */ + 0x0000, /* R1269 */ + 0x0000, /* R1270 */ + 0x0000, /* R1271 */ + 0x0000, /* R1272 */ + 0x0000, /* R1273 */ + 0x0000, /* R1274 */ + 0x0000, /* R1275 */ + 0x0000, /* R1276 */ + 0x0000, /* R1277 */ + 0x0000, /* R1278 */ + 0x0000, /* R1279 */ + 0x0000, /* R1280 */ + 0x0000, /* R1281 */ + 0x0000, /* R1282 */ + 0x0000, /* R1283 */ + 0x0000, /* R1284 */ + 0x0000, /* R1285 */ + 0x0000, /* R1286 */ + 0x0000, /* R1287 */ + 0x0000, /* R1288 */ + 0x0000, /* R1289 */ + 0x0000, /* R1290 */ + 0x0000, /* R1291 */ + 0x0000, /* R1292 */ + 0x0000, /* R1293 */ + 0x0000, /* R1294 */ + 0x0000, /* R1295 */ + 0x0000, /* R1296 */ + 0x0000, /* R1297 */ + 0x0000, /* R1298 */ + 0x0000, /* R1299 */ + 0x0000, /* R1300 */ + 0x0000, /* R1301 */ + 0x0000, /* R1302 */ + 0x0000, /* R1303 */ + 0x0000, /* R1304 */ + 0x0000, /* R1305 */ + 0x0000, /* R1306 */ + 0x0000, /* R1307 */ + 0x0000, /* R1308 */ + 0x0000, /* R1309 */ + 0x0000, /* R1310 */ + 0x0000, /* R1311 */ + 0x0000, /* R1312 */ + 0x0000, /* R1313 */ + 0x0000, /* R1314 */ + 0x0000, /* R1315 */ + 0x0000, /* R1316 */ + 0x0000, /* R1317 */ + 0x0000, /* R1318 */ + 0x0000, /* R1319 */ + 0x0000, /* R1320 */ + 0x0000, /* R1321 */ + 0x0000, /* R1322 */ + 0x0000, /* R1323 */ + 0x0000, /* R1324 */ + 0x0000, /* R1325 */ + 0x0000, /* R1326 */ + 0x0000, /* R1327 */ + 0x0000, /* R1328 */ + 0x0000, /* R1329 */ + 0x0000, /* R1330 */ + 0x0000, /* R1331 */ + 0x0000, /* R1332 */ + 0x0000, /* R1333 */ + 0x0000, /* R1334 */ + 0x0000, /* R1335 */ + 0x0000, /* R1336 */ + 0x0000, /* R1337 */ + 0x0000, /* R1338 */ + 0x0000, /* R1339 */ + 0x0000, /* R1340 */ + 0x0000, /* R1341 */ + 0x0000, /* R1342 */ + 0x0000, /* R1343 */ + 0x0000, /* R1344 */ + 0x0000, /* R1345 */ + 0x0000, /* R1346 */ + 0x0000, /* R1347 */ + 0x0000, /* R1348 */ + 0x0000, /* R1349 */ + 0x0000, /* R1350 */ + 0x0000, /* R1351 */ + 0x0000, /* R1352 */ + 0x0000, /* R1353 */ + 0x0000, /* R1354 */ + 0x0000, /* R1355 */ + 0x0000, /* R1356 */ + 0x0000, /* R1357 */ + 0x0000, /* R1358 */ + 0x0000, /* R1359 */ + 0x0000, /* R1360 */ + 0x0000, /* R1361 */ + 0x0000, /* R1362 */ + 0x0000, /* R1363 */ + 0x0000, /* R1364 */ + 0x0000, /* R1365 */ + 0x0000, /* R1366 */ + 0x0000, /* R1367 */ + 0x0000, /* R1368 */ + 0x0000, /* R1369 */ + 0x0000, /* R1370 */ + 0x0000, /* R1371 */ + 0x0000, /* R1372 */ + 0x0000, /* R1373 */ + 0x0000, /* R1374 */ + 0x0000, /* R1375 */ + 0x0000, /* R1376 */ + 0x0000, /* R1377 */ + 0x0000, /* R1378 */ + 0x0000, /* R1379 */ + 0x0000, /* R1380 */ + 0x0000, /* R1381 */ + 0x0000, /* R1382 */ + 0x0000, /* R1383 */ + 0x0000, /* R1384 */ + 0x0000, /* R1385 */ + 0x0000, /* R1386 */ + 0x0000, /* R1387 */ + 0x0000, /* R1388 */ + 0x0000, /* R1389 */ + 0x0000, /* R1390 */ + 0x0000, /* R1391 */ + 0x0000, /* R1392 */ + 0x0000, /* R1393 */ + 0x0000, /* R1394 */ + 0x0000, /* R1395 */ + 0x0000, /* R1396 */ + 0x0000, /* R1397 */ + 0x0000, /* R1398 */ + 0x0000, /* R1399 */ + 0x0000, /* R1400 */ + 0x0000, /* R1401 */ + 0x0000, /* R1402 */ + 0x0000, /* R1403 */ + 0x0000, /* R1404 */ + 0x0000, /* R1405 */ + 0x0000, /* R1406 */ + 0x0000, /* R1407 */ + 0x0000, /* R1408 */ + 0x0000, /* R1409 */ + 0x0000, /* R1410 */ + 0x0000, /* R1411 */ + 0x0000, /* R1412 */ + 0x0000, /* R1413 */ + 0x0000, /* R1414 */ + 0x0000, /* R1415 */ + 0x0000, /* R1416 */ + 0x0000, /* R1417 */ + 0x0000, /* R1418 */ + 0x0000, /* R1419 */ + 0x0000, /* R1420 */ + 0x0000, /* R1421 */ + 0x0000, /* R1422 */ + 0x0000, /* R1423 */ + 0x0000, /* R1424 */ + 0x0000, /* R1425 */ + 0x0000, /* R1426 */ + 0x0000, /* R1427 */ + 0x0000, /* R1428 */ + 0x0000, /* R1429 */ + 0x0000, /* R1430 */ + 0x0000, /* R1431 */ + 0x0000, /* R1432 */ + 0x0000, /* R1433 */ + 0x0000, /* R1434 */ + 0x0000, /* R1435 */ + 0x0000, /* R1436 */ + 0x0000, /* R1437 */ + 0x0000, /* R1438 */ + 0x0000, /* R1439 */ + 0x0000, /* R1440 */ + 0x0000, /* R1441 */ + 0x0000, /* R1442 */ + 0x0000, /* R1443 */ + 0x0000, /* R1444 */ + 0x0000, /* R1445 */ + 0x0000, /* R1446 */ + 0x0000, /* R1447 */ + 0x0000, /* R1448 */ + 0x0000, /* R1449 */ + 0x0000, /* R1450 */ + 0x0000, /* R1451 */ + 0x0000, /* R1452 */ + 0x0000, /* R1453 */ + 0x0000, /* R1454 */ + 0x0000, /* R1455 */ + 0x0000, /* R1456 */ + 0x0000, /* R1457 */ + 0x0000, /* R1458 */ + 0x0000, /* R1459 */ + 0x0000, /* R1460 */ + 0x0000, /* R1461 */ + 0x0000, /* R1462 */ + 0x0000, /* R1463 */ + 0x0000, /* R1464 */ + 0x0000, /* R1465 */ + 0x0000, /* R1466 */ + 0x0000, /* R1467 */ + 0x0000, /* R1468 */ + 0x0000, /* R1469 */ + 0x0000, /* R1470 */ + 0x0000, /* R1471 */ + 0x0000, /* R1472 */ + 0x0000, /* R1473 */ + 0x0000, /* R1474 */ + 0x0000, /* R1475 */ + 0x0000, /* R1476 */ + 0x0000, /* R1477 */ + 0x0000, /* R1478 */ + 0x0000, /* R1479 */ + 0x0000, /* R1480 */ + 0x0000, /* R1481 */ + 0x0000, /* R1482 */ + 0x0000, /* R1483 */ + 0x0000, /* R1484 */ + 0x0000, /* R1485 */ + 0x0000, /* R1486 */ + 0x0000, /* R1487 */ + 0x0000, /* R1488 */ + 0x0000, /* R1489 */ + 0x0000, /* R1490 */ + 0x0000, /* R1491 */ + 0x0000, /* R1492 */ + 0x0000, /* R1493 */ + 0x0000, /* R1494 */ + 0x0000, /* R1495 */ + 0x0000, /* R1496 */ + 0x0000, /* R1497 */ + 0x0000, /* R1498 */ + 0x0000, /* R1499 */ + 0x0000, /* R1500 */ + 0x0000, /* R1501 */ + 0x0000, /* R1502 */ + 0x0000, /* R1503 */ + 0x0000, /* R1504 */ + 0x0000, /* R1505 */ + 0x0000, /* R1506 */ + 0x0000, /* R1507 */ + 0x0000, /* R1508 */ + 0x0000, /* R1509 */ + 0x0000, /* R1510 */ + 0x0000, /* R1511 */ + 0x0000, /* R1512 */ + 0x0000, /* R1513 */ + 0x0000, /* R1514 */ + 0x0000, /* R1515 */ + 0x0000, /* R1516 */ + 0x0000, /* R1517 */ + 0x0000, /* R1518 */ + 0x0000, /* R1519 */ + 0x0000, /* R1520 */ + 0x0000, /* R1521 */ + 0x0000, /* R1522 */ + 0x0000, /* R1523 */ + 0x0000, /* R1524 */ + 0x0000, /* R1525 */ + 0x0000, /* R1526 */ + 0x0000, /* R1527 */ + 0x0000, /* R1528 */ + 0x0000, /* R1529 */ + 0x0000, /* R1530 */ + 0x0000, /* R1531 */ + 0x0000, /* R1532 */ + 0x0000, /* R1533 */ + 0x0000, /* R1534 */ + 0x0000, /* R1535 */ + 0x0000, /* R1536 */ + 0x0000, /* R1537 */ + 0x0000, /* R1538 */ + 0x0000, /* R1539 */ + 0x0000, /* R1540 */ + 0x0000, /* R1541 */ + 0x0000, /* R1542 */ + 0x0000, /* R1543 */ + 0x0000, /* R1544 */ + 0x0000, /* R1545 */ + 0x0000, /* R1546 */ + 0x0000, /* R1547 */ + 0x0000, /* R1548 */ + 0x0000, /* R1549 */ + 0x0000, /* R1550 */ + 0x0000, /* R1551 */ + 0x0000, /* R1552 */ + 0x0000, /* R1553 */ + 0x0000, /* R1554 */ + 0x0000, /* R1555 */ + 0x0000, /* R1556 */ + 0x0000, /* R1557 */ + 0x0000, /* R1558 */ + 0x0000, /* R1559 */ + 0x0000, /* R1560 */ + 0x0000, /* R1561 */ + 0x0000, /* R1562 */ + 0x0000, /* R1563 */ + 0x0000, /* R1564 */ + 0x0000, /* R1565 */ + 0x0000, /* R1566 */ + 0x0000, /* R1567 */ + 0x0000, /* R1568 */ + 0x0000, /* R1569 */ + 0x0000, /* R1570 */ + 0x0000, /* R1571 */ + 0x0000, /* R1572 */ + 0x0000, /* R1573 */ + 0x0000, /* R1574 */ + 0x0000, /* R1575 */ + 0x0000, /* R1576 */ + 0x0000, /* R1577 */ + 0x0000, /* R1578 */ + 0x0000, /* R1579 */ + 0x0000, /* R1580 */ + 0x0000, /* R1581 */ + 0x0000, /* R1582 */ + 0x0000, /* R1583 */ + 0x0000, /* R1584 */ + 0x0000, /* R1585 */ + 0x0000, /* R1586 */ + 0x0000, /* R1587 */ + 0x0000, /* R1588 */ + 0x0000, /* R1589 */ + 0x0000, /* R1590 */ + 0x0000, /* R1591 */ + 0x0000, /* R1592 */ + 0x0000, /* R1593 */ + 0x0000, /* R1594 */ + 0x0000, /* R1595 */ + 0x0000, /* R1596 */ + 0x0000, /* R1597 */ + 0x0000, /* R1598 */ + 0x0000, /* R1599 */ + 0x0000, /* R1600 */ + 0x0000, /* R1601 */ + 0x0000, /* R1602 */ + 0x0000, /* R1603 */ + 0x0000, /* R1604 */ + 0x0000, /* R1605 */ + 0x0000, /* R1606 */ + 0x0000, /* R1607 */ + 0x0000, /* R1608 */ + 0x0000, /* R1609 */ + 0x0000, /* R1610 */ + 0x0000, /* R1611 */ + 0x0000, /* R1612 */ + 0x0000, /* R1613 */ + 0x0000, /* R1614 */ + 0x0000, /* R1615 */ + 0x0000, /* R1616 */ + 0x0000, /* R1617 */ + 0x0000, /* R1618 */ + 0x0000, /* R1619 */ + 0x0000, /* R1620 */ + 0x0000, /* R1621 */ + 0x0000, /* R1622 */ + 0x0000, /* R1623 */ + 0x0000, /* R1624 */ + 0x0000, /* R1625 */ + 0x0000, /* R1626 */ + 0x0000, /* R1627 */ + 0x0000, /* R1628 */ + 0x0000, /* R1629 */ + 0x0000, /* R1630 */ + 0x0000, /* R1631 */ + 0x0000, /* R1632 */ + 0x0000, /* R1633 */ + 0x0000, /* R1634 */ + 0x0000, /* R1635 */ + 0x0000, /* R1636 */ + 0x0000, /* R1637 */ + 0x0000, /* R1638 */ + 0x0000, /* R1639 */ + 0x0000, /* R1640 */ + 0x0000, /* R1641 */ + 0x0000, /* R1642 */ + 0x0000, /* R1643 */ + 0x0000, /* R1644 */ + 0x0000, /* R1645 */ + 0x0000, /* R1646 */ + 0x0000, /* R1647 */ + 0x0000, /* R1648 */ + 0x0000, /* R1649 */ + 0x0000, /* R1650 */ + 0x0000, /* R1651 */ + 0x0000, /* R1652 */ + 0x0000, /* R1653 */ + 0x0000, /* R1654 */ + 0x0000, /* R1655 */ + 0x0000, /* R1656 */ + 0x0000, /* R1657 */ + 0x0000, /* R1658 */ + 0x0000, /* R1659 */ + 0x0000, /* R1660 */ + 0x0000, /* R1661 */ + 0x0000, /* R1662 */ + 0x0000, /* R1663 */ + 0x0000, /* R1664 */ + 0x0000, /* R1665 */ + 0x0000, /* R1666 */ + 0x0000, /* R1667 */ + 0x0000, /* R1668 */ + 0x0000, /* R1669 */ + 0x0000, /* R1670 */ + 0x0000, /* R1671 */ + 0x0000, /* R1672 */ + 0x0000, /* R1673 */ + 0x0000, /* R1674 */ + 0x0000, /* R1675 */ + 0x0000, /* R1676 */ + 0x0000, /* R1677 */ + 0x0000, /* R1678 */ + 0x0000, /* R1679 */ + 0x0000, /* R1680 */ + 0x0000, /* R1681 */ + 0x0000, /* R1682 */ + 0x0000, /* R1683 */ + 0x0000, /* R1684 */ + 0x0000, /* R1685 */ + 0x0000, /* R1686 */ + 0x0000, /* R1687 */ + 0x0000, /* R1688 */ + 0x0000, /* R1689 */ + 0x0000, /* R1690 */ + 0x0000, /* R1691 */ + 0x0000, /* R1692 */ + 0x0000, /* R1693 */ + 0x0000, /* R1694 */ + 0x0000, /* R1695 */ + 0x0000, /* R1696 */ + 0x0000, /* R1697 */ + 0x0000, /* R1698 */ + 0x0000, /* R1699 */ + 0x0000, /* R1700 */ + 0x0000, /* R1701 */ + 0x0000, /* R1702 */ + 0x0000, /* R1703 */ + 0x0000, /* R1704 */ + 0x0000, /* R1705 */ + 0x0000, /* R1706 */ + 0x0000, /* R1707 */ + 0x0000, /* R1708 */ + 0x0000, /* R1709 */ + 0x0000, /* R1710 */ + 0x0000, /* R1711 */ + 0x0000, /* R1712 */ + 0x0000, /* R1713 */ + 0x0000, /* R1714 */ + 0x0000, /* R1715 */ + 0x0000, /* R1716 */ + 0x0000, /* R1717 */ + 0x0000, /* R1718 */ + 0x0000, /* R1719 */ + 0x0000, /* R1720 */ + 0x0000, /* R1721 */ + 0x0000, /* R1722 */ + 0x0000, /* R1723 */ + 0x0000, /* R1724 */ + 0x0000, /* R1725 */ + 0x0000, /* R1726 */ + 0x0000, /* R1727 */ + 0x0000, /* R1728 */ + 0x0000, /* R1729 */ + 0x0000, /* R1730 */ + 0x0000, /* R1731 */ + 0x0000, /* R1732 */ + 0x0000, /* R1733 */ + 0x0000, /* R1734 */ + 0x0000, /* R1735 */ + 0x0000, /* R1736 */ + 0x0000, /* R1737 */ + 0x0000, /* R1738 */ + 0x0000, /* R1739 */ + 0x0000, /* R1740 */ + 0x0000, /* R1741 */ + 0x0000, /* R1742 */ + 0x0000, /* R1743 */ + 0x0000, /* R1744 */ + 0x0000, /* R1745 */ + 0x0000, /* R1746 */ + 0x0000, /* R1747 */ + 0x0000, /* R1748 */ + 0x0000, /* R1749 */ + 0x0000, /* R1750 */ + 0x0000, /* R1751 */ + 0x0000, /* R1752 */ + 0x0000, /* R1753 */ + 0x0000, /* R1754 */ + 0x0000, /* R1755 */ + 0x0000, /* R1756 */ + 0x0000, /* R1757 */ + 0x0000, /* R1758 */ + 0x0000, /* R1759 */ + 0x0000, /* R1760 */ + 0x0000, /* R1761 */ + 0x0000, /* R1762 */ + 0x0000, /* R1763 */ + 0x0000, /* R1764 */ + 0x0000, /* R1765 */ + 0x0000, /* R1766 */ + 0x0000, /* R1767 */ + 0x0000, /* R1768 */ + 0x0000, /* R1769 */ + 0x0000, /* R1770 */ + 0x0000, /* R1771 */ + 0x0000, /* R1772 */ + 0x0000, /* R1773 */ + 0x0000, /* R1774 */ + 0x0000, /* R1775 */ + 0x0000, /* R1776 */ + 0x0000, /* R1777 */ + 0x0000, /* R1778 */ + 0x0000, /* R1779 */ + 0x0000, /* R1780 */ + 0x0000, /* R1781 */ + 0x0000, /* R1782 */ + 0x0000, /* R1783 */ + 0x0000, /* R1784 */ + 0x0000, /* R1785 */ + 0x0000, /* R1786 */ + 0x0000, /* R1787 */ + 0x0000, /* R1788 */ + 0x0000, /* R1789 */ + 0x0000, /* R1790 */ + 0x0000, /* R1791 */ + 0x0000, /* R1792 */ + 0x0000, /* R1793 */ + 0x0000, /* R1794 */ + 0x0000, /* R1795 */ + 0x0000, /* R1796 */ + 0x0000, /* R1797 */ + 0x0000, /* R1798 */ + 0x0000, /* R1799 */ + 0x0000, /* R1800 */ + 0x0000, /* R1801 */ + 0x0000, /* R1802 */ + 0x0000, /* R1803 */ + 0x0000, /* R1804 */ + 0x0000, /* R1805 */ + 0x0000, /* R1806 */ + 0x0000, /* R1807 */ + 0x0000, /* R1808 */ + 0x0000, /* R1809 */ + 0x0000, /* R1810 */ + 0x0000, /* R1811 */ + 0x0000, /* R1812 */ + 0x0000, /* R1813 */ + 0x0000, /* R1814 */ + 0x0000, /* R1815 */ + 0x0000, /* R1816 */ + 0x0000, /* R1817 */ + 0x0000, /* R1818 */ + 0x0000, /* R1819 */ + 0x0000, /* R1820 */ + 0x0000, /* R1821 */ + 0x0000, /* R1822 */ + 0x0000, /* R1823 */ + 0x0000, /* R1824 */ + 0x0000, /* R1825 */ + 0x0000, /* R1826 */ + 0x0000, /* R1827 */ + 0x0000, /* R1828 */ + 0x0000, /* R1829 */ + 0x0000, /* R1830 */ + 0x0000, /* R1831 */ + 0x0000, /* R1832 */ + 0x0000, /* R1833 */ + 0x0000, /* R1834 */ + 0x0000, /* R1835 */ + 0x0000, /* R1836 */ + 0x0000, /* R1837 */ + 0x0000, /* R1838 */ + 0x0000, /* R1839 */ + 0x0000, /* R1840 */ + 0x0000, /* R1841 */ + 0x0000, /* R1842 */ + 0x0000, /* R1843 */ + 0x0000, /* R1844 */ + 0x0000, /* R1845 */ + 0x0000, /* R1846 */ + 0x0000, /* R1847 */ + 0x0000, /* R1848 */ + 0x0000, /* R1849 */ + 0x0000, /* R1850 */ + 0x0000, /* R1851 */ + 0x0000, /* R1852 */ + 0x0000, /* R1853 */ + 0x0000, /* R1854 */ + 0x0000, /* R1855 */ + 0x0000, /* R1856 */ + 0x0000, /* R1857 */ + 0x0000, /* R1858 */ + 0x0000, /* R1859 */ + 0x0000, /* R1860 */ + 0x0000, /* R1861 */ + 0x0000, /* R1862 */ + 0x0000, /* R1863 */ + 0x0000, /* R1864 */ + 0x0000, /* R1865 */ + 0x0000, /* R1866 */ + 0x0000, /* R1867 */ + 0x0000, /* R1868 */ + 0x0000, /* R1869 */ + 0x0000, /* R1870 */ + 0x0000, /* R1871 */ + 0x0000, /* R1872 */ + 0x0000, /* R1873 */ + 0x0000, /* R1874 */ + 0x0000, /* R1875 */ + 0x0000, /* R1876 */ + 0x0000, /* R1877 */ + 0x0000, /* R1878 */ + 0x0000, /* R1879 */ + 0x0000, /* R1880 */ + 0x0000, /* R1881 */ + 0x0000, /* R1882 */ + 0x0000, /* R1883 */ + 0x0000, /* R1884 */ + 0x0000, /* R1885 */ + 0x0000, /* R1886 */ + 0x0000, /* R1887 */ + 0x0000, /* R1888 */ + 0x0000, /* R1889 */ + 0x0000, /* R1890 */ + 0x0000, /* R1891 */ + 0x0000, /* R1892 */ + 0x0000, /* R1893 */ + 0x0000, /* R1894 */ + 0x0000, /* R1895 */ + 0x0000, /* R1896 */ + 0x0000, /* R1897 */ + 0x0000, /* R1898 */ + 0x0000, /* R1899 */ + 0x0000, /* R1900 */ + 0x0000, /* R1901 */ + 0x0000, /* R1902 */ + 0x0000, /* R1903 */ + 0x0000, /* R1904 */ + 0x0000, /* R1905 */ + 0x0000, /* R1906 */ + 0x0000, /* R1907 */ + 0x0000, /* R1908 */ + 0x0000, /* R1909 */ + 0x0000, /* R1910 */ + 0x0000, /* R1911 */ + 0x0000, /* R1912 */ + 0x0000, /* R1913 */ + 0x0000, /* R1914 */ + 0x0000, /* R1915 */ + 0x0000, /* R1916 */ + 0x0000, /* R1917 */ + 0x0000, /* R1918 */ + 0x0000, /* R1919 */ + 0x0000, /* R1920 */ + 0x0000, /* R1921 */ + 0x0000, /* R1922 */ + 0x0000, /* R1923 */ + 0x0000, /* R1924 */ + 0x0000, /* R1925 */ + 0x0000, /* R1926 */ + 0x0000, /* R1927 */ + 0x0000, /* R1928 */ + 0x0000, /* R1929 */ + 0x0000, /* R1930 */ + 0x0000, /* R1931 */ + 0x0000, /* R1932 */ + 0x0000, /* R1933 */ + 0x0000, /* R1934 */ + 0x0000, /* R1935 */ + 0x0000, /* R1936 */ + 0x0000, /* R1937 */ + 0x0000, /* R1938 */ + 0x0000, /* R1939 */ + 0x0000, /* R1940 */ + 0x0000, /* R1941 */ + 0x0000, /* R1942 */ + 0x0000, /* R1943 */ + 0x0000, /* R1944 */ + 0x0000, /* R1945 */ + 0x0000, /* R1946 */ + 0x0000, /* R1947 */ + 0x0000, /* R1948 */ + 0x0000, /* R1949 */ + 0x0000, /* R1950 */ + 0x0000, /* R1951 */ + 0x0000, /* R1952 */ + 0x0000, /* R1953 */ + 0x0000, /* R1954 */ + 0x0000, /* R1955 */ + 0x0000, /* R1956 */ + 0x0000, /* R1957 */ + 0x0000, /* R1958 */ + 0x0000, /* R1959 */ + 0x0000, /* R1960 */ + 0x0000, /* R1961 */ + 0x0000, /* R1962 */ + 0x0000, /* R1963 */ + 0x0000, /* R1964 */ + 0x0000, /* R1965 */ + 0x0000, /* R1966 */ + 0x0000, /* R1967 */ + 0x0000, /* R1968 */ + 0x0000, /* R1969 */ + 0x0000, /* R1970 */ + 0x0000, /* R1971 */ + 0x0000, /* R1972 */ + 0x0000, /* R1973 */ + 0x0000, /* R1974 */ + 0x0000, /* R1975 */ + 0x0000, /* R1976 */ + 0x0000, /* R1977 */ + 0x0000, /* R1978 */ + 0x0000, /* R1979 */ + 0x0000, /* R1980 */ + 0x0000, /* R1981 */ + 0x0000, /* R1982 */ + 0x0000, /* R1983 */ + 0x0000, /* R1984 */ + 0x0000, /* R1985 */ + 0x0000, /* R1986 */ + 0x0000, /* R1987 */ + 0x0000, /* R1988 */ + 0x0000, /* R1989 */ + 0x0000, /* R1990 */ + 0x0000, /* R1991 */ + 0x0000, /* R1992 */ + 0x0000, /* R1993 */ + 0x0000, /* R1994 */ + 0x0000, /* R1995 */ + 0x0000, /* R1996 */ + 0x0000, /* R1997 */ + 0x0000, /* R1998 */ + 0x0000, /* R1999 */ + 0x0000, /* R2000 */ + 0x0000, /* R2001 */ + 0x0000, /* R2002 */ + 0x0000, /* R2003 */ + 0x0000, /* R2004 */ + 0x0000, /* R2005 */ + 0x0000, /* R2006 */ + 0x0000, /* R2007 */ + 0x0000, /* R2008 */ + 0x0000, /* R2009 */ + 0x0000, /* R2010 */ + 0x0000, /* R2011 */ + 0x0000, /* R2012 */ + 0x0000, /* R2013 */ + 0x0000, /* R2014 */ + 0x0000, /* R2015 */ + 0x0000, /* R2016 */ + 0x0000, /* R2017 */ + 0x0000, /* R2018 */ + 0x0000, /* R2019 */ + 0x0000, /* R2020 */ + 0x0000, /* R2021 */ + 0x0000, /* R2022 */ + 0x0000, /* R2023 */ + 0x0000, /* R2024 */ + 0x0000, /* R2025 */ + 0x0000, /* R2026 */ + 0x0000, /* R2027 */ + 0x0000, /* R2028 */ + 0x0000, /* R2029 */ + 0x0000, /* R2030 */ + 0x0000, /* R2031 */ + 0x0000, /* R2032 */ + 0x0000, /* R2033 */ + 0x0000, /* R2034 */ + 0x0000, /* R2035 */ + 0x0000, /* R2036 */ + 0x0000, /* R2037 */ + 0x0000, /* R2038 */ + 0x0000, /* R2039 */ + 0x0000, /* R2040 */ + 0x0000, /* R2041 */ + 0x0000, /* R2042 */ + 0x0000, /* R2043 */ + 0x0000, /* R2044 */ + 0x0000, /* R2045 */ + 0x0000, /* R2046 */ + 0x0000, /* R2047 */ + 0x0000, /* R2048 */ + 0x0000, /* R2049 */ + 0x0000, /* R2050 */ + 0x0000, /* R2051 */ + 0x0000, /* R2052 */ + 0x0000, /* R2053 */ + 0x0000, /* R2054 */ + 0x0000, /* R2055 */ + 0x0000, /* R2056 */ + 0x0000, /* R2057 */ + 0x0000, /* R2058 */ + 0x0000, /* R2059 */ + 0x0000, /* R2060 */ + 0x0000, /* R2061 */ + 0x0000, /* R2062 */ + 0x0000, /* R2063 */ + 0x0000, /* R2064 */ + 0x0000, /* R2065 */ + 0x0000, /* R2066 */ + 0x0000, /* R2067 */ + 0x0000, /* R2068 */ + 0x0000, /* R2069 */ + 0x0000, /* R2070 */ + 0x0000, /* R2071 */ + 0x0000, /* R2072 */ + 0x0000, /* R2073 */ + 0x0000, /* R2074 */ + 0x0000, /* R2075 */ + 0x0000, /* R2076 */ + 0x0000, /* R2077 */ + 0x0000, /* R2078 */ + 0x0000, /* R2079 */ + 0x0000, /* R2080 */ + 0x0000, /* R2081 */ + 0x0000, /* R2082 */ + 0x0000, /* R2083 */ + 0x0000, /* R2084 */ + 0x0000, /* R2085 */ + 0x0000, /* R2086 */ + 0x0000, /* R2087 */ + 0x0000, /* R2088 */ + 0x0000, /* R2089 */ + 0x0000, /* R2090 */ + 0x0000, /* R2091 */ + 0x0000, /* R2092 */ + 0x0000, /* R2093 */ + 0x0000, /* R2094 */ + 0x0000, /* R2095 */ + 0x0000, /* R2096 */ + 0x0000, /* R2097 */ + 0x0000, /* R2098 */ + 0x0000, /* R2099 */ + 0x0000, /* R2100 */ + 0x0000, /* R2101 */ + 0x0000, /* R2102 */ + 0x0000, /* R2103 */ + 0x0000, /* R2104 */ + 0x0000, /* R2105 */ + 0x0000, /* R2106 */ + 0x0000, /* R2107 */ + 0x0000, /* R2108 */ + 0x0000, /* R2109 */ + 0x0000, /* R2110 */ + 0x0000, /* R2111 */ + 0x0000, /* R2112 */ + 0x0000, /* R2113 */ + 0x0000, /* R2114 */ + 0x0000, /* R2115 */ + 0x0000, /* R2116 */ + 0x0000, /* R2117 */ + 0x0000, /* R2118 */ + 0x0000, /* R2119 */ + 0x0000, /* R2120 */ + 0x0000, /* R2121 */ + 0x0000, /* R2122 */ + 0x0000, /* R2123 */ + 0x0000, /* R2124 */ + 0x0000, /* R2125 */ + 0x0000, /* R2126 */ + 0x0000, /* R2127 */ + 0x0000, /* R2128 */ + 0x0000, /* R2129 */ + 0x0000, /* R2130 */ + 0x0000, /* R2131 */ + 0x0000, /* R2132 */ + 0x0000, /* R2133 */ + 0x0000, /* R2134 */ + 0x0000, /* R2135 */ + 0x0000, /* R2136 */ + 0x0000, /* R2137 */ + 0x0000, /* R2138 */ + 0x0000, /* R2139 */ + 0x0000, /* R2140 */ + 0x0000, /* R2141 */ + 0x0000, /* R2142 */ + 0x0000, /* R2143 */ + 0x0000, /* R2144 */ + 0x0000, /* R2145 */ + 0x0000, /* R2146 */ + 0x0000, /* R2147 */ + 0x0000, /* R2148 */ + 0x0000, /* R2149 */ + 0x0000, /* R2150 */ + 0x0000, /* R2151 */ + 0x0000, /* R2152 */ + 0x0000, /* R2153 */ + 0x0000, /* R2154 */ + 0x0000, /* R2155 */ + 0x0000, /* R2156 */ + 0x0000, /* R2157 */ + 0x0000, /* R2158 */ + 0x0000, /* R2159 */ + 0x0000, /* R2160 */ + 0x0000, /* R2161 */ + 0x0000, /* R2162 */ + 0x0000, /* R2163 */ + 0x0000, /* R2164 */ + 0x0000, /* R2165 */ + 0x0000, /* R2166 */ + 0x0000, /* R2167 */ + 0x0000, /* R2168 */ + 0x0000, /* R2169 */ + 0x0000, /* R2170 */ + 0x0000, /* R2171 */ + 0x0000, /* R2172 */ + 0x0000, /* R2173 */ + 0x0000, /* R2174 */ + 0x0000, /* R2175 */ + 0x0000, /* R2176 */ + 0x0000, /* R2177 */ + 0x0000, /* R2178 */ + 0x0000, /* R2179 */ + 0x0000, /* R2180 */ + 0x0000, /* R2181 */ + 0x0000, /* R2182 */ + 0x0000, /* R2183 */ + 0x0000, /* R2184 */ + 0x0000, /* R2185 */ + 0x0000, /* R2186 */ + 0x0000, /* R2187 */ + 0x0000, /* R2188 */ + 0x0000, /* R2189 */ + 0x0000, /* R2190 */ + 0x0000, /* R2191 */ + 0x0000, /* R2192 */ + 0x0000, /* R2193 */ + 0x0000, /* R2194 */ + 0x0000, /* R2195 */ + 0x0000, /* R2196 */ + 0x0000, /* R2197 */ + 0x0000, /* R2198 */ + 0x0000, /* R2199 */ + 0x0000, /* R2200 */ + 0x0000, /* R2201 */ + 0x0000, /* R2202 */ + 0x0000, /* R2203 */ + 0x0000, /* R2204 */ + 0x0000, /* R2205 */ + 0x0000, /* R2206 */ + 0x0000, /* R2207 */ + 0x0000, /* R2208 */ + 0x0000, /* R2209 */ + 0x0000, /* R2210 */ + 0x0000, /* R2211 */ + 0x0000, /* R2212 */ + 0x0000, /* R2213 */ + 0x0000, /* R2214 */ + 0x0000, /* R2215 */ + 0x0000, /* R2216 */ + 0x0000, /* R2217 */ + 0x0000, /* R2218 */ + 0x0000, /* R2219 */ + 0x0000, /* R2220 */ + 0x0000, /* R2221 */ + 0x0000, /* R2222 */ + 0x0000, /* R2223 */ + 0x0000, /* R2224 */ + 0x0000, /* R2225 */ + 0x0000, /* R2226 */ + 0x0000, /* R2227 */ + 0x0000, /* R2228 */ + 0x0000, /* R2229 */ + 0x0000, /* R2230 */ + 0x0000, /* R2231 */ + 0x0000, /* R2232 */ + 0x0000, /* R2233 */ + 0x0000, /* R2234 */ + 0x0000, /* R2235 */ + 0x0000, /* R2236 */ + 0x0000, /* R2237 */ + 0x0000, /* R2238 */ + 0x0000, /* R2239 */ + 0x0000, /* R2240 */ + 0x0000, /* R2241 */ + 0x0000, /* R2242 */ + 0x0000, /* R2243 */ + 0x0000, /* R2244 */ + 0x0000, /* R2245 */ + 0x0000, /* R2246 */ + 0x0000, /* R2247 */ + 0x0000, /* R2248 */ + 0x0000, /* R2249 */ + 0x0000, /* R2250 */ + 0x0000, /* R2251 */ + 0x0000, /* R2252 */ + 0x0000, /* R2253 */ + 0x0000, /* R2254 */ + 0x0000, /* R2255 */ + 0x0000, /* R2256 */ + 0x0000, /* R2257 */ + 0x0000, /* R2258 */ + 0x0000, /* R2259 */ + 0x0000, /* R2260 */ + 0x0000, /* R2261 */ + 0x0000, /* R2262 */ + 0x0000, /* R2263 */ + 0x0000, /* R2264 */ + 0x0000, /* R2265 */ + 0x0000, /* R2266 */ + 0x0000, /* R2267 */ + 0x0000, /* R2268 */ + 0x0000, /* R2269 */ + 0x0000, /* R2270 */ + 0x0000, /* R2271 */ + 0x0000, /* R2272 */ + 0x0000, /* R2273 */ + 0x0000, /* R2274 */ + 0x0000, /* R2275 */ + 0x0000, /* R2276 */ + 0x0000, /* R2277 */ + 0x0000, /* R2278 */ + 0x0000, /* R2279 */ + 0x0000, /* R2280 */ + 0x0000, /* R2281 */ + 0x0000, /* R2282 */ + 0x0000, /* R2283 */ + 0x0000, /* R2284 */ + 0x0000, /* R2285 */ + 0x0000, /* R2286 */ + 0x0000, /* R2287 */ + 0x0000, /* R2288 */ + 0x0000, /* R2289 */ + 0x0000, /* R2290 */ + 0x0000, /* R2291 */ + 0x0000, /* R2292 */ + 0x0000, /* R2293 */ + 0x0000, /* R2294 */ + 0x0000, /* R2295 */ + 0x0000, /* R2296 */ + 0x0000, /* R2297 */ + 0x0000, /* R2298 */ + 0x0000, /* R2299 */ + 0x0000, /* R2300 */ + 0x0000, /* R2301 */ + 0x0000, /* R2302 */ + 0x0000, /* R2303 */ + 0x0000, /* R2304 */ + 0x0000, /* R2305 */ + 0x0000, /* R2306 */ + 0x0000, /* R2307 */ + 0x0000, /* R2308 */ + 0x0000, /* R2309 */ + 0x0000, /* R2310 */ + 0x0000, /* R2311 */ + 0x0000, /* R2312 */ + 0x0000, /* R2313 */ + 0x0000, /* R2314 */ + 0x0000, /* R2315 */ + 0x0000, /* R2316 */ + 0x0000, /* R2317 */ + 0x0000, /* R2318 */ + 0x0000, /* R2319 */ + 0x0000, /* R2320 */ + 0x0000, /* R2321 */ + 0x0000, /* R2322 */ + 0x0000, /* R2323 */ + 0x0000, /* R2324 */ + 0x0000, /* R2325 */ + 0x0000, /* R2326 */ + 0x0000, /* R2327 */ + 0x0000, /* R2328 */ + 0x0000, /* R2329 */ + 0x0000, /* R2330 */ + 0x0000, /* R2331 */ + 0x0000, /* R2332 */ + 0x0000, /* R2333 */ + 0x0000, /* R2334 */ + 0x0000, /* R2335 */ + 0x0000, /* R2336 */ + 0x0000, /* R2337 */ + 0x0000, /* R2338 */ + 0x0000, /* R2339 */ + 0x0000, /* R2340 */ + 0x0000, /* R2341 */ + 0x0000, /* R2342 */ + 0x0000, /* R2343 */ + 0x0000, /* R2344 */ + 0x0000, /* R2345 */ + 0x0000, /* R2346 */ + 0x0000, /* R2347 */ + 0x0000, /* R2348 */ + 0x0000, /* R2349 */ + 0x0000, /* R2350 */ + 0x0000, /* R2351 */ + 0x0000, /* R2352 */ + 0x0000, /* R2353 */ + 0x0000, /* R2354 */ + 0x0000, /* R2355 */ + 0x0000, /* R2356 */ + 0x0000, /* R2357 */ + 0x0000, /* R2358 */ + 0x0000, /* R2359 */ + 0x0000, /* R2360 */ + 0x0000, /* R2361 */ + 0x0000, /* R2362 */ + 0x0000, /* R2363 */ + 0x0000, /* R2364 */ + 0x0000, /* R2365 */ + 0x0000, /* R2366 */ + 0x0000, /* R2367 */ + 0x0000, /* R2368 */ + 0x0000, /* R2369 */ + 0x0000, /* R2370 */ + 0x0000, /* R2371 */ + 0x0000, /* R2372 */ + 0x0000, /* R2373 */ + 0x0000, /* R2374 */ + 0x0000, /* R2375 */ + 0x0000, /* R2376 */ + 0x0000, /* R2377 */ + 0x0000, /* R2378 */ + 0x0000, /* R2379 */ + 0x0000, /* R2380 */ + 0x0000, /* R2381 */ + 0x0000, /* R2382 */ + 0x0000, /* R2383 */ + 0x0000, /* R2384 */ + 0x0000, /* R2385 */ + 0x0000, /* R2386 */ + 0x0000, /* R2387 */ + 0x0000, /* R2388 */ + 0x0000, /* R2389 */ + 0x0000, /* R2390 */ + 0x0000, /* R2391 */ + 0x0000, /* R2392 */ + 0x0000, /* R2393 */ + 0x0000, /* R2394 */ + 0x0000, /* R2395 */ + 0x0000, /* R2396 */ + 0x0000, /* R2397 */ + 0x0000, /* R2398 */ + 0x0000, /* R2399 */ + 0x0000, /* R2400 */ + 0x0000, /* R2401 */ + 0x0000, /* R2402 */ + 0x0000, /* R2403 */ + 0x0000, /* R2404 */ + 0x0000, /* R2405 */ + 0x0000, /* R2406 */ + 0x0000, /* R2407 */ + 0x0000, /* R2408 */ + 0x0000, /* R2409 */ + 0x0000, /* R2410 */ + 0x0000, /* R2411 */ + 0x0000, /* R2412 */ + 0x0000, /* R2413 */ + 0x0000, /* R2414 */ + 0x0000, /* R2415 */ + 0x0000, /* R2416 */ + 0x0000, /* R2417 */ + 0x0000, /* R2418 */ + 0x0000, /* R2419 */ + 0x0000, /* R2420 */ + 0x0000, /* R2421 */ + 0x0000, /* R2422 */ + 0x0000, /* R2423 */ + 0x0000, /* R2424 */ + 0x0000, /* R2425 */ + 0x0000, /* R2426 */ + 0x0000, /* R2427 */ + 0x0000, /* R2428 */ + 0x0000, /* R2429 */ + 0x0000, /* R2430 */ + 0x0000, /* R2431 */ + 0x0000, /* R2432 */ + 0x0000, /* R2433 */ + 0x0000, /* R2434 */ + 0x0000, /* R2435 */ + 0x0000, /* R2436 */ + 0x0000, /* R2437 */ + 0x0000, /* R2438 */ + 0x0000, /* R2439 */ + 0x0000, /* R2440 */ + 0x0000, /* R2441 */ + 0x0000, /* R2442 */ + 0x0000, /* R2443 */ + 0x0000, /* R2444 */ + 0x0000, /* R2445 */ + 0x0000, /* R2446 */ + 0x0000, /* R2447 */ + 0x0000, /* R2448 */ + 0x0000, /* R2449 */ + 0x0000, /* R2450 */ + 0x0000, /* R2451 */ + 0x0000, /* R2452 */ + 0x0000, /* R2453 */ + 0x0000, /* R2454 */ + 0x0000, /* R2455 */ + 0x0000, /* R2456 */ + 0x0000, /* R2457 */ + 0x0000, /* R2458 */ + 0x0000, /* R2459 */ + 0x0000, /* R2460 */ + 0x0000, /* R2461 */ + 0x0000, /* R2462 */ + 0x0000, /* R2463 */ + 0x0000, /* R2464 */ + 0x0000, /* R2465 */ + 0x0000, /* R2466 */ + 0x0000, /* R2467 */ + 0x0000, /* R2468 */ + 0x0000, /* R2469 */ + 0x0000, /* R2470 */ + 0x0000, /* R2471 */ + 0x0000, /* R2472 */ + 0x0000, /* R2473 */ + 0x0000, /* R2474 */ + 0x0000, /* R2475 */ + 0x0000, /* R2476 */ + 0x0000, /* R2477 */ + 0x0000, /* R2478 */ + 0x0000, /* R2479 */ + 0x0000, /* R2480 */ + 0x0000, /* R2481 */ + 0x0000, /* R2482 */ + 0x0000, /* R2483 */ + 0x0000, /* R2484 */ + 0x0000, /* R2485 */ + 0x0000, /* R2486 */ + 0x0000, /* R2487 */ + 0x0000, /* R2488 */ + 0x0000, /* R2489 */ + 0x0000, /* R2490 */ + 0x0000, /* R2491 */ + 0x0000, /* R2492 */ + 0x0000, /* R2493 */ + 0x0000, /* R2494 */ + 0x0000, /* R2495 */ + 0x0000, /* R2496 */ + 0x0000, /* R2497 */ + 0x0000, /* R2498 */ + 0x0000, /* R2499 */ + 0x0000, /* R2500 */ + 0x0000, /* R2501 */ + 0x0000, /* R2502 */ + 0x0000, /* R2503 */ + 0x0000, /* R2504 */ + 0x0000, /* R2505 */ + 0x0000, /* R2506 */ + 0x0000, /* R2507 */ + 0x0000, /* R2508 */ + 0x0000, /* R2509 */ + 0x0000, /* R2510 */ + 0x0000, /* R2511 */ + 0x0000, /* R2512 */ + 0x0000, /* R2513 */ + 0x0000, /* R2514 */ + 0x0000, /* R2515 */ + 0x0000, /* R2516 */ + 0x0000, /* R2517 */ + 0x0000, /* R2518 */ + 0x0000, /* R2519 */ + 0x0000, /* R2520 */ + 0x0000, /* R2521 */ + 0x0000, /* R2522 */ + 0x0000, /* R2523 */ + 0x0000, /* R2524 */ + 0x0000, /* R2525 */ + 0x0000, /* R2526 */ + 0x0000, /* R2527 */ + 0x0000, /* R2528 */ + 0x0000, /* R2529 */ + 0x0000, /* R2530 */ + 0x0000, /* R2531 */ + 0x0000, /* R2532 */ + 0x0000, /* R2533 */ + 0x0000, /* R2534 */ + 0x0000, /* R2535 */ + 0x0000, /* R2536 */ + 0x0000, /* R2537 */ + 0x0000, /* R2538 */ + 0x0000, /* R2539 */ + 0x0000, /* R2540 */ + 0x0000, /* R2541 */ + 0x0000, /* R2542 */ + 0x0000, /* R2543 */ + 0x0000, /* R2544 */ + 0x0000, /* R2545 */ + 0x0000, /* R2546 */ + 0x0000, /* R2547 */ + 0x0000, /* R2548 */ + 0x0000, /* R2549 */ + 0x0000, /* R2550 */ + 0x0000, /* R2551 */ + 0x0000, /* R2552 */ + 0x0000, /* R2553 */ + 0x0000, /* R2554 */ + 0x0000, /* R2555 */ + 0x0000, /* R2556 */ + 0x0000, /* R2557 */ + 0x0000, /* R2558 */ + 0x0000, /* R2559 */ + 0x0000, /* R2560 */ + 0x0000, /* R2561 */ + 0x0000, /* R2562 */ + 0x0000, /* R2563 */ + 0x0000, /* R2564 */ + 0x0000, /* R2565 */ + 0x0000, /* R2566 */ + 0x0000, /* R2567 */ + 0x0000, /* R2568 */ + 0x0000, /* R2569 */ + 0x0000, /* R2570 */ + 0x0000, /* R2571 */ + 0x0000, /* R2572 */ + 0x0000, /* R2573 */ + 0x0000, /* R2574 */ + 0x0000, /* R2575 */ + 0x0000, /* R2576 */ + 0x0000, /* R2577 */ + 0x0000, /* R2578 */ + 0x0000, /* R2579 */ + 0x0000, /* R2580 */ + 0x0000, /* R2581 */ + 0x0000, /* R2582 */ + 0x0000, /* R2583 */ + 0x0000, /* R2584 */ + 0x0000, /* R2585 */ + 0x0000, /* R2586 */ + 0x0000, /* R2587 */ + 0x0000, /* R2588 */ + 0x0000, /* R2589 */ + 0x0000, /* R2590 */ + 0x0000, /* R2591 */ + 0x0000, /* R2592 */ + 0x0000, /* R2593 */ + 0x0000, /* R2594 */ + 0x0000, /* R2595 */ + 0x0000, /* R2596 */ + 0x0000, /* R2597 */ + 0x0000, /* R2598 */ + 0x0000, /* R2599 */ + 0x0000, /* R2600 */ + 0x0000, /* R2601 */ + 0x0000, /* R2602 */ + 0x0000, /* R2603 */ + 0x0000, /* R2604 */ + 0x0000, /* R2605 */ + 0x0000, /* R2606 */ + 0x0000, /* R2607 */ + 0x0000, /* R2608 */ + 0x0000, /* R2609 */ + 0x0000, /* R2610 */ + 0x0000, /* R2611 */ + 0x0000, /* R2612 */ + 0x0000, /* R2613 */ + 0x0000, /* R2614 */ + 0x0000, /* R2615 */ + 0x0000, /* R2616 */ + 0x0000, /* R2617 */ + 0x0000, /* R2618 */ + 0x0000, /* R2619 */ + 0x0000, /* R2620 */ + 0x0000, /* R2621 */ + 0x0000, /* R2622 */ + 0x0000, /* R2623 */ + 0x0000, /* R2624 */ + 0x0000, /* R2625 */ + 0x0000, /* R2626 */ + 0x0000, /* R2627 */ + 0x0000, /* R2628 */ + 0x0000, /* R2629 */ + 0x0000, /* R2630 */ + 0x0000, /* R2631 */ + 0x0000, /* R2632 */ + 0x0000, /* R2633 */ + 0x0000, /* R2634 */ + 0x0000, /* R2635 */ + 0x0000, /* R2636 */ + 0x0000, /* R2637 */ + 0x0000, /* R2638 */ + 0x0000, /* R2639 */ + 0x0000, /* R2640 */ + 0x0000, /* R2641 */ + 0x0000, /* R2642 */ + 0x0000, /* R2643 */ + 0x0000, /* R2644 */ + 0x0000, /* R2645 */ + 0x0000, /* R2646 */ + 0x0000, /* R2647 */ + 0x0000, /* R2648 */ + 0x0000, /* R2649 */ + 0x0000, /* R2650 */ + 0x0000, /* R2651 */ + 0x0000, /* R2652 */ + 0x0000, /* R2653 */ + 0x0000, /* R2654 */ + 0x0000, /* R2655 */ + 0x0000, /* R2656 */ + 0x0000, /* R2657 */ + 0x0000, /* R2658 */ + 0x0000, /* R2659 */ + 0x0000, /* R2660 */ + 0x0000, /* R2661 */ + 0x0000, /* R2662 */ + 0x0000, /* R2663 */ + 0x0000, /* R2664 */ + 0x0000, /* R2665 */ + 0x0000, /* R2666 */ + 0x0000, /* R2667 */ + 0x0000, /* R2668 */ + 0x0000, /* R2669 */ + 0x0000, /* R2670 */ + 0x0000, /* R2671 */ + 0x0000, /* R2672 */ + 0x0000, /* R2673 */ + 0x0000, /* R2674 */ + 0x0000, /* R2675 */ + 0x0000, /* R2676 */ + 0x0000, /* R2677 */ + 0x0000, /* R2678 */ + 0x0000, /* R2679 */ + 0x0000, /* R2680 */ + 0x0000, /* R2681 */ + 0x0000, /* R2682 */ + 0x0000, /* R2683 */ + 0x0000, /* R2684 */ + 0x0000, /* R2685 */ + 0x0000, /* R2686 */ + 0x0000, /* R2687 */ + 0x0000, /* R2688 */ + 0x0000, /* R2689 */ + 0x0000, /* R2690 */ + 0x0000, /* R2691 */ + 0x0000, /* R2692 */ + 0x0000, /* R2693 */ + 0x0000, /* R2694 */ + 0x0000, /* R2695 */ + 0x0000, /* R2696 */ + 0x0000, /* R2697 */ + 0x0000, /* R2698 */ + 0x0000, /* R2699 */ + 0x0000, /* R2700 */ + 0x0000, /* R2701 */ + 0x0000, /* R2702 */ + 0x0000, /* R2703 */ + 0x0000, /* R2704 */ + 0x0000, /* R2705 */ + 0x0000, /* R2706 */ + 0x0000, /* R2707 */ + 0x0000, /* R2708 */ + 0x0000, /* R2709 */ + 0x0000, /* R2710 */ + 0x0000, /* R2711 */ + 0x0000, /* R2712 */ + 0x0000, /* R2713 */ + 0x0000, /* R2714 */ + 0x0000, /* R2715 */ + 0x0000, /* R2716 */ + 0x0000, /* R2717 */ + 0x0000, /* R2718 */ + 0x0000, /* R2719 */ + 0x0000, /* R2720 */ + 0x0000, /* R2721 */ + 0x0000, /* R2722 */ + 0x0000, /* R2723 */ + 0x0000, /* R2724 */ + 0x0000, /* R2725 */ + 0x0000, /* R2726 */ + 0x0000, /* R2727 */ + 0x0000, /* R2728 */ + 0x0000, /* R2729 */ + 0x0000, /* R2730 */ + 0x0000, /* R2731 */ + 0x0000, /* R2732 */ + 0x0000, /* R2733 */ + 0x0000, /* R2734 */ + 0x0000, /* R2735 */ + 0x0000, /* R2736 */ + 0x0000, /* R2737 */ + 0x0000, /* R2738 */ + 0x0000, /* R2739 */ + 0x0000, /* R2740 */ + 0x0000, /* R2741 */ + 0x0000, /* R2742 */ + 0x0000, /* R2743 */ + 0x0000, /* R2744 */ + 0x0000, /* R2745 */ + 0x0000, /* R2746 */ + 0x0000, /* R2747 */ + 0x0000, /* R2748 */ + 0x0000, /* R2749 */ + 0x0000, /* R2750 */ + 0x0000, /* R2751 */ + 0x0000, /* R2752 */ + 0x0000, /* R2753 */ + 0x0000, /* R2754 */ + 0x0000, /* R2755 */ + 0x0000, /* R2756 */ + 0x0000, /* R2757 */ + 0x0000, /* R2758 */ + 0x0000, /* R2759 */ + 0x0000, /* R2760 */ + 0x0000, /* R2761 */ + 0x0000, /* R2762 */ + 0x0000, /* R2763 */ + 0x0000, /* R2764 */ + 0x0000, /* R2765 */ + 0x0000, /* R2766 */ + 0x0000, /* R2767 */ + 0x0000, /* R2768 */ + 0x0000, /* R2769 */ + 0x0000, /* R2770 */ + 0x0000, /* R2771 */ + 0x0000, /* R2772 */ + 0x0000, /* R2773 */ + 0x0000, /* R2774 */ + 0x0000, /* R2775 */ + 0x0000, /* R2776 */ + 0x0000, /* R2777 */ + 0x0000, /* R2778 */ + 0x0000, /* R2779 */ + 0x0000, /* R2780 */ + 0x0000, /* R2781 */ + 0x0000, /* R2782 */ + 0x0000, /* R2783 */ + 0x0000, /* R2784 */ + 0x0000, /* R2785 */ + 0x0000, /* R2786 */ + 0x0000, /* R2787 */ + 0x0000, /* R2788 */ + 0x0000, /* R2789 */ + 0x0000, /* R2790 */ + 0x0000, /* R2791 */ + 0x0000, /* R2792 */ + 0x0000, /* R2793 */ + 0x0000, /* R2794 */ + 0x0000, /* R2795 */ + 0x0000, /* R2796 */ + 0x0000, /* R2797 */ + 0x0000, /* R2798 */ + 0x0000, /* R2799 */ + 0x0000, /* R2800 */ + 0x0000, /* R2801 */ + 0x0000, /* R2802 */ + 0x0000, /* R2803 */ + 0x0000, /* R2804 */ + 0x0000, /* R2805 */ + 0x0000, /* R2806 */ + 0x0000, /* R2807 */ + 0x0000, /* R2808 */ + 0x0000, /* R2809 */ + 0x0000, /* R2810 */ + 0x0000, /* R2811 */ + 0x0000, /* R2812 */ + 0x0000, /* R2813 */ + 0x0000, /* R2814 */ + 0x0000, /* R2815 */ + 0x0000, /* R2816 */ + 0x0000, /* R2817 */ + 0x0000, /* R2818 */ + 0x0000, /* R2819 */ + 0x0000, /* R2820 */ + 0x0000, /* R2821 */ + 0x0000, /* R2822 */ + 0x0000, /* R2823 */ + 0x0000, /* R2824 */ + 0x0000, /* R2825 */ + 0x0000, /* R2826 */ + 0x0000, /* R2827 */ + 0x0000, /* R2828 */ + 0x0000, /* R2829 */ + 0x0000, /* R2830 */ + 0x0000, /* R2831 */ + 0x0000, /* R2832 */ + 0x0000, /* R2833 */ + 0x0000, /* R2834 */ + 0x0000, /* R2835 */ + 0x0000, /* R2836 */ + 0x0000, /* R2837 */ + 0x0000, /* R2838 */ + 0x0000, /* R2839 */ + 0x0000, /* R2840 */ + 0x0000, /* R2841 */ + 0x0000, /* R2842 */ + 0x0000, /* R2843 */ + 0x0000, /* R2844 */ + 0x0000, /* R2845 */ + 0x0000, /* R2846 */ + 0x0000, /* R2847 */ + 0x0000, /* R2848 */ + 0x0000, /* R2849 */ + 0x0000, /* R2850 */ + 0x0000, /* R2851 */ + 0x0000, /* R2852 */ + 0x0000, /* R2853 */ + 0x0000, /* R2854 */ + 0x0000, /* R2855 */ + 0x0000, /* R2856 */ + 0x0000, /* R2857 */ + 0x0000, /* R2858 */ + 0x0000, /* R2859 */ + 0x0000, /* R2860 */ + 0x0000, /* R2861 */ + 0x0000, /* R2862 */ + 0x0000, /* R2863 */ + 0x0000, /* R2864 */ + 0x0000, /* R2865 */ + 0x0000, /* R2866 */ + 0x0000, /* R2867 */ + 0x0000, /* R2868 */ + 0x0000, /* R2869 */ + 0x0000, /* R2870 */ + 0x0000, /* R2871 */ + 0x0000, /* R2872 */ + 0x0000, /* R2873 */ + 0x0000, /* R2874 */ + 0x0000, /* R2875 */ + 0x0000, /* R2876 */ + 0x0000, /* R2877 */ + 0x0000, /* R2878 */ + 0x0000, /* R2879 */ + 0x0000, /* R2880 */ + 0x0000, /* R2881 */ + 0x0000, /* R2882 */ + 0x0000, /* R2883 */ + 0x0000, /* R2884 */ + 0x0000, /* R2885 */ + 0x0000, /* R2886 */ + 0x0000, /* R2887 */ + 0x0000, /* R2888 */ + 0x0000, /* R2889 */ + 0x0000, /* R2890 */ + 0x0000, /* R2891 */ + 0x0000, /* R2892 */ + 0x0000, /* R2893 */ + 0x0000, /* R2894 */ + 0x0000, /* R2895 */ + 0x0000, /* R2896 */ + 0x0000, /* R2897 */ + 0x0000, /* R2898 */ + 0x0000, /* R2899 */ + 0x0000, /* R2900 */ + 0x0000, /* R2901 */ + 0x0000, /* R2902 */ + 0x0000, /* R2903 */ + 0x0000, /* R2904 */ + 0x0000, /* R2905 */ + 0x0000, /* R2906 */ + 0x0000, /* R2907 */ + 0x0000, /* R2908 */ + 0x0000, /* R2909 */ + 0x0000, /* R2910 */ + 0x0000, /* R2911 */ + 0x0000, /* R2912 */ + 0x0000, /* R2913 */ + 0x0000, /* R2914 */ + 0x0000, /* R2915 */ + 0x0000, /* R2916 */ + 0x0000, /* R2917 */ + 0x0000, /* R2918 */ + 0x0000, /* R2919 */ + 0x0000, /* R2920 */ + 0x0000, /* R2921 */ + 0x0000, /* R2922 */ + 0x0000, /* R2923 */ + 0x0000, /* R2924 */ + 0x0000, /* R2925 */ + 0x0000, /* R2926 */ + 0x0000, /* R2927 */ + 0x0000, /* R2928 */ + 0x0000, /* R2929 */ + 0x0000, /* R2930 */ + 0x0000, /* R2931 */ + 0x0000, /* R2932 */ + 0x0000, /* R2933 */ + 0x0000, /* R2934 */ + 0x0000, /* R2935 */ + 0x0000, /* R2936 */ + 0x0000, /* R2937 */ + 0x0000, /* R2938 */ + 0x0000, /* R2939 */ + 0x0000, /* R2940 */ + 0x0000, /* R2941 */ + 0x0000, /* R2942 */ + 0x0000, /* R2943 */ + 0x0000, /* R2944 */ + 0x0000, /* R2945 */ + 0x0000, /* R2946 */ + 0x0000, /* R2947 */ + 0x0000, /* R2948 */ + 0x0000, /* R2949 */ + 0x0000, /* R2950 */ + 0x0000, /* R2951 */ + 0x0000, /* R2952 */ + 0x0000, /* R2953 */ + 0x0000, /* R2954 */ + 0x0000, /* R2955 */ + 0x0000, /* R2956 */ + 0x0000, /* R2957 */ + 0x0000, /* R2958 */ + 0x0000, /* R2959 */ + 0x0000, /* R2960 */ + 0x0000, /* R2961 */ + 0x0000, /* R2962 */ + 0x0000, /* R2963 */ + 0x0000, /* R2964 */ + 0x0000, /* R2965 */ + 0x0000, /* R2966 */ + 0x0000, /* R2967 */ + 0x0000, /* R2968 */ + 0x0000, /* R2969 */ + 0x0000, /* R2970 */ + 0x0000, /* R2971 */ + 0x0000, /* R2972 */ + 0x0000, /* R2973 */ + 0x0000, /* R2974 */ + 0x0000, /* R2975 */ + 0x0000, /* R2976 */ + 0x0000, /* R2977 */ + 0x0000, /* R2978 */ + 0x0000, /* R2979 */ + 0x0000, /* R2980 */ + 0x0000, /* R2981 */ + 0x0000, /* R2982 */ + 0x0000, /* R2983 */ + 0x0000, /* R2984 */ + 0x0000, /* R2985 */ + 0x0000, /* R2986 */ + 0x0000, /* R2987 */ + 0x0000, /* R2988 */ + 0x0000, /* R2989 */ + 0x0000, /* R2990 */ + 0x0000, /* R2991 */ + 0x0000, /* R2992 */ + 0x0000, /* R2993 */ + 0x0000, /* R2994 */ + 0x0000, /* R2995 */ + 0x0000, /* R2996 */ + 0x0000, /* R2997 */ + 0x0000, /* R2998 */ + 0x0000, /* R2999 */ + 0x0000, /* R3000 */ + 0x0000, /* R3001 */ + 0x0000, /* R3002 */ + 0x0000, /* R3003 */ + 0x0000, /* R3004 */ + 0x0000, /* R3005 */ + 0x0000, /* R3006 */ + 0x0000, /* R3007 */ + 0x0000, /* R3008 */ + 0x0000, /* R3009 */ + 0x0000, /* R3010 */ + 0x0000, /* R3011 */ + 0x0000, /* R3012 */ + 0x0000, /* R3013 */ + 0x0000, /* R3014 */ + 0x0000, /* R3015 */ + 0x0000, /* R3016 */ + 0x0000, /* R3017 */ + 0x0000, /* R3018 */ + 0x0000, /* R3019 */ + 0x0000, /* R3020 */ + 0x0000, /* R3021 */ + 0x0000, /* R3022 */ + 0x0000, /* R3023 */ + 0x0000, /* R3024 */ + 0x0000, /* R3025 */ + 0x0000, /* R3026 */ + 0x0000, /* R3027 */ + 0x0000, /* R3028 */ + 0x0000, /* R3029 */ + 0x0000, /* R3030 */ + 0x0000, /* R3031 */ + 0x0000, /* R3032 */ + 0x0000, /* R3033 */ + 0x0000, /* R3034 */ + 0x0000, /* R3035 */ + 0x0000, /* R3036 */ + 0x0000, /* R3037 */ + 0x0000, /* R3038 */ + 0x0000, /* R3039 */ + 0x0000, /* R3040 */ + 0x0000, /* R3041 */ + 0x0000, /* R3042 */ + 0x0000, /* R3043 */ + 0x0000, /* R3044 */ + 0x0000, /* R3045 */ + 0x0000, /* R3046 */ + 0x0000, /* R3047 */ + 0x0000, /* R3048 */ + 0x0000, /* R3049 */ + 0x0000, /* R3050 */ + 0x0000, /* R3051 */ + 0x0000, /* R3052 */ + 0x0000, /* R3053 */ + 0x0000, /* R3054 */ + 0x0000, /* R3055 */ + 0x0000, /* R3056 */ + 0x0000, /* R3057 */ + 0x0000, /* R3058 */ + 0x0000, /* R3059 */ + 0x0000, /* R3060 */ + 0x0000, /* R3061 */ + 0x0000, /* R3062 */ + 0x0000, /* R3063 */ + 0x0000, /* R3064 */ + 0x0000, /* R3065 */ + 0x0000, /* R3066 */ + 0x0000, /* R3067 */ + 0x0000, /* R3068 */ + 0x0000, /* R3069 */ + 0x0000, /* R3070 */ + 0x0000, /* R3071 */ + 0x0000, /* R3072 */ + 0x0000, /* R3073 */ + 0x0000, /* R3074 */ + 0x0000, /* R3075 */ + 0x0000, /* R3076 */ + 0x0000, /* R3077 */ + 0x0000, /* R3078 */ + 0x0000, /* R3079 */ + 0x0000, /* R3080 */ + 0x0000, /* R3081 */ + 0x0000, /* R3082 */ + 0x0000, /* R3083 */ + 0x0000, /* R3084 */ + 0x0000, /* R3085 */ + 0x0000, /* R3086 */ + 0x0000, /* R3087 */ + 0x0000, /* R3088 */ + 0x0000, /* R3089 */ + 0x0000, /* R3090 */ + 0x0000, /* R3091 */ + 0x0000, /* R3092 */ + 0x0000, /* R3093 */ + 0x0000, /* R3094 */ + 0x0000, /* R3095 */ + 0x0000, /* R3096 */ + 0x0000, /* R3097 */ + 0x0000, /* R3098 */ + 0x0000, /* R3099 */ + 0x0000, /* R3100 */ + 0x0000, /* R3101 */ + 0x0000, /* R3102 */ + 0x0000, /* R3103 */ + 0x0000, /* R3104 */ + 0x0000, /* R3105 */ + 0x0000, /* R3106 */ + 0x0000, /* R3107 */ + 0x0000, /* R3108 */ + 0x0000, /* R3109 */ + 0x0000, /* R3110 */ + 0x0000, /* R3111 */ + 0x0000, /* R3112 */ + 0x0000, /* R3113 */ + 0x0000, /* R3114 */ + 0x0000, /* R3115 */ + 0x0000, /* R3116 */ + 0x0000, /* R3117 */ + 0x0000, /* R3118 */ + 0x0000, /* R3119 */ + 0x0000, /* R3120 */ + 0x0000, /* R3121 */ + 0x0000, /* R3122 */ + 0x0000, /* R3123 */ + 0x0000, /* R3124 */ + 0x0000, /* R3125 */ + 0x0000, /* R3126 */ + 0x0000, /* R3127 */ + 0x0000, /* R3128 */ + 0x0000, /* R3129 */ + 0x0000, /* R3130 */ + 0x0000, /* R3131 */ + 0x0000, /* R3132 */ + 0x0000, /* R3133 */ + 0x0000, /* R3134 */ + 0x0000, /* R3135 */ + 0x0000, /* R3136 */ + 0x0000, /* R3137 */ + 0x0000, /* R3138 */ + 0x0000, /* R3139 */ + 0x0000, /* R3140 */ + 0x0000, /* R3141 */ + 0x0000, /* R3142 */ + 0x0000, /* R3143 */ + 0x0000, /* R3144 */ + 0x0000, /* R3145 */ + 0x0000, /* R3146 */ + 0x0000, /* R3147 */ + 0x0000, /* R3148 */ + 0x0000, /* R3149 */ + 0x0000, /* R3150 */ + 0x0000, /* R3151 */ + 0x0000, /* R3152 */ + 0x0000, /* R3153 */ + 0x0000, /* R3154 */ + 0x0000, /* R3155 */ + 0x0000, /* R3156 */ + 0x0000, /* R3157 */ + 0x0000, /* R3158 */ + 0x0000, /* R3159 */ + 0x0000, /* R3160 */ + 0x0000, /* R3161 */ + 0x0000, /* R3162 */ + 0x0000, /* R3163 */ + 0x0000, /* R3164 */ + 0x0000, /* R3165 */ + 0x0000, /* R3166 */ + 0x0000, /* R3167 */ + 0x0000, /* R3168 */ + 0x0000, /* R3169 */ + 0x0000, /* R3170 */ + 0x0000, /* R3171 */ + 0x0000, /* R3172 */ + 0x0000, /* R3173 */ + 0x0000, /* R3174 */ + 0x0000, /* R3175 */ + 0x0000, /* R3176 */ + 0x0000, /* R3177 */ + 0x0000, /* R3178 */ + 0x0000, /* R3179 */ + 0x0000, /* R3180 */ + 0x0000, /* R3181 */ + 0x0000, /* R3182 */ + 0x0000, /* R3183 */ + 0x0000, /* R3184 */ + 0x0000, /* R3185 */ + 0x0000, /* R3186 */ + 0x0000, /* R3187 */ + 0x0000, /* R3188 */ + 0x0000, /* R3189 */ + 0x0000, /* R3190 */ + 0x0000, /* R3191 */ + 0x0000, /* R3192 */ + 0x0000, /* R3193 */ + 0x0000, /* R3194 */ + 0x0000, /* R3195 */ + 0x0000, /* R3196 */ + 0x0000, /* R3197 */ + 0x0000, /* R3198 */ + 0x0000, /* R3199 */ + 0x0000, /* R3200 */ + 0x0000, /* R3201 */ + 0x0000, /* R3202 */ + 0x0000, /* R3203 */ + 0x0000, /* R3204 */ + 0x0000, /* R3205 */ + 0x0000, /* R3206 */ + 0x0000, /* R3207 */ + 0x0000, /* R3208 */ + 0x0000, /* R3209 */ + 0x0000, /* R3210 */ + 0x0000, /* R3211 */ + 0x0000, /* R3212 */ + 0x0000, /* R3213 */ + 0x0000, /* R3214 */ + 0x0000, /* R3215 */ + 0x0000, /* R3216 */ + 0x0000, /* R3217 */ + 0x0000, /* R3218 */ + 0x0000, /* R3219 */ + 0x0000, /* R3220 */ + 0x0000, /* R3221 */ + 0x0000, /* R3222 */ + 0x0000, /* R3223 */ + 0x0000, /* R3224 */ + 0x0000, /* R3225 */ + 0x0000, /* R3226 */ + 0x0000, /* R3227 */ + 0x0000, /* R3228 */ + 0x0000, /* R3229 */ + 0x0000, /* R3230 */ + 0x0000, /* R3231 */ + 0x0000, /* R3232 */ + 0x0000, /* R3233 */ + 0x0000, /* R3234 */ + 0x0000, /* R3235 */ + 0x0000, /* R3236 */ + 0x0000, /* R3237 */ + 0x0000, /* R3238 */ + 0x0000, /* R3239 */ + 0x0000, /* R3240 */ + 0x0000, /* R3241 */ + 0x0000, /* R3242 */ + 0x0000, /* R3243 */ + 0x0000, /* R3244 */ + 0x0000, /* R3245 */ + 0x0000, /* R3246 */ + 0x0000, /* R3247 */ + 0x0000, /* R3248 */ + 0x0000, /* R3249 */ + 0x0000, /* R3250 */ + 0x0000, /* R3251 */ + 0x0000, /* R3252 */ + 0x0000, /* R3253 */ + 0x0000, /* R3254 */ + 0x0000, /* R3255 */ + 0x0000, /* R3256 */ + 0x0000, /* R3257 */ + 0x0000, /* R3258 */ + 0x0000, /* R3259 */ + 0x0000, /* R3260 */ + 0x0000, /* R3261 */ + 0x0000, /* R3262 */ + 0x0000, /* R3263 */ + 0x0000, /* R3264 */ + 0x0000, /* R3265 */ + 0x0000, /* R3266 */ + 0x0000, /* R3267 */ + 0x0000, /* R3268 */ + 0x0000, /* R3269 */ + 0x0000, /* R3270 */ + 0x0000, /* R3271 */ + 0x0000, /* R3272 */ + 0x0000, /* R3273 */ + 0x0000, /* R3274 */ + 0x0000, /* R3275 */ + 0x0000, /* R3276 */ + 0x0000, /* R3277 */ + 0x0000, /* R3278 */ + 0x0000, /* R3279 */ + 0x0000, /* R3280 */ + 0x0000, /* R3281 */ + 0x0000, /* R3282 */ + 0x0000, /* R3283 */ + 0x0000, /* R3284 */ + 0x0000, /* R3285 */ + 0x0000, /* R3286 */ + 0x0000, /* R3287 */ + 0x0000, /* R3288 */ + 0x0000, /* R3289 */ + 0x0000, /* R3290 */ + 0x0000, /* R3291 */ + 0x0000, /* R3292 */ + 0x0000, /* R3293 */ + 0x0000, /* R3294 */ + 0x0000, /* R3295 */ + 0x0000, /* R3296 */ + 0x0000, /* R3297 */ + 0x0000, /* R3298 */ + 0x0000, /* R3299 */ + 0x0000, /* R3300 */ + 0x0000, /* R3301 */ + 0x0000, /* R3302 */ + 0x0000, /* R3303 */ + 0x0000, /* R3304 */ + 0x0000, /* R3305 */ + 0x0000, /* R3306 */ + 0x0000, /* R3307 */ + 0x0000, /* R3308 */ + 0x0000, /* R3309 */ + 0x0000, /* R3310 */ + 0x0000, /* R3311 */ + 0x0000, /* R3312 */ + 0x0000, /* R3313 */ + 0x0000, /* R3314 */ + 0x0000, /* R3315 */ + 0x0000, /* R3316 */ + 0x0000, /* R3317 */ + 0x0000, /* R3318 */ + 0x0000, /* R3319 */ + 0x0000, /* R3320 */ + 0x0000, /* R3321 */ + 0x0000, /* R3322 */ + 0x0000, /* R3323 */ + 0x0000, /* R3324 */ + 0x0000, /* R3325 */ + 0x0000, /* R3326 */ + 0x0000, /* R3327 */ + 0x0000, /* R3328 */ + 0x0000, /* R3329 */ + 0x0000, /* R3330 */ + 0x0000, /* R3331 */ + 0x0000, /* R3332 */ + 0x0000, /* R3333 */ + 0x0000, /* R3334 */ + 0x0000, /* R3335 */ + 0x0000, /* R3336 */ + 0x0000, /* R3337 */ + 0x0000, /* R3338 */ + 0x0000, /* R3339 */ + 0x0000, /* R3340 */ + 0x0000, /* R3341 */ + 0x0000, /* R3342 */ + 0x0000, /* R3343 */ + 0x0000, /* R3344 */ + 0x0000, /* R3345 */ + 0x0000, /* R3346 */ + 0x0000, /* R3347 */ + 0x0000, /* R3348 */ + 0x0000, /* R3349 */ + 0x0000, /* R3350 */ + 0x0000, /* R3351 */ + 0x0000, /* R3352 */ + 0x0000, /* R3353 */ + 0x0000, /* R3354 */ + 0x0000, /* R3355 */ + 0x0000, /* R3356 */ + 0x0000, /* R3357 */ + 0x0000, /* R3358 */ + 0x0000, /* R3359 */ + 0x0000, /* R3360 */ + 0x0000, /* R3361 */ + 0x0000, /* R3362 */ + 0x0000, /* R3363 */ + 0x0000, /* R3364 */ + 0x0000, /* R3365 */ + 0x0000, /* R3366 */ + 0x0000, /* R3367 */ + 0x0000, /* R3368 */ + 0x0000, /* R3369 */ + 0x0000, /* R3370 */ + 0x0000, /* R3371 */ + 0x0000, /* R3372 */ + 0x0000, /* R3373 */ + 0x0000, /* R3374 */ + 0x0000, /* R3375 */ + 0x0000, /* R3376 */ + 0x0000, /* R3377 */ + 0x0000, /* R3378 */ + 0x0000, /* R3379 */ + 0x0000, /* R3380 */ + 0x0000, /* R3381 */ + 0x0000, /* R3382 */ + 0x0000, /* R3383 */ + 0x0000, /* R3384 */ + 0x0000, /* R3385 */ + 0x0000, /* R3386 */ + 0x0000, /* R3387 */ + 0x0000, /* R3388 */ + 0x0000, /* R3389 */ + 0x0000, /* R3390 */ + 0x0000, /* R3391 */ + 0x0000, /* R3392 */ + 0x0000, /* R3393 */ + 0x0000, /* R3394 */ + 0x0000, /* R3395 */ + 0x0000, /* R3396 */ + 0x0000, /* R3397 */ + 0x0000, /* R3398 */ + 0x0000, /* R3399 */ + 0x0000, /* R3400 */ + 0x0000, /* R3401 */ + 0x0000, /* R3402 */ + 0x0000, /* R3403 */ + 0x0000, /* R3404 */ + 0x0000, /* R3405 */ + 0x0000, /* R3406 */ + 0x0000, /* R3407 */ + 0x0000, /* R3408 */ + 0x0000, /* R3409 */ + 0x0000, /* R3410 */ + 0x0000, /* R3411 */ + 0x0000, /* R3412 */ + 0x0000, /* R3413 */ + 0x0000, /* R3414 */ + 0x0000, /* R3415 */ + 0x0000, /* R3416 */ + 0x0000, /* R3417 */ + 0x0000, /* R3418 */ + 0x0000, /* R3419 */ + 0x0000, /* R3420 */ + 0x0000, /* R3421 */ + 0x0000, /* R3422 */ + 0x0000, /* R3423 */ + 0x0000, /* R3424 */ + 0x0000, /* R3425 */ + 0x0000, /* R3426 */ + 0x0000, /* R3427 */ + 0x0000, /* R3428 */ + 0x0000, /* R3429 */ + 0x0000, /* R3430 */ + 0x0000, /* R3431 */ + 0x0000, /* R3432 */ + 0x0000, /* R3433 */ + 0x0000, /* R3434 */ + 0x0000, /* R3435 */ + 0x0000, /* R3436 */ + 0x0000, /* R3437 */ + 0x0000, /* R3438 */ + 0x0000, /* R3439 */ + 0x0000, /* R3440 */ + 0x0000, /* R3441 */ + 0x0000, /* R3442 */ + 0x0000, /* R3443 */ + 0x0000, /* R3444 */ + 0x0000, /* R3445 */ + 0x0000, /* R3446 */ + 0x0000, /* R3447 */ + 0x0000, /* R3448 */ + 0x0000, /* R3449 */ + 0x0000, /* R3450 */ + 0x0000, /* R3451 */ + 0x0000, /* R3452 */ + 0x0000, /* R3453 */ + 0x0000, /* R3454 */ + 0x0000, /* R3455 */ + 0x0000, /* R3456 */ + 0x0000, /* R3457 */ + 0x0000, /* R3458 */ + 0x0000, /* R3459 */ + 0x0000, /* R3460 */ + 0x0000, /* R3461 */ + 0x0000, /* R3462 */ + 0x0000, /* R3463 */ + 0x0000, /* R3464 */ + 0x0000, /* R3465 */ + 0x0000, /* R3466 */ + 0x0000, /* R3467 */ + 0x0000, /* R3468 */ + 0x0000, /* R3469 */ + 0x0000, /* R3470 */ + 0x0000, /* R3471 */ + 0x0000, /* R3472 */ + 0x0000, /* R3473 */ + 0x0000, /* R3474 */ + 0x0000, /* R3475 */ + 0x0000, /* R3476 */ + 0x0000, /* R3477 */ + 0x0000, /* R3478 */ + 0x0000, /* R3479 */ + 0x0000, /* R3480 */ + 0x0000, /* R3481 */ + 0x0000, /* R3482 */ + 0x0000, /* R3483 */ + 0x0000, /* R3484 */ + 0x0000, /* R3485 */ + 0x0000, /* R3486 */ + 0x0000, /* R3487 */ + 0x0000, /* R3488 */ + 0x0000, /* R3489 */ + 0x0000, /* R3490 */ + 0x0000, /* R3491 */ + 0x0000, /* R3492 */ + 0x0000, /* R3493 */ + 0x0000, /* R3494 */ + 0x0000, /* R3495 */ + 0x0000, /* R3496 */ + 0x0000, /* R3497 */ + 0x0000, /* R3498 */ + 0x0000, /* R3499 */ + 0x0000, /* R3500 */ + 0x0000, /* R3501 */ + 0x0000, /* R3502 */ + 0x0000, /* R3503 */ + 0x0000, /* R3504 */ + 0x0000, /* R3505 */ + 0x0000, /* R3506 */ + 0x0000, /* R3507 */ + 0x0000, /* R3508 */ + 0x0000, /* R3509 */ + 0x0000, /* R3510 */ + 0x0000, /* R3511 */ + 0x0000, /* R3512 */ + 0x0000, /* R3513 */ + 0x0000, /* R3514 */ + 0x0000, /* R3515 */ + 0x0000, /* R3516 */ + 0x0000, /* R3517 */ + 0x0000, /* R3518 */ + 0x0000, /* R3519 */ + 0x0000, /* R3520 */ + 0x0000, /* R3521 */ + 0x0000, /* R3522 */ + 0x0000, /* R3523 */ + 0x0000, /* R3524 */ + 0x0000, /* R3525 */ + 0x0000, /* R3526 */ + 0x0000, /* R3527 */ + 0x0000, /* R3528 */ + 0x0000, /* R3529 */ + 0x0000, /* R3530 */ + 0x0000, /* R3531 */ + 0x0000, /* R3532 */ + 0x0000, /* R3533 */ + 0x0000, /* R3534 */ + 0x0000, /* R3535 */ + 0x0000, /* R3536 */ + 0x0000, /* R3537 */ + 0x0000, /* R3538 */ + 0x0000, /* R3539 */ + 0x0000, /* R3540 */ + 0x0000, /* R3541 */ + 0x0000, /* R3542 */ + 0x0000, /* R3543 */ + 0x0000, /* R3544 */ + 0x0000, /* R3545 */ + 0x0000, /* R3546 */ + 0x0000, /* R3547 */ + 0x0000, /* R3548 */ + 0x0000, /* R3549 */ + 0x0000, /* R3550 */ + 0x0000, /* R3551 */ + 0x0000, /* R3552 */ + 0x0000, /* R3553 */ + 0x0000, /* R3554 */ + 0x0000, /* R3555 */ + 0x0000, /* R3556 */ + 0x0000, /* R3557 */ + 0x0000, /* R3558 */ + 0x0000, /* R3559 */ + 0x0000, /* R3560 */ + 0x0000, /* R3561 */ + 0x0000, /* R3562 */ + 0x0000, /* R3563 */ + 0x0000, /* R3564 */ + 0x0000, /* R3565 */ + 0x0000, /* R3566 */ + 0x0000, /* R3567 */ + 0x0000, /* R3568 */ + 0x0000, /* R3569 */ + 0x0000, /* R3570 */ + 0x0000, /* R3571 */ + 0x0000, /* R3572 */ + 0x0000, /* R3573 */ + 0x0000, /* R3574 */ + 0x0000, /* R3575 */ + 0x0000, /* R3576 */ + 0x0000, /* R3577 */ + 0x0000, /* R3578 */ + 0x0000, /* R3579 */ + 0x0000, /* R3580 */ + 0x0000, /* R3581 */ + 0x0000, /* R3582 */ + 0x0000, /* R3583 */ + 0x0000, /* R3584 */ + 0x0000, /* R3585 */ + 0x0000, /* R3586 */ + 0x0000, /* R3587 */ + 0x0000, /* R3588 */ + 0x0000, /* R3589 */ + 0x0000, /* R3590 */ + 0x0000, /* R3591 */ + 0x0000, /* R3592 */ + 0x0000, /* R3593 */ + 0x0000, /* R3594 */ + 0x0000, /* R3595 */ + 0x0000, /* R3596 */ + 0x0000, /* R3597 */ + 0x0000, /* R3598 */ + 0x0000, /* R3599 */ + 0x0000, /* R3600 */ + 0x0000, /* R3601 */ + 0x0000, /* R3602 */ + 0x0000, /* R3603 */ + 0x0000, /* R3604 */ + 0x0000, /* R3605 */ + 0x0000, /* R3606 */ + 0x0000, /* R3607 */ + 0x0000, /* R3608 */ + 0x0000, /* R3609 */ + 0x0000, /* R3610 */ + 0x0000, /* R3611 */ + 0x0000, /* R3612 */ + 0x0000, /* R3613 */ + 0x0000, /* R3614 */ + 0x0000, /* R3615 */ + 0x0000, /* R3616 */ + 0x0000, /* R3617 */ + 0x0000, /* R3618 */ + 0x0000, /* R3619 */ + 0x0000, /* R3620 */ + 0x0000, /* R3621 */ + 0x0000, /* R3622 */ + 0x0000, /* R3623 */ + 0x0000, /* R3624 */ + 0x0000, /* R3625 */ + 0x0000, /* R3626 */ + 0x0000, /* R3627 */ + 0x0000, /* R3628 */ + 0x0000, /* R3629 */ + 0x0000, /* R3630 */ + 0x0000, /* R3631 */ + 0x0000, /* R3632 */ + 0x0000, /* R3633 */ + 0x0000, /* R3634 */ + 0x0000, /* R3635 */ + 0x0000, /* R3636 */ + 0x0000, /* R3637 */ + 0x0000, /* R3638 */ + 0x0000, /* R3639 */ + 0x0000, /* R3640 */ + 0x0000, /* R3641 */ + 0x0000, /* R3642 */ + 0x0000, /* R3643 */ + 0x0000, /* R3644 */ + 0x0000, /* R3645 */ + 0x0000, /* R3646 */ + 0x0000, /* R3647 */ + 0x0000, /* R3648 */ + 0x0000, /* R3649 */ + 0x0000, /* R3650 */ + 0x0000, /* R3651 */ + 0x0000, /* R3652 */ + 0x0000, /* R3653 */ + 0x0000, /* R3654 */ + 0x0000, /* R3655 */ + 0x0000, /* R3656 */ + 0x0000, /* R3657 */ + 0x0000, /* R3658 */ + 0x0000, /* R3659 */ + 0x0000, /* R3660 */ + 0x0000, /* R3661 */ + 0x0000, /* R3662 */ + 0x0000, /* R3663 */ + 0x0000, /* R3664 */ + 0x0000, /* R3665 */ + 0x0000, /* R3666 */ + 0x0000, /* R3667 */ + 0x0000, /* R3668 */ + 0x0000, /* R3669 */ + 0x0000, /* R3670 */ + 0x0000, /* R3671 */ + 0x0000, /* R3672 */ + 0x0000, /* R3673 */ + 0x0000, /* R3674 */ + 0x0000, /* R3675 */ + 0x0000, /* R3676 */ + 0x0000, /* R3677 */ + 0x0000, /* R3678 */ + 0x0000, /* R3679 */ + 0x0000, /* R3680 */ + 0x0000, /* R3681 */ + 0x0000, /* R3682 */ + 0x0000, /* R3683 */ + 0x0000, /* R3684 */ + 0x0000, /* R3685 */ + 0x0000, /* R3686 */ + 0x0000, /* R3687 */ + 0x0000, /* R3688 */ + 0x0000, /* R3689 */ + 0x0000, /* R3690 */ + 0x0000, /* R3691 */ + 0x0000, /* R3692 */ + 0x0000, /* R3693 */ + 0x0000, /* R3694 */ + 0x0000, /* R3695 */ + 0x0000, /* R3696 */ + 0x0000, /* R3697 */ + 0x0000, /* R3698 */ + 0x0000, /* R3699 */ + 0x0000, /* R3700 */ + 0x0000, /* R3701 */ + 0x0000, /* R3702 */ + 0x0000, /* R3703 */ + 0x0000, /* R3704 */ + 0x0000, /* R3705 */ + 0x0000, /* R3706 */ + 0x0000, /* R3707 */ + 0x0000, /* R3708 */ + 0x0000, /* R3709 */ + 0x0000, /* R3710 */ + 0x0000, /* R3711 */ + 0x0000, /* R3712 */ + 0x0000, /* R3713 */ + 0x0000, /* R3714 */ + 0x0000, /* R3715 */ + 0x0000, /* R3716 */ + 0x0000, /* R3717 */ + 0x0000, /* R3718 */ + 0x0000, /* R3719 */ + 0x0000, /* R3720 */ + 0x0000, /* R3721 */ + 0x0000, /* R3722 */ + 0x0000, /* R3723 */ + 0x0000, /* R3724 */ + 0x0000, /* R3725 */ + 0x0000, /* R3726 */ + 0x0000, /* R3727 */ + 0x0000, /* R3728 */ + 0x0000, /* R3729 */ + 0x0000, /* R3730 */ + 0x0000, /* R3731 */ + 0x0000, /* R3732 */ + 0x0000, /* R3733 */ + 0x0000, /* R3734 */ + 0x0000, /* R3735 */ + 0x0000, /* R3736 */ + 0x0000, /* R3737 */ + 0x0000, /* R3738 */ + 0x0000, /* R3739 */ + 0x0000, /* R3740 */ + 0x0000, /* R3741 */ + 0x0000, /* R3742 */ + 0x0000, /* R3743 */ + 0x0000, /* R3744 */ + 0x0000, /* R3745 */ + 0x0000, /* R3746 */ + 0x0000, /* R3747 */ + 0x0000, /* R3748 */ + 0x0000, /* R3749 */ + 0x0000, /* R3750 */ + 0x0000, /* R3751 */ + 0x0000, /* R3752 */ + 0x0000, /* R3753 */ + 0x0000, /* R3754 */ + 0x0000, /* R3755 */ + 0x0000, /* R3756 */ + 0x0000, /* R3757 */ + 0x0000, /* R3758 */ + 0x0000, /* R3759 */ + 0x0000, /* R3760 */ + 0x0000, /* R3761 */ + 0x0000, /* R3762 */ + 0x0000, /* R3763 */ + 0x0000, /* R3764 */ + 0x0000, /* R3765 */ + 0x0000, /* R3766 */ + 0x0000, /* R3767 */ + 0x0000, /* R3768 */ + 0x0000, /* R3769 */ + 0x0000, /* R3770 */ + 0x0000, /* R3771 */ + 0x0000, /* R3772 */ + 0x0000, /* R3773 */ + 0x0000, /* R3774 */ + 0x0000, /* R3775 */ + 0x0000, /* R3776 */ + 0x0000, /* R3777 */ + 0x0000, /* R3778 */ + 0x0000, /* R3779 */ + 0x0000, /* R3780 */ + 0x0000, /* R3781 */ + 0x0000, /* R3782 */ + 0x0000, /* R3783 */ + 0x0000, /* R3784 */ + 0x0000, /* R3785 */ + 0x0000, /* R3786 */ + 0x0000, /* R3787 */ + 0x0000, /* R3788 */ + 0x0000, /* R3789 */ + 0x0000, /* R3790 */ + 0x0000, /* R3791 */ + 0x0000, /* R3792 */ + 0x0000, /* R3793 */ + 0x0000, /* R3794 */ + 0x0000, /* R3795 */ + 0x0000, /* R3796 */ + 0x0000, /* R3797 */ + 0x0000, /* R3798 */ + 0x0000, /* R3799 */ + 0x0000, /* R3800 */ + 0x0000, /* R3801 */ + 0x0000, /* R3802 */ + 0x0000, /* R3803 */ + 0x0000, /* R3804 */ + 0x0000, /* R3805 */ + 0x0000, /* R3806 */ + 0x0000, /* R3807 */ + 0x0000, /* R3808 */ + 0x0000, /* R3809 */ + 0x0000, /* R3810 */ + 0x0000, /* R3811 */ + 0x0000, /* R3812 */ + 0x0000, /* R3813 */ + 0x0000, /* R3814 */ + 0x0000, /* R3815 */ + 0x0000, /* R3816 */ + 0x0000, /* R3817 */ + 0x0000, /* R3818 */ + 0x0000, /* R3819 */ + 0x0000, /* R3820 */ + 0x0000, /* R3821 */ + 0x0000, /* R3822 */ + 0x0000, /* R3823 */ + 0x0000, /* R3824 */ + 0x0000, /* R3825 */ + 0x0000, /* R3826 */ + 0x0000, /* R3827 */ + 0x0000, /* R3828 */ + 0x0000, /* R3829 */ + 0x0000, /* R3830 */ + 0x0000, /* R3831 */ + 0x0000, /* R3832 */ + 0x0000, /* R3833 */ + 0x0000, /* R3834 */ + 0x0000, /* R3835 */ + 0x0000, /* R3836 */ + 0x0000, /* R3837 */ + 0x0000, /* R3838 */ + 0x0000, /* R3839 */ + 0x0000, /* R3840 */ + 0x0000, /* R3841 */ + 0x0000, /* R3842 */ + 0x0000, /* R3843 */ + 0x0000, /* R3844 */ + 0x0000, /* R3845 */ + 0x0000, /* R3846 */ + 0x0000, /* R3847 */ + 0x0000, /* R3848 */ + 0x0000, /* R3849 */ + 0x0000, /* R3850 */ + 0x0000, /* R3851 */ + 0x0000, /* R3852 */ + 0x0000, /* R3853 */ + 0x0000, /* R3854 */ + 0x0000, /* R3855 */ + 0x0000, /* R3856 */ + 0x0000, /* R3857 */ + 0x0000, /* R3858 */ + 0x0000, /* R3859 */ + 0x0000, /* R3860 */ + 0x0000, /* R3861 */ + 0x0000, /* R3862 */ + 0x0000, /* R3863 */ + 0x0000, /* R3864 */ + 0x0000, /* R3865 */ + 0x0000, /* R3866 */ + 0x0000, /* R3867 */ + 0x0000, /* R3868 */ + 0x0000, /* R3869 */ + 0x0000, /* R3870 */ + 0x0000, /* R3871 */ + 0x0000, /* R3872 */ + 0x0000, /* R3873 */ + 0x0000, /* R3874 */ + 0x0000, /* R3875 */ + 0x0000, /* R3876 */ + 0x0000, /* R3877 */ + 0x0000, /* R3878 */ + 0x0000, /* R3879 */ + 0x0000, /* R3880 */ + 0x0000, /* R3881 */ + 0x0000, /* R3882 */ + 0x0000, /* R3883 */ + 0x0000, /* R3884 */ + 0x0000, /* R3885 */ + 0x0000, /* R3886 */ + 0x0000, /* R3887 */ + 0x0000, /* R3888 */ + 0x0000, /* R3889 */ + 0x0000, /* R3890 */ + 0x0000, /* R3891 */ + 0x0000, /* R3892 */ + 0x0000, /* R3893 */ + 0x0000, /* R3894 */ + 0x0000, /* R3895 */ + 0x0000, /* R3896 */ + 0x0000, /* R3897 */ + 0x0000, /* R3898 */ + 0x0000, /* R3899 */ + 0x0000, /* R3900 */ + 0x0000, /* R3901 */ + 0x0000, /* R3902 */ + 0x0000, /* R3903 */ + 0x0000, /* R3904 */ + 0x0000, /* R3905 */ + 0x0000, /* R3906 */ + 0x0000, /* R3907 */ + 0x0000, /* R3908 */ + 0x0000, /* R3909 */ + 0x0000, /* R3910 */ + 0x0000, /* R3911 */ + 0x0000, /* R3912 */ + 0x0000, /* R3913 */ + 0x0000, /* R3914 */ + 0x0000, /* R3915 */ + 0x0000, /* R3916 */ + 0x0000, /* R3917 */ + 0x0000, /* R3918 */ + 0x0000, /* R3919 */ + 0x0000, /* R3920 */ + 0x0000, /* R3921 */ + 0x0000, /* R3922 */ + 0x0000, /* R3923 */ + 0x0000, /* R3924 */ + 0x0000, /* R3925 */ + 0x0000, /* R3926 */ + 0x0000, /* R3927 */ + 0x0000, /* R3928 */ + 0x0000, /* R3929 */ + 0x0000, /* R3930 */ + 0x0000, /* R3931 */ + 0x0000, /* R3932 */ + 0x0000, /* R3933 */ + 0x0000, /* R3934 */ + 0x0000, /* R3935 */ + 0x0000, /* R3936 */ + 0x0000, /* R3937 */ + 0x0000, /* R3938 */ + 0x0000, /* R3939 */ + 0x0000, /* R3940 */ + 0x0000, /* R3941 */ + 0x0000, /* R3942 */ + 0x0000, /* R3943 */ + 0x0000, /* R3944 */ + 0x0000, /* R3945 */ + 0x0000, /* R3946 */ + 0x0000, /* R3947 */ + 0x0000, /* R3948 */ + 0x0000, /* R3949 */ + 0x0000, /* R3950 */ + 0x0000, /* R3951 */ + 0x0000, /* R3952 */ + 0x0000, /* R3953 */ + 0x0000, /* R3954 */ + 0x0000, /* R3955 */ + 0x0000, /* R3956 */ + 0x0000, /* R3957 */ + 0x0000, /* R3958 */ + 0x0000, /* R3959 */ + 0x0000, /* R3960 */ + 0x0000, /* R3961 */ + 0x0000, /* R3962 */ + 0x0000, /* R3963 */ + 0x0000, /* R3964 */ + 0x0000, /* R3965 */ + 0x0000, /* R3966 */ + 0x0000, /* R3967 */ + 0x0000, /* R3968 */ + 0x0000, /* R3969 */ + 0x0000, /* R3970 */ + 0x0000, /* R3971 */ + 0x0000, /* R3972 */ + 0x0000, /* R3973 */ + 0x0000, /* R3974 */ + 0x0000, /* R3975 */ + 0x0000, /* R3976 */ + 0x0000, /* R3977 */ + 0x0000, /* R3978 */ + 0x0000, /* R3979 */ + 0x0000, /* R3980 */ + 0x0000, /* R3981 */ + 0x0000, /* R3982 */ + 0x0000, /* R3983 */ + 0x0000, /* R3984 */ + 0x0000, /* R3985 */ + 0x0000, /* R3986 */ + 0x0000, /* R3987 */ + 0x0000, /* R3988 */ + 0x0000, /* R3989 */ + 0x0000, /* R3990 */ + 0x0000, /* R3991 */ + 0x0000, /* R3992 */ + 0x0000, /* R3993 */ + 0x0000, /* R3994 */ + 0x0000, /* R3995 */ + 0x0000, /* R3996 */ + 0x0000, /* R3997 */ + 0x0000, /* R3998 */ + 0x0000, /* R3999 */ + 0x0000, /* R4000 */ + 0x0000, /* R4001 */ + 0x0000, /* R4002 */ + 0x0000, /* R4003 */ + 0x0000, /* R4004 */ + 0x0000, /* R4005 */ + 0x0000, /* R4006 */ + 0x0000, /* R4007 */ + 0x0000, /* R4008 */ + 0x0000, /* R4009 */ + 0x0000, /* R4010 */ + 0x0000, /* R4011 */ + 0x0000, /* R4012 */ + 0x0000, /* R4013 */ + 0x0000, /* R4014 */ + 0x0000, /* R4015 */ + 0x0000, /* R4016 */ + 0x0000, /* R4017 */ + 0x0000, /* R4018 */ + 0x0000, /* R4019 */ + 0x0000, /* R4020 */ + 0x0000, /* R4021 */ + 0x0000, /* R4022 */ + 0x0000, /* R4023 */ + 0x0000, /* R4024 */ + 0x0000, /* R4025 */ + 0x0000, /* R4026 */ + 0x0000, /* R4027 */ + 0x0000, /* R4028 */ + 0x0000, /* R4029 */ + 0x0000, /* R4030 */ + 0x0000, /* R4031 */ + 0x0000, /* R4032 */ + 0x0000, /* R4033 */ + 0x0000, /* R4034 */ + 0x0000, /* R4035 */ + 0x0000, /* R4036 */ + 0x0000, /* R4037 */ + 0x0000, /* R4038 */ + 0x0000, /* R4039 */ + 0x0000, /* R4040 */ + 0x0000, /* R4041 */ + 0x0000, /* R4042 */ + 0x0000, /* R4043 */ + 0x0000, /* R4044 */ + 0x0000, /* R4045 */ + 0x0000, /* R4046 */ + 0x0000, /* R4047 */ + 0x0000, /* R4048 */ + 0x0000, /* R4049 */ + 0x0000, /* R4050 */ + 0x0000, /* R4051 */ + 0x0000, /* R4052 */ + 0x0000, /* R4053 */ + 0x0000, /* R4054 */ + 0x0000, /* R4055 */ + 0x0000, /* R4056 */ + 0x0000, /* R4057 */ + 0x0000, /* R4058 */ + 0x0000, /* R4059 */ + 0x0000, /* R4060 */ + 0x0000, /* R4061 */ + 0x0000, /* R4062 */ + 0x0000, /* R4063 */ + 0x0000, /* R4064 */ + 0x0000, /* R4065 */ + 0x0000, /* R4066 */ + 0x0000, /* R4067 */ + 0x0000, /* R4068 */ + 0x0000, /* R4069 */ + 0x0000, /* R4070 */ + 0x0000, /* R4071 */ + 0x0000, /* R4072 */ + 0x0000, /* R4073 */ + 0x0000, /* R4074 */ + 0x0000, /* R4075 */ + 0x0000, /* R4076 */ + 0x0000, /* R4077 */ + 0x0000, /* R4078 */ + 0x0000, /* R4079 */ + 0x0000, /* R4080 */ + 0x0000, /* R4081 */ + 0x0000, /* R4082 */ + 0x0000, /* R4083 */ + 0x0000, /* R4084 */ + 0x0000, /* R4085 */ + 0x0000, /* R4086 */ + 0x0000, /* R4087 */ + 0x0000, /* R4088 */ + 0x0000, /* R4089 */ + 0x0000, /* R4090 */ + 0x0000, /* R4091 */ + 0x0000, /* R4092 */ + 0x0000, /* R4093 */ + 0x0000, /* R4094 */ + 0x0000, /* R4095 */ + 0x001C, /* R4096 - Write Sequencer 0 */ + 0x0003, /* R4097 - Write Sequencer 1 */ + 0x0103, /* R4098 - Write Sequencer 2 */ + 0x0000, /* R4099 - Write Sequencer 3 */ + 0x0019, /* R4100 - Write Sequencer 4 */ + 0x0007, /* R4101 - Write Sequencer 5 */ + 0x0206, /* R4102 - Write Sequencer 6 */ + 0x0000, /* R4103 - Write Sequencer 7 */ + 0x0048, /* R4104 - Write Sequencer 8 */ + 0x0001, /* R4105 - Write Sequencer 9 */ + 0x0000, /* R4106 - Write Sequencer 10 */ + 0x0006, /* R4107 - Write Sequencer 11 */ + 0x001A, /* R4108 - Write Sequencer 12 */ + 0x000F, /* R4109 - Write Sequencer 13 */ + 0x0305, /* R4110 - Write Sequencer 14 */ + 0x0000, /* R4111 - Write Sequencer 15 */ + 0x0045, /* R4112 - Write Sequencer 16 */ + 0x0011, /* R4113 - Write Sequencer 17 */ + 0x0400, /* R4114 - Write Sequencer 18 */ + 0x0000, /* R4115 - Write Sequencer 19 */ + 0x0045, /* R4116 - Write Sequencer 20 */ + 0x0019, /* R4117 - Write Sequencer 21 */ + 0x0401, /* R4118 - Write Sequencer 22 */ + 0x0000, /* R4119 - Write Sequencer 23 */ + 0x0002, /* R4120 - Write Sequencer 24 */ + 0x0030, /* R4121 - Write Sequencer 25 */ + 0x0600, /* R4122 - Write Sequencer 26 */ + 0x0000, /* R4123 - Write Sequencer 27 */ + 0x0003, /* R4124 - Write Sequencer 28 */ + 0x0030, /* R4125 - Write Sequencer 29 */ + 0x0600, /* R4126 - Write Sequencer 30 */ + 0x0000, /* R4127 - Write Sequencer 31 */ + 0x0003, /* R4128 - Write Sequencer 32 */ + 0x0001, /* R4129 - Write Sequencer 33 */ + 0x0008, /* R4130 - Write Sequencer 34 */ + 0x0000, /* R4131 - Write Sequencer 35 */ + 0x003D, /* R4132 - Write Sequencer 36 */ + 0x0033, /* R4133 - Write Sequencer 37 */ + 0x0502, /* R4134 - Write Sequencer 38 */ + 0x000A, /* R4135 - Write Sequencer 39 */ + 0x00FE, /* R4136 - Write Sequencer 40 */ + 0x0000, /* R4137 - Write Sequencer 41 */ + 0x0000, /* R4138 - Write Sequencer 42 */ + 0x0000, /* R4139 - Write Sequencer 43 */ + 0x0007, /* R4140 - Write Sequencer 44 */ + 0x0000, /* R4141 - Write Sequencer 45 */ + 0x0102, /* R4142 - Write Sequencer 46 */ + 0x0000, /* R4143 - Write Sequencer 47 */ + 0x0045, /* R4144 - Write Sequencer 48 */ + 0x001D, /* R4145 - Write Sequencer 49 */ + 0x0402, /* R4146 - Write Sequencer 50 */ + 0x0000, /* R4147 - Write Sequencer 51 */ + 0x0045, /* R4148 - Write Sequencer 52 */ + 0x001F, /* R4149 - Write Sequencer 53 */ + 0x0403, /* R4150 - Write Sequencer 54 */ + 0x0000, /* R4151 - Write Sequencer 55 */ + 0x00FE, /* R4152 - Write Sequencer 56 */ + 0x0000, /* R4153 - Write Sequencer 57 */ + 0x0000, /* R4154 - Write Sequencer 58 */ + 0x0000, /* R4155 - Write Sequencer 59 */ + 0x0005, /* R4156 - Write Sequencer 60 */ + 0x0000, /* R4157 - Write Sequencer 61 */ + 0x0003, /* R4158 - Write Sequencer 62 */ + 0x0107, /* R4159 - Write Sequencer 63 */ + 0x00FE, /* R4160 - Write Sequencer 64 */ + 0x0000, /* R4161 - Write Sequencer 65 */ + 0x0000, /* R4162 - Write Sequencer 66 */ + 0x0000, /* R4163 - Write Sequencer 67 */ + 0x00FE, /* R4164 - Write Sequencer 68 */ + 0x0000, /* R4165 - Write Sequencer 69 */ + 0x0000, /* R4166 - Write Sequencer 70 */ + 0x0000, /* R4167 - Write Sequencer 71 */ + 0x0020, /* R4168 - Write Sequencer 72 */ + 0x0007, /* R4169 - Write Sequencer 73 */ + 0x0203, /* R4170 - Write Sequencer 74 */ + 0x0000, /* R4171 - Write Sequencer 75 */ + 0x0021, /* R4172 - Write Sequencer 76 */ + 0x0007, /* R4173 - Write Sequencer 77 */ + 0x0203, /* R4174 - Write Sequencer 78 */ + 0x0000, /* R4175 - Write Sequencer 79 */ + 0x0019, /* R4176 - Write Sequencer 80 */ + 0x0019, /* R4177 - Write Sequencer 81 */ + 0x0401, /* R4178 - Write Sequencer 82 */ + 0x0000, /* R4179 - Write Sequencer 83 */ + 0x003C, /* R4180 - Write Sequencer 84 */ + 0x0033, /* R4181 - Write Sequencer 85 */ + 0x0502, /* R4182 - Write Sequencer 86 */ + 0x000A, /* R4183 - Write Sequencer 87 */ + 0x00FE, /* R4184 - Write Sequencer 88 */ + 0x0000, /* R4185 - Write Sequencer 89 */ + 0x0000, /* R4186 - Write Sequencer 90 */ + 0x0000, /* R4187 - Write Sequencer 91 */ + 0x0019, /* R4188 - Write Sequencer 92 */ + 0x0003, /* R4189 - Write Sequencer 93 */ + 0x0102, /* R4190 - Write Sequencer 94 */ + 0x0000, /* R4191 - Write Sequencer 95 */ + 0x0020, /* R4192 - Write Sequencer 96 */ + 0x0000, /* R4193 - Write Sequencer 97 */ + 0x0203, /* R4194 - Write Sequencer 98 */ + 0x0000, /* R4195 - Write Sequencer 99 */ + 0x0021, /* R4196 - Write Sequencer 100 */ + 0x0000, /* R4197 - Write Sequencer 101 */ + 0x0203, /* R4198 - Write Sequencer 102 */ + 0x0100, /* R4199 - Write Sequencer 103 */ + 0x00FE, /* R4200 - Write Sequencer 104 */ + 0x0000, /* R4201 - Write Sequencer 105 */ + 0x0000, /* R4202 - Write Sequencer 106 */ + 0x0000, /* R4203 - Write Sequencer 107 */ + 0x0005, /* R4204 - Write Sequencer 108 */ + 0x0001, /* R4205 - Write Sequencer 109 */ + 0x0003, /* R4206 - Write Sequencer 110 */ + 0x0008, /* R4207 - Write Sequencer 111 */ + 0x0000, /* R4208 - Write Sequencer 112 */ + 0x0001, /* R4209 - Write Sequencer 113 */ + 0x0007, /* R4210 - Write Sequencer 114 */ + 0x0000, /* R4211 - Write Sequencer 115 */ + 0x0001, /* R4212 - Write Sequencer 116 */ + 0x0003, /* R4213 - Write Sequencer 117 */ + 0x0107, /* R4214 - Write Sequencer 118 */ + 0x0000, /* R4215 - Write Sequencer 119 */ + 0x0045, /* R4216 - Write Sequencer 120 */ + 0x000E, /* R4217 - Write Sequencer 121 */ + 0x0403, /* R4218 - Write Sequencer 122 */ + 0x0000, /* R4219 - Write Sequencer 123 */ + 0x0060, /* R4220 - Write Sequencer 124 */ + 0x000E, /* R4221 - Write Sequencer 125 */ + 0x0403, /* R4222 - Write Sequencer 126 */ + 0x0000, /* R4223 - Write Sequencer 127 */ + 0x0002, /* R4224 - Write Sequencer 128 */ + 0x0000, /* R4225 - Write Sequencer 129 */ + 0x0600, /* R4226 - Write Sequencer 130 */ + 0x0000, /* R4227 - Write Sequencer 131 */ + 0x0003, /* R4228 - Write Sequencer 132 */ + 0x0000, /* R4229 - Write Sequencer 133 */ + 0x0600, /* R4230 - Write Sequencer 134 */ + 0x0000, /* R4231 - Write Sequencer 135 */ + 0x0003, /* R4232 - Write Sequencer 136 */ + 0x0001, /* R4233 - Write Sequencer 137 */ + 0x0008, /* R4234 - Write Sequencer 138 */ + 0x0000, /* R4235 - Write Sequencer 139 */ + 0x0028, /* R4236 - Write Sequencer 140 */ + 0x0000, /* R4237 - Write Sequencer 141 */ + 0x0600, /* R4238 - Write Sequencer 142 */ + 0x0000, /* R4239 - Write Sequencer 143 */ + 0x0029, /* R4240 - Write Sequencer 144 */ + 0x0000, /* R4241 - Write Sequencer 145 */ + 0x0600, /* R4242 - Write Sequencer 146 */ + 0x0000, /* R4243 - Write Sequencer 147 */ + 0x0029, /* R4244 - Write Sequencer 148 */ + 0x0001, /* R4245 - Write Sequencer 149 */ + 0x0008, /* R4246 - Write Sequencer 150 */ + 0x0000, /* R4247 - Write Sequencer 151 */ + 0x003C, /* R4248 - Write Sequencer 152 */ + 0x0000, /* R4249 - Write Sequencer 153 */ + 0x0403, /* R4250 - Write Sequencer 154 */ + 0x0000, /* R4251 - Write Sequencer 155 */ + 0x003D, /* R4252 - Write Sequencer 156 */ + 0x0000, /* R4253 - Write Sequencer 157 */ + 0x0403, /* R4254 - Write Sequencer 158 */ + 0x0000, /* R4255 - Write Sequencer 159 */ + 0x003E, /* R4256 - Write Sequencer 160 */ + 0x0000, /* R4257 - Write Sequencer 161 */ + 0x0403, /* R4258 - Write Sequencer 162 */ + 0x0000, /* R4259 - Write Sequencer 163 */ + 0x0045, /* R4260 - Write Sequencer 164 */ + 0x0000, /* R4261 - Write Sequencer 165 */ + 0x0700, /* R4262 - Write Sequencer 166 */ + 0x0000, /* R4263 - Write Sequencer 167 */ + 0x0060, /* R4264 - Write Sequencer 168 */ + 0x0000, /* R4265 - Write Sequencer 169 */ + 0x0700, /* R4266 - Write Sequencer 170 */ + 0x0000, /* R4267 - Write Sequencer 171 */ + 0x0031, /* R4268 - Write Sequencer 172 */ + 0x0000, /* R4269 - Write Sequencer 173 */ + 0x0106, /* R4270 - Write Sequencer 174 */ + 0x0000, /* R4271 - Write Sequencer 175 */ + 0x0063, /* R4272 - Write Sequencer 176 */ + 0x0000, /* R4273 - Write Sequencer 177 */ + 0x0300, /* R4274 - Write Sequencer 178 */ + 0x0000, /* R4275 - Write Sequencer 179 */ + 0x001A, /* R4276 - Write Sequencer 180 */ + 0x0000, /* R4277 - Write Sequencer 181 */ + 0x0503, /* R4278 - Write Sequencer 182 */ + 0x0000, /* R4279 - Write Sequencer 183 */ + 0x0048, /* R4280 - Write Sequencer 184 */ + 0x0000, /* R4281 - Write Sequencer 185 */ + 0x0000, /* R4282 - Write Sequencer 186 */ + 0x0000, /* R4283 - Write Sequencer 187 */ + 0x0019, /* R4284 - Write Sequencer 188 */ + 0x0000, /* R4285 - Write Sequencer 189 */ + 0x0501, /* R4286 - Write Sequencer 190 */ + 0x0000, /* R4287 - Write Sequencer 191 */ + 0x001C, /* R4288 - Write Sequencer 192 */ + 0x0000, /* R4289 - Write Sequencer 193 */ + 0x0103, /* R4290 - Write Sequencer 194 */ + 0x0000, /* R4291 - Write Sequencer 195 */ + 0x0019, /* R4292 - Write Sequencer 196 */ + 0x0000, /* R4293 - Write Sequencer 197 */ + 0x0107, /* R4294 - Write Sequencer 198 */ + 0x0100, /* R4295 - Write Sequencer 199 */ + 0x00FE, /* R4296 - Write Sequencer 200 */ + 0x0000, /* R4297 - Write Sequencer 201 */ + 0x0000, /* R4298 - Write Sequencer 202 */ + 0x0000, /* R4299 - Write Sequencer 203 */ + 0x00FE, /* R4300 - Write Sequencer 204 */ + 0x0000, /* R4301 - Write Sequencer 205 */ + 0x0000, /* R4302 - Write Sequencer 206 */ + 0x0000, /* R4303 - Write Sequencer 207 */ + 0x001C, /* R4304 - Write Sequencer 208 */ + 0x0003, /* R4305 - Write Sequencer 209 */ + 0x0103, /* R4306 - Write Sequencer 210 */ + 0x0000, /* R4307 - Write Sequencer 211 */ + 0x0019, /* R4308 - Write Sequencer 212 */ + 0x0007, /* R4309 - Write Sequencer 213 */ + 0x0206, /* R4310 - Write Sequencer 214 */ + 0x0000, /* R4311 - Write Sequencer 215 */ + 0x0048, /* R4312 - Write Sequencer 216 */ + 0x0001, /* R4313 - Write Sequencer 217 */ + 0x0000, /* R4314 - Write Sequencer 218 */ + 0x0006, /* R4315 - Write Sequencer 219 */ + 0x001A, /* R4316 - Write Sequencer 220 */ + 0x000F, /* R4317 - Write Sequencer 221 */ + 0x0305, /* R4318 - Write Sequencer 222 */ + 0x0000, /* R4319 - Write Sequencer 223 */ + 0x0045, /* R4320 - Write Sequencer 224 */ + 0x0011, /* R4321 - Write Sequencer 225 */ + 0x0400, /* R4322 - Write Sequencer 226 */ + 0x0000, /* R4323 - Write Sequencer 227 */ + 0x0045, /* R4324 - Write Sequencer 228 */ + 0x0019, /* R4325 - Write Sequencer 229 */ + 0x0401, /* R4326 - Write Sequencer 230 */ + 0x0000, /* R4327 - Write Sequencer 231 */ + 0x0060, /* R4328 - Write Sequencer 232 */ + 0x0011, /* R4329 - Write Sequencer 233 */ + 0x0400, /* R4330 - Write Sequencer 234 */ + 0x0000, /* R4331 - Write Sequencer 235 */ + 0x0060, /* R4332 - Write Sequencer 236 */ + 0x0019, /* R4333 - Write Sequencer 237 */ + 0x0401, /* R4334 - Write Sequencer 238 */ + 0x0000, /* R4335 - Write Sequencer 239 */ + 0x0002, /* R4336 - Write Sequencer 240 */ + 0x0030, /* R4337 - Write Sequencer 241 */ + 0x0600, /* R4338 - Write Sequencer 242 */ + 0x0000, /* R4339 - Write Sequencer 243 */ + 0x0003, /* R4340 - Write Sequencer 244 */ + 0x0030, /* R4341 - Write Sequencer 245 */ + 0x0600, /* R4342 - Write Sequencer 246 */ + 0x0000, /* R4343 - Write Sequencer 247 */ + 0x0003, /* R4344 - Write Sequencer 248 */ + 0x0001, /* R4345 - Write Sequencer 249 */ + 0x0008, /* R4346 - Write Sequencer 250 */ + 0x0000, /* R4347 - Write Sequencer 251 */ + 0x003D, /* R4348 - Write Sequencer 252 */ + 0x0033, /* R4349 - Write Sequencer 253 */ + 0x0502, /* R4350 - Write Sequencer 254 */ + 0x000A, /* R4351 - Write Sequencer 255 */ + 0x003E, /* R4352 - Write Sequencer 256 */ + 0x0033, /* R4353 - Write Sequencer 257 */ + 0x0502, /* R4354 - Write Sequencer 258 */ + 0x000A, /* R4355 - Write Sequencer 259 */ + 0x0007, /* R4356 - Write Sequencer 260 */ + 0x0000, /* R4357 - Write Sequencer 261 */ + 0x0102, /* R4358 - Write Sequencer 262 */ + 0x0000, /* R4359 - Write Sequencer 263 */ + 0x0045, /* R4360 - Write Sequencer 264 */ + 0x001D, /* R4361 - Write Sequencer 265 */ + 0x0402, /* R4362 - Write Sequencer 266 */ + 0x0000, /* R4363 - Write Sequencer 267 */ + 0x0045, /* R4364 - Write Sequencer 268 */ + 0x001F, /* R4365 - Write Sequencer 269 */ + 0x0403, /* R4366 - Write Sequencer 270 */ + 0x0000, /* R4367 - Write Sequencer 271 */ + 0x0060, /* R4368 - Write Sequencer 272 */ + 0x001D, /* R4369 - Write Sequencer 273 */ + 0x0402, /* R4370 - Write Sequencer 274 */ + 0x0000, /* R4371 - Write Sequencer 275 */ + 0x0060, /* R4372 - Write Sequencer 276 */ + 0x001F, /* R4373 - Write Sequencer 277 */ + 0x0403, /* R4374 - Write Sequencer 278 */ + 0x0000, /* R4375 - Write Sequencer 279 */ + 0x0005, /* R4376 - Write Sequencer 280 */ + 0x0000, /* R4377 - Write Sequencer 281 */ + 0x0003, /* R4378 - Write Sequencer 282 */ + 0x0108, /* R4379 - Write Sequencer 283 */ + 0x00FE, /* R4380 - Write Sequencer 284 */ + 0x0000, /* R4381 - Write Sequencer 285 */ + 0x0000, /* R4382 - Write Sequencer 286 */ + 0x0000, /* R4383 - Write Sequencer 287 */ + 0x0045, /* R4384 - Write Sequencer 288 */ + 0x000E, /* R4385 - Write Sequencer 289 */ + 0x0403, /* R4386 - Write Sequencer 290 */ + 0x0000, /* R4387 - Write Sequencer 291 */ + 0x001A, /* R4388 - Write Sequencer 292 */ + 0x0003, /* R4389 - Write Sequencer 293 */ + 0x0100, /* R4390 - Write Sequencer 294 */ + 0x0000, /* R4391 - Write Sequencer 295 */ + 0x0002, /* R4392 - Write Sequencer 296 */ + 0x0001, /* R4393 - Write Sequencer 297 */ + 0x0008, /* R4394 - Write Sequencer 298 */ + 0x0000, /* R4395 - Write Sequencer 299 */ + 0x0045, /* R4396 - Write Sequencer 300 */ + 0x0000, /* R4397 - Write Sequencer 301 */ + 0x0700, /* R4398 - Write Sequencer 302 */ + 0x0000, /* R4399 - Write Sequencer 303 */ + 0x0060, /* R4400 - Write Sequencer 304 */ + 0x0011, /* R4401 - Write Sequencer 305 */ + 0x0400, /* R4402 - Write Sequencer 306 */ + 0x0000, /* R4403 - Write Sequencer 307 */ + 0x0060, /* R4404 - Write Sequencer 308 */ + 0x0019, /* R4405 - Write Sequencer 309 */ + 0x0401, /* R4406 - Write Sequencer 310 */ + 0x0000, /* R4407 - Write Sequencer 311 */ + 0x001A, /* R4408 - Write Sequencer 312 */ + 0x0000, /* R4409 - Write Sequencer 313 */ + 0x0100, /* R4410 - Write Sequencer 314 */ + 0x0000, /* R4411 - Write Sequencer 315 */ + 0x0002, /* R4412 - Write Sequencer 316 */ + 0x0001, /* R4413 - Write Sequencer 317 */ + 0x0008, /* R4414 - Write Sequencer 318 */ + 0x0000, /* R4415 - Write Sequencer 319 */ + 0x0060, /* R4416 - Write Sequencer 320 */ + 0x001D, /* R4417 - Write Sequencer 321 */ + 0x0402, /* R4418 - Write Sequencer 322 */ + 0x0000, /* R4419 - Write Sequencer 323 */ + 0x0060, /* R4420 - Write Sequencer 324 */ + 0x001F, /* R4421 - Write Sequencer 325 */ + 0x0403, /* R4422 - Write Sequencer 326 */ + 0x0000, /* R4423 - Write Sequencer 327 */ + 0x0005, /* R4424 - Write Sequencer 328 */ + 0x0000, /* R4425 - Write Sequencer 329 */ + 0x0003, /* R4426 - Write Sequencer 330 */ + 0x0100, /* R4427 - Write Sequencer 331 */ + 0x00FE, /* R4428 - Write Sequencer 332 */ + 0x0000, /* R4429 - Write Sequencer 333 */ + 0x0000, /* R4430 - Write Sequencer 334 */ + 0x0000, /* R4431 - Write Sequencer 335 */ + 0x0060, /* R4432 - Write Sequencer 336 */ + 0x000E, /* R4433 - Write Sequencer 337 */ + 0x0403, /* R4434 - Write Sequencer 338 */ + 0x0000, /* R4435 - Write Sequencer 339 */ + 0x001A, /* R4436 - Write Sequencer 340 */ + 0x0003, /* R4437 - Write Sequencer 341 */ + 0x0100, /* R4438 - Write Sequencer 342 */ + 0x0000, /* R4439 - Write Sequencer 343 */ + 0x0002, /* R4440 - Write Sequencer 344 */ + 0x0001, /* R4441 - Write Sequencer 345 */ + 0x0008, /* R4442 - Write Sequencer 346 */ + 0x0000, /* R4443 - Write Sequencer 347 */ + 0x0060, /* R4444 - Write Sequencer 348 */ + 0x0000, /* R4445 - Write Sequencer 349 */ + 0x0700, /* R4446 - Write Sequencer 350 */ + 0x0000, /* R4447 - Write Sequencer 351 */ + 0x0045, /* R4448 - Write Sequencer 352 */ + 0x0011, /* R4449 - Write Sequencer 353 */ + 0x0400, /* R4450 - Write Sequencer 354 */ + 0x0000, /* R4451 - Write Sequencer 355 */ + 0x0045, /* R4452 - Write Sequencer 356 */ + 0x0019, /* R4453 - Write Sequencer 357 */ + 0x0401, /* R4454 - Write Sequencer 358 */ + 0x0000, /* R4455 - Write Sequencer 359 */ + 0x001A, /* R4456 - Write Sequencer 360 */ + 0x0000, /* R4457 - Write Sequencer 361 */ + 0x0100, /* R4458 - Write Sequencer 362 */ + 0x0000, /* R4459 - Write Sequencer 363 */ + 0x0002, /* R4460 - Write Sequencer 364 */ + 0x0001, /* R4461 - Write Sequencer 365 */ + 0x0008, /* R4462 - Write Sequencer 366 */ + 0x0000, /* R4463 - Write Sequencer 367 */ + 0x0045, /* R4464 - Write Sequencer 368 */ + 0x001D, /* R4465 - Write Sequencer 369 */ + 0x0402, /* R4466 - Write Sequencer 370 */ + 0x0000, /* R4467 - Write Sequencer 371 */ + 0x0045, /* R4468 - Write Sequencer 372 */ + 0x001F, /* R4469 - Write Sequencer 373 */ + 0x0403, /* R4470 - Write Sequencer 374 */ + 0x0000, /* R4471 - Write Sequencer 375 */ + 0x0005, /* R4472 - Write Sequencer 376 */ + 0x0000, /* R4473 - Write Sequencer 377 */ + 0x0003, /* R4474 - Write Sequencer 378 */ + 0x0100, /* R4475 - Write Sequencer 379 */ + 0x00FE, /* R4476 - Write Sequencer 380 */ + 0x0000, /* R4477 - Write Sequencer 381 */ + 0x0000, /* R4478 - Write Sequencer 382 */ + 0x0000, /* R4479 - Write Sequencer 383 */ + 0x00FE, /* R4480 - Write Sequencer 384 */ + 0x0000, /* R4481 - Write Sequencer 385 */ + 0x0000, /* R4482 - Write Sequencer 386 */ + 0x0000, /* R4483 - Write Sequencer 387 */ + 0x00FE, /* R4484 - Write Sequencer 388 */ + 0x0000, /* R4485 - Write Sequencer 389 */ + 0x0000, /* R4486 - Write Sequencer 390 */ + 0x0000, /* R4487 - Write Sequencer 391 */ + 0x00FE, /* R4488 - Write Sequencer 392 */ + 0x0000, /* R4489 - Write Sequencer 393 */ + 0x0000, /* R4490 - Write Sequencer 394 */ + 0x0000, /* R4491 - Write Sequencer 395 */ + 0x00FE, /* R4492 - Write Sequencer 396 */ + 0x0000, /* R4493 - Write Sequencer 397 */ + 0x0000, /* R4494 - Write Sequencer 398 */ + 0x0000, /* R4495 - Write Sequencer 399 */ + 0x0031, /* R4496 - Write Sequencer 400 */ + 0x0001, /* R4497 - Write Sequencer 401 */ + 0x0004, /* R4498 - Write Sequencer 402 */ + 0x0000, /* R4499 - Write Sequencer 403 */ + 0x0031, /* R4500 - Write Sequencer 404 */ + 0x0007, /* R4501 - Write Sequencer 405 */ + 0x0200, /* R4502 - Write Sequencer 406 */ + 0x0000, /* R4503 - Write Sequencer 407 */ + 0x0031, /* R4504 - Write Sequencer 408 */ + 0x0000, /* R4505 - Write Sequencer 409 */ + 0x0106, /* R4506 - Write Sequencer 410 */ + 0x0100, /* R4507 - Write Sequencer 411 */ + 0x00FE, /* R4508 - Write Sequencer 412 */ + 0x0000, /* R4509 - Write Sequencer 413 */ + 0x0000, /* R4510 - Write Sequencer 414 */ + 0x0000, /* R4511 - Write Sequencer 415 */ + 0x0031, /* R4512 - Write Sequencer 416 */ + 0x0003, /* R4513 - Write Sequencer 417 */ + 0x0106, /* R4514 - Write Sequencer 418 */ + 0x0000, /* R4515 - Write Sequencer 419 */ + 0x0031, /* R4516 - Write Sequencer 420 */ + 0x0004, /* R4517 - Write Sequencer 421 */ + 0x0200, /* R4518 - Write Sequencer 422 */ + 0x0000, /* R4519 - Write Sequencer 423 */ + 0x0031, /* R4520 - Write Sequencer 424 */ + 0x0000, /* R4521 - Write Sequencer 425 */ + 0x0004, /* R4522 - Write Sequencer 426 */ + 0x0100, /* R4523 - Write Sequencer 427 */ + 0x0000, /* R4524 - Write Sequencer 428 */ + 0x0000, /* R4525 - Write Sequencer 429 */ + 0x0000, /* R4526 - Write Sequencer 430 */ + 0x0000, /* R4527 - Write Sequencer 431 */ + 0x0000, /* R4528 - Write Sequencer 432 */ + 0x0000, /* R4529 - Write Sequencer 433 */ + 0x0000, /* R4530 - Write Sequencer 434 */ + 0x0000, /* R4531 - Write Sequencer 435 */ + 0x0000, /* R4532 - Write Sequencer 436 */ + 0x0000, /* R4533 - Write Sequencer 437 */ + 0x0000, /* R4534 - Write Sequencer 438 */ + 0x0000, /* R4535 - Write Sequencer 439 */ + 0x0000, /* R4536 - Write Sequencer 440 */ + 0x0000, /* R4537 - Write Sequencer 441 */ + 0x0000, /* R4538 - Write Sequencer 442 */ + 0x0000, /* R4539 - Write Sequencer 443 */ + 0x0000, /* R4540 - Write Sequencer 444 */ + 0x0000, /* R4541 - Write Sequencer 445 */ + 0x0000, /* R4542 - Write Sequencer 446 */ + 0x0000, /* R4543 - Write Sequencer 447 */ + 0x0000, /* R4544 - Write Sequencer 448 */ + 0x0000, /* R4545 - Write Sequencer 449 */ + 0x0000, /* R4546 - Write Sequencer 450 */ + 0x0000, /* R4547 - Write Sequencer 451 */ + 0x0000, /* R4548 - Write Sequencer 452 */ + 0x0000, /* R4549 - Write Sequencer 453 */ + 0x0000, /* R4550 - Write Sequencer 454 */ + 0x0000, /* R4551 - Write Sequencer 455 */ + 0x0000, /* R4552 - Write Sequencer 456 */ + 0x0000, /* R4553 - Write Sequencer 457 */ + 0x0000, /* R4554 - Write Sequencer 458 */ + 0x0000, /* R4555 - Write Sequencer 459 */ + 0x0000, /* R4556 - Write Sequencer 460 */ + 0x0000, /* R4557 - Write Sequencer 461 */ + 0x0000, /* R4558 - Write Sequencer 462 */ + 0x0000, /* R4559 - Write Sequencer 463 */ + 0x0000, /* R4560 - Write Sequencer 464 */ + 0x0000, /* R4561 - Write Sequencer 465 */ + 0x0000, /* R4562 - Write Sequencer 466 */ + 0x0000, /* R4563 - Write Sequencer 467 */ + 0x0000, /* R4564 - Write Sequencer 468 */ + 0x0000, /* R4565 - Write Sequencer 469 */ + 0x0000, /* R4566 - Write Sequencer 470 */ + 0x0000, /* R4567 - Write Sequencer 471 */ + 0x0000, /* R4568 - Write Sequencer 472 */ + 0x0000, /* R4569 - Write Sequencer 473 */ + 0x0000, /* R4570 - Write Sequencer 474 */ + 0x0000, /* R4571 - Write Sequencer 475 */ + 0x0000, /* R4572 - Write Sequencer 476 */ + 0x0000, /* R4573 - Write Sequencer 477 */ + 0x0000, /* R4574 - Write Sequencer 478 */ + 0x0000, /* R4575 - Write Sequencer 479 */ + 0x0000, /* R4576 - Write Sequencer 480 */ + 0x0000, /* R4577 - Write Sequencer 481 */ + 0x0000, /* R4578 - Write Sequencer 482 */ + 0x0000, /* R4579 - Write Sequencer 483 */ + 0x0000, /* R4580 - Write Sequencer 484 */ + 0x0000, /* R4581 - Write Sequencer 485 */ + 0x0000, /* R4582 - Write Sequencer 486 */ + 0x0000, /* R4583 - Write Sequencer 487 */ + 0x0000, /* R4584 - Write Sequencer 488 */ + 0x0000, /* R4585 - Write Sequencer 489 */ + 0x0000, /* R4586 - Write Sequencer 490 */ + 0x0000, /* R4587 - Write Sequencer 491 */ + 0x0000, /* R4588 - Write Sequencer 492 */ + 0x0000, /* R4589 - Write Sequencer 493 */ + 0x0000, /* R4590 - Write Sequencer 494 */ + 0x0000, /* R4591 - Write Sequencer 495 */ + 0x0000, /* R4592 - Write Sequencer 496 */ + 0x0000, /* R4593 - Write Sequencer 497 */ + 0x0000, /* R4594 - Write Sequencer 498 */ + 0x0000, /* R4595 - Write Sequencer 499 */ + 0x0000, /* R4596 - Write Sequencer 500 */ + 0x0000, /* R4597 - Write Sequencer 501 */ + 0x0000, /* R4598 - Write Sequencer 502 */ + 0x0000, /* R4599 - Write Sequencer 503 */ + 0x0000, /* R4600 - Write Sequencer 504 */ + 0x0000, /* R4601 - Write Sequencer 505 */ + 0x0000, /* R4602 - Write Sequencer 506 */ + 0x0000, /* R4603 - Write Sequencer 507 */ + 0x0000, /* R4604 - Write Sequencer 508 */ + 0x0000, /* R4605 - Write Sequencer 509 */ + 0x0000, /* R4606 - Write Sequencer 510 */ + 0x0000, /* R4607 - Write Sequencer 511 */ + 0x0000, /* R4608 */ + 0x0000, /* R4609 */ + 0x0000, /* R4610 */ + 0x0000, /* R4611 */ + 0x0000, /* R4612 */ + 0x0000, /* R4613 */ + 0x0000, /* R4614 */ + 0x0000, /* R4615 */ + 0x0000, /* R4616 */ + 0x0000, /* R4617 */ + 0x0000, /* R4618 */ + 0x0000, /* R4619 */ + 0x0000, /* R4620 */ + 0x0000, /* R4621 */ + 0x0000, /* R4622 */ + 0x0000, /* R4623 */ + 0x0000, /* R4624 */ + 0x0000, /* R4625 */ + 0x0000, /* R4626 */ + 0x0000, /* R4627 */ + 0x0000, /* R4628 */ + 0x0000, /* R4629 */ + 0x0000, /* R4630 */ + 0x0000, /* R4631 */ + 0x0000, /* R4632 */ + 0x0000, /* R4633 */ + 0x0000, /* R4634 */ + 0x0000, /* R4635 */ + 0x0000, /* R4636 */ + 0x0000, /* R4637 */ + 0x0000, /* R4638 */ + 0x0000, /* R4639 */ + 0x0000, /* R4640 */ + 0x0000, /* R4641 */ + 0x0000, /* R4642 */ + 0x0000, /* R4643 */ + 0x0000, /* R4644 */ + 0x0000, /* R4645 */ + 0x0000, /* R4646 */ + 0x0000, /* R4647 */ + 0x0000, /* R4648 */ + 0x0000, /* R4649 */ + 0x0000, /* R4650 */ + 0x0000, /* R4651 */ + 0x0000, /* R4652 */ + 0x0000, /* R4653 */ + 0x0000, /* R4654 */ + 0x0000, /* R4655 */ + 0x0000, /* R4656 */ + 0x0000, /* R4657 */ + 0x0000, /* R4658 */ + 0x0000, /* R4659 */ + 0x0000, /* R4660 */ + 0x0000, /* R4661 */ + 0x0000, /* R4662 */ + 0x0000, /* R4663 */ + 0x0000, /* R4664 */ + 0x0000, /* R4665 */ + 0x0000, /* R4666 */ + 0x0000, /* R4667 */ + 0x0000, /* R4668 */ + 0x0000, /* R4669 */ + 0x0000, /* R4670 */ + 0x0000, /* R4671 */ + 0x0000, /* R4672 */ + 0x0000, /* R4673 */ + 0x0000, /* R4674 */ + 0x0000, /* R4675 */ + 0x0000, /* R4676 */ + 0x0000, /* R4677 */ + 0x0000, /* R4678 */ + 0x0000, /* R4679 */ + 0x0000, /* R4680 */ + 0x0000, /* R4681 */ + 0x0000, /* R4682 */ + 0x0000, /* R4683 */ + 0x0000, /* R4684 */ + 0x0000, /* R4685 */ + 0x0000, /* R4686 */ + 0x0000, /* R4687 */ + 0x0000, /* R4688 */ + 0x0000, /* R4689 */ + 0x0000, /* R4690 */ + 0x0000, /* R4691 */ + 0x0000, /* R4692 */ + 0x0000, /* R4693 */ + 0x0000, /* R4694 */ + 0x0000, /* R4695 */ + 0x0000, /* R4696 */ + 0x0000, /* R4697 */ + 0x0000, /* R4698 */ + 0x0000, /* R4699 */ + 0x0000, /* R4700 */ + 0x0000, /* R4701 */ + 0x0000, /* R4702 */ + 0x0000, /* R4703 */ + 0x0000, /* R4704 */ + 0x0000, /* R4705 */ + 0x0000, /* R4706 */ + 0x0000, /* R4707 */ + 0x0000, /* R4708 */ + 0x0000, /* R4709 */ + 0x0000, /* R4710 */ + 0x0000, /* R4711 */ + 0x0000, /* R4712 */ + 0x0000, /* R4713 */ + 0x0000, /* R4714 */ + 0x0000, /* R4715 */ + 0x0000, /* R4716 */ + 0x0000, /* R4717 */ + 0x0000, /* R4718 */ + 0x0000, /* R4719 */ + 0x0000, /* R4720 */ + 0x0000, /* R4721 */ + 0x0000, /* R4722 */ + 0x0000, /* R4723 */ + 0x0000, /* R4724 */ + 0x0000, /* R4725 */ + 0x0000, /* R4726 */ + 0x0000, /* R4727 */ + 0x0000, /* R4728 */ + 0x0000, /* R4729 */ + 0x0000, /* R4730 */ + 0x0000, /* R4731 */ + 0x0000, /* R4732 */ + 0x0000, /* R4733 */ + 0x0000, /* R4734 */ + 0x0000, /* R4735 */ + 0x0000, /* R4736 */ + 0x0000, /* R4737 */ + 0x0000, /* R4738 */ + 0x0000, /* R4739 */ + 0x0000, /* R4740 */ + 0x0000, /* R4741 */ + 0x0000, /* R4742 */ + 0x0000, /* R4743 */ + 0x0000, /* R4744 */ + 0x0000, /* R4745 */ + 0x0000, /* R4746 */ + 0x0000, /* R4747 */ + 0x0000, /* R4748 */ + 0x0000, /* R4749 */ + 0x0000, /* R4750 */ + 0x0000, /* R4751 */ + 0x0000, /* R4752 */ + 0x0000, /* R4753 */ + 0x0000, /* R4754 */ + 0x0000, /* R4755 */ + 0x0000, /* R4756 */ + 0x0000, /* R4757 */ + 0x0000, /* R4758 */ + 0x0000, /* R4759 */ + 0x0000, /* R4760 */ + 0x0000, /* R4761 */ + 0x0000, /* R4762 */ + 0x0000, /* R4763 */ + 0x0000, /* R4764 */ + 0x0000, /* R4765 */ + 0x0000, /* R4766 */ + 0x0000, /* R4767 */ + 0x0000, /* R4768 */ + 0x0000, /* R4769 */ + 0x0000, /* R4770 */ + 0x0000, /* R4771 */ + 0x0000, /* R4772 */ + 0x0000, /* R4773 */ + 0x0000, /* R4774 */ + 0x0000, /* R4775 */ + 0x0000, /* R4776 */ + 0x0000, /* R4777 */ + 0x0000, /* R4778 */ + 0x0000, /* R4779 */ + 0x0000, /* R4780 */ + 0x0000, /* R4781 */ + 0x0000, /* R4782 */ + 0x0000, /* R4783 */ + 0x0000, /* R4784 */ + 0x0000, /* R4785 */ + 0x0000, /* R4786 */ + 0x0000, /* R4787 */ + 0x0000, /* R4788 */ + 0x0000, /* R4789 */ + 0x0000, /* R4790 */ + 0x0000, /* R4791 */ + 0x0000, /* R4792 */ + 0x0000, /* R4793 */ + 0x0000, /* R4794 */ + 0x0000, /* R4795 */ + 0x0000, /* R4796 */ + 0x0000, /* R4797 */ + 0x0000, /* R4798 */ + 0x0000, /* R4799 */ + 0x0000, /* R4800 */ + 0x0000, /* R4801 */ + 0x0000, /* R4802 */ + 0x0000, /* R4803 */ + 0x0000, /* R4804 */ + 0x0000, /* R4805 */ + 0x0000, /* R4806 */ + 0x0000, /* R4807 */ + 0x0000, /* R4808 */ + 0x0000, /* R4809 */ + 0x0000, /* R4810 */ + 0x0000, /* R4811 */ + 0x0000, /* R4812 */ + 0x0000, /* R4813 */ + 0x0000, /* R4814 */ + 0x0000, /* R4815 */ + 0x0000, /* R4816 */ + 0x0000, /* R4817 */ + 0x0000, /* R4818 */ + 0x0000, /* R4819 */ + 0x0000, /* R4820 */ + 0x0000, /* R4821 */ + 0x0000, /* R4822 */ + 0x0000, /* R4823 */ + 0x0000, /* R4824 */ + 0x0000, /* R4825 */ + 0x0000, /* R4826 */ + 0x0000, /* R4827 */ + 0x0000, /* R4828 */ + 0x0000, /* R4829 */ + 0x0000, /* R4830 */ + 0x0000, /* R4831 */ + 0x0000, /* R4832 */ + 0x0000, /* R4833 */ + 0x0000, /* R4834 */ + 0x0000, /* R4835 */ + 0x0000, /* R4836 */ + 0x0000, /* R4837 */ + 0x0000, /* R4838 */ + 0x0000, /* R4839 */ + 0x0000, /* R4840 */ + 0x0000, /* R4841 */ + 0x0000, /* R4842 */ + 0x0000, /* R4843 */ + 0x0000, /* R4844 */ + 0x0000, /* R4845 */ + 0x0000, /* R4846 */ + 0x0000, /* R4847 */ + 0x0000, /* R4848 */ + 0x0000, /* R4849 */ + 0x0000, /* R4850 */ + 0x0000, /* R4851 */ + 0x0000, /* R4852 */ + 0x0000, /* R4853 */ + 0x0000, /* R4854 */ + 0x0000, /* R4855 */ + 0x0000, /* R4856 */ + 0x0000, /* R4857 */ + 0x0000, /* R4858 */ + 0x0000, /* R4859 */ + 0x0000, /* R4860 */ + 0x0000, /* R4861 */ + 0x0000, /* R4862 */ + 0x0000, /* R4863 */ + 0x0000, /* R4864 */ + 0x0000, /* R4865 */ + 0x0000, /* R4866 */ + 0x0000, /* R4867 */ + 0x0000, /* R4868 */ + 0x0000, /* R4869 */ + 0x0000, /* R4870 */ + 0x0000, /* R4871 */ + 0x0000, /* R4872 */ + 0x0000, /* R4873 */ + 0x0000, /* R4874 */ + 0x0000, /* R4875 */ + 0x0000, /* R4876 */ + 0x0000, /* R4877 */ + 0x0000, /* R4878 */ + 0x0000, /* R4879 */ + 0x0000, /* R4880 */ + 0x0000, /* R4881 */ + 0x0000, /* R4882 */ + 0x0000, /* R4883 */ + 0x0000, /* R4884 */ + 0x0000, /* R4885 */ + 0x0000, /* R4886 */ + 0x0000, /* R4887 */ + 0x0000, /* R4888 */ + 0x0000, /* R4889 */ + 0x0000, /* R4890 */ + 0x0000, /* R4891 */ + 0x0000, /* R4892 */ + 0x0000, /* R4893 */ + 0x0000, /* R4894 */ + 0x0000, /* R4895 */ + 0x0000, /* R4896 */ + 0x0000, /* R4897 */ + 0x0000, /* R4898 */ + 0x0000, /* R4899 */ + 0x0000, /* R4900 */ + 0x0000, /* R4901 */ + 0x0000, /* R4902 */ + 0x0000, /* R4903 */ + 0x0000, /* R4904 */ + 0x0000, /* R4905 */ + 0x0000, /* R4906 */ + 0x0000, /* R4907 */ + 0x0000, /* R4908 */ + 0x0000, /* R4909 */ + 0x0000, /* R4910 */ + 0x0000, /* R4911 */ + 0x0000, /* R4912 */ + 0x0000, /* R4913 */ + 0x0000, /* R4914 */ + 0x0000, /* R4915 */ + 0x0000, /* R4916 */ + 0x0000, /* R4917 */ + 0x0000, /* R4918 */ + 0x0000, /* R4919 */ + 0x0000, /* R4920 */ + 0x0000, /* R4921 */ + 0x0000, /* R4922 */ + 0x0000, /* R4923 */ + 0x0000, /* R4924 */ + 0x0000, /* R4925 */ + 0x0000, /* R4926 */ + 0x0000, /* R4927 */ + 0x0000, /* R4928 */ + 0x0000, /* R4929 */ + 0x0000, /* R4930 */ + 0x0000, /* R4931 */ + 0x0000, /* R4932 */ + 0x0000, /* R4933 */ + 0x0000, /* R4934 */ + 0x0000, /* R4935 */ + 0x0000, /* R4936 */ + 0x0000, /* R4937 */ + 0x0000, /* R4938 */ + 0x0000, /* R4939 */ + 0x0000, /* R4940 */ + 0x0000, /* R4941 */ + 0x0000, /* R4942 */ + 0x0000, /* R4943 */ + 0x0000, /* R4944 */ + 0x0000, /* R4945 */ + 0x0000, /* R4946 */ + 0x0000, /* R4947 */ + 0x0000, /* R4948 */ + 0x0000, /* R4949 */ + 0x0000, /* R4950 */ + 0x0000, /* R4951 */ + 0x0000, /* R4952 */ + 0x0000, /* R4953 */ + 0x0000, /* R4954 */ + 0x0000, /* R4955 */ + 0x0000, /* R4956 */ + 0x0000, /* R4957 */ + 0x0000, /* R4958 */ + 0x0000, /* R4959 */ + 0x0000, /* R4960 */ + 0x0000, /* R4961 */ + 0x0000, /* R4962 */ + 0x0000, /* R4963 */ + 0x0000, /* R4964 */ + 0x0000, /* R4965 */ + 0x0000, /* R4966 */ + 0x0000, /* R4967 */ + 0x0000, /* R4968 */ + 0x0000, /* R4969 */ + 0x0000, /* R4970 */ + 0x0000, /* R4971 */ + 0x0000, /* R4972 */ + 0x0000, /* R4973 */ + 0x0000, /* R4974 */ + 0x0000, /* R4975 */ + 0x0000, /* R4976 */ + 0x0000, /* R4977 */ + 0x0000, /* R4978 */ + 0x0000, /* R4979 */ + 0x0000, /* R4980 */ + 0x0000, /* R4981 */ + 0x0000, /* R4982 */ + 0x0000, /* R4983 */ + 0x0000, /* R4984 */ + 0x0000, /* R4985 */ + 0x0000, /* R4986 */ + 0x0000, /* R4987 */ + 0x0000, /* R4988 */ + 0x0000, /* R4989 */ + 0x0000, /* R4990 */ + 0x0000, /* R4991 */ + 0x0000, /* R4992 */ + 0x0000, /* R4993 */ + 0x0000, /* R4994 */ + 0x0000, /* R4995 */ + 0x0000, /* R4996 */ + 0x0000, /* R4997 */ + 0x0000, /* R4998 */ + 0x0000, /* R4999 */ + 0x0000, /* R5000 */ + 0x0000, /* R5001 */ + 0x0000, /* R5002 */ + 0x0000, /* R5003 */ + 0x0000, /* R5004 */ + 0x0000, /* R5005 */ + 0x0000, /* R5006 */ + 0x0000, /* R5007 */ + 0x0000, /* R5008 */ + 0x0000, /* R5009 */ + 0x0000, /* R5010 */ + 0x0000, /* R5011 */ + 0x0000, /* R5012 */ + 0x0000, /* R5013 */ + 0x0000, /* R5014 */ + 0x0000, /* R5015 */ + 0x0000, /* R5016 */ + 0x0000, /* R5017 */ + 0x0000, /* R5018 */ + 0x0000, /* R5019 */ + 0x0000, /* R5020 */ + 0x0000, /* R5021 */ + 0x0000, /* R5022 */ + 0x0000, /* R5023 */ + 0x0000, /* R5024 */ + 0x0000, /* R5025 */ + 0x0000, /* R5026 */ + 0x0000, /* R5027 */ + 0x0000, /* R5028 */ + 0x0000, /* R5029 */ + 0x0000, /* R5030 */ + 0x0000, /* R5031 */ + 0x0000, /* R5032 */ + 0x0000, /* R5033 */ + 0x0000, /* R5034 */ + 0x0000, /* R5035 */ + 0x0000, /* R5036 */ + 0x0000, /* R5037 */ + 0x0000, /* R5038 */ + 0x0000, /* R5039 */ + 0x0000, /* R5040 */ + 0x0000, /* R5041 */ + 0x0000, /* R5042 */ + 0x0000, /* R5043 */ + 0x0000, /* R5044 */ + 0x0000, /* R5045 */ + 0x0000, /* R5046 */ + 0x0000, /* R5047 */ + 0x0000, /* R5048 */ + 0x0000, /* R5049 */ + 0x0000, /* R5050 */ + 0x0000, /* R5051 */ + 0x0000, /* R5052 */ + 0x0000, /* R5053 */ + 0x0000, /* R5054 */ + 0x0000, /* R5055 */ + 0x0000, /* R5056 */ + 0x0000, /* R5057 */ + 0x0000, /* R5058 */ + 0x0000, /* R5059 */ + 0x0000, /* R5060 */ + 0x0000, /* R5061 */ + 0x0000, /* R5062 */ + 0x0000, /* R5063 */ + 0x0000, /* R5064 */ + 0x0000, /* R5065 */ + 0x0000, /* R5066 */ + 0x0000, /* R5067 */ + 0x0000, /* R5068 */ + 0x0000, /* R5069 */ + 0x0000, /* R5070 */ + 0x0000, /* R5071 */ + 0x0000, /* R5072 */ + 0x0000, /* R5073 */ + 0x0000, /* R5074 */ + 0x0000, /* R5075 */ + 0x0000, /* R5076 */ + 0x0000, /* R5077 */ + 0x0000, /* R5078 */ + 0x0000, /* R5079 */ + 0x0000, /* R5080 */ + 0x0000, /* R5081 */ + 0x0000, /* R5082 */ + 0x0000, /* R5083 */ + 0x0000, /* R5084 */ + 0x0000, /* R5085 */ + 0x0000, /* R5086 */ + 0x0000, /* R5087 */ + 0x0000, /* R5088 */ + 0x0000, /* R5089 */ + 0x0000, /* R5090 */ + 0x0000, /* R5091 */ + 0x0000, /* R5092 */ + 0x0000, /* R5093 */ + 0x0000, /* R5094 */ + 0x0000, /* R5095 */ + 0x0000, /* R5096 */ + 0x0000, /* R5097 */ + 0x0000, /* R5098 */ + 0x0000, /* R5099 */ + 0x0000, /* R5100 */ + 0x0000, /* R5101 */ + 0x0000, /* R5102 */ + 0x0000, /* R5103 */ + 0x0000, /* R5104 */ + 0x0000, /* R5105 */ + 0x0000, /* R5106 */ + 0x0000, /* R5107 */ + 0x0000, /* R5108 */ + 0x0000, /* R5109 */ + 0x0000, /* R5110 */ + 0x0000, /* R5111 */ + 0x0000, /* R5112 */ + 0x0000, /* R5113 */ + 0x0000, /* R5114 */ + 0x0000, /* R5115 */ + 0x0000, /* R5116 */ + 0x0000, /* R5117 */ + 0x0000, /* R5118 */ + 0x0000, /* R5119 */ + 0x0000, /* R5120 */ + 0x0000, /* R5121 */ + 0x0000, /* R5122 */ + 0x0000, /* R5123 */ + 0x0000, /* R5124 */ + 0x0000, /* R5125 */ + 0x0000, /* R5126 */ + 0x0000, /* R5127 */ + 0x0000, /* R5128 */ + 0x0000, /* R5129 */ + 0x0000, /* R5130 */ + 0x0000, /* R5131 */ + 0x0000, /* R5132 */ + 0x0000, /* R5133 */ + 0x0000, /* R5134 */ + 0x0000, /* R5135 */ + 0x0000, /* R5136 */ + 0x0000, /* R5137 */ + 0x0000, /* R5138 */ + 0x0000, /* R5139 */ + 0x0000, /* R5140 */ + 0x0000, /* R5141 */ + 0x0000, /* R5142 */ + 0x0000, /* R5143 */ + 0x0000, /* R5144 */ + 0x0000, /* R5145 */ + 0x0000, /* R5146 */ + 0x0000, /* R5147 */ + 0x0000, /* R5148 */ + 0x0000, /* R5149 */ + 0x0000, /* R5150 */ + 0x0000, /* R5151 */ + 0x0000, /* R5152 */ + 0x0000, /* R5153 */ + 0x0000, /* R5154 */ + 0x0000, /* R5155 */ + 0x0000, /* R5156 */ + 0x0000, /* R5157 */ + 0x0000, /* R5158 */ + 0x0000, /* R5159 */ + 0x0000, /* R5160 */ + 0x0000, /* R5161 */ + 0x0000, /* R5162 */ + 0x0000, /* R5163 */ + 0x0000, /* R5164 */ + 0x0000, /* R5165 */ + 0x0000, /* R5166 */ + 0x0000, /* R5167 */ + 0x0000, /* R5168 */ + 0x0000, /* R5169 */ + 0x0000, /* R5170 */ + 0x0000, /* R5171 */ + 0x0000, /* R5172 */ + 0x0000, /* R5173 */ + 0x0000, /* R5174 */ + 0x0000, /* R5175 */ + 0x0000, /* R5176 */ + 0x0000, /* R5177 */ + 0x0000, /* R5178 */ + 0x0000, /* R5179 */ + 0x0000, /* R5180 */ + 0x0000, /* R5181 */ + 0x0000, /* R5182 */ + 0x0000, /* R5183 */ + 0x0000, /* R5184 */ + 0x0000, /* R5185 */ + 0x0000, /* R5186 */ + 0x0000, /* R5187 */ + 0x0000, /* R5188 */ + 0x0000, /* R5189 */ + 0x0000, /* R5190 */ + 0x0000, /* R5191 */ + 0x0000, /* R5192 */ + 0x0000, /* R5193 */ + 0x0000, /* R5194 */ + 0x0000, /* R5195 */ + 0x0000, /* R5196 */ + 0x0000, /* R5197 */ + 0x0000, /* R5198 */ + 0x0000, /* R5199 */ + 0x0000, /* R5200 */ + 0x0000, /* R5201 */ + 0x0000, /* R5202 */ + 0x0000, /* R5203 */ + 0x0000, /* R5204 */ + 0x0000, /* R5205 */ + 0x0000, /* R5206 */ + 0x0000, /* R5207 */ + 0x0000, /* R5208 */ + 0x0000, /* R5209 */ + 0x0000, /* R5210 */ + 0x0000, /* R5211 */ + 0x0000, /* R5212 */ + 0x0000, /* R5213 */ + 0x0000, /* R5214 */ + 0x0000, /* R5215 */ + 0x0000, /* R5216 */ + 0x0000, /* R5217 */ + 0x0000, /* R5218 */ + 0x0000, /* R5219 */ + 0x0000, /* R5220 */ + 0x0000, /* R5221 */ + 0x0000, /* R5222 */ + 0x0000, /* R5223 */ + 0x0000, /* R5224 */ + 0x0000, /* R5225 */ + 0x0000, /* R5226 */ + 0x0000, /* R5227 */ + 0x0000, /* R5228 */ + 0x0000, /* R5229 */ + 0x0000, /* R5230 */ + 0x0000, /* R5231 */ + 0x0000, /* R5232 */ + 0x0000, /* R5233 */ + 0x0000, /* R5234 */ + 0x0000, /* R5235 */ + 0x0000, /* R5236 */ + 0x0000, /* R5237 */ + 0x0000, /* R5238 */ + 0x0000, /* R5239 */ + 0x0000, /* R5240 */ + 0x0000, /* R5241 */ + 0x0000, /* R5242 */ + 0x0000, /* R5243 */ + 0x0000, /* R5244 */ + 0x0000, /* R5245 */ + 0x0000, /* R5246 */ + 0x0000, /* R5247 */ + 0x0000, /* R5248 */ + 0x0000, /* R5249 */ + 0x0000, /* R5250 */ + 0x0000, /* R5251 */ + 0x0000, /* R5252 */ + 0x0000, /* R5253 */ + 0x0000, /* R5254 */ + 0x0000, /* R5255 */ + 0x0000, /* R5256 */ + 0x0000, /* R5257 */ + 0x0000, /* R5258 */ + 0x0000, /* R5259 */ + 0x0000, /* R5260 */ + 0x0000, /* R5261 */ + 0x0000, /* R5262 */ + 0x0000, /* R5263 */ + 0x0000, /* R5264 */ + 0x0000, /* R5265 */ + 0x0000, /* R5266 */ + 0x0000, /* R5267 */ + 0x0000, /* R5268 */ + 0x0000, /* R5269 */ + 0x0000, /* R5270 */ + 0x0000, /* R5271 */ + 0x0000, /* R5272 */ + 0x0000, /* R5273 */ + 0x0000, /* R5274 */ + 0x0000, /* R5275 */ + 0x0000, /* R5276 */ + 0x0000, /* R5277 */ + 0x0000, /* R5278 */ + 0x0000, /* R5279 */ + 0x0000, /* R5280 */ + 0x0000, /* R5281 */ + 0x0000, /* R5282 */ + 0x0000, /* R5283 */ + 0x0000, /* R5284 */ + 0x0000, /* R5285 */ + 0x0000, /* R5286 */ + 0x0000, /* R5287 */ + 0x0000, /* R5288 */ + 0x0000, /* R5289 */ + 0x0000, /* R5290 */ + 0x0000, /* R5291 */ + 0x0000, /* R5292 */ + 0x0000, /* R5293 */ + 0x0000, /* R5294 */ + 0x0000, /* R5295 */ + 0x0000, /* R5296 */ + 0x0000, /* R5297 */ + 0x0000, /* R5298 */ + 0x0000, /* R5299 */ + 0x0000, /* R5300 */ + 0x0000, /* R5301 */ + 0x0000, /* R5302 */ + 0x0000, /* R5303 */ + 0x0000, /* R5304 */ + 0x0000, /* R5305 */ + 0x0000, /* R5306 */ + 0x0000, /* R5307 */ + 0x0000, /* R5308 */ + 0x0000, /* R5309 */ + 0x0000, /* R5310 */ + 0x0000, /* R5311 */ + 0x0000, /* R5312 */ + 0x0000, /* R5313 */ + 0x0000, /* R5314 */ + 0x0000, /* R5315 */ + 0x0000, /* R5316 */ + 0x0000, /* R5317 */ + 0x0000, /* R5318 */ + 0x0000, /* R5319 */ + 0x0000, /* R5320 */ + 0x0000, /* R5321 */ + 0x0000, /* R5322 */ + 0x0000, /* R5323 */ + 0x0000, /* R5324 */ + 0x0000, /* R5325 */ + 0x0000, /* R5326 */ + 0x0000, /* R5327 */ + 0x0000, /* R5328 */ + 0x0000, /* R5329 */ + 0x0000, /* R5330 */ + 0x0000, /* R5331 */ + 0x0000, /* R5332 */ + 0x0000, /* R5333 */ + 0x0000, /* R5334 */ + 0x0000, /* R5335 */ + 0x0000, /* R5336 */ + 0x0000, /* R5337 */ + 0x0000, /* R5338 */ + 0x0000, /* R5339 */ + 0x0000, /* R5340 */ + 0x0000, /* R5341 */ + 0x0000, /* R5342 */ + 0x0000, /* R5343 */ + 0x0000, /* R5344 */ + 0x0000, /* R5345 */ + 0x0000, /* R5346 */ + 0x0000, /* R5347 */ + 0x0000, /* R5348 */ + 0x0000, /* R5349 */ + 0x0000, /* R5350 */ + 0x0000, /* R5351 */ + 0x0000, /* R5352 */ + 0x0000, /* R5353 */ + 0x0000, /* R5354 */ + 0x0000, /* R5355 */ + 0x0000, /* R5356 */ + 0x0000, /* R5357 */ + 0x0000, /* R5358 */ + 0x0000, /* R5359 */ + 0x0000, /* R5360 */ + 0x0000, /* R5361 */ + 0x0000, /* R5362 */ + 0x0000, /* R5363 */ + 0x0000, /* R5364 */ + 0x0000, /* R5365 */ + 0x0000, /* R5366 */ + 0x0000, /* R5367 */ + 0x0000, /* R5368 */ + 0x0000, /* R5369 */ + 0x0000, /* R5370 */ + 0x0000, /* R5371 */ + 0x0000, /* R5372 */ + 0x0000, /* R5373 */ + 0x0000, /* R5374 */ + 0x0000, /* R5375 */ + 0x0000, /* R5376 */ + 0x0000, /* R5377 */ + 0x0000, /* R5378 */ + 0x0000, /* R5379 */ + 0x0000, /* R5380 */ + 0x0000, /* R5381 */ + 0x0000, /* R5382 */ + 0x0000, /* R5383 */ + 0x0000, /* R5384 */ + 0x0000, /* R5385 */ + 0x0000, /* R5386 */ + 0x0000, /* R5387 */ + 0x0000, /* R5388 */ + 0x0000, /* R5389 */ + 0x0000, /* R5390 */ + 0x0000, /* R5391 */ + 0x0000, /* R5392 */ + 0x0000, /* R5393 */ + 0x0000, /* R5394 */ + 0x0000, /* R5395 */ + 0x0000, /* R5396 */ + 0x0000, /* R5397 */ + 0x0000, /* R5398 */ + 0x0000, /* R5399 */ + 0x0000, /* R5400 */ + 0x0000, /* R5401 */ + 0x0000, /* R5402 */ + 0x0000, /* R5403 */ + 0x0000, /* R5404 */ + 0x0000, /* R5405 */ + 0x0000, /* R5406 */ + 0x0000, /* R5407 */ + 0x0000, /* R5408 */ + 0x0000, /* R5409 */ + 0x0000, /* R5410 */ + 0x0000, /* R5411 */ + 0x0000, /* R5412 */ + 0x0000, /* R5413 */ + 0x0000, /* R5414 */ + 0x0000, /* R5415 */ + 0x0000, /* R5416 */ + 0x0000, /* R5417 */ + 0x0000, /* R5418 */ + 0x0000, /* R5419 */ + 0x0000, /* R5420 */ + 0x0000, /* R5421 */ + 0x0000, /* R5422 */ + 0x0000, /* R5423 */ + 0x0000, /* R5424 */ + 0x0000, /* R5425 */ + 0x0000, /* R5426 */ + 0x0000, /* R5427 */ + 0x0000, /* R5428 */ + 0x0000, /* R5429 */ + 0x0000, /* R5430 */ + 0x0000, /* R5431 */ + 0x0000, /* R5432 */ + 0x0000, /* R5433 */ + 0x0000, /* R5434 */ + 0x0000, /* R5435 */ + 0x0000, /* R5436 */ + 0x0000, /* R5437 */ + 0x0000, /* R5438 */ + 0x0000, /* R5439 */ + 0x0000, /* R5440 */ + 0x0000, /* R5441 */ + 0x0000, /* R5442 */ + 0x0000, /* R5443 */ + 0x0000, /* R5444 */ + 0x0000, /* R5445 */ + 0x0000, /* R5446 */ + 0x0000, /* R5447 */ + 0x0000, /* R5448 */ + 0x0000, /* R5449 */ + 0x0000, /* R5450 */ + 0x0000, /* R5451 */ + 0x0000, /* R5452 */ + 0x0000, /* R5453 */ + 0x0000, /* R5454 */ + 0x0000, /* R5455 */ + 0x0000, /* R5456 */ + 0x0000, /* R5457 */ + 0x0000, /* R5458 */ + 0x0000, /* R5459 */ + 0x0000, /* R5460 */ + 0x0000, /* R5461 */ + 0x0000, /* R5462 */ + 0x0000, /* R5463 */ + 0x0000, /* R5464 */ + 0x0000, /* R5465 */ + 0x0000, /* R5466 */ + 0x0000, /* R5467 */ + 0x0000, /* R5468 */ + 0x0000, /* R5469 */ + 0x0000, /* R5470 */ + 0x0000, /* R5471 */ + 0x0000, /* R5472 */ + 0x0000, /* R5473 */ + 0x0000, /* R5474 */ + 0x0000, /* R5475 */ + 0x0000, /* R5476 */ + 0x0000, /* R5477 */ + 0x0000, /* R5478 */ + 0x0000, /* R5479 */ + 0x0000, /* R5480 */ + 0x0000, /* R5481 */ + 0x0000, /* R5482 */ + 0x0000, /* R5483 */ + 0x0000, /* R5484 */ + 0x0000, /* R5485 */ + 0x0000, /* R5486 */ + 0x0000, /* R5487 */ + 0x0000, /* R5488 */ + 0x0000, /* R5489 */ + 0x0000, /* R5490 */ + 0x0000, /* R5491 */ + 0x0000, /* R5492 */ + 0x0000, /* R5493 */ + 0x0000, /* R5494 */ + 0x0000, /* R5495 */ + 0x0000, /* R5496 */ + 0x0000, /* R5497 */ + 0x0000, /* R5498 */ + 0x0000, /* R5499 */ + 0x0000, /* R5500 */ + 0x0000, /* R5501 */ + 0x0000, /* R5502 */ + 0x0000, /* R5503 */ + 0x0000, /* R5504 */ + 0x0000, /* R5505 */ + 0x0000, /* R5506 */ + 0x0000, /* R5507 */ + 0x0000, /* R5508 */ + 0x0000, /* R5509 */ + 0x0000, /* R5510 */ + 0x0000, /* R5511 */ + 0x0000, /* R5512 */ + 0x0000, /* R5513 */ + 0x0000, /* R5514 */ + 0x0000, /* R5515 */ + 0x0000, /* R5516 */ + 0x0000, /* R5517 */ + 0x0000, /* R5518 */ + 0x0000, /* R5519 */ + 0x0000, /* R5520 */ + 0x0000, /* R5521 */ + 0x0000, /* R5522 */ + 0x0000, /* R5523 */ + 0x0000, /* R5524 */ + 0x0000, /* R5525 */ + 0x0000, /* R5526 */ + 0x0000, /* R5527 */ + 0x0000, /* R5528 */ + 0x0000, /* R5529 */ + 0x0000, /* R5530 */ + 0x0000, /* R5531 */ + 0x0000, /* R5532 */ + 0x0000, /* R5533 */ + 0x0000, /* R5534 */ + 0x0000, /* R5535 */ + 0x0000, /* R5536 */ + 0x0000, /* R5537 */ + 0x0000, /* R5538 */ + 0x0000, /* R5539 */ + 0x0000, /* R5540 */ + 0x0000, /* R5541 */ + 0x0000, /* R5542 */ + 0x0000, /* R5543 */ + 0x0000, /* R5544 */ + 0x0000, /* R5545 */ + 0x0000, /* R5546 */ + 0x0000, /* R5547 */ + 0x0000, /* R5548 */ + 0x0000, /* R5549 */ + 0x0000, /* R5550 */ + 0x0000, /* R5551 */ + 0x0000, /* R5552 */ + 0x0000, /* R5553 */ + 0x0000, /* R5554 */ + 0x0000, /* R5555 */ + 0x0000, /* R5556 */ + 0x0000, /* R5557 */ + 0x0000, /* R5558 */ + 0x0000, /* R5559 */ + 0x0000, /* R5560 */ + 0x0000, /* R5561 */ + 0x0000, /* R5562 */ + 0x0000, /* R5563 */ + 0x0000, /* R5564 */ + 0x0000, /* R5565 */ + 0x0000, /* R5566 */ + 0x0000, /* R5567 */ + 0x0000, /* R5568 */ + 0x0000, /* R5569 */ + 0x0000, /* R5570 */ + 0x0000, /* R5571 */ + 0x0000, /* R5572 */ + 0x0000, /* R5573 */ + 0x0000, /* R5574 */ + 0x0000, /* R5575 */ + 0x0000, /* R5576 */ + 0x0000, /* R5577 */ + 0x0000, /* R5578 */ + 0x0000, /* R5579 */ + 0x0000, /* R5580 */ + 0x0000, /* R5581 */ + 0x0000, /* R5582 */ + 0x0000, /* R5583 */ + 0x0000, /* R5584 */ + 0x0000, /* R5585 */ + 0x0000, /* R5586 */ + 0x0000, /* R5587 */ + 0x0000, /* R5588 */ + 0x0000, /* R5589 */ + 0x0000, /* R5590 */ + 0x0000, /* R5591 */ + 0x0000, /* R5592 */ + 0x0000, /* R5593 */ + 0x0000, /* R5594 */ + 0x0000, /* R5595 */ + 0x0000, /* R5596 */ + 0x0000, /* R5597 */ + 0x0000, /* R5598 */ + 0x0000, /* R5599 */ + 0x0000, /* R5600 */ + 0x0000, /* R5601 */ + 0x0000, /* R5602 */ + 0x0000, /* R5603 */ + 0x0000, /* R5604 */ + 0x0000, /* R5605 */ + 0x0000, /* R5606 */ + 0x0000, /* R5607 */ + 0x0000, /* R5608 */ + 0x0000, /* R5609 */ + 0x0000, /* R5610 */ + 0x0000, /* R5611 */ + 0x0000, /* R5612 */ + 0x0000, /* R5613 */ + 0x0000, /* R5614 */ + 0x0000, /* R5615 */ + 0x0000, /* R5616 */ + 0x0000, /* R5617 */ + 0x0000, /* R5618 */ + 0x0000, /* R5619 */ + 0x0000, /* R5620 */ + 0x0000, /* R5621 */ + 0x0000, /* R5622 */ + 0x0000, /* R5623 */ + 0x0000, /* R5624 */ + 0x0000, /* R5625 */ + 0x0000, /* R5626 */ + 0x0000, /* R5627 */ + 0x0000, /* R5628 */ + 0x0000, /* R5629 */ + 0x0000, /* R5630 */ + 0x0000, /* R5631 */ + 0x0000, /* R5632 */ + 0x0000, /* R5633 */ + 0x0000, /* R5634 */ + 0x0000, /* R5635 */ + 0x0000, /* R5636 */ + 0x0000, /* R5637 */ + 0x0000, /* R5638 */ + 0x0000, /* R5639 */ + 0x0000, /* R5640 */ + 0x0000, /* R5641 */ + 0x0000, /* R5642 */ + 0x0000, /* R5643 */ + 0x0000, /* R5644 */ + 0x0000, /* R5645 */ + 0x0000, /* R5646 */ + 0x0000, /* R5647 */ + 0x0000, /* R5648 */ + 0x0000, /* R5649 */ + 0x0000, /* R5650 */ + 0x0000, /* R5651 */ + 0x0000, /* R5652 */ + 0x0000, /* R5653 */ + 0x0000, /* R5654 */ + 0x0000, /* R5655 */ + 0x0000, /* R5656 */ + 0x0000, /* R5657 */ + 0x0000, /* R5658 */ + 0x0000, /* R5659 */ + 0x0000, /* R5660 */ + 0x0000, /* R5661 */ + 0x0000, /* R5662 */ + 0x0000, /* R5663 */ + 0x0000, /* R5664 */ + 0x0000, /* R5665 */ + 0x0000, /* R5666 */ + 0x0000, /* R5667 */ + 0x0000, /* R5668 */ + 0x0000, /* R5669 */ + 0x0000, /* R5670 */ + 0x0000, /* R5671 */ + 0x0000, /* R5672 */ + 0x0000, /* R5673 */ + 0x0000, /* R5674 */ + 0x0000, /* R5675 */ + 0x0000, /* R5676 */ + 0x0000, /* R5677 */ + 0x0000, /* R5678 */ + 0x0000, /* R5679 */ + 0x0000, /* R5680 */ + 0x0000, /* R5681 */ + 0x0000, /* R5682 */ + 0x0000, /* R5683 */ + 0x0000, /* R5684 */ + 0x0000, /* R5685 */ + 0x0000, /* R5686 */ + 0x0000, /* R5687 */ + 0x0000, /* R5688 */ + 0x0000, /* R5689 */ + 0x0000, /* R5690 */ + 0x0000, /* R5691 */ + 0x0000, /* R5692 */ + 0x0000, /* R5693 */ + 0x0000, /* R5694 */ + 0x0000, /* R5695 */ + 0x0000, /* R5696 */ + 0x0000, /* R5697 */ + 0x0000, /* R5698 */ + 0x0000, /* R5699 */ + 0x0000, /* R5700 */ + 0x0000, /* R5701 */ + 0x0000, /* R5702 */ + 0x0000, /* R5703 */ + 0x0000, /* R5704 */ + 0x0000, /* R5705 */ + 0x0000, /* R5706 */ + 0x0000, /* R5707 */ + 0x0000, /* R5708 */ + 0x0000, /* R5709 */ + 0x0000, /* R5710 */ + 0x0000, /* R5711 */ + 0x0000, /* R5712 */ + 0x0000, /* R5713 */ + 0x0000, /* R5714 */ + 0x0000, /* R5715 */ + 0x0000, /* R5716 */ + 0x0000, /* R5717 */ + 0x0000, /* R5718 */ + 0x0000, /* R5719 */ + 0x0000, /* R5720 */ + 0x0000, /* R5721 */ + 0x0000, /* R5722 */ + 0x0000, /* R5723 */ + 0x0000, /* R5724 */ + 0x0000, /* R5725 */ + 0x0000, /* R5726 */ + 0x0000, /* R5727 */ + 0x0000, /* R5728 */ + 0x0000, /* R5729 */ + 0x0000, /* R5730 */ + 0x0000, /* R5731 */ + 0x0000, /* R5732 */ + 0x0000, /* R5733 */ + 0x0000, /* R5734 */ + 0x0000, /* R5735 */ + 0x0000, /* R5736 */ + 0x0000, /* R5737 */ + 0x0000, /* R5738 */ + 0x0000, /* R5739 */ + 0x0000, /* R5740 */ + 0x0000, /* R5741 */ + 0x0000, /* R5742 */ + 0x0000, /* R5743 */ + 0x0000, /* R5744 */ + 0x0000, /* R5745 */ + 0x0000, /* R5746 */ + 0x0000, /* R5747 */ + 0x0000, /* R5748 */ + 0x0000, /* R5749 */ + 0x0000, /* R5750 */ + 0x0000, /* R5751 */ + 0x0000, /* R5752 */ + 0x0000, /* R5753 */ + 0x0000, /* R5754 */ + 0x0000, /* R5755 */ + 0x0000, /* R5756 */ + 0x0000, /* R5757 */ + 0x0000, /* R5758 */ + 0x0000, /* R5759 */ + 0x0000, /* R5760 */ + 0x0000, /* R5761 */ + 0x0000, /* R5762 */ + 0x0000, /* R5763 */ + 0x0000, /* R5764 */ + 0x0000, /* R5765 */ + 0x0000, /* R5766 */ + 0x0000, /* R5767 */ + 0x0000, /* R5768 */ + 0x0000, /* R5769 */ + 0x0000, /* R5770 */ + 0x0000, /* R5771 */ + 0x0000, /* R5772 */ + 0x0000, /* R5773 */ + 0x0000, /* R5774 */ + 0x0000, /* R5775 */ + 0x0000, /* R5776 */ + 0x0000, /* R5777 */ + 0x0000, /* R5778 */ + 0x0000, /* R5779 */ + 0x0000, /* R5780 */ + 0x0000, /* R5781 */ + 0x0000, /* R5782 */ + 0x0000, /* R5783 */ + 0x0000, /* R5784 */ + 0x0000, /* R5785 */ + 0x0000, /* R5786 */ + 0x0000, /* R5787 */ + 0x0000, /* R5788 */ + 0x0000, /* R5789 */ + 0x0000, /* R5790 */ + 0x0000, /* R5791 */ + 0x0000, /* R5792 */ + 0x0000, /* R5793 */ + 0x0000, /* R5794 */ + 0x0000, /* R5795 */ + 0x0000, /* R5796 */ + 0x0000, /* R5797 */ + 0x0000, /* R5798 */ + 0x0000, /* R5799 */ + 0x0000, /* R5800 */ + 0x0000, /* R5801 */ + 0x0000, /* R5802 */ + 0x0000, /* R5803 */ + 0x0000, /* R5804 */ + 0x0000, /* R5805 */ + 0x0000, /* R5806 */ + 0x0000, /* R5807 */ + 0x0000, /* R5808 */ + 0x0000, /* R5809 */ + 0x0000, /* R5810 */ + 0x0000, /* R5811 */ + 0x0000, /* R5812 */ + 0x0000, /* R5813 */ + 0x0000, /* R5814 */ + 0x0000, /* R5815 */ + 0x0000, /* R5816 */ + 0x0000, /* R5817 */ + 0x0000, /* R5818 */ + 0x0000, /* R5819 */ + 0x0000, /* R5820 */ + 0x0000, /* R5821 */ + 0x0000, /* R5822 */ + 0x0000, /* R5823 */ + 0x0000, /* R5824 */ + 0x0000, /* R5825 */ + 0x0000, /* R5826 */ + 0x0000, /* R5827 */ + 0x0000, /* R5828 */ + 0x0000, /* R5829 */ + 0x0000, /* R5830 */ + 0x0000, /* R5831 */ + 0x0000, /* R5832 */ + 0x0000, /* R5833 */ + 0x0000, /* R5834 */ + 0x0000, /* R5835 */ + 0x0000, /* R5836 */ + 0x0000, /* R5837 */ + 0x0000, /* R5838 */ + 0x0000, /* R5839 */ + 0x0000, /* R5840 */ + 0x0000, /* R5841 */ + 0x0000, /* R5842 */ + 0x0000, /* R5843 */ + 0x0000, /* R5844 */ + 0x0000, /* R5845 */ + 0x0000, /* R5846 */ + 0x0000, /* R5847 */ + 0x0000, /* R5848 */ + 0x0000, /* R5849 */ + 0x0000, /* R5850 */ + 0x0000, /* R5851 */ + 0x0000, /* R5852 */ + 0x0000, /* R5853 */ + 0x0000, /* R5854 */ + 0x0000, /* R5855 */ + 0x0000, /* R5856 */ + 0x0000, /* R5857 */ + 0x0000, /* R5858 */ + 0x0000, /* R5859 */ + 0x0000, /* R5860 */ + 0x0000, /* R5861 */ + 0x0000, /* R5862 */ + 0x0000, /* R5863 */ + 0x0000, /* R5864 */ + 0x0000, /* R5865 */ + 0x0000, /* R5866 */ + 0x0000, /* R5867 */ + 0x0000, /* R5868 */ + 0x0000, /* R5869 */ + 0x0000, /* R5870 */ + 0x0000, /* R5871 */ + 0x0000, /* R5872 */ + 0x0000, /* R5873 */ + 0x0000, /* R5874 */ + 0x0000, /* R5875 */ + 0x0000, /* R5876 */ + 0x0000, /* R5877 */ + 0x0000, /* R5878 */ + 0x0000, /* R5879 */ + 0x0000, /* R5880 */ + 0x0000, /* R5881 */ + 0x0000, /* R5882 */ + 0x0000, /* R5883 */ + 0x0000, /* R5884 */ + 0x0000, /* R5885 */ + 0x0000, /* R5886 */ + 0x0000, /* R5887 */ + 0x0000, /* R5888 */ + 0x0000, /* R5889 */ + 0x0000, /* R5890 */ + 0x0000, /* R5891 */ + 0x0000, /* R5892 */ + 0x0000, /* R5893 */ + 0x0000, /* R5894 */ + 0x0000, /* R5895 */ + 0x0000, /* R5896 */ + 0x0000, /* R5897 */ + 0x0000, /* R5898 */ + 0x0000, /* R5899 */ + 0x0000, /* R5900 */ + 0x0000, /* R5901 */ + 0x0000, /* R5902 */ + 0x0000, /* R5903 */ + 0x0000, /* R5904 */ + 0x0000, /* R5905 */ + 0x0000, /* R5906 */ + 0x0000, /* R5907 */ + 0x0000, /* R5908 */ + 0x0000, /* R5909 */ + 0x0000, /* R5910 */ + 0x0000, /* R5911 */ + 0x0000, /* R5912 */ + 0x0000, /* R5913 */ + 0x0000, /* R5914 */ + 0x0000, /* R5915 */ + 0x0000, /* R5916 */ + 0x0000, /* R5917 */ + 0x0000, /* R5918 */ + 0x0000, /* R5919 */ + 0x0000, /* R5920 */ + 0x0000, /* R5921 */ + 0x0000, /* R5922 */ + 0x0000, /* R5923 */ + 0x0000, /* R5924 */ + 0x0000, /* R5925 */ + 0x0000, /* R5926 */ + 0x0000, /* R5927 */ + 0x0000, /* R5928 */ + 0x0000, /* R5929 */ + 0x0000, /* R5930 */ + 0x0000, /* R5931 */ + 0x0000, /* R5932 */ + 0x0000, /* R5933 */ + 0x0000, /* R5934 */ + 0x0000, /* R5935 */ + 0x0000, /* R5936 */ + 0x0000, /* R5937 */ + 0x0000, /* R5938 */ + 0x0000, /* R5939 */ + 0x0000, /* R5940 */ + 0x0000, /* R5941 */ + 0x0000, /* R5942 */ + 0x0000, /* R5943 */ + 0x0000, /* R5944 */ + 0x0000, /* R5945 */ + 0x0000, /* R5946 */ + 0x0000, /* R5947 */ + 0x0000, /* R5948 */ + 0x0000, /* R5949 */ + 0x0000, /* R5950 */ + 0x0000, /* R5951 */ + 0x0000, /* R5952 */ + 0x0000, /* R5953 */ + 0x0000, /* R5954 */ + 0x0000, /* R5955 */ + 0x0000, /* R5956 */ + 0x0000, /* R5957 */ + 0x0000, /* R5958 */ + 0x0000, /* R5959 */ + 0x0000, /* R5960 */ + 0x0000, /* R5961 */ + 0x0000, /* R5962 */ + 0x0000, /* R5963 */ + 0x0000, /* R5964 */ + 0x0000, /* R5965 */ + 0x0000, /* R5966 */ + 0x0000, /* R5967 */ + 0x0000, /* R5968 */ + 0x0000, /* R5969 */ + 0x0000, /* R5970 */ + 0x0000, /* R5971 */ + 0x0000, /* R5972 */ + 0x0000, /* R5973 */ + 0x0000, /* R5974 */ + 0x0000, /* R5975 */ + 0x0000, /* R5976 */ + 0x0000, /* R5977 */ + 0x0000, /* R5978 */ + 0x0000, /* R5979 */ + 0x0000, /* R5980 */ + 0x0000, /* R5981 */ + 0x0000, /* R5982 */ + 0x0000, /* R5983 */ + 0x0000, /* R5984 */ + 0x0000, /* R5985 */ + 0x0000, /* R5986 */ + 0x0000, /* R5987 */ + 0x0000, /* R5988 */ + 0x0000, /* R5989 */ + 0x0000, /* R5990 */ + 0x0000, /* R5991 */ + 0x0000, /* R5992 */ + 0x0000, /* R5993 */ + 0x0000, /* R5994 */ + 0x0000, /* R5995 */ + 0x0000, /* R5996 */ + 0x0000, /* R5997 */ + 0x0000, /* R5998 */ + 0x0000, /* R5999 */ + 0x0000, /* R6000 */ + 0x0000, /* R6001 */ + 0x0000, /* R6002 */ + 0x0000, /* R6003 */ + 0x0000, /* R6004 */ + 0x0000, /* R6005 */ + 0x0000, /* R6006 */ + 0x0000, /* R6007 */ + 0x0000, /* R6008 */ + 0x0000, /* R6009 */ + 0x0000, /* R6010 */ + 0x0000, /* R6011 */ + 0x0000, /* R6012 */ + 0x0000, /* R6013 */ + 0x0000, /* R6014 */ + 0x0000, /* R6015 */ + 0x0000, /* R6016 */ + 0x0000, /* R6017 */ + 0x0000, /* R6018 */ + 0x0000, /* R6019 */ + 0x0000, /* R6020 */ + 0x0000, /* R6021 */ + 0x0000, /* R6022 */ + 0x0000, /* R6023 */ + 0x0000, /* R6024 */ + 0x0000, /* R6025 */ + 0x0000, /* R6026 */ + 0x0000, /* R6027 */ + 0x0000, /* R6028 */ + 0x0000, /* R6029 */ + 0x0000, /* R6030 */ + 0x0000, /* R6031 */ + 0x0000, /* R6032 */ + 0x0000, /* R6033 */ + 0x0000, /* R6034 */ + 0x0000, /* R6035 */ + 0x0000, /* R6036 */ + 0x0000, /* R6037 */ + 0x0000, /* R6038 */ + 0x0000, /* R6039 */ + 0x0000, /* R6040 */ + 0x0000, /* R6041 */ + 0x0000, /* R6042 */ + 0x0000, /* R6043 */ + 0x0000, /* R6044 */ + 0x0000, /* R6045 */ + 0x0000, /* R6046 */ + 0x0000, /* R6047 */ + 0x0000, /* R6048 */ + 0x0000, /* R6049 */ + 0x0000, /* R6050 */ + 0x0000, /* R6051 */ + 0x0000, /* R6052 */ + 0x0000, /* R6053 */ + 0x0000, /* R6054 */ + 0x0000, /* R6055 */ + 0x0000, /* R6056 */ + 0x0000, /* R6057 */ + 0x0000, /* R6058 */ + 0x0000, /* R6059 */ + 0x0000, /* R6060 */ + 0x0000, /* R6061 */ + 0x0000, /* R6062 */ + 0x0000, /* R6063 */ + 0x0000, /* R6064 */ + 0x0000, /* R6065 */ + 0x0000, /* R6066 */ + 0x0000, /* R6067 */ + 0x0000, /* R6068 */ + 0x0000, /* R6069 */ + 0x0000, /* R6070 */ + 0x0000, /* R6071 */ + 0x0000, /* R6072 */ + 0x0000, /* R6073 */ + 0x0000, /* R6074 */ + 0x0000, /* R6075 */ + 0x0000, /* R6076 */ + 0x0000, /* R6077 */ + 0x0000, /* R6078 */ + 0x0000, /* R6079 */ + 0x0000, /* R6080 */ + 0x0000, /* R6081 */ + 0x0000, /* R6082 */ + 0x0000, /* R6083 */ + 0x0000, /* R6084 */ + 0x0000, /* R6085 */ + 0x0000, /* R6086 */ + 0x0000, /* R6087 */ + 0x0000, /* R6088 */ + 0x0000, /* R6089 */ + 0x0000, /* R6090 */ + 0x0000, /* R6091 */ + 0x0000, /* R6092 */ + 0x0000, /* R6093 */ + 0x0000, /* R6094 */ + 0x0000, /* R6095 */ + 0x0000, /* R6096 */ + 0x0000, /* R6097 */ + 0x0000, /* R6098 */ + 0x0000, /* R6099 */ + 0x0000, /* R6100 */ + 0x0000, /* R6101 */ + 0x0000, /* R6102 */ + 0x0000, /* R6103 */ + 0x0000, /* R6104 */ + 0x0000, /* R6105 */ + 0x0000, /* R6106 */ + 0x0000, /* R6107 */ + 0x0000, /* R6108 */ + 0x0000, /* R6109 */ + 0x0000, /* R6110 */ + 0x0000, /* R6111 */ + 0x0000, /* R6112 */ + 0x0000, /* R6113 */ + 0x0000, /* R6114 */ + 0x0000, /* R6115 */ + 0x0000, /* R6116 */ + 0x0000, /* R6117 */ + 0x0000, /* R6118 */ + 0x0000, /* R6119 */ + 0x0000, /* R6120 */ + 0x0000, /* R6121 */ + 0x0000, /* R6122 */ + 0x0000, /* R6123 */ + 0x0000, /* R6124 */ + 0x0000, /* R6125 */ + 0x0000, /* R6126 */ + 0x0000, /* R6127 */ + 0x0000, /* R6128 */ + 0x0000, /* R6129 */ + 0x0000, /* R6130 */ + 0x0000, /* R6131 */ + 0x0000, /* R6132 */ + 0x0000, /* R6133 */ + 0x0000, /* R6134 */ + 0x0000, /* R6135 */ + 0x0000, /* R6136 */ + 0x0000, /* R6137 */ + 0x0000, /* R6138 */ + 0x0000, /* R6139 */ + 0x0000, /* R6140 */ + 0x0000, /* R6141 */ + 0x0000, /* R6142 */ + 0x0000, /* R6143 */ + 0x0000, /* R6144 */ + 0x0000, /* R6145 */ + 0x0000, /* R6146 */ + 0x0000, /* R6147 */ + 0x0000, /* R6148 */ + 0x0000, /* R6149 */ + 0x0000, /* R6150 */ + 0x0000, /* R6151 */ + 0x0000, /* R6152 */ + 0x0000, /* R6153 */ + 0x0000, /* R6154 */ + 0x0000, /* R6155 */ + 0x0000, /* R6156 */ + 0x0000, /* R6157 */ + 0x0000, /* R6158 */ + 0x0000, /* R6159 */ + 0x0000, /* R6160 */ + 0x0000, /* R6161 */ + 0x0000, /* R6162 */ + 0x0000, /* R6163 */ + 0x0000, /* R6164 */ + 0x0000, /* R6165 */ + 0x0000, /* R6166 */ + 0x0000, /* R6167 */ + 0x0000, /* R6168 */ + 0x0000, /* R6169 */ + 0x0000, /* R6170 */ + 0x0000, /* R6171 */ + 0x0000, /* R6172 */ + 0x0000, /* R6173 */ + 0x0000, /* R6174 */ + 0x0000, /* R6175 */ + 0x0000, /* R6176 */ + 0x0000, /* R6177 */ + 0x0000, /* R6178 */ + 0x0000, /* R6179 */ + 0x0000, /* R6180 */ + 0x0000, /* R6181 */ + 0x0000, /* R6182 */ + 0x0000, /* R6183 */ + 0x0000, /* R6184 */ + 0x0000, /* R6185 */ + 0x0000, /* R6186 */ + 0x0000, /* R6187 */ + 0x0000, /* R6188 */ + 0x0000, /* R6189 */ + 0x0000, /* R6190 */ + 0x0000, /* R6191 */ + 0x0000, /* R6192 */ + 0x0000, /* R6193 */ + 0x0000, /* R6194 */ + 0x0000, /* R6195 */ + 0x0000, /* R6196 */ + 0x0000, /* R6197 */ + 0x0000, /* R6198 */ + 0x0000, /* R6199 */ + 0x0000, /* R6200 */ + 0x0000, /* R6201 */ + 0x0000, /* R6202 */ + 0x0000, /* R6203 */ + 0x0000, /* R6204 */ + 0x0000, /* R6205 */ + 0x0000, /* R6206 */ + 0x0000, /* R6207 */ + 0x0000, /* R6208 */ + 0x0000, /* R6209 */ + 0x0000, /* R6210 */ + 0x0000, /* R6211 */ + 0x0000, /* R6212 */ + 0x0000, /* R6213 */ + 0x0000, /* R6214 */ + 0x0000, /* R6215 */ + 0x0000, /* R6216 */ + 0x0000, /* R6217 */ + 0x0000, /* R6218 */ + 0x0000, /* R6219 */ + 0x0000, /* R6220 */ + 0x0000, /* R6221 */ + 0x0000, /* R6222 */ + 0x0000, /* R6223 */ + 0x0000, /* R6224 */ + 0x0000, /* R6225 */ + 0x0000, /* R6226 */ + 0x0000, /* R6227 */ + 0x0000, /* R6228 */ + 0x0000, /* R6229 */ + 0x0000, /* R6230 */ + 0x0000, /* R6231 */ + 0x0000, /* R6232 */ + 0x0000, /* R6233 */ + 0x0000, /* R6234 */ + 0x0000, /* R6235 */ + 0x0000, /* R6236 */ + 0x0000, /* R6237 */ + 0x0000, /* R6238 */ + 0x0000, /* R6239 */ + 0x0000, /* R6240 */ + 0x0000, /* R6241 */ + 0x0000, /* R6242 */ + 0x0000, /* R6243 */ + 0x0000, /* R6244 */ + 0x0000, /* R6245 */ + 0x0000, /* R6246 */ + 0x0000, /* R6247 */ + 0x0000, /* R6248 */ + 0x0000, /* R6249 */ + 0x0000, /* R6250 */ + 0x0000, /* R6251 */ + 0x0000, /* R6252 */ + 0x0000, /* R6253 */ + 0x0000, /* R6254 */ + 0x0000, /* R6255 */ + 0x0000, /* R6256 */ + 0x0000, /* R6257 */ + 0x0000, /* R6258 */ + 0x0000, /* R6259 */ + 0x0000, /* R6260 */ + 0x0000, /* R6261 */ + 0x0000, /* R6262 */ + 0x0000, /* R6263 */ + 0x0000, /* R6264 */ + 0x0000, /* R6265 */ + 0x0000, /* R6266 */ + 0x0000, /* R6267 */ + 0x0000, /* R6268 */ + 0x0000, /* R6269 */ + 0x0000, /* R6270 */ + 0x0000, /* R6271 */ + 0x0000, /* R6272 */ + 0x0000, /* R6273 */ + 0x0000, /* R6274 */ + 0x0000, /* R6275 */ + 0x0000, /* R6276 */ + 0x0000, /* R6277 */ + 0x0000, /* R6278 */ + 0x0000, /* R6279 */ + 0x0000, /* R6280 */ + 0x0000, /* R6281 */ + 0x0000, /* R6282 */ + 0x0000, /* R6283 */ + 0x0000, /* R6284 */ + 0x0000, /* R6285 */ + 0x0000, /* R6286 */ + 0x0000, /* R6287 */ + 0x0000, /* R6288 */ + 0x0000, /* R6289 */ + 0x0000, /* R6290 */ + 0x0000, /* R6291 */ + 0x0000, /* R6292 */ + 0x0000, /* R6293 */ + 0x0000, /* R6294 */ + 0x0000, /* R6295 */ + 0x0000, /* R6296 */ + 0x0000, /* R6297 */ + 0x0000, /* R6298 */ + 0x0000, /* R6299 */ + 0x0000, /* R6300 */ + 0x0000, /* R6301 */ + 0x0000, /* R6302 */ + 0x0000, /* R6303 */ + 0x0000, /* R6304 */ + 0x0000, /* R6305 */ + 0x0000, /* R6306 */ + 0x0000, /* R6307 */ + 0x0000, /* R6308 */ + 0x0000, /* R6309 */ + 0x0000, /* R6310 */ + 0x0000, /* R6311 */ + 0x0000, /* R6312 */ + 0x0000, /* R6313 */ + 0x0000, /* R6314 */ + 0x0000, /* R6315 */ + 0x0000, /* R6316 */ + 0x0000, /* R6317 */ + 0x0000, /* R6318 */ + 0x0000, /* R6319 */ + 0x0000, /* R6320 */ + 0x0000, /* R6321 */ + 0x0000, /* R6322 */ + 0x0000, /* R6323 */ + 0x0000, /* R6324 */ + 0x0000, /* R6325 */ + 0x0000, /* R6326 */ + 0x0000, /* R6327 */ + 0x0000, /* R6328 */ + 0x0000, /* R6329 */ + 0x0000, /* R6330 */ + 0x0000, /* R6331 */ + 0x0000, /* R6332 */ + 0x0000, /* R6333 */ + 0x0000, /* R6334 */ + 0x0000, /* R6335 */ + 0x0000, /* R6336 */ + 0x0000, /* R6337 */ + 0x0000, /* R6338 */ + 0x0000, /* R6339 */ + 0x0000, /* R6340 */ + 0x0000, /* R6341 */ + 0x0000, /* R6342 */ + 0x0000, /* R6343 */ + 0x0000, /* R6344 */ + 0x0000, /* R6345 */ + 0x0000, /* R6346 */ + 0x0000, /* R6347 */ + 0x0000, /* R6348 */ + 0x0000, /* R6349 */ + 0x0000, /* R6350 */ + 0x0000, /* R6351 */ + 0x0000, /* R6352 */ + 0x0000, /* R6353 */ + 0x0000, /* R6354 */ + 0x0000, /* R6355 */ + 0x0000, /* R6356 */ + 0x0000, /* R6357 */ + 0x0000, /* R6358 */ + 0x0000, /* R6359 */ + 0x0000, /* R6360 */ + 0x0000, /* R6361 */ + 0x0000, /* R6362 */ + 0x0000, /* R6363 */ + 0x0000, /* R6364 */ + 0x0000, /* R6365 */ + 0x0000, /* R6366 */ + 0x0000, /* R6367 */ + 0x0000, /* R6368 */ + 0x0000, /* R6369 */ + 0x0000, /* R6370 */ + 0x0000, /* R6371 */ + 0x0000, /* R6372 */ + 0x0000, /* R6373 */ + 0x0000, /* R6374 */ + 0x0000, /* R6375 */ + 0x0000, /* R6376 */ + 0x0000, /* R6377 */ + 0x0000, /* R6378 */ + 0x0000, /* R6379 */ + 0x0000, /* R6380 */ + 0x0000, /* R6381 */ + 0x0000, /* R6382 */ + 0x0000, /* R6383 */ + 0x0000, /* R6384 */ + 0x0000, /* R6385 */ + 0x0000, /* R6386 */ + 0x0000, /* R6387 */ + 0x0000, /* R6388 */ + 0x0000, /* R6389 */ + 0x0000, /* R6390 */ + 0x0000, /* R6391 */ + 0x0000, /* R6392 */ + 0x0000, /* R6393 */ + 0x0000, /* R6394 */ + 0x0000, /* R6395 */ + 0x0000, /* R6396 */ + 0x0000, /* R6397 */ + 0x0000, /* R6398 */ + 0x0000, /* R6399 */ + 0x0000, /* R6400 */ + 0x0000, /* R6401 */ + 0x0000, /* R6402 */ + 0x0000, /* R6403 */ + 0x0000, /* R6404 */ + 0x0000, /* R6405 */ + 0x0000, /* R6406 */ + 0x0000, /* R6407 */ + 0x0000, /* R6408 */ + 0x0000, /* R6409 */ + 0x0000, /* R6410 */ + 0x0000, /* R6411 */ + 0x0000, /* R6412 */ + 0x0000, /* R6413 */ + 0x0000, /* R6414 */ + 0x0000, /* R6415 */ + 0x0000, /* R6416 */ + 0x0000, /* R6417 */ + 0x0000, /* R6418 */ + 0x0000, /* R6419 */ + 0x0000, /* R6420 */ + 0x0000, /* R6421 */ + 0x0000, /* R6422 */ + 0x0000, /* R6423 */ + 0x0000, /* R6424 */ + 0x0000, /* R6425 */ + 0x0000, /* R6426 */ + 0x0000, /* R6427 */ + 0x0000, /* R6428 */ + 0x0000, /* R6429 */ + 0x0000, /* R6430 */ + 0x0000, /* R6431 */ + 0x0000, /* R6432 */ + 0x0000, /* R6433 */ + 0x0000, /* R6434 */ + 0x0000, /* R6435 */ + 0x0000, /* R6436 */ + 0x0000, /* R6437 */ + 0x0000, /* R6438 */ + 0x0000, /* R6439 */ + 0x0000, /* R6440 */ + 0x0000, /* R6441 */ + 0x0000, /* R6442 */ + 0x0000, /* R6443 */ + 0x0000, /* R6444 */ + 0x0000, /* R6445 */ + 0x0000, /* R6446 */ + 0x0000, /* R6447 */ + 0x0000, /* R6448 */ + 0x0000, /* R6449 */ + 0x0000, /* R6450 */ + 0x0000, /* R6451 */ + 0x0000, /* R6452 */ + 0x0000, /* R6453 */ + 0x0000, /* R6454 */ + 0x0000, /* R6455 */ + 0x0000, /* R6456 */ + 0x0000, /* R6457 */ + 0x0000, /* R6458 */ + 0x0000, /* R6459 */ + 0x0000, /* R6460 */ + 0x0000, /* R6461 */ + 0x0000, /* R6462 */ + 0x0000, /* R6463 */ + 0x0000, /* R6464 */ + 0x0000, /* R6465 */ + 0x0000, /* R6466 */ + 0x0000, /* R6467 */ + 0x0000, /* R6468 */ + 0x0000, /* R6469 */ + 0x0000, /* R6470 */ + 0x0000, /* R6471 */ + 0x0000, /* R6472 */ + 0x0000, /* R6473 */ + 0x0000, /* R6474 */ + 0x0000, /* R6475 */ + 0x0000, /* R6476 */ + 0x0000, /* R6477 */ + 0x0000, /* R6478 */ + 0x0000, /* R6479 */ + 0x0000, /* R6480 */ + 0x0000, /* R6481 */ + 0x0000, /* R6482 */ + 0x0000, /* R6483 */ + 0x0000, /* R6484 */ + 0x0000, /* R6485 */ + 0x0000, /* R6486 */ + 0x0000, /* R6487 */ + 0x0000, /* R6488 */ + 0x0000, /* R6489 */ + 0x0000, /* R6490 */ + 0x0000, /* R6491 */ + 0x0000, /* R6492 */ + 0x0000, /* R6493 */ + 0x0000, /* R6494 */ + 0x0000, /* R6495 */ + 0x0000, /* R6496 */ + 0x0000, /* R6497 */ + 0x0000, /* R6498 */ + 0x0000, /* R6499 */ + 0x0000, /* R6500 */ + 0x0000, /* R6501 */ + 0x0000, /* R6502 */ + 0x0000, /* R6503 */ + 0x0000, /* R6504 */ + 0x0000, /* R6505 */ + 0x0000, /* R6506 */ + 0x0000, /* R6507 */ + 0x0000, /* R6508 */ + 0x0000, /* R6509 */ + 0x0000, /* R6510 */ + 0x0000, /* R6511 */ + 0x0000, /* R6512 */ + 0x0000, /* R6513 */ + 0x0000, /* R6514 */ + 0x0000, /* R6515 */ + 0x0000, /* R6516 */ + 0x0000, /* R6517 */ + 0x0000, /* R6518 */ + 0x0000, /* R6519 */ + 0x0000, /* R6520 */ + 0x0000, /* R6521 */ + 0x0000, /* R6522 */ + 0x0000, /* R6523 */ + 0x0000, /* R6524 */ + 0x0000, /* R6525 */ + 0x0000, /* R6526 */ + 0x0000, /* R6527 */ + 0x0000, /* R6528 */ + 0x0000, /* R6529 */ + 0x0000, /* R6530 */ + 0x0000, /* R6531 */ + 0x0000, /* R6532 */ + 0x0000, /* R6533 */ + 0x0000, /* R6534 */ + 0x0000, /* R6535 */ + 0x0000, /* R6536 */ + 0x0000, /* R6537 */ + 0x0000, /* R6538 */ + 0x0000, /* R6539 */ + 0x0000, /* R6540 */ + 0x0000, /* R6541 */ + 0x0000, /* R6542 */ + 0x0000, /* R6543 */ + 0x0000, /* R6544 */ + 0x0000, /* R6545 */ + 0x0000, /* R6546 */ + 0x0000, /* R6547 */ + 0x0000, /* R6548 */ + 0x0000, /* R6549 */ + 0x0000, /* R6550 */ + 0x0000, /* R6551 */ + 0x0000, /* R6552 */ + 0x0000, /* R6553 */ + 0x0000, /* R6554 */ + 0x0000, /* R6555 */ + 0x0000, /* R6556 */ + 0x0000, /* R6557 */ + 0x0000, /* R6558 */ + 0x0000, /* R6559 */ + 0x0000, /* R6560 */ + 0x0000, /* R6561 */ + 0x0000, /* R6562 */ + 0x0000, /* R6563 */ + 0x0000, /* R6564 */ + 0x0000, /* R6565 */ + 0x0000, /* R6566 */ + 0x0000, /* R6567 */ + 0x0000, /* R6568 */ + 0x0000, /* R6569 */ + 0x0000, /* R6570 */ + 0x0000, /* R6571 */ + 0x0000, /* R6572 */ + 0x0000, /* R6573 */ + 0x0000, /* R6574 */ + 0x0000, /* R6575 */ + 0x0000, /* R6576 */ + 0x0000, /* R6577 */ + 0x0000, /* R6578 */ + 0x0000, /* R6579 */ + 0x0000, /* R6580 */ + 0x0000, /* R6581 */ + 0x0000, /* R6582 */ + 0x0000, /* R6583 */ + 0x0000, /* R6584 */ + 0x0000, /* R6585 */ + 0x0000, /* R6586 */ + 0x0000, /* R6587 */ + 0x0000, /* R6588 */ + 0x0000, /* R6589 */ + 0x0000, /* R6590 */ + 0x0000, /* R6591 */ + 0x0000, /* R6592 */ + 0x0000, /* R6593 */ + 0x0000, /* R6594 */ + 0x0000, /* R6595 */ + 0x0000, /* R6596 */ + 0x0000, /* R6597 */ + 0x0000, /* R6598 */ + 0x0000, /* R6599 */ + 0x0000, /* R6600 */ + 0x0000, /* R6601 */ + 0x0000, /* R6602 */ + 0x0000, /* R6603 */ + 0x0000, /* R6604 */ + 0x0000, /* R6605 */ + 0x0000, /* R6606 */ + 0x0000, /* R6607 */ + 0x0000, /* R6608 */ + 0x0000, /* R6609 */ + 0x0000, /* R6610 */ + 0x0000, /* R6611 */ + 0x0000, /* R6612 */ + 0x0000, /* R6613 */ + 0x0000, /* R6614 */ + 0x0000, /* R6615 */ + 0x0000, /* R6616 */ + 0x0000, /* R6617 */ + 0x0000, /* R6618 */ + 0x0000, /* R6619 */ + 0x0000, /* R6620 */ + 0x0000, /* R6621 */ + 0x0000, /* R6622 */ + 0x0000, /* R6623 */ + 0x0000, /* R6624 */ + 0x0000, /* R6625 */ + 0x0000, /* R6626 */ + 0x0000, /* R6627 */ + 0x0000, /* R6628 */ + 0x0000, /* R6629 */ + 0x0000, /* R6630 */ + 0x0000, /* R6631 */ + 0x0000, /* R6632 */ + 0x0000, /* R6633 */ + 0x0000, /* R6634 */ + 0x0000, /* R6635 */ + 0x0000, /* R6636 */ + 0x0000, /* R6637 */ + 0x0000, /* R6638 */ + 0x0000, /* R6639 */ + 0x0000, /* R6640 */ + 0x0000, /* R6641 */ + 0x0000, /* R6642 */ + 0x0000, /* R6643 */ + 0x0000, /* R6644 */ + 0x0000, /* R6645 */ + 0x0000, /* R6646 */ + 0x0000, /* R6647 */ + 0x0000, /* R6648 */ + 0x0000, /* R6649 */ + 0x0000, /* R6650 */ + 0x0000, /* R6651 */ + 0x0000, /* R6652 */ + 0x0000, /* R6653 */ + 0x0000, /* R6654 */ + 0x0000, /* R6655 */ + 0x0000, /* R6656 */ + 0x0000, /* R6657 */ + 0x0000, /* R6658 */ + 0x0000, /* R6659 */ + 0x0000, /* R6660 */ + 0x0000, /* R6661 */ + 0x0000, /* R6662 */ + 0x0000, /* R6663 */ + 0x0000, /* R6664 */ + 0x0000, /* R6665 */ + 0x0000, /* R6666 */ + 0x0000, /* R6667 */ + 0x0000, /* R6668 */ + 0x0000, /* R6669 */ + 0x0000, /* R6670 */ + 0x0000, /* R6671 */ + 0x0000, /* R6672 */ + 0x0000, /* R6673 */ + 0x0000, /* R6674 */ + 0x0000, /* R6675 */ + 0x0000, /* R6676 */ + 0x0000, /* R6677 */ + 0x0000, /* R6678 */ + 0x0000, /* R6679 */ + 0x0000, /* R6680 */ + 0x0000, /* R6681 */ + 0x0000, /* R6682 */ + 0x0000, /* R6683 */ + 0x0000, /* R6684 */ + 0x0000, /* R6685 */ + 0x0000, /* R6686 */ + 0x0000, /* R6687 */ + 0x0000, /* R6688 */ + 0x0000, /* R6689 */ + 0x0000, /* R6690 */ + 0x0000, /* R6691 */ + 0x0000, /* R6692 */ + 0x0000, /* R6693 */ + 0x0000, /* R6694 */ + 0x0000, /* R6695 */ + 0x0000, /* R6696 */ + 0x0000, /* R6697 */ + 0x0000, /* R6698 */ + 0x0000, /* R6699 */ + 0x0000, /* R6700 */ + 0x0000, /* R6701 */ + 0x0000, /* R6702 */ + 0x0000, /* R6703 */ + 0x0000, /* R6704 */ + 0x0000, /* R6705 */ + 0x0000, /* R6706 */ + 0x0000, /* R6707 */ + 0x0000, /* R6708 */ + 0x0000, /* R6709 */ + 0x0000, /* R6710 */ + 0x0000, /* R6711 */ + 0x0000, /* R6712 */ + 0x0000, /* R6713 */ + 0x0000, /* R6714 */ + 0x0000, /* R6715 */ + 0x0000, /* R6716 */ + 0x0000, /* R6717 */ + 0x0000, /* R6718 */ + 0x0000, /* R6719 */ + 0x0000, /* R6720 */ + 0x0000, /* R6721 */ + 0x0000, /* R6722 */ + 0x0000, /* R6723 */ + 0x0000, /* R6724 */ + 0x0000, /* R6725 */ + 0x0000, /* R6726 */ + 0x0000, /* R6727 */ + 0x0000, /* R6728 */ + 0x0000, /* R6729 */ + 0x0000, /* R6730 */ + 0x0000, /* R6731 */ + 0x0000, /* R6732 */ + 0x0000, /* R6733 */ + 0x0000, /* R6734 */ + 0x0000, /* R6735 */ + 0x0000, /* R6736 */ + 0x0000, /* R6737 */ + 0x0000, /* R6738 */ + 0x0000, /* R6739 */ + 0x0000, /* R6740 */ + 0x0000, /* R6741 */ + 0x0000, /* R6742 */ + 0x0000, /* R6743 */ + 0x0000, /* R6744 */ + 0x0000, /* R6745 */ + 0x0000, /* R6746 */ + 0x0000, /* R6747 */ + 0x0000, /* R6748 */ + 0x0000, /* R6749 */ + 0x0000, /* R6750 */ + 0x0000, /* R6751 */ + 0x0000, /* R6752 */ + 0x0000, /* R6753 */ + 0x0000, /* R6754 */ + 0x0000, /* R6755 */ + 0x0000, /* R6756 */ + 0x0000, /* R6757 */ + 0x0000, /* R6758 */ + 0x0000, /* R6759 */ + 0x0000, /* R6760 */ + 0x0000, /* R6761 */ + 0x0000, /* R6762 */ + 0x0000, /* R6763 */ + 0x0000, /* R6764 */ + 0x0000, /* R6765 */ + 0x0000, /* R6766 */ + 0x0000, /* R6767 */ + 0x0000, /* R6768 */ + 0x0000, /* R6769 */ + 0x0000, /* R6770 */ + 0x0000, /* R6771 */ + 0x0000, /* R6772 */ + 0x0000, /* R6773 */ + 0x0000, /* R6774 */ + 0x0000, /* R6775 */ + 0x0000, /* R6776 */ + 0x0000, /* R6777 */ + 0x0000, /* R6778 */ + 0x0000, /* R6779 */ + 0x0000, /* R6780 */ + 0x0000, /* R6781 */ + 0x0000, /* R6782 */ + 0x0000, /* R6783 */ + 0x0000, /* R6784 */ + 0x0000, /* R6785 */ + 0x0000, /* R6786 */ + 0x0000, /* R6787 */ + 0x0000, /* R6788 */ + 0x0000, /* R6789 */ + 0x0000, /* R6790 */ + 0x0000, /* R6791 */ + 0x0000, /* R6792 */ + 0x0000, /* R6793 */ + 0x0000, /* R6794 */ + 0x0000, /* R6795 */ + 0x0000, /* R6796 */ + 0x0000, /* R6797 */ + 0x0000, /* R6798 */ + 0x0000, /* R6799 */ + 0x0000, /* R6800 */ + 0x0000, /* R6801 */ + 0x0000, /* R6802 */ + 0x0000, /* R6803 */ + 0x0000, /* R6804 */ + 0x0000, /* R6805 */ + 0x0000, /* R6806 */ + 0x0000, /* R6807 */ + 0x0000, /* R6808 */ + 0x0000, /* R6809 */ + 0x0000, /* R6810 */ + 0x0000, /* R6811 */ + 0x0000, /* R6812 */ + 0x0000, /* R6813 */ + 0x0000, /* R6814 */ + 0x0000, /* R6815 */ + 0x0000, /* R6816 */ + 0x0000, /* R6817 */ + 0x0000, /* R6818 */ + 0x0000, /* R6819 */ + 0x0000, /* R6820 */ + 0x0000, /* R6821 */ + 0x0000, /* R6822 */ + 0x0000, /* R6823 */ + 0x0000, /* R6824 */ + 0x0000, /* R6825 */ + 0x0000, /* R6826 */ + 0x0000, /* R6827 */ + 0x0000, /* R6828 */ + 0x0000, /* R6829 */ + 0x0000, /* R6830 */ + 0x0000, /* R6831 */ + 0x0000, /* R6832 */ + 0x0000, /* R6833 */ + 0x0000, /* R6834 */ + 0x0000, /* R6835 */ + 0x0000, /* R6836 */ + 0x0000, /* R6837 */ + 0x0000, /* R6838 */ + 0x0000, /* R6839 */ + 0x0000, /* R6840 */ + 0x0000, /* R6841 */ + 0x0000, /* R6842 */ + 0x0000, /* R6843 */ + 0x0000, /* R6844 */ + 0x0000, /* R6845 */ + 0x0000, /* R6846 */ + 0x0000, /* R6847 */ + 0x0000, /* R6848 */ + 0x0000, /* R6849 */ + 0x0000, /* R6850 */ + 0x0000, /* R6851 */ + 0x0000, /* R6852 */ + 0x0000, /* R6853 */ + 0x0000, /* R6854 */ + 0x0000, /* R6855 */ + 0x0000, /* R6856 */ + 0x0000, /* R6857 */ + 0x0000, /* R6858 */ + 0x0000, /* R6859 */ + 0x0000, /* R6860 */ + 0x0000, /* R6861 */ + 0x0000, /* R6862 */ + 0x0000, /* R6863 */ + 0x0000, /* R6864 */ + 0x0000, /* R6865 */ + 0x0000, /* R6866 */ + 0x0000, /* R6867 */ + 0x0000, /* R6868 */ + 0x0000, /* R6869 */ + 0x0000, /* R6870 */ + 0x0000, /* R6871 */ + 0x0000, /* R6872 */ + 0x0000, /* R6873 */ + 0x0000, /* R6874 */ + 0x0000, /* R6875 */ + 0x0000, /* R6876 */ + 0x0000, /* R6877 */ + 0x0000, /* R6878 */ + 0x0000, /* R6879 */ + 0x0000, /* R6880 */ + 0x0000, /* R6881 */ + 0x0000, /* R6882 */ + 0x0000, /* R6883 */ + 0x0000, /* R6884 */ + 0x0000, /* R6885 */ + 0x0000, /* R6886 */ + 0x0000, /* R6887 */ + 0x0000, /* R6888 */ + 0x0000, /* R6889 */ + 0x0000, /* R6890 */ + 0x0000, /* R6891 */ + 0x0000, /* R6892 */ + 0x0000, /* R6893 */ + 0x0000, /* R6894 */ + 0x0000, /* R6895 */ + 0x0000, /* R6896 */ + 0x0000, /* R6897 */ + 0x0000, /* R6898 */ + 0x0000, /* R6899 */ + 0x0000, /* R6900 */ + 0x0000, /* R6901 */ + 0x0000, /* R6902 */ + 0x0000, /* R6903 */ + 0x0000, /* R6904 */ + 0x0000, /* R6905 */ + 0x0000, /* R6906 */ + 0x0000, /* R6907 */ + 0x0000, /* R6908 */ + 0x0000, /* R6909 */ + 0x0000, /* R6910 */ + 0x0000, /* R6911 */ + 0x0000, /* R6912 */ + 0x0000, /* R6913 */ + 0x0000, /* R6914 */ + 0x0000, /* R6915 */ + 0x0000, /* R6916 */ + 0x0000, /* R6917 */ + 0x0000, /* R6918 */ + 0x0000, /* R6919 */ + 0x0000, /* R6920 */ + 0x0000, /* R6921 */ + 0x0000, /* R6922 */ + 0x0000, /* R6923 */ + 0x0000, /* R6924 */ + 0x0000, /* R6925 */ + 0x0000, /* R6926 */ + 0x0000, /* R6927 */ + 0x0000, /* R6928 */ + 0x0000, /* R6929 */ + 0x0000, /* R6930 */ + 0x0000, /* R6931 */ + 0x0000, /* R6932 */ + 0x0000, /* R6933 */ + 0x0000, /* R6934 */ + 0x0000, /* R6935 */ + 0x0000, /* R6936 */ + 0x0000, /* R6937 */ + 0x0000, /* R6938 */ + 0x0000, /* R6939 */ + 0x0000, /* R6940 */ + 0x0000, /* R6941 */ + 0x0000, /* R6942 */ + 0x0000, /* R6943 */ + 0x0000, /* R6944 */ + 0x0000, /* R6945 */ + 0x0000, /* R6946 */ + 0x0000, /* R6947 */ + 0x0000, /* R6948 */ + 0x0000, /* R6949 */ + 0x0000, /* R6950 */ + 0x0000, /* R6951 */ + 0x0000, /* R6952 */ + 0x0000, /* R6953 */ + 0x0000, /* R6954 */ + 0x0000, /* R6955 */ + 0x0000, /* R6956 */ + 0x0000, /* R6957 */ + 0x0000, /* R6958 */ + 0x0000, /* R6959 */ + 0x0000, /* R6960 */ + 0x0000, /* R6961 */ + 0x0000, /* R6962 */ + 0x0000, /* R6963 */ + 0x0000, /* R6964 */ + 0x0000, /* R6965 */ + 0x0000, /* R6966 */ + 0x0000, /* R6967 */ + 0x0000, /* R6968 */ + 0x0000, /* R6969 */ + 0x0000, /* R6970 */ + 0x0000, /* R6971 */ + 0x0000, /* R6972 */ + 0x0000, /* R6973 */ + 0x0000, /* R6974 */ + 0x0000, /* R6975 */ + 0x0000, /* R6976 */ + 0x0000, /* R6977 */ + 0x0000, /* R6978 */ + 0x0000, /* R6979 */ + 0x0000, /* R6980 */ + 0x0000, /* R6981 */ + 0x0000, /* R6982 */ + 0x0000, /* R6983 */ + 0x0000, /* R6984 */ + 0x0000, /* R6985 */ + 0x0000, /* R6986 */ + 0x0000, /* R6987 */ + 0x0000, /* R6988 */ + 0x0000, /* R6989 */ + 0x0000, /* R6990 */ + 0x0000, /* R6991 */ + 0x0000, /* R6992 */ + 0x0000, /* R6993 */ + 0x0000, /* R6994 */ + 0x0000, /* R6995 */ + 0x0000, /* R6996 */ + 0x0000, /* R6997 */ + 0x0000, /* R6998 */ + 0x0000, /* R6999 */ + 0x0000, /* R7000 */ + 0x0000, /* R7001 */ + 0x0000, /* R7002 */ + 0x0000, /* R7003 */ + 0x0000, /* R7004 */ + 0x0000, /* R7005 */ + 0x0000, /* R7006 */ + 0x0000, /* R7007 */ + 0x0000, /* R7008 */ + 0x0000, /* R7009 */ + 0x0000, /* R7010 */ + 0x0000, /* R7011 */ + 0x0000, /* R7012 */ + 0x0000, /* R7013 */ + 0x0000, /* R7014 */ + 0x0000, /* R7015 */ + 0x0000, /* R7016 */ + 0x0000, /* R7017 */ + 0x0000, /* R7018 */ + 0x0000, /* R7019 */ + 0x0000, /* R7020 */ + 0x0000, /* R7021 */ + 0x0000, /* R7022 */ + 0x0000, /* R7023 */ + 0x0000, /* R7024 */ + 0x0000, /* R7025 */ + 0x0000, /* R7026 */ + 0x0000, /* R7027 */ + 0x0000, /* R7028 */ + 0x0000, /* R7029 */ + 0x0000, /* R7030 */ + 0x0000, /* R7031 */ + 0x0000, /* R7032 */ + 0x0000, /* R7033 */ + 0x0000, /* R7034 */ + 0x0000, /* R7035 */ + 0x0000, /* R7036 */ + 0x0000, /* R7037 */ + 0x0000, /* R7038 */ + 0x0000, /* R7039 */ + 0x0000, /* R7040 */ + 0x0000, /* R7041 */ + 0x0000, /* R7042 */ + 0x0000, /* R7043 */ + 0x0000, /* R7044 */ + 0x0000, /* R7045 */ + 0x0000, /* R7046 */ + 0x0000, /* R7047 */ + 0x0000, /* R7048 */ + 0x0000, /* R7049 */ + 0x0000, /* R7050 */ + 0x0000, /* R7051 */ + 0x0000, /* R7052 */ + 0x0000, /* R7053 */ + 0x0000, /* R7054 */ + 0x0000, /* R7055 */ + 0x0000, /* R7056 */ + 0x0000, /* R7057 */ + 0x0000, /* R7058 */ + 0x0000, /* R7059 */ + 0x0000, /* R7060 */ + 0x0000, /* R7061 */ + 0x0000, /* R7062 */ + 0x0000, /* R7063 */ + 0x0000, /* R7064 */ + 0x0000, /* R7065 */ + 0x0000, /* R7066 */ + 0x0000, /* R7067 */ + 0x0000, /* R7068 */ + 0x0000, /* R7069 */ + 0x0000, /* R7070 */ + 0x0000, /* R7071 */ + 0x0000, /* R7072 */ + 0x0000, /* R7073 */ + 0x0000, /* R7074 */ + 0x0000, /* R7075 */ + 0x0000, /* R7076 */ + 0x0000, /* R7077 */ + 0x0000, /* R7078 */ + 0x0000, /* R7079 */ + 0x0000, /* R7080 */ + 0x0000, /* R7081 */ + 0x0000, /* R7082 */ + 0x0000, /* R7083 */ + 0x0000, /* R7084 */ + 0x0000, /* R7085 */ + 0x0000, /* R7086 */ + 0x0000, /* R7087 */ + 0x0000, /* R7088 */ + 0x0000, /* R7089 */ + 0x0000, /* R7090 */ + 0x0000, /* R7091 */ + 0x0000, /* R7092 */ + 0x0000, /* R7093 */ + 0x0000, /* R7094 */ + 0x0000, /* R7095 */ + 0x0000, /* R7096 */ + 0x0000, /* R7097 */ + 0x0000, /* R7098 */ + 0x0000, /* R7099 */ + 0x0000, /* R7100 */ + 0x0000, /* R7101 */ + 0x0000, /* R7102 */ + 0x0000, /* R7103 */ + 0x0000, /* R7104 */ + 0x0000, /* R7105 */ + 0x0000, /* R7106 */ + 0x0000, /* R7107 */ + 0x0000, /* R7108 */ + 0x0000, /* R7109 */ + 0x0000, /* R7110 */ + 0x0000, /* R7111 */ + 0x0000, /* R7112 */ + 0x0000, /* R7113 */ + 0x0000, /* R7114 */ + 0x0000, /* R7115 */ + 0x0000, /* R7116 */ + 0x0000, /* R7117 */ + 0x0000, /* R7118 */ + 0x0000, /* R7119 */ + 0x0000, /* R7120 */ + 0x0000, /* R7121 */ + 0x0000, /* R7122 */ + 0x0000, /* R7123 */ + 0x0000, /* R7124 */ + 0x0000, /* R7125 */ + 0x0000, /* R7126 */ + 0x0000, /* R7127 */ + 0x0000, /* R7128 */ + 0x0000, /* R7129 */ + 0x0000, /* R7130 */ + 0x0000, /* R7131 */ + 0x0000, /* R7132 */ + 0x0000, /* R7133 */ + 0x0000, /* R7134 */ + 0x0000, /* R7135 */ + 0x0000, /* R7136 */ + 0x0000, /* R7137 */ + 0x0000, /* R7138 */ + 0x0000, /* R7139 */ + 0x0000, /* R7140 */ + 0x0000, /* R7141 */ + 0x0000, /* R7142 */ + 0x0000, /* R7143 */ + 0x0000, /* R7144 */ + 0x0000, /* R7145 */ + 0x0000, /* R7146 */ + 0x0000, /* R7147 */ + 0x0000, /* R7148 */ + 0x0000, /* R7149 */ + 0x0000, /* R7150 */ + 0x0000, /* R7151 */ + 0x0000, /* R7152 */ + 0x0000, /* R7153 */ + 0x0000, /* R7154 */ + 0x0000, /* R7155 */ + 0x0000, /* R7156 */ + 0x0000, /* R7157 */ + 0x0000, /* R7158 */ + 0x0000, /* R7159 */ + 0x0000, /* R7160 */ + 0x0000, /* R7161 */ + 0x0000, /* R7162 */ + 0x0000, /* R7163 */ + 0x0000, /* R7164 */ + 0x0000, /* R7165 */ + 0x0000, /* R7166 */ + 0x0000, /* R7167 */ + 0x0000, /* R7168 */ + 0x0000, /* R7169 */ + 0x0000, /* R7170 */ + 0x0000, /* R7171 */ + 0x0000, /* R7172 */ + 0x0000, /* R7173 */ + 0x0000, /* R7174 */ + 0x0000, /* R7175 */ + 0x0000, /* R7176 */ + 0x0000, /* R7177 */ + 0x0000, /* R7178 */ + 0x0000, /* R7179 */ + 0x0000, /* R7180 */ + 0x0000, /* R7181 */ + 0x0000, /* R7182 */ + 0x0000, /* R7183 */ + 0x0000, /* R7184 */ + 0x0000, /* R7185 */ + 0x0000, /* R7186 */ + 0x0000, /* R7187 */ + 0x0000, /* R7188 */ + 0x0000, /* R7189 */ + 0x0000, /* R7190 */ + 0x0000, /* R7191 */ + 0x0000, /* R7192 */ + 0x0000, /* R7193 */ + 0x0000, /* R7194 */ + 0x0000, /* R7195 */ + 0x0000, /* R7196 */ + 0x0000, /* R7197 */ + 0x0000, /* R7198 */ + 0x0000, /* R7199 */ + 0x0000, /* R7200 */ + 0x0000, /* R7201 */ + 0x0000, /* R7202 */ + 0x0000, /* R7203 */ + 0x0000, /* R7204 */ + 0x0000, /* R7205 */ + 0x0000, /* R7206 */ + 0x0000, /* R7207 */ + 0x0000, /* R7208 */ + 0x0000, /* R7209 */ + 0x0000, /* R7210 */ + 0x0000, /* R7211 */ + 0x0000, /* R7212 */ + 0x0000, /* R7213 */ + 0x0000, /* R7214 */ + 0x0000, /* R7215 */ + 0x0000, /* R7216 */ + 0x0000, /* R7217 */ + 0x0000, /* R7218 */ + 0x0000, /* R7219 */ + 0x0000, /* R7220 */ + 0x0000, /* R7221 */ + 0x0000, /* R7222 */ + 0x0000, /* R7223 */ + 0x0000, /* R7224 */ + 0x0000, /* R7225 */ + 0x0000, /* R7226 */ + 0x0000, /* R7227 */ + 0x0000, /* R7228 */ + 0x0000, /* R7229 */ + 0x0000, /* R7230 */ + 0x0000, /* R7231 */ + 0x0000, /* R7232 */ + 0x0000, /* R7233 */ + 0x0000, /* R7234 */ + 0x0000, /* R7235 */ + 0x0000, /* R7236 */ + 0x0000, /* R7237 */ + 0x0000, /* R7238 */ + 0x0000, /* R7239 */ + 0x0000, /* R7240 */ + 0x0000, /* R7241 */ + 0x0000, /* R7242 */ + 0x0000, /* R7243 */ + 0x0000, /* R7244 */ + 0x0000, /* R7245 */ + 0x0000, /* R7246 */ + 0x0000, /* R7247 */ + 0x0000, /* R7248 */ + 0x0000, /* R7249 */ + 0x0000, /* R7250 */ + 0x0000, /* R7251 */ + 0x0000, /* R7252 */ + 0x0000, /* R7253 */ + 0x0000, /* R7254 */ + 0x0000, /* R7255 */ + 0x0000, /* R7256 */ + 0x0000, /* R7257 */ + 0x0000, /* R7258 */ + 0x0000, /* R7259 */ + 0x0000, /* R7260 */ + 0x0000, /* R7261 */ + 0x0000, /* R7262 */ + 0x0000, /* R7263 */ + 0x0000, /* R7264 */ + 0x0000, /* R7265 */ + 0x0000, /* R7266 */ + 0x0000, /* R7267 */ + 0x0000, /* R7268 */ + 0x0000, /* R7269 */ + 0x0000, /* R7270 */ + 0x0000, /* R7271 */ + 0x0000, /* R7272 */ + 0x0000, /* R7273 */ + 0x0000, /* R7274 */ + 0x0000, /* R7275 */ + 0x0000, /* R7276 */ + 0x0000, /* R7277 */ + 0x0000, /* R7278 */ + 0x0000, /* R7279 */ + 0x0000, /* R7280 */ + 0x0000, /* R7281 */ + 0x0000, /* R7282 */ + 0x0000, /* R7283 */ + 0x0000, /* R7284 */ + 0x0000, /* R7285 */ + 0x0000, /* R7286 */ + 0x0000, /* R7287 */ + 0x0000, /* R7288 */ + 0x0000, /* R7289 */ + 0x0000, /* R7290 */ + 0x0000, /* R7291 */ + 0x0000, /* R7292 */ + 0x0000, /* R7293 */ + 0x0000, /* R7294 */ + 0x0000, /* R7295 */ + 0x0000, /* R7296 */ + 0x0000, /* R7297 */ + 0x0000, /* R7298 */ + 0x0000, /* R7299 */ + 0x0000, /* R7300 */ + 0x0000, /* R7301 */ + 0x0000, /* R7302 */ + 0x0000, /* R7303 */ + 0x0000, /* R7304 */ + 0x0000, /* R7305 */ + 0x0000, /* R7306 */ + 0x0000, /* R7307 */ + 0x0000, /* R7308 */ + 0x0000, /* R7309 */ + 0x0000, /* R7310 */ + 0x0000, /* R7311 */ + 0x0000, /* R7312 */ + 0x0000, /* R7313 */ + 0x0000, /* R7314 */ + 0x0000, /* R7315 */ + 0x0000, /* R7316 */ + 0x0000, /* R7317 */ + 0x0000, /* R7318 */ + 0x0000, /* R7319 */ + 0x0000, /* R7320 */ + 0x0000, /* R7321 */ + 0x0000, /* R7322 */ + 0x0000, /* R7323 */ + 0x0000, /* R7324 */ + 0x0000, /* R7325 */ + 0x0000, /* R7326 */ + 0x0000, /* R7327 */ + 0x0000, /* R7328 */ + 0x0000, /* R7329 */ + 0x0000, /* R7330 */ + 0x0000, /* R7331 */ + 0x0000, /* R7332 */ + 0x0000, /* R7333 */ + 0x0000, /* R7334 */ + 0x0000, /* R7335 */ + 0x0000, /* R7336 */ + 0x0000, /* R7337 */ + 0x0000, /* R7338 */ + 0x0000, /* R7339 */ + 0x0000, /* R7340 */ + 0x0000, /* R7341 */ + 0x0000, /* R7342 */ + 0x0000, /* R7343 */ + 0x0000, /* R7344 */ + 0x0000, /* R7345 */ + 0x0000, /* R7346 */ + 0x0000, /* R7347 */ + 0x0000, /* R7348 */ + 0x0000, /* R7349 */ + 0x0000, /* R7350 */ + 0x0000, /* R7351 */ + 0x0000, /* R7352 */ + 0x0000, /* R7353 */ + 0x0000, /* R7354 */ + 0x0000, /* R7355 */ + 0x0000, /* R7356 */ + 0x0000, /* R7357 */ + 0x0000, /* R7358 */ + 0x0000, /* R7359 */ + 0x0000, /* R7360 */ + 0x0000, /* R7361 */ + 0x0000, /* R7362 */ + 0x0000, /* R7363 */ + 0x0000, /* R7364 */ + 0x0000, /* R7365 */ + 0x0000, /* R7366 */ + 0x0000, /* R7367 */ + 0x0000, /* R7368 */ + 0x0000, /* R7369 */ + 0x0000, /* R7370 */ + 0x0000, /* R7371 */ + 0x0000, /* R7372 */ + 0x0000, /* R7373 */ + 0x0000, /* R7374 */ + 0x0000, /* R7375 */ + 0x0000, /* R7376 */ + 0x0000, /* R7377 */ + 0x0000, /* R7378 */ + 0x0000, /* R7379 */ + 0x0000, /* R7380 */ + 0x0000, /* R7381 */ + 0x0000, /* R7382 */ + 0x0000, /* R7383 */ + 0x0000, /* R7384 */ + 0x0000, /* R7385 */ + 0x0000, /* R7386 */ + 0x0000, /* R7387 */ + 0x0000, /* R7388 */ + 0x0000, /* R7389 */ + 0x0000, /* R7390 */ + 0x0000, /* R7391 */ + 0x0000, /* R7392 */ + 0x0000, /* R7393 */ + 0x0000, /* R7394 */ + 0x0000, /* R7395 */ + 0x0000, /* R7396 */ + 0x0000, /* R7397 */ + 0x0000, /* R7398 */ + 0x0000, /* R7399 */ + 0x0000, /* R7400 */ + 0x0000, /* R7401 */ + 0x0000, /* R7402 */ + 0x0000, /* R7403 */ + 0x0000, /* R7404 */ + 0x0000, /* R7405 */ + 0x0000, /* R7406 */ + 0x0000, /* R7407 */ + 0x0000, /* R7408 */ + 0x0000, /* R7409 */ + 0x0000, /* R7410 */ + 0x0000, /* R7411 */ + 0x0000, /* R7412 */ + 0x0000, /* R7413 */ + 0x0000, /* R7414 */ + 0x0000, /* R7415 */ + 0x0000, /* R7416 */ + 0x0000, /* R7417 */ + 0x0000, /* R7418 */ + 0x0000, /* R7419 */ + 0x0000, /* R7420 */ + 0x0000, /* R7421 */ + 0x0000, /* R7422 */ + 0x0000, /* R7423 */ + 0x0000, /* R7424 */ + 0x0000, /* R7425 */ + 0x0000, /* R7426 */ + 0x0000, /* R7427 */ + 0x0000, /* R7428 */ + 0x0000, /* R7429 */ + 0x0000, /* R7430 */ + 0x0000, /* R7431 */ + 0x0000, /* R7432 */ + 0x0000, /* R7433 */ + 0x0000, /* R7434 */ + 0x0000, /* R7435 */ + 0x0000, /* R7436 */ + 0x0000, /* R7437 */ + 0x0000, /* R7438 */ + 0x0000, /* R7439 */ + 0x0000, /* R7440 */ + 0x0000, /* R7441 */ + 0x0000, /* R7442 */ + 0x0000, /* R7443 */ + 0x0000, /* R7444 */ + 0x0000, /* R7445 */ + 0x0000, /* R7446 */ + 0x0000, /* R7447 */ + 0x0000, /* R7448 */ + 0x0000, /* R7449 */ + 0x0000, /* R7450 */ + 0x0000, /* R7451 */ + 0x0000, /* R7452 */ + 0x0000, /* R7453 */ + 0x0000, /* R7454 */ + 0x0000, /* R7455 */ + 0x0000, /* R7456 */ + 0x0000, /* R7457 */ + 0x0000, /* R7458 */ + 0x0000, /* R7459 */ + 0x0000, /* R7460 */ + 0x0000, /* R7461 */ + 0x0000, /* R7462 */ + 0x0000, /* R7463 */ + 0x0000, /* R7464 */ + 0x0000, /* R7465 */ + 0x0000, /* R7466 */ + 0x0000, /* R7467 */ + 0x0000, /* R7468 */ + 0x0000, /* R7469 */ + 0x0000, /* R7470 */ + 0x0000, /* R7471 */ + 0x0000, /* R7472 */ + 0x0000, /* R7473 */ + 0x0000, /* R7474 */ + 0x0000, /* R7475 */ + 0x0000, /* R7476 */ + 0x0000, /* R7477 */ + 0x0000, /* R7478 */ + 0x0000, /* R7479 */ + 0x0000, /* R7480 */ + 0x0000, /* R7481 */ + 0x0000, /* R7482 */ + 0x0000, /* R7483 */ + 0x0000, /* R7484 */ + 0x0000, /* R7485 */ + 0x0000, /* R7486 */ + 0x0000, /* R7487 */ + 0x0000, /* R7488 */ + 0x0000, /* R7489 */ + 0x0000, /* R7490 */ + 0x0000, /* R7491 */ + 0x0000, /* R7492 */ + 0x0000, /* R7493 */ + 0x0000, /* R7494 */ + 0x0000, /* R7495 */ + 0x0000, /* R7496 */ + 0x0000, /* R7497 */ + 0x0000, /* R7498 */ + 0x0000, /* R7499 */ + 0x0000, /* R7500 */ + 0x0000, /* R7501 */ + 0x0000, /* R7502 */ + 0x0000, /* R7503 */ + 0x0000, /* R7504 */ + 0x0000, /* R7505 */ + 0x0000, /* R7506 */ + 0x0000, /* R7507 */ + 0x0000, /* R7508 */ + 0x0000, /* R7509 */ + 0x0000, /* R7510 */ + 0x0000, /* R7511 */ + 0x0000, /* R7512 */ + 0x0000, /* R7513 */ + 0x0000, /* R7514 */ + 0x0000, /* R7515 */ + 0x0000, /* R7516 */ + 0x0000, /* R7517 */ + 0x0000, /* R7518 */ + 0x0000, /* R7519 */ + 0x0000, /* R7520 */ + 0x0000, /* R7521 */ + 0x0000, /* R7522 */ + 0x0000, /* R7523 */ + 0x0000, /* R7524 */ + 0x0000, /* R7525 */ + 0x0000, /* R7526 */ + 0x0000, /* R7527 */ + 0x0000, /* R7528 */ + 0x0000, /* R7529 */ + 0x0000, /* R7530 */ + 0x0000, /* R7531 */ + 0x0000, /* R7532 */ + 0x0000, /* R7533 */ + 0x0000, /* R7534 */ + 0x0000, /* R7535 */ + 0x0000, /* R7536 */ + 0x0000, /* R7537 */ + 0x0000, /* R7538 */ + 0x0000, /* R7539 */ + 0x0000, /* R7540 */ + 0x0000, /* R7541 */ + 0x0000, /* R7542 */ + 0x0000, /* R7543 */ + 0x0000, /* R7544 */ + 0x0000, /* R7545 */ + 0x0000, /* R7546 */ + 0x0000, /* R7547 */ + 0x0000, /* R7548 */ + 0x0000, /* R7549 */ + 0x0000, /* R7550 */ + 0x0000, /* R7551 */ + 0x0000, /* R7552 */ + 0x0000, /* R7553 */ + 0x0000, /* R7554 */ + 0x0000, /* R7555 */ + 0x0000, /* R7556 */ + 0x0000, /* R7557 */ + 0x0000, /* R7558 */ + 0x0000, /* R7559 */ + 0x0000, /* R7560 */ + 0x0000, /* R7561 */ + 0x0000, /* R7562 */ + 0x0000, /* R7563 */ + 0x0000, /* R7564 */ + 0x0000, /* R7565 */ + 0x0000, /* R7566 */ + 0x0000, /* R7567 */ + 0x0000, /* R7568 */ + 0x0000, /* R7569 */ + 0x0000, /* R7570 */ + 0x0000, /* R7571 */ + 0x0000, /* R7572 */ + 0x0000, /* R7573 */ + 0x0000, /* R7574 */ + 0x0000, /* R7575 */ + 0x0000, /* R7576 */ + 0x0000, /* R7577 */ + 0x0000, /* R7578 */ + 0x0000, /* R7579 */ + 0x0000, /* R7580 */ + 0x0000, /* R7581 */ + 0x0000, /* R7582 */ + 0x0000, /* R7583 */ + 0x0000, /* R7584 */ + 0x0000, /* R7585 */ + 0x0000, /* R7586 */ + 0x0000, /* R7587 */ + 0x0000, /* R7588 */ + 0x0000, /* R7589 */ + 0x0000, /* R7590 */ + 0x0000, /* R7591 */ + 0x0000, /* R7592 */ + 0x0000, /* R7593 */ + 0x0000, /* R7594 */ + 0x0000, /* R7595 */ + 0x0000, /* R7596 */ + 0x0000, /* R7597 */ + 0x0000, /* R7598 */ + 0x0000, /* R7599 */ + 0x0000, /* R7600 */ + 0x0000, /* R7601 */ + 0x0000, /* R7602 */ + 0x0000, /* R7603 */ + 0x0000, /* R7604 */ + 0x0000, /* R7605 */ + 0x0000, /* R7606 */ + 0x0000, /* R7607 */ + 0x0000, /* R7608 */ + 0x0000, /* R7609 */ + 0x0000, /* R7610 */ + 0x0000, /* R7611 */ + 0x0000, /* R7612 */ + 0x0000, /* R7613 */ + 0x0000, /* R7614 */ + 0x0000, /* R7615 */ + 0x0000, /* R7616 */ + 0x0000, /* R7617 */ + 0x0000, /* R7618 */ + 0x0000, /* R7619 */ + 0x0000, /* R7620 */ + 0x0000, /* R7621 */ + 0x0000, /* R7622 */ + 0x0000, /* R7623 */ + 0x0000, /* R7624 */ + 0x0000, /* R7625 */ + 0x0000, /* R7626 */ + 0x0000, /* R7627 */ + 0x0000, /* R7628 */ + 0x0000, /* R7629 */ + 0x0000, /* R7630 */ + 0x0000, /* R7631 */ + 0x0000, /* R7632 */ + 0x0000, /* R7633 */ + 0x0000, /* R7634 */ + 0x0000, /* R7635 */ + 0x0000, /* R7636 */ + 0x0000, /* R7637 */ + 0x0000, /* R7638 */ + 0x0000, /* R7639 */ + 0x0000, /* R7640 */ + 0x0000, /* R7641 */ + 0x0000, /* R7642 */ + 0x0000, /* R7643 */ + 0x0000, /* R7644 */ + 0x0000, /* R7645 */ + 0x0000, /* R7646 */ + 0x0000, /* R7647 */ + 0x0000, /* R7648 */ + 0x0000, /* R7649 */ + 0x0000, /* R7650 */ + 0x0000, /* R7651 */ + 0x0000, /* R7652 */ + 0x0000, /* R7653 */ + 0x0000, /* R7654 */ + 0x0000, /* R7655 */ + 0x0000, /* R7656 */ + 0x0000, /* R7657 */ + 0x0000, /* R7658 */ + 0x0000, /* R7659 */ + 0x0000, /* R7660 */ + 0x0000, /* R7661 */ + 0x0000, /* R7662 */ + 0x0000, /* R7663 */ + 0x0000, /* R7664 */ + 0x0000, /* R7665 */ + 0x0000, /* R7666 */ + 0x0000, /* R7667 */ + 0x0000, /* R7668 */ + 0x0000, /* R7669 */ + 0x0000, /* R7670 */ + 0x0000, /* R7671 */ + 0x0000, /* R7672 */ + 0x0000, /* R7673 */ + 0x0000, /* R7674 */ + 0x0000, /* R7675 */ + 0x0000, /* R7676 */ + 0x0000, /* R7677 */ + 0x0000, /* R7678 */ + 0x0000, /* R7679 */ + 0x0000, /* R7680 */ + 0x0000, /* R7681 */ + 0x0000, /* R7682 */ + 0x0000, /* R7683 */ + 0x0000, /* R7684 */ + 0x0000, /* R7685 */ + 0x0000, /* R7686 */ + 0x0000, /* R7687 */ + 0x0000, /* R7688 */ + 0x0000, /* R7689 */ + 0x0000, /* R7690 */ + 0x0000, /* R7691 */ + 0x0000, /* R7692 */ + 0x0000, /* R7693 */ + 0x0000, /* R7694 */ + 0x0000, /* R7695 */ + 0x0000, /* R7696 */ + 0x0000, /* R7697 */ + 0x0000, /* R7698 */ + 0x0000, /* R7699 */ + 0x0000, /* R7700 */ + 0x0000, /* R7701 */ + 0x0000, /* R7702 */ + 0x0000, /* R7703 */ + 0x0000, /* R7704 */ + 0x0000, /* R7705 */ + 0x0000, /* R7706 */ + 0x0000, /* R7707 */ + 0x0000, /* R7708 */ + 0x0000, /* R7709 */ + 0x0000, /* R7710 */ + 0x0000, /* R7711 */ + 0x0000, /* R7712 */ + 0x0000, /* R7713 */ + 0x0000, /* R7714 */ + 0x0000, /* R7715 */ + 0x0000, /* R7716 */ + 0x0000, /* R7717 */ + 0x0000, /* R7718 */ + 0x0000, /* R7719 */ + 0x0000, /* R7720 */ + 0x0000, /* R7721 */ + 0x0000, /* R7722 */ + 0x0000, /* R7723 */ + 0x0000, /* R7724 */ + 0x0000, /* R7725 */ + 0x0000, /* R7726 */ + 0x0000, /* R7727 */ + 0x0000, /* R7728 */ + 0x0000, /* R7729 */ + 0x0000, /* R7730 */ + 0x0000, /* R7731 */ + 0x0000, /* R7732 */ + 0x0000, /* R7733 */ + 0x0000, /* R7734 */ + 0x0000, /* R7735 */ + 0x0000, /* R7736 */ + 0x0000, /* R7737 */ + 0x0000, /* R7738 */ + 0x0000, /* R7739 */ + 0x0000, /* R7740 */ + 0x0000, /* R7741 */ + 0x0000, /* R7742 */ + 0x0000, /* R7743 */ + 0x0000, /* R7744 */ + 0x0000, /* R7745 */ + 0x0000, /* R7746 */ + 0x0000, /* R7747 */ + 0x0000, /* R7748 */ + 0x0000, /* R7749 */ + 0x0000, /* R7750 */ + 0x0000, /* R7751 */ + 0x0000, /* R7752 */ + 0x0000, /* R7753 */ + 0x0000, /* R7754 */ + 0x0000, /* R7755 */ + 0x0000, /* R7756 */ + 0x0000, /* R7757 */ + 0x0000, /* R7758 */ + 0x0000, /* R7759 */ + 0x0000, /* R7760 */ + 0x0000, /* R7761 */ + 0x0000, /* R7762 */ + 0x0000, /* R7763 */ + 0x0000, /* R7764 */ + 0x0000, /* R7765 */ + 0x0000, /* R7766 */ + 0x0000, /* R7767 */ + 0x0000, /* R7768 */ + 0x0000, /* R7769 */ + 0x0000, /* R7770 */ + 0x0000, /* R7771 */ + 0x0000, /* R7772 */ + 0x0000, /* R7773 */ + 0x0000, /* R7774 */ + 0x0000, /* R7775 */ + 0x0000, /* R7776 */ + 0x0000, /* R7777 */ + 0x0000, /* R7778 */ + 0x0000, /* R7779 */ + 0x0000, /* R7780 */ + 0x0000, /* R7781 */ + 0x0000, /* R7782 */ + 0x0000, /* R7783 */ + 0x0000, /* R7784 */ + 0x0000, /* R7785 */ + 0x0000, /* R7786 */ + 0x0000, /* R7787 */ + 0x0000, /* R7788 */ + 0x0000, /* R7789 */ + 0x0000, /* R7790 */ + 0x0000, /* R7791 */ + 0x0000, /* R7792 */ + 0x0000, /* R7793 */ + 0x0000, /* R7794 */ + 0x0000, /* R7795 */ + 0x0000, /* R7796 */ + 0x0000, /* R7797 */ + 0x0000, /* R7798 */ + 0x0000, /* R7799 */ + 0x0000, /* R7800 */ + 0x0000, /* R7801 */ + 0x0000, /* R7802 */ + 0x0000, /* R7803 */ + 0x0000, /* R7804 */ + 0x0000, /* R7805 */ + 0x0000, /* R7806 */ + 0x0000, /* R7807 */ + 0x0000, /* R7808 */ + 0x0000, /* R7809 */ + 0x0000, /* R7810 */ + 0x0000, /* R7811 */ + 0x0000, /* R7812 */ + 0x0000, /* R7813 */ + 0x0000, /* R7814 */ + 0x0000, /* R7815 */ + 0x0000, /* R7816 */ + 0x0000, /* R7817 */ + 0x0000, /* R7818 */ + 0x0000, /* R7819 */ + 0x0000, /* R7820 */ + 0x0000, /* R7821 */ + 0x0000, /* R7822 */ + 0x0000, /* R7823 */ + 0x0000, /* R7824 */ + 0x0000, /* R7825 */ + 0x0000, /* R7826 */ + 0x0000, /* R7827 */ + 0x0000, /* R7828 */ + 0x0000, /* R7829 */ + 0x0000, /* R7830 */ + 0x0000, /* R7831 */ + 0x0000, /* R7832 */ + 0x0000, /* R7833 */ + 0x0000, /* R7834 */ + 0x0000, /* R7835 */ + 0x0000, /* R7836 */ + 0x0000, /* R7837 */ + 0x0000, /* R7838 */ + 0x0000, /* R7839 */ + 0x0000, /* R7840 */ + 0x0000, /* R7841 */ + 0x0000, /* R7842 */ + 0x0000, /* R7843 */ + 0x0000, /* R7844 */ + 0x0000, /* R7845 */ + 0x0000, /* R7846 */ + 0x0000, /* R7847 */ + 0x0000, /* R7848 */ + 0x0000, /* R7849 */ + 0x0000, /* R7850 */ + 0x0000, /* R7851 */ + 0x0000, /* R7852 */ + 0x0000, /* R7853 */ + 0x0000, /* R7854 */ + 0x0000, /* R7855 */ + 0x0000, /* R7856 */ + 0x0000, /* R7857 */ + 0x0000, /* R7858 */ + 0x0000, /* R7859 */ + 0x0000, /* R7860 */ + 0x0000, /* R7861 */ + 0x0000, /* R7862 */ + 0x0000, /* R7863 */ + 0x0000, /* R7864 */ + 0x0000, /* R7865 */ + 0x0000, /* R7866 */ + 0x0000, /* R7867 */ + 0x0000, /* R7868 */ + 0x0000, /* R7869 */ + 0x0000, /* R7870 */ + 0x0000, /* R7871 */ + 0x0000, /* R7872 */ + 0x0000, /* R7873 */ + 0x0000, /* R7874 */ + 0x0000, /* R7875 */ + 0x0000, /* R7876 */ + 0x0000, /* R7877 */ + 0x0000, /* R7878 */ + 0x0000, /* R7879 */ + 0x0000, /* R7880 */ + 0x0000, /* R7881 */ + 0x0000, /* R7882 */ + 0x0000, /* R7883 */ + 0x0000, /* R7884 */ + 0x0000, /* R7885 */ + 0x0000, /* R7886 */ + 0x0000, /* R7887 */ + 0x0000, /* R7888 */ + 0x0000, /* R7889 */ + 0x0000, /* R7890 */ + 0x0000, /* R7891 */ + 0x0000, /* R7892 */ + 0x0000, /* R7893 */ + 0x0000, /* R7894 */ + 0x0000, /* R7895 */ + 0x0000, /* R7896 */ + 0x0000, /* R7897 */ + 0x0000, /* R7898 */ + 0x0000, /* R7899 */ + 0x0000, /* R7900 */ + 0x0000, /* R7901 */ + 0x0000, /* R7902 */ + 0x0000, /* R7903 */ + 0x0000, /* R7904 */ + 0x0000, /* R7905 */ + 0x0000, /* R7906 */ + 0x0000, /* R7907 */ + 0x0000, /* R7908 */ + 0x0000, /* R7909 */ + 0x0000, /* R7910 */ + 0x0000, /* R7911 */ + 0x0000, /* R7912 */ + 0x0000, /* R7913 */ + 0x0000, /* R7914 */ + 0x0000, /* R7915 */ + 0x0000, /* R7916 */ + 0x0000, /* R7917 */ + 0x0000, /* R7918 */ + 0x0000, /* R7919 */ + 0x0000, /* R7920 */ + 0x0000, /* R7921 */ + 0x0000, /* R7922 */ + 0x0000, /* R7923 */ + 0x0000, /* R7924 */ + 0x0000, /* R7925 */ + 0x0000, /* R7926 */ + 0x0000, /* R7927 */ + 0x0000, /* R7928 */ + 0x0000, /* R7929 */ + 0x0000, /* R7930 */ + 0x0000, /* R7931 */ + 0x0000, /* R7932 */ + 0x0000, /* R7933 */ + 0x0000, /* R7934 */ + 0x0000, /* R7935 */ + 0x0000, /* R7936 */ + 0x0000, /* R7937 */ + 0x0000, /* R7938 */ + 0x0000, /* R7939 */ + 0x0000, /* R7940 */ + 0x0000, /* R7941 */ + 0x0000, /* R7942 */ + 0x0000, /* R7943 */ + 0x0000, /* R7944 */ + 0x0000, /* R7945 */ + 0x0000, /* R7946 */ + 0x0000, /* R7947 */ + 0x0000, /* R7948 */ + 0x0000, /* R7949 */ + 0x0000, /* R7950 */ + 0x0000, /* R7951 */ + 0x0000, /* R7952 */ + 0x0000, /* R7953 */ + 0x0000, /* R7954 */ + 0x0000, /* R7955 */ + 0x0000, /* R7956 */ + 0x0000, /* R7957 */ + 0x0000, /* R7958 */ + 0x0000, /* R7959 */ + 0x0000, /* R7960 */ + 0x0000, /* R7961 */ + 0x0000, /* R7962 */ + 0x0000, /* R7963 */ + 0x0000, /* R7964 */ + 0x0000, /* R7965 */ + 0x0000, /* R7966 */ + 0x0000, /* R7967 */ + 0x0000, /* R7968 */ + 0x0000, /* R7969 */ + 0x0000, /* R7970 */ + 0x0000, /* R7971 */ + 0x0000, /* R7972 */ + 0x0000, /* R7973 */ + 0x0000, /* R7974 */ + 0x0000, /* R7975 */ + 0x0000, /* R7976 */ + 0x0000, /* R7977 */ + 0x0000, /* R7978 */ + 0x0000, /* R7979 */ + 0x0000, /* R7980 */ + 0x0000, /* R7981 */ + 0x0000, /* R7982 */ + 0x0000, /* R7983 */ + 0x0000, /* R7984 */ + 0x0000, /* R7985 */ + 0x0000, /* R7986 */ + 0x0000, /* R7987 */ + 0x0000, /* R7988 */ + 0x0000, /* R7989 */ + 0x0000, /* R7990 */ + 0x0000, /* R7991 */ + 0x0000, /* R7992 */ + 0x0000, /* R7993 */ + 0x0000, /* R7994 */ + 0x0000, /* R7995 */ + 0x0000, /* R7996 */ + 0x0000, /* R7997 */ + 0x0000, /* R7998 */ + 0x0000, /* R7999 */ + 0x0000, /* R8000 */ + 0x0000, /* R8001 */ + 0x0000, /* R8002 */ + 0x0000, /* R8003 */ + 0x0000, /* R8004 */ + 0x0000, /* R8005 */ + 0x0000, /* R8006 */ + 0x0000, /* R8007 */ + 0x0000, /* R8008 */ + 0x0000, /* R8009 */ + 0x0000, /* R8010 */ + 0x0000, /* R8011 */ + 0x0000, /* R8012 */ + 0x0000, /* R8013 */ + 0x0000, /* R8014 */ + 0x0000, /* R8015 */ + 0x0000, /* R8016 */ + 0x0000, /* R8017 */ + 0x0000, /* R8018 */ + 0x0000, /* R8019 */ + 0x0000, /* R8020 */ + 0x0000, /* R8021 */ + 0x0000, /* R8022 */ + 0x0000, /* R8023 */ + 0x0000, /* R8024 */ + 0x0000, /* R8025 */ + 0x0000, /* R8026 */ + 0x0000, /* R8027 */ + 0x0000, /* R8028 */ + 0x0000, /* R8029 */ + 0x0000, /* R8030 */ + 0x0000, /* R8031 */ + 0x0000, /* R8032 */ + 0x0000, /* R8033 */ + 0x0000, /* R8034 */ + 0x0000, /* R8035 */ + 0x0000, /* R8036 */ + 0x0000, /* R8037 */ + 0x0000, /* R8038 */ + 0x0000, /* R8039 */ + 0x0000, /* R8040 */ + 0x0000, /* R8041 */ + 0x0000, /* R8042 */ + 0x0000, /* R8043 */ + 0x0000, /* R8044 */ + 0x0000, /* R8045 */ + 0x0000, /* R8046 */ + 0x0000, /* R8047 */ + 0x0000, /* R8048 */ + 0x0000, /* R8049 */ + 0x0000, /* R8050 */ + 0x0000, /* R8051 */ + 0x0000, /* R8052 */ + 0x0000, /* R8053 */ + 0x0000, /* R8054 */ + 0x0000, /* R8055 */ + 0x0000, /* R8056 */ + 0x0000, /* R8057 */ + 0x0000, /* R8058 */ + 0x0000, /* R8059 */ + 0x0000, /* R8060 */ + 0x0000, /* R8061 */ + 0x0000, /* R8062 */ + 0x0000, /* R8063 */ + 0x0000, /* R8064 */ + 0x0000, /* R8065 */ + 0x0000, /* R8066 */ + 0x0000, /* R8067 */ + 0x0000, /* R8068 */ + 0x0000, /* R8069 */ + 0x0000, /* R8070 */ + 0x0000, /* R8071 */ + 0x0000, /* R8072 */ + 0x0000, /* R8073 */ + 0x0000, /* R8074 */ + 0x0000, /* R8075 */ + 0x0000, /* R8076 */ + 0x0000, /* R8077 */ + 0x0000, /* R8078 */ + 0x0000, /* R8079 */ + 0x0000, /* R8080 */ + 0x0000, /* R8081 */ + 0x0000, /* R8082 */ + 0x0000, /* R8083 */ + 0x0000, /* R8084 */ + 0x0000, /* R8085 */ + 0x0000, /* R8086 */ + 0x0000, /* R8087 */ + 0x0000, /* R8088 */ + 0x0000, /* R8089 */ + 0x0000, /* R8090 */ + 0x0000, /* R8091 */ + 0x0000, /* R8092 */ + 0x0000, /* R8093 */ + 0x0000, /* R8094 */ + 0x0000, /* R8095 */ + 0x0000, /* R8096 */ + 0x0000, /* R8097 */ + 0x0000, /* R8098 */ + 0x0000, /* R8099 */ + 0x0000, /* R8100 */ + 0x0000, /* R8101 */ + 0x0000, /* R8102 */ + 0x0000, /* R8103 */ + 0x0000, /* R8104 */ + 0x0000, /* R8105 */ + 0x0000, /* R8106 */ + 0x0000, /* R8107 */ + 0x0000, /* R8108 */ + 0x0000, /* R8109 */ + 0x0000, /* R8110 */ + 0x0000, /* R8111 */ + 0x0000, /* R8112 */ + 0x0000, /* R8113 */ + 0x0000, /* R8114 */ + 0x0000, /* R8115 */ + 0x0000, /* R8116 */ + 0x0000, /* R8117 */ + 0x0000, /* R8118 */ + 0x0000, /* R8119 */ + 0x0000, /* R8120 */ + 0x0000, /* R8121 */ + 0x0000, /* R8122 */ + 0x0000, /* R8123 */ + 0x0000, /* R8124 */ + 0x0000, /* R8125 */ + 0x0000, /* R8126 */ + 0x0000, /* R8127 */ + 0x0000, /* R8128 */ + 0x0000, /* R8129 */ + 0x0000, /* R8130 */ + 0x0000, /* R8131 */ + 0x0000, /* R8132 */ + 0x0000, /* R8133 */ + 0x0000, /* R8134 */ + 0x0000, /* R8135 */ + 0x0000, /* R8136 */ + 0x0000, /* R8137 */ + 0x0000, /* R8138 */ + 0x0000, /* R8139 */ + 0x0000, /* R8140 */ + 0x0000, /* R8141 */ + 0x0000, /* R8142 */ + 0x0000, /* R8143 */ + 0x0000, /* R8144 */ + 0x0000, /* R8145 */ + 0x0000, /* R8146 */ + 0x0000, /* R8147 */ + 0x0000, /* R8148 */ + 0x0000, /* R8149 */ + 0x0000, /* R8150 */ + 0x0000, /* R8151 */ + 0x0000, /* R8152 */ + 0x0000, /* R8153 */ + 0x0000, /* R8154 */ + 0x0000, /* R8155 */ + 0x0000, /* R8156 */ + 0x0000, /* R8157 */ + 0x0000, /* R8158 */ + 0x0000, /* R8159 */ + 0x0000, /* R8160 */ + 0x0000, /* R8161 */ + 0x0000, /* R8162 */ + 0x0000, /* R8163 */ + 0x0000, /* R8164 */ + 0x0000, /* R8165 */ + 0x0000, /* R8166 */ + 0x0000, /* R8167 */ + 0x0000, /* R8168 */ + 0x0000, /* R8169 */ + 0x0000, /* R8170 */ + 0x0000, /* R8171 */ + 0x0000, /* R8172 */ + 0x0000, /* R8173 */ + 0x0000, /* R8174 */ + 0x0000, /* R8175 */ + 0x0000, /* R8176 */ + 0x0000, /* R8177 */ + 0x0000, /* R8178 */ + 0x0000, /* R8179 */ + 0x0000, /* R8180 */ + 0x0000, /* R8181 */ + 0x0000, /* R8182 */ + 0x0000, /* R8183 */ + 0x0000, /* R8184 */ + 0x0000, /* R8185 */ + 0x0000, /* R8186 */ + 0x0000, /* R8187 */ + 0x0000, /* R8188 */ + 0x0000, /* R8189 */ + 0x0000, /* R8190 */ + 0x0000, /* R8191 */ + 0x0000, /* R8192 - DSP2 Instruction RAM 0 */ + 0x0000, /* R8193 */ + 0x0000, /* R8194 */ + 0x0000, /* R8195 */ + 0x0000, /* R8196 */ + 0x0000, /* R8197 */ + 0x0000, /* R8198 */ + 0x0000, /* R8199 */ + 0x0000, /* R8200 */ + 0x0000, /* R8201 */ + 0x0000, /* R8202 */ + 0x0000, /* R8203 */ + 0x0000, /* R8204 */ + 0x0000, /* R8205 */ + 0x0000, /* R8206 */ + 0x0000, /* R8207 */ + 0x0000, /* R8208 */ + 0x0000, /* R8209 */ + 0x0000, /* R8210 */ + 0x0000, /* R8211 */ + 0x0000, /* R8212 */ + 0x0000, /* R8213 */ + 0x0000, /* R8214 */ + 0x0000, /* R8215 */ + 0x0000, /* R8216 */ + 0x0000, /* R8217 */ + 0x0000, /* R8218 */ + 0x0000, /* R8219 */ + 0x0000, /* R8220 */ + 0x0000, /* R8221 */ + 0x0000, /* R8222 */ + 0x0000, /* R8223 */ + 0x0000, /* R8224 */ + 0x0000, /* R8225 */ + 0x0000, /* R8226 */ + 0x0000, /* R8227 */ + 0x0000, /* R8228 */ + 0x0000, /* R8229 */ + 0x0000, /* R8230 */ + 0x0000, /* R8231 */ + 0x0000, /* R8232 */ + 0x0000, /* R8233 */ + 0x0000, /* R8234 */ + 0x0000, /* R8235 */ + 0x0000, /* R8236 */ + 0x0000, /* R8237 */ + 0x0000, /* R8238 */ + 0x0000, /* R8239 */ + 0x0000, /* R8240 */ + 0x0000, /* R8241 */ + 0x0000, /* R8242 */ + 0x0000, /* R8243 */ + 0x0000, /* R8244 */ + 0x0000, /* R8245 */ + 0x0000, /* R8246 */ + 0x0000, /* R8247 */ + 0x0000, /* R8248 */ + 0x0000, /* R8249 */ + 0x0000, /* R8250 */ + 0x0000, /* R8251 */ + 0x0000, /* R8252 */ + 0x0000, /* R8253 */ + 0x0000, /* R8254 */ + 0x0000, /* R8255 */ + 0x0000, /* R8256 */ + 0x0000, /* R8257 */ + 0x0000, /* R8258 */ + 0x0000, /* R8259 */ + 0x0000, /* R8260 */ + 0x0000, /* R8261 */ + 0x0000, /* R8262 */ + 0x0000, /* R8263 */ + 0x0000, /* R8264 */ + 0x0000, /* R8265 */ + 0x0000, /* R8266 */ + 0x0000, /* R8267 */ + 0x0000, /* R8268 */ + 0x0000, /* R8269 */ + 0x0000, /* R8270 */ + 0x0000, /* R8271 */ + 0x0000, /* R8272 */ + 0x0000, /* R8273 */ + 0x0000, /* R8274 */ + 0x0000, /* R8275 */ + 0x0000, /* R8276 */ + 0x0000, /* R8277 */ + 0x0000, /* R8278 */ + 0x0000, /* R8279 */ + 0x0000, /* R8280 */ + 0x0000, /* R8281 */ + 0x0000, /* R8282 */ + 0x0000, /* R8283 */ + 0x0000, /* R8284 */ + 0x0000, /* R8285 */ + 0x0000, /* R8286 */ + 0x0000, /* R8287 */ + 0x0000, /* R8288 */ + 0x0000, /* R8289 */ + 0x0000, /* R8290 */ + 0x0000, /* R8291 */ + 0x0000, /* R8292 */ + 0x0000, /* R8293 */ + 0x0000, /* R8294 */ + 0x0000, /* R8295 */ + 0x0000, /* R8296 */ + 0x0000, /* R8297 */ + 0x0000, /* R8298 */ + 0x0000, /* R8299 */ + 0x0000, /* R8300 */ + 0x0000, /* R8301 */ + 0x0000, /* R8302 */ + 0x0000, /* R8303 */ + 0x0000, /* R8304 */ + 0x0000, /* R8305 */ + 0x0000, /* R8306 */ + 0x0000, /* R8307 */ + 0x0000, /* R8308 */ + 0x0000, /* R8309 */ + 0x0000, /* R8310 */ + 0x0000, /* R8311 */ + 0x0000, /* R8312 */ + 0x0000, /* R8313 */ + 0x0000, /* R8314 */ + 0x0000, /* R8315 */ + 0x0000, /* R8316 */ + 0x0000, /* R8317 */ + 0x0000, /* R8318 */ + 0x0000, /* R8319 */ + 0x0000, /* R8320 */ + 0x0000, /* R8321 */ + 0x0000, /* R8322 */ + 0x0000, /* R8323 */ + 0x0000, /* R8324 */ + 0x0000, /* R8325 */ + 0x0000, /* R8326 */ + 0x0000, /* R8327 */ + 0x0000, /* R8328 */ + 0x0000, /* R8329 */ + 0x0000, /* R8330 */ + 0x0000, /* R8331 */ + 0x0000, /* R8332 */ + 0x0000, /* R8333 */ + 0x0000, /* R8334 */ + 0x0000, /* R8335 */ + 0x0000, /* R8336 */ + 0x0000, /* R8337 */ + 0x0000, /* R8338 */ + 0x0000, /* R8339 */ + 0x0000, /* R8340 */ + 0x0000, /* R8341 */ + 0x0000, /* R8342 */ + 0x0000, /* R8343 */ + 0x0000, /* R8344 */ + 0x0000, /* R8345 */ + 0x0000, /* R8346 */ + 0x0000, /* R8347 */ + 0x0000, /* R8348 */ + 0x0000, /* R8349 */ + 0x0000, /* R8350 */ + 0x0000, /* R8351 */ + 0x0000, /* R8352 */ + 0x0000, /* R8353 */ + 0x0000, /* R8354 */ + 0x0000, /* R8355 */ + 0x0000, /* R8356 */ + 0x0000, /* R8357 */ + 0x0000, /* R8358 */ + 0x0000, /* R8359 */ + 0x0000, /* R8360 */ + 0x0000, /* R8361 */ + 0x0000, /* R8362 */ + 0x0000, /* R8363 */ + 0x0000, /* R8364 */ + 0x0000, /* R8365 */ + 0x0000, /* R8366 */ + 0x0000, /* R8367 */ + 0x0000, /* R8368 */ + 0x0000, /* R8369 */ + 0x0000, /* R8370 */ + 0x0000, /* R8371 */ + 0x0000, /* R8372 */ + 0x0000, /* R8373 */ + 0x0000, /* R8374 */ + 0x0000, /* R8375 */ + 0x0000, /* R8376 */ + 0x0000, /* R8377 */ + 0x0000, /* R8378 */ + 0x0000, /* R8379 */ + 0x0000, /* R8380 */ + 0x0000, /* R8381 */ + 0x0000, /* R8382 */ + 0x0000, /* R8383 */ + 0x0000, /* R8384 */ + 0x0000, /* R8385 */ + 0x0000, /* R8386 */ + 0x0000, /* R8387 */ + 0x0000, /* R8388 */ + 0x0000, /* R8389 */ + 0x0000, /* R8390 */ + 0x0000, /* R8391 */ + 0x0000, /* R8392 */ + 0x0000, /* R8393 */ + 0x0000, /* R8394 */ + 0x0000, /* R8395 */ + 0x0000, /* R8396 */ + 0x0000, /* R8397 */ + 0x0000, /* R8398 */ + 0x0000, /* R8399 */ + 0x0000, /* R8400 */ + 0x0000, /* R8401 */ + 0x0000, /* R8402 */ + 0x0000, /* R8403 */ + 0x0000, /* R8404 */ + 0x0000, /* R8405 */ + 0x0000, /* R8406 */ + 0x0000, /* R8407 */ + 0x0000, /* R8408 */ + 0x0000, /* R8409 */ + 0x0000, /* R8410 */ + 0x0000, /* R8411 */ + 0x0000, /* R8412 */ + 0x0000, /* R8413 */ + 0x0000, /* R8414 */ + 0x0000, /* R8415 */ + 0x0000, /* R8416 */ + 0x0000, /* R8417 */ + 0x0000, /* R8418 */ + 0x0000, /* R8419 */ + 0x0000, /* R8420 */ + 0x0000, /* R8421 */ + 0x0000, /* R8422 */ + 0x0000, /* R8423 */ + 0x0000, /* R8424 */ + 0x0000, /* R8425 */ + 0x0000, /* R8426 */ + 0x0000, /* R8427 */ + 0x0000, /* R8428 */ + 0x0000, /* R8429 */ + 0x0000, /* R8430 */ + 0x0000, /* R8431 */ + 0x0000, /* R8432 */ + 0x0000, /* R8433 */ + 0x0000, /* R8434 */ + 0x0000, /* R8435 */ + 0x0000, /* R8436 */ + 0x0000, /* R8437 */ + 0x0000, /* R8438 */ + 0x0000, /* R8439 */ + 0x0000, /* R8440 */ + 0x0000, /* R8441 */ + 0x0000, /* R8442 */ + 0x0000, /* R8443 */ + 0x0000, /* R8444 */ + 0x0000, /* R8445 */ + 0x0000, /* R8446 */ + 0x0000, /* R8447 */ + 0x0000, /* R8448 */ + 0x0000, /* R8449 */ + 0x0000, /* R8450 */ + 0x0000, /* R8451 */ + 0x0000, /* R8452 */ + 0x0000, /* R8453 */ + 0x0000, /* R8454 */ + 0x0000, /* R8455 */ + 0x0000, /* R8456 */ + 0x0000, /* R8457 */ + 0x0000, /* R8458 */ + 0x0000, /* R8459 */ + 0x0000, /* R8460 */ + 0x0000, /* R8461 */ + 0x0000, /* R8462 */ + 0x0000, /* R8463 */ + 0x0000, /* R8464 */ + 0x0000, /* R8465 */ + 0x0000, /* R8466 */ + 0x0000, /* R8467 */ + 0x0000, /* R8468 */ + 0x0000, /* R8469 */ + 0x0000, /* R8470 */ + 0x0000, /* R8471 */ + 0x0000, /* R8472 */ + 0x0000, /* R8473 */ + 0x0000, /* R8474 */ + 0x0000, /* R8475 */ + 0x0000, /* R8476 */ + 0x0000, /* R8477 */ + 0x0000, /* R8478 */ + 0x0000, /* R8479 */ + 0x0000, /* R8480 */ + 0x0000, /* R8481 */ + 0x0000, /* R8482 */ + 0x0000, /* R8483 */ + 0x0000, /* R8484 */ + 0x0000, /* R8485 */ + 0x0000, /* R8486 */ + 0x0000, /* R8487 */ + 0x0000, /* R8488 */ + 0x0000, /* R8489 */ + 0x0000, /* R8490 */ + 0x0000, /* R8491 */ + 0x0000, /* R8492 */ + 0x0000, /* R8493 */ + 0x0000, /* R8494 */ + 0x0000, /* R8495 */ + 0x0000, /* R8496 */ + 0x0000, /* R8497 */ + 0x0000, /* R8498 */ + 0x0000, /* R8499 */ + 0x0000, /* R8500 */ + 0x0000, /* R8501 */ + 0x0000, /* R8502 */ + 0x0000, /* R8503 */ + 0x0000, /* R8504 */ + 0x0000, /* R8505 */ + 0x0000, /* R8506 */ + 0x0000, /* R8507 */ + 0x0000, /* R8508 */ + 0x0000, /* R8509 */ + 0x0000, /* R8510 */ + 0x0000, /* R8511 */ + 0x0000, /* R8512 */ + 0x0000, /* R8513 */ + 0x0000, /* R8514 */ + 0x0000, /* R8515 */ + 0x0000, /* R8516 */ + 0x0000, /* R8517 */ + 0x0000, /* R8518 */ + 0x0000, /* R8519 */ + 0x0000, /* R8520 */ + 0x0000, /* R8521 */ + 0x0000, /* R8522 */ + 0x0000, /* R8523 */ + 0x0000, /* R8524 */ + 0x0000, /* R8525 */ + 0x0000, /* R8526 */ + 0x0000, /* R8527 */ + 0x0000, /* R8528 */ + 0x0000, /* R8529 */ + 0x0000, /* R8530 */ + 0x0000, /* R8531 */ + 0x0000, /* R8532 */ + 0x0000, /* R8533 */ + 0x0000, /* R8534 */ + 0x0000, /* R8535 */ + 0x0000, /* R8536 */ + 0x0000, /* R8537 */ + 0x0000, /* R8538 */ + 0x0000, /* R8539 */ + 0x0000, /* R8540 */ + 0x0000, /* R8541 */ + 0x0000, /* R8542 */ + 0x0000, /* R8543 */ + 0x0000, /* R8544 */ + 0x0000, /* R8545 */ + 0x0000, /* R8546 */ + 0x0000, /* R8547 */ + 0x0000, /* R8548 */ + 0x0000, /* R8549 */ + 0x0000, /* R8550 */ + 0x0000, /* R8551 */ + 0x0000, /* R8552 */ + 0x0000, /* R8553 */ + 0x0000, /* R8554 */ + 0x0000, /* R8555 */ + 0x0000, /* R8556 */ + 0x0000, /* R8557 */ + 0x0000, /* R8558 */ + 0x0000, /* R8559 */ + 0x0000, /* R8560 */ + 0x0000, /* R8561 */ + 0x0000, /* R8562 */ + 0x0000, /* R8563 */ + 0x0000, /* R8564 */ + 0x0000, /* R8565 */ + 0x0000, /* R8566 */ + 0x0000, /* R8567 */ + 0x0000, /* R8568 */ + 0x0000, /* R8569 */ + 0x0000, /* R8570 */ + 0x0000, /* R8571 */ + 0x0000, /* R8572 */ + 0x0000, /* R8573 */ + 0x0000, /* R8574 */ + 0x0000, /* R8575 */ + 0x0000, /* R8576 */ + 0x0000, /* R8577 */ + 0x0000, /* R8578 */ + 0x0000, /* R8579 */ + 0x0000, /* R8580 */ + 0x0000, /* R8581 */ + 0x0000, /* R8582 */ + 0x0000, /* R8583 */ + 0x0000, /* R8584 */ + 0x0000, /* R8585 */ + 0x0000, /* R8586 */ + 0x0000, /* R8587 */ + 0x0000, /* R8588 */ + 0x0000, /* R8589 */ + 0x0000, /* R8590 */ + 0x0000, /* R8591 */ + 0x0000, /* R8592 */ + 0x0000, /* R8593 */ + 0x0000, /* R8594 */ + 0x0000, /* R8595 */ + 0x0000, /* R8596 */ + 0x0000, /* R8597 */ + 0x0000, /* R8598 */ + 0x0000, /* R8599 */ + 0x0000, /* R8600 */ + 0x0000, /* R8601 */ + 0x0000, /* R8602 */ + 0x0000, /* R8603 */ + 0x0000, /* R8604 */ + 0x0000, /* R8605 */ + 0x0000, /* R8606 */ + 0x0000, /* R8607 */ + 0x0000, /* R8608 */ + 0x0000, /* R8609 */ + 0x0000, /* R8610 */ + 0x0000, /* R8611 */ + 0x0000, /* R8612 */ + 0x0000, /* R8613 */ + 0x0000, /* R8614 */ + 0x0000, /* R8615 */ + 0x0000, /* R8616 */ + 0x0000, /* R8617 */ + 0x0000, /* R8618 */ + 0x0000, /* R8619 */ + 0x0000, /* R8620 */ + 0x0000, /* R8621 */ + 0x0000, /* R8622 */ + 0x0000, /* R8623 */ + 0x0000, /* R8624 */ + 0x0000, /* R8625 */ + 0x0000, /* R8626 */ + 0x0000, /* R8627 */ + 0x0000, /* R8628 */ + 0x0000, /* R8629 */ + 0x0000, /* R8630 */ + 0x0000, /* R8631 */ + 0x0000, /* R8632 */ + 0x0000, /* R8633 */ + 0x0000, /* R8634 */ + 0x0000, /* R8635 */ + 0x0000, /* R8636 */ + 0x0000, /* R8637 */ + 0x0000, /* R8638 */ + 0x0000, /* R8639 */ + 0x0000, /* R8640 */ + 0x0000, /* R8641 */ + 0x0000, /* R8642 */ + 0x0000, /* R8643 */ + 0x0000, /* R8644 */ + 0x0000, /* R8645 */ + 0x0000, /* R8646 */ + 0x0000, /* R8647 */ + 0x0000, /* R8648 */ + 0x0000, /* R8649 */ + 0x0000, /* R8650 */ + 0x0000, /* R8651 */ + 0x0000, /* R8652 */ + 0x0000, /* R8653 */ + 0x0000, /* R8654 */ + 0x0000, /* R8655 */ + 0x0000, /* R8656 */ + 0x0000, /* R8657 */ + 0x0000, /* R8658 */ + 0x0000, /* R8659 */ + 0x0000, /* R8660 */ + 0x0000, /* R8661 */ + 0x0000, /* R8662 */ + 0x0000, /* R8663 */ + 0x0000, /* R8664 */ + 0x0000, /* R8665 */ + 0x0000, /* R8666 */ + 0x0000, /* R8667 */ + 0x0000, /* R8668 */ + 0x0000, /* R8669 */ + 0x0000, /* R8670 */ + 0x0000, /* R8671 */ + 0x0000, /* R8672 */ + 0x0000, /* R8673 */ + 0x0000, /* R8674 */ + 0x0000, /* R8675 */ + 0x0000, /* R8676 */ + 0x0000, /* R8677 */ + 0x0000, /* R8678 */ + 0x0000, /* R8679 */ + 0x0000, /* R8680 */ + 0x0000, /* R8681 */ + 0x0000, /* R8682 */ + 0x0000, /* R8683 */ + 0x0000, /* R8684 */ + 0x0000, /* R8685 */ + 0x0000, /* R8686 */ + 0x0000, /* R8687 */ + 0x0000, /* R8688 */ + 0x0000, /* R8689 */ + 0x0000, /* R8690 */ + 0x0000, /* R8691 */ + 0x0000, /* R8692 */ + 0x0000, /* R8693 */ + 0x0000, /* R8694 */ + 0x0000, /* R8695 */ + 0x0000, /* R8696 */ + 0x0000, /* R8697 */ + 0x0000, /* R8698 */ + 0x0000, /* R8699 */ + 0x0000, /* R8700 */ + 0x0000, /* R8701 */ + 0x0000, /* R8702 */ + 0x0000, /* R8703 */ + 0x0000, /* R8704 */ + 0x0000, /* R8705 */ + 0x0000, /* R8706 */ + 0x0000, /* R8707 */ + 0x0000, /* R8708 */ + 0x0000, /* R8709 */ + 0x0000, /* R8710 */ + 0x0000, /* R8711 */ + 0x0000, /* R8712 */ + 0x0000, /* R8713 */ + 0x0000, /* R8714 */ + 0x0000, /* R8715 */ + 0x0000, /* R8716 */ + 0x0000, /* R8717 */ + 0x0000, /* R8718 */ + 0x0000, /* R8719 */ + 0x0000, /* R8720 */ + 0x0000, /* R8721 */ + 0x0000, /* R8722 */ + 0x0000, /* R8723 */ + 0x0000, /* R8724 */ + 0x0000, /* R8725 */ + 0x0000, /* R8726 */ + 0x0000, /* R8727 */ + 0x0000, /* R8728 */ + 0x0000, /* R8729 */ + 0x0000, /* R8730 */ + 0x0000, /* R8731 */ + 0x0000, /* R8732 */ + 0x0000, /* R8733 */ + 0x0000, /* R8734 */ + 0x0000, /* R8735 */ + 0x0000, /* R8736 */ + 0x0000, /* R8737 */ + 0x0000, /* R8738 */ + 0x0000, /* R8739 */ + 0x0000, /* R8740 */ + 0x0000, /* R8741 */ + 0x0000, /* R8742 */ + 0x0000, /* R8743 */ + 0x0000, /* R8744 */ + 0x0000, /* R8745 */ + 0x0000, /* R8746 */ + 0x0000, /* R8747 */ + 0x0000, /* R8748 */ + 0x0000, /* R8749 */ + 0x0000, /* R8750 */ + 0x0000, /* R8751 */ + 0x0000, /* R8752 */ + 0x0000, /* R8753 */ + 0x0000, /* R8754 */ + 0x0000, /* R8755 */ + 0x0000, /* R8756 */ + 0x0000, /* R8757 */ + 0x0000, /* R8758 */ + 0x0000, /* R8759 */ + 0x0000, /* R8760 */ + 0x0000, /* R8761 */ + 0x0000, /* R8762 */ + 0x0000, /* R8763 */ + 0x0000, /* R8764 */ + 0x0000, /* R8765 */ + 0x0000, /* R8766 */ + 0x0000, /* R8767 */ + 0x0000, /* R8768 */ + 0x0000, /* R8769 */ + 0x0000, /* R8770 */ + 0x0000, /* R8771 */ + 0x0000, /* R8772 */ + 0x0000, /* R8773 */ + 0x0000, /* R8774 */ + 0x0000, /* R8775 */ + 0x0000, /* R8776 */ + 0x0000, /* R8777 */ + 0x0000, /* R8778 */ + 0x0000, /* R8779 */ + 0x0000, /* R8780 */ + 0x0000, /* R8781 */ + 0x0000, /* R8782 */ + 0x0000, /* R8783 */ + 0x0000, /* R8784 */ + 0x0000, /* R8785 */ + 0x0000, /* R8786 */ + 0x0000, /* R8787 */ + 0x0000, /* R8788 */ + 0x0000, /* R8789 */ + 0x0000, /* R8790 */ + 0x0000, /* R8791 */ + 0x0000, /* R8792 */ + 0x0000, /* R8793 */ + 0x0000, /* R8794 */ + 0x0000, /* R8795 */ + 0x0000, /* R8796 */ + 0x0000, /* R8797 */ + 0x0000, /* R8798 */ + 0x0000, /* R8799 */ + 0x0000, /* R8800 */ + 0x0000, /* R8801 */ + 0x0000, /* R8802 */ + 0x0000, /* R8803 */ + 0x0000, /* R8804 */ + 0x0000, /* R8805 */ + 0x0000, /* R8806 */ + 0x0000, /* R8807 */ + 0x0000, /* R8808 */ + 0x0000, /* R8809 */ + 0x0000, /* R8810 */ + 0x0000, /* R8811 */ + 0x0000, /* R8812 */ + 0x0000, /* R8813 */ + 0x0000, /* R8814 */ + 0x0000, /* R8815 */ + 0x0000, /* R8816 */ + 0x0000, /* R8817 */ + 0x0000, /* R8818 */ + 0x0000, /* R8819 */ + 0x0000, /* R8820 */ + 0x0000, /* R8821 */ + 0x0000, /* R8822 */ + 0x0000, /* R8823 */ + 0x0000, /* R8824 */ + 0x0000, /* R8825 */ + 0x0000, /* R8826 */ + 0x0000, /* R8827 */ + 0x0000, /* R8828 */ + 0x0000, /* R8829 */ + 0x0000, /* R8830 */ + 0x0000, /* R8831 */ + 0x0000, /* R8832 */ + 0x0000, /* R8833 */ + 0x0000, /* R8834 */ + 0x0000, /* R8835 */ + 0x0000, /* R8836 */ + 0x0000, /* R8837 */ + 0x0000, /* R8838 */ + 0x0000, /* R8839 */ + 0x0000, /* R8840 */ + 0x0000, /* R8841 */ + 0x0000, /* R8842 */ + 0x0000, /* R8843 */ + 0x0000, /* R8844 */ + 0x0000, /* R8845 */ + 0x0000, /* R8846 */ + 0x0000, /* R8847 */ + 0x0000, /* R8848 */ + 0x0000, /* R8849 */ + 0x0000, /* R8850 */ + 0x0000, /* R8851 */ + 0x0000, /* R8852 */ + 0x0000, /* R8853 */ + 0x0000, /* R8854 */ + 0x0000, /* R8855 */ + 0x0000, /* R8856 */ + 0x0000, /* R8857 */ + 0x0000, /* R8858 */ + 0x0000, /* R8859 */ + 0x0000, /* R8860 */ + 0x0000, /* R8861 */ + 0x0000, /* R8862 */ + 0x0000, /* R8863 */ + 0x0000, /* R8864 */ + 0x0000, /* R8865 */ + 0x0000, /* R8866 */ + 0x0000, /* R8867 */ + 0x0000, /* R8868 */ + 0x0000, /* R8869 */ + 0x0000, /* R8870 */ + 0x0000, /* R8871 */ + 0x0000, /* R8872 */ + 0x0000, /* R8873 */ + 0x0000, /* R8874 */ + 0x0000, /* R8875 */ + 0x0000, /* R8876 */ + 0x0000, /* R8877 */ + 0x0000, /* R8878 */ + 0x0000, /* R8879 */ + 0x0000, /* R8880 */ + 0x0000, /* R8881 */ + 0x0000, /* R8882 */ + 0x0000, /* R8883 */ + 0x0000, /* R8884 */ + 0x0000, /* R8885 */ + 0x0000, /* R8886 */ + 0x0000, /* R8887 */ + 0x0000, /* R8888 */ + 0x0000, /* R8889 */ + 0x0000, /* R8890 */ + 0x0000, /* R8891 */ + 0x0000, /* R8892 */ + 0x0000, /* R8893 */ + 0x0000, /* R8894 */ + 0x0000, /* R8895 */ + 0x0000, /* R8896 */ + 0x0000, /* R8897 */ + 0x0000, /* R8898 */ + 0x0000, /* R8899 */ + 0x0000, /* R8900 */ + 0x0000, /* R8901 */ + 0x0000, /* R8902 */ + 0x0000, /* R8903 */ + 0x0000, /* R8904 */ + 0x0000, /* R8905 */ + 0x0000, /* R8906 */ + 0x0000, /* R8907 */ + 0x0000, /* R8908 */ + 0x0000, /* R8909 */ + 0x0000, /* R8910 */ + 0x0000, /* R8911 */ + 0x0000, /* R8912 */ + 0x0000, /* R8913 */ + 0x0000, /* R8914 */ + 0x0000, /* R8915 */ + 0x0000, /* R8916 */ + 0x0000, /* R8917 */ + 0x0000, /* R8918 */ + 0x0000, /* R8919 */ + 0x0000, /* R8920 */ + 0x0000, /* R8921 */ + 0x0000, /* R8922 */ + 0x0000, /* R8923 */ + 0x0000, /* R8924 */ + 0x0000, /* R8925 */ + 0x0000, /* R8926 */ + 0x0000, /* R8927 */ + 0x0000, /* R8928 */ + 0x0000, /* R8929 */ + 0x0000, /* R8930 */ + 0x0000, /* R8931 */ + 0x0000, /* R8932 */ + 0x0000, /* R8933 */ + 0x0000, /* R8934 */ + 0x0000, /* R8935 */ + 0x0000, /* R8936 */ + 0x0000, /* R8937 */ + 0x0000, /* R8938 */ + 0x0000, /* R8939 */ + 0x0000, /* R8940 */ + 0x0000, /* R8941 */ + 0x0000, /* R8942 */ + 0x0000, /* R8943 */ + 0x0000, /* R8944 */ + 0x0000, /* R8945 */ + 0x0000, /* R8946 */ + 0x0000, /* R8947 */ + 0x0000, /* R8948 */ + 0x0000, /* R8949 */ + 0x0000, /* R8950 */ + 0x0000, /* R8951 */ + 0x0000, /* R8952 */ + 0x0000, /* R8953 */ + 0x0000, /* R8954 */ + 0x0000, /* R8955 */ + 0x0000, /* R8956 */ + 0x0000, /* R8957 */ + 0x0000, /* R8958 */ + 0x0000, /* R8959 */ + 0x0000, /* R8960 */ + 0x0000, /* R8961 */ + 0x0000, /* R8962 */ + 0x0000, /* R8963 */ + 0x0000, /* R8964 */ + 0x0000, /* R8965 */ + 0x0000, /* R8966 */ + 0x0000, /* R8967 */ + 0x0000, /* R8968 */ + 0x0000, /* R8969 */ + 0x0000, /* R8970 */ + 0x0000, /* R8971 */ + 0x0000, /* R8972 */ + 0x0000, /* R8973 */ + 0x0000, /* R8974 */ + 0x0000, /* R8975 */ + 0x0000, /* R8976 */ + 0x0000, /* R8977 */ + 0x0000, /* R8978 */ + 0x0000, /* R8979 */ + 0x0000, /* R8980 */ + 0x0000, /* R8981 */ + 0x0000, /* R8982 */ + 0x0000, /* R8983 */ + 0x0000, /* R8984 */ + 0x0000, /* R8985 */ + 0x0000, /* R8986 */ + 0x0000, /* R8987 */ + 0x0000, /* R8988 */ + 0x0000, /* R8989 */ + 0x0000, /* R8990 */ + 0x0000, /* R8991 */ + 0x0000, /* R8992 */ + 0x0000, /* R8993 */ + 0x0000, /* R8994 */ + 0x0000, /* R8995 */ + 0x0000, /* R8996 */ + 0x0000, /* R8997 */ + 0x0000, /* R8998 */ + 0x0000, /* R8999 */ + 0x0000, /* R9000 */ + 0x0000, /* R9001 */ + 0x0000, /* R9002 */ + 0x0000, /* R9003 */ + 0x0000, /* R9004 */ + 0x0000, /* R9005 */ + 0x0000, /* R9006 */ + 0x0000, /* R9007 */ + 0x0000, /* R9008 */ + 0x0000, /* R9009 */ + 0x0000, /* R9010 */ + 0x0000, /* R9011 */ + 0x0000, /* R9012 */ + 0x0000, /* R9013 */ + 0x0000, /* R9014 */ + 0x0000, /* R9015 */ + 0x0000, /* R9016 */ + 0x0000, /* R9017 */ + 0x0000, /* R9018 */ + 0x0000, /* R9019 */ + 0x0000, /* R9020 */ + 0x0000, /* R9021 */ + 0x0000, /* R9022 */ + 0x0000, /* R9023 */ + 0x0000, /* R9024 */ + 0x0000, /* R9025 */ + 0x0000, /* R9026 */ + 0x0000, /* R9027 */ + 0x0000, /* R9028 */ + 0x0000, /* R9029 */ + 0x0000, /* R9030 */ + 0x0000, /* R9031 */ + 0x0000, /* R9032 */ + 0x0000, /* R9033 */ + 0x0000, /* R9034 */ + 0x0000, /* R9035 */ + 0x0000, /* R9036 */ + 0x0000, /* R9037 */ + 0x0000, /* R9038 */ + 0x0000, /* R9039 */ + 0x0000, /* R9040 */ + 0x0000, /* R9041 */ + 0x0000, /* R9042 */ + 0x0000, /* R9043 */ + 0x0000, /* R9044 */ + 0x0000, /* R9045 */ + 0x0000, /* R9046 */ + 0x0000, /* R9047 */ + 0x0000, /* R9048 */ + 0x0000, /* R9049 */ + 0x0000, /* R9050 */ + 0x0000, /* R9051 */ + 0x0000, /* R9052 */ + 0x0000, /* R9053 */ + 0x0000, /* R9054 */ + 0x0000, /* R9055 */ + 0x0000, /* R9056 */ + 0x0000, /* R9057 */ + 0x0000, /* R9058 */ + 0x0000, /* R9059 */ + 0x0000, /* R9060 */ + 0x0000, /* R9061 */ + 0x0000, /* R9062 */ + 0x0000, /* R9063 */ + 0x0000, /* R9064 */ + 0x0000, /* R9065 */ + 0x0000, /* R9066 */ + 0x0000, /* R9067 */ + 0x0000, /* R9068 */ + 0x0000, /* R9069 */ + 0x0000, /* R9070 */ + 0x0000, /* R9071 */ + 0x0000, /* R9072 */ + 0x0000, /* R9073 */ + 0x0000, /* R9074 */ + 0x0000, /* R9075 */ + 0x0000, /* R9076 */ + 0x0000, /* R9077 */ + 0x0000, /* R9078 */ + 0x0000, /* R9079 */ + 0x0000, /* R9080 */ + 0x0000, /* R9081 */ + 0x0000, /* R9082 */ + 0x0000, /* R9083 */ + 0x0000, /* R9084 */ + 0x0000, /* R9085 */ + 0x0000, /* R9086 */ + 0x0000, /* R9087 */ + 0x0000, /* R9088 */ + 0x0000, /* R9089 */ + 0x0000, /* R9090 */ + 0x0000, /* R9091 */ + 0x0000, /* R9092 */ + 0x0000, /* R9093 */ + 0x0000, /* R9094 */ + 0x0000, /* R9095 */ + 0x0000, /* R9096 */ + 0x0000, /* R9097 */ + 0x0000, /* R9098 */ + 0x0000, /* R9099 */ + 0x0000, /* R9100 */ + 0x0000, /* R9101 */ + 0x0000, /* R9102 */ + 0x0000, /* R9103 */ + 0x0000, /* R9104 */ + 0x0000, /* R9105 */ + 0x0000, /* R9106 */ + 0x0000, /* R9107 */ + 0x0000, /* R9108 */ + 0x0000, /* R9109 */ + 0x0000, /* R9110 */ + 0x0000, /* R9111 */ + 0x0000, /* R9112 */ + 0x0000, /* R9113 */ + 0x0000, /* R9114 */ + 0x0000, /* R9115 */ + 0x0000, /* R9116 */ + 0x0000, /* R9117 */ + 0x0000, /* R9118 */ + 0x0000, /* R9119 */ + 0x0000, /* R9120 */ + 0x0000, /* R9121 */ + 0x0000, /* R9122 */ + 0x0000, /* R9123 */ + 0x0000, /* R9124 */ + 0x0000, /* R9125 */ + 0x0000, /* R9126 */ + 0x0000, /* R9127 */ + 0x0000, /* R9128 */ + 0x0000, /* R9129 */ + 0x0000, /* R9130 */ + 0x0000, /* R9131 */ + 0x0000, /* R9132 */ + 0x0000, /* R9133 */ + 0x0000, /* R9134 */ + 0x0000, /* R9135 */ + 0x0000, /* R9136 */ + 0x0000, /* R9137 */ + 0x0000, /* R9138 */ + 0x0000, /* R9139 */ + 0x0000, /* R9140 */ + 0x0000, /* R9141 */ + 0x0000, /* R9142 */ + 0x0000, /* R9143 */ + 0x0000, /* R9144 */ + 0x0000, /* R9145 */ + 0x0000, /* R9146 */ + 0x0000, /* R9147 */ + 0x0000, /* R9148 */ + 0x0000, /* R9149 */ + 0x0000, /* R9150 */ + 0x0000, /* R9151 */ + 0x0000, /* R9152 */ + 0x0000, /* R9153 */ + 0x0000, /* R9154 */ + 0x0000, /* R9155 */ + 0x0000, /* R9156 */ + 0x0000, /* R9157 */ + 0x0000, /* R9158 */ + 0x0000, /* R9159 */ + 0x0000, /* R9160 */ + 0x0000, /* R9161 */ + 0x0000, /* R9162 */ + 0x0000, /* R9163 */ + 0x0000, /* R9164 */ + 0x0000, /* R9165 */ + 0x0000, /* R9166 */ + 0x0000, /* R9167 */ + 0x0000, /* R9168 */ + 0x0000, /* R9169 */ + 0x0000, /* R9170 */ + 0x0000, /* R9171 */ + 0x0000, /* R9172 */ + 0x0000, /* R9173 */ + 0x0000, /* R9174 */ + 0x0000, /* R9175 */ + 0x0000, /* R9176 */ + 0x0000, /* R9177 */ + 0x0000, /* R9178 */ + 0x0000, /* R9179 */ + 0x0000, /* R9180 */ + 0x0000, /* R9181 */ + 0x0000, /* R9182 */ + 0x0000, /* R9183 */ + 0x0000, /* R9184 */ + 0x0000, /* R9185 */ + 0x0000, /* R9186 */ + 0x0000, /* R9187 */ + 0x0000, /* R9188 */ + 0x0000, /* R9189 */ + 0x0000, /* R9190 */ + 0x0000, /* R9191 */ + 0x0000, /* R9192 */ + 0x0000, /* R9193 */ + 0x0000, /* R9194 */ + 0x0000, /* R9195 */ + 0x0000, /* R9196 */ + 0x0000, /* R9197 */ + 0x0000, /* R9198 */ + 0x0000, /* R9199 */ + 0x0000, /* R9200 */ + 0x0000, /* R9201 */ + 0x0000, /* R9202 */ + 0x0000, /* R9203 */ + 0x0000, /* R9204 */ + 0x0000, /* R9205 */ + 0x0000, /* R9206 */ + 0x0000, /* R9207 */ + 0x0000, /* R9208 */ + 0x0000, /* R9209 */ + 0x0000, /* R9210 */ + 0x0000, /* R9211 */ + 0x0000, /* R9212 */ + 0x0000, /* R9213 */ + 0x0000, /* R9214 */ + 0x0000, /* R9215 */ + 0x0030, /* R9216 - DSP2 Address RAM 2 */ + 0x0000, /* R9217 - DSP2 Address RAM 1 */ + 0x0000, /* R9218 - DSP2 Address RAM 0 */ + 0x0000, /* R9219 */ + 0x0000, /* R9220 */ + 0x0000, /* R9221 */ + 0x0000, /* R9222 */ + 0x0000, /* R9223 */ + 0x0000, /* R9224 */ + 0x0000, /* R9225 */ + 0x0000, /* R9226 */ + 0x0000, /* R9227 */ + 0x0000, /* R9228 */ + 0x0000, /* R9229 */ + 0x0000, /* R9230 */ + 0x0000, /* R9231 */ + 0x0000, /* R9232 */ + 0x0000, /* R9233 */ + 0x0000, /* R9234 */ + 0x0000, /* R9235 */ + 0x0000, /* R9236 */ + 0x0000, /* R9237 */ + 0x0000, /* R9238 */ + 0x0000, /* R9239 */ + 0x0000, /* R9240 */ + 0x0000, /* R9241 */ + 0x0000, /* R9242 */ + 0x0000, /* R9243 */ + 0x0000, /* R9244 */ + 0x0000, /* R9245 */ + 0x0000, /* R9246 */ + 0x0000, /* R9247 */ + 0x0000, /* R9248 */ + 0x0000, /* R9249 */ + 0x0000, /* R9250 */ + 0x0000, /* R9251 */ + 0x0000, /* R9252 */ + 0x0000, /* R9253 */ + 0x0000, /* R9254 */ + 0x0000, /* R9255 */ + 0x0000, /* R9256 */ + 0x0000, /* R9257 */ + 0x0000, /* R9258 */ + 0x0000, /* R9259 */ + 0x0000, /* R9260 */ + 0x0000, /* R9261 */ + 0x0000, /* R9262 */ + 0x0000, /* R9263 */ + 0x0000, /* R9264 */ + 0x0000, /* R9265 */ + 0x0000, /* R9266 */ + 0x0000, /* R9267 */ + 0x0000, /* R9268 */ + 0x0000, /* R9269 */ + 0x0000, /* R9270 */ + 0x0000, /* R9271 */ + 0x0000, /* R9272 */ + 0x0000, /* R9273 */ + 0x0000, /* R9274 */ + 0x0000, /* R9275 */ + 0x0000, /* R9276 */ + 0x0000, /* R9277 */ + 0x0000, /* R9278 */ + 0x0000, /* R9279 */ + 0x0000, /* R9280 */ + 0x0000, /* R9281 */ + 0x0000, /* R9282 */ + 0x0000, /* R9283 */ + 0x0000, /* R9284 */ + 0x0000, /* R9285 */ + 0x0000, /* R9286 */ + 0x0000, /* R9287 */ + 0x0000, /* R9288 */ + 0x0000, /* R9289 */ + 0x0000, /* R9290 */ + 0x0000, /* R9291 */ + 0x0000, /* R9292 */ + 0x0000, /* R9293 */ + 0x0000, /* R9294 */ + 0x0000, /* R9295 */ + 0x0000, /* R9296 */ + 0x0000, /* R9297 */ + 0x0000, /* R9298 */ + 0x0000, /* R9299 */ + 0x0000, /* R9300 */ + 0x0000, /* R9301 */ + 0x0000, /* R9302 */ + 0x0000, /* R9303 */ + 0x0000, /* R9304 */ + 0x0000, /* R9305 */ + 0x0000, /* R9306 */ + 0x0000, /* R9307 */ + 0x0000, /* R9308 */ + 0x0000, /* R9309 */ + 0x0000, /* R9310 */ + 0x0000, /* R9311 */ + 0x0000, /* R9312 */ + 0x0000, /* R9313 */ + 0x0000, /* R9314 */ + 0x0000, /* R9315 */ + 0x0000, /* R9316 */ + 0x0000, /* R9317 */ + 0x0000, /* R9318 */ + 0x0000, /* R9319 */ + 0x0000, /* R9320 */ + 0x0000, /* R9321 */ + 0x0000, /* R9322 */ + 0x0000, /* R9323 */ + 0x0000, /* R9324 */ + 0x0000, /* R9325 */ + 0x0000, /* R9326 */ + 0x0000, /* R9327 */ + 0x0000, /* R9328 */ + 0x0000, /* R9329 */ + 0x0000, /* R9330 */ + 0x0000, /* R9331 */ + 0x0000, /* R9332 */ + 0x0000, /* R9333 */ + 0x0000, /* R9334 */ + 0x0000, /* R9335 */ + 0x0000, /* R9336 */ + 0x0000, /* R9337 */ + 0x0000, /* R9338 */ + 0x0000, /* R9339 */ + 0x0000, /* R9340 */ + 0x0000, /* R9341 */ + 0x0000, /* R9342 */ + 0x0000, /* R9343 */ + 0x0000, /* R9344 */ + 0x0000, /* R9345 */ + 0x0000, /* R9346 */ + 0x0000, /* R9347 */ + 0x0000, /* R9348 */ + 0x0000, /* R9349 */ + 0x0000, /* R9350 */ + 0x0000, /* R9351 */ + 0x0000, /* R9352 */ + 0x0000, /* R9353 */ + 0x0000, /* R9354 */ + 0x0000, /* R9355 */ + 0x0000, /* R9356 */ + 0x0000, /* R9357 */ + 0x0000, /* R9358 */ + 0x0000, /* R9359 */ + 0x0000, /* R9360 */ + 0x0000, /* R9361 */ + 0x0000, /* R9362 */ + 0x0000, /* R9363 */ + 0x0000, /* R9364 */ + 0x0000, /* R9365 */ + 0x0000, /* R9366 */ + 0x0000, /* R9367 */ + 0x0000, /* R9368 */ + 0x0000, /* R9369 */ + 0x0000, /* R9370 */ + 0x0000, /* R9371 */ + 0x0000, /* R9372 */ + 0x0000, /* R9373 */ + 0x0000, /* R9374 */ + 0x0000, /* R9375 */ + 0x0000, /* R9376 */ + 0x0000, /* R9377 */ + 0x0000, /* R9378 */ + 0x0000, /* R9379 */ + 0x0000, /* R9380 */ + 0x0000, /* R9381 */ + 0x0000, /* R9382 */ + 0x0000, /* R9383 */ + 0x0000, /* R9384 */ + 0x0000, /* R9385 */ + 0x0000, /* R9386 */ + 0x0000, /* R9387 */ + 0x0000, /* R9388 */ + 0x0000, /* R9389 */ + 0x0000, /* R9390 */ + 0x0000, /* R9391 */ + 0x0000, /* R9392 */ + 0x0000, /* R9393 */ + 0x0000, /* R9394 */ + 0x0000, /* R9395 */ + 0x0000, /* R9396 */ + 0x0000, /* R9397 */ + 0x0000, /* R9398 */ + 0x0000, /* R9399 */ + 0x0000, /* R9400 */ + 0x0000, /* R9401 */ + 0x0000, /* R9402 */ + 0x0000, /* R9403 */ + 0x0000, /* R9404 */ + 0x0000, /* R9405 */ + 0x0000, /* R9406 */ + 0x0000, /* R9407 */ + 0x0000, /* R9408 */ + 0x0000, /* R9409 */ + 0x0000, /* R9410 */ + 0x0000, /* R9411 */ + 0x0000, /* R9412 */ + 0x0000, /* R9413 */ + 0x0000, /* R9414 */ + 0x0000, /* R9415 */ + 0x0000, /* R9416 */ + 0x0000, /* R9417 */ + 0x0000, /* R9418 */ + 0x0000, /* R9419 */ + 0x0000, /* R9420 */ + 0x0000, /* R9421 */ + 0x0000, /* R9422 */ + 0x0000, /* R9423 */ + 0x0000, /* R9424 */ + 0x0000, /* R9425 */ + 0x0000, /* R9426 */ + 0x0000, /* R9427 */ + 0x0000, /* R9428 */ + 0x0000, /* R9429 */ + 0x0000, /* R9430 */ + 0x0000, /* R9431 */ + 0x0000, /* R9432 */ + 0x0000, /* R9433 */ + 0x0000, /* R9434 */ + 0x0000, /* R9435 */ + 0x0000, /* R9436 */ + 0x0000, /* R9437 */ + 0x0000, /* R9438 */ + 0x0000, /* R9439 */ + 0x0000, /* R9440 */ + 0x0000, /* R9441 */ + 0x0000, /* R9442 */ + 0x0000, /* R9443 */ + 0x0000, /* R9444 */ + 0x0000, /* R9445 */ + 0x0000, /* R9446 */ + 0x0000, /* R9447 */ + 0x0000, /* R9448 */ + 0x0000, /* R9449 */ + 0x0000, /* R9450 */ + 0x0000, /* R9451 */ + 0x0000, /* R9452 */ + 0x0000, /* R9453 */ + 0x0000, /* R9454 */ + 0x0000, /* R9455 */ + 0x0000, /* R9456 */ + 0x0000, /* R9457 */ + 0x0000, /* R9458 */ + 0x0000, /* R9459 */ + 0x0000, /* R9460 */ + 0x0000, /* R9461 */ + 0x0000, /* R9462 */ + 0x0000, /* R9463 */ + 0x0000, /* R9464 */ + 0x0000, /* R9465 */ + 0x0000, /* R9466 */ + 0x0000, /* R9467 */ + 0x0000, /* R9468 */ + 0x0000, /* R9469 */ + 0x0000, /* R9470 */ + 0x0000, /* R9471 */ + 0x0000, /* R9472 */ + 0x0000, /* R9473 */ + 0x0000, /* R9474 */ + 0x0000, /* R9475 */ + 0x0000, /* R9476 */ + 0x0000, /* R9477 */ + 0x0000, /* R9478 */ + 0x0000, /* R9479 */ + 0x0000, /* R9480 */ + 0x0000, /* R9481 */ + 0x0000, /* R9482 */ + 0x0000, /* R9483 */ + 0x0000, /* R9484 */ + 0x0000, /* R9485 */ + 0x0000, /* R9486 */ + 0x0000, /* R9487 */ + 0x0000, /* R9488 */ + 0x0000, /* R9489 */ + 0x0000, /* R9490 */ + 0x0000, /* R9491 */ + 0x0000, /* R9492 */ + 0x0000, /* R9493 */ + 0x0000, /* R9494 */ + 0x0000, /* R9495 */ + 0x0000, /* R9496 */ + 0x0000, /* R9497 */ + 0x0000, /* R9498 */ + 0x0000, /* R9499 */ + 0x0000, /* R9500 */ + 0x0000, /* R9501 */ + 0x0000, /* R9502 */ + 0x0000, /* R9503 */ + 0x0000, /* R9504 */ + 0x0000, /* R9505 */ + 0x0000, /* R9506 */ + 0x0000, /* R9507 */ + 0x0000, /* R9508 */ + 0x0000, /* R9509 */ + 0x0000, /* R9510 */ + 0x0000, /* R9511 */ + 0x0000, /* R9512 */ + 0x0000, /* R9513 */ + 0x0000, /* R9514 */ + 0x0000, /* R9515 */ + 0x0000, /* R9516 */ + 0x0000, /* R9517 */ + 0x0000, /* R9518 */ + 0x0000, /* R9519 */ + 0x0000, /* R9520 */ + 0x0000, /* R9521 */ + 0x0000, /* R9522 */ + 0x0000, /* R9523 */ + 0x0000, /* R9524 */ + 0x0000, /* R9525 */ + 0x0000, /* R9526 */ + 0x0000, /* R9527 */ + 0x0000, /* R9528 */ + 0x0000, /* R9529 */ + 0x0000, /* R9530 */ + 0x0000, /* R9531 */ + 0x0000, /* R9532 */ + 0x0000, /* R9533 */ + 0x0000, /* R9534 */ + 0x0000, /* R9535 */ + 0x0000, /* R9536 */ + 0x0000, /* R9537 */ + 0x0000, /* R9538 */ + 0x0000, /* R9539 */ + 0x0000, /* R9540 */ + 0x0000, /* R9541 */ + 0x0000, /* R9542 */ + 0x0000, /* R9543 */ + 0x0000, /* R9544 */ + 0x0000, /* R9545 */ + 0x0000, /* R9546 */ + 0x0000, /* R9547 */ + 0x0000, /* R9548 */ + 0x0000, /* R9549 */ + 0x0000, /* R9550 */ + 0x0000, /* R9551 */ + 0x0000, /* R9552 */ + 0x0000, /* R9553 */ + 0x0000, /* R9554 */ + 0x0000, /* R9555 */ + 0x0000, /* R9556 */ + 0x0000, /* R9557 */ + 0x0000, /* R9558 */ + 0x0000, /* R9559 */ + 0x0000, /* R9560 */ + 0x0000, /* R9561 */ + 0x0000, /* R9562 */ + 0x0000, /* R9563 */ + 0x0000, /* R9564 */ + 0x0000, /* R9565 */ + 0x0000, /* R9566 */ + 0x0000, /* R9567 */ + 0x0000, /* R9568 */ + 0x0000, /* R9569 */ + 0x0000, /* R9570 */ + 0x0000, /* R9571 */ + 0x0000, /* R9572 */ + 0x0000, /* R9573 */ + 0x0000, /* R9574 */ + 0x0000, /* R9575 */ + 0x0000, /* R9576 */ + 0x0000, /* R9577 */ + 0x0000, /* R9578 */ + 0x0000, /* R9579 */ + 0x0000, /* R9580 */ + 0x0000, /* R9581 */ + 0x0000, /* R9582 */ + 0x0000, /* R9583 */ + 0x0000, /* R9584 */ + 0x0000, /* R9585 */ + 0x0000, /* R9586 */ + 0x0000, /* R9587 */ + 0x0000, /* R9588 */ + 0x0000, /* R9589 */ + 0x0000, /* R9590 */ + 0x0000, /* R9591 */ + 0x0000, /* R9592 */ + 0x0000, /* R9593 */ + 0x0000, /* R9594 */ + 0x0000, /* R9595 */ + 0x0000, /* R9596 */ + 0x0000, /* R9597 */ + 0x0000, /* R9598 */ + 0x0000, /* R9599 */ + 0x0000, /* R9600 */ + 0x0000, /* R9601 */ + 0x0000, /* R9602 */ + 0x0000, /* R9603 */ + 0x0000, /* R9604 */ + 0x0000, /* R9605 */ + 0x0000, /* R9606 */ + 0x0000, /* R9607 */ + 0x0000, /* R9608 */ + 0x0000, /* R9609 */ + 0x0000, /* R9610 */ + 0x0000, /* R9611 */ + 0x0000, /* R9612 */ + 0x0000, /* R9613 */ + 0x0000, /* R9614 */ + 0x0000, /* R9615 */ + 0x0000, /* R9616 */ + 0x0000, /* R9617 */ + 0x0000, /* R9618 */ + 0x0000, /* R9619 */ + 0x0000, /* R9620 */ + 0x0000, /* R9621 */ + 0x0000, /* R9622 */ + 0x0000, /* R9623 */ + 0x0000, /* R9624 */ + 0x0000, /* R9625 */ + 0x0000, /* R9626 */ + 0x0000, /* R9627 */ + 0x0000, /* R9628 */ + 0x0000, /* R9629 */ + 0x0000, /* R9630 */ + 0x0000, /* R9631 */ + 0x0000, /* R9632 */ + 0x0000, /* R9633 */ + 0x0000, /* R9634 */ + 0x0000, /* R9635 */ + 0x0000, /* R9636 */ + 0x0000, /* R9637 */ + 0x0000, /* R9638 */ + 0x0000, /* R9639 */ + 0x0000, /* R9640 */ + 0x0000, /* R9641 */ + 0x0000, /* R9642 */ + 0x0000, /* R9643 */ + 0x0000, /* R9644 */ + 0x0000, /* R9645 */ + 0x0000, /* R9646 */ + 0x0000, /* R9647 */ + 0x0000, /* R9648 */ + 0x0000, /* R9649 */ + 0x0000, /* R9650 */ + 0x0000, /* R9651 */ + 0x0000, /* R9652 */ + 0x0000, /* R9653 */ + 0x0000, /* R9654 */ + 0x0000, /* R9655 */ + 0x0000, /* R9656 */ + 0x0000, /* R9657 */ + 0x0000, /* R9658 */ + 0x0000, /* R9659 */ + 0x0000, /* R9660 */ + 0x0000, /* R9661 */ + 0x0000, /* R9662 */ + 0x0000, /* R9663 */ + 0x0000, /* R9664 */ + 0x0000, /* R9665 */ + 0x0000, /* R9666 */ + 0x0000, /* R9667 */ + 0x0000, /* R9668 */ + 0x0000, /* R9669 */ + 0x0000, /* R9670 */ + 0x0000, /* R9671 */ + 0x0000, /* R9672 */ + 0x0000, /* R9673 */ + 0x0000, /* R9674 */ + 0x0000, /* R9675 */ + 0x0000, /* R9676 */ + 0x0000, /* R9677 */ + 0x0000, /* R9678 */ + 0x0000, /* R9679 */ + 0x0000, /* R9680 */ + 0x0000, /* R9681 */ + 0x0000, /* R9682 */ + 0x0000, /* R9683 */ + 0x0000, /* R9684 */ + 0x0000, /* R9685 */ + 0x0000, /* R9686 */ + 0x0000, /* R9687 */ + 0x0000, /* R9688 */ + 0x0000, /* R9689 */ + 0x0000, /* R9690 */ + 0x0000, /* R9691 */ + 0x0000, /* R9692 */ + 0x0000, /* R9693 */ + 0x0000, /* R9694 */ + 0x0000, /* R9695 */ + 0x0000, /* R9696 */ + 0x0000, /* R9697 */ + 0x0000, /* R9698 */ + 0x0000, /* R9699 */ + 0x0000, /* R9700 */ + 0x0000, /* R9701 */ + 0x0000, /* R9702 */ + 0x0000, /* R9703 */ + 0x0000, /* R9704 */ + 0x0000, /* R9705 */ + 0x0000, /* R9706 */ + 0x0000, /* R9707 */ + 0x0000, /* R9708 */ + 0x0000, /* R9709 */ + 0x0000, /* R9710 */ + 0x0000, /* R9711 */ + 0x0000, /* R9712 */ + 0x0000, /* R9713 */ + 0x0000, /* R9714 */ + 0x0000, /* R9715 */ + 0x0000, /* R9716 */ + 0x0000, /* R9717 */ + 0x0000, /* R9718 */ + 0x0000, /* R9719 */ + 0x0000, /* R9720 */ + 0x0000, /* R9721 */ + 0x0000, /* R9722 */ + 0x0000, /* R9723 */ + 0x0000, /* R9724 */ + 0x0000, /* R9725 */ + 0x0000, /* R9726 */ + 0x0000, /* R9727 */ + 0x0000, /* R9728 */ + 0x0000, /* R9729 */ + 0x0000, /* R9730 */ + 0x0000, /* R9731 */ + 0x0000, /* R9732 */ + 0x0000, /* R9733 */ + 0x0000, /* R9734 */ + 0x0000, /* R9735 */ + 0x0000, /* R9736 */ + 0x0000, /* R9737 */ + 0x0000, /* R9738 */ + 0x0000, /* R9739 */ + 0x0000, /* R9740 */ + 0x0000, /* R9741 */ + 0x0000, /* R9742 */ + 0x0000, /* R9743 */ + 0x0000, /* R9744 */ + 0x0000, /* R9745 */ + 0x0000, /* R9746 */ + 0x0000, /* R9747 */ + 0x0000, /* R9748 */ + 0x0000, /* R9749 */ + 0x0000, /* R9750 */ + 0x0000, /* R9751 */ + 0x0000, /* R9752 */ + 0x0000, /* R9753 */ + 0x0000, /* R9754 */ + 0x0000, /* R9755 */ + 0x0000, /* R9756 */ + 0x0000, /* R9757 */ + 0x0000, /* R9758 */ + 0x0000, /* R9759 */ + 0x0000, /* R9760 */ + 0x0000, /* R9761 */ + 0x0000, /* R9762 */ + 0x0000, /* R9763 */ + 0x0000, /* R9764 */ + 0x0000, /* R9765 */ + 0x0000, /* R9766 */ + 0x0000, /* R9767 */ + 0x0000, /* R9768 */ + 0x0000, /* R9769 */ + 0x0000, /* R9770 */ + 0x0000, /* R9771 */ + 0x0000, /* R9772 */ + 0x0000, /* R9773 */ + 0x0000, /* R9774 */ + 0x0000, /* R9775 */ + 0x0000, /* R9776 */ + 0x0000, /* R9777 */ + 0x0000, /* R9778 */ + 0x0000, /* R9779 */ + 0x0000, /* R9780 */ + 0x0000, /* R9781 */ + 0x0000, /* R9782 */ + 0x0000, /* R9783 */ + 0x0000, /* R9784 */ + 0x0000, /* R9785 */ + 0x0000, /* R9786 */ + 0x0000, /* R9787 */ + 0x0000, /* R9788 */ + 0x0000, /* R9789 */ + 0x0000, /* R9790 */ + 0x0000, /* R9791 */ + 0x0000, /* R9792 */ + 0x0000, /* R9793 */ + 0x0000, /* R9794 */ + 0x0000, /* R9795 */ + 0x0000, /* R9796 */ + 0x0000, /* R9797 */ + 0x0000, /* R9798 */ + 0x0000, /* R9799 */ + 0x0000, /* R9800 */ + 0x0000, /* R9801 */ + 0x0000, /* R9802 */ + 0x0000, /* R9803 */ + 0x0000, /* R9804 */ + 0x0000, /* R9805 */ + 0x0000, /* R9806 */ + 0x0000, /* R9807 */ + 0x0000, /* R9808 */ + 0x0000, /* R9809 */ + 0x0000, /* R9810 */ + 0x0000, /* R9811 */ + 0x0000, /* R9812 */ + 0x0000, /* R9813 */ + 0x0000, /* R9814 */ + 0x0000, /* R9815 */ + 0x0000, /* R9816 */ + 0x0000, /* R9817 */ + 0x0000, /* R9818 */ + 0x0000, /* R9819 */ + 0x0000, /* R9820 */ + 0x0000, /* R9821 */ + 0x0000, /* R9822 */ + 0x0000, /* R9823 */ + 0x0000, /* R9824 */ + 0x0000, /* R9825 */ + 0x0000, /* R9826 */ + 0x0000, /* R9827 */ + 0x0000, /* R9828 */ + 0x0000, /* R9829 */ + 0x0000, /* R9830 */ + 0x0000, /* R9831 */ + 0x0000, /* R9832 */ + 0x0000, /* R9833 */ + 0x0000, /* R9834 */ + 0x0000, /* R9835 */ + 0x0000, /* R9836 */ + 0x0000, /* R9837 */ + 0x0000, /* R9838 */ + 0x0000, /* R9839 */ + 0x0000, /* R9840 */ + 0x0000, /* R9841 */ + 0x0000, /* R9842 */ + 0x0000, /* R9843 */ + 0x0000, /* R9844 */ + 0x0000, /* R9845 */ + 0x0000, /* R9846 */ + 0x0000, /* R9847 */ + 0x0000, /* R9848 */ + 0x0000, /* R9849 */ + 0x0000, /* R9850 */ + 0x0000, /* R9851 */ + 0x0000, /* R9852 */ + 0x0000, /* R9853 */ + 0x0000, /* R9854 */ + 0x0000, /* R9855 */ + 0x0000, /* R9856 */ + 0x0000, /* R9857 */ + 0x0000, /* R9858 */ + 0x0000, /* R9859 */ + 0x0000, /* R9860 */ + 0x0000, /* R9861 */ + 0x0000, /* R9862 */ + 0x0000, /* R9863 */ + 0x0000, /* R9864 */ + 0x0000, /* R9865 */ + 0x0000, /* R9866 */ + 0x0000, /* R9867 */ + 0x0000, /* R9868 */ + 0x0000, /* R9869 */ + 0x0000, /* R9870 */ + 0x0000, /* R9871 */ + 0x0000, /* R9872 */ + 0x0000, /* R9873 */ + 0x0000, /* R9874 */ + 0x0000, /* R9875 */ + 0x0000, /* R9876 */ + 0x0000, /* R9877 */ + 0x0000, /* R9878 */ + 0x0000, /* R9879 */ + 0x0000, /* R9880 */ + 0x0000, /* R9881 */ + 0x0000, /* R9882 */ + 0x0000, /* R9883 */ + 0x0000, /* R9884 */ + 0x0000, /* R9885 */ + 0x0000, /* R9886 */ + 0x0000, /* R9887 */ + 0x0000, /* R9888 */ + 0x0000, /* R9889 */ + 0x0000, /* R9890 */ + 0x0000, /* R9891 */ + 0x0000, /* R9892 */ + 0x0000, /* R9893 */ + 0x0000, /* R9894 */ + 0x0000, /* R9895 */ + 0x0000, /* R9896 */ + 0x0000, /* R9897 */ + 0x0000, /* R9898 */ + 0x0000, /* R9899 */ + 0x0000, /* R9900 */ + 0x0000, /* R9901 */ + 0x0000, /* R9902 */ + 0x0000, /* R9903 */ + 0x0000, /* R9904 */ + 0x0000, /* R9905 */ + 0x0000, /* R9906 */ + 0x0000, /* R9907 */ + 0x0000, /* R9908 */ + 0x0000, /* R9909 */ + 0x0000, /* R9910 */ + 0x0000, /* R9911 */ + 0x0000, /* R9912 */ + 0x0000, /* R9913 */ + 0x0000, /* R9914 */ + 0x0000, /* R9915 */ + 0x0000, /* R9916 */ + 0x0000, /* R9917 */ + 0x0000, /* R9918 */ + 0x0000, /* R9919 */ + 0x0000, /* R9920 */ + 0x0000, /* R9921 */ + 0x0000, /* R9922 */ + 0x0000, /* R9923 */ + 0x0000, /* R9924 */ + 0x0000, /* R9925 */ + 0x0000, /* R9926 */ + 0x0000, /* R9927 */ + 0x0000, /* R9928 */ + 0x0000, /* R9929 */ + 0x0000, /* R9930 */ + 0x0000, /* R9931 */ + 0x0000, /* R9932 */ + 0x0000, /* R9933 */ + 0x0000, /* R9934 */ + 0x0000, /* R9935 */ + 0x0000, /* R9936 */ + 0x0000, /* R9937 */ + 0x0000, /* R9938 */ + 0x0000, /* R9939 */ + 0x0000, /* R9940 */ + 0x0000, /* R9941 */ + 0x0000, /* R9942 */ + 0x0000, /* R9943 */ + 0x0000, /* R9944 */ + 0x0000, /* R9945 */ + 0x0000, /* R9946 */ + 0x0000, /* R9947 */ + 0x0000, /* R9948 */ + 0x0000, /* R9949 */ + 0x0000, /* R9950 */ + 0x0000, /* R9951 */ + 0x0000, /* R9952 */ + 0x0000, /* R9953 */ + 0x0000, /* R9954 */ + 0x0000, /* R9955 */ + 0x0000, /* R9956 */ + 0x0000, /* R9957 */ + 0x0000, /* R9958 */ + 0x0000, /* R9959 */ + 0x0000, /* R9960 */ + 0x0000, /* R9961 */ + 0x0000, /* R9962 */ + 0x0000, /* R9963 */ + 0x0000, /* R9964 */ + 0x0000, /* R9965 */ + 0x0000, /* R9966 */ + 0x0000, /* R9967 */ + 0x0000, /* R9968 */ + 0x0000, /* R9969 */ + 0x0000, /* R9970 */ + 0x0000, /* R9971 */ + 0x0000, /* R9972 */ + 0x0000, /* R9973 */ + 0x0000, /* R9974 */ + 0x0000, /* R9975 */ + 0x0000, /* R9976 */ + 0x0000, /* R9977 */ + 0x0000, /* R9978 */ + 0x0000, /* R9979 */ + 0x0000, /* R9980 */ + 0x0000, /* R9981 */ + 0x0000, /* R9982 */ + 0x0000, /* R9983 */ + 0x0000, /* R9984 */ + 0x0000, /* R9985 */ + 0x0000, /* R9986 */ + 0x0000, /* R9987 */ + 0x0000, /* R9988 */ + 0x0000, /* R9989 */ + 0x0000, /* R9990 */ + 0x0000, /* R9991 */ + 0x0000, /* R9992 */ + 0x0000, /* R9993 */ + 0x0000, /* R9994 */ + 0x0000, /* R9995 */ + 0x0000, /* R9996 */ + 0x0000, /* R9997 */ + 0x0000, /* R9998 */ + 0x0000, /* R9999 */ + 0x0000, /* R10000 */ + 0x0000, /* R10001 */ + 0x0000, /* R10002 */ + 0x0000, /* R10003 */ + 0x0000, /* R10004 */ + 0x0000, /* R10005 */ + 0x0000, /* R10006 */ + 0x0000, /* R10007 */ + 0x0000, /* R10008 */ + 0x0000, /* R10009 */ + 0x0000, /* R10010 */ + 0x0000, /* R10011 */ + 0x0000, /* R10012 */ + 0x0000, /* R10013 */ + 0x0000, /* R10014 */ + 0x0000, /* R10015 */ + 0x0000, /* R10016 */ + 0x0000, /* R10017 */ + 0x0000, /* R10018 */ + 0x0000, /* R10019 */ + 0x0000, /* R10020 */ + 0x0000, /* R10021 */ + 0x0000, /* R10022 */ + 0x0000, /* R10023 */ + 0x0000, /* R10024 */ + 0x0000, /* R10025 */ + 0x0000, /* R10026 */ + 0x0000, /* R10027 */ + 0x0000, /* R10028 */ + 0x0000, /* R10029 */ + 0x0000, /* R10030 */ + 0x0000, /* R10031 */ + 0x0000, /* R10032 */ + 0x0000, /* R10033 */ + 0x0000, /* R10034 */ + 0x0000, /* R10035 */ + 0x0000, /* R10036 */ + 0x0000, /* R10037 */ + 0x0000, /* R10038 */ + 0x0000, /* R10039 */ + 0x0000, /* R10040 */ + 0x0000, /* R10041 */ + 0x0000, /* R10042 */ + 0x0000, /* R10043 */ + 0x0000, /* R10044 */ + 0x0000, /* R10045 */ + 0x0000, /* R10046 */ + 0x0000, /* R10047 */ + 0x0000, /* R10048 */ + 0x0000, /* R10049 */ + 0x0000, /* R10050 */ + 0x0000, /* R10051 */ + 0x0000, /* R10052 */ + 0x0000, /* R10053 */ + 0x0000, /* R10054 */ + 0x0000, /* R10055 */ + 0x0000, /* R10056 */ + 0x0000, /* R10057 */ + 0x0000, /* R10058 */ + 0x0000, /* R10059 */ + 0x0000, /* R10060 */ + 0x0000, /* R10061 */ + 0x0000, /* R10062 */ + 0x0000, /* R10063 */ + 0x0000, /* R10064 */ + 0x0000, /* R10065 */ + 0x0000, /* R10066 */ + 0x0000, /* R10067 */ + 0x0000, /* R10068 */ + 0x0000, /* R10069 */ + 0x0000, /* R10070 */ + 0x0000, /* R10071 */ + 0x0000, /* R10072 */ + 0x0000, /* R10073 */ + 0x0000, /* R10074 */ + 0x0000, /* R10075 */ + 0x0000, /* R10076 */ + 0x0000, /* R10077 */ + 0x0000, /* R10078 */ + 0x0000, /* R10079 */ + 0x0000, /* R10080 */ + 0x0000, /* R10081 */ + 0x0000, /* R10082 */ + 0x0000, /* R10083 */ + 0x0000, /* R10084 */ + 0x0000, /* R10085 */ + 0x0000, /* R10086 */ + 0x0000, /* R10087 */ + 0x0000, /* R10088 */ + 0x0000, /* R10089 */ + 0x0000, /* R10090 */ + 0x0000, /* R10091 */ + 0x0000, /* R10092 */ + 0x0000, /* R10093 */ + 0x0000, /* R10094 */ + 0x0000, /* R10095 */ + 0x0000, /* R10096 */ + 0x0000, /* R10097 */ + 0x0000, /* R10098 */ + 0x0000, /* R10099 */ + 0x0000, /* R10100 */ + 0x0000, /* R10101 */ + 0x0000, /* R10102 */ + 0x0000, /* R10103 */ + 0x0000, /* R10104 */ + 0x0000, /* R10105 */ + 0x0000, /* R10106 */ + 0x0000, /* R10107 */ + 0x0000, /* R10108 */ + 0x0000, /* R10109 */ + 0x0000, /* R10110 */ + 0x0000, /* R10111 */ + 0x0000, /* R10112 */ + 0x0000, /* R10113 */ + 0x0000, /* R10114 */ + 0x0000, /* R10115 */ + 0x0000, /* R10116 */ + 0x0000, /* R10117 */ + 0x0000, /* R10118 */ + 0x0000, /* R10119 */ + 0x0000, /* R10120 */ + 0x0000, /* R10121 */ + 0x0000, /* R10122 */ + 0x0000, /* R10123 */ + 0x0000, /* R10124 */ + 0x0000, /* R10125 */ + 0x0000, /* R10126 */ + 0x0000, /* R10127 */ + 0x0000, /* R10128 */ + 0x0000, /* R10129 */ + 0x0000, /* R10130 */ + 0x0000, /* R10131 */ + 0x0000, /* R10132 */ + 0x0000, /* R10133 */ + 0x0000, /* R10134 */ + 0x0000, /* R10135 */ + 0x0000, /* R10136 */ + 0x0000, /* R10137 */ + 0x0000, /* R10138 */ + 0x0000, /* R10139 */ + 0x0000, /* R10140 */ + 0x0000, /* R10141 */ + 0x0000, /* R10142 */ + 0x0000, /* R10143 */ + 0x0000, /* R10144 */ + 0x0000, /* R10145 */ + 0x0000, /* R10146 */ + 0x0000, /* R10147 */ + 0x0000, /* R10148 */ + 0x0000, /* R10149 */ + 0x0000, /* R10150 */ + 0x0000, /* R10151 */ + 0x0000, /* R10152 */ + 0x0000, /* R10153 */ + 0x0000, /* R10154 */ + 0x0000, /* R10155 */ + 0x0000, /* R10156 */ + 0x0000, /* R10157 */ + 0x0000, /* R10158 */ + 0x0000, /* R10159 */ + 0x0000, /* R10160 */ + 0x0000, /* R10161 */ + 0x0000, /* R10162 */ + 0x0000, /* R10163 */ + 0x0000, /* R10164 */ + 0x0000, /* R10165 */ + 0x0000, /* R10166 */ + 0x0000, /* R10167 */ + 0x0000, /* R10168 */ + 0x0000, /* R10169 */ + 0x0000, /* R10170 */ + 0x0000, /* R10171 */ + 0x0000, /* R10172 */ + 0x0000, /* R10173 */ + 0x0000, /* R10174 */ + 0x0000, /* R10175 */ + 0x0000, /* R10176 */ + 0x0000, /* R10177 */ + 0x0000, /* R10178 */ + 0x0000, /* R10179 */ + 0x0000, /* R10180 */ + 0x0000, /* R10181 */ + 0x0000, /* R10182 */ + 0x0000, /* R10183 */ + 0x0000, /* R10184 */ + 0x0000, /* R10185 */ + 0x0000, /* R10186 */ + 0x0000, /* R10187 */ + 0x0000, /* R10188 */ + 0x0000, /* R10189 */ + 0x0000, /* R10190 */ + 0x0000, /* R10191 */ + 0x0000, /* R10192 */ + 0x0000, /* R10193 */ + 0x0000, /* R10194 */ + 0x0000, /* R10195 */ + 0x0000, /* R10196 */ + 0x0000, /* R10197 */ + 0x0000, /* R10198 */ + 0x0000, /* R10199 */ + 0x0000, /* R10200 */ + 0x0000, /* R10201 */ + 0x0000, /* R10202 */ + 0x0000, /* R10203 */ + 0x0000, /* R10204 */ + 0x0000, /* R10205 */ + 0x0000, /* R10206 */ + 0x0000, /* R10207 */ + 0x0000, /* R10208 */ + 0x0000, /* R10209 */ + 0x0000, /* R10210 */ + 0x0000, /* R10211 */ + 0x0000, /* R10212 */ + 0x0000, /* R10213 */ + 0x0000, /* R10214 */ + 0x0000, /* R10215 */ + 0x0000, /* R10216 */ + 0x0000, /* R10217 */ + 0x0000, /* R10218 */ + 0x0000, /* R10219 */ + 0x0000, /* R10220 */ + 0x0000, /* R10221 */ + 0x0000, /* R10222 */ + 0x0000, /* R10223 */ + 0x0000, /* R10224 */ + 0x0000, /* R10225 */ + 0x0000, /* R10226 */ + 0x0000, /* R10227 */ + 0x0000, /* R10228 */ + 0x0000, /* R10229 */ + 0x0000, /* R10230 */ + 0x0000, /* R10231 */ + 0x0000, /* R10232 */ + 0x0000, /* R10233 */ + 0x0000, /* R10234 */ + 0x0000, /* R10235 */ + 0x0000, /* R10236 */ + 0x0000, /* R10237 */ + 0x0000, /* R10238 */ + 0x0000, /* R10239 */ + 0x0000, /* R10240 */ + 0x0000, /* R10241 */ + 0x0000, /* R10242 */ + 0x0000, /* R10243 */ + 0x0000, /* R10244 */ + 0x0000, /* R10245 */ + 0x0000, /* R10246 */ + 0x0000, /* R10247 */ + 0x0000, /* R10248 */ + 0x0000, /* R10249 */ + 0x0000, /* R10250 */ + 0x0000, /* R10251 */ + 0x0000, /* R10252 */ + 0x0000, /* R10253 */ + 0x0000, /* R10254 */ + 0x0000, /* R10255 */ + 0x0000, /* R10256 */ + 0x0000, /* R10257 */ + 0x0000, /* R10258 */ + 0x0000, /* R10259 */ + 0x0000, /* R10260 */ + 0x0000, /* R10261 */ + 0x0000, /* R10262 */ + 0x0000, /* R10263 */ + 0x0000, /* R10264 */ + 0x0000, /* R10265 */ + 0x0000, /* R10266 */ + 0x0000, /* R10267 */ + 0x0000, /* R10268 */ + 0x0000, /* R10269 */ + 0x0000, /* R10270 */ + 0x0000, /* R10271 */ + 0x0000, /* R10272 */ + 0x0000, /* R10273 */ + 0x0000, /* R10274 */ + 0x0000, /* R10275 */ + 0x0000, /* R10276 */ + 0x0000, /* R10277 */ + 0x0000, /* R10278 */ + 0x0000, /* R10279 */ + 0x0000, /* R10280 */ + 0x0000, /* R10281 */ + 0x0000, /* R10282 */ + 0x0000, /* R10283 */ + 0x0000, /* R10284 */ + 0x0000, /* R10285 */ + 0x0000, /* R10286 */ + 0x0000, /* R10287 */ + 0x0000, /* R10288 */ + 0x0000, /* R10289 */ + 0x0000, /* R10290 */ + 0x0000, /* R10291 */ + 0x0000, /* R10292 */ + 0x0000, /* R10293 */ + 0x0000, /* R10294 */ + 0x0000, /* R10295 */ + 0x0000, /* R10296 */ + 0x0000, /* R10297 */ + 0x0000, /* R10298 */ + 0x0000, /* R10299 */ + 0x0000, /* R10300 */ + 0x0000, /* R10301 */ + 0x0000, /* R10302 */ + 0x0000, /* R10303 */ + 0x0000, /* R10304 */ + 0x0000, /* R10305 */ + 0x0000, /* R10306 */ + 0x0000, /* R10307 */ + 0x0000, /* R10308 */ + 0x0000, /* R10309 */ + 0x0000, /* R10310 */ + 0x0000, /* R10311 */ + 0x0000, /* R10312 */ + 0x0000, /* R10313 */ + 0x0000, /* R10314 */ + 0x0000, /* R10315 */ + 0x0000, /* R10316 */ + 0x0000, /* R10317 */ + 0x0000, /* R10318 */ + 0x0000, /* R10319 */ + 0x0000, /* R10320 */ + 0x0000, /* R10321 */ + 0x0000, /* R10322 */ + 0x0000, /* R10323 */ + 0x0000, /* R10324 */ + 0x0000, /* R10325 */ + 0x0000, /* R10326 */ + 0x0000, /* R10327 */ + 0x0000, /* R10328 */ + 0x0000, /* R10329 */ + 0x0000, /* R10330 */ + 0x0000, /* R10331 */ + 0x0000, /* R10332 */ + 0x0000, /* R10333 */ + 0x0000, /* R10334 */ + 0x0000, /* R10335 */ + 0x0000, /* R10336 */ + 0x0000, /* R10337 */ + 0x0000, /* R10338 */ + 0x0000, /* R10339 */ + 0x0000, /* R10340 */ + 0x0000, /* R10341 */ + 0x0000, /* R10342 */ + 0x0000, /* R10343 */ + 0x0000, /* R10344 */ + 0x0000, /* R10345 */ + 0x0000, /* R10346 */ + 0x0000, /* R10347 */ + 0x0000, /* R10348 */ + 0x0000, /* R10349 */ + 0x0000, /* R10350 */ + 0x0000, /* R10351 */ + 0x0000, /* R10352 */ + 0x0000, /* R10353 */ + 0x0000, /* R10354 */ + 0x0000, /* R10355 */ + 0x0000, /* R10356 */ + 0x0000, /* R10357 */ + 0x0000, /* R10358 */ + 0x0000, /* R10359 */ + 0x0000, /* R10360 */ + 0x0000, /* R10361 */ + 0x0000, /* R10362 */ + 0x0000, /* R10363 */ + 0x0000, /* R10364 */ + 0x0000, /* R10365 */ + 0x0000, /* R10366 */ + 0x0000, /* R10367 */ + 0x0000, /* R10368 */ + 0x0000, /* R10369 */ + 0x0000, /* R10370 */ + 0x0000, /* R10371 */ + 0x0000, /* R10372 */ + 0x0000, /* R10373 */ + 0x0000, /* R10374 */ + 0x0000, /* R10375 */ + 0x0000, /* R10376 */ + 0x0000, /* R10377 */ + 0x0000, /* R10378 */ + 0x0000, /* R10379 */ + 0x0000, /* R10380 */ + 0x0000, /* R10381 */ + 0x0000, /* R10382 */ + 0x0000, /* R10383 */ + 0x0000, /* R10384 */ + 0x0000, /* R10385 */ + 0x0000, /* R10386 */ + 0x0000, /* R10387 */ + 0x0000, /* R10388 */ + 0x0000, /* R10389 */ + 0x0000, /* R10390 */ + 0x0000, /* R10391 */ + 0x0000, /* R10392 */ + 0x0000, /* R10393 */ + 0x0000, /* R10394 */ + 0x0000, /* R10395 */ + 0x0000, /* R10396 */ + 0x0000, /* R10397 */ + 0x0000, /* R10398 */ + 0x0000, /* R10399 */ + 0x0000, /* R10400 */ + 0x0000, /* R10401 */ + 0x0000, /* R10402 */ + 0x0000, /* R10403 */ + 0x0000, /* R10404 */ + 0x0000, /* R10405 */ + 0x0000, /* R10406 */ + 0x0000, /* R10407 */ + 0x0000, /* R10408 */ + 0x0000, /* R10409 */ + 0x0000, /* R10410 */ + 0x0000, /* R10411 */ + 0x0000, /* R10412 */ + 0x0000, /* R10413 */ + 0x0000, /* R10414 */ + 0x0000, /* R10415 */ + 0x0000, /* R10416 */ + 0x0000, /* R10417 */ + 0x0000, /* R10418 */ + 0x0000, /* R10419 */ + 0x0000, /* R10420 */ + 0x0000, /* R10421 */ + 0x0000, /* R10422 */ + 0x0000, /* R10423 */ + 0x0000, /* R10424 */ + 0x0000, /* R10425 */ + 0x0000, /* R10426 */ + 0x0000, /* R10427 */ + 0x0000, /* R10428 */ + 0x0000, /* R10429 */ + 0x0000, /* R10430 */ + 0x0000, /* R10431 */ + 0x0000, /* R10432 */ + 0x0000, /* R10433 */ + 0x0000, /* R10434 */ + 0x0000, /* R10435 */ + 0x0000, /* R10436 */ + 0x0000, /* R10437 */ + 0x0000, /* R10438 */ + 0x0000, /* R10439 */ + 0x0000, /* R10440 */ + 0x0000, /* R10441 */ + 0x0000, /* R10442 */ + 0x0000, /* R10443 */ + 0x0000, /* R10444 */ + 0x0000, /* R10445 */ + 0x0000, /* R10446 */ + 0x0000, /* R10447 */ + 0x0000, /* R10448 */ + 0x0000, /* R10449 */ + 0x0000, /* R10450 */ + 0x0000, /* R10451 */ + 0x0000, /* R10452 */ + 0x0000, /* R10453 */ + 0x0000, /* R10454 */ + 0x0000, /* R10455 */ + 0x0000, /* R10456 */ + 0x0000, /* R10457 */ + 0x0000, /* R10458 */ + 0x0000, /* R10459 */ + 0x0000, /* R10460 */ + 0x0000, /* R10461 */ + 0x0000, /* R10462 */ + 0x0000, /* R10463 */ + 0x0000, /* R10464 */ + 0x0000, /* R10465 */ + 0x0000, /* R10466 */ + 0x0000, /* R10467 */ + 0x0000, /* R10468 */ + 0x0000, /* R10469 */ + 0x0000, /* R10470 */ + 0x0000, /* R10471 */ + 0x0000, /* R10472 */ + 0x0000, /* R10473 */ + 0x0000, /* R10474 */ + 0x0000, /* R10475 */ + 0x0000, /* R10476 */ + 0x0000, /* R10477 */ + 0x0000, /* R10478 */ + 0x0000, /* R10479 */ + 0x0000, /* R10480 */ + 0x0000, /* R10481 */ + 0x0000, /* R10482 */ + 0x0000, /* R10483 */ + 0x0000, /* R10484 */ + 0x0000, /* R10485 */ + 0x0000, /* R10486 */ + 0x0000, /* R10487 */ + 0x0000, /* R10488 */ + 0x0000, /* R10489 */ + 0x0000, /* R10490 */ + 0x0000, /* R10491 */ + 0x0000, /* R10492 */ + 0x0000, /* R10493 */ + 0x0000, /* R10494 */ + 0x0000, /* R10495 */ + 0x0000, /* R10496 */ + 0x0000, /* R10497 */ + 0x0000, /* R10498 */ + 0x0000, /* R10499 */ + 0x0000, /* R10500 */ + 0x0000, /* R10501 */ + 0x0000, /* R10502 */ + 0x0000, /* R10503 */ + 0x0000, /* R10504 */ + 0x0000, /* R10505 */ + 0x0000, /* R10506 */ + 0x0000, /* R10507 */ + 0x0000, /* R10508 */ + 0x0000, /* R10509 */ + 0x0000, /* R10510 */ + 0x0000, /* R10511 */ + 0x0000, /* R10512 */ + 0x0000, /* R10513 */ + 0x0000, /* R10514 */ + 0x0000, /* R10515 */ + 0x0000, /* R10516 */ + 0x0000, /* R10517 */ + 0x0000, /* R10518 */ + 0x0000, /* R10519 */ + 0x0000, /* R10520 */ + 0x0000, /* R10521 */ + 0x0000, /* R10522 */ + 0x0000, /* R10523 */ + 0x0000, /* R10524 */ + 0x0000, /* R10525 */ + 0x0000, /* R10526 */ + 0x0000, /* R10527 */ + 0x0000, /* R10528 */ + 0x0000, /* R10529 */ + 0x0000, /* R10530 */ + 0x0000, /* R10531 */ + 0x0000, /* R10532 */ + 0x0000, /* R10533 */ + 0x0000, /* R10534 */ + 0x0000, /* R10535 */ + 0x0000, /* R10536 */ + 0x0000, /* R10537 */ + 0x0000, /* R10538 */ + 0x0000, /* R10539 */ + 0x0000, /* R10540 */ + 0x0000, /* R10541 */ + 0x0000, /* R10542 */ + 0x0000, /* R10543 */ + 0x0000, /* R10544 */ + 0x0000, /* R10545 */ + 0x0000, /* R10546 */ + 0x0000, /* R10547 */ + 0x0000, /* R10548 */ + 0x0000, /* R10549 */ + 0x0000, /* R10550 */ + 0x0000, /* R10551 */ + 0x0000, /* R10552 */ + 0x0000, /* R10553 */ + 0x0000, /* R10554 */ + 0x0000, /* R10555 */ + 0x0000, /* R10556 */ + 0x0000, /* R10557 */ + 0x0000, /* R10558 */ + 0x0000, /* R10559 */ + 0x0000, /* R10560 */ + 0x0000, /* R10561 */ + 0x0000, /* R10562 */ + 0x0000, /* R10563 */ + 0x0000, /* R10564 */ + 0x0000, /* R10565 */ + 0x0000, /* R10566 */ + 0x0000, /* R10567 */ + 0x0000, /* R10568 */ + 0x0000, /* R10569 */ + 0x0000, /* R10570 */ + 0x0000, /* R10571 */ + 0x0000, /* R10572 */ + 0x0000, /* R10573 */ + 0x0000, /* R10574 */ + 0x0000, /* R10575 */ + 0x0000, /* R10576 */ + 0x0000, /* R10577 */ + 0x0000, /* R10578 */ + 0x0000, /* R10579 */ + 0x0000, /* R10580 */ + 0x0000, /* R10581 */ + 0x0000, /* R10582 */ + 0x0000, /* R10583 */ + 0x0000, /* R10584 */ + 0x0000, /* R10585 */ + 0x0000, /* R10586 */ + 0x0000, /* R10587 */ + 0x0000, /* R10588 */ + 0x0000, /* R10589 */ + 0x0000, /* R10590 */ + 0x0000, /* R10591 */ + 0x0000, /* R10592 */ + 0x0000, /* R10593 */ + 0x0000, /* R10594 */ + 0x0000, /* R10595 */ + 0x0000, /* R10596 */ + 0x0000, /* R10597 */ + 0x0000, /* R10598 */ + 0x0000, /* R10599 */ + 0x0000, /* R10600 */ + 0x0000, /* R10601 */ + 0x0000, /* R10602 */ + 0x0000, /* R10603 */ + 0x0000, /* R10604 */ + 0x0000, /* R10605 */ + 0x0000, /* R10606 */ + 0x0000, /* R10607 */ + 0x0000, /* R10608 */ + 0x0000, /* R10609 */ + 0x0000, /* R10610 */ + 0x0000, /* R10611 */ + 0x0000, /* R10612 */ + 0x0000, /* R10613 */ + 0x0000, /* R10614 */ + 0x0000, /* R10615 */ + 0x0000, /* R10616 */ + 0x0000, /* R10617 */ + 0x0000, /* R10618 */ + 0x0000, /* R10619 */ + 0x0000, /* R10620 */ + 0x0000, /* R10621 */ + 0x0000, /* R10622 */ + 0x0000, /* R10623 */ + 0x0000, /* R10624 */ + 0x0000, /* R10625 */ + 0x0000, /* R10626 */ + 0x0000, /* R10627 */ + 0x0000, /* R10628 */ + 0x0000, /* R10629 */ + 0x0000, /* R10630 */ + 0x0000, /* R10631 */ + 0x0000, /* R10632 */ + 0x0000, /* R10633 */ + 0x0000, /* R10634 */ + 0x0000, /* R10635 */ + 0x0000, /* R10636 */ + 0x0000, /* R10637 */ + 0x0000, /* R10638 */ + 0x0000, /* R10639 */ + 0x0000, /* R10640 */ + 0x0000, /* R10641 */ + 0x0000, /* R10642 */ + 0x0000, /* R10643 */ + 0x0000, /* R10644 */ + 0x0000, /* R10645 */ + 0x0000, /* R10646 */ + 0x0000, /* R10647 */ + 0x0000, /* R10648 */ + 0x0000, /* R10649 */ + 0x0000, /* R10650 */ + 0x0000, /* R10651 */ + 0x0000, /* R10652 */ + 0x0000, /* R10653 */ + 0x0000, /* R10654 */ + 0x0000, /* R10655 */ + 0x0000, /* R10656 */ + 0x0000, /* R10657 */ + 0x0000, /* R10658 */ + 0x0000, /* R10659 */ + 0x0000, /* R10660 */ + 0x0000, /* R10661 */ + 0x0000, /* R10662 */ + 0x0000, /* R10663 */ + 0x0000, /* R10664 */ + 0x0000, /* R10665 */ + 0x0000, /* R10666 */ + 0x0000, /* R10667 */ + 0x0000, /* R10668 */ + 0x0000, /* R10669 */ + 0x0000, /* R10670 */ + 0x0000, /* R10671 */ + 0x0000, /* R10672 */ + 0x0000, /* R10673 */ + 0x0000, /* R10674 */ + 0x0000, /* R10675 */ + 0x0000, /* R10676 */ + 0x0000, /* R10677 */ + 0x0000, /* R10678 */ + 0x0000, /* R10679 */ + 0x0000, /* R10680 */ + 0x0000, /* R10681 */ + 0x0000, /* R10682 */ + 0x0000, /* R10683 */ + 0x0000, /* R10684 */ + 0x0000, /* R10685 */ + 0x0000, /* R10686 */ + 0x0000, /* R10687 */ + 0x0000, /* R10688 */ + 0x0000, /* R10689 */ + 0x0000, /* R10690 */ + 0x0000, /* R10691 */ + 0x0000, /* R10692 */ + 0x0000, /* R10693 */ + 0x0000, /* R10694 */ + 0x0000, /* R10695 */ + 0x0000, /* R10696 */ + 0x0000, /* R10697 */ + 0x0000, /* R10698 */ + 0x0000, /* R10699 */ + 0x0000, /* R10700 */ + 0x0000, /* R10701 */ + 0x0000, /* R10702 */ + 0x0000, /* R10703 */ + 0x0000, /* R10704 */ + 0x0000, /* R10705 */ + 0x0000, /* R10706 */ + 0x0000, /* R10707 */ + 0x0000, /* R10708 */ + 0x0000, /* R10709 */ + 0x0000, /* R10710 */ + 0x0000, /* R10711 */ + 0x0000, /* R10712 */ + 0x0000, /* R10713 */ + 0x0000, /* R10714 */ + 0x0000, /* R10715 */ + 0x0000, /* R10716 */ + 0x0000, /* R10717 */ + 0x0000, /* R10718 */ + 0x0000, /* R10719 */ + 0x0000, /* R10720 */ + 0x0000, /* R10721 */ + 0x0000, /* R10722 */ + 0x0000, /* R10723 */ + 0x0000, /* R10724 */ + 0x0000, /* R10725 */ + 0x0000, /* R10726 */ + 0x0000, /* R10727 */ + 0x0000, /* R10728 */ + 0x0000, /* R10729 */ + 0x0000, /* R10730 */ + 0x0000, /* R10731 */ + 0x0000, /* R10732 */ + 0x0000, /* R10733 */ + 0x0000, /* R10734 */ + 0x0000, /* R10735 */ + 0x0000, /* R10736 */ + 0x0000, /* R10737 */ + 0x0000, /* R10738 */ + 0x0000, /* R10739 */ + 0x0000, /* R10740 */ + 0x0000, /* R10741 */ + 0x0000, /* R10742 */ + 0x0000, /* R10743 */ + 0x0000, /* R10744 */ + 0x0000, /* R10745 */ + 0x0000, /* R10746 */ + 0x0000, /* R10747 */ + 0x0000, /* R10748 */ + 0x0000, /* R10749 */ + 0x0000, /* R10750 */ + 0x0000, /* R10751 */ + 0x0000, /* R10752 */ + 0x0000, /* R10753 */ + 0x0000, /* R10754 */ + 0x0000, /* R10755 */ + 0x0000, /* R10756 */ + 0x0000, /* R10757 */ + 0x0000, /* R10758 */ + 0x0000, /* R10759 */ + 0x0000, /* R10760 */ + 0x0000, /* R10761 */ + 0x0000, /* R10762 */ + 0x0000, /* R10763 */ + 0x0000, /* R10764 */ + 0x0000, /* R10765 */ + 0x0000, /* R10766 */ + 0x0000, /* R10767 */ + 0x0000, /* R10768 */ + 0x0000, /* R10769 */ + 0x0000, /* R10770 */ + 0x0000, /* R10771 */ + 0x0000, /* R10772 */ + 0x0000, /* R10773 */ + 0x0000, /* R10774 */ + 0x0000, /* R10775 */ + 0x0000, /* R10776 */ + 0x0000, /* R10777 */ + 0x0000, /* R10778 */ + 0x0000, /* R10779 */ + 0x0000, /* R10780 */ + 0x0000, /* R10781 */ + 0x0000, /* R10782 */ + 0x0000, /* R10783 */ + 0x0000, /* R10784 */ + 0x0000, /* R10785 */ + 0x0000, /* R10786 */ + 0x0000, /* R10787 */ + 0x0000, /* R10788 */ + 0x0000, /* R10789 */ + 0x0000, /* R10790 */ + 0x0000, /* R10791 */ + 0x0000, /* R10792 */ + 0x0000, /* R10793 */ + 0x0000, /* R10794 */ + 0x0000, /* R10795 */ + 0x0000, /* R10796 */ + 0x0000, /* R10797 */ + 0x0000, /* R10798 */ + 0x0000, /* R10799 */ + 0x0000, /* R10800 */ + 0x0000, /* R10801 */ + 0x0000, /* R10802 */ + 0x0000, /* R10803 */ + 0x0000, /* R10804 */ + 0x0000, /* R10805 */ + 0x0000, /* R10806 */ + 0x0000, /* R10807 */ + 0x0000, /* R10808 */ + 0x0000, /* R10809 */ + 0x0000, /* R10810 */ + 0x0000, /* R10811 */ + 0x0000, /* R10812 */ + 0x0000, /* R10813 */ + 0x0000, /* R10814 */ + 0x0000, /* R10815 */ + 0x0000, /* R10816 */ + 0x0000, /* R10817 */ + 0x0000, /* R10818 */ + 0x0000, /* R10819 */ + 0x0000, /* R10820 */ + 0x0000, /* R10821 */ + 0x0000, /* R10822 */ + 0x0000, /* R10823 */ + 0x0000, /* R10824 */ + 0x0000, /* R10825 */ + 0x0000, /* R10826 */ + 0x0000, /* R10827 */ + 0x0000, /* R10828 */ + 0x0000, /* R10829 */ + 0x0000, /* R10830 */ + 0x0000, /* R10831 */ + 0x0000, /* R10832 */ + 0x0000, /* R10833 */ + 0x0000, /* R10834 */ + 0x0000, /* R10835 */ + 0x0000, /* R10836 */ + 0x0000, /* R10837 */ + 0x0000, /* R10838 */ + 0x0000, /* R10839 */ + 0x0000, /* R10840 */ + 0x0000, /* R10841 */ + 0x0000, /* R10842 */ + 0x0000, /* R10843 */ + 0x0000, /* R10844 */ + 0x0000, /* R10845 */ + 0x0000, /* R10846 */ + 0x0000, /* R10847 */ + 0x0000, /* R10848 */ + 0x0000, /* R10849 */ + 0x0000, /* R10850 */ + 0x0000, /* R10851 */ + 0x0000, /* R10852 */ + 0x0000, /* R10853 */ + 0x0000, /* R10854 */ + 0x0000, /* R10855 */ + 0x0000, /* R10856 */ + 0x0000, /* R10857 */ + 0x0000, /* R10858 */ + 0x0000, /* R10859 */ + 0x0000, /* R10860 */ + 0x0000, /* R10861 */ + 0x0000, /* R10862 */ + 0x0000, /* R10863 */ + 0x0000, /* R10864 */ + 0x0000, /* R10865 */ + 0x0000, /* R10866 */ + 0x0000, /* R10867 */ + 0x0000, /* R10868 */ + 0x0000, /* R10869 */ + 0x0000, /* R10870 */ + 0x0000, /* R10871 */ + 0x0000, /* R10872 */ + 0x0000, /* R10873 */ + 0x0000, /* R10874 */ + 0x0000, /* R10875 */ + 0x0000, /* R10876 */ + 0x0000, /* R10877 */ + 0x0000, /* R10878 */ + 0x0000, /* R10879 */ + 0x0000, /* R10880 */ + 0x0000, /* R10881 */ + 0x0000, /* R10882 */ + 0x0000, /* R10883 */ + 0x0000, /* R10884 */ + 0x0000, /* R10885 */ + 0x0000, /* R10886 */ + 0x0000, /* R10887 */ + 0x0000, /* R10888 */ + 0x0000, /* R10889 */ + 0x0000, /* R10890 */ + 0x0000, /* R10891 */ + 0x0000, /* R10892 */ + 0x0000, /* R10893 */ + 0x0000, /* R10894 */ + 0x0000, /* R10895 */ + 0x0000, /* R10896 */ + 0x0000, /* R10897 */ + 0x0000, /* R10898 */ + 0x0000, /* R10899 */ + 0x0000, /* R10900 */ + 0x0000, /* R10901 */ + 0x0000, /* R10902 */ + 0x0000, /* R10903 */ + 0x0000, /* R10904 */ + 0x0000, /* R10905 */ + 0x0000, /* R10906 */ + 0x0000, /* R10907 */ + 0x0000, /* R10908 */ + 0x0000, /* R10909 */ + 0x0000, /* R10910 */ + 0x0000, /* R10911 */ + 0x0000, /* R10912 */ + 0x0000, /* R10913 */ + 0x0000, /* R10914 */ + 0x0000, /* R10915 */ + 0x0000, /* R10916 */ + 0x0000, /* R10917 */ + 0x0000, /* R10918 */ + 0x0000, /* R10919 */ + 0x0000, /* R10920 */ + 0x0000, /* R10921 */ + 0x0000, /* R10922 */ + 0x0000, /* R10923 */ + 0x0000, /* R10924 */ + 0x0000, /* R10925 */ + 0x0000, /* R10926 */ + 0x0000, /* R10927 */ + 0x0000, /* R10928 */ + 0x0000, /* R10929 */ + 0x0000, /* R10930 */ + 0x0000, /* R10931 */ + 0x0000, /* R10932 */ + 0x0000, /* R10933 */ + 0x0000, /* R10934 */ + 0x0000, /* R10935 */ + 0x0000, /* R10936 */ + 0x0000, /* R10937 */ + 0x0000, /* R10938 */ + 0x0000, /* R10939 */ + 0x0000, /* R10940 */ + 0x0000, /* R10941 */ + 0x0000, /* R10942 */ + 0x0000, /* R10943 */ + 0x0000, /* R10944 */ + 0x0000, /* R10945 */ + 0x0000, /* R10946 */ + 0x0000, /* R10947 */ + 0x0000, /* R10948 */ + 0x0000, /* R10949 */ + 0x0000, /* R10950 */ + 0x0000, /* R10951 */ + 0x0000, /* R10952 */ + 0x0000, /* R10953 */ + 0x0000, /* R10954 */ + 0x0000, /* R10955 */ + 0x0000, /* R10956 */ + 0x0000, /* R10957 */ + 0x0000, /* R10958 */ + 0x0000, /* R10959 */ + 0x0000, /* R10960 */ + 0x0000, /* R10961 */ + 0x0000, /* R10962 */ + 0x0000, /* R10963 */ + 0x0000, /* R10964 */ + 0x0000, /* R10965 */ + 0x0000, /* R10966 */ + 0x0000, /* R10967 */ + 0x0000, /* R10968 */ + 0x0000, /* R10969 */ + 0x0000, /* R10970 */ + 0x0000, /* R10971 */ + 0x0000, /* R10972 */ + 0x0000, /* R10973 */ + 0x0000, /* R10974 */ + 0x0000, /* R10975 */ + 0x0000, /* R10976 */ + 0x0000, /* R10977 */ + 0x0000, /* R10978 */ + 0x0000, /* R10979 */ + 0x0000, /* R10980 */ + 0x0000, /* R10981 */ + 0x0000, /* R10982 */ + 0x0000, /* R10983 */ + 0x0000, /* R10984 */ + 0x0000, /* R10985 */ + 0x0000, /* R10986 */ + 0x0000, /* R10987 */ + 0x0000, /* R10988 */ + 0x0000, /* R10989 */ + 0x0000, /* R10990 */ + 0x0000, /* R10991 */ + 0x0000, /* R10992 */ + 0x0000, /* R10993 */ + 0x0000, /* R10994 */ + 0x0000, /* R10995 */ + 0x0000, /* R10996 */ + 0x0000, /* R10997 */ + 0x0000, /* R10998 */ + 0x0000, /* R10999 */ + 0x0000, /* R11000 */ + 0x0000, /* R11001 */ + 0x0000, /* R11002 */ + 0x0000, /* R11003 */ + 0x0000, /* R11004 */ + 0x0000, /* R11005 */ + 0x0000, /* R11006 */ + 0x0000, /* R11007 */ + 0x0000, /* R11008 */ + 0x0000, /* R11009 */ + 0x0000, /* R11010 */ + 0x0000, /* R11011 */ + 0x0000, /* R11012 */ + 0x0000, /* R11013 */ + 0x0000, /* R11014 */ + 0x0000, /* R11015 */ + 0x0000, /* R11016 */ + 0x0000, /* R11017 */ + 0x0000, /* R11018 */ + 0x0000, /* R11019 */ + 0x0000, /* R11020 */ + 0x0000, /* R11021 */ + 0x0000, /* R11022 */ + 0x0000, /* R11023 */ + 0x0000, /* R11024 */ + 0x0000, /* R11025 */ + 0x0000, /* R11026 */ + 0x0000, /* R11027 */ + 0x0000, /* R11028 */ + 0x0000, /* R11029 */ + 0x0000, /* R11030 */ + 0x0000, /* R11031 */ + 0x0000, /* R11032 */ + 0x0000, /* R11033 */ + 0x0000, /* R11034 */ + 0x0000, /* R11035 */ + 0x0000, /* R11036 */ + 0x0000, /* R11037 */ + 0x0000, /* R11038 */ + 0x0000, /* R11039 */ + 0x0000, /* R11040 */ + 0x0000, /* R11041 */ + 0x0000, /* R11042 */ + 0x0000, /* R11043 */ + 0x0000, /* R11044 */ + 0x0000, /* R11045 */ + 0x0000, /* R11046 */ + 0x0000, /* R11047 */ + 0x0000, /* R11048 */ + 0x0000, /* R11049 */ + 0x0000, /* R11050 */ + 0x0000, /* R11051 */ + 0x0000, /* R11052 */ + 0x0000, /* R11053 */ + 0x0000, /* R11054 */ + 0x0000, /* R11055 */ + 0x0000, /* R11056 */ + 0x0000, /* R11057 */ + 0x0000, /* R11058 */ + 0x0000, /* R11059 */ + 0x0000, /* R11060 */ + 0x0000, /* R11061 */ + 0x0000, /* R11062 */ + 0x0000, /* R11063 */ + 0x0000, /* R11064 */ + 0x0000, /* R11065 */ + 0x0000, /* R11066 */ + 0x0000, /* R11067 */ + 0x0000, /* R11068 */ + 0x0000, /* R11069 */ + 0x0000, /* R11070 */ + 0x0000, /* R11071 */ + 0x0000, /* R11072 */ + 0x0000, /* R11073 */ + 0x0000, /* R11074 */ + 0x0000, /* R11075 */ + 0x0000, /* R11076 */ + 0x0000, /* R11077 */ + 0x0000, /* R11078 */ + 0x0000, /* R11079 */ + 0x0000, /* R11080 */ + 0x0000, /* R11081 */ + 0x0000, /* R11082 */ + 0x0000, /* R11083 */ + 0x0000, /* R11084 */ + 0x0000, /* R11085 */ + 0x0000, /* R11086 */ + 0x0000, /* R11087 */ + 0x0000, /* R11088 */ + 0x0000, /* R11089 */ + 0x0000, /* R11090 */ + 0x0000, /* R11091 */ + 0x0000, /* R11092 */ + 0x0000, /* R11093 */ + 0x0000, /* R11094 */ + 0x0000, /* R11095 */ + 0x0000, /* R11096 */ + 0x0000, /* R11097 */ + 0x0000, /* R11098 */ + 0x0000, /* R11099 */ + 0x0000, /* R11100 */ + 0x0000, /* R11101 */ + 0x0000, /* R11102 */ + 0x0000, /* R11103 */ + 0x0000, /* R11104 */ + 0x0000, /* R11105 */ + 0x0000, /* R11106 */ + 0x0000, /* R11107 */ + 0x0000, /* R11108 */ + 0x0000, /* R11109 */ + 0x0000, /* R11110 */ + 0x0000, /* R11111 */ + 0x0000, /* R11112 */ + 0x0000, /* R11113 */ + 0x0000, /* R11114 */ + 0x0000, /* R11115 */ + 0x0000, /* R11116 */ + 0x0000, /* R11117 */ + 0x0000, /* R11118 */ + 0x0000, /* R11119 */ + 0x0000, /* R11120 */ + 0x0000, /* R11121 */ + 0x0000, /* R11122 */ + 0x0000, /* R11123 */ + 0x0000, /* R11124 */ + 0x0000, /* R11125 */ + 0x0000, /* R11126 */ + 0x0000, /* R11127 */ + 0x0000, /* R11128 */ + 0x0000, /* R11129 */ + 0x0000, /* R11130 */ + 0x0000, /* R11131 */ + 0x0000, /* R11132 */ + 0x0000, /* R11133 */ + 0x0000, /* R11134 */ + 0x0000, /* R11135 */ + 0x0000, /* R11136 */ + 0x0000, /* R11137 */ + 0x0000, /* R11138 */ + 0x0000, /* R11139 */ + 0x0000, /* R11140 */ + 0x0000, /* R11141 */ + 0x0000, /* R11142 */ + 0x0000, /* R11143 */ + 0x0000, /* R11144 */ + 0x0000, /* R11145 */ + 0x0000, /* R11146 */ + 0x0000, /* R11147 */ + 0x0000, /* R11148 */ + 0x0000, /* R11149 */ + 0x0000, /* R11150 */ + 0x0000, /* R11151 */ + 0x0000, /* R11152 */ + 0x0000, /* R11153 */ + 0x0000, /* R11154 */ + 0x0000, /* R11155 */ + 0x0000, /* R11156 */ + 0x0000, /* R11157 */ + 0x0000, /* R11158 */ + 0x0000, /* R11159 */ + 0x0000, /* R11160 */ + 0x0000, /* R11161 */ + 0x0000, /* R11162 */ + 0x0000, /* R11163 */ + 0x0000, /* R11164 */ + 0x0000, /* R11165 */ + 0x0000, /* R11166 */ + 0x0000, /* R11167 */ + 0x0000, /* R11168 */ + 0x0000, /* R11169 */ + 0x0000, /* R11170 */ + 0x0000, /* R11171 */ + 0x0000, /* R11172 */ + 0x0000, /* R11173 */ + 0x0000, /* R11174 */ + 0x0000, /* R11175 */ + 0x0000, /* R11176 */ + 0x0000, /* R11177 */ + 0x0000, /* R11178 */ + 0x0000, /* R11179 */ + 0x0000, /* R11180 */ + 0x0000, /* R11181 */ + 0x0000, /* R11182 */ + 0x0000, /* R11183 */ + 0x0000, /* R11184 */ + 0x0000, /* R11185 */ + 0x0000, /* R11186 */ + 0x0000, /* R11187 */ + 0x0000, /* R11188 */ + 0x0000, /* R11189 */ + 0x0000, /* R11190 */ + 0x0000, /* R11191 */ + 0x0000, /* R11192 */ + 0x0000, /* R11193 */ + 0x0000, /* R11194 */ + 0x0000, /* R11195 */ + 0x0000, /* R11196 */ + 0x0000, /* R11197 */ + 0x0000, /* R11198 */ + 0x0000, /* R11199 */ + 0x0000, /* R11200 */ + 0x0000, /* R11201 */ + 0x0000, /* R11202 */ + 0x0000, /* R11203 */ + 0x0000, /* R11204 */ + 0x0000, /* R11205 */ + 0x0000, /* R11206 */ + 0x0000, /* R11207 */ + 0x0000, /* R11208 */ + 0x0000, /* R11209 */ + 0x0000, /* R11210 */ + 0x0000, /* R11211 */ + 0x0000, /* R11212 */ + 0x0000, /* R11213 */ + 0x0000, /* R11214 */ + 0x0000, /* R11215 */ + 0x0000, /* R11216 */ + 0x0000, /* R11217 */ + 0x0000, /* R11218 */ + 0x0000, /* R11219 */ + 0x0000, /* R11220 */ + 0x0000, /* R11221 */ + 0x0000, /* R11222 */ + 0x0000, /* R11223 */ + 0x0000, /* R11224 */ + 0x0000, /* R11225 */ + 0x0000, /* R11226 */ + 0x0000, /* R11227 */ + 0x0000, /* R11228 */ + 0x0000, /* R11229 */ + 0x0000, /* R11230 */ + 0x0000, /* R11231 */ + 0x0000, /* R11232 */ + 0x0000, /* R11233 */ + 0x0000, /* R11234 */ + 0x0000, /* R11235 */ + 0x0000, /* R11236 */ + 0x0000, /* R11237 */ + 0x0000, /* R11238 */ + 0x0000, /* R11239 */ + 0x0000, /* R11240 */ + 0x0000, /* R11241 */ + 0x0000, /* R11242 */ + 0x0000, /* R11243 */ + 0x0000, /* R11244 */ + 0x0000, /* R11245 */ + 0x0000, /* R11246 */ + 0x0000, /* R11247 */ + 0x0000, /* R11248 */ + 0x0000, /* R11249 */ + 0x0000, /* R11250 */ + 0x0000, /* R11251 */ + 0x0000, /* R11252 */ + 0x0000, /* R11253 */ + 0x0000, /* R11254 */ + 0x0000, /* R11255 */ + 0x0000, /* R11256 */ + 0x0000, /* R11257 */ + 0x0000, /* R11258 */ + 0x0000, /* R11259 */ + 0x0000, /* R11260 */ + 0x0000, /* R11261 */ + 0x0000, /* R11262 */ + 0x0000, /* R11263 */ + 0x0000, /* R11264 */ + 0x0000, /* R11265 */ + 0x0000, /* R11266 */ + 0x0000, /* R11267 */ + 0x0000, /* R11268 */ + 0x0000, /* R11269 */ + 0x0000, /* R11270 */ + 0x0000, /* R11271 */ + 0x0000, /* R11272 */ + 0x0000, /* R11273 */ + 0x0000, /* R11274 */ + 0x0000, /* R11275 */ + 0x0000, /* R11276 */ + 0x0000, /* R11277 */ + 0x0000, /* R11278 */ + 0x0000, /* R11279 */ + 0x0000, /* R11280 */ + 0x0000, /* R11281 */ + 0x0000, /* R11282 */ + 0x0000, /* R11283 */ + 0x0000, /* R11284 */ + 0x0000, /* R11285 */ + 0x0000, /* R11286 */ + 0x0000, /* R11287 */ + 0x0000, /* R11288 */ + 0x0000, /* R11289 */ + 0x0000, /* R11290 */ + 0x0000, /* R11291 */ + 0x0000, /* R11292 */ + 0x0000, /* R11293 */ + 0x0000, /* R11294 */ + 0x0000, /* R11295 */ + 0x0000, /* R11296 */ + 0x0000, /* R11297 */ + 0x0000, /* R11298 */ + 0x0000, /* R11299 */ + 0x0000, /* R11300 */ + 0x0000, /* R11301 */ + 0x0000, /* R11302 */ + 0x0000, /* R11303 */ + 0x0000, /* R11304 */ + 0x0000, /* R11305 */ + 0x0000, /* R11306 */ + 0x0000, /* R11307 */ + 0x0000, /* R11308 */ + 0x0000, /* R11309 */ + 0x0000, /* R11310 */ + 0x0000, /* R11311 */ + 0x0000, /* R11312 */ + 0x0000, /* R11313 */ + 0x0000, /* R11314 */ + 0x0000, /* R11315 */ + 0x0000, /* R11316 */ + 0x0000, /* R11317 */ + 0x0000, /* R11318 */ + 0x0000, /* R11319 */ + 0x0000, /* R11320 */ + 0x0000, /* R11321 */ + 0x0000, /* R11322 */ + 0x0000, /* R11323 */ + 0x0000, /* R11324 */ + 0x0000, /* R11325 */ + 0x0000, /* R11326 */ + 0x0000, /* R11327 */ + 0x0000, /* R11328 */ + 0x0000, /* R11329 */ + 0x0000, /* R11330 */ + 0x0000, /* R11331 */ + 0x0000, /* R11332 */ + 0x0000, /* R11333 */ + 0x0000, /* R11334 */ + 0x0000, /* R11335 */ + 0x0000, /* R11336 */ + 0x0000, /* R11337 */ + 0x0000, /* R11338 */ + 0x0000, /* R11339 */ + 0x0000, /* R11340 */ + 0x0000, /* R11341 */ + 0x0000, /* R11342 */ + 0x0000, /* R11343 */ + 0x0000, /* R11344 */ + 0x0000, /* R11345 */ + 0x0000, /* R11346 */ + 0x0000, /* R11347 */ + 0x0000, /* R11348 */ + 0x0000, /* R11349 */ + 0x0000, /* R11350 */ + 0x0000, /* R11351 */ + 0x0000, /* R11352 */ + 0x0000, /* R11353 */ + 0x0000, /* R11354 */ + 0x0000, /* R11355 */ + 0x0000, /* R11356 */ + 0x0000, /* R11357 */ + 0x0000, /* R11358 */ + 0x0000, /* R11359 */ + 0x0000, /* R11360 */ + 0x0000, /* R11361 */ + 0x0000, /* R11362 */ + 0x0000, /* R11363 */ + 0x0000, /* R11364 */ + 0x0000, /* R11365 */ + 0x0000, /* R11366 */ + 0x0000, /* R11367 */ + 0x0000, /* R11368 */ + 0x0000, /* R11369 */ + 0x0000, /* R11370 */ + 0x0000, /* R11371 */ + 0x0000, /* R11372 */ + 0x0000, /* R11373 */ + 0x0000, /* R11374 */ + 0x0000, /* R11375 */ + 0x0000, /* R11376 */ + 0x0000, /* R11377 */ + 0x0000, /* R11378 */ + 0x0000, /* R11379 */ + 0x0000, /* R11380 */ + 0x0000, /* R11381 */ + 0x0000, /* R11382 */ + 0x0000, /* R11383 */ + 0x0000, /* R11384 */ + 0x0000, /* R11385 */ + 0x0000, /* R11386 */ + 0x0000, /* R11387 */ + 0x0000, /* R11388 */ + 0x0000, /* R11389 */ + 0x0000, /* R11390 */ + 0x0000, /* R11391 */ + 0x0000, /* R11392 */ + 0x0000, /* R11393 */ + 0x0000, /* R11394 */ + 0x0000, /* R11395 */ + 0x0000, /* R11396 */ + 0x0000, /* R11397 */ + 0x0000, /* R11398 */ + 0x0000, /* R11399 */ + 0x0000, /* R11400 */ + 0x0000, /* R11401 */ + 0x0000, /* R11402 */ + 0x0000, /* R11403 */ + 0x0000, /* R11404 */ + 0x0000, /* R11405 */ + 0x0000, /* R11406 */ + 0x0000, /* R11407 */ + 0x0000, /* R11408 */ + 0x0000, /* R11409 */ + 0x0000, /* R11410 */ + 0x0000, /* R11411 */ + 0x0000, /* R11412 */ + 0x0000, /* R11413 */ + 0x0000, /* R11414 */ + 0x0000, /* R11415 */ + 0x0000, /* R11416 */ + 0x0000, /* R11417 */ + 0x0000, /* R11418 */ + 0x0000, /* R11419 */ + 0x0000, /* R11420 */ + 0x0000, /* R11421 */ + 0x0000, /* R11422 */ + 0x0000, /* R11423 */ + 0x0000, /* R11424 */ + 0x0000, /* R11425 */ + 0x0000, /* R11426 */ + 0x0000, /* R11427 */ + 0x0000, /* R11428 */ + 0x0000, /* R11429 */ + 0x0000, /* R11430 */ + 0x0000, /* R11431 */ + 0x0000, /* R11432 */ + 0x0000, /* R11433 */ + 0x0000, /* R11434 */ + 0x0000, /* R11435 */ + 0x0000, /* R11436 */ + 0x0000, /* R11437 */ + 0x0000, /* R11438 */ + 0x0000, /* R11439 */ + 0x0000, /* R11440 */ + 0x0000, /* R11441 */ + 0x0000, /* R11442 */ + 0x0000, /* R11443 */ + 0x0000, /* R11444 */ + 0x0000, /* R11445 */ + 0x0000, /* R11446 */ + 0x0000, /* R11447 */ + 0x0000, /* R11448 */ + 0x0000, /* R11449 */ + 0x0000, /* R11450 */ + 0x0000, /* R11451 */ + 0x0000, /* R11452 */ + 0x0000, /* R11453 */ + 0x0000, /* R11454 */ + 0x0000, /* R11455 */ + 0x0000, /* R11456 */ + 0x0000, /* R11457 */ + 0x0000, /* R11458 */ + 0x0000, /* R11459 */ + 0x0000, /* R11460 */ + 0x0000, /* R11461 */ + 0x0000, /* R11462 */ + 0x0000, /* R11463 */ + 0x0000, /* R11464 */ + 0x0000, /* R11465 */ + 0x0000, /* R11466 */ + 0x0000, /* R11467 */ + 0x0000, /* R11468 */ + 0x0000, /* R11469 */ + 0x0000, /* R11470 */ + 0x0000, /* R11471 */ + 0x0000, /* R11472 */ + 0x0000, /* R11473 */ + 0x0000, /* R11474 */ + 0x0000, /* R11475 */ + 0x0000, /* R11476 */ + 0x0000, /* R11477 */ + 0x0000, /* R11478 */ + 0x0000, /* R11479 */ + 0x0000, /* R11480 */ + 0x0000, /* R11481 */ + 0x0000, /* R11482 */ + 0x0000, /* R11483 */ + 0x0000, /* R11484 */ + 0x0000, /* R11485 */ + 0x0000, /* R11486 */ + 0x0000, /* R11487 */ + 0x0000, /* R11488 */ + 0x0000, /* R11489 */ + 0x0000, /* R11490 */ + 0x0000, /* R11491 */ + 0x0000, /* R11492 */ + 0x0000, /* R11493 */ + 0x0000, /* R11494 */ + 0x0000, /* R11495 */ + 0x0000, /* R11496 */ + 0x0000, /* R11497 */ + 0x0000, /* R11498 */ + 0x0000, /* R11499 */ + 0x0000, /* R11500 */ + 0x0000, /* R11501 */ + 0x0000, /* R11502 */ + 0x0000, /* R11503 */ + 0x0000, /* R11504 */ + 0x0000, /* R11505 */ + 0x0000, /* R11506 */ + 0x0000, /* R11507 */ + 0x0000, /* R11508 */ + 0x0000, /* R11509 */ + 0x0000, /* R11510 */ + 0x0000, /* R11511 */ + 0x0000, /* R11512 */ + 0x0000, /* R11513 */ + 0x0000, /* R11514 */ + 0x0000, /* R11515 */ + 0x0000, /* R11516 */ + 0x0000, /* R11517 */ + 0x0000, /* R11518 */ + 0x0000, /* R11519 */ + 0x0000, /* R11520 */ + 0x0000, /* R11521 */ + 0x0000, /* R11522 */ + 0x0000, /* R11523 */ + 0x0000, /* R11524 */ + 0x0000, /* R11525 */ + 0x0000, /* R11526 */ + 0x0000, /* R11527 */ + 0x0000, /* R11528 */ + 0x0000, /* R11529 */ + 0x0000, /* R11530 */ + 0x0000, /* R11531 */ + 0x0000, /* R11532 */ + 0x0000, /* R11533 */ + 0x0000, /* R11534 */ + 0x0000, /* R11535 */ + 0x0000, /* R11536 */ + 0x0000, /* R11537 */ + 0x0000, /* R11538 */ + 0x0000, /* R11539 */ + 0x0000, /* R11540 */ + 0x0000, /* R11541 */ + 0x0000, /* R11542 */ + 0x0000, /* R11543 */ + 0x0000, /* R11544 */ + 0x0000, /* R11545 */ + 0x0000, /* R11546 */ + 0x0000, /* R11547 */ + 0x0000, /* R11548 */ + 0x0000, /* R11549 */ + 0x0000, /* R11550 */ + 0x0000, /* R11551 */ + 0x0000, /* R11552 */ + 0x0000, /* R11553 */ + 0x0000, /* R11554 */ + 0x0000, /* R11555 */ + 0x0000, /* R11556 */ + 0x0000, /* R11557 */ + 0x0000, /* R11558 */ + 0x0000, /* R11559 */ + 0x0000, /* R11560 */ + 0x0000, /* R11561 */ + 0x0000, /* R11562 */ + 0x0000, /* R11563 */ + 0x0000, /* R11564 */ + 0x0000, /* R11565 */ + 0x0000, /* R11566 */ + 0x0000, /* R11567 */ + 0x0000, /* R11568 */ + 0x0000, /* R11569 */ + 0x0000, /* R11570 */ + 0x0000, /* R11571 */ + 0x0000, /* R11572 */ + 0x0000, /* R11573 */ + 0x0000, /* R11574 */ + 0x0000, /* R11575 */ + 0x0000, /* R11576 */ + 0x0000, /* R11577 */ + 0x0000, /* R11578 */ + 0x0000, /* R11579 */ + 0x0000, /* R11580 */ + 0x0000, /* R11581 */ + 0x0000, /* R11582 */ + 0x0000, /* R11583 */ + 0x0000, /* R11584 */ + 0x0000, /* R11585 */ + 0x0000, /* R11586 */ + 0x0000, /* R11587 */ + 0x0000, /* R11588 */ + 0x0000, /* R11589 */ + 0x0000, /* R11590 */ + 0x0000, /* R11591 */ + 0x0000, /* R11592 */ + 0x0000, /* R11593 */ + 0x0000, /* R11594 */ + 0x0000, /* R11595 */ + 0x0000, /* R11596 */ + 0x0000, /* R11597 */ + 0x0000, /* R11598 */ + 0x0000, /* R11599 */ + 0x0000, /* R11600 */ + 0x0000, /* R11601 */ + 0x0000, /* R11602 */ + 0x0000, /* R11603 */ + 0x0000, /* R11604 */ + 0x0000, /* R11605 */ + 0x0000, /* R11606 */ + 0x0000, /* R11607 */ + 0x0000, /* R11608 */ + 0x0000, /* R11609 */ + 0x0000, /* R11610 */ + 0x0000, /* R11611 */ + 0x0000, /* R11612 */ + 0x0000, /* R11613 */ + 0x0000, /* R11614 */ + 0x0000, /* R11615 */ + 0x0000, /* R11616 */ + 0x0000, /* R11617 */ + 0x0000, /* R11618 */ + 0x0000, /* R11619 */ + 0x0000, /* R11620 */ + 0x0000, /* R11621 */ + 0x0000, /* R11622 */ + 0x0000, /* R11623 */ + 0x0000, /* R11624 */ + 0x0000, /* R11625 */ + 0x0000, /* R11626 */ + 0x0000, /* R11627 */ + 0x0000, /* R11628 */ + 0x0000, /* R11629 */ + 0x0000, /* R11630 */ + 0x0000, /* R11631 */ + 0x0000, /* R11632 */ + 0x0000, /* R11633 */ + 0x0000, /* R11634 */ + 0x0000, /* R11635 */ + 0x0000, /* R11636 */ + 0x0000, /* R11637 */ + 0x0000, /* R11638 */ + 0x0000, /* R11639 */ + 0x0000, /* R11640 */ + 0x0000, /* R11641 */ + 0x0000, /* R11642 */ + 0x0000, /* R11643 */ + 0x0000, /* R11644 */ + 0x0000, /* R11645 */ + 0x0000, /* R11646 */ + 0x0000, /* R11647 */ + 0x0000, /* R11648 */ + 0x0000, /* R11649 */ + 0x0000, /* R11650 */ + 0x0000, /* R11651 */ + 0x0000, /* R11652 */ + 0x0000, /* R11653 */ + 0x0000, /* R11654 */ + 0x0000, /* R11655 */ + 0x0000, /* R11656 */ + 0x0000, /* R11657 */ + 0x0000, /* R11658 */ + 0x0000, /* R11659 */ + 0x0000, /* R11660 */ + 0x0000, /* R11661 */ + 0x0000, /* R11662 */ + 0x0000, /* R11663 */ + 0x0000, /* R11664 */ + 0x0000, /* R11665 */ + 0x0000, /* R11666 */ + 0x0000, /* R11667 */ + 0x0000, /* R11668 */ + 0x0000, /* R11669 */ + 0x0000, /* R11670 */ + 0x0000, /* R11671 */ + 0x0000, /* R11672 */ + 0x0000, /* R11673 */ + 0x0000, /* R11674 */ + 0x0000, /* R11675 */ + 0x0000, /* R11676 */ + 0x0000, /* R11677 */ + 0x0000, /* R11678 */ + 0x0000, /* R11679 */ + 0x0000, /* R11680 */ + 0x0000, /* R11681 */ + 0x0000, /* R11682 */ + 0x0000, /* R11683 */ + 0x0000, /* R11684 */ + 0x0000, /* R11685 */ + 0x0000, /* R11686 */ + 0x0000, /* R11687 */ + 0x0000, /* R11688 */ + 0x0000, /* R11689 */ + 0x0000, /* R11690 */ + 0x0000, /* R11691 */ + 0x0000, /* R11692 */ + 0x0000, /* R11693 */ + 0x0000, /* R11694 */ + 0x0000, /* R11695 */ + 0x0000, /* R11696 */ + 0x0000, /* R11697 */ + 0x0000, /* R11698 */ + 0x0000, /* R11699 */ + 0x0000, /* R11700 */ + 0x0000, /* R11701 */ + 0x0000, /* R11702 */ + 0x0000, /* R11703 */ + 0x0000, /* R11704 */ + 0x0000, /* R11705 */ + 0x0000, /* R11706 */ + 0x0000, /* R11707 */ + 0x0000, /* R11708 */ + 0x0000, /* R11709 */ + 0x0000, /* R11710 */ + 0x0000, /* R11711 */ + 0x0000, /* R11712 */ + 0x0000, /* R11713 */ + 0x0000, /* R11714 */ + 0x0000, /* R11715 */ + 0x0000, /* R11716 */ + 0x0000, /* R11717 */ + 0x0000, /* R11718 */ + 0x0000, /* R11719 */ + 0x0000, /* R11720 */ + 0x0000, /* R11721 */ + 0x0000, /* R11722 */ + 0x0000, /* R11723 */ + 0x0000, /* R11724 */ + 0x0000, /* R11725 */ + 0x0000, /* R11726 */ + 0x0000, /* R11727 */ + 0x0000, /* R11728 */ + 0x0000, /* R11729 */ + 0x0000, /* R11730 */ + 0x0000, /* R11731 */ + 0x0000, /* R11732 */ + 0x0000, /* R11733 */ + 0x0000, /* R11734 */ + 0x0000, /* R11735 */ + 0x0000, /* R11736 */ + 0x0000, /* R11737 */ + 0x0000, /* R11738 */ + 0x0000, /* R11739 */ + 0x0000, /* R11740 */ + 0x0000, /* R11741 */ + 0x0000, /* R11742 */ + 0x0000, /* R11743 */ + 0x0000, /* R11744 */ + 0x0000, /* R11745 */ + 0x0000, /* R11746 */ + 0x0000, /* R11747 */ + 0x0000, /* R11748 */ + 0x0000, /* R11749 */ + 0x0000, /* R11750 */ + 0x0000, /* R11751 */ + 0x0000, /* R11752 */ + 0x0000, /* R11753 */ + 0x0000, /* R11754 */ + 0x0000, /* R11755 */ + 0x0000, /* R11756 */ + 0x0000, /* R11757 */ + 0x0000, /* R11758 */ + 0x0000, /* R11759 */ + 0x0000, /* R11760 */ + 0x0000, /* R11761 */ + 0x0000, /* R11762 */ + 0x0000, /* R11763 */ + 0x0000, /* R11764 */ + 0x0000, /* R11765 */ + 0x0000, /* R11766 */ + 0x0000, /* R11767 */ + 0x0000, /* R11768 */ + 0x0000, /* R11769 */ + 0x0000, /* R11770 */ + 0x0000, /* R11771 */ + 0x0000, /* R11772 */ + 0x0000, /* R11773 */ + 0x0000, /* R11774 */ + 0x0000, /* R11775 */ + 0x0000, /* R11776 */ + 0x0000, /* R11777 */ + 0x0000, /* R11778 */ + 0x0000, /* R11779 */ + 0x0000, /* R11780 */ + 0x0000, /* R11781 */ + 0x0000, /* R11782 */ + 0x0000, /* R11783 */ + 0x0000, /* R11784 */ + 0x0000, /* R11785 */ + 0x0000, /* R11786 */ + 0x0000, /* R11787 */ + 0x0000, /* R11788 */ + 0x0000, /* R11789 */ + 0x0000, /* R11790 */ + 0x0000, /* R11791 */ + 0x0000, /* R11792 */ + 0x0000, /* R11793 */ + 0x0000, /* R11794 */ + 0x0000, /* R11795 */ + 0x0000, /* R11796 */ + 0x0000, /* R11797 */ + 0x0000, /* R11798 */ + 0x0000, /* R11799 */ + 0x0000, /* R11800 */ + 0x0000, /* R11801 */ + 0x0000, /* R11802 */ + 0x0000, /* R11803 */ + 0x0000, /* R11804 */ + 0x0000, /* R11805 */ + 0x0000, /* R11806 */ + 0x0000, /* R11807 */ + 0x0000, /* R11808 */ + 0x0000, /* R11809 */ + 0x0000, /* R11810 */ + 0x0000, /* R11811 */ + 0x0000, /* R11812 */ + 0x0000, /* R11813 */ + 0x0000, /* R11814 */ + 0x0000, /* R11815 */ + 0x0000, /* R11816 */ + 0x0000, /* R11817 */ + 0x0000, /* R11818 */ + 0x0000, /* R11819 */ + 0x0000, /* R11820 */ + 0x0000, /* R11821 */ + 0x0000, /* R11822 */ + 0x0000, /* R11823 */ + 0x0000, /* R11824 */ + 0x0000, /* R11825 */ + 0x0000, /* R11826 */ + 0x0000, /* R11827 */ + 0x0000, /* R11828 */ + 0x0000, /* R11829 */ + 0x0000, /* R11830 */ + 0x0000, /* R11831 */ + 0x0000, /* R11832 */ + 0x0000, /* R11833 */ + 0x0000, /* R11834 */ + 0x0000, /* R11835 */ + 0x0000, /* R11836 */ + 0x0000, /* R11837 */ + 0x0000, /* R11838 */ + 0x0000, /* R11839 */ + 0x0000, /* R11840 */ + 0x0000, /* R11841 */ + 0x0000, /* R11842 */ + 0x0000, /* R11843 */ + 0x0000, /* R11844 */ + 0x0000, /* R11845 */ + 0x0000, /* R11846 */ + 0x0000, /* R11847 */ + 0x0000, /* R11848 */ + 0x0000, /* R11849 */ + 0x0000, /* R11850 */ + 0x0000, /* R11851 */ + 0x0000, /* R11852 */ + 0x0000, /* R11853 */ + 0x0000, /* R11854 */ + 0x0000, /* R11855 */ + 0x0000, /* R11856 */ + 0x0000, /* R11857 */ + 0x0000, /* R11858 */ + 0x0000, /* R11859 */ + 0x0000, /* R11860 */ + 0x0000, /* R11861 */ + 0x0000, /* R11862 */ + 0x0000, /* R11863 */ + 0x0000, /* R11864 */ + 0x0000, /* R11865 */ + 0x0000, /* R11866 */ + 0x0000, /* R11867 */ + 0x0000, /* R11868 */ + 0x0000, /* R11869 */ + 0x0000, /* R11870 */ + 0x0000, /* R11871 */ + 0x0000, /* R11872 */ + 0x0000, /* R11873 */ + 0x0000, /* R11874 */ + 0x0000, /* R11875 */ + 0x0000, /* R11876 */ + 0x0000, /* R11877 */ + 0x0000, /* R11878 */ + 0x0000, /* R11879 */ + 0x0000, /* R11880 */ + 0x0000, /* R11881 */ + 0x0000, /* R11882 */ + 0x0000, /* R11883 */ + 0x0000, /* R11884 */ + 0x0000, /* R11885 */ + 0x0000, /* R11886 */ + 0x0000, /* R11887 */ + 0x0000, /* R11888 */ + 0x0000, /* R11889 */ + 0x0000, /* R11890 */ + 0x0000, /* R11891 */ + 0x0000, /* R11892 */ + 0x0000, /* R11893 */ + 0x0000, /* R11894 */ + 0x0000, /* R11895 */ + 0x0000, /* R11896 */ + 0x0000, /* R11897 */ + 0x0000, /* R11898 */ + 0x0000, /* R11899 */ + 0x0000, /* R11900 */ + 0x0000, /* R11901 */ + 0x0000, /* R11902 */ + 0x0000, /* R11903 */ + 0x0000, /* R11904 */ + 0x0000, /* R11905 */ + 0x0000, /* R11906 */ + 0x0000, /* R11907 */ + 0x0000, /* R11908 */ + 0x0000, /* R11909 */ + 0x0000, /* R11910 */ + 0x0000, /* R11911 */ + 0x0000, /* R11912 */ + 0x0000, /* R11913 */ + 0x0000, /* R11914 */ + 0x0000, /* R11915 */ + 0x0000, /* R11916 */ + 0x0000, /* R11917 */ + 0x0000, /* R11918 */ + 0x0000, /* R11919 */ + 0x0000, /* R11920 */ + 0x0000, /* R11921 */ + 0x0000, /* R11922 */ + 0x0000, /* R11923 */ + 0x0000, /* R11924 */ + 0x0000, /* R11925 */ + 0x0000, /* R11926 */ + 0x0000, /* R11927 */ + 0x0000, /* R11928 */ + 0x0000, /* R11929 */ + 0x0000, /* R11930 */ + 0x0000, /* R11931 */ + 0x0000, /* R11932 */ + 0x0000, /* R11933 */ + 0x0000, /* R11934 */ + 0x0000, /* R11935 */ + 0x0000, /* R11936 */ + 0x0000, /* R11937 */ + 0x0000, /* R11938 */ + 0x0000, /* R11939 */ + 0x0000, /* R11940 */ + 0x0000, /* R11941 */ + 0x0000, /* R11942 */ + 0x0000, /* R11943 */ + 0x0000, /* R11944 */ + 0x0000, /* R11945 */ + 0x0000, /* R11946 */ + 0x0000, /* R11947 */ + 0x0000, /* R11948 */ + 0x0000, /* R11949 */ + 0x0000, /* R11950 */ + 0x0000, /* R11951 */ + 0x0000, /* R11952 */ + 0x0000, /* R11953 */ + 0x0000, /* R11954 */ + 0x0000, /* R11955 */ + 0x0000, /* R11956 */ + 0x0000, /* R11957 */ + 0x0000, /* R11958 */ + 0x0000, /* R11959 */ + 0x0000, /* R11960 */ + 0x0000, /* R11961 */ + 0x0000, /* R11962 */ + 0x0000, /* R11963 */ + 0x0000, /* R11964 */ + 0x0000, /* R11965 */ + 0x0000, /* R11966 */ + 0x0000, /* R11967 */ + 0x0000, /* R11968 */ + 0x0000, /* R11969 */ + 0x0000, /* R11970 */ + 0x0000, /* R11971 */ + 0x0000, /* R11972 */ + 0x0000, /* R11973 */ + 0x0000, /* R11974 */ + 0x0000, /* R11975 */ + 0x0000, /* R11976 */ + 0x0000, /* R11977 */ + 0x0000, /* R11978 */ + 0x0000, /* R11979 */ + 0x0000, /* R11980 */ + 0x0000, /* R11981 */ + 0x0000, /* R11982 */ + 0x0000, /* R11983 */ + 0x0000, /* R11984 */ + 0x0000, /* R11985 */ + 0x0000, /* R11986 */ + 0x0000, /* R11987 */ + 0x0000, /* R11988 */ + 0x0000, /* R11989 */ + 0x0000, /* R11990 */ + 0x0000, /* R11991 */ + 0x0000, /* R11992 */ + 0x0000, /* R11993 */ + 0x0000, /* R11994 */ + 0x0000, /* R11995 */ + 0x0000, /* R11996 */ + 0x0000, /* R11997 */ + 0x0000, /* R11998 */ + 0x0000, /* R11999 */ + 0x0000, /* R12000 */ + 0x0000, /* R12001 */ + 0x0000, /* R12002 */ + 0x0000, /* R12003 */ + 0x0000, /* R12004 */ + 0x0000, /* R12005 */ + 0x0000, /* R12006 */ + 0x0000, /* R12007 */ + 0x0000, /* R12008 */ + 0x0000, /* R12009 */ + 0x0000, /* R12010 */ + 0x0000, /* R12011 */ + 0x0000, /* R12012 */ + 0x0000, /* R12013 */ + 0x0000, /* R12014 */ + 0x0000, /* R12015 */ + 0x0000, /* R12016 */ + 0x0000, /* R12017 */ + 0x0000, /* R12018 */ + 0x0000, /* R12019 */ + 0x0000, /* R12020 */ + 0x0000, /* R12021 */ + 0x0000, /* R12022 */ + 0x0000, /* R12023 */ + 0x0000, /* R12024 */ + 0x0000, /* R12025 */ + 0x0000, /* R12026 */ + 0x0000, /* R12027 */ + 0x0000, /* R12028 */ + 0x0000, /* R12029 */ + 0x0000, /* R12030 */ + 0x0000, /* R12031 */ + 0x0000, /* R12032 */ + 0x0000, /* R12033 */ + 0x0000, /* R12034 */ + 0x0000, /* R12035 */ + 0x0000, /* R12036 */ + 0x0000, /* R12037 */ + 0x0000, /* R12038 */ + 0x0000, /* R12039 */ + 0x0000, /* R12040 */ + 0x0000, /* R12041 */ + 0x0000, /* R12042 */ + 0x0000, /* R12043 */ + 0x0000, /* R12044 */ + 0x0000, /* R12045 */ + 0x0000, /* R12046 */ + 0x0000, /* R12047 */ + 0x0000, /* R12048 */ + 0x0000, /* R12049 */ + 0x0000, /* R12050 */ + 0x0000, /* R12051 */ + 0x0000, /* R12052 */ + 0x0000, /* R12053 */ + 0x0000, /* R12054 */ + 0x0000, /* R12055 */ + 0x0000, /* R12056 */ + 0x0000, /* R12057 */ + 0x0000, /* R12058 */ + 0x0000, /* R12059 */ + 0x0000, /* R12060 */ + 0x0000, /* R12061 */ + 0x0000, /* R12062 */ + 0x0000, /* R12063 */ + 0x0000, /* R12064 */ + 0x0000, /* R12065 */ + 0x0000, /* R12066 */ + 0x0000, /* R12067 */ + 0x0000, /* R12068 */ + 0x0000, /* R12069 */ + 0x0000, /* R12070 */ + 0x0000, /* R12071 */ + 0x0000, /* R12072 */ + 0x0000, /* R12073 */ + 0x0000, /* R12074 */ + 0x0000, /* R12075 */ + 0x0000, /* R12076 */ + 0x0000, /* R12077 */ + 0x0000, /* R12078 */ + 0x0000, /* R12079 */ + 0x0000, /* R12080 */ + 0x0000, /* R12081 */ + 0x0000, /* R12082 */ + 0x0000, /* R12083 */ + 0x0000, /* R12084 */ + 0x0000, /* R12085 */ + 0x0000, /* R12086 */ + 0x0000, /* R12087 */ + 0x0000, /* R12088 */ + 0x0000, /* R12089 */ + 0x0000, /* R12090 */ + 0x0000, /* R12091 */ + 0x0000, /* R12092 */ + 0x0000, /* R12093 */ + 0x0000, /* R12094 */ + 0x0000, /* R12095 */ + 0x0000, /* R12096 */ + 0x0000, /* R12097 */ + 0x0000, /* R12098 */ + 0x0000, /* R12099 */ + 0x0000, /* R12100 */ + 0x0000, /* R12101 */ + 0x0000, /* R12102 */ + 0x0000, /* R12103 */ + 0x0000, /* R12104 */ + 0x0000, /* R12105 */ + 0x0000, /* R12106 */ + 0x0000, /* R12107 */ + 0x0000, /* R12108 */ + 0x0000, /* R12109 */ + 0x0000, /* R12110 */ + 0x0000, /* R12111 */ + 0x0000, /* R12112 */ + 0x0000, /* R12113 */ + 0x0000, /* R12114 */ + 0x0000, /* R12115 */ + 0x0000, /* R12116 */ + 0x0000, /* R12117 */ + 0x0000, /* R12118 */ + 0x0000, /* R12119 */ + 0x0000, /* R12120 */ + 0x0000, /* R12121 */ + 0x0000, /* R12122 */ + 0x0000, /* R12123 */ + 0x0000, /* R12124 */ + 0x0000, /* R12125 */ + 0x0000, /* R12126 */ + 0x0000, /* R12127 */ + 0x0000, /* R12128 */ + 0x0000, /* R12129 */ + 0x0000, /* R12130 */ + 0x0000, /* R12131 */ + 0x0000, /* R12132 */ + 0x0000, /* R12133 */ + 0x0000, /* R12134 */ + 0x0000, /* R12135 */ + 0x0000, /* R12136 */ + 0x0000, /* R12137 */ + 0x0000, /* R12138 */ + 0x0000, /* R12139 */ + 0x0000, /* R12140 */ + 0x0000, /* R12141 */ + 0x0000, /* R12142 */ + 0x0000, /* R12143 */ + 0x0000, /* R12144 */ + 0x0000, /* R12145 */ + 0x0000, /* R12146 */ + 0x0000, /* R12147 */ + 0x0000, /* R12148 */ + 0x0000, /* R12149 */ + 0x0000, /* R12150 */ + 0x0000, /* R12151 */ + 0x0000, /* R12152 */ + 0x0000, /* R12153 */ + 0x0000, /* R12154 */ + 0x0000, /* R12155 */ + 0x0000, /* R12156 */ + 0x0000, /* R12157 */ + 0x0000, /* R12158 */ + 0x0000, /* R12159 */ + 0x0000, /* R12160 */ + 0x0000, /* R12161 */ + 0x0000, /* R12162 */ + 0x0000, /* R12163 */ + 0x0000, /* R12164 */ + 0x0000, /* R12165 */ + 0x0000, /* R12166 */ + 0x0000, /* R12167 */ + 0x0000, /* R12168 */ + 0x0000, /* R12169 */ + 0x0000, /* R12170 */ + 0x0000, /* R12171 */ + 0x0000, /* R12172 */ + 0x0000, /* R12173 */ + 0x0000, /* R12174 */ + 0x0000, /* R12175 */ + 0x0000, /* R12176 */ + 0x0000, /* R12177 */ + 0x0000, /* R12178 */ + 0x0000, /* R12179 */ + 0x0000, /* R12180 */ + 0x0000, /* R12181 */ + 0x0000, /* R12182 */ + 0x0000, /* R12183 */ + 0x0000, /* R12184 */ + 0x0000, /* R12185 */ + 0x0000, /* R12186 */ + 0x0000, /* R12187 */ + 0x0000, /* R12188 */ + 0x0000, /* R12189 */ + 0x0000, /* R12190 */ + 0x0000, /* R12191 */ + 0x0000, /* R12192 */ + 0x0000, /* R12193 */ + 0x0000, /* R12194 */ + 0x0000, /* R12195 */ + 0x0000, /* R12196 */ + 0x0000, /* R12197 */ + 0x0000, /* R12198 */ + 0x0000, /* R12199 */ + 0x0000, /* R12200 */ + 0x0000, /* R12201 */ + 0x0000, /* R12202 */ + 0x0000, /* R12203 */ + 0x0000, /* R12204 */ + 0x0000, /* R12205 */ + 0x0000, /* R12206 */ + 0x0000, /* R12207 */ + 0x0000, /* R12208 */ + 0x0000, /* R12209 */ + 0x0000, /* R12210 */ + 0x0000, /* R12211 */ + 0x0000, /* R12212 */ + 0x0000, /* R12213 */ + 0x0000, /* R12214 */ + 0x0000, /* R12215 */ + 0x0000, /* R12216 */ + 0x0000, /* R12217 */ + 0x0000, /* R12218 */ + 0x0000, /* R12219 */ + 0x0000, /* R12220 */ + 0x0000, /* R12221 */ + 0x0000, /* R12222 */ + 0x0000, /* R12223 */ + 0x0000, /* R12224 */ + 0x0000, /* R12225 */ + 0x0000, /* R12226 */ + 0x0000, /* R12227 */ + 0x0000, /* R12228 */ + 0x0000, /* R12229 */ + 0x0000, /* R12230 */ + 0x0000, /* R12231 */ + 0x0000, /* R12232 */ + 0x0000, /* R12233 */ + 0x0000, /* R12234 */ + 0x0000, /* R12235 */ + 0x0000, /* R12236 */ + 0x0000, /* R12237 */ + 0x0000, /* R12238 */ + 0x0000, /* R12239 */ + 0x0000, /* R12240 */ + 0x0000, /* R12241 */ + 0x0000, /* R12242 */ + 0x0000, /* R12243 */ + 0x0000, /* R12244 */ + 0x0000, /* R12245 */ + 0x0000, /* R12246 */ + 0x0000, /* R12247 */ + 0x0000, /* R12248 */ + 0x0000, /* R12249 */ + 0x0000, /* R12250 */ + 0x0000, /* R12251 */ + 0x0000, /* R12252 */ + 0x0000, /* R12253 */ + 0x0000, /* R12254 */ + 0x0000, /* R12255 */ + 0x0000, /* R12256 */ + 0x0000, /* R12257 */ + 0x0000, /* R12258 */ + 0x0000, /* R12259 */ + 0x0000, /* R12260 */ + 0x0000, /* R12261 */ + 0x0000, /* R12262 */ + 0x0000, /* R12263 */ + 0x0000, /* R12264 */ + 0x0000, /* R12265 */ + 0x0000, /* R12266 */ + 0x0000, /* R12267 */ + 0x0000, /* R12268 */ + 0x0000, /* R12269 */ + 0x0000, /* R12270 */ + 0x0000, /* R12271 */ + 0x0000, /* R12272 */ + 0x0000, /* R12273 */ + 0x0000, /* R12274 */ + 0x0000, /* R12275 */ + 0x0000, /* R12276 */ + 0x0000, /* R12277 */ + 0x0000, /* R12278 */ + 0x0000, /* R12279 */ + 0x0000, /* R12280 */ + 0x0000, /* R12281 */ + 0x0000, /* R12282 */ + 0x0000, /* R12283 */ + 0x0000, /* R12284 */ + 0x0000, /* R12285 */ + 0x0000, /* R12286 */ + 0x0000, /* R12287 */ + 0x0000, /* R12288 - DSP2 Data1 RAM 1 */ + 0x0000, /* R12289 - DSP2 Data1 RAM 0 */ + 0x0000, /* R12290 */ + 0x0000, /* R12291 */ + 0x0000, /* R12292 */ + 0x0000, /* R12293 */ + 0x0000, /* R12294 */ + 0x0000, /* R12295 */ + 0x0000, /* R12296 */ + 0x0000, /* R12297 */ + 0x0000, /* R12298 */ + 0x0000, /* R12299 */ + 0x0000, /* R12300 */ + 0x0000, /* R12301 */ + 0x0000, /* R12302 */ + 0x0000, /* R12303 */ + 0x0000, /* R12304 */ + 0x0000, /* R12305 */ + 0x0000, /* R12306 */ + 0x0000, /* R12307 */ + 0x0000, /* R12308 */ + 0x0000, /* R12309 */ + 0x0000, /* R12310 */ + 0x0000, /* R12311 */ + 0x0000, /* R12312 */ + 0x0000, /* R12313 */ + 0x0000, /* R12314 */ + 0x0000, /* R12315 */ + 0x0000, /* R12316 */ + 0x0000, /* R12317 */ + 0x0000, /* R12318 */ + 0x0000, /* R12319 */ + 0x0000, /* R12320 */ + 0x0000, /* R12321 */ + 0x0000, /* R12322 */ + 0x0000, /* R12323 */ + 0x0000, /* R12324 */ + 0x0000, /* R12325 */ + 0x0000, /* R12326 */ + 0x0000, /* R12327 */ + 0x0000, /* R12328 */ + 0x0000, /* R12329 */ + 0x0000, /* R12330 */ + 0x0000, /* R12331 */ + 0x0000, /* R12332 */ + 0x0000, /* R12333 */ + 0x0000, /* R12334 */ + 0x0000, /* R12335 */ + 0x0000, /* R12336 */ + 0x0000, /* R12337 */ + 0x0000, /* R12338 */ + 0x0000, /* R12339 */ + 0x0000, /* R12340 */ + 0x0000, /* R12341 */ + 0x0000, /* R12342 */ + 0x0000, /* R12343 */ + 0x0000, /* R12344 */ + 0x0000, /* R12345 */ + 0x0000, /* R12346 */ + 0x0000, /* R12347 */ + 0x0000, /* R12348 */ + 0x0000, /* R12349 */ + 0x0000, /* R12350 */ + 0x0000, /* R12351 */ + 0x0000, /* R12352 */ + 0x0000, /* R12353 */ + 0x0000, /* R12354 */ + 0x0000, /* R12355 */ + 0x0000, /* R12356 */ + 0x0000, /* R12357 */ + 0x0000, /* R12358 */ + 0x0000, /* R12359 */ + 0x0000, /* R12360 */ + 0x0000, /* R12361 */ + 0x0000, /* R12362 */ + 0x0000, /* R12363 */ + 0x0000, /* R12364 */ + 0x0000, /* R12365 */ + 0x0000, /* R12366 */ + 0x0000, /* R12367 */ + 0x0000, /* R12368 */ + 0x0000, /* R12369 */ + 0x0000, /* R12370 */ + 0x0000, /* R12371 */ + 0x0000, /* R12372 */ + 0x0000, /* R12373 */ + 0x0000, /* R12374 */ + 0x0000, /* R12375 */ + 0x0000, /* R12376 */ + 0x0000, /* R12377 */ + 0x0000, /* R12378 */ + 0x0000, /* R12379 */ + 0x0000, /* R12380 */ + 0x0000, /* R12381 */ + 0x0000, /* R12382 */ + 0x0000, /* R12383 */ + 0x0000, /* R12384 */ + 0x0000, /* R12385 */ + 0x0000, /* R12386 */ + 0x0000, /* R12387 */ + 0x0000, /* R12388 */ + 0x0000, /* R12389 */ + 0x0000, /* R12390 */ + 0x0000, /* R12391 */ + 0x0000, /* R12392 */ + 0x0000, /* R12393 */ + 0x0000, /* R12394 */ + 0x0000, /* R12395 */ + 0x0000, /* R12396 */ + 0x0000, /* R12397 */ + 0x0000, /* R12398 */ + 0x0000, /* R12399 */ + 0x0000, /* R12400 */ + 0x0000, /* R12401 */ + 0x0000, /* R12402 */ + 0x0000, /* R12403 */ + 0x0000, /* R12404 */ + 0x0000, /* R12405 */ + 0x0000, /* R12406 */ + 0x0000, /* R12407 */ + 0x0000, /* R12408 */ + 0x0000, /* R12409 */ + 0x0000, /* R12410 */ + 0x0000, /* R12411 */ + 0x0000, /* R12412 */ + 0x0000, /* R12413 */ + 0x0000, /* R12414 */ + 0x0000, /* R12415 */ + 0x0000, /* R12416 */ + 0x0000, /* R12417 */ + 0x0000, /* R12418 */ + 0x0000, /* R12419 */ + 0x0000, /* R12420 */ + 0x0000, /* R12421 */ + 0x0000, /* R12422 */ + 0x0000, /* R12423 */ + 0x0000, /* R12424 */ + 0x0000, /* R12425 */ + 0x0000, /* R12426 */ + 0x0000, /* R12427 */ + 0x0000, /* R12428 */ + 0x0000, /* R12429 */ + 0x0000, /* R12430 */ + 0x0000, /* R12431 */ + 0x0000, /* R12432 */ + 0x0000, /* R12433 */ + 0x0000, /* R12434 */ + 0x0000, /* R12435 */ + 0x0000, /* R12436 */ + 0x0000, /* R12437 */ + 0x0000, /* R12438 */ + 0x0000, /* R12439 */ + 0x0000, /* R12440 */ + 0x0000, /* R12441 */ + 0x0000, /* R12442 */ + 0x0000, /* R12443 */ + 0x0000, /* R12444 */ + 0x0000, /* R12445 */ + 0x0000, /* R12446 */ + 0x0000, /* R12447 */ + 0x0000, /* R12448 */ + 0x0000, /* R12449 */ + 0x0000, /* R12450 */ + 0x0000, /* R12451 */ + 0x0000, /* R12452 */ + 0x0000, /* R12453 */ + 0x0000, /* R12454 */ + 0x0000, /* R12455 */ + 0x0000, /* R12456 */ + 0x0000, /* R12457 */ + 0x0000, /* R12458 */ + 0x0000, /* R12459 */ + 0x0000, /* R12460 */ + 0x0000, /* R12461 */ + 0x0000, /* R12462 */ + 0x0000, /* R12463 */ + 0x0000, /* R12464 */ + 0x0000, /* R12465 */ + 0x0000, /* R12466 */ + 0x0000, /* R12467 */ + 0x0000, /* R12468 */ + 0x0000, /* R12469 */ + 0x0000, /* R12470 */ + 0x0000, /* R12471 */ + 0x0000, /* R12472 */ + 0x0000, /* R12473 */ + 0x0000, /* R12474 */ + 0x0000, /* R12475 */ + 0x0000, /* R12476 */ + 0x0000, /* R12477 */ + 0x0000, /* R12478 */ + 0x0000, /* R12479 */ + 0x0000, /* R12480 */ + 0x0000, /* R12481 */ + 0x0000, /* R12482 */ + 0x0000, /* R12483 */ + 0x0000, /* R12484 */ + 0x0000, /* R12485 */ + 0x0000, /* R12486 */ + 0x0000, /* R12487 */ + 0x0000, /* R12488 */ + 0x0000, /* R12489 */ + 0x0000, /* R12490 */ + 0x0000, /* R12491 */ + 0x0000, /* R12492 */ + 0x0000, /* R12493 */ + 0x0000, /* R12494 */ + 0x0000, /* R12495 */ + 0x0000, /* R12496 */ + 0x0000, /* R12497 */ + 0x0000, /* R12498 */ + 0x0000, /* R12499 */ + 0x0000, /* R12500 */ + 0x0000, /* R12501 */ + 0x0000, /* R12502 */ + 0x0000, /* R12503 */ + 0x0000, /* R12504 */ + 0x0000, /* R12505 */ + 0x0000, /* R12506 */ + 0x0000, /* R12507 */ + 0x0000, /* R12508 */ + 0x0000, /* R12509 */ + 0x0000, /* R12510 */ + 0x0000, /* R12511 */ + 0x0000, /* R12512 */ + 0x0000, /* R12513 */ + 0x0000, /* R12514 */ + 0x0000, /* R12515 */ + 0x0000, /* R12516 */ + 0x0000, /* R12517 */ + 0x0000, /* R12518 */ + 0x0000, /* R12519 */ + 0x0000, /* R12520 */ + 0x0000, /* R12521 */ + 0x0000, /* R12522 */ + 0x0000, /* R12523 */ + 0x0000, /* R12524 */ + 0x0000, /* R12525 */ + 0x0000, /* R12526 */ + 0x0000, /* R12527 */ + 0x0000, /* R12528 */ + 0x0000, /* R12529 */ + 0x0000, /* R12530 */ + 0x0000, /* R12531 */ + 0x0000, /* R12532 */ + 0x0000, /* R12533 */ + 0x0000, /* R12534 */ + 0x0000, /* R12535 */ + 0x0000, /* R12536 */ + 0x0000, /* R12537 */ + 0x0000, /* R12538 */ + 0x0000, /* R12539 */ + 0x0000, /* R12540 */ + 0x0000, /* R12541 */ + 0x0000, /* R12542 */ + 0x0000, /* R12543 */ + 0x0000, /* R12544 */ + 0x0000, /* R12545 */ + 0x0000, /* R12546 */ + 0x0000, /* R12547 */ + 0x0000, /* R12548 */ + 0x0000, /* R12549 */ + 0x0000, /* R12550 */ + 0x0000, /* R12551 */ + 0x0000, /* R12552 */ + 0x0000, /* R12553 */ + 0x0000, /* R12554 */ + 0x0000, /* R12555 */ + 0x0000, /* R12556 */ + 0x0000, /* R12557 */ + 0x0000, /* R12558 */ + 0x0000, /* R12559 */ + 0x0000, /* R12560 */ + 0x0000, /* R12561 */ + 0x0000, /* R12562 */ + 0x0000, /* R12563 */ + 0x0000, /* R12564 */ + 0x0000, /* R12565 */ + 0x0000, /* R12566 */ + 0x0000, /* R12567 */ + 0x0000, /* R12568 */ + 0x0000, /* R12569 */ + 0x0000, /* R12570 */ + 0x0000, /* R12571 */ + 0x0000, /* R12572 */ + 0x0000, /* R12573 */ + 0x0000, /* R12574 */ + 0x0000, /* R12575 */ + 0x0000, /* R12576 */ + 0x0000, /* R12577 */ + 0x0000, /* R12578 */ + 0x0000, /* R12579 */ + 0x0000, /* R12580 */ + 0x0000, /* R12581 */ + 0x0000, /* R12582 */ + 0x0000, /* R12583 */ + 0x0000, /* R12584 */ + 0x0000, /* R12585 */ + 0x0000, /* R12586 */ + 0x0000, /* R12587 */ + 0x0000, /* R12588 */ + 0x0000, /* R12589 */ + 0x0000, /* R12590 */ + 0x0000, /* R12591 */ + 0x0000, /* R12592 */ + 0x0000, /* R12593 */ + 0x0000, /* R12594 */ + 0x0000, /* R12595 */ + 0x0000, /* R12596 */ + 0x0000, /* R12597 */ + 0x0000, /* R12598 */ + 0x0000, /* R12599 */ + 0x0000, /* R12600 */ + 0x0000, /* R12601 */ + 0x0000, /* R12602 */ + 0x0000, /* R12603 */ + 0x0000, /* R12604 */ + 0x0000, /* R12605 */ + 0x0000, /* R12606 */ + 0x0000, /* R12607 */ + 0x0000, /* R12608 */ + 0x0000, /* R12609 */ + 0x0000, /* R12610 */ + 0x0000, /* R12611 */ + 0x0000, /* R12612 */ + 0x0000, /* R12613 */ + 0x0000, /* R12614 */ + 0x0000, /* R12615 */ + 0x0000, /* R12616 */ + 0x0000, /* R12617 */ + 0x0000, /* R12618 */ + 0x0000, /* R12619 */ + 0x0000, /* R12620 */ + 0x0000, /* R12621 */ + 0x0000, /* R12622 */ + 0x0000, /* R12623 */ + 0x0000, /* R12624 */ + 0x0000, /* R12625 */ + 0x0000, /* R12626 */ + 0x0000, /* R12627 */ + 0x0000, /* R12628 */ + 0x0000, /* R12629 */ + 0x0000, /* R12630 */ + 0x0000, /* R12631 */ + 0x0000, /* R12632 */ + 0x0000, /* R12633 */ + 0x0000, /* R12634 */ + 0x0000, /* R12635 */ + 0x0000, /* R12636 */ + 0x0000, /* R12637 */ + 0x0000, /* R12638 */ + 0x0000, /* R12639 */ + 0x0000, /* R12640 */ + 0x0000, /* R12641 */ + 0x0000, /* R12642 */ + 0x0000, /* R12643 */ + 0x0000, /* R12644 */ + 0x0000, /* R12645 */ + 0x0000, /* R12646 */ + 0x0000, /* R12647 */ + 0x0000, /* R12648 */ + 0x0000, /* R12649 */ + 0x0000, /* R12650 */ + 0x0000, /* R12651 */ + 0x0000, /* R12652 */ + 0x0000, /* R12653 */ + 0x0000, /* R12654 */ + 0x0000, /* R12655 */ + 0x0000, /* R12656 */ + 0x0000, /* R12657 */ + 0x0000, /* R12658 */ + 0x0000, /* R12659 */ + 0x0000, /* R12660 */ + 0x0000, /* R12661 */ + 0x0000, /* R12662 */ + 0x0000, /* R12663 */ + 0x0000, /* R12664 */ + 0x0000, /* R12665 */ + 0x0000, /* R12666 */ + 0x0000, /* R12667 */ + 0x0000, /* R12668 */ + 0x0000, /* R12669 */ + 0x0000, /* R12670 */ + 0x0000, /* R12671 */ + 0x0000, /* R12672 */ + 0x0000, /* R12673 */ + 0x0000, /* R12674 */ + 0x0000, /* R12675 */ + 0x0000, /* R12676 */ + 0x0000, /* R12677 */ + 0x0000, /* R12678 */ + 0x0000, /* R12679 */ + 0x0000, /* R12680 */ + 0x0000, /* R12681 */ + 0x0000, /* R12682 */ + 0x0000, /* R12683 */ + 0x0000, /* R12684 */ + 0x0000, /* R12685 */ + 0x0000, /* R12686 */ + 0x0000, /* R12687 */ + 0x0000, /* R12688 */ + 0x0000, /* R12689 */ + 0x0000, /* R12690 */ + 0x0000, /* R12691 */ + 0x0000, /* R12692 */ + 0x0000, /* R12693 */ + 0x0000, /* R12694 */ + 0x0000, /* R12695 */ + 0x0000, /* R12696 */ + 0x0000, /* R12697 */ + 0x0000, /* R12698 */ + 0x0000, /* R12699 */ + 0x0000, /* R12700 */ + 0x0000, /* R12701 */ + 0x0000, /* R12702 */ + 0x0000, /* R12703 */ + 0x0000, /* R12704 */ + 0x0000, /* R12705 */ + 0x0000, /* R12706 */ + 0x0000, /* R12707 */ + 0x0000, /* R12708 */ + 0x0000, /* R12709 */ + 0x0000, /* R12710 */ + 0x0000, /* R12711 */ + 0x0000, /* R12712 */ + 0x0000, /* R12713 */ + 0x0000, /* R12714 */ + 0x0000, /* R12715 */ + 0x0000, /* R12716 */ + 0x0000, /* R12717 */ + 0x0000, /* R12718 */ + 0x0000, /* R12719 */ + 0x0000, /* R12720 */ + 0x0000, /* R12721 */ + 0x0000, /* R12722 */ + 0x0000, /* R12723 */ + 0x0000, /* R12724 */ + 0x0000, /* R12725 */ + 0x0000, /* R12726 */ + 0x0000, /* R12727 */ + 0x0000, /* R12728 */ + 0x0000, /* R12729 */ + 0x0000, /* R12730 */ + 0x0000, /* R12731 */ + 0x0000, /* R12732 */ + 0x0000, /* R12733 */ + 0x0000, /* R12734 */ + 0x0000, /* R12735 */ + 0x0000, /* R12736 */ + 0x0000, /* R12737 */ + 0x0000, /* R12738 */ + 0x0000, /* R12739 */ + 0x0000, /* R12740 */ + 0x0000, /* R12741 */ + 0x0000, /* R12742 */ + 0x0000, /* R12743 */ + 0x0000, /* R12744 */ + 0x0000, /* R12745 */ + 0x0000, /* R12746 */ + 0x0000, /* R12747 */ + 0x0000, /* R12748 */ + 0x0000, /* R12749 */ + 0x0000, /* R12750 */ + 0x0000, /* R12751 */ + 0x0000, /* R12752 */ + 0x0000, /* R12753 */ + 0x0000, /* R12754 */ + 0x0000, /* R12755 */ + 0x0000, /* R12756 */ + 0x0000, /* R12757 */ + 0x0000, /* R12758 */ + 0x0000, /* R12759 */ + 0x0000, /* R12760 */ + 0x0000, /* R12761 */ + 0x0000, /* R12762 */ + 0x0000, /* R12763 */ + 0x0000, /* R12764 */ + 0x0000, /* R12765 */ + 0x0000, /* R12766 */ + 0x0000, /* R12767 */ + 0x0000, /* R12768 */ + 0x0000, /* R12769 */ + 0x0000, /* R12770 */ + 0x0000, /* R12771 */ + 0x0000, /* R12772 */ + 0x0000, /* R12773 */ + 0x0000, /* R12774 */ + 0x0000, /* R12775 */ + 0x0000, /* R12776 */ + 0x0000, /* R12777 */ + 0x0000, /* R12778 */ + 0x0000, /* R12779 */ + 0x0000, /* R12780 */ + 0x0000, /* R12781 */ + 0x0000, /* R12782 */ + 0x0000, /* R12783 */ + 0x0000, /* R12784 */ + 0x0000, /* R12785 */ + 0x0000, /* R12786 */ + 0x0000, /* R12787 */ + 0x0000, /* R12788 */ + 0x0000, /* R12789 */ + 0x0000, /* R12790 */ + 0x0000, /* R12791 */ + 0x0000, /* R12792 */ + 0x0000, /* R12793 */ + 0x0000, /* R12794 */ + 0x0000, /* R12795 */ + 0x0000, /* R12796 */ + 0x0000, /* R12797 */ + 0x0000, /* R12798 */ + 0x0000, /* R12799 */ + 0x0000, /* R12800 */ + 0x0000, /* R12801 */ + 0x0000, /* R12802 */ + 0x0000, /* R12803 */ + 0x0000, /* R12804 */ + 0x0000, /* R12805 */ + 0x0000, /* R12806 */ + 0x0000, /* R12807 */ + 0x0000, /* R12808 */ + 0x0000, /* R12809 */ + 0x0000, /* R12810 */ + 0x0000, /* R12811 */ + 0x0000, /* R12812 */ + 0x0000, /* R12813 */ + 0x0000, /* R12814 */ + 0x0000, /* R12815 */ + 0x0000, /* R12816 */ + 0x0000, /* R12817 */ + 0x0000, /* R12818 */ + 0x0000, /* R12819 */ + 0x0000, /* R12820 */ + 0x0000, /* R12821 */ + 0x0000, /* R12822 */ + 0x0000, /* R12823 */ + 0x0000, /* R12824 */ + 0x0000, /* R12825 */ + 0x0000, /* R12826 */ + 0x0000, /* R12827 */ + 0x0000, /* R12828 */ + 0x0000, /* R12829 */ + 0x0000, /* R12830 */ + 0x0000, /* R12831 */ + 0x0000, /* R12832 */ + 0x0000, /* R12833 */ + 0x0000, /* R12834 */ + 0x0000, /* R12835 */ + 0x0000, /* R12836 */ + 0x0000, /* R12837 */ + 0x0000, /* R12838 */ + 0x0000, /* R12839 */ + 0x0000, /* R12840 */ + 0x0000, /* R12841 */ + 0x0000, /* R12842 */ + 0x0000, /* R12843 */ + 0x0000, /* R12844 */ + 0x0000, /* R12845 */ + 0x0000, /* R12846 */ + 0x0000, /* R12847 */ + 0x0000, /* R12848 */ + 0x0000, /* R12849 */ + 0x0000, /* R12850 */ + 0x0000, /* R12851 */ + 0x0000, /* R12852 */ + 0x0000, /* R12853 */ + 0x0000, /* R12854 */ + 0x0000, /* R12855 */ + 0x0000, /* R12856 */ + 0x0000, /* R12857 */ + 0x0000, /* R12858 */ + 0x0000, /* R12859 */ + 0x0000, /* R12860 */ + 0x0000, /* R12861 */ + 0x0000, /* R12862 */ + 0x0000, /* R12863 */ + 0x0000, /* R12864 */ + 0x0000, /* R12865 */ + 0x0000, /* R12866 */ + 0x0000, /* R12867 */ + 0x0000, /* R12868 */ + 0x0000, /* R12869 */ + 0x0000, /* R12870 */ + 0x0000, /* R12871 */ + 0x0000, /* R12872 */ + 0x0000, /* R12873 */ + 0x0000, /* R12874 */ + 0x0000, /* R12875 */ + 0x0000, /* R12876 */ + 0x0000, /* R12877 */ + 0x0000, /* R12878 */ + 0x0000, /* R12879 */ + 0x0000, /* R12880 */ + 0x0000, /* R12881 */ + 0x0000, /* R12882 */ + 0x0000, /* R12883 */ + 0x0000, /* R12884 */ + 0x0000, /* R12885 */ + 0x0000, /* R12886 */ + 0x0000, /* R12887 */ + 0x0000, /* R12888 */ + 0x0000, /* R12889 */ + 0x0000, /* R12890 */ + 0x0000, /* R12891 */ + 0x0000, /* R12892 */ + 0x0000, /* R12893 */ + 0x0000, /* R12894 */ + 0x0000, /* R12895 */ + 0x0000, /* R12896 */ + 0x0000, /* R12897 */ + 0x0000, /* R12898 */ + 0x0000, /* R12899 */ + 0x0000, /* R12900 */ + 0x0000, /* R12901 */ + 0x0000, /* R12902 */ + 0x0000, /* R12903 */ + 0x0000, /* R12904 */ + 0x0000, /* R12905 */ + 0x0000, /* R12906 */ + 0x0000, /* R12907 */ + 0x0000, /* R12908 */ + 0x0000, /* R12909 */ + 0x0000, /* R12910 */ + 0x0000, /* R12911 */ + 0x0000, /* R12912 */ + 0x0000, /* R12913 */ + 0x0000, /* R12914 */ + 0x0000, /* R12915 */ + 0x0000, /* R12916 */ + 0x0000, /* R12917 */ + 0x0000, /* R12918 */ + 0x0000, /* R12919 */ + 0x0000, /* R12920 */ + 0x0000, /* R12921 */ + 0x0000, /* R12922 */ + 0x0000, /* R12923 */ + 0x0000, /* R12924 */ + 0x0000, /* R12925 */ + 0x0000, /* R12926 */ + 0x0000, /* R12927 */ + 0x0000, /* R12928 */ + 0x0000, /* R12929 */ + 0x0000, /* R12930 */ + 0x0000, /* R12931 */ + 0x0000, /* R12932 */ + 0x0000, /* R12933 */ + 0x0000, /* R12934 */ + 0x0000, /* R12935 */ + 0x0000, /* R12936 */ + 0x0000, /* R12937 */ + 0x0000, /* R12938 */ + 0x0000, /* R12939 */ + 0x0000, /* R12940 */ + 0x0000, /* R12941 */ + 0x0000, /* R12942 */ + 0x0000, /* R12943 */ + 0x0000, /* R12944 */ + 0x0000, /* R12945 */ + 0x0000, /* R12946 */ + 0x0000, /* R12947 */ + 0x0000, /* R12948 */ + 0x0000, /* R12949 */ + 0x0000, /* R12950 */ + 0x0000, /* R12951 */ + 0x0000, /* R12952 */ + 0x0000, /* R12953 */ + 0x0000, /* R12954 */ + 0x0000, /* R12955 */ + 0x0000, /* R12956 */ + 0x0000, /* R12957 */ + 0x0000, /* R12958 */ + 0x0000, /* R12959 */ + 0x0000, /* R12960 */ + 0x0000, /* R12961 */ + 0x0000, /* R12962 */ + 0x0000, /* R12963 */ + 0x0000, /* R12964 */ + 0x0000, /* R12965 */ + 0x0000, /* R12966 */ + 0x0000, /* R12967 */ + 0x0000, /* R12968 */ + 0x0000, /* R12969 */ + 0x0000, /* R12970 */ + 0x0000, /* R12971 */ + 0x0000, /* R12972 */ + 0x0000, /* R12973 */ + 0x0000, /* R12974 */ + 0x0000, /* R12975 */ + 0x0000, /* R12976 */ + 0x0000, /* R12977 */ + 0x0000, /* R12978 */ + 0x0000, /* R12979 */ + 0x0000, /* R12980 */ + 0x0000, /* R12981 */ + 0x0000, /* R12982 */ + 0x0000, /* R12983 */ + 0x0000, /* R12984 */ + 0x0000, /* R12985 */ + 0x0000, /* R12986 */ + 0x0000, /* R12987 */ + 0x0000, /* R12988 */ + 0x0000, /* R12989 */ + 0x0000, /* R12990 */ + 0x0000, /* R12991 */ + 0x0000, /* R12992 */ + 0x0000, /* R12993 */ + 0x0000, /* R12994 */ + 0x0000, /* R12995 */ + 0x0000, /* R12996 */ + 0x0000, /* R12997 */ + 0x0000, /* R12998 */ + 0x0000, /* R12999 */ + 0x0000, /* R13000 */ + 0x0000, /* R13001 */ + 0x0000, /* R13002 */ + 0x0000, /* R13003 */ + 0x0000, /* R13004 */ + 0x0000, /* R13005 */ + 0x0000, /* R13006 */ + 0x0000, /* R13007 */ + 0x0000, /* R13008 */ + 0x0000, /* R13009 */ + 0x0000, /* R13010 */ + 0x0000, /* R13011 */ + 0x0000, /* R13012 */ + 0x0000, /* R13013 */ + 0x0000, /* R13014 */ + 0x0000, /* R13015 */ + 0x0000, /* R13016 */ + 0x0000, /* R13017 */ + 0x0000, /* R13018 */ + 0x0000, /* R13019 */ + 0x0000, /* R13020 */ + 0x0000, /* R13021 */ + 0x0000, /* R13022 */ + 0x0000, /* R13023 */ + 0x0000, /* R13024 */ + 0x0000, /* R13025 */ + 0x0000, /* R13026 */ + 0x0000, /* R13027 */ + 0x0000, /* R13028 */ + 0x0000, /* R13029 */ + 0x0000, /* R13030 */ + 0x0000, /* R13031 */ + 0x0000, /* R13032 */ + 0x0000, /* R13033 */ + 0x0000, /* R13034 */ + 0x0000, /* R13035 */ + 0x0000, /* R13036 */ + 0x0000, /* R13037 */ + 0x0000, /* R13038 */ + 0x0000, /* R13039 */ + 0x0000, /* R13040 */ + 0x0000, /* R13041 */ + 0x0000, /* R13042 */ + 0x0000, /* R13043 */ + 0x0000, /* R13044 */ + 0x0000, /* R13045 */ + 0x0000, /* R13046 */ + 0x0000, /* R13047 */ + 0x0000, /* R13048 */ + 0x0000, /* R13049 */ + 0x0000, /* R13050 */ + 0x0000, /* R13051 */ + 0x0000, /* R13052 */ + 0x0000, /* R13053 */ + 0x0000, /* R13054 */ + 0x0000, /* R13055 */ + 0x0000, /* R13056 */ + 0x0000, /* R13057 */ + 0x0000, /* R13058 */ + 0x0000, /* R13059 */ + 0x0000, /* R13060 */ + 0x0000, /* R13061 */ + 0x0000, /* R13062 */ + 0x0000, /* R13063 */ + 0x0000, /* R13064 */ + 0x0000, /* R13065 */ + 0x0000, /* R13066 */ + 0x0000, /* R13067 */ + 0x0000, /* R13068 */ + 0x0000, /* R13069 */ + 0x0000, /* R13070 */ + 0x0000, /* R13071 */ + 0x0000, /* R13072 */ + 0x0000, /* R13073 */ + 0x0000, /* R13074 */ + 0x0000, /* R13075 */ + 0x0000, /* R13076 */ + 0x0000, /* R13077 */ + 0x0000, /* R13078 */ + 0x0000, /* R13079 */ + 0x0000, /* R13080 */ + 0x0000, /* R13081 */ + 0x0000, /* R13082 */ + 0x0000, /* R13083 */ + 0x0000, /* R13084 */ + 0x0000, /* R13085 */ + 0x0000, /* R13086 */ + 0x0000, /* R13087 */ + 0x0000, /* R13088 */ + 0x0000, /* R13089 */ + 0x0000, /* R13090 */ + 0x0000, /* R13091 */ + 0x0000, /* R13092 */ + 0x0000, /* R13093 */ + 0x0000, /* R13094 */ + 0x0000, /* R13095 */ + 0x0000, /* R13096 */ + 0x0000, /* R13097 */ + 0x0000, /* R13098 */ + 0x0000, /* R13099 */ + 0x0000, /* R13100 */ + 0x0000, /* R13101 */ + 0x0000, /* R13102 */ + 0x0000, /* R13103 */ + 0x0000, /* R13104 */ + 0x0000, /* R13105 */ + 0x0000, /* R13106 */ + 0x0000, /* R13107 */ + 0x0000, /* R13108 */ + 0x0000, /* R13109 */ + 0x0000, /* R13110 */ + 0x0000, /* R13111 */ + 0x0000, /* R13112 */ + 0x0000, /* R13113 */ + 0x0000, /* R13114 */ + 0x0000, /* R13115 */ + 0x0000, /* R13116 */ + 0x0000, /* R13117 */ + 0x0000, /* R13118 */ + 0x0000, /* R13119 */ + 0x0000, /* R13120 */ + 0x0000, /* R13121 */ + 0x0000, /* R13122 */ + 0x0000, /* R13123 */ + 0x0000, /* R13124 */ + 0x0000, /* R13125 */ + 0x0000, /* R13126 */ + 0x0000, /* R13127 */ + 0x0000, /* R13128 */ + 0x0000, /* R13129 */ + 0x0000, /* R13130 */ + 0x0000, /* R13131 */ + 0x0000, /* R13132 */ + 0x0000, /* R13133 */ + 0x0000, /* R13134 */ + 0x0000, /* R13135 */ + 0x0000, /* R13136 */ + 0x0000, /* R13137 */ + 0x0000, /* R13138 */ + 0x0000, /* R13139 */ + 0x0000, /* R13140 */ + 0x0000, /* R13141 */ + 0x0000, /* R13142 */ + 0x0000, /* R13143 */ + 0x0000, /* R13144 */ + 0x0000, /* R13145 */ + 0x0000, /* R13146 */ + 0x0000, /* R13147 */ + 0x0000, /* R13148 */ + 0x0000, /* R13149 */ + 0x0000, /* R13150 */ + 0x0000, /* R13151 */ + 0x0000, /* R13152 */ + 0x0000, /* R13153 */ + 0x0000, /* R13154 */ + 0x0000, /* R13155 */ + 0x0000, /* R13156 */ + 0x0000, /* R13157 */ + 0x0000, /* R13158 */ + 0x0000, /* R13159 */ + 0x0000, /* R13160 */ + 0x0000, /* R13161 */ + 0x0000, /* R13162 */ + 0x0000, /* R13163 */ + 0x0000, /* R13164 */ + 0x0000, /* R13165 */ + 0x0000, /* R13166 */ + 0x0000, /* R13167 */ + 0x0000, /* R13168 */ + 0x0000, /* R13169 */ + 0x0000, /* R13170 */ + 0x0000, /* R13171 */ + 0x0000, /* R13172 */ + 0x0000, /* R13173 */ + 0x0000, /* R13174 */ + 0x0000, /* R13175 */ + 0x0000, /* R13176 */ + 0x0000, /* R13177 */ + 0x0000, /* R13178 */ + 0x0000, /* R13179 */ + 0x0000, /* R13180 */ + 0x0000, /* R13181 */ + 0x0000, /* R13182 */ + 0x0000, /* R13183 */ + 0x0000, /* R13184 */ + 0x0000, /* R13185 */ + 0x0000, /* R13186 */ + 0x0000, /* R13187 */ + 0x0000, /* R13188 */ + 0x0000, /* R13189 */ + 0x0000, /* R13190 */ + 0x0000, /* R13191 */ + 0x0000, /* R13192 */ + 0x0000, /* R13193 */ + 0x0000, /* R13194 */ + 0x0000, /* R13195 */ + 0x0000, /* R13196 */ + 0x0000, /* R13197 */ + 0x0000, /* R13198 */ + 0x0000, /* R13199 */ + 0x0000, /* R13200 */ + 0x0000, /* R13201 */ + 0x0000, /* R13202 */ + 0x0000, /* R13203 */ + 0x0000, /* R13204 */ + 0x0000, /* R13205 */ + 0x0000, /* R13206 */ + 0x0000, /* R13207 */ + 0x0000, /* R13208 */ + 0x0000, /* R13209 */ + 0x0000, /* R13210 */ + 0x0000, /* R13211 */ + 0x0000, /* R13212 */ + 0x0000, /* R13213 */ + 0x0000, /* R13214 */ + 0x0000, /* R13215 */ + 0x0000, /* R13216 */ + 0x0000, /* R13217 */ + 0x0000, /* R13218 */ + 0x0000, /* R13219 */ + 0x0000, /* R13220 */ + 0x0000, /* R13221 */ + 0x0000, /* R13222 */ + 0x0000, /* R13223 */ + 0x0000, /* R13224 */ + 0x0000, /* R13225 */ + 0x0000, /* R13226 */ + 0x0000, /* R13227 */ + 0x0000, /* R13228 */ + 0x0000, /* R13229 */ + 0x0000, /* R13230 */ + 0x0000, /* R13231 */ + 0x0000, /* R13232 */ + 0x0000, /* R13233 */ + 0x0000, /* R13234 */ + 0x0000, /* R13235 */ + 0x0000, /* R13236 */ + 0x0000, /* R13237 */ + 0x0000, /* R13238 */ + 0x0000, /* R13239 */ + 0x0000, /* R13240 */ + 0x0000, /* R13241 */ + 0x0000, /* R13242 */ + 0x0000, /* R13243 */ + 0x0000, /* R13244 */ + 0x0000, /* R13245 */ + 0x0000, /* R13246 */ + 0x0000, /* R13247 */ + 0x0000, /* R13248 */ + 0x0000, /* R13249 */ + 0x0000, /* R13250 */ + 0x0000, /* R13251 */ + 0x0000, /* R13252 */ + 0x0000, /* R13253 */ + 0x0000, /* R13254 */ + 0x0000, /* R13255 */ + 0x0000, /* R13256 */ + 0x0000, /* R13257 */ + 0x0000, /* R13258 */ + 0x0000, /* R13259 */ + 0x0000, /* R13260 */ + 0x0000, /* R13261 */ + 0x0000, /* R13262 */ + 0x0000, /* R13263 */ + 0x0000, /* R13264 */ + 0x0000, /* R13265 */ + 0x0000, /* R13266 */ + 0x0000, /* R13267 */ + 0x0000, /* R13268 */ + 0x0000, /* R13269 */ + 0x0000, /* R13270 */ + 0x0000, /* R13271 */ + 0x0000, /* R13272 */ + 0x0000, /* R13273 */ + 0x0000, /* R13274 */ + 0x0000, /* R13275 */ + 0x0000, /* R13276 */ + 0x0000, /* R13277 */ + 0x0000, /* R13278 */ + 0x0000, /* R13279 */ + 0x0000, /* R13280 */ + 0x0000, /* R13281 */ + 0x0000, /* R13282 */ + 0x0000, /* R13283 */ + 0x0000, /* R13284 */ + 0x0000, /* R13285 */ + 0x0000, /* R13286 */ + 0x0000, /* R13287 */ + 0x0000, /* R13288 */ + 0x0000, /* R13289 */ + 0x0000, /* R13290 */ + 0x0000, /* R13291 */ + 0x0000, /* R13292 */ + 0x0000, /* R13293 */ + 0x0000, /* R13294 */ + 0x0000, /* R13295 */ + 0x0000, /* R13296 */ + 0x0000, /* R13297 */ + 0x0000, /* R13298 */ + 0x0000, /* R13299 */ + 0x0000, /* R13300 */ + 0x0000, /* R13301 */ + 0x0000, /* R13302 */ + 0x0000, /* R13303 */ + 0x0000, /* R13304 */ + 0x0000, /* R13305 */ + 0x0000, /* R13306 */ + 0x0000, /* R13307 */ + 0x0000, /* R13308 */ + 0x0000, /* R13309 */ + 0x0000, /* R13310 */ + 0x0000, /* R13311 */ + 0x0000, /* R13312 - DSP2 Data2 RAM 1 */ + 0x0000, /* R13313 - DSP2 Data2 RAM 0 */ + 0x0000, /* R13314 */ + 0x0000, /* R13315 */ + 0x0000, /* R13316 */ + 0x0000, /* R13317 */ + 0x0000, /* R13318 */ + 0x0000, /* R13319 */ + 0x0000, /* R13320 */ + 0x0000, /* R13321 */ + 0x0000, /* R13322 */ + 0x0000, /* R13323 */ + 0x0000, /* R13324 */ + 0x0000, /* R13325 */ + 0x0000, /* R13326 */ + 0x0000, /* R13327 */ + 0x0000, /* R13328 */ + 0x0000, /* R13329 */ + 0x0000, /* R13330 */ + 0x0000, /* R13331 */ + 0x0000, /* R13332 */ + 0x0000, /* R13333 */ + 0x0000, /* R13334 */ + 0x0000, /* R13335 */ + 0x0000, /* R13336 */ + 0x0000, /* R13337 */ + 0x0000, /* R13338 */ + 0x0000, /* R13339 */ + 0x0000, /* R13340 */ + 0x0000, /* R13341 */ + 0x0000, /* R13342 */ + 0x0000, /* R13343 */ + 0x0000, /* R13344 */ + 0x0000, /* R13345 */ + 0x0000, /* R13346 */ + 0x0000, /* R13347 */ + 0x0000, /* R13348 */ + 0x0000, /* R13349 */ + 0x0000, /* R13350 */ + 0x0000, /* R13351 */ + 0x0000, /* R13352 */ + 0x0000, /* R13353 */ + 0x0000, /* R13354 */ + 0x0000, /* R13355 */ + 0x0000, /* R13356 */ + 0x0000, /* R13357 */ + 0x0000, /* R13358 */ + 0x0000, /* R13359 */ + 0x0000, /* R13360 */ + 0x0000, /* R13361 */ + 0x0000, /* R13362 */ + 0x0000, /* R13363 */ + 0x0000, /* R13364 */ + 0x0000, /* R13365 */ + 0x0000, /* R13366 */ + 0x0000, /* R13367 */ + 0x0000, /* R13368 */ + 0x0000, /* R13369 */ + 0x0000, /* R13370 */ + 0x0000, /* R13371 */ + 0x0000, /* R13372 */ + 0x0000, /* R13373 */ + 0x0000, /* R13374 */ + 0x0000, /* R13375 */ + 0x0000, /* R13376 */ + 0x0000, /* R13377 */ + 0x0000, /* R13378 */ + 0x0000, /* R13379 */ + 0x0000, /* R13380 */ + 0x0000, /* R13381 */ + 0x0000, /* R13382 */ + 0x0000, /* R13383 */ + 0x0000, /* R13384 */ + 0x0000, /* R13385 */ + 0x0000, /* R13386 */ + 0x0000, /* R13387 */ + 0x0000, /* R13388 */ + 0x0000, /* R13389 */ + 0x0000, /* R13390 */ + 0x0000, /* R13391 */ + 0x0000, /* R13392 */ + 0x0000, /* R13393 */ + 0x0000, /* R13394 */ + 0x0000, /* R13395 */ + 0x0000, /* R13396 */ + 0x0000, /* R13397 */ + 0x0000, /* R13398 */ + 0x0000, /* R13399 */ + 0x0000, /* R13400 */ + 0x0000, /* R13401 */ + 0x0000, /* R13402 */ + 0x0000, /* R13403 */ + 0x0000, /* R13404 */ + 0x0000, /* R13405 */ + 0x0000, /* R13406 */ + 0x0000, /* R13407 */ + 0x0000, /* R13408 */ + 0x0000, /* R13409 */ + 0x0000, /* R13410 */ + 0x0000, /* R13411 */ + 0x0000, /* R13412 */ + 0x0000, /* R13413 */ + 0x0000, /* R13414 */ + 0x0000, /* R13415 */ + 0x0000, /* R13416 */ + 0x0000, /* R13417 */ + 0x0000, /* R13418 */ + 0x0000, /* R13419 */ + 0x0000, /* R13420 */ + 0x0000, /* R13421 */ + 0x0000, /* R13422 */ + 0x0000, /* R13423 */ + 0x0000, /* R13424 */ + 0x0000, /* R13425 */ + 0x0000, /* R13426 */ + 0x0000, /* R13427 */ + 0x0000, /* R13428 */ + 0x0000, /* R13429 */ + 0x0000, /* R13430 */ + 0x0000, /* R13431 */ + 0x0000, /* R13432 */ + 0x0000, /* R13433 */ + 0x0000, /* R13434 */ + 0x0000, /* R13435 */ + 0x0000, /* R13436 */ + 0x0000, /* R13437 */ + 0x0000, /* R13438 */ + 0x0000, /* R13439 */ + 0x0000, /* R13440 */ + 0x0000, /* R13441 */ + 0x0000, /* R13442 */ + 0x0000, /* R13443 */ + 0x0000, /* R13444 */ + 0x0000, /* R13445 */ + 0x0000, /* R13446 */ + 0x0000, /* R13447 */ + 0x0000, /* R13448 */ + 0x0000, /* R13449 */ + 0x0000, /* R13450 */ + 0x0000, /* R13451 */ + 0x0000, /* R13452 */ + 0x0000, /* R13453 */ + 0x0000, /* R13454 */ + 0x0000, /* R13455 */ + 0x0000, /* R13456 */ + 0x0000, /* R13457 */ + 0x0000, /* R13458 */ + 0x0000, /* R13459 */ + 0x0000, /* R13460 */ + 0x0000, /* R13461 */ + 0x0000, /* R13462 */ + 0x0000, /* R13463 */ + 0x0000, /* R13464 */ + 0x0000, /* R13465 */ + 0x0000, /* R13466 */ + 0x0000, /* R13467 */ + 0x0000, /* R13468 */ + 0x0000, /* R13469 */ + 0x0000, /* R13470 */ + 0x0000, /* R13471 */ + 0x0000, /* R13472 */ + 0x0000, /* R13473 */ + 0x0000, /* R13474 */ + 0x0000, /* R13475 */ + 0x0000, /* R13476 */ + 0x0000, /* R13477 */ + 0x0000, /* R13478 */ + 0x0000, /* R13479 */ + 0x0000, /* R13480 */ + 0x0000, /* R13481 */ + 0x0000, /* R13482 */ + 0x0000, /* R13483 */ + 0x0000, /* R13484 */ + 0x0000, /* R13485 */ + 0x0000, /* R13486 */ + 0x0000, /* R13487 */ + 0x0000, /* R13488 */ + 0x0000, /* R13489 */ + 0x0000, /* R13490 */ + 0x0000, /* R13491 */ + 0x0000, /* R13492 */ + 0x0000, /* R13493 */ + 0x0000, /* R13494 */ + 0x0000, /* R13495 */ + 0x0000, /* R13496 */ + 0x0000, /* R13497 */ + 0x0000, /* R13498 */ + 0x0000, /* R13499 */ + 0x0000, /* R13500 */ + 0x0000, /* R13501 */ + 0x0000, /* R13502 */ + 0x0000, /* R13503 */ + 0x0000, /* R13504 */ + 0x0000, /* R13505 */ + 0x0000, /* R13506 */ + 0x0000, /* R13507 */ + 0x0000, /* R13508 */ + 0x0000, /* R13509 */ + 0x0000, /* R13510 */ + 0x0000, /* R13511 */ + 0x0000, /* R13512 */ + 0x0000, /* R13513 */ + 0x0000, /* R13514 */ + 0x0000, /* R13515 */ + 0x0000, /* R13516 */ + 0x0000, /* R13517 */ + 0x0000, /* R13518 */ + 0x0000, /* R13519 */ + 0x0000, /* R13520 */ + 0x0000, /* R13521 */ + 0x0000, /* R13522 */ + 0x0000, /* R13523 */ + 0x0000, /* R13524 */ + 0x0000, /* R13525 */ + 0x0000, /* R13526 */ + 0x0000, /* R13527 */ + 0x0000, /* R13528 */ + 0x0000, /* R13529 */ + 0x0000, /* R13530 */ + 0x0000, /* R13531 */ + 0x0000, /* R13532 */ + 0x0000, /* R13533 */ + 0x0000, /* R13534 */ + 0x0000, /* R13535 */ + 0x0000, /* R13536 */ + 0x0000, /* R13537 */ + 0x0000, /* R13538 */ + 0x0000, /* R13539 */ + 0x0000, /* R13540 */ + 0x0000, /* R13541 */ + 0x0000, /* R13542 */ + 0x0000, /* R13543 */ + 0x0000, /* R13544 */ + 0x0000, /* R13545 */ + 0x0000, /* R13546 */ + 0x0000, /* R13547 */ + 0x0000, /* R13548 */ + 0x0000, /* R13549 */ + 0x0000, /* R13550 */ + 0x0000, /* R13551 */ + 0x0000, /* R13552 */ + 0x0000, /* R13553 */ + 0x0000, /* R13554 */ + 0x0000, /* R13555 */ + 0x0000, /* R13556 */ + 0x0000, /* R13557 */ + 0x0000, /* R13558 */ + 0x0000, /* R13559 */ + 0x0000, /* R13560 */ + 0x0000, /* R13561 */ + 0x0000, /* R13562 */ + 0x0000, /* R13563 */ + 0x0000, /* R13564 */ + 0x0000, /* R13565 */ + 0x0000, /* R13566 */ + 0x0000, /* R13567 */ + 0x0000, /* R13568 */ + 0x0000, /* R13569 */ + 0x0000, /* R13570 */ + 0x0000, /* R13571 */ + 0x0000, /* R13572 */ + 0x0000, /* R13573 */ + 0x0000, /* R13574 */ + 0x0000, /* R13575 */ + 0x0000, /* R13576 */ + 0x0000, /* R13577 */ + 0x0000, /* R13578 */ + 0x0000, /* R13579 */ + 0x0000, /* R13580 */ + 0x0000, /* R13581 */ + 0x0000, /* R13582 */ + 0x0000, /* R13583 */ + 0x0000, /* R13584 */ + 0x0000, /* R13585 */ + 0x0000, /* R13586 */ + 0x0000, /* R13587 */ + 0x0000, /* R13588 */ + 0x0000, /* R13589 */ + 0x0000, /* R13590 */ + 0x0000, /* R13591 */ + 0x0000, /* R13592 */ + 0x0000, /* R13593 */ + 0x0000, /* R13594 */ + 0x0000, /* R13595 */ + 0x0000, /* R13596 */ + 0x0000, /* R13597 */ + 0x0000, /* R13598 */ + 0x0000, /* R13599 */ + 0x0000, /* R13600 */ + 0x0000, /* R13601 */ + 0x0000, /* R13602 */ + 0x0000, /* R13603 */ + 0x0000, /* R13604 */ + 0x0000, /* R13605 */ + 0x0000, /* R13606 */ + 0x0000, /* R13607 */ + 0x0000, /* R13608 */ + 0x0000, /* R13609 */ + 0x0000, /* R13610 */ + 0x0000, /* R13611 */ + 0x0000, /* R13612 */ + 0x0000, /* R13613 */ + 0x0000, /* R13614 */ + 0x0000, /* R13615 */ + 0x0000, /* R13616 */ + 0x0000, /* R13617 */ + 0x0000, /* R13618 */ + 0x0000, /* R13619 */ + 0x0000, /* R13620 */ + 0x0000, /* R13621 */ + 0x0000, /* R13622 */ + 0x0000, /* R13623 */ + 0x0000, /* R13624 */ + 0x0000, /* R13625 */ + 0x0000, /* R13626 */ + 0x0000, /* R13627 */ + 0x0000, /* R13628 */ + 0x0000, /* R13629 */ + 0x0000, /* R13630 */ + 0x0000, /* R13631 */ + 0x0000, /* R13632 */ + 0x0000, /* R13633 */ + 0x0000, /* R13634 */ + 0x0000, /* R13635 */ + 0x0000, /* R13636 */ + 0x0000, /* R13637 */ + 0x0000, /* R13638 */ + 0x0000, /* R13639 */ + 0x0000, /* R13640 */ + 0x0000, /* R13641 */ + 0x0000, /* R13642 */ + 0x0000, /* R13643 */ + 0x0000, /* R13644 */ + 0x0000, /* R13645 */ + 0x0000, /* R13646 */ + 0x0000, /* R13647 */ + 0x0000, /* R13648 */ + 0x0000, /* R13649 */ + 0x0000, /* R13650 */ + 0x0000, /* R13651 */ + 0x0000, /* R13652 */ + 0x0000, /* R13653 */ + 0x0000, /* R13654 */ + 0x0000, /* R13655 */ + 0x0000, /* R13656 */ + 0x0000, /* R13657 */ + 0x0000, /* R13658 */ + 0x0000, /* R13659 */ + 0x0000, /* R13660 */ + 0x0000, /* R13661 */ + 0x0000, /* R13662 */ + 0x0000, /* R13663 */ + 0x0000, /* R13664 */ + 0x0000, /* R13665 */ + 0x0000, /* R13666 */ + 0x0000, /* R13667 */ + 0x0000, /* R13668 */ + 0x0000, /* R13669 */ + 0x0000, /* R13670 */ + 0x0000, /* R13671 */ + 0x0000, /* R13672 */ + 0x0000, /* R13673 */ + 0x0000, /* R13674 */ + 0x0000, /* R13675 */ + 0x0000, /* R13676 */ + 0x0000, /* R13677 */ + 0x0000, /* R13678 */ + 0x0000, /* R13679 */ + 0x0000, /* R13680 */ + 0x0000, /* R13681 */ + 0x0000, /* R13682 */ + 0x0000, /* R13683 */ + 0x0000, /* R13684 */ + 0x0000, /* R13685 */ + 0x0000, /* R13686 */ + 0x0000, /* R13687 */ + 0x0000, /* R13688 */ + 0x0000, /* R13689 */ + 0x0000, /* R13690 */ + 0x0000, /* R13691 */ + 0x0000, /* R13692 */ + 0x0000, /* R13693 */ + 0x0000, /* R13694 */ + 0x0000, /* R13695 */ + 0x0000, /* R13696 */ + 0x0000, /* R13697 */ + 0x0000, /* R13698 */ + 0x0000, /* R13699 */ + 0x0000, /* R13700 */ + 0x0000, /* R13701 */ + 0x0000, /* R13702 */ + 0x0000, /* R13703 */ + 0x0000, /* R13704 */ + 0x0000, /* R13705 */ + 0x0000, /* R13706 */ + 0x0000, /* R13707 */ + 0x0000, /* R13708 */ + 0x0000, /* R13709 */ + 0x0000, /* R13710 */ + 0x0000, /* R13711 */ + 0x0000, /* R13712 */ + 0x0000, /* R13713 */ + 0x0000, /* R13714 */ + 0x0000, /* R13715 */ + 0x0000, /* R13716 */ + 0x0000, /* R13717 */ + 0x0000, /* R13718 */ + 0x0000, /* R13719 */ + 0x0000, /* R13720 */ + 0x0000, /* R13721 */ + 0x0000, /* R13722 */ + 0x0000, /* R13723 */ + 0x0000, /* R13724 */ + 0x0000, /* R13725 */ + 0x0000, /* R13726 */ + 0x0000, /* R13727 */ + 0x0000, /* R13728 */ + 0x0000, /* R13729 */ + 0x0000, /* R13730 */ + 0x0000, /* R13731 */ + 0x0000, /* R13732 */ + 0x0000, /* R13733 */ + 0x0000, /* R13734 */ + 0x0000, /* R13735 */ + 0x0000, /* R13736 */ + 0x0000, /* R13737 */ + 0x0000, /* R13738 */ + 0x0000, /* R13739 */ + 0x0000, /* R13740 */ + 0x0000, /* R13741 */ + 0x0000, /* R13742 */ + 0x0000, /* R13743 */ + 0x0000, /* R13744 */ + 0x0000, /* R13745 */ + 0x0000, /* R13746 */ + 0x0000, /* R13747 */ + 0x0000, /* R13748 */ + 0x0000, /* R13749 */ + 0x0000, /* R13750 */ + 0x0000, /* R13751 */ + 0x0000, /* R13752 */ + 0x0000, /* R13753 */ + 0x0000, /* R13754 */ + 0x0000, /* R13755 */ + 0x0000, /* R13756 */ + 0x0000, /* R13757 */ + 0x0000, /* R13758 */ + 0x0000, /* R13759 */ + 0x0000, /* R13760 */ + 0x0000, /* R13761 */ + 0x0000, /* R13762 */ + 0x0000, /* R13763 */ + 0x0000, /* R13764 */ + 0x0000, /* R13765 */ + 0x0000, /* R13766 */ + 0x0000, /* R13767 */ + 0x0000, /* R13768 */ + 0x0000, /* R13769 */ + 0x0000, /* R13770 */ + 0x0000, /* R13771 */ + 0x0000, /* R13772 */ + 0x0000, /* R13773 */ + 0x0000, /* R13774 */ + 0x0000, /* R13775 */ + 0x0000, /* R13776 */ + 0x0000, /* R13777 */ + 0x0000, /* R13778 */ + 0x0000, /* R13779 */ + 0x0000, /* R13780 */ + 0x0000, /* R13781 */ + 0x0000, /* R13782 */ + 0x0000, /* R13783 */ + 0x0000, /* R13784 */ + 0x0000, /* R13785 */ + 0x0000, /* R13786 */ + 0x0000, /* R13787 */ + 0x0000, /* R13788 */ + 0x0000, /* R13789 */ + 0x0000, /* R13790 */ + 0x0000, /* R13791 */ + 0x0000, /* R13792 */ + 0x0000, /* R13793 */ + 0x0000, /* R13794 */ + 0x0000, /* R13795 */ + 0x0000, /* R13796 */ + 0x0000, /* R13797 */ + 0x0000, /* R13798 */ + 0x0000, /* R13799 */ + 0x0000, /* R13800 */ + 0x0000, /* R13801 */ + 0x0000, /* R13802 */ + 0x0000, /* R13803 */ + 0x0000, /* R13804 */ + 0x0000, /* R13805 */ + 0x0000, /* R13806 */ + 0x0000, /* R13807 */ + 0x0000, /* R13808 */ + 0x0000, /* R13809 */ + 0x0000, /* R13810 */ + 0x0000, /* R13811 */ + 0x0000, /* R13812 */ + 0x0000, /* R13813 */ + 0x0000, /* R13814 */ + 0x0000, /* R13815 */ + 0x0000, /* R13816 */ + 0x0000, /* R13817 */ + 0x0000, /* R13818 */ + 0x0000, /* R13819 */ + 0x0000, /* R13820 */ + 0x0000, /* R13821 */ + 0x0000, /* R13822 */ + 0x0000, /* R13823 */ + 0x0000, /* R13824 */ + 0x0000, /* R13825 */ + 0x0000, /* R13826 */ + 0x0000, /* R13827 */ + 0x0000, /* R13828 */ + 0x0000, /* R13829 */ + 0x0000, /* R13830 */ + 0x0000, /* R13831 */ + 0x0000, /* R13832 */ + 0x0000, /* R13833 */ + 0x0000, /* R13834 */ + 0x0000, /* R13835 */ + 0x0000, /* R13836 */ + 0x0000, /* R13837 */ + 0x0000, /* R13838 */ + 0x0000, /* R13839 */ + 0x0000, /* R13840 */ + 0x0000, /* R13841 */ + 0x0000, /* R13842 */ + 0x0000, /* R13843 */ + 0x0000, /* R13844 */ + 0x0000, /* R13845 */ + 0x0000, /* R13846 */ + 0x0000, /* R13847 */ + 0x0000, /* R13848 */ + 0x0000, /* R13849 */ + 0x0000, /* R13850 */ + 0x0000, /* R13851 */ + 0x0000, /* R13852 */ + 0x0000, /* R13853 */ + 0x0000, /* R13854 */ + 0x0000, /* R13855 */ + 0x0000, /* R13856 */ + 0x0000, /* R13857 */ + 0x0000, /* R13858 */ + 0x0000, /* R13859 */ + 0x0000, /* R13860 */ + 0x0000, /* R13861 */ + 0x0000, /* R13862 */ + 0x0000, /* R13863 */ + 0x0000, /* R13864 */ + 0x0000, /* R13865 */ + 0x0000, /* R13866 */ + 0x0000, /* R13867 */ + 0x0000, /* R13868 */ + 0x0000, /* R13869 */ + 0x0000, /* R13870 */ + 0x0000, /* R13871 */ + 0x0000, /* R13872 */ + 0x0000, /* R13873 */ + 0x0000, /* R13874 */ + 0x0000, /* R13875 */ + 0x0000, /* R13876 */ + 0x0000, /* R13877 */ + 0x0000, /* R13878 */ + 0x0000, /* R13879 */ + 0x0000, /* R13880 */ + 0x0000, /* R13881 */ + 0x0000, /* R13882 */ + 0x0000, /* R13883 */ + 0x0000, /* R13884 */ + 0x0000, /* R13885 */ + 0x0000, /* R13886 */ + 0x0000, /* R13887 */ + 0x0000, /* R13888 */ + 0x0000, /* R13889 */ + 0x0000, /* R13890 */ + 0x0000, /* R13891 */ + 0x0000, /* R13892 */ + 0x0000, /* R13893 */ + 0x0000, /* R13894 */ + 0x0000, /* R13895 */ + 0x0000, /* R13896 */ + 0x0000, /* R13897 */ + 0x0000, /* R13898 */ + 0x0000, /* R13899 */ + 0x0000, /* R13900 */ + 0x0000, /* R13901 */ + 0x0000, /* R13902 */ + 0x0000, /* R13903 */ + 0x0000, /* R13904 */ + 0x0000, /* R13905 */ + 0x0000, /* R13906 */ + 0x0000, /* R13907 */ + 0x0000, /* R13908 */ + 0x0000, /* R13909 */ + 0x0000, /* R13910 */ + 0x0000, /* R13911 */ + 0x0000, /* R13912 */ + 0x0000, /* R13913 */ + 0x0000, /* R13914 */ + 0x0000, /* R13915 */ + 0x0000, /* R13916 */ + 0x0000, /* R13917 */ + 0x0000, /* R13918 */ + 0x0000, /* R13919 */ + 0x0000, /* R13920 */ + 0x0000, /* R13921 */ + 0x0000, /* R13922 */ + 0x0000, /* R13923 */ + 0x0000, /* R13924 */ + 0x0000, /* R13925 */ + 0x0000, /* R13926 */ + 0x0000, /* R13927 */ + 0x0000, /* R13928 */ + 0x0000, /* R13929 */ + 0x0000, /* R13930 */ + 0x0000, /* R13931 */ + 0x0000, /* R13932 */ + 0x0000, /* R13933 */ + 0x0000, /* R13934 */ + 0x0000, /* R13935 */ + 0x0000, /* R13936 */ + 0x0000, /* R13937 */ + 0x0000, /* R13938 */ + 0x0000, /* R13939 */ + 0x0000, /* R13940 */ + 0x0000, /* R13941 */ + 0x0000, /* R13942 */ + 0x0000, /* R13943 */ + 0x0000, /* R13944 */ + 0x0000, /* R13945 */ + 0x0000, /* R13946 */ + 0x0000, /* R13947 */ + 0x0000, /* R13948 */ + 0x0000, /* R13949 */ + 0x0000, /* R13950 */ + 0x0000, /* R13951 */ + 0x0000, /* R13952 */ + 0x0000, /* R13953 */ + 0x0000, /* R13954 */ + 0x0000, /* R13955 */ + 0x0000, /* R13956 */ + 0x0000, /* R13957 */ + 0x0000, /* R13958 */ + 0x0000, /* R13959 */ + 0x0000, /* R13960 */ + 0x0000, /* R13961 */ + 0x0000, /* R13962 */ + 0x0000, /* R13963 */ + 0x0000, /* R13964 */ + 0x0000, /* R13965 */ + 0x0000, /* R13966 */ + 0x0000, /* R13967 */ + 0x0000, /* R13968 */ + 0x0000, /* R13969 */ + 0x0000, /* R13970 */ + 0x0000, /* R13971 */ + 0x0000, /* R13972 */ + 0x0000, /* R13973 */ + 0x0000, /* R13974 */ + 0x0000, /* R13975 */ + 0x0000, /* R13976 */ + 0x0000, /* R13977 */ + 0x0000, /* R13978 */ + 0x0000, /* R13979 */ + 0x0000, /* R13980 */ + 0x0000, /* R13981 */ + 0x0000, /* R13982 */ + 0x0000, /* R13983 */ + 0x0000, /* R13984 */ + 0x0000, /* R13985 */ + 0x0000, /* R13986 */ + 0x0000, /* R13987 */ + 0x0000, /* R13988 */ + 0x0000, /* R13989 */ + 0x0000, /* R13990 */ + 0x0000, /* R13991 */ + 0x0000, /* R13992 */ + 0x0000, /* R13993 */ + 0x0000, /* R13994 */ + 0x0000, /* R13995 */ + 0x0000, /* R13996 */ + 0x0000, /* R13997 */ + 0x0000, /* R13998 */ + 0x0000, /* R13999 */ + 0x0000, /* R14000 */ + 0x0000, /* R14001 */ + 0x0000, /* R14002 */ + 0x0000, /* R14003 */ + 0x0000, /* R14004 */ + 0x0000, /* R14005 */ + 0x0000, /* R14006 */ + 0x0000, /* R14007 */ + 0x0000, /* R14008 */ + 0x0000, /* R14009 */ + 0x0000, /* R14010 */ + 0x0000, /* R14011 */ + 0x0000, /* R14012 */ + 0x0000, /* R14013 */ + 0x0000, /* R14014 */ + 0x0000, /* R14015 */ + 0x0000, /* R14016 */ + 0x0000, /* R14017 */ + 0x0000, /* R14018 */ + 0x0000, /* R14019 */ + 0x0000, /* R14020 */ + 0x0000, /* R14021 */ + 0x0000, /* R14022 */ + 0x0000, /* R14023 */ + 0x0000, /* R14024 */ + 0x0000, /* R14025 */ + 0x0000, /* R14026 */ + 0x0000, /* R14027 */ + 0x0000, /* R14028 */ + 0x0000, /* R14029 */ + 0x0000, /* R14030 */ + 0x0000, /* R14031 */ + 0x0000, /* R14032 */ + 0x0000, /* R14033 */ + 0x0000, /* R14034 */ + 0x0000, /* R14035 */ + 0x0000, /* R14036 */ + 0x0000, /* R14037 */ + 0x0000, /* R14038 */ + 0x0000, /* R14039 */ + 0x0000, /* R14040 */ + 0x0000, /* R14041 */ + 0x0000, /* R14042 */ + 0x0000, /* R14043 */ + 0x0000, /* R14044 */ + 0x0000, /* R14045 */ + 0x0000, /* R14046 */ + 0x0000, /* R14047 */ + 0x0000, /* R14048 */ + 0x0000, /* R14049 */ + 0x0000, /* R14050 */ + 0x0000, /* R14051 */ + 0x0000, /* R14052 */ + 0x0000, /* R14053 */ + 0x0000, /* R14054 */ + 0x0000, /* R14055 */ + 0x0000, /* R14056 */ + 0x0000, /* R14057 */ + 0x0000, /* R14058 */ + 0x0000, /* R14059 */ + 0x0000, /* R14060 */ + 0x0000, /* R14061 */ + 0x0000, /* R14062 */ + 0x0000, /* R14063 */ + 0x0000, /* R14064 */ + 0x0000, /* R14065 */ + 0x0000, /* R14066 */ + 0x0000, /* R14067 */ + 0x0000, /* R14068 */ + 0x0000, /* R14069 */ + 0x0000, /* R14070 */ + 0x0000, /* R14071 */ + 0x0000, /* R14072 */ + 0x0000, /* R14073 */ + 0x0000, /* R14074 */ + 0x0000, /* R14075 */ + 0x0000, /* R14076 */ + 0x0000, /* R14077 */ + 0x0000, /* R14078 */ + 0x0000, /* R14079 */ + 0x0000, /* R14080 */ + 0x0000, /* R14081 */ + 0x0000, /* R14082 */ + 0x0000, /* R14083 */ + 0x0000, /* R14084 */ + 0x0000, /* R14085 */ + 0x0000, /* R14086 */ + 0x0000, /* R14087 */ + 0x0000, /* R14088 */ + 0x0000, /* R14089 */ + 0x0000, /* R14090 */ + 0x0000, /* R14091 */ + 0x0000, /* R14092 */ + 0x0000, /* R14093 */ + 0x0000, /* R14094 */ + 0x0000, /* R14095 */ + 0x0000, /* R14096 */ + 0x0000, /* R14097 */ + 0x0000, /* R14098 */ + 0x0000, /* R14099 */ + 0x0000, /* R14100 */ + 0x0000, /* R14101 */ + 0x0000, /* R14102 */ + 0x0000, /* R14103 */ + 0x0000, /* R14104 */ + 0x0000, /* R14105 */ + 0x0000, /* R14106 */ + 0x0000, /* R14107 */ + 0x0000, /* R14108 */ + 0x0000, /* R14109 */ + 0x0000, /* R14110 */ + 0x0000, /* R14111 */ + 0x0000, /* R14112 */ + 0x0000, /* R14113 */ + 0x0000, /* R14114 */ + 0x0000, /* R14115 */ + 0x0000, /* R14116 */ + 0x0000, /* R14117 */ + 0x0000, /* R14118 */ + 0x0000, /* R14119 */ + 0x0000, /* R14120 */ + 0x0000, /* R14121 */ + 0x0000, /* R14122 */ + 0x0000, /* R14123 */ + 0x0000, /* R14124 */ + 0x0000, /* R14125 */ + 0x0000, /* R14126 */ + 0x0000, /* R14127 */ + 0x0000, /* R14128 */ + 0x0000, /* R14129 */ + 0x0000, /* R14130 */ + 0x0000, /* R14131 */ + 0x0000, /* R14132 */ + 0x0000, /* R14133 */ + 0x0000, /* R14134 */ + 0x0000, /* R14135 */ + 0x0000, /* R14136 */ + 0x0000, /* R14137 */ + 0x0000, /* R14138 */ + 0x0000, /* R14139 */ + 0x0000, /* R14140 */ + 0x0000, /* R14141 */ + 0x0000, /* R14142 */ + 0x0000, /* R14143 */ + 0x0000, /* R14144 */ + 0x0000, /* R14145 */ + 0x0000, /* R14146 */ + 0x0000, /* R14147 */ + 0x0000, /* R14148 */ + 0x0000, /* R14149 */ + 0x0000, /* R14150 */ + 0x0000, /* R14151 */ + 0x0000, /* R14152 */ + 0x0000, /* R14153 */ + 0x0000, /* R14154 */ + 0x0000, /* R14155 */ + 0x0000, /* R14156 */ + 0x0000, /* R14157 */ + 0x0000, /* R14158 */ + 0x0000, /* R14159 */ + 0x0000, /* R14160 */ + 0x0000, /* R14161 */ + 0x0000, /* R14162 */ + 0x0000, /* R14163 */ + 0x0000, /* R14164 */ + 0x0000, /* R14165 */ + 0x0000, /* R14166 */ + 0x0000, /* R14167 */ + 0x0000, /* R14168 */ + 0x0000, /* R14169 */ + 0x0000, /* R14170 */ + 0x0000, /* R14171 */ + 0x0000, /* R14172 */ + 0x0000, /* R14173 */ + 0x0000, /* R14174 */ + 0x0000, /* R14175 */ + 0x0000, /* R14176 */ + 0x0000, /* R14177 */ + 0x0000, /* R14178 */ + 0x0000, /* R14179 */ + 0x0000, /* R14180 */ + 0x0000, /* R14181 */ + 0x0000, /* R14182 */ + 0x0000, /* R14183 */ + 0x0000, /* R14184 */ + 0x0000, /* R14185 */ + 0x0000, /* R14186 */ + 0x0000, /* R14187 */ + 0x0000, /* R14188 */ + 0x0000, /* R14189 */ + 0x0000, /* R14190 */ + 0x0000, /* R14191 */ + 0x0000, /* R14192 */ + 0x0000, /* R14193 */ + 0x0000, /* R14194 */ + 0x0000, /* R14195 */ + 0x0000, /* R14196 */ + 0x0000, /* R14197 */ + 0x0000, /* R14198 */ + 0x0000, /* R14199 */ + 0x0000, /* R14200 */ + 0x0000, /* R14201 */ + 0x0000, /* R14202 */ + 0x0000, /* R14203 */ + 0x0000, /* R14204 */ + 0x0000, /* R14205 */ + 0x0000, /* R14206 */ + 0x0000, /* R14207 */ + 0x0000, /* R14208 */ + 0x0000, /* R14209 */ + 0x0000, /* R14210 */ + 0x0000, /* R14211 */ + 0x0000, /* R14212 */ + 0x0000, /* R14213 */ + 0x0000, /* R14214 */ + 0x0000, /* R14215 */ + 0x0000, /* R14216 */ + 0x0000, /* R14217 */ + 0x0000, /* R14218 */ + 0x0000, /* R14219 */ + 0x0000, /* R14220 */ + 0x0000, /* R14221 */ + 0x0000, /* R14222 */ + 0x0000, /* R14223 */ + 0x0000, /* R14224 */ + 0x0000, /* R14225 */ + 0x0000, /* R14226 */ + 0x0000, /* R14227 */ + 0x0000, /* R14228 */ + 0x0000, /* R14229 */ + 0x0000, /* R14230 */ + 0x0000, /* R14231 */ + 0x0000, /* R14232 */ + 0x0000, /* R14233 */ + 0x0000, /* R14234 */ + 0x0000, /* R14235 */ + 0x0000, /* R14236 */ + 0x0000, /* R14237 */ + 0x0000, /* R14238 */ + 0x0000, /* R14239 */ + 0x0000, /* R14240 */ + 0x0000, /* R14241 */ + 0x0000, /* R14242 */ + 0x0000, /* R14243 */ + 0x0000, /* R14244 */ + 0x0000, /* R14245 */ + 0x0000, /* R14246 */ + 0x0000, /* R14247 */ + 0x0000, /* R14248 */ + 0x0000, /* R14249 */ + 0x0000, /* R14250 */ + 0x0000, /* R14251 */ + 0x0000, /* R14252 */ + 0x0000, /* R14253 */ + 0x0000, /* R14254 */ + 0x0000, /* R14255 */ + 0x0000, /* R14256 */ + 0x0000, /* R14257 */ + 0x0000, /* R14258 */ + 0x0000, /* R14259 */ + 0x0000, /* R14260 */ + 0x0000, /* R14261 */ + 0x0000, /* R14262 */ + 0x0000, /* R14263 */ + 0x0000, /* R14264 */ + 0x0000, /* R14265 */ + 0x0000, /* R14266 */ + 0x0000, /* R14267 */ + 0x0000, /* R14268 */ + 0x0000, /* R14269 */ + 0x0000, /* R14270 */ + 0x0000, /* R14271 */ + 0x0000, /* R14272 */ + 0x0000, /* R14273 */ + 0x0000, /* R14274 */ + 0x0000, /* R14275 */ + 0x0000, /* R14276 */ + 0x0000, /* R14277 */ + 0x0000, /* R14278 */ + 0x0000, /* R14279 */ + 0x0000, /* R14280 */ + 0x0000, /* R14281 */ + 0x0000, /* R14282 */ + 0x0000, /* R14283 */ + 0x0000, /* R14284 */ + 0x0000, /* R14285 */ + 0x0000, /* R14286 */ + 0x0000, /* R14287 */ + 0x0000, /* R14288 */ + 0x0000, /* R14289 */ + 0x0000, /* R14290 */ + 0x0000, /* R14291 */ + 0x0000, /* R14292 */ + 0x0000, /* R14293 */ + 0x0000, /* R14294 */ + 0x0000, /* R14295 */ + 0x0000, /* R14296 */ + 0x0000, /* R14297 */ + 0x0000, /* R14298 */ + 0x0000, /* R14299 */ + 0x0000, /* R14300 */ + 0x0000, /* R14301 */ + 0x0000, /* R14302 */ + 0x0000, /* R14303 */ + 0x0000, /* R14304 */ + 0x0000, /* R14305 */ + 0x0000, /* R14306 */ + 0x0000, /* R14307 */ + 0x0000, /* R14308 */ + 0x0000, /* R14309 */ + 0x0000, /* R14310 */ + 0x0000, /* R14311 */ + 0x0000, /* R14312 */ + 0x0000, /* R14313 */ + 0x0000, /* R14314 */ + 0x0000, /* R14315 */ + 0x0000, /* R14316 */ + 0x0000, /* R14317 */ + 0x0000, /* R14318 */ + 0x0000, /* R14319 */ + 0x0000, /* R14320 */ + 0x0000, /* R14321 */ + 0x0000, /* R14322 */ + 0x0000, /* R14323 */ + 0x0000, /* R14324 */ + 0x0000, /* R14325 */ + 0x0000, /* R14326 */ + 0x0000, /* R14327 */ + 0x0000, /* R14328 */ + 0x0000, /* R14329 */ + 0x0000, /* R14330 */ + 0x0000, /* R14331 */ + 0x0000, /* R14332 */ + 0x0000, /* R14333 */ + 0x0000, /* R14334 */ + 0x0000, /* R14335 */ + 0x0000, /* R14336 - DSP2 Data3 RAM 1 */ + 0x0000, /* R14337 - DSP2 Data3 RAM 0 */ + 0x0000, /* R14338 */ + 0x0000, /* R14339 */ + 0x0000, /* R14340 */ + 0x0000, /* R14341 */ + 0x0000, /* R14342 */ + 0x0000, /* R14343 */ + 0x0000, /* R14344 */ + 0x0000, /* R14345 */ + 0x0000, /* R14346 */ + 0x0000, /* R14347 */ + 0x0000, /* R14348 */ + 0x0000, /* R14349 */ + 0x0000, /* R14350 */ + 0x0000, /* R14351 */ + 0x0000, /* R14352 */ + 0x0000, /* R14353 */ + 0x0000, /* R14354 */ + 0x0000, /* R14355 */ + 0x0000, /* R14356 */ + 0x0000, /* R14357 */ + 0x0000, /* R14358 */ + 0x0000, /* R14359 */ + 0x0000, /* R14360 */ + 0x0000, /* R14361 */ + 0x0000, /* R14362 */ + 0x0000, /* R14363 */ + 0x0000, /* R14364 */ + 0x0000, /* R14365 */ + 0x0000, /* R14366 */ + 0x0000, /* R14367 */ + 0x0000, /* R14368 */ + 0x0000, /* R14369 */ + 0x0000, /* R14370 */ + 0x0000, /* R14371 */ + 0x0000, /* R14372 */ + 0x0000, /* R14373 */ + 0x0000, /* R14374 */ + 0x0000, /* R14375 */ + 0x0000, /* R14376 */ + 0x0000, /* R14377 */ + 0x0000, /* R14378 */ + 0x0000, /* R14379 */ + 0x0000, /* R14380 */ + 0x0000, /* R14381 */ + 0x0000, /* R14382 */ + 0x0000, /* R14383 */ + 0x0000, /* R14384 */ + 0x0000, /* R14385 */ + 0x0000, /* R14386 */ + 0x0000, /* R14387 */ + 0x0000, /* R14388 */ + 0x0000, /* R14389 */ + 0x0000, /* R14390 */ + 0x0000, /* R14391 */ + 0x0000, /* R14392 */ + 0x0000, /* R14393 */ + 0x0000, /* R14394 */ + 0x0000, /* R14395 */ + 0x0000, /* R14396 */ + 0x0000, /* R14397 */ + 0x0000, /* R14398 */ + 0x0000, /* R14399 */ + 0x0000, /* R14400 */ + 0x0000, /* R14401 */ + 0x0000, /* R14402 */ + 0x0000, /* R14403 */ + 0x0000, /* R14404 */ + 0x0000, /* R14405 */ + 0x0000, /* R14406 */ + 0x0000, /* R14407 */ + 0x0000, /* R14408 */ + 0x0000, /* R14409 */ + 0x0000, /* R14410 */ + 0x0000, /* R14411 */ + 0x0000, /* R14412 */ + 0x0000, /* R14413 */ + 0x0000, /* R14414 */ + 0x0000, /* R14415 */ + 0x0000, /* R14416 */ + 0x0000, /* R14417 */ + 0x0000, /* R14418 */ + 0x0000, /* R14419 */ + 0x0000, /* R14420 */ + 0x0000, /* R14421 */ + 0x0000, /* R14422 */ + 0x0000, /* R14423 */ + 0x0000, /* R14424 */ + 0x0000, /* R14425 */ + 0x0000, /* R14426 */ + 0x0000, /* R14427 */ + 0x0000, /* R14428 */ + 0x0000, /* R14429 */ + 0x0000, /* R14430 */ + 0x0000, /* R14431 */ + 0x0000, /* R14432 */ + 0x0000, /* R14433 */ + 0x0000, /* R14434 */ + 0x0000, /* R14435 */ + 0x0000, /* R14436 */ + 0x0000, /* R14437 */ + 0x0000, /* R14438 */ + 0x0000, /* R14439 */ + 0x0000, /* R14440 */ + 0x0000, /* R14441 */ + 0x0000, /* R14442 */ + 0x0000, /* R14443 */ + 0x0000, /* R14444 */ + 0x0000, /* R14445 */ + 0x0000, /* R14446 */ + 0x0000, /* R14447 */ + 0x0000, /* R14448 */ + 0x0000, /* R14449 */ + 0x0000, /* R14450 */ + 0x0000, /* R14451 */ + 0x0000, /* R14452 */ + 0x0000, /* R14453 */ + 0x0000, /* R14454 */ + 0x0000, /* R14455 */ + 0x0000, /* R14456 */ + 0x0000, /* R14457 */ + 0x0000, /* R14458 */ + 0x0000, /* R14459 */ + 0x0000, /* R14460 */ + 0x0000, /* R14461 */ + 0x0000, /* R14462 */ + 0x0000, /* R14463 */ + 0x0000, /* R14464 */ + 0x0000, /* R14465 */ + 0x0000, /* R14466 */ + 0x0000, /* R14467 */ + 0x0000, /* R14468 */ + 0x0000, /* R14469 */ + 0x0000, /* R14470 */ + 0x0000, /* R14471 */ + 0x0000, /* R14472 */ + 0x0000, /* R14473 */ + 0x0000, /* R14474 */ + 0x0000, /* R14475 */ + 0x0000, /* R14476 */ + 0x0000, /* R14477 */ + 0x0000, /* R14478 */ + 0x0000, /* R14479 */ + 0x0000, /* R14480 */ + 0x0000, /* R14481 */ + 0x0000, /* R14482 */ + 0x0000, /* R14483 */ + 0x0000, /* R14484 */ + 0x0000, /* R14485 */ + 0x0000, /* R14486 */ + 0x0000, /* R14487 */ + 0x0000, /* R14488 */ + 0x0000, /* R14489 */ + 0x0000, /* R14490 */ + 0x0000, /* R14491 */ + 0x0000, /* R14492 */ + 0x0000, /* R14493 */ + 0x0000, /* R14494 */ + 0x0000, /* R14495 */ + 0x0000, /* R14496 */ + 0x0000, /* R14497 */ + 0x0000, /* R14498 */ + 0x0000, /* R14499 */ + 0x0000, /* R14500 */ + 0x0000, /* R14501 */ + 0x0000, /* R14502 */ + 0x0000, /* R14503 */ + 0x0000, /* R14504 */ + 0x0000, /* R14505 */ + 0x0000, /* R14506 */ + 0x0000, /* R14507 */ + 0x0000, /* R14508 */ + 0x0000, /* R14509 */ + 0x0000, /* R14510 */ + 0x0000, /* R14511 */ + 0x0000, /* R14512 */ + 0x0000, /* R14513 */ + 0x0000, /* R14514 */ + 0x0000, /* R14515 */ + 0x0000, /* R14516 */ + 0x0000, /* R14517 */ + 0x0000, /* R14518 */ + 0x0000, /* R14519 */ + 0x0000, /* R14520 */ + 0x0000, /* R14521 */ + 0x0000, /* R14522 */ + 0x0000, /* R14523 */ + 0x0000, /* R14524 */ + 0x0000, /* R14525 */ + 0x0000, /* R14526 */ + 0x0000, /* R14527 */ + 0x0000, /* R14528 */ + 0x0000, /* R14529 */ + 0x0000, /* R14530 */ + 0x0000, /* R14531 */ + 0x0000, /* R14532 */ + 0x0000, /* R14533 */ + 0x0000, /* R14534 */ + 0x0000, /* R14535 */ + 0x0000, /* R14536 */ + 0x0000, /* R14537 */ + 0x0000, /* R14538 */ + 0x0000, /* R14539 */ + 0x0000, /* R14540 */ + 0x0000, /* R14541 */ + 0x0000, /* R14542 */ + 0x0000, /* R14543 */ + 0x0000, /* R14544 */ + 0x0000, /* R14545 */ + 0x0000, /* R14546 */ + 0x0000, /* R14547 */ + 0x0000, /* R14548 */ + 0x0000, /* R14549 */ + 0x0000, /* R14550 */ + 0x0000, /* R14551 */ + 0x0000, /* R14552 */ + 0x0000, /* R14553 */ + 0x0000, /* R14554 */ + 0x0000, /* R14555 */ + 0x0000, /* R14556 */ + 0x0000, /* R14557 */ + 0x0000, /* R14558 */ + 0x0000, /* R14559 */ + 0x0000, /* R14560 */ + 0x0000, /* R14561 */ + 0x0000, /* R14562 */ + 0x0000, /* R14563 */ + 0x0000, /* R14564 */ + 0x0000, /* R14565 */ + 0x0000, /* R14566 */ + 0x0000, /* R14567 */ + 0x0000, /* R14568 */ + 0x0000, /* R14569 */ + 0x0000, /* R14570 */ + 0x0000, /* R14571 */ + 0x0000, /* R14572 */ + 0x0000, /* R14573 */ + 0x0000, /* R14574 */ + 0x0000, /* R14575 */ + 0x0000, /* R14576 */ + 0x0000, /* R14577 */ + 0x0000, /* R14578 */ + 0x0000, /* R14579 */ + 0x0000, /* R14580 */ + 0x0000, /* R14581 */ + 0x0000, /* R14582 */ + 0x0000, /* R14583 */ + 0x0000, /* R14584 */ + 0x0000, /* R14585 */ + 0x0000, /* R14586 */ + 0x0000, /* R14587 */ + 0x0000, /* R14588 */ + 0x0000, /* R14589 */ + 0x0000, /* R14590 */ + 0x0000, /* R14591 */ + 0x0000, /* R14592 */ + 0x0000, /* R14593 */ + 0x0000, /* R14594 */ + 0x0000, /* R14595 */ + 0x0000, /* R14596 */ + 0x0000, /* R14597 */ + 0x0000, /* R14598 */ + 0x0000, /* R14599 */ + 0x0000, /* R14600 */ + 0x0000, /* R14601 */ + 0x0000, /* R14602 */ + 0x0000, /* R14603 */ + 0x0000, /* R14604 */ + 0x0000, /* R14605 */ + 0x0000, /* R14606 */ + 0x0000, /* R14607 */ + 0x0000, /* R14608 */ + 0x0000, /* R14609 */ + 0x0000, /* R14610 */ + 0x0000, /* R14611 */ + 0x0000, /* R14612 */ + 0x0000, /* R14613 */ + 0x0000, /* R14614 */ + 0x0000, /* R14615 */ + 0x0000, /* R14616 */ + 0x0000, /* R14617 */ + 0x0000, /* R14618 */ + 0x0000, /* R14619 */ + 0x0000, /* R14620 */ + 0x0000, /* R14621 */ + 0x0000, /* R14622 */ + 0x0000, /* R14623 */ + 0x0000, /* R14624 */ + 0x0000, /* R14625 */ + 0x0000, /* R14626 */ + 0x0000, /* R14627 */ + 0x0000, /* R14628 */ + 0x0000, /* R14629 */ + 0x0000, /* R14630 */ + 0x0000, /* R14631 */ + 0x0000, /* R14632 */ + 0x0000, /* R14633 */ + 0x0000, /* R14634 */ + 0x0000, /* R14635 */ + 0x0000, /* R14636 */ + 0x0000, /* R14637 */ + 0x0000, /* R14638 */ + 0x0000, /* R14639 */ + 0x0000, /* R14640 */ + 0x0000, /* R14641 */ + 0x0000, /* R14642 */ + 0x0000, /* R14643 */ + 0x0000, /* R14644 */ + 0x0000, /* R14645 */ + 0x0000, /* R14646 */ + 0x0000, /* R14647 */ + 0x0000, /* R14648 */ + 0x0000, /* R14649 */ + 0x0000, /* R14650 */ + 0x0000, /* R14651 */ + 0x0000, /* R14652 */ + 0x0000, /* R14653 */ + 0x0000, /* R14654 */ + 0x0000, /* R14655 */ + 0x0000, /* R14656 */ + 0x0000, /* R14657 */ + 0x0000, /* R14658 */ + 0x0000, /* R14659 */ + 0x0000, /* R14660 */ + 0x0000, /* R14661 */ + 0x0000, /* R14662 */ + 0x0000, /* R14663 */ + 0x0000, /* R14664 */ + 0x0000, /* R14665 */ + 0x0000, /* R14666 */ + 0x0000, /* R14667 */ + 0x0000, /* R14668 */ + 0x0000, /* R14669 */ + 0x0000, /* R14670 */ + 0x0000, /* R14671 */ + 0x0000, /* R14672 */ + 0x0000, /* R14673 */ + 0x0000, /* R14674 */ + 0x0000, /* R14675 */ + 0x0000, /* R14676 */ + 0x0000, /* R14677 */ + 0x0000, /* R14678 */ + 0x0000, /* R14679 */ + 0x0000, /* R14680 */ + 0x0000, /* R14681 */ + 0x0000, /* R14682 */ + 0x0000, /* R14683 */ + 0x0000, /* R14684 */ + 0x0000, /* R14685 */ + 0x0000, /* R14686 */ + 0x0000, /* R14687 */ + 0x0000, /* R14688 */ + 0x0000, /* R14689 */ + 0x0000, /* R14690 */ + 0x0000, /* R14691 */ + 0x0000, /* R14692 */ + 0x0000, /* R14693 */ + 0x0000, /* R14694 */ + 0x0000, /* R14695 */ + 0x0000, /* R14696 */ + 0x0000, /* R14697 */ + 0x0000, /* R14698 */ + 0x0000, /* R14699 */ + 0x0000, /* R14700 */ + 0x0000, /* R14701 */ + 0x0000, /* R14702 */ + 0x0000, /* R14703 */ + 0x0000, /* R14704 */ + 0x0000, /* R14705 */ + 0x0000, /* R14706 */ + 0x0000, /* R14707 */ + 0x0000, /* R14708 */ + 0x0000, /* R14709 */ + 0x0000, /* R14710 */ + 0x0000, /* R14711 */ + 0x0000, /* R14712 */ + 0x0000, /* R14713 */ + 0x0000, /* R14714 */ + 0x0000, /* R14715 */ + 0x0000, /* R14716 */ + 0x0000, /* R14717 */ + 0x0000, /* R14718 */ + 0x0000, /* R14719 */ + 0x0000, /* R14720 */ + 0x0000, /* R14721 */ + 0x0000, /* R14722 */ + 0x0000, /* R14723 */ + 0x0000, /* R14724 */ + 0x0000, /* R14725 */ + 0x0000, /* R14726 */ + 0x0000, /* R14727 */ + 0x0000, /* R14728 */ + 0x0000, /* R14729 */ + 0x0000, /* R14730 */ + 0x0000, /* R14731 */ + 0x0000, /* R14732 */ + 0x0000, /* R14733 */ + 0x0000, /* R14734 */ + 0x0000, /* R14735 */ + 0x0000, /* R14736 */ + 0x0000, /* R14737 */ + 0x0000, /* R14738 */ + 0x0000, /* R14739 */ + 0x0000, /* R14740 */ + 0x0000, /* R14741 */ + 0x0000, /* R14742 */ + 0x0000, /* R14743 */ + 0x0000, /* R14744 */ + 0x0000, /* R14745 */ + 0x0000, /* R14746 */ + 0x0000, /* R14747 */ + 0x0000, /* R14748 */ + 0x0000, /* R14749 */ + 0x0000, /* R14750 */ + 0x0000, /* R14751 */ + 0x0000, /* R14752 */ + 0x0000, /* R14753 */ + 0x0000, /* R14754 */ + 0x0000, /* R14755 */ + 0x0000, /* R14756 */ + 0x0000, /* R14757 */ + 0x0000, /* R14758 */ + 0x0000, /* R14759 */ + 0x0000, /* R14760 */ + 0x0000, /* R14761 */ + 0x0000, /* R14762 */ + 0x0000, /* R14763 */ + 0x0000, /* R14764 */ + 0x0000, /* R14765 */ + 0x0000, /* R14766 */ + 0x0000, /* R14767 */ + 0x0000, /* R14768 */ + 0x0000, /* R14769 */ + 0x0000, /* R14770 */ + 0x0000, /* R14771 */ + 0x0000, /* R14772 */ + 0x0000, /* R14773 */ + 0x0000, /* R14774 */ + 0x0000, /* R14775 */ + 0x0000, /* R14776 */ + 0x0000, /* R14777 */ + 0x0000, /* R14778 */ + 0x0000, /* R14779 */ + 0x0000, /* R14780 */ + 0x0000, /* R14781 */ + 0x0000, /* R14782 */ + 0x0000, /* R14783 */ + 0x0000, /* R14784 */ + 0x0000, /* R14785 */ + 0x0000, /* R14786 */ + 0x0000, /* R14787 */ + 0x0000, /* R14788 */ + 0x0000, /* R14789 */ + 0x0000, /* R14790 */ + 0x0000, /* R14791 */ + 0x0000, /* R14792 */ + 0x0000, /* R14793 */ + 0x0000, /* R14794 */ + 0x0000, /* R14795 */ + 0x0000, /* R14796 */ + 0x0000, /* R14797 */ + 0x0000, /* R14798 */ + 0x0000, /* R14799 */ + 0x0000, /* R14800 */ + 0x0000, /* R14801 */ + 0x0000, /* R14802 */ + 0x0000, /* R14803 */ + 0x0000, /* R14804 */ + 0x0000, /* R14805 */ + 0x0000, /* R14806 */ + 0x0000, /* R14807 */ + 0x0000, /* R14808 */ + 0x0000, /* R14809 */ + 0x0000, /* R14810 */ + 0x0000, /* R14811 */ + 0x0000, /* R14812 */ + 0x0000, /* R14813 */ + 0x0000, /* R14814 */ + 0x0000, /* R14815 */ + 0x0000, /* R14816 */ + 0x0000, /* R14817 */ + 0x0000, /* R14818 */ + 0x0000, /* R14819 */ + 0x0000, /* R14820 */ + 0x0000, /* R14821 */ + 0x0000, /* R14822 */ + 0x0000, /* R14823 */ + 0x0000, /* R14824 */ + 0x0000, /* R14825 */ + 0x0000, /* R14826 */ + 0x0000, /* R14827 */ + 0x0000, /* R14828 */ + 0x0000, /* R14829 */ + 0x0000, /* R14830 */ + 0x0000, /* R14831 */ + 0x0000, /* R14832 */ + 0x0000, /* R14833 */ + 0x0000, /* R14834 */ + 0x0000, /* R14835 */ + 0x0000, /* R14836 */ + 0x0000, /* R14837 */ + 0x0000, /* R14838 */ + 0x0000, /* R14839 */ + 0x0000, /* R14840 */ + 0x0000, /* R14841 */ + 0x0000, /* R14842 */ + 0x0000, /* R14843 */ + 0x0000, /* R14844 */ + 0x0000, /* R14845 */ + 0x0000, /* R14846 */ + 0x0000, /* R14847 */ + 0x0000, /* R14848 */ + 0x0000, /* R14849 */ + 0x0000, /* R14850 */ + 0x0000, /* R14851 */ + 0x0000, /* R14852 */ + 0x0000, /* R14853 */ + 0x0000, /* R14854 */ + 0x0000, /* R14855 */ + 0x0000, /* R14856 */ + 0x0000, /* R14857 */ + 0x0000, /* R14858 */ + 0x0000, /* R14859 */ + 0x0000, /* R14860 */ + 0x0000, /* R14861 */ + 0x0000, /* R14862 */ + 0x0000, /* R14863 */ + 0x0000, /* R14864 */ + 0x0000, /* R14865 */ + 0x0000, /* R14866 */ + 0x0000, /* R14867 */ + 0x0000, /* R14868 */ + 0x0000, /* R14869 */ + 0x0000, /* R14870 */ + 0x0000, /* R14871 */ + 0x0000, /* R14872 */ + 0x0000, /* R14873 */ + 0x0000, /* R14874 */ + 0x0000, /* R14875 */ + 0x0000, /* R14876 */ + 0x0000, /* R14877 */ + 0x0000, /* R14878 */ + 0x0000, /* R14879 */ + 0x0000, /* R14880 */ + 0x0000, /* R14881 */ + 0x0000, /* R14882 */ + 0x0000, /* R14883 */ + 0x0000, /* R14884 */ + 0x0000, /* R14885 */ + 0x0000, /* R14886 */ + 0x0000, /* R14887 */ + 0x0000, /* R14888 */ + 0x0000, /* R14889 */ + 0x0000, /* R14890 */ + 0x0000, /* R14891 */ + 0x0000, /* R14892 */ + 0x0000, /* R14893 */ + 0x0000, /* R14894 */ + 0x0000, /* R14895 */ + 0x0000, /* R14896 */ + 0x0000, /* R14897 */ + 0x0000, /* R14898 */ + 0x0000, /* R14899 */ + 0x0000, /* R14900 */ + 0x0000, /* R14901 */ + 0x0000, /* R14902 */ + 0x0000, /* R14903 */ + 0x0000, /* R14904 */ + 0x0000, /* R14905 */ + 0x0000, /* R14906 */ + 0x0000, /* R14907 */ + 0x0000, /* R14908 */ + 0x0000, /* R14909 */ + 0x0000, /* R14910 */ + 0x0000, /* R14911 */ + 0x0000, /* R14912 */ + 0x0000, /* R14913 */ + 0x0000, /* R14914 */ + 0x0000, /* R14915 */ + 0x0000, /* R14916 */ + 0x0000, /* R14917 */ + 0x0000, /* R14918 */ + 0x0000, /* R14919 */ + 0x0000, /* R14920 */ + 0x0000, /* R14921 */ + 0x0000, /* R14922 */ + 0x0000, /* R14923 */ + 0x0000, /* R14924 */ + 0x0000, /* R14925 */ + 0x0000, /* R14926 */ + 0x0000, /* R14927 */ + 0x0000, /* R14928 */ + 0x0000, /* R14929 */ + 0x0000, /* R14930 */ + 0x0000, /* R14931 */ + 0x0000, /* R14932 */ + 0x0000, /* R14933 */ + 0x0000, /* R14934 */ + 0x0000, /* R14935 */ + 0x0000, /* R14936 */ + 0x0000, /* R14937 */ + 0x0000, /* R14938 */ + 0x0000, /* R14939 */ + 0x0000, /* R14940 */ + 0x0000, /* R14941 */ + 0x0000, /* R14942 */ + 0x0000, /* R14943 */ + 0x0000, /* R14944 */ + 0x0000, /* R14945 */ + 0x0000, /* R14946 */ + 0x0000, /* R14947 */ + 0x0000, /* R14948 */ + 0x0000, /* R14949 */ + 0x0000, /* R14950 */ + 0x0000, /* R14951 */ + 0x0000, /* R14952 */ + 0x0000, /* R14953 */ + 0x0000, /* R14954 */ + 0x0000, /* R14955 */ + 0x0000, /* R14956 */ + 0x0000, /* R14957 */ + 0x0000, /* R14958 */ + 0x0000, /* R14959 */ + 0x0000, /* R14960 */ + 0x0000, /* R14961 */ + 0x0000, /* R14962 */ + 0x0000, /* R14963 */ + 0x0000, /* R14964 */ + 0x0000, /* R14965 */ + 0x0000, /* R14966 */ + 0x0000, /* R14967 */ + 0x0000, /* R14968 */ + 0x0000, /* R14969 */ + 0x0000, /* R14970 */ + 0x0000, /* R14971 */ + 0x0000, /* R14972 */ + 0x0000, /* R14973 */ + 0x0000, /* R14974 */ + 0x0000, /* R14975 */ + 0x0000, /* R14976 */ + 0x0000, /* R14977 */ + 0x0000, /* R14978 */ + 0x0000, /* R14979 */ + 0x0000, /* R14980 */ + 0x0000, /* R14981 */ + 0x0000, /* R14982 */ + 0x0000, /* R14983 */ + 0x0000, /* R14984 */ + 0x0000, /* R14985 */ + 0x0000, /* R14986 */ + 0x0000, /* R14987 */ + 0x0000, /* R14988 */ + 0x0000, /* R14989 */ + 0x0000, /* R14990 */ + 0x0000, /* R14991 */ + 0x0000, /* R14992 */ + 0x0000, /* R14993 */ + 0x0000, /* R14994 */ + 0x0000, /* R14995 */ + 0x0000, /* R14996 */ + 0x0000, /* R14997 */ + 0x0000, /* R14998 */ + 0x0000, /* R14999 */ + 0x0000, /* R15000 */ + 0x0000, /* R15001 */ + 0x0000, /* R15002 */ + 0x0000, /* R15003 */ + 0x0000, /* R15004 */ + 0x0000, /* R15005 */ + 0x0000, /* R15006 */ + 0x0000, /* R15007 */ + 0x0000, /* R15008 */ + 0x0000, /* R15009 */ + 0x0000, /* R15010 */ + 0x0000, /* R15011 */ + 0x0000, /* R15012 */ + 0x0000, /* R15013 */ + 0x0000, /* R15014 */ + 0x0000, /* R15015 */ + 0x0000, /* R15016 */ + 0x0000, /* R15017 */ + 0x0000, /* R15018 */ + 0x0000, /* R15019 */ + 0x0000, /* R15020 */ + 0x0000, /* R15021 */ + 0x0000, /* R15022 */ + 0x0000, /* R15023 */ + 0x0000, /* R15024 */ + 0x0000, /* R15025 */ + 0x0000, /* R15026 */ + 0x0000, /* R15027 */ + 0x0000, /* R15028 */ + 0x0000, /* R15029 */ + 0x0000, /* R15030 */ + 0x0000, /* R15031 */ + 0x0000, /* R15032 */ + 0x0000, /* R15033 */ + 0x0000, /* R15034 */ + 0x0000, /* R15035 */ + 0x0000, /* R15036 */ + 0x0000, /* R15037 */ + 0x0000, /* R15038 */ + 0x0000, /* R15039 */ + 0x0000, /* R15040 */ + 0x0000, /* R15041 */ + 0x0000, /* R15042 */ + 0x0000, /* R15043 */ + 0x0000, /* R15044 */ + 0x0000, /* R15045 */ + 0x0000, /* R15046 */ + 0x0000, /* R15047 */ + 0x0000, /* R15048 */ + 0x0000, /* R15049 */ + 0x0000, /* R15050 */ + 0x0000, /* R15051 */ + 0x0000, /* R15052 */ + 0x0000, /* R15053 */ + 0x0000, /* R15054 */ + 0x0000, /* R15055 */ + 0x0000, /* R15056 */ + 0x0000, /* R15057 */ + 0x0000, /* R15058 */ + 0x0000, /* R15059 */ + 0x0000, /* R15060 */ + 0x0000, /* R15061 */ + 0x0000, /* R15062 */ + 0x0000, /* R15063 */ + 0x0000, /* R15064 */ + 0x0000, /* R15065 */ + 0x0000, /* R15066 */ + 0x0000, /* R15067 */ + 0x0000, /* R15068 */ + 0x0000, /* R15069 */ + 0x0000, /* R15070 */ + 0x0000, /* R15071 */ + 0x0000, /* R15072 */ + 0x0000, /* R15073 */ + 0x0000, /* R15074 */ + 0x0000, /* R15075 */ + 0x0000, /* R15076 */ + 0x0000, /* R15077 */ + 0x0000, /* R15078 */ + 0x0000, /* R15079 */ + 0x0000, /* R15080 */ + 0x0000, /* R15081 */ + 0x0000, /* R15082 */ + 0x0000, /* R15083 */ + 0x0000, /* R15084 */ + 0x0000, /* R15085 */ + 0x0000, /* R15086 */ + 0x0000, /* R15087 */ + 0x0000, /* R15088 */ + 0x0000, /* R15089 */ + 0x0000, /* R15090 */ + 0x0000, /* R15091 */ + 0x0000, /* R15092 */ + 0x0000, /* R15093 */ + 0x0000, /* R15094 */ + 0x0000, /* R15095 */ + 0x0000, /* R15096 */ + 0x0000, /* R15097 */ + 0x0000, /* R15098 */ + 0x0000, /* R15099 */ + 0x0000, /* R15100 */ + 0x0000, /* R15101 */ + 0x0000, /* R15102 */ + 0x0000, /* R15103 */ + 0x0000, /* R15104 */ + 0x0000, /* R15105 */ + 0x0000, /* R15106 */ + 0x0000, /* R15107 */ + 0x0000, /* R15108 */ + 0x0000, /* R15109 */ + 0x0000, /* R15110 */ + 0x0000, /* R15111 */ + 0x0000, /* R15112 */ + 0x0000, /* R15113 */ + 0x0000, /* R15114 */ + 0x0000, /* R15115 */ + 0x0000, /* R15116 */ + 0x0000, /* R15117 */ + 0x0000, /* R15118 */ + 0x0000, /* R15119 */ + 0x0000, /* R15120 */ + 0x0000, /* R15121 */ + 0x0000, /* R15122 */ + 0x0000, /* R15123 */ + 0x0000, /* R15124 */ + 0x0000, /* R15125 */ + 0x0000, /* R15126 */ + 0x0000, /* R15127 */ + 0x0000, /* R15128 */ + 0x0000, /* R15129 */ + 0x0000, /* R15130 */ + 0x0000, /* R15131 */ + 0x0000, /* R15132 */ + 0x0000, /* R15133 */ + 0x0000, /* R15134 */ + 0x0000, /* R15135 */ + 0x0000, /* R15136 */ + 0x0000, /* R15137 */ + 0x0000, /* R15138 */ + 0x0000, /* R15139 */ + 0x0000, /* R15140 */ + 0x0000, /* R15141 */ + 0x0000, /* R15142 */ + 0x0000, /* R15143 */ + 0x0000, /* R15144 */ + 0x0000, /* R15145 */ + 0x0000, /* R15146 */ + 0x0000, /* R15147 */ + 0x0000, /* R15148 */ + 0x0000, /* R15149 */ + 0x0000, /* R15150 */ + 0x0000, /* R15151 */ + 0x0000, /* R15152 */ + 0x0000, /* R15153 */ + 0x0000, /* R15154 */ + 0x0000, /* R15155 */ + 0x0000, /* R15156 */ + 0x0000, /* R15157 */ + 0x0000, /* R15158 */ + 0x0000, /* R15159 */ + 0x0000, /* R15160 */ + 0x0000, /* R15161 */ + 0x0000, /* R15162 */ + 0x0000, /* R15163 */ + 0x0000, /* R15164 */ + 0x0000, /* R15165 */ + 0x0000, /* R15166 */ + 0x0000, /* R15167 */ + 0x0000, /* R15168 */ + 0x0000, /* R15169 */ + 0x0000, /* R15170 */ + 0x0000, /* R15171 */ + 0x0000, /* R15172 */ + 0x0000, /* R15173 */ + 0x0000, /* R15174 */ + 0x0000, /* R15175 */ + 0x0000, /* R15176 */ + 0x0000, /* R15177 */ + 0x0000, /* R15178 */ + 0x0000, /* R15179 */ + 0x0000, /* R15180 */ + 0x0000, /* R15181 */ + 0x0000, /* R15182 */ + 0x0000, /* R15183 */ + 0x0000, /* R15184 */ + 0x0000, /* R15185 */ + 0x0000, /* R15186 */ + 0x0000, /* R15187 */ + 0x0000, /* R15188 */ + 0x0000, /* R15189 */ + 0x0000, /* R15190 */ + 0x0000, /* R15191 */ + 0x0000, /* R15192 */ + 0x0000, /* R15193 */ + 0x0000, /* R15194 */ + 0x0000, /* R15195 */ + 0x0000, /* R15196 */ + 0x0000, /* R15197 */ + 0x0000, /* R15198 */ + 0x0000, /* R15199 */ + 0x0000, /* R15200 */ + 0x0000, /* R15201 */ + 0x0000, /* R15202 */ + 0x0000, /* R15203 */ + 0x0000, /* R15204 */ + 0x0000, /* R15205 */ + 0x0000, /* R15206 */ + 0x0000, /* R15207 */ + 0x0000, /* R15208 */ + 0x0000, /* R15209 */ + 0x0000, /* R15210 */ + 0x0000, /* R15211 */ + 0x0000, /* R15212 */ + 0x0000, /* R15213 */ + 0x0000, /* R15214 */ + 0x0000, /* R15215 */ + 0x0000, /* R15216 */ + 0x0000, /* R15217 */ + 0x0000, /* R15218 */ + 0x0000, /* R15219 */ + 0x0000, /* R15220 */ + 0x0000, /* R15221 */ + 0x0000, /* R15222 */ + 0x0000, /* R15223 */ + 0x0000, /* R15224 */ + 0x0000, /* R15225 */ + 0x0000, /* R15226 */ + 0x0000, /* R15227 */ + 0x0000, /* R15228 */ + 0x0000, /* R15229 */ + 0x0000, /* R15230 */ + 0x0000, /* R15231 */ + 0x0000, /* R15232 */ + 0x0000, /* R15233 */ + 0x0000, /* R15234 */ + 0x0000, /* R15235 */ + 0x0000, /* R15236 */ + 0x0000, /* R15237 */ + 0x0000, /* R15238 */ + 0x0000, /* R15239 */ + 0x0000, /* R15240 */ + 0x0000, /* R15241 */ + 0x0000, /* R15242 */ + 0x0000, /* R15243 */ + 0x0000, /* R15244 */ + 0x0000, /* R15245 */ + 0x0000, /* R15246 */ + 0x0000, /* R15247 */ + 0x0000, /* R15248 */ + 0x0000, /* R15249 */ + 0x0000, /* R15250 */ + 0x0000, /* R15251 */ + 0x0000, /* R15252 */ + 0x0000, /* R15253 */ + 0x0000, /* R15254 */ + 0x0000, /* R15255 */ + 0x0000, /* R15256 */ + 0x0000, /* R15257 */ + 0x0000, /* R15258 */ + 0x0000, /* R15259 */ + 0x0000, /* R15260 */ + 0x0000, /* R15261 */ + 0x0000, /* R15262 */ + 0x0000, /* R15263 */ + 0x0000, /* R15264 */ + 0x0000, /* R15265 */ + 0x0000, /* R15266 */ + 0x0000, /* R15267 */ + 0x0000, /* R15268 */ + 0x0000, /* R15269 */ + 0x0000, /* R15270 */ + 0x0000, /* R15271 */ + 0x0000, /* R15272 */ + 0x0000, /* R15273 */ + 0x0000, /* R15274 */ + 0x0000, /* R15275 */ + 0x0000, /* R15276 */ + 0x0000, /* R15277 */ + 0x0000, /* R15278 */ + 0x0000, /* R15279 */ + 0x0000, /* R15280 */ + 0x0000, /* R15281 */ + 0x0000, /* R15282 */ + 0x0000, /* R15283 */ + 0x0000, /* R15284 */ + 0x0000, /* R15285 */ + 0x0000, /* R15286 */ + 0x0000, /* R15287 */ + 0x0000, /* R15288 */ + 0x0000, /* R15289 */ + 0x0000, /* R15290 */ + 0x0000, /* R15291 */ + 0x0000, /* R15292 */ + 0x0000, /* R15293 */ + 0x0000, /* R15294 */ + 0x0000, /* R15295 */ + 0x0000, /* R15296 */ + 0x0000, /* R15297 */ + 0x0000, /* R15298 */ + 0x0000, /* R15299 */ + 0x0000, /* R15300 */ + 0x0000, /* R15301 */ + 0x0000, /* R15302 */ + 0x0000, /* R15303 */ + 0x0000, /* R15304 */ + 0x0000, /* R15305 */ + 0x0000, /* R15306 */ + 0x0000, /* R15307 */ + 0x0000, /* R15308 */ + 0x0000, /* R15309 */ + 0x0000, /* R15310 */ + 0x0000, /* R15311 */ + 0x0000, /* R15312 */ + 0x0000, /* R15313 */ + 0x0000, /* R15314 */ + 0x0000, /* R15315 */ + 0x0000, /* R15316 */ + 0x0000, /* R15317 */ + 0x0000, /* R15318 */ + 0x0000, /* R15319 */ + 0x0000, /* R15320 */ + 0x0000, /* R15321 */ + 0x0000, /* R15322 */ + 0x0000, /* R15323 */ + 0x0000, /* R15324 */ + 0x0000, /* R15325 */ + 0x0000, /* R15326 */ + 0x0000, /* R15327 */ + 0x0000, /* R15328 */ + 0x0000, /* R15329 */ + 0x0000, /* R15330 */ + 0x0000, /* R15331 */ + 0x0000, /* R15332 */ + 0x0000, /* R15333 */ + 0x0000, /* R15334 */ + 0x0000, /* R15335 */ + 0x0000, /* R15336 */ + 0x0000, /* R15337 */ + 0x0000, /* R15338 */ + 0x0000, /* R15339 */ + 0x0000, /* R15340 */ + 0x0000, /* R15341 */ + 0x0000, /* R15342 */ + 0x0000, /* R15343 */ + 0x0000, /* R15344 */ + 0x0000, /* R15345 */ + 0x0000, /* R15346 */ + 0x0000, /* R15347 */ + 0x0000, /* R15348 */ + 0x0000, /* R15349 */ + 0x0000, /* R15350 */ + 0x0000, /* R15351 */ + 0x0000, /* R15352 */ + 0x0000, /* R15353 */ + 0x0000, /* R15354 */ + 0x0000, /* R15355 */ + 0x0000, /* R15356 */ + 0x0000, /* R15357 */ + 0x0000, /* R15358 */ + 0x0000, /* R15359 */ + 0x000A, /* R15360 - DSP2 Coeff RAM 0 */ + 0x0000, /* R15361 */ + 0x0000, /* R15362 */ + 0x0000, /* R15363 */ + 0x0000, /* R15364 */ + 0x0000, /* R15365 */ + 0x0000, /* R15366 */ + 0x0000, /* R15367 */ + 0x0000, /* R15368 */ + 0x0000, /* R15369 */ + 0x0000, /* R15370 */ + 0x0000, /* R15371 */ + 0x0000, /* R15372 */ + 0x0000, /* R15373 */ + 0x0000, /* R15374 */ + 0x0000, /* R15375 */ + 0x0000, /* R15376 */ + 0x0000, /* R15377 */ + 0x0000, /* R15378 */ + 0x0000, /* R15379 */ + 0x0000, /* R15380 */ + 0x0000, /* R15381 */ + 0x0000, /* R15382 */ + 0x0000, /* R15383 */ + 0x0000, /* R15384 */ + 0x0000, /* R15385 */ + 0x0000, /* R15386 */ + 0x0000, /* R15387 */ + 0x0000, /* R15388 */ + 0x0000, /* R15389 */ + 0x0000, /* R15390 */ + 0x0000, /* R15391 */ + 0x0000, /* R15392 */ + 0x0000, /* R15393 */ + 0x0000, /* R15394 */ + 0x0000, /* R15395 */ + 0x0000, /* R15396 */ + 0x0000, /* R15397 */ + 0x0000, /* R15398 */ + 0x0000, /* R15399 */ + 0x0000, /* R15400 */ + 0x0000, /* R15401 */ + 0x0000, /* R15402 */ + 0x0000, /* R15403 */ + 0x0000, /* R15404 */ + 0x0000, /* R15405 */ + 0x0000, /* R15406 */ + 0x0000, /* R15407 */ + 0x0000, /* R15408 */ + 0x0000, /* R15409 */ + 0x0000, /* R15410 */ + 0x0000, /* R15411 */ + 0x0000, /* R15412 */ + 0x0000, /* R15413 */ + 0x0000, /* R15414 */ + 0x0000, /* R15415 */ + 0x0000, /* R15416 */ + 0x0000, /* R15417 */ + 0x0000, /* R15418 */ + 0x0000, /* R15419 */ + 0x0000, /* R15420 */ + 0x0000, /* R15421 */ + 0x0000, /* R15422 */ + 0x0000, /* R15423 */ + 0x0000, /* R15424 */ + 0x0000, /* R15425 */ + 0x0000, /* R15426 */ + 0x0000, /* R15427 */ + 0x0000, /* R15428 */ + 0x0000, /* R15429 */ + 0x0000, /* R15430 */ + 0x0000, /* R15431 */ + 0x0000, /* R15432 */ + 0x0000, /* R15433 */ + 0x0000, /* R15434 */ + 0x0000, /* R15435 */ + 0x0000, /* R15436 */ + 0x0000, /* R15437 */ + 0x0000, /* R15438 */ + 0x0000, /* R15439 */ + 0x0000, /* R15440 */ + 0x0000, /* R15441 */ + 0x0000, /* R15442 */ + 0x0000, /* R15443 */ + 0x0000, /* R15444 */ + 0x0000, /* R15445 */ + 0x0000, /* R15446 */ + 0x0000, /* R15447 */ + 0x0000, /* R15448 */ + 0x0000, /* R15449 */ + 0x0000, /* R15450 */ + 0x0000, /* R15451 */ + 0x0000, /* R15452 */ + 0x0000, /* R15453 */ + 0x0000, /* R15454 */ + 0x0000, /* R15455 */ + 0x0000, /* R15456 */ + 0x0000, /* R15457 */ + 0x0000, /* R15458 */ + 0x0000, /* R15459 */ + 0x0000, /* R15460 */ + 0x0000, /* R15461 */ + 0x0000, /* R15462 */ + 0x0000, /* R15463 */ + 0x0000, /* R15464 */ + 0x0000, /* R15465 */ + 0x0000, /* R15466 */ + 0x0000, /* R15467 */ + 0x0000, /* R15468 */ + 0x0000, /* R15469 */ + 0x0000, /* R15470 */ + 0x0000, /* R15471 */ + 0x0000, /* R15472 */ + 0x0000, /* R15473 */ + 0x0000, /* R15474 */ + 0x0000, /* R15475 */ + 0x0000, /* R15476 */ + 0x0000, /* R15477 */ + 0x0000, /* R15478 */ + 0x0000, /* R15479 */ + 0x0000, /* R15480 */ + 0x0000, /* R15481 */ + 0x0000, /* R15482 */ + 0x0000, /* R15483 */ + 0x0000, /* R15484 */ + 0x0000, /* R15485 */ + 0x0000, /* R15486 */ + 0x0000, /* R15487 */ + 0x0000, /* R15488 */ + 0x0000, /* R15489 */ + 0x0000, /* R15490 */ + 0x0000, /* R15491 */ + 0x0000, /* R15492 */ + 0x0000, /* R15493 */ + 0x0000, /* R15494 */ + 0x0000, /* R15495 */ + 0x0000, /* R15496 */ + 0x0000, /* R15497 */ + 0x0000, /* R15498 */ + 0x0000, /* R15499 */ + 0x0000, /* R15500 */ + 0x0000, /* R15501 */ + 0x0000, /* R15502 */ + 0x0000, /* R15503 */ + 0x0000, /* R15504 */ + 0x0000, /* R15505 */ + 0x0000, /* R15506 */ + 0x0000, /* R15507 */ + 0x0000, /* R15508 */ + 0x0000, /* R15509 */ + 0x0000, /* R15510 */ + 0x0000, /* R15511 */ + 0x0000, /* R15512 */ + 0x0000, /* R15513 */ + 0x0000, /* R15514 */ + 0x0000, /* R15515 */ + 0x0000, /* R15516 */ + 0x0000, /* R15517 */ + 0x0000, /* R15518 */ + 0x0000, /* R15519 */ + 0x0000, /* R15520 */ + 0x0000, /* R15521 */ + 0x0000, /* R15522 */ + 0x0000, /* R15523 */ + 0x0000, /* R15524 */ + 0x0000, /* R15525 */ + 0x0000, /* R15526 */ + 0x0000, /* R15527 */ + 0x0000, /* R15528 */ + 0x0000, /* R15529 */ + 0x0000, /* R15530 */ + 0x0000, /* R15531 */ + 0x0000, /* R15532 */ + 0x0000, /* R15533 */ + 0x0000, /* R15534 */ + 0x0000, /* R15535 */ + 0x0000, /* R15536 */ + 0x0000, /* R15537 */ + 0x0000, /* R15538 */ + 0x0000, /* R15539 */ + 0x0000, /* R15540 */ + 0x0000, /* R15541 */ + 0x0000, /* R15542 */ + 0x0000, /* R15543 */ + 0x0000, /* R15544 */ + 0x0000, /* R15545 */ + 0x0000, /* R15546 */ + 0x0000, /* R15547 */ + 0x0000, /* R15548 */ + 0x0000, /* R15549 */ + 0x0000, /* R15550 */ + 0x0000, /* R15551 */ + 0x0000, /* R15552 */ + 0x0000, /* R15553 */ + 0x0000, /* R15554 */ + 0x0000, /* R15555 */ + 0x0000, /* R15556 */ + 0x0000, /* R15557 */ + 0x0000, /* R15558 */ + 0x0000, /* R15559 */ + 0x0000, /* R15560 */ + 0x0000, /* R15561 */ + 0x0000, /* R15562 */ + 0x0000, /* R15563 */ + 0x0000, /* R15564 */ + 0x0000, /* R15565 */ + 0x0000, /* R15566 */ + 0x0000, /* R15567 */ + 0x0000, /* R15568 */ + 0x0000, /* R15569 */ + 0x0000, /* R15570 */ + 0x0000, /* R15571 */ + 0x0000, /* R15572 */ + 0x0000, /* R15573 */ + 0x0000, /* R15574 */ + 0x0000, /* R15575 */ + 0x0000, /* R15576 */ + 0x0000, /* R15577 */ + 0x0000, /* R15578 */ + 0x0000, /* R15579 */ + 0x0000, /* R15580 */ + 0x0000, /* R15581 */ + 0x0000, /* R15582 */ + 0x0000, /* R15583 */ + 0x0000, /* R15584 */ + 0x0000, /* R15585 */ + 0x0000, /* R15586 */ + 0x0000, /* R15587 */ + 0x0000, /* R15588 */ + 0x0000, /* R15589 */ + 0x0000, /* R15590 */ + 0x0000, /* R15591 */ + 0x0000, /* R15592 */ + 0x0000, /* R15593 */ + 0x0000, /* R15594 */ + 0x0000, /* R15595 */ + 0x0000, /* R15596 */ + 0x0000, /* R15597 */ + 0x0000, /* R15598 */ + 0x0000, /* R15599 */ + 0x0000, /* R15600 */ + 0x0000, /* R15601 */ + 0x0000, /* R15602 */ + 0x0000, /* R15603 */ + 0x0000, /* R15604 */ + 0x0000, /* R15605 */ + 0x0000, /* R15606 */ + 0x0000, /* R15607 */ + 0x0000, /* R15608 */ + 0x0000, /* R15609 */ + 0x0000, /* R15610 */ + 0x0000, /* R15611 */ + 0x0000, /* R15612 */ + 0x0000, /* R15613 */ + 0x0000, /* R15614 */ + 0x0000, /* R15615 */ + 0x0000, /* R15616 */ + 0x0000, /* R15617 */ + 0x0000, /* R15618 */ + 0x0000, /* R15619 */ + 0x0000, /* R15620 */ + 0x0000, /* R15621 */ + 0x0000, /* R15622 */ + 0x0000, /* R15623 */ + 0x0000, /* R15624 */ + 0x0000, /* R15625 */ + 0x0000, /* R15626 */ + 0x0000, /* R15627 */ + 0x0000, /* R15628 */ + 0x0000, /* R15629 */ + 0x0000, /* R15630 */ + 0x0000, /* R15631 */ + 0x0000, /* R15632 */ + 0x0000, /* R15633 */ + 0x0000, /* R15634 */ + 0x0000, /* R15635 */ + 0x0000, /* R15636 */ + 0x0000, /* R15637 */ + 0x0000, /* R15638 */ + 0x0000, /* R15639 */ + 0x0000, /* R15640 */ + 0x0000, /* R15641 */ + 0x0000, /* R15642 */ + 0x0000, /* R15643 */ + 0x0000, /* R15644 */ + 0x0000, /* R15645 */ + 0x0000, /* R15646 */ + 0x0000, /* R15647 */ + 0x0000, /* R15648 */ + 0x0000, /* R15649 */ + 0x0000, /* R15650 */ + 0x0000, /* R15651 */ + 0x0000, /* R15652 */ + 0x0000, /* R15653 */ + 0x0000, /* R15654 */ + 0x0000, /* R15655 */ + 0x0000, /* R15656 */ + 0x0000, /* R15657 */ + 0x0000, /* R15658 */ + 0x0000, /* R15659 */ + 0x0000, /* R15660 */ + 0x0000, /* R15661 */ + 0x0000, /* R15662 */ + 0x0000, /* R15663 */ + 0x0000, /* R15664 */ + 0x0000, /* R15665 */ + 0x0000, /* R15666 */ + 0x0000, /* R15667 */ + 0x0000, /* R15668 */ + 0x0000, /* R15669 */ + 0x0000, /* R15670 */ + 0x0000, /* R15671 */ + 0x0000, /* R15672 */ + 0x0000, /* R15673 */ + 0x0000, /* R15674 */ + 0x0000, /* R15675 */ + 0x0000, /* R15676 */ + 0x0000, /* R15677 */ + 0x0000, /* R15678 */ + 0x0000, /* R15679 */ + 0x0000, /* R15680 */ + 0x0000, /* R15681 */ + 0x0000, /* R15682 */ + 0x0000, /* R15683 */ + 0x0000, /* R15684 */ + 0x0000, /* R15685 */ + 0x0000, /* R15686 */ + 0x0000, /* R15687 */ + 0x0000, /* R15688 */ + 0x0000, /* R15689 */ + 0x0000, /* R15690 */ + 0x0000, /* R15691 */ + 0x0000, /* R15692 */ + 0x0000, /* R15693 */ + 0x0000, /* R15694 */ + 0x0000, /* R15695 */ + 0x0000, /* R15696 */ + 0x0000, /* R15697 */ + 0x0000, /* R15698 */ + 0x0000, /* R15699 */ + 0x0000, /* R15700 */ + 0x0000, /* R15701 */ + 0x0000, /* R15702 */ + 0x0000, /* R15703 */ + 0x0000, /* R15704 */ + 0x0000, /* R15705 */ + 0x0000, /* R15706 */ + 0x0000, /* R15707 */ + 0x0000, /* R15708 */ + 0x0000, /* R15709 */ + 0x0000, /* R15710 */ + 0x0000, /* R15711 */ + 0x0000, /* R15712 */ + 0x0000, /* R15713 */ + 0x0000, /* R15714 */ + 0x0000, /* R15715 */ + 0x0000, /* R15716 */ + 0x0000, /* R15717 */ + 0x0000, /* R15718 */ + 0x0000, /* R15719 */ + 0x0000, /* R15720 */ + 0x0000, /* R15721 */ + 0x0000, /* R15722 */ + 0x0000, /* R15723 */ + 0x0000, /* R15724 */ + 0x0000, /* R15725 */ + 0x0000, /* R15726 */ + 0x0000, /* R15727 */ + 0x0000, /* R15728 */ + 0x0000, /* R15729 */ + 0x0000, /* R15730 */ + 0x0000, /* R15731 */ + 0x0000, /* R15732 */ + 0x0000, /* R15733 */ + 0x0000, /* R15734 */ + 0x0000, /* R15735 */ + 0x0000, /* R15736 */ + 0x0000, /* R15737 */ + 0x0000, /* R15738 */ + 0x0000, /* R15739 */ + 0x0000, /* R15740 */ + 0x0000, /* R15741 */ + 0x0000, /* R15742 */ + 0x0000, /* R15743 */ + 0x0000, /* R15744 */ + 0x0000, /* R15745 */ + 0x0000, /* R15746 */ + 0x0000, /* R15747 */ + 0x0000, /* R15748 */ + 0x0000, /* R15749 */ + 0x0000, /* R15750 */ + 0x0000, /* R15751 */ + 0x0000, /* R15752 */ + 0x0000, /* R15753 */ + 0x0000, /* R15754 */ + 0x0000, /* R15755 */ + 0x0000, /* R15756 */ + 0x0000, /* R15757 */ + 0x0000, /* R15758 */ + 0x0000, /* R15759 */ + 0x0000, /* R15760 */ + 0x0000, /* R15761 */ + 0x0000, /* R15762 */ + 0x0000, /* R15763 */ + 0x0000, /* R15764 */ + 0x0000, /* R15765 */ + 0x0000, /* R15766 */ + 0x0000, /* R15767 */ + 0x0000, /* R15768 */ + 0x0000, /* R15769 */ + 0x0000, /* R15770 */ + 0x0000, /* R15771 */ + 0x0000, /* R15772 */ + 0x0000, /* R15773 */ + 0x0000, /* R15774 */ + 0x0000, /* R15775 */ + 0x0000, /* R15776 */ + 0x0000, /* R15777 */ + 0x0000, /* R15778 */ + 0x0000, /* R15779 */ + 0x0000, /* R15780 */ + 0x0000, /* R15781 */ + 0x0000, /* R15782 */ + 0x0000, /* R15783 */ + 0x0000, /* R15784 */ + 0x0000, /* R15785 */ + 0x0000, /* R15786 */ + 0x0000, /* R15787 */ + 0x0000, /* R15788 */ + 0x0000, /* R15789 */ + 0x0000, /* R15790 */ + 0x0000, /* R15791 */ + 0x0000, /* R15792 */ + 0x0000, /* R15793 */ + 0x0000, /* R15794 */ + 0x0000, /* R15795 */ + 0x0000, /* R15796 */ + 0x0000, /* R15797 */ + 0x0000, /* R15798 */ + 0x0000, /* R15799 */ + 0x0000, /* R15800 */ + 0x0000, /* R15801 */ + 0x0000, /* R15802 */ + 0x0000, /* R15803 */ + 0x0000, /* R15804 */ + 0x0000, /* R15805 */ + 0x0000, /* R15806 */ + 0x0000, /* R15807 */ + 0x0000, /* R15808 */ + 0x0000, /* R15809 */ + 0x0000, /* R15810 */ + 0x0000, /* R15811 */ + 0x0000, /* R15812 */ + 0x0000, /* R15813 */ + 0x0000, /* R15814 */ + 0x0000, /* R15815 */ + 0x0000, /* R15816 */ + 0x0000, /* R15817 */ + 0x0000, /* R15818 */ + 0x0000, /* R15819 */ + 0x0000, /* R15820 */ + 0x0000, /* R15821 */ + 0x0000, /* R15822 */ + 0x0000, /* R15823 */ + 0x0000, /* R15824 */ + 0x0000, /* R15825 */ + 0x0000, /* R15826 */ + 0x0000, /* R15827 */ + 0x0000, /* R15828 */ + 0x0000, /* R15829 */ + 0x0000, /* R15830 */ + 0x0000, /* R15831 */ + 0x0000, /* R15832 */ + 0x0000, /* R15833 */ + 0x0000, /* R15834 */ + 0x0000, /* R15835 */ + 0x0000, /* R15836 */ + 0x0000, /* R15837 */ + 0x0000, /* R15838 */ + 0x0000, /* R15839 */ + 0x0000, /* R15840 */ + 0x0000, /* R15841 */ + 0x0000, /* R15842 */ + 0x0000, /* R15843 */ + 0x0000, /* R15844 */ + 0x0000, /* R15845 */ + 0x0000, /* R15846 */ + 0x0000, /* R15847 */ + 0x0000, /* R15848 */ + 0x0000, /* R15849 */ + 0x0000, /* R15850 */ + 0x0000, /* R15851 */ + 0x0000, /* R15852 */ + 0x0000, /* R15853 */ + 0x0000, /* R15854 */ + 0x0000, /* R15855 */ + 0x0000, /* R15856 */ + 0x0000, /* R15857 */ + 0x0000, /* R15858 */ + 0x0000, /* R15859 */ + 0x0000, /* R15860 */ + 0x0000, /* R15861 */ + 0x0000, /* R15862 */ + 0x0000, /* R15863 */ + 0x0000, /* R15864 */ + 0x0000, /* R15865 */ + 0x0000, /* R15866 */ + 0x0000, /* R15867 */ + 0x0000, /* R15868 */ + 0x0000, /* R15869 */ + 0x0000, /* R15870 */ + 0x0000, /* R15871 */ + 0x0000, /* R15872 */ + 0x0000, /* R15873 */ + 0x0000, /* R15874 */ + 0x0000, /* R15875 */ + 0x0000, /* R15876 */ + 0x0000, /* R15877 */ + 0x0000, /* R15878 */ + 0x0000, /* R15879 */ + 0x0000, /* R15880 */ + 0x0000, /* R15881 */ + 0x0000, /* R15882 */ + 0x0000, /* R15883 */ + 0x0000, /* R15884 */ + 0x0000, /* R15885 */ + 0x0000, /* R15886 */ + 0x0000, /* R15887 */ + 0x0000, /* R15888 */ + 0x0000, /* R15889 */ + 0x0000, /* R15890 */ + 0x0000, /* R15891 */ + 0x0000, /* R15892 */ + 0x0000, /* R15893 */ + 0x0000, /* R15894 */ + 0x0000, /* R15895 */ + 0x0000, /* R15896 */ + 0x0000, /* R15897 */ + 0x0000, /* R15898 */ + 0x0000, /* R15899 */ + 0x0000, /* R15900 */ + 0x0000, /* R15901 */ + 0x0000, /* R15902 */ + 0x0000, /* R15903 */ + 0x0000, /* R15904 */ + 0x0000, /* R15905 */ + 0x0000, /* R15906 */ + 0x0000, /* R15907 */ + 0x0000, /* R15908 */ + 0x0000, /* R15909 */ + 0x0000, /* R15910 */ + 0x0000, /* R15911 */ + 0x0000, /* R15912 */ + 0x0000, /* R15913 */ + 0x0000, /* R15914 */ + 0x0000, /* R15915 */ + 0x0000, /* R15916 */ + 0x0000, /* R15917 */ + 0x0000, /* R15918 */ + 0x0000, /* R15919 */ + 0x0000, /* R15920 */ + 0x0000, /* R15921 */ + 0x0000, /* R15922 */ + 0x0000, /* R15923 */ + 0x0000, /* R15924 */ + 0x0000, /* R15925 */ + 0x0000, /* R15926 */ + 0x0000, /* R15927 */ + 0x0000, /* R15928 */ + 0x0000, /* R15929 */ + 0x0000, /* R15930 */ + 0x0000, /* R15931 */ + 0x0000, /* R15932 */ + 0x0000, /* R15933 */ + 0x0000, /* R15934 */ + 0x0000, /* R15935 */ + 0x0000, /* R15936 */ + 0x0000, /* R15937 */ + 0x0000, /* R15938 */ + 0x0000, /* R15939 */ + 0x0000, /* R15940 */ + 0x0000, /* R15941 */ + 0x0000, /* R15942 */ + 0x0000, /* R15943 */ + 0x0000, /* R15944 */ + 0x0000, /* R15945 */ + 0x0000, /* R15946 */ + 0x0000, /* R15947 */ + 0x0000, /* R15948 */ + 0x0000, /* R15949 */ + 0x0000, /* R15950 */ + 0x0000, /* R15951 */ + 0x0000, /* R15952 */ + 0x0000, /* R15953 */ + 0x0000, /* R15954 */ + 0x0000, /* R15955 */ + 0x0000, /* R15956 */ + 0x0000, /* R15957 */ + 0x0000, /* R15958 */ + 0x0000, /* R15959 */ + 0x0000, /* R15960 */ + 0x0000, /* R15961 */ + 0x0000, /* R15962 */ + 0x0000, /* R15963 */ + 0x0000, /* R15964 */ + 0x0000, /* R15965 */ + 0x0000, /* R15966 */ + 0x0000, /* R15967 */ + 0x0000, /* R15968 */ + 0x0000, /* R15969 */ + 0x0000, /* R15970 */ + 0x0000, /* R15971 */ + 0x0000, /* R15972 */ + 0x0000, /* R15973 */ + 0x0000, /* R15974 */ + 0x0000, /* R15975 */ + 0x0000, /* R15976 */ + 0x0000, /* R15977 */ + 0x0000, /* R15978 */ + 0x0000, /* R15979 */ + 0x0000, /* R15980 */ + 0x0000, /* R15981 */ + 0x0000, /* R15982 */ + 0x0000, /* R15983 */ + 0x0000, /* R15984 */ + 0x0000, /* R15985 */ + 0x0000, /* R15986 */ + 0x0000, /* R15987 */ + 0x0000, /* R15988 */ + 0x0000, /* R15989 */ + 0x0000, /* R15990 */ + 0x0000, /* R15991 */ + 0x0000, /* R15992 */ + 0x0000, /* R15993 */ + 0x0000, /* R15994 */ + 0x0000, /* R15995 */ + 0x0000, /* R15996 */ + 0x0000, /* R15997 */ + 0x0000, /* R15998 */ + 0x0000, /* R15999 */ + 0x0000, /* R16000 */ + 0x0000, /* R16001 */ + 0x0000, /* R16002 */ + 0x0000, /* R16003 */ + 0x0000, /* R16004 */ + 0x0000, /* R16005 */ + 0x0000, /* R16006 */ + 0x0000, /* R16007 */ + 0x0000, /* R16008 */ + 0x0000, /* R16009 */ + 0x0000, /* R16010 */ + 0x0000, /* R16011 */ + 0x0000, /* R16012 */ + 0x0000, /* R16013 */ + 0x0000, /* R16014 */ + 0x0000, /* R16015 */ + 0x0000, /* R16016 */ + 0x0000, /* R16017 */ + 0x0000, /* R16018 */ + 0x0000, /* R16019 */ + 0x0000, /* R16020 */ + 0x0000, /* R16021 */ + 0x0000, /* R16022 */ + 0x0000, /* R16023 */ + 0x0000, /* R16024 */ + 0x0000, /* R16025 */ + 0x0000, /* R16026 */ + 0x0000, /* R16027 */ + 0x0000, /* R16028 */ + 0x0000, /* R16029 */ + 0x0000, /* R16030 */ + 0x0000, /* R16031 */ + 0x0000, /* R16032 */ + 0x0000, /* R16033 */ + 0x0000, /* R16034 */ + 0x0000, /* R16035 */ + 0x0000, /* R16036 */ + 0x0000, /* R16037 */ + 0x0000, /* R16038 */ + 0x0000, /* R16039 */ + 0x0000, /* R16040 */ + 0x0000, /* R16041 */ + 0x0000, /* R16042 */ + 0x0000, /* R16043 */ + 0x0000, /* R16044 */ + 0x0000, /* R16045 */ + 0x0000, /* R16046 */ + 0x0000, /* R16047 */ + 0x0000, /* R16048 */ + 0x0000, /* R16049 */ + 0x0000, /* R16050 */ + 0x0000, /* R16051 */ + 0x0000, /* R16052 */ + 0x0000, /* R16053 */ + 0x0000, /* R16054 */ + 0x0000, /* R16055 */ + 0x0000, /* R16056 */ + 0x0000, /* R16057 */ + 0x0000, /* R16058 */ + 0x0000, /* R16059 */ + 0x0000, /* R16060 */ + 0x0000, /* R16061 */ + 0x0000, /* R16062 */ + 0x0000, /* R16063 */ + 0x0000, /* R16064 */ + 0x0000, /* R16065 */ + 0x0000, /* R16066 */ + 0x0000, /* R16067 */ + 0x0000, /* R16068 */ + 0x0000, /* R16069 */ + 0x0000, /* R16070 */ + 0x0000, /* R16071 */ + 0x0000, /* R16072 */ + 0x0000, /* R16073 */ + 0x0000, /* R16074 */ + 0x0000, /* R16075 */ + 0x0000, /* R16076 */ + 0x0000, /* R16077 */ + 0x0000, /* R16078 */ + 0x0000, /* R16079 */ + 0x0000, /* R16080 */ + 0x0000, /* R16081 */ + 0x0000, /* R16082 */ + 0x0000, /* R16083 */ + 0x0000, /* R16084 */ + 0x0000, /* R16085 */ + 0x0000, /* R16086 */ + 0x0000, /* R16087 */ + 0x0000, /* R16088 */ + 0x0000, /* R16089 */ + 0x0000, /* R16090 */ + 0x0000, /* R16091 */ + 0x0000, /* R16092 */ + 0x0000, /* R16093 */ + 0x0000, /* R16094 */ + 0x0000, /* R16095 */ + 0x0000, /* R16096 */ + 0x0000, /* R16097 */ + 0x0000, /* R16098 */ + 0x0000, /* R16099 */ + 0x0000, /* R16100 */ + 0x0000, /* R16101 */ + 0x0000, /* R16102 */ + 0x0000, /* R16103 */ + 0x0000, /* R16104 */ + 0x0000, /* R16105 */ + 0x0000, /* R16106 */ + 0x0000, /* R16107 */ + 0x0000, /* R16108 */ + 0x0000, /* R16109 */ + 0x0000, /* R16110 */ + 0x0000, /* R16111 */ + 0x0000, /* R16112 */ + 0x0000, /* R16113 */ + 0x0000, /* R16114 */ + 0x0000, /* R16115 */ + 0x0000, /* R16116 */ + 0x0000, /* R16117 */ + 0x0000, /* R16118 */ + 0x0000, /* R16119 */ + 0x0000, /* R16120 */ + 0x0000, /* R16121 */ + 0x0000, /* R16122 */ + 0x0000, /* R16123 */ + 0x0000, /* R16124 */ + 0x0000, /* R16125 */ + 0x0000, /* R16126 */ + 0x0000, /* R16127 */ + 0x0000, /* R16128 */ + 0x0000, /* R16129 */ + 0x0000, /* R16130 */ + 0x0000, /* R16131 */ + 0x0000, /* R16132 */ + 0x0000, /* R16133 */ + 0x0000, /* R16134 */ + 0x0000, /* R16135 */ + 0x0000, /* R16136 */ + 0x0000, /* R16137 */ + 0x0000, /* R16138 */ + 0x0000, /* R16139 */ + 0x0000, /* R16140 */ + 0x0000, /* R16141 */ + 0x0000, /* R16142 */ + 0x0000, /* R16143 */ + 0x0000, /* R16144 */ + 0x0000, /* R16145 */ + 0x0000, /* R16146 */ + 0x0000, /* R16147 */ + 0x0000, /* R16148 */ + 0x0000, /* R16149 */ + 0x0000, /* R16150 */ + 0x0000, /* R16151 */ + 0x0000, /* R16152 */ + 0x0000, /* R16153 */ + 0x0000, /* R16154 */ + 0x0000, /* R16155 */ + 0x0000, /* R16156 */ + 0x0000, /* R16157 */ + 0x0000, /* R16158 */ + 0x0000, /* R16159 */ + 0x0000, /* R16160 */ + 0x0000, /* R16161 */ + 0x0000, /* R16162 */ + 0x0000, /* R16163 */ + 0x0000, /* R16164 */ + 0x0000, /* R16165 */ + 0x0000, /* R16166 */ + 0x0000, /* R16167 */ + 0x0000, /* R16168 */ + 0x0000, /* R16169 */ + 0x0000, /* R16170 */ + 0x0000, /* R16171 */ + 0x0000, /* R16172 */ + 0x0000, /* R16173 */ + 0x0000, /* R16174 */ + 0x0000, /* R16175 */ + 0x0000, /* R16176 */ + 0x0000, /* R16177 */ + 0x0000, /* R16178 */ + 0x0000, /* R16179 */ + 0x0000, /* R16180 */ + 0x0000, /* R16181 */ + 0x0000, /* R16182 */ + 0x0000, /* R16183 */ + 0x0000, /* R16184 */ + 0x0000, /* R16185 */ + 0x0000, /* R16186 */ + 0x0000, /* R16187 */ + 0x0000, /* R16188 */ + 0x0000, /* R16189 */ + 0x0000, /* R16190 */ + 0x0000, /* R16191 */ + 0x0000, /* R16192 */ + 0x0000, /* R16193 */ + 0x0000, /* R16194 */ + 0x0000, /* R16195 */ + 0x0000, /* R16196 */ + 0x0000, /* R16197 */ + 0x0000, /* R16198 */ + 0x0000, /* R16199 */ + 0x0000, /* R16200 */ + 0x0000, /* R16201 */ + 0x0000, /* R16202 */ + 0x0000, /* R16203 */ + 0x0000, /* R16204 */ + 0x0000, /* R16205 */ + 0x0000, /* R16206 */ + 0x0000, /* R16207 */ + 0x0000, /* R16208 */ + 0x0000, /* R16209 */ + 0x0000, /* R16210 */ + 0x0000, /* R16211 */ + 0x0000, /* R16212 */ + 0x0000, /* R16213 */ + 0x0000, /* R16214 */ + 0x0000, /* R16215 */ + 0x0000, /* R16216 */ + 0x0000, /* R16217 */ + 0x0000, /* R16218 */ + 0x0000, /* R16219 */ + 0x0000, /* R16220 */ + 0x0000, /* R16221 */ + 0x0000, /* R16222 */ + 0x0000, /* R16223 */ + 0x0000, /* R16224 */ + 0x0000, /* R16225 */ + 0x0000, /* R16226 */ + 0x0000, /* R16227 */ + 0x0000, /* R16228 */ + 0x0000, /* R16229 */ + 0x0000, /* R16230 */ + 0x0000, /* R16231 */ + 0x0000, /* R16232 */ + 0x0000, /* R16233 */ + 0x0000, /* R16234 */ + 0x0000, /* R16235 */ + 0x0000, /* R16236 */ + 0x0000, /* R16237 */ + 0x0000, /* R16238 */ + 0x0000, /* R16239 */ + 0x0000, /* R16240 */ + 0x0000, /* R16241 */ + 0x0000, /* R16242 */ + 0x0000, /* R16243 */ + 0x0000, /* R16244 */ + 0x0000, /* R16245 */ + 0x0000, /* R16246 */ + 0x0000, /* R16247 */ + 0x0000, /* R16248 */ + 0x0000, /* R16249 */ + 0x0000, /* R16250 */ + 0x0000, /* R16251 */ + 0x0000, /* R16252 */ + 0x0000, /* R16253 */ + 0x0000, /* R16254 */ + 0x0000, /* R16255 */ + 0x0000, /* R16256 */ + 0x0000, /* R16257 */ + 0x0000, /* R16258 */ + 0x0000, /* R16259 */ + 0x0000, /* R16260 */ + 0x0000, /* R16261 */ + 0x0000, /* R16262 */ + 0x0000, /* R16263 */ + 0x0000, /* R16264 */ + 0x0000, /* R16265 */ + 0x0000, /* R16266 */ + 0x0000, /* R16267 */ + 0x0000, /* R16268 */ + 0x0000, /* R16269 */ + 0x0000, /* R16270 */ + 0x0000, /* R16271 */ + 0x0000, /* R16272 */ + 0x0000, /* R16273 */ + 0x0000, /* R16274 */ + 0x0000, /* R16275 */ + 0x0000, /* R16276 */ + 0x0000, /* R16277 */ + 0x0000, /* R16278 */ + 0x0000, /* R16279 */ + 0x0000, /* R16280 */ + 0x0000, /* R16281 */ + 0x0000, /* R16282 */ + 0x0000, /* R16283 */ + 0x0000, /* R16284 */ + 0x0000, /* R16285 */ + 0x0000, /* R16286 */ + 0x0000, /* R16287 */ + 0x0000, /* R16288 */ + 0x0000, /* R16289 */ + 0x0000, /* R16290 */ + 0x0000, /* R16291 */ + 0x0000, /* R16292 */ + 0x0000, /* R16293 */ + 0x0000, /* R16294 */ + 0x0000, /* R16295 */ + 0x0000, /* R16296 */ + 0x0000, /* R16297 */ + 0x0000, /* R16298 */ + 0x0000, /* R16299 */ + 0x0000, /* R16300 */ + 0x0000, /* R16301 */ + 0x0000, /* R16302 */ + 0x0000, /* R16303 */ + 0x0000, /* R16304 */ + 0x0000, /* R16305 */ + 0x0000, /* R16306 */ + 0x0000, /* R16307 */ + 0x0000, /* R16308 */ + 0x0000, /* R16309 */ + 0x0000, /* R16310 */ + 0x0000, /* R16311 */ + 0x0000, /* R16312 */ + 0x0000, /* R16313 */ + 0x0000, /* R16314 */ + 0x0000, /* R16315 */ + 0x0000, /* R16316 */ + 0x0000, /* R16317 */ + 0x0000, /* R16318 */ + 0x0000, /* R16319 */ + 0x0000, /* R16320 */ + 0x0000, /* R16321 */ + 0x0000, /* R16322 */ + 0x0000, /* R16323 */ + 0x0000, /* R16324 */ + 0x0000, /* R16325 */ + 0x0000, /* R16326 */ + 0x0000, /* R16327 */ + 0x0000, /* R16328 */ + 0x0000, /* R16329 */ + 0x0000, /* R16330 */ + 0x0000, /* R16331 */ + 0x0000, /* R16332 */ + 0x0000, /* R16333 */ + 0x0000, /* R16334 */ + 0x0000, /* R16335 */ + 0x0000, /* R16336 */ + 0x0000, /* R16337 */ + 0x0000, /* R16338 */ + 0x0000, /* R16339 */ + 0x0000, /* R16340 */ + 0x0000, /* R16341 */ + 0x0000, /* R16342 */ + 0x0000, /* R16343 */ + 0x0000, /* R16344 */ + 0x0000, /* R16345 */ + 0x0000, /* R16346 */ + 0x0000, /* R16347 */ + 0x0000, /* R16348 */ + 0x0000, /* R16349 */ + 0x0000, /* R16350 */ + 0x0000, /* R16351 */ + 0x0000, /* R16352 */ + 0x0000, /* R16353 */ + 0x0000, /* R16354 */ + 0x0000, /* R16355 */ + 0x0000, /* R16356 */ + 0x0000, /* R16357 */ + 0x0000, /* R16358 */ + 0x0000, /* R16359 */ + 0x0000, /* R16360 */ + 0x0000, /* R16361 */ + 0x0000, /* R16362 */ + 0x0000, /* R16363 */ + 0x0000, /* R16364 */ + 0x0000, /* R16365 */ + 0x0000, /* R16366 */ + 0x0000, /* R16367 */ + 0x0000, /* R16368 */ + 0x0000, /* R16369 */ + 0x0000, /* R16370 */ + 0x0000, /* R16371 */ + 0x0000, /* R16372 */ + 0x0000, /* R16373 */ + 0x0000, /* R16374 */ + 0x0000, /* R16375 */ + 0x0000, /* R16376 */ + 0x0000, /* R16377 */ + 0x0000, /* R16378 */ + 0x0000, /* R16379 */ + 0x0000, /* R16380 */ + 0x0000, /* R16381 */ + 0x0000, /* R16382 */ + 0x0000, /* R16383 */ + 0x0000, /* R16384 - RETUNEADC_SHARED_COEFF_1 */ + 0x0000, /* R16385 - RETUNEADC_SHARED_COEFF_0 */ + 0x0000, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */ + 0x0000, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */ + 0x0000, /* R16388 - SOUNDSTAGE_ENABLES_1 */ + 0x0000, /* R16389 - SOUNDSTAGE_ENABLES_0 */ + 0x0000, /* R16390 */ + 0x0000, /* R16391 */ + 0x0000, /* R16392 */ + 0x0000, /* R16393 */ + 0x0000, /* R16394 */ + 0x0000, /* R16395 */ + 0x0000, /* R16396 */ + 0x0000, /* R16397 */ + 0x0000, /* R16398 */ + 0x0000, /* R16399 */ + 0x0000, /* R16400 */ + 0x0000, /* R16401 */ + 0x0000, /* R16402 */ + 0x0000, /* R16403 */ + 0x0000, /* R16404 */ + 0x0000, /* R16405 */ + 0x0000, /* R16406 */ + 0x0000, /* R16407 */ + 0x0000, /* R16408 */ + 0x0000, /* R16409 */ + 0x0000, /* R16410 */ + 0x0000, /* R16411 */ + 0x0000, /* R16412 */ + 0x0000, /* R16413 */ + 0x0000, /* R16414 */ + 0x0000, /* R16415 */ + 0x0000, /* R16416 */ + 0x0000, /* R16417 */ + 0x0000, /* R16418 */ + 0x0000, /* R16419 */ + 0x0000, /* R16420 */ + 0x0000, /* R16421 */ + 0x0000, /* R16422 */ + 0x0000, /* R16423 */ + 0x0000, /* R16424 */ + 0x0000, /* R16425 */ + 0x0000, /* R16426 */ + 0x0000, /* R16427 */ + 0x0000, /* R16428 */ + 0x0000, /* R16429 */ + 0x0000, /* R16430 */ + 0x0000, /* R16431 */ + 0x0000, /* R16432 */ + 0x0000, /* R16433 */ + 0x0000, /* R16434 */ + 0x0000, /* R16435 */ + 0x0000, /* R16436 */ + 0x0000, /* R16437 */ + 0x0000, /* R16438 */ + 0x0000, /* R16439 */ + 0x0000, /* R16440 */ + 0x0000, /* R16441 */ + 0x0000, /* R16442 */ + 0x0000, /* R16443 */ + 0x0000, /* R16444 */ + 0x0000, /* R16445 */ + 0x0000, /* R16446 */ + 0x0000, /* R16447 */ + 0x0000, /* R16448 */ + 0x0000, /* R16449 */ + 0x0000, /* R16450 */ + 0x0000, /* R16451 */ + 0x0000, /* R16452 */ + 0x0000, /* R16453 */ + 0x0000, /* R16454 */ + 0x0000, /* R16455 */ + 0x0000, /* R16456 */ + 0x0000, /* R16457 */ + 0x0000, /* R16458 */ + 0x0000, /* R16459 */ + 0x0000, /* R16460 */ + 0x0000, /* R16461 */ + 0x0000, /* R16462 */ + 0x0000, /* R16463 */ + 0x0000, /* R16464 */ + 0x0000, /* R16465 */ + 0x0000, /* R16466 */ + 0x0000, /* R16467 */ + 0x0000, /* R16468 */ + 0x0000, /* R16469 */ + 0x0000, /* R16470 */ + 0x0000, /* R16471 */ + 0x0000, /* R16472 */ + 0x0000, /* R16473 */ + 0x0000, /* R16474 */ + 0x0000, /* R16475 */ + 0x0000, /* R16476 */ + 0x0000, /* R16477 */ + 0x0000, /* R16478 */ + 0x0000, /* R16479 */ + 0x0000, /* R16480 */ + 0x0000, /* R16481 */ + 0x0000, /* R16482 */ + 0x0000, /* R16483 */ + 0x0000, /* R16484 */ + 0x0000, /* R16485 */ + 0x0000, /* R16486 */ + 0x0000, /* R16487 */ + 0x0000, /* R16488 */ + 0x0000, /* R16489 */ + 0x0000, /* R16490 */ + 0x0000, /* R16491 */ + 0x0000, /* R16492 */ + 0x0000, /* R16493 */ + 0x0000, /* R16494 */ + 0x0000, /* R16495 */ + 0x0000, /* R16496 */ + 0x0000, /* R16497 */ + 0x0000, /* R16498 */ + 0x0000, /* R16499 */ + 0x0000, /* R16500 */ + 0x0000, /* R16501 */ + 0x0000, /* R16502 */ + 0x0000, /* R16503 */ + 0x0000, /* R16504 */ + 0x0000, /* R16505 */ + 0x0000, /* R16506 */ + 0x0000, /* R16507 */ + 0x0000, /* R16508 */ + 0x0000, /* R16509 */ + 0x0000, /* R16510 */ + 0x0000, /* R16511 */ + 0x0000, /* R16512 */ + 0x0000, /* R16513 */ + 0x0000, /* R16514 */ + 0x0000, /* R16515 */ + 0x0000, /* R16516 */ + 0x0000, /* R16517 */ + 0x0000, /* R16518 */ + 0x0000, /* R16519 */ + 0x0000, /* R16520 */ + 0x0000, /* R16521 */ + 0x0000, /* R16522 */ + 0x0000, /* R16523 */ + 0x0000, /* R16524 */ + 0x0000, /* R16525 */ + 0x0000, /* R16526 */ + 0x0000, /* R16527 */ + 0x0000, /* R16528 */ + 0x0000, /* R16529 */ + 0x0000, /* R16530 */ + 0x0000, /* R16531 */ + 0x0000, /* R16532 */ + 0x0000, /* R16533 */ + 0x0000, /* R16534 */ + 0x0000, /* R16535 */ + 0x0000, /* R16536 */ + 0x0000, /* R16537 */ + 0x0000, /* R16538 */ + 0x0000, /* R16539 */ + 0x0000, /* R16540 */ + 0x0000, /* R16541 */ + 0x0000, /* R16542 */ + 0x0000, /* R16543 */ + 0x0000, /* R16544 */ + 0x0000, /* R16545 */ + 0x0000, /* R16546 */ + 0x0000, /* R16547 */ + 0x0000, /* R16548 */ + 0x0000, /* R16549 */ + 0x0000, /* R16550 */ + 0x0000, /* R16551 */ + 0x0000, /* R16552 */ + 0x0000, /* R16553 */ + 0x0000, /* R16554 */ + 0x0000, /* R16555 */ + 0x0000, /* R16556 */ + 0x0000, /* R16557 */ + 0x0000, /* R16558 */ + 0x0000, /* R16559 */ + 0x0000, /* R16560 */ + 0x0000, /* R16561 */ + 0x0000, /* R16562 */ + 0x0000, /* R16563 */ + 0x0000, /* R16564 */ + 0x0000, /* R16565 */ + 0x0000, /* R16566 */ + 0x0000, /* R16567 */ + 0x0000, /* R16568 */ + 0x0000, /* R16569 */ + 0x0000, /* R16570 */ + 0x0000, /* R16571 */ + 0x0000, /* R16572 */ + 0x0000, /* R16573 */ + 0x0000, /* R16574 */ + 0x0000, /* R16575 */ + 0x0000, /* R16576 */ + 0x0000, /* R16577 */ + 0x0000, /* R16578 */ + 0x0000, /* R16579 */ + 0x0000, /* R16580 */ + 0x0000, /* R16581 */ + 0x0000, /* R16582 */ + 0x0000, /* R16583 */ + 0x0000, /* R16584 */ + 0x0000, /* R16585 */ + 0x0000, /* R16586 */ + 0x0000, /* R16587 */ + 0x0000, /* R16588 */ + 0x0000, /* R16589 */ + 0x0000, /* R16590 */ + 0x0000, /* R16591 */ + 0x0000, /* R16592 */ + 0x0000, /* R16593 */ + 0x0000, /* R16594 */ + 0x0000, /* R16595 */ + 0x0000, /* R16596 */ + 0x0000, /* R16597 */ + 0x0000, /* R16598 */ + 0x0000, /* R16599 */ + 0x0000, /* R16600 */ + 0x0000, /* R16601 */ + 0x0000, /* R16602 */ + 0x0000, /* R16603 */ + 0x0000, /* R16604 */ + 0x0000, /* R16605 */ + 0x0000, /* R16606 */ + 0x0000, /* R16607 */ + 0x0000, /* R16608 */ + 0x0000, /* R16609 */ + 0x0000, /* R16610 */ + 0x0000, /* R16611 */ + 0x0000, /* R16612 */ + 0x0000, /* R16613 */ + 0x0000, /* R16614 */ + 0x0000, /* R16615 */ + 0x0000, /* R16616 */ + 0x0000, /* R16617 */ + 0x0000, /* R16618 */ + 0x0000, /* R16619 */ + 0x0000, /* R16620 */ + 0x0000, /* R16621 */ + 0x0000, /* R16622 */ + 0x0000, /* R16623 */ + 0x0000, /* R16624 */ + 0x0000, /* R16625 */ + 0x0000, /* R16626 */ + 0x0000, /* R16627 */ + 0x0000, /* R16628 */ + 0x0000, /* R16629 */ + 0x0000, /* R16630 */ + 0x0000, /* R16631 */ + 0x0000, /* R16632 */ + 0x0000, /* R16633 */ + 0x0000, /* R16634 */ + 0x0000, /* R16635 */ + 0x0000, /* R16636 */ + 0x0000, /* R16637 */ + 0x0000, /* R16638 */ + 0x0000, /* R16639 */ + 0x0000, /* R16640 */ + 0x0000, /* R16641 */ + 0x0000, /* R16642 */ + 0x0000, /* R16643 */ + 0x0000, /* R16644 */ + 0x0000, /* R16645 */ + 0x0000, /* R16646 */ + 0x0000, /* R16647 */ + 0x0000, /* R16648 */ + 0x0000, /* R16649 */ + 0x0000, /* R16650 */ + 0x0000, /* R16651 */ + 0x0000, /* R16652 */ + 0x0000, /* R16653 */ + 0x0000, /* R16654 */ + 0x0000, /* R16655 */ + 0x0000, /* R16656 */ + 0x0000, /* R16657 */ + 0x0000, /* R16658 */ + 0x0000, /* R16659 */ + 0x0000, /* R16660 */ + 0x0000, /* R16661 */ + 0x0000, /* R16662 */ + 0x0000, /* R16663 */ + 0x0000, /* R16664 */ + 0x0000, /* R16665 */ + 0x0000, /* R16666 */ + 0x0000, /* R16667 */ + 0x0000, /* R16668 */ + 0x0000, /* R16669 */ + 0x0000, /* R16670 */ + 0x0000, /* R16671 */ + 0x0000, /* R16672 */ + 0x0000, /* R16673 */ + 0x0000, /* R16674 */ + 0x0000, /* R16675 */ + 0x0000, /* R16676 */ + 0x0000, /* R16677 */ + 0x0000, /* R16678 */ + 0x0000, /* R16679 */ + 0x0000, /* R16680 */ + 0x0000, /* R16681 */ + 0x0000, /* R16682 */ + 0x0000, /* R16683 */ + 0x0000, /* R16684 */ + 0x0000, /* R16685 */ + 0x0000, /* R16686 */ + 0x0000, /* R16687 */ + 0x0000, /* R16688 */ + 0x0000, /* R16689 */ + 0x0000, /* R16690 */ + 0x0000, /* R16691 */ + 0x0000, /* R16692 */ + 0x0000, /* R16693 */ + 0x0000, /* R16694 */ + 0x0000, /* R16695 */ + 0x0000, /* R16696 */ + 0x0000, /* R16697 */ + 0x0000, /* R16698 */ + 0x0000, /* R16699 */ + 0x0000, /* R16700 */ + 0x0000, /* R16701 */ + 0x0000, /* R16702 */ + 0x0000, /* R16703 */ + 0x0000, /* R16704 */ + 0x0000, /* R16705 */ + 0x0000, /* R16706 */ + 0x0000, /* R16707 */ + 0x0000, /* R16708 */ + 0x0000, /* R16709 */ + 0x0000, /* R16710 */ + 0x0000, /* R16711 */ + 0x0000, /* R16712 */ + 0x0000, /* R16713 */ + 0x0000, /* R16714 */ + 0x0000, /* R16715 */ + 0x0000, /* R16716 */ + 0x0000, /* R16717 */ + 0x0000, /* R16718 */ + 0x0000, /* R16719 */ + 0x0000, /* R16720 */ + 0x0000, /* R16721 */ + 0x0000, /* R16722 */ + 0x0000, /* R16723 */ + 0x0000, /* R16724 */ + 0x0000, /* R16725 */ + 0x0000, /* R16726 */ + 0x0000, /* R16727 */ + 0x0000, /* R16728 */ + 0x0000, /* R16729 */ + 0x0000, /* R16730 */ + 0x0000, /* R16731 */ + 0x0000, /* R16732 */ + 0x0000, /* R16733 */ + 0x0000, /* R16734 */ + 0x0000, /* R16735 */ + 0x0000, /* R16736 */ + 0x0000, /* R16737 */ + 0x0000, /* R16738 */ + 0x0000, /* R16739 */ + 0x0000, /* R16740 */ + 0x0000, /* R16741 */ + 0x0000, /* R16742 */ + 0x0000, /* R16743 */ + 0x0000, /* R16744 */ + 0x0000, /* R16745 */ + 0x0000, /* R16746 */ + 0x0000, /* R16747 */ + 0x0000, /* R16748 */ + 0x0000, /* R16749 */ + 0x0000, /* R16750 */ + 0x0000, /* R16751 */ + 0x0000, /* R16752 */ + 0x0000, /* R16753 */ + 0x0000, /* R16754 */ + 0x0000, /* R16755 */ + 0x0000, /* R16756 */ + 0x0000, /* R16757 */ + 0x0000, /* R16758 */ + 0x0000, /* R16759 */ + 0x0000, /* R16760 */ + 0x0000, /* R16761 */ + 0x0000, /* R16762 */ + 0x0000, /* R16763 */ + 0x0000, /* R16764 */ + 0x0000, /* R16765 */ + 0x0000, /* R16766 */ + 0x0000, /* R16767 */ + 0x0000, /* R16768 */ + 0x0000, /* R16769 */ + 0x0000, /* R16770 */ + 0x0000, /* R16771 */ + 0x0000, /* R16772 */ + 0x0000, /* R16773 */ + 0x0000, /* R16774 */ + 0x0000, /* R16775 */ + 0x0000, /* R16776 */ + 0x0000, /* R16777 */ + 0x0000, /* R16778 */ + 0x0000, /* R16779 */ + 0x0000, /* R16780 */ + 0x0000, /* R16781 */ + 0x0000, /* R16782 */ + 0x0000, /* R16783 */ + 0x0000, /* R16784 */ + 0x0000, /* R16785 */ + 0x0000, /* R16786 */ + 0x0000, /* R16787 */ + 0x0000, /* R16788 */ + 0x0000, /* R16789 */ + 0x0000, /* R16790 */ + 0x0000, /* R16791 */ + 0x0000, /* R16792 */ + 0x0000, /* R16793 */ + 0x0000, /* R16794 */ + 0x0000, /* R16795 */ + 0x0000, /* R16796 */ + 0x0000, /* R16797 */ + 0x0000, /* R16798 */ + 0x0000, /* R16799 */ + 0x0000, /* R16800 */ + 0x0000, /* R16801 */ + 0x0000, /* R16802 */ + 0x0000, /* R16803 */ + 0x0000, /* R16804 */ + 0x0000, /* R16805 */ + 0x0000, /* R16806 */ + 0x0000, /* R16807 */ + 0x0000, /* R16808 */ + 0x0000, /* R16809 */ + 0x0000, /* R16810 */ + 0x0000, /* R16811 */ + 0x0000, /* R16812 */ + 0x0000, /* R16813 */ + 0x0000, /* R16814 */ + 0x0000, /* R16815 */ + 0x0000, /* R16816 */ + 0x0000, /* R16817 */ + 0x0000, /* R16818 */ + 0x0000, /* R16819 */ + 0x0000, /* R16820 */ + 0x0000, /* R16821 */ + 0x0000, /* R16822 */ + 0x0000, /* R16823 */ + 0x0000, /* R16824 */ + 0x0000, /* R16825 */ + 0x0000, /* R16826 */ + 0x0000, /* R16827 */ + 0x0000, /* R16828 */ + 0x0000, /* R16829 */ + 0x0000, /* R16830 */ + 0x0000, /* R16831 */ + 0x0000, /* R16832 */ + 0x0000, /* R16833 */ + 0x0000, /* R16834 */ + 0x0000, /* R16835 */ + 0x0000, /* R16836 */ + 0x0000, /* R16837 */ + 0x0000, /* R16838 */ + 0x0000, /* R16839 */ + 0x0000, /* R16840 */ + 0x0000, /* R16841 */ + 0x0000, /* R16842 */ + 0x0000, /* R16843 */ + 0x0000, /* R16844 */ + 0x0000, /* R16845 */ + 0x0000, /* R16846 */ + 0x0000, /* R16847 */ + 0x0000, /* R16848 */ + 0x0000, /* R16849 */ + 0x0000, /* R16850 */ + 0x0000, /* R16851 */ + 0x0000, /* R16852 */ + 0x0000, /* R16853 */ + 0x0000, /* R16854 */ + 0x0000, /* R16855 */ + 0x0000, /* R16856 */ + 0x0000, /* R16857 */ + 0x0000, /* R16858 */ + 0x0000, /* R16859 */ + 0x0000, /* R16860 */ + 0x0000, /* R16861 */ + 0x0000, /* R16862 */ + 0x0000, /* R16863 */ + 0x0000, /* R16864 */ + 0x0000, /* R16865 */ + 0x0000, /* R16866 */ + 0x0000, /* R16867 */ + 0x0000, /* R16868 */ + 0x0000, /* R16869 */ + 0x0000, /* R16870 */ + 0x0000, /* R16871 */ + 0x0000, /* R16872 */ + 0x0000, /* R16873 */ + 0x0000, /* R16874 */ + 0x0000, /* R16875 */ + 0x0000, /* R16876 */ + 0x0000, /* R16877 */ + 0x0000, /* R16878 */ + 0x0000, /* R16879 */ + 0x0000, /* R16880 */ + 0x0000, /* R16881 */ + 0x0000, /* R16882 */ + 0x0000, /* R16883 */ + 0x0000, /* R16884 */ + 0x0000, /* R16885 */ + 0x0000, /* R16886 */ + 0x0000, /* R16887 */ + 0x0000, /* R16888 */ + 0x0000, /* R16889 */ + 0x0000, /* R16890 */ + 0x0000, /* R16891 */ + 0x0000, /* R16892 */ + 0x0000, /* R16893 */ + 0x0000, /* R16894 */ + 0x0000, /* R16895 */ + 0x0002, /* R16896 - HDBASS_AI_1 */ + 0xBD12, /* R16897 - HDBASS_AI_0 */ + 0x007C, /* R16898 - HDBASS_AR_1 */ + 0x586C, /* R16899 - HDBASS_AR_0 */ + 0x0053, /* R16900 - HDBASS_B_1 */ + 0x8121, /* R16901 - HDBASS_B_0 */ + 0x003F, /* R16902 - HDBASS_K_1 */ + 0x8BD8, /* R16903 - HDBASS_K_0 */ + 0x0032, /* R16904 - HDBASS_N1_1 */ + 0xF52D, /* R16905 - HDBASS_N1_0 */ + 0x0065, /* R16906 - HDBASS_N2_1 */ + 0xAC8C, /* R16907 - HDBASS_N2_0 */ + 0x006B, /* R16908 - HDBASS_N3_1 */ + 0xE087, /* R16909 - HDBASS_N3_0 */ + 0x0072, /* R16910 - HDBASS_N4_1 */ + 0x1483, /* R16911 - HDBASS_N4_0 */ + 0x0072, /* R16912 - HDBASS_N5_1 */ + 0x1483, /* R16913 - HDBASS_N5_0 */ + 0x0043, /* R16914 - HDBASS_X1_1 */ + 0x3525, /* R16915 - HDBASS_X1_0 */ + 0x0006, /* R16916 - HDBASS_X2_1 */ + 0x6A4A, /* R16917 - HDBASS_X2_0 */ + 0x0043, /* R16918 - HDBASS_X3_1 */ + 0x6079, /* R16919 - HDBASS_X3_0 */ + 0x0008, /* R16920 - HDBASS_ATK_1 */ + 0x0000, /* R16921 - HDBASS_ATK_0 */ + 0x0001, /* R16922 - HDBASS_DCY_1 */ + 0x0000, /* R16923 - HDBASS_DCY_0 */ + 0x0059, /* R16924 - HDBASS_PG_1 */ + 0x999A, /* R16925 - HDBASS_PG_0 */ + 0x0000, /* R16926 */ + 0x0000, /* R16927 */ + 0x0000, /* R16928 */ + 0x0000, /* R16929 */ + 0x0000, /* R16930 */ + 0x0000, /* R16931 */ + 0x0000, /* R16932 */ + 0x0000, /* R16933 */ + 0x0000, /* R16934 */ + 0x0000, /* R16935 */ + 0x0000, /* R16936 */ + 0x0000, /* R16937 */ + 0x0000, /* R16938 */ + 0x0000, /* R16939 */ + 0x0000, /* R16940 */ + 0x0000, /* R16941 */ + 0x0000, /* R16942 */ + 0x0000, /* R16943 */ + 0x0000, /* R16944 */ + 0x0000, /* R16945 */ + 0x0000, /* R16946 */ + 0x0000, /* R16947 */ + 0x0000, /* R16948 */ + 0x0000, /* R16949 */ + 0x0000, /* R16950 */ + 0x0000, /* R16951 */ + 0x0000, /* R16952 */ + 0x0000, /* R16953 */ + 0x0000, /* R16954 */ + 0x0000, /* R16955 */ + 0x0000, /* R16956 */ + 0x0000, /* R16957 */ + 0x0000, /* R16958 */ + 0x0000, /* R16959 */ + 0x0000, /* R16960 */ + 0x0000, /* R16961 */ + 0x0000, /* R16962 */ + 0x0000, /* R16963 */ + 0x0000, /* R16964 */ + 0x0000, /* R16965 */ + 0x0000, /* R16966 */ + 0x0000, /* R16967 */ + 0x0000, /* R16968 */ + 0x0000, /* R16969 */ + 0x0000, /* R16970 */ + 0x0000, /* R16971 */ + 0x0000, /* R16972 */ + 0x0000, /* R16973 */ + 0x0000, /* R16974 */ + 0x0000, /* R16975 */ + 0x0000, /* R16976 */ + 0x0000, /* R16977 */ + 0x0000, /* R16978 */ + 0x0000, /* R16979 */ + 0x0000, /* R16980 */ + 0x0000, /* R16981 */ + 0x0000, /* R16982 */ + 0x0000, /* R16983 */ + 0x0000, /* R16984 */ + 0x0000, /* R16985 */ + 0x0000, /* R16986 */ + 0x0000, /* R16987 */ + 0x0000, /* R16988 */ + 0x0000, /* R16989 */ + 0x0000, /* R16990 */ + 0x0000, /* R16991 */ + 0x0000, /* R16992 */ + 0x0000, /* R16993 */ + 0x0000, /* R16994 */ + 0x0000, /* R16995 */ + 0x0000, /* R16996 */ + 0x0000, /* R16997 */ + 0x0000, /* R16998 */ + 0x0000, /* R16999 */ + 0x0000, /* R17000 */ + 0x0000, /* R17001 */ + 0x0000, /* R17002 */ + 0x0000, /* R17003 */ + 0x0000, /* R17004 */ + 0x0000, /* R17005 */ + 0x0000, /* R17006 */ + 0x0000, /* R17007 */ + 0x0000, /* R17008 */ + 0x0000, /* R17009 */ + 0x0000, /* R17010 */ + 0x0000, /* R17011 */ + 0x0000, /* R17012 */ + 0x0000, /* R17013 */ + 0x0000, /* R17014 */ + 0x0000, /* R17015 */ + 0x0000, /* R17016 */ + 0x0000, /* R17017 */ + 0x0000, /* R17018 */ + 0x0000, /* R17019 */ + 0x0000, /* R17020 */ + 0x0000, /* R17021 */ + 0x0000, /* R17022 */ + 0x0000, /* R17023 */ + 0x0000, /* R17024 */ + 0x0000, /* R17025 */ + 0x0000, /* R17026 */ + 0x0000, /* R17027 */ + 0x0000, /* R17028 */ + 0x0000, /* R17029 */ + 0x0000, /* R17030 */ + 0x0000, /* R17031 */ + 0x0000, /* R17032 */ + 0x0000, /* R17033 */ + 0x0000, /* R17034 */ + 0x0000, /* R17035 */ + 0x0000, /* R17036 */ + 0x0000, /* R17037 */ + 0x0000, /* R17038 */ + 0x0000, /* R17039 */ + 0x0000, /* R17040 */ + 0x0000, /* R17041 */ + 0x0000, /* R17042 */ + 0x0000, /* R17043 */ + 0x0000, /* R17044 */ + 0x0000, /* R17045 */ + 0x0000, /* R17046 */ + 0x0000, /* R17047 */ + 0x0000, /* R17048 */ + 0x0000, /* R17049 */ + 0x0000, /* R17050 */ + 0x0000, /* R17051 */ + 0x0000, /* R17052 */ + 0x0000, /* R17053 */ + 0x0000, /* R17054 */ + 0x0000, /* R17055 */ + 0x0000, /* R17056 */ + 0x0000, /* R17057 */ + 0x0000, /* R17058 */ + 0x0000, /* R17059 */ + 0x0000, /* R17060 */ + 0x0000, /* R17061 */ + 0x0000, /* R17062 */ + 0x0000, /* R17063 */ + 0x0000, /* R17064 */ + 0x0000, /* R17065 */ + 0x0000, /* R17066 */ + 0x0000, /* R17067 */ + 0x0000, /* R17068 */ + 0x0000, /* R17069 */ + 0x0000, /* R17070 */ + 0x0000, /* R17071 */ + 0x0000, /* R17072 */ + 0x0000, /* R17073 */ + 0x0000, /* R17074 */ + 0x0000, /* R17075 */ + 0x0000, /* R17076 */ + 0x0000, /* R17077 */ + 0x0000, /* R17078 */ + 0x0000, /* R17079 */ + 0x0000, /* R17080 */ + 0x0000, /* R17081 */ + 0x0000, /* R17082 */ + 0x0000, /* R17083 */ + 0x0000, /* R17084 */ + 0x0000, /* R17085 */ + 0x0000, /* R17086 */ + 0x0000, /* R17087 */ + 0x0000, /* R17088 */ + 0x0000, /* R17089 */ + 0x0000, /* R17090 */ + 0x0000, /* R17091 */ + 0x0000, /* R17092 */ + 0x0000, /* R17093 */ + 0x0000, /* R17094 */ + 0x0000, /* R17095 */ + 0x0000, /* R17096 */ + 0x0000, /* R17097 */ + 0x0000, /* R17098 */ + 0x0000, /* R17099 */ + 0x0000, /* R17100 */ + 0x0000, /* R17101 */ + 0x0000, /* R17102 */ + 0x0000, /* R17103 */ + 0x0000, /* R17104 */ + 0x0000, /* R17105 */ + 0x0000, /* R17106 */ + 0x0000, /* R17107 */ + 0x0000, /* R17108 */ + 0x0000, /* R17109 */ + 0x0000, /* R17110 */ + 0x0000, /* R17111 */ + 0x0000, /* R17112 */ + 0x0000, /* R17113 */ + 0x0000, /* R17114 */ + 0x0000, /* R17115 */ + 0x0000, /* R17116 */ + 0x0000, /* R17117 */ + 0x0000, /* R17118 */ + 0x0000, /* R17119 */ + 0x0000, /* R17120 */ + 0x0000, /* R17121 */ + 0x0000, /* R17122 */ + 0x0000, /* R17123 */ + 0x0000, /* R17124 */ + 0x0000, /* R17125 */ + 0x0000, /* R17126 */ + 0x0000, /* R17127 */ + 0x0000, /* R17128 */ + 0x0000, /* R17129 */ + 0x0000, /* R17130 */ + 0x0000, /* R17131 */ + 0x0000, /* R17132 */ + 0x0000, /* R17133 */ + 0x0000, /* R17134 */ + 0x0000, /* R17135 */ + 0x0000, /* R17136 */ + 0x0000, /* R17137 */ + 0x0000, /* R17138 */ + 0x0000, /* R17139 */ + 0x0000, /* R17140 */ + 0x0000, /* R17141 */ + 0x0000, /* R17142 */ + 0x0000, /* R17143 */ + 0x0000, /* R17144 */ + 0x0000, /* R17145 */ + 0x0000, /* R17146 */ + 0x0000, /* R17147 */ + 0x0000, /* R17148 */ + 0x0000, /* R17149 */ + 0x0000, /* R17150 */ + 0x0000, /* R17151 */ + 0x0000, /* R17152 */ + 0x0000, /* R17153 */ + 0x0000, /* R17154 */ + 0x0000, /* R17155 */ + 0x0000, /* R17156 */ + 0x0000, /* R17157 */ + 0x0000, /* R17158 */ + 0x0000, /* R17159 */ + 0x0000, /* R17160 */ + 0x0000, /* R17161 */ + 0x0000, /* R17162 */ + 0x0000, /* R17163 */ + 0x0000, /* R17164 */ + 0x0000, /* R17165 */ + 0x0000, /* R17166 */ + 0x0000, /* R17167 */ + 0x0000, /* R17168 */ + 0x0000, /* R17169 */ + 0x0000, /* R17170 */ + 0x0000, /* R17171 */ + 0x0000, /* R17172 */ + 0x0000, /* R17173 */ + 0x0000, /* R17174 */ + 0x0000, /* R17175 */ + 0x0000, /* R17176 */ + 0x0000, /* R17177 */ + 0x0000, /* R17178 */ + 0x0000, /* R17179 */ + 0x0000, /* R17180 */ + 0x0000, /* R17181 */ + 0x0000, /* R17182 */ + 0x0000, /* R17183 */ + 0x0000, /* R17184 */ + 0x0000, /* R17185 */ + 0x0000, /* R17186 */ + 0x0000, /* R17187 */ + 0x0000, /* R17188 */ + 0x0000, /* R17189 */ + 0x0000, /* R17190 */ + 0x0000, /* R17191 */ + 0x0000, /* R17192 */ + 0x0000, /* R17193 */ + 0x0000, /* R17194 */ + 0x0000, /* R17195 */ + 0x0000, /* R17196 */ + 0x0000, /* R17197 */ + 0x0000, /* R17198 */ + 0x0000, /* R17199 */ + 0x0000, /* R17200 */ + 0x0000, /* R17201 */ + 0x0000, /* R17202 */ + 0x0000, /* R17203 */ + 0x0000, /* R17204 */ + 0x0000, /* R17205 */ + 0x0000, /* R17206 */ + 0x0000, /* R17207 */ + 0x0000, /* R17208 */ + 0x0000, /* R17209 */ + 0x0000, /* R17210 */ + 0x0000, /* R17211 */ + 0x0000, /* R17212 */ + 0x0000, /* R17213 */ + 0x0000, /* R17214 */ + 0x0000, /* R17215 */ + 0x0000, /* R17216 */ + 0x0000, /* R17217 */ + 0x0000, /* R17218 */ + 0x0000, /* R17219 */ + 0x0000, /* R17220 */ + 0x0000, /* R17221 */ + 0x0000, /* R17222 */ + 0x0000, /* R17223 */ + 0x0000, /* R17224 */ + 0x0000, /* R17225 */ + 0x0000, /* R17226 */ + 0x0000, /* R17227 */ + 0x0000, /* R17228 */ + 0x0000, /* R17229 */ + 0x0000, /* R17230 */ + 0x0000, /* R17231 */ + 0x0000, /* R17232 */ + 0x0000, /* R17233 */ + 0x0000, /* R17234 */ + 0x0000, /* R17235 */ + 0x0000, /* R17236 */ + 0x0000, /* R17237 */ + 0x0000, /* R17238 */ + 0x0000, /* R17239 */ + 0x0000, /* R17240 */ + 0x0000, /* R17241 */ + 0x0000, /* R17242 */ + 0x0000, /* R17243 */ + 0x0000, /* R17244 */ + 0x0000, /* R17245 */ + 0x0000, /* R17246 */ + 0x0000, /* R17247 */ + 0x0000, /* R17248 */ + 0x0000, /* R17249 */ + 0x0000, /* R17250 */ + 0x0000, /* R17251 */ + 0x0000, /* R17252 */ + 0x0000, /* R17253 */ + 0x0000, /* R17254 */ + 0x0000, /* R17255 */ + 0x0000, /* R17256 */ + 0x0000, /* R17257 */ + 0x0000, /* R17258 */ + 0x0000, /* R17259 */ + 0x0000, /* R17260 */ + 0x0000, /* R17261 */ + 0x0000, /* R17262 */ + 0x0000, /* R17263 */ + 0x0000, /* R17264 */ + 0x0000, /* R17265 */ + 0x0000, /* R17266 */ + 0x0000, /* R17267 */ + 0x0000, /* R17268 */ + 0x0000, /* R17269 */ + 0x0000, /* R17270 */ + 0x0000, /* R17271 */ + 0x0000, /* R17272 */ + 0x0000, /* R17273 */ + 0x0000, /* R17274 */ + 0x0000, /* R17275 */ + 0x0000, /* R17276 */ + 0x0000, /* R17277 */ + 0x0000, /* R17278 */ + 0x0000, /* R17279 */ + 0x0000, /* R17280 */ + 0x0000, /* R17281 */ + 0x0000, /* R17282 */ + 0x0000, /* R17283 */ + 0x0000, /* R17284 */ + 0x0000, /* R17285 */ + 0x0000, /* R17286 */ + 0x0000, /* R17287 */ + 0x0000, /* R17288 */ + 0x0000, /* R17289 */ + 0x0000, /* R17290 */ + 0x0000, /* R17291 */ + 0x0000, /* R17292 */ + 0x0000, /* R17293 */ + 0x0000, /* R17294 */ + 0x0000, /* R17295 */ + 0x0000, /* R17296 */ + 0x0000, /* R17297 */ + 0x0000, /* R17298 */ + 0x0000, /* R17299 */ + 0x0000, /* R17300 */ + 0x0000, /* R17301 */ + 0x0000, /* R17302 */ + 0x0000, /* R17303 */ + 0x0000, /* R17304 */ + 0x0000, /* R17305 */ + 0x0000, /* R17306 */ + 0x0000, /* R17307 */ + 0x0000, /* R17308 */ + 0x0000, /* R17309 */ + 0x0000, /* R17310 */ + 0x0000, /* R17311 */ + 0x0000, /* R17312 */ + 0x0000, /* R17313 */ + 0x0000, /* R17314 */ + 0x0000, /* R17315 */ + 0x0000, /* R17316 */ + 0x0000, /* R17317 */ + 0x0000, /* R17318 */ + 0x0000, /* R17319 */ + 0x0000, /* R17320 */ + 0x0000, /* R17321 */ + 0x0000, /* R17322 */ + 0x0000, /* R17323 */ + 0x0000, /* R17324 */ + 0x0000, /* R17325 */ + 0x0000, /* R17326 */ + 0x0000, /* R17327 */ + 0x0000, /* R17328 */ + 0x0000, /* R17329 */ + 0x0000, /* R17330 */ + 0x0000, /* R17331 */ + 0x0000, /* R17332 */ + 0x0000, /* R17333 */ + 0x0000, /* R17334 */ + 0x0000, /* R17335 */ + 0x0000, /* R17336 */ + 0x0000, /* R17337 */ + 0x0000, /* R17338 */ + 0x0000, /* R17339 */ + 0x0000, /* R17340 */ + 0x0000, /* R17341 */ + 0x0000, /* R17342 */ + 0x0000, /* R17343 */ + 0x0000, /* R17344 */ + 0x0000, /* R17345 */ + 0x0000, /* R17346 */ + 0x0000, /* R17347 */ + 0x0000, /* R17348 */ + 0x0000, /* R17349 */ + 0x0000, /* R17350 */ + 0x0000, /* R17351 */ + 0x0000, /* R17352 */ + 0x0000, /* R17353 */ + 0x0000, /* R17354 */ + 0x0000, /* R17355 */ + 0x0000, /* R17356 */ + 0x0000, /* R17357 */ + 0x0000, /* R17358 */ + 0x0000, /* R17359 */ + 0x0000, /* R17360 */ + 0x0000, /* R17361 */ + 0x0000, /* R17362 */ + 0x0000, /* R17363 */ + 0x0000, /* R17364 */ + 0x0000, /* R17365 */ + 0x0000, /* R17366 */ + 0x0000, /* R17367 */ + 0x0000, /* R17368 */ + 0x0000, /* R17369 */ + 0x0000, /* R17370 */ + 0x0000, /* R17371 */ + 0x0000, /* R17372 */ + 0x0000, /* R17373 */ + 0x0000, /* R17374 */ + 0x0000, /* R17375 */ + 0x0000, /* R17376 */ + 0x0000, /* R17377 */ + 0x0000, /* R17378 */ + 0x0000, /* R17379 */ + 0x0000, /* R17380 */ + 0x0000, /* R17381 */ + 0x0000, /* R17382 */ + 0x0000, /* R17383 */ + 0x0000, /* R17384 */ + 0x0000, /* R17385 */ + 0x0000, /* R17386 */ + 0x0000, /* R17387 */ + 0x0000, /* R17388 */ + 0x0000, /* R17389 */ + 0x0000, /* R17390 */ + 0x0000, /* R17391 */ + 0x0000, /* R17392 */ + 0x0000, /* R17393 */ + 0x0000, /* R17394 */ + 0x0000, /* R17395 */ + 0x0000, /* R17396 */ + 0x0000, /* R17397 */ + 0x0000, /* R17398 */ + 0x0000, /* R17399 */ + 0x0000, /* R17400 */ + 0x0000, /* R17401 */ + 0x0000, /* R17402 */ + 0x0000, /* R17403 */ + 0x0000, /* R17404 */ + 0x0000, /* R17405 */ + 0x0000, /* R17406 */ + 0x0000, /* R17407 */ + 0x0083, /* R17408 - HPF_C_1 */ + 0x98AD, /* R17409 - HPF_C_0 */ + 0x0000, /* R17410 */ + 0x0000, /* R17411 */ + 0x0000, /* R17412 */ + 0x0000, /* R17413 */ + 0x0000, /* R17414 */ + 0x0000, /* R17415 */ + 0x0000, /* R17416 */ + 0x0000, /* R17417 */ + 0x0000, /* R17418 */ + 0x0000, /* R17419 */ + 0x0000, /* R17420 */ + 0x0000, /* R17421 */ + 0x0000, /* R17422 */ + 0x0000, /* R17423 */ + 0x0000, /* R17424 */ + 0x0000, /* R17425 */ + 0x0000, /* R17426 */ + 0x0000, /* R17427 */ + 0x0000, /* R17428 */ + 0x0000, /* R17429 */ + 0x0000, /* R17430 */ + 0x0000, /* R17431 */ + 0x0000, /* R17432 */ + 0x0000, /* R17433 */ + 0x0000, /* R17434 */ + 0x0000, /* R17435 */ + 0x0000, /* R17436 */ + 0x0000, /* R17437 */ + 0x0000, /* R17438 */ + 0x0000, /* R17439 */ + 0x0000, /* R17440 */ + 0x0000, /* R17441 */ + 0x0000, /* R17442 */ + 0x0000, /* R17443 */ + 0x0000, /* R17444 */ + 0x0000, /* R17445 */ + 0x0000, /* R17446 */ + 0x0000, /* R17447 */ + 0x0000, /* R17448 */ + 0x0000, /* R17449 */ + 0x0000, /* R17450 */ + 0x0000, /* R17451 */ + 0x0000, /* R17452 */ + 0x0000, /* R17453 */ + 0x0000, /* R17454 */ + 0x0000, /* R17455 */ + 0x0000, /* R17456 */ + 0x0000, /* R17457 */ + 0x0000, /* R17458 */ + 0x0000, /* R17459 */ + 0x0000, /* R17460 */ + 0x0000, /* R17461 */ + 0x0000, /* R17462 */ + 0x0000, /* R17463 */ + 0x0000, /* R17464 */ + 0x0000, /* R17465 */ + 0x0000, /* R17466 */ + 0x0000, /* R17467 */ + 0x0000, /* R17468 */ + 0x0000, /* R17469 */ + 0x0000, /* R17470 */ + 0x0000, /* R17471 */ + 0x0000, /* R17472 */ + 0x0000, /* R17473 */ + 0x0000, /* R17474 */ + 0x0000, /* R17475 */ + 0x0000, /* R17476 */ + 0x0000, /* R17477 */ + 0x0000, /* R17478 */ + 0x0000, /* R17479 */ + 0x0000, /* R17480 */ + 0x0000, /* R17481 */ + 0x0000, /* R17482 */ + 0x0000, /* R17483 */ + 0x0000, /* R17484 */ + 0x0000, /* R17485 */ + 0x0000, /* R17486 */ + 0x0000, /* R17487 */ + 0x0000, /* R17488 */ + 0x0000, /* R17489 */ + 0x0000, /* R17490 */ + 0x0000, /* R17491 */ + 0x0000, /* R17492 */ + 0x0000, /* R17493 */ + 0x0000, /* R17494 */ + 0x0000, /* R17495 */ + 0x0000, /* R17496 */ + 0x0000, /* R17497 */ + 0x0000, /* R17498 */ + 0x0000, /* R17499 */ + 0x0000, /* R17500 */ + 0x0000, /* R17501 */ + 0x0000, /* R17502 */ + 0x0000, /* R17503 */ + 0x0000, /* R17504 */ + 0x0000, /* R17505 */ + 0x0000, /* R17506 */ + 0x0000, /* R17507 */ + 0x0000, /* R17508 */ + 0x0000, /* R17509 */ + 0x0000, /* R17510 */ + 0x0000, /* R17511 */ + 0x0000, /* R17512 */ + 0x0000, /* R17513 */ + 0x0000, /* R17514 */ + 0x0000, /* R17515 */ + 0x0000, /* R17516 */ + 0x0000, /* R17517 */ + 0x0000, /* R17518 */ + 0x0000, /* R17519 */ + 0x0000, /* R17520 */ + 0x0000, /* R17521 */ + 0x0000, /* R17522 */ + 0x0000, /* R17523 */ + 0x0000, /* R17524 */ + 0x0000, /* R17525 */ + 0x0000, /* R17526 */ + 0x0000, /* R17527 */ + 0x0000, /* R17528 */ + 0x0000, /* R17529 */ + 0x0000, /* R17530 */ + 0x0000, /* R17531 */ + 0x0000, /* R17532 */ + 0x0000, /* R17533 */ + 0x0000, /* R17534 */ + 0x0000, /* R17535 */ + 0x0000, /* R17536 */ + 0x0000, /* R17537 */ + 0x0000, /* R17538 */ + 0x0000, /* R17539 */ + 0x0000, /* R17540 */ + 0x0000, /* R17541 */ + 0x0000, /* R17542 */ + 0x0000, /* R17543 */ + 0x0000, /* R17544 */ + 0x0000, /* R17545 */ + 0x0000, /* R17546 */ + 0x0000, /* R17547 */ + 0x0000, /* R17548 */ + 0x0000, /* R17549 */ + 0x0000, /* R17550 */ + 0x0000, /* R17551 */ + 0x0000, /* R17552 */ + 0x0000, /* R17553 */ + 0x0000, /* R17554 */ + 0x0000, /* R17555 */ + 0x0000, /* R17556 */ + 0x0000, /* R17557 */ + 0x0000, /* R17558 */ + 0x0000, /* R17559 */ + 0x0000, /* R17560 */ + 0x0000, /* R17561 */ + 0x0000, /* R17562 */ + 0x0000, /* R17563 */ + 0x0000, /* R17564 */ + 0x0000, /* R17565 */ + 0x0000, /* R17566 */ + 0x0000, /* R17567 */ + 0x0000, /* R17568 */ + 0x0000, /* R17569 */ + 0x0000, /* R17570 */ + 0x0000, /* R17571 */ + 0x0000, /* R17572 */ + 0x0000, /* R17573 */ + 0x0000, /* R17574 */ + 0x0000, /* R17575 */ + 0x0000, /* R17576 */ + 0x0000, /* R17577 */ + 0x0000, /* R17578 */ + 0x0000, /* R17579 */ + 0x0000, /* R17580 */ + 0x0000, /* R17581 */ + 0x0000, /* R17582 */ + 0x0000, /* R17583 */ + 0x0000, /* R17584 */ + 0x0000, /* R17585 */ + 0x0000, /* R17586 */ + 0x0000, /* R17587 */ + 0x0000, /* R17588 */ + 0x0000, /* R17589 */ + 0x0000, /* R17590 */ + 0x0000, /* R17591 */ + 0x0000, /* R17592 */ + 0x0000, /* R17593 */ + 0x0000, /* R17594 */ + 0x0000, /* R17595 */ + 0x0000, /* R17596 */ + 0x0000, /* R17597 */ + 0x0000, /* R17598 */ + 0x0000, /* R17599 */ + 0x0000, /* R17600 */ + 0x0000, /* R17601 */ + 0x0000, /* R17602 */ + 0x0000, /* R17603 */ + 0x0000, /* R17604 */ + 0x0000, /* R17605 */ + 0x0000, /* R17606 */ + 0x0000, /* R17607 */ + 0x0000, /* R17608 */ + 0x0000, /* R17609 */ + 0x0000, /* R17610 */ + 0x0000, /* R17611 */ + 0x0000, /* R17612 */ + 0x0000, /* R17613 */ + 0x0000, /* R17614 */ + 0x0000, /* R17615 */ + 0x0000, /* R17616 */ + 0x0000, /* R17617 */ + 0x0000, /* R17618 */ + 0x0000, /* R17619 */ + 0x0000, /* R17620 */ + 0x0000, /* R17621 */ + 0x0000, /* R17622 */ + 0x0000, /* R17623 */ + 0x0000, /* R17624 */ + 0x0000, /* R17625 */ + 0x0000, /* R17626 */ + 0x0000, /* R17627 */ + 0x0000, /* R17628 */ + 0x0000, /* R17629 */ + 0x0000, /* R17630 */ + 0x0000, /* R17631 */ + 0x0000, /* R17632 */ + 0x0000, /* R17633 */ + 0x0000, /* R17634 */ + 0x0000, /* R17635 */ + 0x0000, /* R17636 */ + 0x0000, /* R17637 */ + 0x0000, /* R17638 */ + 0x0000, /* R17639 */ + 0x0000, /* R17640 */ + 0x0000, /* R17641 */ + 0x0000, /* R17642 */ + 0x0000, /* R17643 */ + 0x0000, /* R17644 */ + 0x0000, /* R17645 */ + 0x0000, /* R17646 */ + 0x0000, /* R17647 */ + 0x0000, /* R17648 */ + 0x0000, /* R17649 */ + 0x0000, /* R17650 */ + 0x0000, /* R17651 */ + 0x0000, /* R17652 */ + 0x0000, /* R17653 */ + 0x0000, /* R17654 */ + 0x0000, /* R17655 */ + 0x0000, /* R17656 */ + 0x0000, /* R17657 */ + 0x0000, /* R17658 */ + 0x0000, /* R17659 */ + 0x0000, /* R17660 */ + 0x0000, /* R17661 */ + 0x0000, /* R17662 */ + 0x0000, /* R17663 */ + 0x0000, /* R17664 */ + 0x0000, /* R17665 */ + 0x0000, /* R17666 */ + 0x0000, /* R17667 */ + 0x0000, /* R17668 */ + 0x0000, /* R17669 */ + 0x0000, /* R17670 */ + 0x0000, /* R17671 */ + 0x0000, /* R17672 */ + 0x0000, /* R17673 */ + 0x0000, /* R17674 */ + 0x0000, /* R17675 */ + 0x0000, /* R17676 */ + 0x0000, /* R17677 */ + 0x0000, /* R17678 */ + 0x0000, /* R17679 */ + 0x0000, /* R17680 */ + 0x0000, /* R17681 */ + 0x0000, /* R17682 */ + 0x0000, /* R17683 */ + 0x0000, /* R17684 */ + 0x0000, /* R17685 */ + 0x0000, /* R17686 */ + 0x0000, /* R17687 */ + 0x0000, /* R17688 */ + 0x0000, /* R17689 */ + 0x0000, /* R17690 */ + 0x0000, /* R17691 */ + 0x0000, /* R17692 */ + 0x0000, /* R17693 */ + 0x0000, /* R17694 */ + 0x0000, /* R17695 */ + 0x0000, /* R17696 */ + 0x0000, /* R17697 */ + 0x0000, /* R17698 */ + 0x0000, /* R17699 */ + 0x0000, /* R17700 */ + 0x0000, /* R17701 */ + 0x0000, /* R17702 */ + 0x0000, /* R17703 */ + 0x0000, /* R17704 */ + 0x0000, /* R17705 */ + 0x0000, /* R17706 */ + 0x0000, /* R17707 */ + 0x0000, /* R17708 */ + 0x0000, /* R17709 */ + 0x0000, /* R17710 */ + 0x0000, /* R17711 */ + 0x0000, /* R17712 */ + 0x0000, /* R17713 */ + 0x0000, /* R17714 */ + 0x0000, /* R17715 */ + 0x0000, /* R17716 */ + 0x0000, /* R17717 */ + 0x0000, /* R17718 */ + 0x0000, /* R17719 */ + 0x0000, /* R17720 */ + 0x0000, /* R17721 */ + 0x0000, /* R17722 */ + 0x0000, /* R17723 */ + 0x0000, /* R17724 */ + 0x0000, /* R17725 */ + 0x0000, /* R17726 */ + 0x0000, /* R17727 */ + 0x0000, /* R17728 */ + 0x0000, /* R17729 */ + 0x0000, /* R17730 */ + 0x0000, /* R17731 */ + 0x0000, /* R17732 */ + 0x0000, /* R17733 */ + 0x0000, /* R17734 */ + 0x0000, /* R17735 */ + 0x0000, /* R17736 */ + 0x0000, /* R17737 */ + 0x0000, /* R17738 */ + 0x0000, /* R17739 */ + 0x0000, /* R17740 */ + 0x0000, /* R17741 */ + 0x0000, /* R17742 */ + 0x0000, /* R17743 */ + 0x0000, /* R17744 */ + 0x0000, /* R17745 */ + 0x0000, /* R17746 */ + 0x0000, /* R17747 */ + 0x0000, /* R17748 */ + 0x0000, /* R17749 */ + 0x0000, /* R17750 */ + 0x0000, /* R17751 */ + 0x0000, /* R17752 */ + 0x0000, /* R17753 */ + 0x0000, /* R17754 */ + 0x0000, /* R17755 */ + 0x0000, /* R17756 */ + 0x0000, /* R17757 */ + 0x0000, /* R17758 */ + 0x0000, /* R17759 */ + 0x0000, /* R17760 */ + 0x0000, /* R17761 */ + 0x0000, /* R17762 */ + 0x0000, /* R17763 */ + 0x0000, /* R17764 */ + 0x0000, /* R17765 */ + 0x0000, /* R17766 */ + 0x0000, /* R17767 */ + 0x0000, /* R17768 */ + 0x0000, /* R17769 */ + 0x0000, /* R17770 */ + 0x0000, /* R17771 */ + 0x0000, /* R17772 */ + 0x0000, /* R17773 */ + 0x0000, /* R17774 */ + 0x0000, /* R17775 */ + 0x0000, /* R17776 */ + 0x0000, /* R17777 */ + 0x0000, /* R17778 */ + 0x0000, /* R17779 */ + 0x0000, /* R17780 */ + 0x0000, /* R17781 */ + 0x0000, /* R17782 */ + 0x0000, /* R17783 */ + 0x0000, /* R17784 */ + 0x0000, /* R17785 */ + 0x0000, /* R17786 */ + 0x0000, /* R17787 */ + 0x0000, /* R17788 */ + 0x0000, /* R17789 */ + 0x0000, /* R17790 */ + 0x0000, /* R17791 */ + 0x0000, /* R17792 */ + 0x0000, /* R17793 */ + 0x0000, /* R17794 */ + 0x0000, /* R17795 */ + 0x0000, /* R17796 */ + 0x0000, /* R17797 */ + 0x0000, /* R17798 */ + 0x0000, /* R17799 */ + 0x0000, /* R17800 */ + 0x0000, /* R17801 */ + 0x0000, /* R17802 */ + 0x0000, /* R17803 */ + 0x0000, /* R17804 */ + 0x0000, /* R17805 */ + 0x0000, /* R17806 */ + 0x0000, /* R17807 */ + 0x0000, /* R17808 */ + 0x0000, /* R17809 */ + 0x0000, /* R17810 */ + 0x0000, /* R17811 */ + 0x0000, /* R17812 */ + 0x0000, /* R17813 */ + 0x0000, /* R17814 */ + 0x0000, /* R17815 */ + 0x0000, /* R17816 */ + 0x0000, /* R17817 */ + 0x0000, /* R17818 */ + 0x0000, /* R17819 */ + 0x0000, /* R17820 */ + 0x0000, /* R17821 */ + 0x0000, /* R17822 */ + 0x0000, /* R17823 */ + 0x0000, /* R17824 */ + 0x0000, /* R17825 */ + 0x0000, /* R17826 */ + 0x0000, /* R17827 */ + 0x0000, /* R17828 */ + 0x0000, /* R17829 */ + 0x0000, /* R17830 */ + 0x0000, /* R17831 */ + 0x0000, /* R17832 */ + 0x0000, /* R17833 */ + 0x0000, /* R17834 */ + 0x0000, /* R17835 */ + 0x0000, /* R17836 */ + 0x0000, /* R17837 */ + 0x0000, /* R17838 */ + 0x0000, /* R17839 */ + 0x0000, /* R17840 */ + 0x0000, /* R17841 */ + 0x0000, /* R17842 */ + 0x0000, /* R17843 */ + 0x0000, /* R17844 */ + 0x0000, /* R17845 */ + 0x0000, /* R17846 */ + 0x0000, /* R17847 */ + 0x0000, /* R17848 */ + 0x0000, /* R17849 */ + 0x0000, /* R17850 */ + 0x0000, /* R17851 */ + 0x0000, /* R17852 */ + 0x0000, /* R17853 */ + 0x0000, /* R17854 */ + 0x0000, /* R17855 */ + 0x0000, /* R17856 */ + 0x0000, /* R17857 */ + 0x0000, /* R17858 */ + 0x0000, /* R17859 */ + 0x0000, /* R17860 */ + 0x0000, /* R17861 */ + 0x0000, /* R17862 */ + 0x0000, /* R17863 */ + 0x0000, /* R17864 */ + 0x0000, /* R17865 */ + 0x0000, /* R17866 */ + 0x0000, /* R17867 */ + 0x0000, /* R17868 */ + 0x0000, /* R17869 */ + 0x0000, /* R17870 */ + 0x0000, /* R17871 */ + 0x0000, /* R17872 */ + 0x0000, /* R17873 */ + 0x0000, /* R17874 */ + 0x0000, /* R17875 */ + 0x0000, /* R17876 */ + 0x0000, /* R17877 */ + 0x0000, /* R17878 */ + 0x0000, /* R17879 */ + 0x0000, /* R17880 */ + 0x0000, /* R17881 */ + 0x0000, /* R17882 */ + 0x0000, /* R17883 */ + 0x0000, /* R17884 */ + 0x0000, /* R17885 */ + 0x0000, /* R17886 */ + 0x0000, /* R17887 */ + 0x0000, /* R17888 */ + 0x0000, /* R17889 */ + 0x0000, /* R17890 */ + 0x0000, /* R17891 */ + 0x0000, /* R17892 */ + 0x0000, /* R17893 */ + 0x0000, /* R17894 */ + 0x0000, /* R17895 */ + 0x0000, /* R17896 */ + 0x0000, /* R17897 */ + 0x0000, /* R17898 */ + 0x0000, /* R17899 */ + 0x0000, /* R17900 */ + 0x0000, /* R17901 */ + 0x0000, /* R17902 */ + 0x0000, /* R17903 */ + 0x0000, /* R17904 */ + 0x0000, /* R17905 */ + 0x0000, /* R17906 */ + 0x0000, /* R17907 */ + 0x0000, /* R17908 */ + 0x0000, /* R17909 */ + 0x0000, /* R17910 */ + 0x0000, /* R17911 */ + 0x0000, /* R17912 */ + 0x0000, /* R17913 */ + 0x0000, /* R17914 */ + 0x0000, /* R17915 */ + 0x0000, /* R17916 */ + 0x0000, /* R17917 */ + 0x0000, /* R17918 */ + 0x0000, /* R17919 */ + 0x007F, /* R17920 - ADCL_RETUNE_C1_1 */ + 0xFFFF, /* R17921 - ADCL_RETUNE_C1_0 */ + 0x0000, /* R17922 - ADCL_RETUNE_C2_1 */ + 0x0000, /* R17923 - ADCL_RETUNE_C2_0 */ + 0x0000, /* R17924 - ADCL_RETUNE_C3_1 */ + 0x0000, /* R17925 - ADCL_RETUNE_C3_0 */ + 0x0000, /* R17926 - ADCL_RETUNE_C4_1 */ + 0x0000, /* R17927 - ADCL_RETUNE_C4_0 */ + 0x0000, /* R17928 - ADCL_RETUNE_C5_1 */ + 0x0000, /* R17929 - ADCL_RETUNE_C5_0 */ + 0x0000, /* R17930 - ADCL_RETUNE_C6_1 */ + 0x0000, /* R17931 - ADCL_RETUNE_C6_0 */ + 0x0000, /* R17932 - ADCL_RETUNE_C7_1 */ + 0x0000, /* R17933 - ADCL_RETUNE_C7_0 */ + 0x0000, /* R17934 - ADCL_RETUNE_C8_1 */ + 0x0000, /* R17935 - ADCL_RETUNE_C8_0 */ + 0x0000, /* R17936 - ADCL_RETUNE_C9_1 */ + 0x0000, /* R17937 - ADCL_RETUNE_C9_0 */ + 0x0000, /* R17938 - ADCL_RETUNE_C10_1 */ + 0x0000, /* R17939 - ADCL_RETUNE_C10_0 */ + 0x0000, /* R17940 - ADCL_RETUNE_C11_1 */ + 0x0000, /* R17941 - ADCL_RETUNE_C11_0 */ + 0x0000, /* R17942 - ADCL_RETUNE_C12_1 */ + 0x0000, /* R17943 - ADCL_RETUNE_C12_0 */ + 0x0000, /* R17944 - ADCL_RETUNE_C13_1 */ + 0x0000, /* R17945 - ADCL_RETUNE_C13_0 */ + 0x0000, /* R17946 - ADCL_RETUNE_C14_1 */ + 0x0000, /* R17947 - ADCL_RETUNE_C14_0 */ + 0x0000, /* R17948 - ADCL_RETUNE_C15_1 */ + 0x0000, /* R17949 - ADCL_RETUNE_C15_0 */ + 0x0000, /* R17950 - ADCL_RETUNE_C16_1 */ + 0x0000, /* R17951 - ADCL_RETUNE_C16_0 */ + 0x0000, /* R17952 - ADCL_RETUNE_C17_1 */ + 0x0000, /* R17953 - ADCL_RETUNE_C17_0 */ + 0x0000, /* R17954 - ADCL_RETUNE_C18_1 */ + 0x0000, /* R17955 - ADCL_RETUNE_C18_0 */ + 0x0000, /* R17956 - ADCL_RETUNE_C19_1 */ + 0x0000, /* R17957 - ADCL_RETUNE_C19_0 */ + 0x0000, /* R17958 - ADCL_RETUNE_C20_1 */ + 0x0000, /* R17959 - ADCL_RETUNE_C20_0 */ + 0x0000, /* R17960 - ADCL_RETUNE_C21_1 */ + 0x0000, /* R17961 - ADCL_RETUNE_C21_0 */ + 0x0000, /* R17962 - ADCL_RETUNE_C22_1 */ + 0x0000, /* R17963 - ADCL_RETUNE_C22_0 */ + 0x0000, /* R17964 - ADCL_RETUNE_C23_1 */ + 0x0000, /* R17965 - ADCL_RETUNE_C23_0 */ + 0x0000, /* R17966 - ADCL_RETUNE_C24_1 */ + 0x0000, /* R17967 - ADCL_RETUNE_C24_0 */ + 0x0000, /* R17968 - ADCL_RETUNE_C25_1 */ + 0x0000, /* R17969 - ADCL_RETUNE_C25_0 */ + 0x0000, /* R17970 - ADCL_RETUNE_C26_1 */ + 0x0000, /* R17971 - ADCL_RETUNE_C26_0 */ + 0x0000, /* R17972 - ADCL_RETUNE_C27_1 */ + 0x0000, /* R17973 - ADCL_RETUNE_C27_0 */ + 0x0000, /* R17974 - ADCL_RETUNE_C28_1 */ + 0x0000, /* R17975 - ADCL_RETUNE_C28_0 */ + 0x0000, /* R17976 - ADCL_RETUNE_C29_1 */ + 0x0000, /* R17977 - ADCL_RETUNE_C29_0 */ + 0x0000, /* R17978 - ADCL_RETUNE_C30_1 */ + 0x0000, /* R17979 - ADCL_RETUNE_C30_0 */ + 0x0000, /* R17980 - ADCL_RETUNE_C31_1 */ + 0x0000, /* R17981 - ADCL_RETUNE_C31_0 */ + 0x0000, /* R17982 - ADCL_RETUNE_C32_1 */ + 0x0000, /* R17983 - ADCL_RETUNE_C32_0 */ + 0x0000, /* R17984 */ + 0x0000, /* R17985 */ + 0x0000, /* R17986 */ + 0x0000, /* R17987 */ + 0x0000, /* R17988 */ + 0x0000, /* R17989 */ + 0x0000, /* R17990 */ + 0x0000, /* R17991 */ + 0x0000, /* R17992 */ + 0x0000, /* R17993 */ + 0x0000, /* R17994 */ + 0x0000, /* R17995 */ + 0x0000, /* R17996 */ + 0x0000, /* R17997 */ + 0x0000, /* R17998 */ + 0x0000, /* R17999 */ + 0x0000, /* R18000 */ + 0x0000, /* R18001 */ + 0x0000, /* R18002 */ + 0x0000, /* R18003 */ + 0x0000, /* R18004 */ + 0x0000, /* R18005 */ + 0x0000, /* R18006 */ + 0x0000, /* R18007 */ + 0x0000, /* R18008 */ + 0x0000, /* R18009 */ + 0x0000, /* R18010 */ + 0x0000, /* R18011 */ + 0x0000, /* R18012 */ + 0x0000, /* R18013 */ + 0x0000, /* R18014 */ + 0x0000, /* R18015 */ + 0x0000, /* R18016 */ + 0x0000, /* R18017 */ + 0x0000, /* R18018 */ + 0x0000, /* R18019 */ + 0x0000, /* R18020 */ + 0x0000, /* R18021 */ + 0x0000, /* R18022 */ + 0x0000, /* R18023 */ + 0x0000, /* R18024 */ + 0x0000, /* R18025 */ + 0x0000, /* R18026 */ + 0x0000, /* R18027 */ + 0x0000, /* R18028 */ + 0x0000, /* R18029 */ + 0x0000, /* R18030 */ + 0x0000, /* R18031 */ + 0x0000, /* R18032 */ + 0x0000, /* R18033 */ + 0x0000, /* R18034 */ + 0x0000, /* R18035 */ + 0x0000, /* R18036 */ + 0x0000, /* R18037 */ + 0x0000, /* R18038 */ + 0x0000, /* R18039 */ + 0x0000, /* R18040 */ + 0x0000, /* R18041 */ + 0x0000, /* R18042 */ + 0x0000, /* R18043 */ + 0x0000, /* R18044 */ + 0x0000, /* R18045 */ + 0x0000, /* R18046 */ + 0x0000, /* R18047 */ + 0x0000, /* R18048 */ + 0x0000, /* R18049 */ + 0x0000, /* R18050 */ + 0x0000, /* R18051 */ + 0x0000, /* R18052 */ + 0x0000, /* R18053 */ + 0x0000, /* R18054 */ + 0x0000, /* R18055 */ + 0x0000, /* R18056 */ + 0x0000, /* R18057 */ + 0x0000, /* R18058 */ + 0x0000, /* R18059 */ + 0x0000, /* R18060 */ + 0x0000, /* R18061 */ + 0x0000, /* R18062 */ + 0x0000, /* R18063 */ + 0x0000, /* R18064 */ + 0x0000, /* R18065 */ + 0x0000, /* R18066 */ + 0x0000, /* R18067 */ + 0x0000, /* R18068 */ + 0x0000, /* R18069 */ + 0x0000, /* R18070 */ + 0x0000, /* R18071 */ + 0x0000, /* R18072 */ + 0x0000, /* R18073 */ + 0x0000, /* R18074 */ + 0x0000, /* R18075 */ + 0x0000, /* R18076 */ + 0x0000, /* R18077 */ + 0x0000, /* R18078 */ + 0x0000, /* R18079 */ + 0x0000, /* R18080 */ + 0x0000, /* R18081 */ + 0x0000, /* R18082 */ + 0x0000, /* R18083 */ + 0x0000, /* R18084 */ + 0x0000, /* R18085 */ + 0x0000, /* R18086 */ + 0x0000, /* R18087 */ + 0x0000, /* R18088 */ + 0x0000, /* R18089 */ + 0x0000, /* R18090 */ + 0x0000, /* R18091 */ + 0x0000, /* R18092 */ + 0x0000, /* R18093 */ + 0x0000, /* R18094 */ + 0x0000, /* R18095 */ + 0x0000, /* R18096 */ + 0x0000, /* R18097 */ + 0x0000, /* R18098 */ + 0x0000, /* R18099 */ + 0x0000, /* R18100 */ + 0x0000, /* R18101 */ + 0x0000, /* R18102 */ + 0x0000, /* R18103 */ + 0x0000, /* R18104 */ + 0x0000, /* R18105 */ + 0x0000, /* R18106 */ + 0x0000, /* R18107 */ + 0x0000, /* R18108 */ + 0x0000, /* R18109 */ + 0x0000, /* R18110 */ + 0x0000, /* R18111 */ + 0x0000, /* R18112 */ + 0x0000, /* R18113 */ + 0x0000, /* R18114 */ + 0x0000, /* R18115 */ + 0x0000, /* R18116 */ + 0x0000, /* R18117 */ + 0x0000, /* R18118 */ + 0x0000, /* R18119 */ + 0x0000, /* R18120 */ + 0x0000, /* R18121 */ + 0x0000, /* R18122 */ + 0x0000, /* R18123 */ + 0x0000, /* R18124 */ + 0x0000, /* R18125 */ + 0x0000, /* R18126 */ + 0x0000, /* R18127 */ + 0x0000, /* R18128 */ + 0x0000, /* R18129 */ + 0x0000, /* R18130 */ + 0x0000, /* R18131 */ + 0x0000, /* R18132 */ + 0x0000, /* R18133 */ + 0x0000, /* R18134 */ + 0x0000, /* R18135 */ + 0x0000, /* R18136 */ + 0x0000, /* R18137 */ + 0x0000, /* R18138 */ + 0x0000, /* R18139 */ + 0x0000, /* R18140 */ + 0x0000, /* R18141 */ + 0x0000, /* R18142 */ + 0x0000, /* R18143 */ + 0x0000, /* R18144 */ + 0x0000, /* R18145 */ + 0x0000, /* R18146 */ + 0x0000, /* R18147 */ + 0x0000, /* R18148 */ + 0x0000, /* R18149 */ + 0x0000, /* R18150 */ + 0x0000, /* R18151 */ + 0x0000, /* R18152 */ + 0x0000, /* R18153 */ + 0x0000, /* R18154 */ + 0x0000, /* R18155 */ + 0x0000, /* R18156 */ + 0x0000, /* R18157 */ + 0x0000, /* R18158 */ + 0x0000, /* R18159 */ + 0x0000, /* R18160 */ + 0x0000, /* R18161 */ + 0x0000, /* R18162 */ + 0x0000, /* R18163 */ + 0x0000, /* R18164 */ + 0x0000, /* R18165 */ + 0x0000, /* R18166 */ + 0x0000, /* R18167 */ + 0x0000, /* R18168 */ + 0x0000, /* R18169 */ + 0x0000, /* R18170 */ + 0x0000, /* R18171 */ + 0x0000, /* R18172 */ + 0x0000, /* R18173 */ + 0x0000, /* R18174 */ + 0x0000, /* R18175 */ + 0x0000, /* R18176 */ + 0x0000, /* R18177 */ + 0x0000, /* R18178 */ + 0x0000, /* R18179 */ + 0x0000, /* R18180 */ + 0x0000, /* R18181 */ + 0x0000, /* R18182 */ + 0x0000, /* R18183 */ + 0x0000, /* R18184 */ + 0x0000, /* R18185 */ + 0x0000, /* R18186 */ + 0x0000, /* R18187 */ + 0x0000, /* R18188 */ + 0x0000, /* R18189 */ + 0x0000, /* R18190 */ + 0x0000, /* R18191 */ + 0x0000, /* R18192 */ + 0x0000, /* R18193 */ + 0x0000, /* R18194 */ + 0x0000, /* R18195 */ + 0x0000, /* R18196 */ + 0x0000, /* R18197 */ + 0x0000, /* R18198 */ + 0x0000, /* R18199 */ + 0x0000, /* R18200 */ + 0x0000, /* R18201 */ + 0x0000, /* R18202 */ + 0x0000, /* R18203 */ + 0x0000, /* R18204 */ + 0x0000, /* R18205 */ + 0x0000, /* R18206 */ + 0x0000, /* R18207 */ + 0x0000, /* R18208 */ + 0x0000, /* R18209 */ + 0x0000, /* R18210 */ + 0x0000, /* R18211 */ + 0x0000, /* R18212 */ + 0x0000, /* R18213 */ + 0x0000, /* R18214 */ + 0x0000, /* R18215 */ + 0x0000, /* R18216 */ + 0x0000, /* R18217 */ + 0x0000, /* R18218 */ + 0x0000, /* R18219 */ + 0x0000, /* R18220 */ + 0x0000, /* R18221 */ + 0x0000, /* R18222 */ + 0x0000, /* R18223 */ + 0x0000, /* R18224 */ + 0x0000, /* R18225 */ + 0x0000, /* R18226 */ + 0x0000, /* R18227 */ + 0x0000, /* R18228 */ + 0x0000, /* R18229 */ + 0x0000, /* R18230 */ + 0x0000, /* R18231 */ + 0x0000, /* R18232 */ + 0x0000, /* R18233 */ + 0x0000, /* R18234 */ + 0x0000, /* R18235 */ + 0x0000, /* R18236 */ + 0x0000, /* R18237 */ + 0x0000, /* R18238 */ + 0x0000, /* R18239 */ + 0x0000, /* R18240 */ + 0x0000, /* R18241 */ + 0x0000, /* R18242 */ + 0x0000, /* R18243 */ + 0x0000, /* R18244 */ + 0x0000, /* R18245 */ + 0x0000, /* R18246 */ + 0x0000, /* R18247 */ + 0x0000, /* R18248 */ + 0x0000, /* R18249 */ + 0x0000, /* R18250 */ + 0x0000, /* R18251 */ + 0x0000, /* R18252 */ + 0x0000, /* R18253 */ + 0x0000, /* R18254 */ + 0x0000, /* R18255 */ + 0x0000, /* R18256 */ + 0x0000, /* R18257 */ + 0x0000, /* R18258 */ + 0x0000, /* R18259 */ + 0x0000, /* R18260 */ + 0x0000, /* R18261 */ + 0x0000, /* R18262 */ + 0x0000, /* R18263 */ + 0x0000, /* R18264 */ + 0x0000, /* R18265 */ + 0x0000, /* R18266 */ + 0x0000, /* R18267 */ + 0x0000, /* R18268 */ + 0x0000, /* R18269 */ + 0x0000, /* R18270 */ + 0x0000, /* R18271 */ + 0x0000, /* R18272 */ + 0x0000, /* R18273 */ + 0x0000, /* R18274 */ + 0x0000, /* R18275 */ + 0x0000, /* R18276 */ + 0x0000, /* R18277 */ + 0x0000, /* R18278 */ + 0x0000, /* R18279 */ + 0x0000, /* R18280 */ + 0x0000, /* R18281 */ + 0x0000, /* R18282 */ + 0x0000, /* R18283 */ + 0x0000, /* R18284 */ + 0x0000, /* R18285 */ + 0x0000, /* R18286 */ + 0x0000, /* R18287 */ + 0x0000, /* R18288 */ + 0x0000, /* R18289 */ + 0x0000, /* R18290 */ + 0x0000, /* R18291 */ + 0x0000, /* R18292 */ + 0x0000, /* R18293 */ + 0x0000, /* R18294 */ + 0x0000, /* R18295 */ + 0x0000, /* R18296 */ + 0x0000, /* R18297 */ + 0x0000, /* R18298 */ + 0x0000, /* R18299 */ + 0x0000, /* R18300 */ + 0x0000, /* R18301 */ + 0x0000, /* R18302 */ + 0x0000, /* R18303 */ + 0x0000, /* R18304 */ + 0x0000, /* R18305 */ + 0x0000, /* R18306 */ + 0x0000, /* R18307 */ + 0x0000, /* R18308 */ + 0x0000, /* R18309 */ + 0x0000, /* R18310 */ + 0x0000, /* R18311 */ + 0x0000, /* R18312 */ + 0x0000, /* R18313 */ + 0x0000, /* R18314 */ + 0x0000, /* R18315 */ + 0x0000, /* R18316 */ + 0x0000, /* R18317 */ + 0x0000, /* R18318 */ + 0x0000, /* R18319 */ + 0x0000, /* R18320 */ + 0x0000, /* R18321 */ + 0x0000, /* R18322 */ + 0x0000, /* R18323 */ + 0x0000, /* R18324 */ + 0x0000, /* R18325 */ + 0x0000, /* R18326 */ + 0x0000, /* R18327 */ + 0x0000, /* R18328 */ + 0x0000, /* R18329 */ + 0x0000, /* R18330 */ + 0x0000, /* R18331 */ + 0x0000, /* R18332 */ + 0x0000, /* R18333 */ + 0x0000, /* R18334 */ + 0x0000, /* R18335 */ + 0x0000, /* R18336 */ + 0x0000, /* R18337 */ + 0x0000, /* R18338 */ + 0x0000, /* R18339 */ + 0x0000, /* R18340 */ + 0x0000, /* R18341 */ + 0x0000, /* R18342 */ + 0x0000, /* R18343 */ + 0x0000, /* R18344 */ + 0x0000, /* R18345 */ + 0x0000, /* R18346 */ + 0x0000, /* R18347 */ + 0x0000, /* R18348 */ + 0x0000, /* R18349 */ + 0x0000, /* R18350 */ + 0x0000, /* R18351 */ + 0x0000, /* R18352 */ + 0x0000, /* R18353 */ + 0x0000, /* R18354 */ + 0x0000, /* R18355 */ + 0x0000, /* R18356 */ + 0x0000, /* R18357 */ + 0x0000, /* R18358 */ + 0x0000, /* R18359 */ + 0x0000, /* R18360 */ + 0x0000, /* R18361 */ + 0x0000, /* R18362 */ + 0x0000, /* R18363 */ + 0x0000, /* R18364 */ + 0x0000, /* R18365 */ + 0x0000, /* R18366 */ + 0x0000, /* R18367 */ + 0x0000, /* R18368 */ + 0x0000, /* R18369 */ + 0x0000, /* R18370 */ + 0x0000, /* R18371 */ + 0x0000, /* R18372 */ + 0x0000, /* R18373 */ + 0x0000, /* R18374 */ + 0x0000, /* R18375 */ + 0x0000, /* R18376 */ + 0x0000, /* R18377 */ + 0x0000, /* R18378 */ + 0x0000, /* R18379 */ + 0x0000, /* R18380 */ + 0x0000, /* R18381 */ + 0x0000, /* R18382 */ + 0x0000, /* R18383 */ + 0x0000, /* R18384 */ + 0x0000, /* R18385 */ + 0x0000, /* R18386 */ + 0x0000, /* R18387 */ + 0x0000, /* R18388 */ + 0x0000, /* R18389 */ + 0x0000, /* R18390 */ + 0x0000, /* R18391 */ + 0x0000, /* R18392 */ + 0x0000, /* R18393 */ + 0x0000, /* R18394 */ + 0x0000, /* R18395 */ + 0x0000, /* R18396 */ + 0x0000, /* R18397 */ + 0x0000, /* R18398 */ + 0x0000, /* R18399 */ + 0x0000, /* R18400 */ + 0x0000, /* R18401 */ + 0x0000, /* R18402 */ + 0x0000, /* R18403 */ + 0x0000, /* R18404 */ + 0x0000, /* R18405 */ + 0x0000, /* R18406 */ + 0x0000, /* R18407 */ + 0x0000, /* R18408 */ + 0x0000, /* R18409 */ + 0x0000, /* R18410 */ + 0x0000, /* R18411 */ + 0x0000, /* R18412 */ + 0x0000, /* R18413 */ + 0x0000, /* R18414 */ + 0x0000, /* R18415 */ + 0x0000, /* R18416 */ + 0x0000, /* R18417 */ + 0x0000, /* R18418 */ + 0x0000, /* R18419 */ + 0x0000, /* R18420 */ + 0x0000, /* R18421 */ + 0x0000, /* R18422 */ + 0x0000, /* R18423 */ + 0x0000, /* R18424 */ + 0x0000, /* R18425 */ + 0x0000, /* R18426 */ + 0x0000, /* R18427 */ + 0x0000, /* R18428 */ + 0x0000, /* R18429 */ + 0x0000, /* R18430 */ + 0x0000, /* R18431 */ + 0x0020, /* R18432 - RETUNEADC_PG2_1 */ + 0x0000, /* R18433 - RETUNEADC_PG2_0 */ + 0x0040, /* R18434 - RETUNEADC_PG_1 */ + 0x0000, /* R18435 - RETUNEADC_PG_0 */ + 0x0000, /* R18436 */ + 0x0000, /* R18437 */ + 0x0000, /* R18438 */ + 0x0000, /* R18439 */ + 0x0000, /* R18440 */ + 0x0000, /* R18441 */ + 0x0000, /* R18442 */ + 0x0000, /* R18443 */ + 0x0000, /* R18444 */ + 0x0000, /* R18445 */ + 0x0000, /* R18446 */ + 0x0000, /* R18447 */ + 0x0000, /* R18448 */ + 0x0000, /* R18449 */ + 0x0000, /* R18450 */ + 0x0000, /* R18451 */ + 0x0000, /* R18452 */ + 0x0000, /* R18453 */ + 0x0000, /* R18454 */ + 0x0000, /* R18455 */ + 0x0000, /* R18456 */ + 0x0000, /* R18457 */ + 0x0000, /* R18458 */ + 0x0000, /* R18459 */ + 0x0000, /* R18460 */ + 0x0000, /* R18461 */ + 0x0000, /* R18462 */ + 0x0000, /* R18463 */ + 0x0000, /* R18464 */ + 0x0000, /* R18465 */ + 0x0000, /* R18466 */ + 0x0000, /* R18467 */ + 0x0000, /* R18468 */ + 0x0000, /* R18469 */ + 0x0000, /* R18470 */ + 0x0000, /* R18471 */ + 0x0000, /* R18472 */ + 0x0000, /* R18473 */ + 0x0000, /* R18474 */ + 0x0000, /* R18475 */ + 0x0000, /* R18476 */ + 0x0000, /* R18477 */ + 0x0000, /* R18478 */ + 0x0000, /* R18479 */ + 0x0000, /* R18480 */ + 0x0000, /* R18481 */ + 0x0000, /* R18482 */ + 0x0000, /* R18483 */ + 0x0000, /* R18484 */ + 0x0000, /* R18485 */ + 0x0000, /* R18486 */ + 0x0000, /* R18487 */ + 0x0000, /* R18488 */ + 0x0000, /* R18489 */ + 0x0000, /* R18490 */ + 0x0000, /* R18491 */ + 0x0000, /* R18492 */ + 0x0000, /* R18493 */ + 0x0000, /* R18494 */ + 0x0000, /* R18495 */ + 0x0000, /* R18496 */ + 0x0000, /* R18497 */ + 0x0000, /* R18498 */ + 0x0000, /* R18499 */ + 0x0000, /* R18500 */ + 0x0000, /* R18501 */ + 0x0000, /* R18502 */ + 0x0000, /* R18503 */ + 0x0000, /* R18504 */ + 0x0000, /* R18505 */ + 0x0000, /* R18506 */ + 0x0000, /* R18507 */ + 0x0000, /* R18508 */ + 0x0000, /* R18509 */ + 0x0000, /* R18510 */ + 0x0000, /* R18511 */ + 0x0000, /* R18512 */ + 0x0000, /* R18513 */ + 0x0000, /* R18514 */ + 0x0000, /* R18515 */ + 0x0000, /* R18516 */ + 0x0000, /* R18517 */ + 0x0000, /* R18518 */ + 0x0000, /* R18519 */ + 0x0000, /* R18520 */ + 0x0000, /* R18521 */ + 0x0000, /* R18522 */ + 0x0000, /* R18523 */ + 0x0000, /* R18524 */ + 0x0000, /* R18525 */ + 0x0000, /* R18526 */ + 0x0000, /* R18527 */ + 0x0000, /* R18528 */ + 0x0000, /* R18529 */ + 0x0000, /* R18530 */ + 0x0000, /* R18531 */ + 0x0000, /* R18532 */ + 0x0000, /* R18533 */ + 0x0000, /* R18534 */ + 0x0000, /* R18535 */ + 0x0000, /* R18536 */ + 0x0000, /* R18537 */ + 0x0000, /* R18538 */ + 0x0000, /* R18539 */ + 0x0000, /* R18540 */ + 0x0000, /* R18541 */ + 0x0000, /* R18542 */ + 0x0000, /* R18543 */ + 0x0000, /* R18544 */ + 0x0000, /* R18545 */ + 0x0000, /* R18546 */ + 0x0000, /* R18547 */ + 0x0000, /* R18548 */ + 0x0000, /* R18549 */ + 0x0000, /* R18550 */ + 0x0000, /* R18551 */ + 0x0000, /* R18552 */ + 0x0000, /* R18553 */ + 0x0000, /* R18554 */ + 0x0000, /* R18555 */ + 0x0000, /* R18556 */ + 0x0000, /* R18557 */ + 0x0000, /* R18558 */ + 0x0000, /* R18559 */ + 0x0000, /* R18560 */ + 0x0000, /* R18561 */ + 0x0000, /* R18562 */ + 0x0000, /* R18563 */ + 0x0000, /* R18564 */ + 0x0000, /* R18565 */ + 0x0000, /* R18566 */ + 0x0000, /* R18567 */ + 0x0000, /* R18568 */ + 0x0000, /* R18569 */ + 0x0000, /* R18570 */ + 0x0000, /* R18571 */ + 0x0000, /* R18572 */ + 0x0000, /* R18573 */ + 0x0000, /* R18574 */ + 0x0000, /* R18575 */ + 0x0000, /* R18576 */ + 0x0000, /* R18577 */ + 0x0000, /* R18578 */ + 0x0000, /* R18579 */ + 0x0000, /* R18580 */ + 0x0000, /* R18581 */ + 0x0000, /* R18582 */ + 0x0000, /* R18583 */ + 0x0000, /* R18584 */ + 0x0000, /* R18585 */ + 0x0000, /* R18586 */ + 0x0000, /* R18587 */ + 0x0000, /* R18588 */ + 0x0000, /* R18589 */ + 0x0000, /* R18590 */ + 0x0000, /* R18591 */ + 0x0000, /* R18592 */ + 0x0000, /* R18593 */ + 0x0000, /* R18594 */ + 0x0000, /* R18595 */ + 0x0000, /* R18596 */ + 0x0000, /* R18597 */ + 0x0000, /* R18598 */ + 0x0000, /* R18599 */ + 0x0000, /* R18600 */ + 0x0000, /* R18601 */ + 0x0000, /* R18602 */ + 0x0000, /* R18603 */ + 0x0000, /* R18604 */ + 0x0000, /* R18605 */ + 0x0000, /* R18606 */ + 0x0000, /* R18607 */ + 0x0000, /* R18608 */ + 0x0000, /* R18609 */ + 0x0000, /* R18610 */ + 0x0000, /* R18611 */ + 0x0000, /* R18612 */ + 0x0000, /* R18613 */ + 0x0000, /* R18614 */ + 0x0000, /* R18615 */ + 0x0000, /* R18616 */ + 0x0000, /* R18617 */ + 0x0000, /* R18618 */ + 0x0000, /* R18619 */ + 0x0000, /* R18620 */ + 0x0000, /* R18621 */ + 0x0000, /* R18622 */ + 0x0000, /* R18623 */ + 0x0000, /* R18624 */ + 0x0000, /* R18625 */ + 0x0000, /* R18626 */ + 0x0000, /* R18627 */ + 0x0000, /* R18628 */ + 0x0000, /* R18629 */ + 0x0000, /* R18630 */ + 0x0000, /* R18631 */ + 0x0000, /* R18632 */ + 0x0000, /* R18633 */ + 0x0000, /* R18634 */ + 0x0000, /* R18635 */ + 0x0000, /* R18636 */ + 0x0000, /* R18637 */ + 0x0000, /* R18638 */ + 0x0000, /* R18639 */ + 0x0000, /* R18640 */ + 0x0000, /* R18641 */ + 0x0000, /* R18642 */ + 0x0000, /* R18643 */ + 0x0000, /* R18644 */ + 0x0000, /* R18645 */ + 0x0000, /* R18646 */ + 0x0000, /* R18647 */ + 0x0000, /* R18648 */ + 0x0000, /* R18649 */ + 0x0000, /* R18650 */ + 0x0000, /* R18651 */ + 0x0000, /* R18652 */ + 0x0000, /* R18653 */ + 0x0000, /* R18654 */ + 0x0000, /* R18655 */ + 0x0000, /* R18656 */ + 0x0000, /* R18657 */ + 0x0000, /* R18658 */ + 0x0000, /* R18659 */ + 0x0000, /* R18660 */ + 0x0000, /* R18661 */ + 0x0000, /* R18662 */ + 0x0000, /* R18663 */ + 0x0000, /* R18664 */ + 0x0000, /* R18665 */ + 0x0000, /* R18666 */ + 0x0000, /* R18667 */ + 0x0000, /* R18668 */ + 0x0000, /* R18669 */ + 0x0000, /* R18670 */ + 0x0000, /* R18671 */ + 0x0000, /* R18672 */ + 0x0000, /* R18673 */ + 0x0000, /* R18674 */ + 0x0000, /* R18675 */ + 0x0000, /* R18676 */ + 0x0000, /* R18677 */ + 0x0000, /* R18678 */ + 0x0000, /* R18679 */ + 0x0000, /* R18680 */ + 0x0000, /* R18681 */ + 0x0000, /* R18682 */ + 0x0000, /* R18683 */ + 0x0000, /* R18684 */ + 0x0000, /* R18685 */ + 0x0000, /* R18686 */ + 0x0000, /* R18687 */ + 0x0000, /* R18688 */ + 0x0000, /* R18689 */ + 0x0000, /* R18690 */ + 0x0000, /* R18691 */ + 0x0000, /* R18692 */ + 0x0000, /* R18693 */ + 0x0000, /* R18694 */ + 0x0000, /* R18695 */ + 0x0000, /* R18696 */ + 0x0000, /* R18697 */ + 0x0000, /* R18698 */ + 0x0000, /* R18699 */ + 0x0000, /* R18700 */ + 0x0000, /* R18701 */ + 0x0000, /* R18702 */ + 0x0000, /* R18703 */ + 0x0000, /* R18704 */ + 0x0000, /* R18705 */ + 0x0000, /* R18706 */ + 0x0000, /* R18707 */ + 0x0000, /* R18708 */ + 0x0000, /* R18709 */ + 0x0000, /* R18710 */ + 0x0000, /* R18711 */ + 0x0000, /* R18712 */ + 0x0000, /* R18713 */ + 0x0000, /* R18714 */ + 0x0000, /* R18715 */ + 0x0000, /* R18716 */ + 0x0000, /* R18717 */ + 0x0000, /* R18718 */ + 0x0000, /* R18719 */ + 0x0000, /* R18720 */ + 0x0000, /* R18721 */ + 0x0000, /* R18722 */ + 0x0000, /* R18723 */ + 0x0000, /* R18724 */ + 0x0000, /* R18725 */ + 0x0000, /* R18726 */ + 0x0000, /* R18727 */ + 0x0000, /* R18728 */ + 0x0000, /* R18729 */ + 0x0000, /* R18730 */ + 0x0000, /* R18731 */ + 0x0000, /* R18732 */ + 0x0000, /* R18733 */ + 0x0000, /* R18734 */ + 0x0000, /* R18735 */ + 0x0000, /* R18736 */ + 0x0000, /* R18737 */ + 0x0000, /* R18738 */ + 0x0000, /* R18739 */ + 0x0000, /* R18740 */ + 0x0000, /* R18741 */ + 0x0000, /* R18742 */ + 0x0000, /* R18743 */ + 0x0000, /* R18744 */ + 0x0000, /* R18745 */ + 0x0000, /* R18746 */ + 0x0000, /* R18747 */ + 0x0000, /* R18748 */ + 0x0000, /* R18749 */ + 0x0000, /* R18750 */ + 0x0000, /* R18751 */ + 0x0000, /* R18752 */ + 0x0000, /* R18753 */ + 0x0000, /* R18754 */ + 0x0000, /* R18755 */ + 0x0000, /* R18756 */ + 0x0000, /* R18757 */ + 0x0000, /* R18758 */ + 0x0000, /* R18759 */ + 0x0000, /* R18760 */ + 0x0000, /* R18761 */ + 0x0000, /* R18762 */ + 0x0000, /* R18763 */ + 0x0000, /* R18764 */ + 0x0000, /* R18765 */ + 0x0000, /* R18766 */ + 0x0000, /* R18767 */ + 0x0000, /* R18768 */ + 0x0000, /* R18769 */ + 0x0000, /* R18770 */ + 0x0000, /* R18771 */ + 0x0000, /* R18772 */ + 0x0000, /* R18773 */ + 0x0000, /* R18774 */ + 0x0000, /* R18775 */ + 0x0000, /* R18776 */ + 0x0000, /* R18777 */ + 0x0000, /* R18778 */ + 0x0000, /* R18779 */ + 0x0000, /* R18780 */ + 0x0000, /* R18781 */ + 0x0000, /* R18782 */ + 0x0000, /* R18783 */ + 0x0000, /* R18784 */ + 0x0000, /* R18785 */ + 0x0000, /* R18786 */ + 0x0000, /* R18787 */ + 0x0000, /* R18788 */ + 0x0000, /* R18789 */ + 0x0000, /* R18790 */ + 0x0000, /* R18791 */ + 0x0000, /* R18792 */ + 0x0000, /* R18793 */ + 0x0000, /* R18794 */ + 0x0000, /* R18795 */ + 0x0000, /* R18796 */ + 0x0000, /* R18797 */ + 0x0000, /* R18798 */ + 0x0000, /* R18799 */ + 0x0000, /* R18800 */ + 0x0000, /* R18801 */ + 0x0000, /* R18802 */ + 0x0000, /* R18803 */ + 0x0000, /* R18804 */ + 0x0000, /* R18805 */ + 0x0000, /* R18806 */ + 0x0000, /* R18807 */ + 0x0000, /* R18808 */ + 0x0000, /* R18809 */ + 0x0000, /* R18810 */ + 0x0000, /* R18811 */ + 0x0000, /* R18812 */ + 0x0000, /* R18813 */ + 0x0000, /* R18814 */ + 0x0000, /* R18815 */ + 0x0000, /* R18816 */ + 0x0000, /* R18817 */ + 0x0000, /* R18818 */ + 0x0000, /* R18819 */ + 0x0000, /* R18820 */ + 0x0000, /* R18821 */ + 0x0000, /* R18822 */ + 0x0000, /* R18823 */ + 0x0000, /* R18824 */ + 0x0000, /* R18825 */ + 0x0000, /* R18826 */ + 0x0000, /* R18827 */ + 0x0000, /* R18828 */ + 0x0000, /* R18829 */ + 0x0000, /* R18830 */ + 0x0000, /* R18831 */ + 0x0000, /* R18832 */ + 0x0000, /* R18833 */ + 0x0000, /* R18834 */ + 0x0000, /* R18835 */ + 0x0000, /* R18836 */ + 0x0000, /* R18837 */ + 0x0000, /* R18838 */ + 0x0000, /* R18839 */ + 0x0000, /* R18840 */ + 0x0000, /* R18841 */ + 0x0000, /* R18842 */ + 0x0000, /* R18843 */ + 0x0000, /* R18844 */ + 0x0000, /* R18845 */ + 0x0000, /* R18846 */ + 0x0000, /* R18847 */ + 0x0000, /* R18848 */ + 0x0000, /* R18849 */ + 0x0000, /* R18850 */ + 0x0000, /* R18851 */ + 0x0000, /* R18852 */ + 0x0000, /* R18853 */ + 0x0000, /* R18854 */ + 0x0000, /* R18855 */ + 0x0000, /* R18856 */ + 0x0000, /* R18857 */ + 0x0000, /* R18858 */ + 0x0000, /* R18859 */ + 0x0000, /* R18860 */ + 0x0000, /* R18861 */ + 0x0000, /* R18862 */ + 0x0000, /* R18863 */ + 0x0000, /* R18864 */ + 0x0000, /* R18865 */ + 0x0000, /* R18866 */ + 0x0000, /* R18867 */ + 0x0000, /* R18868 */ + 0x0000, /* R18869 */ + 0x0000, /* R18870 */ + 0x0000, /* R18871 */ + 0x0000, /* R18872 */ + 0x0000, /* R18873 */ + 0x0000, /* R18874 */ + 0x0000, /* R18875 */ + 0x0000, /* R18876 */ + 0x0000, /* R18877 */ + 0x0000, /* R18878 */ + 0x0000, /* R18879 */ + 0x0000, /* R18880 */ + 0x0000, /* R18881 */ + 0x0000, /* R18882 */ + 0x0000, /* R18883 */ + 0x0000, /* R18884 */ + 0x0000, /* R18885 */ + 0x0000, /* R18886 */ + 0x0000, /* R18887 */ + 0x0000, /* R18888 */ + 0x0000, /* R18889 */ + 0x0000, /* R18890 */ + 0x0000, /* R18891 */ + 0x0000, /* R18892 */ + 0x0000, /* R18893 */ + 0x0000, /* R18894 */ + 0x0000, /* R18895 */ + 0x0000, /* R18896 */ + 0x0000, /* R18897 */ + 0x0000, /* R18898 */ + 0x0000, /* R18899 */ + 0x0000, /* R18900 */ + 0x0000, /* R18901 */ + 0x0000, /* R18902 */ + 0x0000, /* R18903 */ + 0x0000, /* R18904 */ + 0x0000, /* R18905 */ + 0x0000, /* R18906 */ + 0x0000, /* R18907 */ + 0x0000, /* R18908 */ + 0x0000, /* R18909 */ + 0x0000, /* R18910 */ + 0x0000, /* R18911 */ + 0x0000, /* R18912 */ + 0x0000, /* R18913 */ + 0x0000, /* R18914 */ + 0x0000, /* R18915 */ + 0x0000, /* R18916 */ + 0x0000, /* R18917 */ + 0x0000, /* R18918 */ + 0x0000, /* R18919 */ + 0x0000, /* R18920 */ + 0x0000, /* R18921 */ + 0x0000, /* R18922 */ + 0x0000, /* R18923 */ + 0x0000, /* R18924 */ + 0x0000, /* R18925 */ + 0x0000, /* R18926 */ + 0x0000, /* R18927 */ + 0x0000, /* R18928 */ + 0x0000, /* R18929 */ + 0x0000, /* R18930 */ + 0x0000, /* R18931 */ + 0x0000, /* R18932 */ + 0x0000, /* R18933 */ + 0x0000, /* R18934 */ + 0x0000, /* R18935 */ + 0x0000, /* R18936 */ + 0x0000, /* R18937 */ + 0x0000, /* R18938 */ + 0x0000, /* R18939 */ + 0x0000, /* R18940 */ + 0x0000, /* R18941 */ + 0x0000, /* R18942 */ + 0x0000, /* R18943 */ + 0x007F, /* R18944 - ADCR_RETUNE_C1_1 */ + 0xFFFF, /* R18945 - ADCR_RETUNE_C1_0 */ + 0x0000, /* R18946 - ADCR_RETUNE_C2_1 */ + 0x0000, /* R18947 - ADCR_RETUNE_C2_0 */ + 0x0000, /* R18948 - ADCR_RETUNE_C3_1 */ + 0x0000, /* R18949 - ADCR_RETUNE_C3_0 */ + 0x0000, /* R18950 - ADCR_RETUNE_C4_1 */ + 0x0000, /* R18951 - ADCR_RETUNE_C4_0 */ + 0x0000, /* R18952 - ADCR_RETUNE_C5_1 */ + 0x0000, /* R18953 - ADCR_RETUNE_C5_0 */ + 0x0000, /* R18954 - ADCR_RETUNE_C6_1 */ + 0x0000, /* R18955 - ADCR_RETUNE_C6_0 */ + 0x0000, /* R18956 - ADCR_RETUNE_C7_1 */ + 0x0000, /* R18957 - ADCR_RETUNE_C7_0 */ + 0x0000, /* R18958 - ADCR_RETUNE_C8_1 */ + 0x0000, /* R18959 - ADCR_RETUNE_C8_0 */ + 0x0000, /* R18960 - ADCR_RETUNE_C9_1 */ + 0x0000, /* R18961 - ADCR_RETUNE_C9_0 */ + 0x0000, /* R18962 - ADCR_RETUNE_C10_1 */ + 0x0000, /* R18963 - ADCR_RETUNE_C10_0 */ + 0x0000, /* R18964 - ADCR_RETUNE_C11_1 */ + 0x0000, /* R18965 - ADCR_RETUNE_C11_0 */ + 0x0000, /* R18966 - ADCR_RETUNE_C12_1 */ + 0x0000, /* R18967 - ADCR_RETUNE_C12_0 */ + 0x0000, /* R18968 - ADCR_RETUNE_C13_1 */ + 0x0000, /* R18969 - ADCR_RETUNE_C13_0 */ + 0x0000, /* R18970 - ADCR_RETUNE_C14_1 */ + 0x0000, /* R18971 - ADCR_RETUNE_C14_0 */ + 0x0000, /* R18972 - ADCR_RETUNE_C15_1 */ + 0x0000, /* R18973 - ADCR_RETUNE_C15_0 */ + 0x0000, /* R18974 - ADCR_RETUNE_C16_1 */ + 0x0000, /* R18975 - ADCR_RETUNE_C16_0 */ + 0x0000, /* R18976 - ADCR_RETUNE_C17_1 */ + 0x0000, /* R18977 - ADCR_RETUNE_C17_0 */ + 0x0000, /* R18978 - ADCR_RETUNE_C18_1 */ + 0x0000, /* R18979 - ADCR_RETUNE_C18_0 */ + 0x0000, /* R18980 - ADCR_RETUNE_C19_1 */ + 0x0000, /* R18981 - ADCR_RETUNE_C19_0 */ + 0x0000, /* R18982 - ADCR_RETUNE_C20_1 */ + 0x0000, /* R18983 - ADCR_RETUNE_C20_0 */ + 0x0000, /* R18984 - ADCR_RETUNE_C21_1 */ + 0x0000, /* R18985 - ADCR_RETUNE_C21_0 */ + 0x0000, /* R18986 - ADCR_RETUNE_C22_1 */ + 0x0000, /* R18987 - ADCR_RETUNE_C22_0 */ + 0x0000, /* R18988 - ADCR_RETUNE_C23_1 */ + 0x0000, /* R18989 - ADCR_RETUNE_C23_0 */ + 0x0000, /* R18990 - ADCR_RETUNE_C24_1 */ + 0x0000, /* R18991 - ADCR_RETUNE_C24_0 */ + 0x0000, /* R18992 - ADCR_RETUNE_C25_1 */ + 0x0000, /* R18993 - ADCR_RETUNE_C25_0 */ + 0x0000, /* R18994 - ADCR_RETUNE_C26_1 */ + 0x0000, /* R18995 - ADCR_RETUNE_C26_0 */ + 0x0000, /* R18996 - ADCR_RETUNE_C27_1 */ + 0x0000, /* R18997 - ADCR_RETUNE_C27_0 */ + 0x0000, /* R18998 - ADCR_RETUNE_C28_1 */ + 0x0000, /* R18999 - ADCR_RETUNE_C28_0 */ + 0x0000, /* R19000 - ADCR_RETUNE_C29_1 */ + 0x0000, /* R19001 - ADCR_RETUNE_C29_0 */ + 0x0000, /* R19002 - ADCR_RETUNE_C30_1 */ + 0x0000, /* R19003 - ADCR_RETUNE_C30_0 */ + 0x0000, /* R19004 - ADCR_RETUNE_C31_1 */ + 0x0000, /* R19005 - ADCR_RETUNE_C31_0 */ + 0x0000, /* R19006 - ADCR_RETUNE_C32_1 */ + 0x0000, /* R19007 - ADCR_RETUNE_C32_0 */ + 0x0000, /* R19008 */ + 0x0000, /* R19009 */ + 0x0000, /* R19010 */ + 0x0000, /* R19011 */ + 0x0000, /* R19012 */ + 0x0000, /* R19013 */ + 0x0000, /* R19014 */ + 0x0000, /* R19015 */ + 0x0000, /* R19016 */ + 0x0000, /* R19017 */ + 0x0000, /* R19018 */ + 0x0000, /* R19019 */ + 0x0000, /* R19020 */ + 0x0000, /* R19021 */ + 0x0000, /* R19022 */ + 0x0000, /* R19023 */ + 0x0000, /* R19024 */ + 0x0000, /* R19025 */ + 0x0000, /* R19026 */ + 0x0000, /* R19027 */ + 0x0000, /* R19028 */ + 0x0000, /* R19029 */ + 0x0000, /* R19030 */ + 0x0000, /* R19031 */ + 0x0000, /* R19032 */ + 0x0000, /* R19033 */ + 0x0000, /* R19034 */ + 0x0000, /* R19035 */ + 0x0000, /* R19036 */ + 0x0000, /* R19037 */ + 0x0000, /* R19038 */ + 0x0000, /* R19039 */ + 0x0000, /* R19040 */ + 0x0000, /* R19041 */ + 0x0000, /* R19042 */ + 0x0000, /* R19043 */ + 0x0000, /* R19044 */ + 0x0000, /* R19045 */ + 0x0000, /* R19046 */ + 0x0000, /* R19047 */ + 0x0000, /* R19048 */ + 0x0000, /* R19049 */ + 0x0000, /* R19050 */ + 0x0000, /* R19051 */ + 0x0000, /* R19052 */ + 0x0000, /* R19053 */ + 0x0000, /* R19054 */ + 0x0000, /* R19055 */ + 0x0000, /* R19056 */ + 0x0000, /* R19057 */ + 0x0000, /* R19058 */ + 0x0000, /* R19059 */ + 0x0000, /* R19060 */ + 0x0000, /* R19061 */ + 0x0000, /* R19062 */ + 0x0000, /* R19063 */ + 0x0000, /* R19064 */ + 0x0000, /* R19065 */ + 0x0000, /* R19066 */ + 0x0000, /* R19067 */ + 0x0000, /* R19068 */ + 0x0000, /* R19069 */ + 0x0000, /* R19070 */ + 0x0000, /* R19071 */ + 0x0000, /* R19072 */ + 0x0000, /* R19073 */ + 0x0000, /* R19074 */ + 0x0000, /* R19075 */ + 0x0000, /* R19076 */ + 0x0000, /* R19077 */ + 0x0000, /* R19078 */ + 0x0000, /* R19079 */ + 0x0000, /* R19080 */ + 0x0000, /* R19081 */ + 0x0000, /* R19082 */ + 0x0000, /* R19083 */ + 0x0000, /* R19084 */ + 0x0000, /* R19085 */ + 0x0000, /* R19086 */ + 0x0000, /* R19087 */ + 0x0000, /* R19088 */ + 0x0000, /* R19089 */ + 0x0000, /* R19090 */ + 0x0000, /* R19091 */ + 0x0000, /* R19092 */ + 0x0000, /* R19093 */ + 0x0000, /* R19094 */ + 0x0000, /* R19095 */ + 0x0000, /* R19096 */ + 0x0000, /* R19097 */ + 0x0000, /* R19098 */ + 0x0000, /* R19099 */ + 0x0000, /* R19100 */ + 0x0000, /* R19101 */ + 0x0000, /* R19102 */ + 0x0000, /* R19103 */ + 0x0000, /* R19104 */ + 0x0000, /* R19105 */ + 0x0000, /* R19106 */ + 0x0000, /* R19107 */ + 0x0000, /* R19108 */ + 0x0000, /* R19109 */ + 0x0000, /* R19110 */ + 0x0000, /* R19111 */ + 0x0000, /* R19112 */ + 0x0000, /* R19113 */ + 0x0000, /* R19114 */ + 0x0000, /* R19115 */ + 0x0000, /* R19116 */ + 0x0000, /* R19117 */ + 0x0000, /* R19118 */ + 0x0000, /* R19119 */ + 0x0000, /* R19120 */ + 0x0000, /* R19121 */ + 0x0000, /* R19122 */ + 0x0000, /* R19123 */ + 0x0000, /* R19124 */ + 0x0000, /* R19125 */ + 0x0000, /* R19126 */ + 0x0000, /* R19127 */ + 0x0000, /* R19128 */ + 0x0000, /* R19129 */ + 0x0000, /* R19130 */ + 0x0000, /* R19131 */ + 0x0000, /* R19132 */ + 0x0000, /* R19133 */ + 0x0000, /* R19134 */ + 0x0000, /* R19135 */ + 0x0000, /* R19136 */ + 0x0000, /* R19137 */ + 0x0000, /* R19138 */ + 0x0000, /* R19139 */ + 0x0000, /* R19140 */ + 0x0000, /* R19141 */ + 0x0000, /* R19142 */ + 0x0000, /* R19143 */ + 0x0000, /* R19144 */ + 0x0000, /* R19145 */ + 0x0000, /* R19146 */ + 0x0000, /* R19147 */ + 0x0000, /* R19148 */ + 0x0000, /* R19149 */ + 0x0000, /* R19150 */ + 0x0000, /* R19151 */ + 0x0000, /* R19152 */ + 0x0000, /* R19153 */ + 0x0000, /* R19154 */ + 0x0000, /* R19155 */ + 0x0000, /* R19156 */ + 0x0000, /* R19157 */ + 0x0000, /* R19158 */ + 0x0000, /* R19159 */ + 0x0000, /* R19160 */ + 0x0000, /* R19161 */ + 0x0000, /* R19162 */ + 0x0000, /* R19163 */ + 0x0000, /* R19164 */ + 0x0000, /* R19165 */ + 0x0000, /* R19166 */ + 0x0000, /* R19167 */ + 0x0000, /* R19168 */ + 0x0000, /* R19169 */ + 0x0000, /* R19170 */ + 0x0000, /* R19171 */ + 0x0000, /* R19172 */ + 0x0000, /* R19173 */ + 0x0000, /* R19174 */ + 0x0000, /* R19175 */ + 0x0000, /* R19176 */ + 0x0000, /* R19177 */ + 0x0000, /* R19178 */ + 0x0000, /* R19179 */ + 0x0000, /* R19180 */ + 0x0000, /* R19181 */ + 0x0000, /* R19182 */ + 0x0000, /* R19183 */ + 0x0000, /* R19184 */ + 0x0000, /* R19185 */ + 0x0000, /* R19186 */ + 0x0000, /* R19187 */ + 0x0000, /* R19188 */ + 0x0000, /* R19189 */ + 0x0000, /* R19190 */ + 0x0000, /* R19191 */ + 0x0000, /* R19192 */ + 0x0000, /* R19193 */ + 0x0000, /* R19194 */ + 0x0000, /* R19195 */ + 0x0000, /* R19196 */ + 0x0000, /* R19197 */ + 0x0000, /* R19198 */ + 0x0000, /* R19199 */ + 0x0000, /* R19200 */ + 0x0000, /* R19201 */ + 0x0000, /* R19202 */ + 0x0000, /* R19203 */ + 0x0000, /* R19204 */ + 0x0000, /* R19205 */ + 0x0000, /* R19206 */ + 0x0000, /* R19207 */ + 0x0000, /* R19208 */ + 0x0000, /* R19209 */ + 0x0000, /* R19210 */ + 0x0000, /* R19211 */ + 0x0000, /* R19212 */ + 0x0000, /* R19213 */ + 0x0000, /* R19214 */ + 0x0000, /* R19215 */ + 0x0000, /* R19216 */ + 0x0000, /* R19217 */ + 0x0000, /* R19218 */ + 0x0000, /* R19219 */ + 0x0000, /* R19220 */ + 0x0000, /* R19221 */ + 0x0000, /* R19222 */ + 0x0000, /* R19223 */ + 0x0000, /* R19224 */ + 0x0000, /* R19225 */ + 0x0000, /* R19226 */ + 0x0000, /* R19227 */ + 0x0000, /* R19228 */ + 0x0000, /* R19229 */ + 0x0000, /* R19230 */ + 0x0000, /* R19231 */ + 0x0000, /* R19232 */ + 0x0000, /* R19233 */ + 0x0000, /* R19234 */ + 0x0000, /* R19235 */ + 0x0000, /* R19236 */ + 0x0000, /* R19237 */ + 0x0000, /* R19238 */ + 0x0000, /* R19239 */ + 0x0000, /* R19240 */ + 0x0000, /* R19241 */ + 0x0000, /* R19242 */ + 0x0000, /* R19243 */ + 0x0000, /* R19244 */ + 0x0000, /* R19245 */ + 0x0000, /* R19246 */ + 0x0000, /* R19247 */ + 0x0000, /* R19248 */ + 0x0000, /* R19249 */ + 0x0000, /* R19250 */ + 0x0000, /* R19251 */ + 0x0000, /* R19252 */ + 0x0000, /* R19253 */ + 0x0000, /* R19254 */ + 0x0000, /* R19255 */ + 0x0000, /* R19256 */ + 0x0000, /* R19257 */ + 0x0000, /* R19258 */ + 0x0000, /* R19259 */ + 0x0000, /* R19260 */ + 0x0000, /* R19261 */ + 0x0000, /* R19262 */ + 0x0000, /* R19263 */ + 0x0000, /* R19264 */ + 0x0000, /* R19265 */ + 0x0000, /* R19266 */ + 0x0000, /* R19267 */ + 0x0000, /* R19268 */ + 0x0000, /* R19269 */ + 0x0000, /* R19270 */ + 0x0000, /* R19271 */ + 0x0000, /* R19272 */ + 0x0000, /* R19273 */ + 0x0000, /* R19274 */ + 0x0000, /* R19275 */ + 0x0000, /* R19276 */ + 0x0000, /* R19277 */ + 0x0000, /* R19278 */ + 0x0000, /* R19279 */ + 0x0000, /* R19280 */ + 0x0000, /* R19281 */ + 0x0000, /* R19282 */ + 0x0000, /* R19283 */ + 0x0000, /* R19284 */ + 0x0000, /* R19285 */ + 0x0000, /* R19286 */ + 0x0000, /* R19287 */ + 0x0000, /* R19288 */ + 0x0000, /* R19289 */ + 0x0000, /* R19290 */ + 0x0000, /* R19291 */ + 0x0000, /* R19292 */ + 0x0000, /* R19293 */ + 0x0000, /* R19294 */ + 0x0000, /* R19295 */ + 0x0000, /* R19296 */ + 0x0000, /* R19297 */ + 0x0000, /* R19298 */ + 0x0000, /* R19299 */ + 0x0000, /* R19300 */ + 0x0000, /* R19301 */ + 0x0000, /* R19302 */ + 0x0000, /* R19303 */ + 0x0000, /* R19304 */ + 0x0000, /* R19305 */ + 0x0000, /* R19306 */ + 0x0000, /* R19307 */ + 0x0000, /* R19308 */ + 0x0000, /* R19309 */ + 0x0000, /* R19310 */ + 0x0000, /* R19311 */ + 0x0000, /* R19312 */ + 0x0000, /* R19313 */ + 0x0000, /* R19314 */ + 0x0000, /* R19315 */ + 0x0000, /* R19316 */ + 0x0000, /* R19317 */ + 0x0000, /* R19318 */ + 0x0000, /* R19319 */ + 0x0000, /* R19320 */ + 0x0000, /* R19321 */ + 0x0000, /* R19322 */ + 0x0000, /* R19323 */ + 0x0000, /* R19324 */ + 0x0000, /* R19325 */ + 0x0000, /* R19326 */ + 0x0000, /* R19327 */ + 0x0000, /* R19328 */ + 0x0000, /* R19329 */ + 0x0000, /* R19330 */ + 0x0000, /* R19331 */ + 0x0000, /* R19332 */ + 0x0000, /* R19333 */ + 0x0000, /* R19334 */ + 0x0000, /* R19335 */ + 0x0000, /* R19336 */ + 0x0000, /* R19337 */ + 0x0000, /* R19338 */ + 0x0000, /* R19339 */ + 0x0000, /* R19340 */ + 0x0000, /* R19341 */ + 0x0000, /* R19342 */ + 0x0000, /* R19343 */ + 0x0000, /* R19344 */ + 0x0000, /* R19345 */ + 0x0000, /* R19346 */ + 0x0000, /* R19347 */ + 0x0000, /* R19348 */ + 0x0000, /* R19349 */ + 0x0000, /* R19350 */ + 0x0000, /* R19351 */ + 0x0000, /* R19352 */ + 0x0000, /* R19353 */ + 0x0000, /* R19354 */ + 0x0000, /* R19355 */ + 0x0000, /* R19356 */ + 0x0000, /* R19357 */ + 0x0000, /* R19358 */ + 0x0000, /* R19359 */ + 0x0000, /* R19360 */ + 0x0000, /* R19361 */ + 0x0000, /* R19362 */ + 0x0000, /* R19363 */ + 0x0000, /* R19364 */ + 0x0000, /* R19365 */ + 0x0000, /* R19366 */ + 0x0000, /* R19367 */ + 0x0000, /* R19368 */ + 0x0000, /* R19369 */ + 0x0000, /* R19370 */ + 0x0000, /* R19371 */ + 0x0000, /* R19372 */ + 0x0000, /* R19373 */ + 0x0000, /* R19374 */ + 0x0000, /* R19375 */ + 0x0000, /* R19376 */ + 0x0000, /* R19377 */ + 0x0000, /* R19378 */ + 0x0000, /* R19379 */ + 0x0000, /* R19380 */ + 0x0000, /* R19381 */ + 0x0000, /* R19382 */ + 0x0000, /* R19383 */ + 0x0000, /* R19384 */ + 0x0000, /* R19385 */ + 0x0000, /* R19386 */ + 0x0000, /* R19387 */ + 0x0000, /* R19388 */ + 0x0000, /* R19389 */ + 0x0000, /* R19390 */ + 0x0000, /* R19391 */ + 0x0000, /* R19392 */ + 0x0000, /* R19393 */ + 0x0000, /* R19394 */ + 0x0000, /* R19395 */ + 0x0000, /* R19396 */ + 0x0000, /* R19397 */ + 0x0000, /* R19398 */ + 0x0000, /* R19399 */ + 0x0000, /* R19400 */ + 0x0000, /* R19401 */ + 0x0000, /* R19402 */ + 0x0000, /* R19403 */ + 0x0000, /* R19404 */ + 0x0000, /* R19405 */ + 0x0000, /* R19406 */ + 0x0000, /* R19407 */ + 0x0000, /* R19408 */ + 0x0000, /* R19409 */ + 0x0000, /* R19410 */ + 0x0000, /* R19411 */ + 0x0000, /* R19412 */ + 0x0000, /* R19413 */ + 0x0000, /* R19414 */ + 0x0000, /* R19415 */ + 0x0000, /* R19416 */ + 0x0000, /* R19417 */ + 0x0000, /* R19418 */ + 0x0000, /* R19419 */ + 0x0000, /* R19420 */ + 0x0000, /* R19421 */ + 0x0000, /* R19422 */ + 0x0000, /* R19423 */ + 0x0000, /* R19424 */ + 0x0000, /* R19425 */ + 0x0000, /* R19426 */ + 0x0000, /* R19427 */ + 0x0000, /* R19428 */ + 0x0000, /* R19429 */ + 0x0000, /* R19430 */ + 0x0000, /* R19431 */ + 0x0000, /* R19432 */ + 0x0000, /* R19433 */ + 0x0000, /* R19434 */ + 0x0000, /* R19435 */ + 0x0000, /* R19436 */ + 0x0000, /* R19437 */ + 0x0000, /* R19438 */ + 0x0000, /* R19439 */ + 0x0000, /* R19440 */ + 0x0000, /* R19441 */ + 0x0000, /* R19442 */ + 0x0000, /* R19443 */ + 0x0000, /* R19444 */ + 0x0000, /* R19445 */ + 0x0000, /* R19446 */ + 0x0000, /* R19447 */ + 0x0000, /* R19448 */ + 0x0000, /* R19449 */ + 0x0000, /* R19450 */ + 0x0000, /* R19451 */ + 0x0000, /* R19452 */ + 0x0000, /* R19453 */ + 0x0000, /* R19454 */ + 0x0000, /* R19455 */ + 0x007F, /* R19456 - DACL_RETUNE_C1_1 */ + 0xFFFF, /* R19457 - DACL_RETUNE_C1_0 */ + 0x0000, /* R19458 - DACL_RETUNE_C2_1 */ + 0x0000, /* R19459 - DACL_RETUNE_C2_0 */ + 0x0000, /* R19460 - DACL_RETUNE_C3_1 */ + 0x0000, /* R19461 - DACL_RETUNE_C3_0 */ + 0x0000, /* R19462 - DACL_RETUNE_C4_1 */ + 0x0000, /* R19463 - DACL_RETUNE_C4_0 */ + 0x0000, /* R19464 - DACL_RETUNE_C5_1 */ + 0x0000, /* R19465 - DACL_RETUNE_C5_0 */ + 0x0000, /* R19466 - DACL_RETUNE_C6_1 */ + 0x0000, /* R19467 - DACL_RETUNE_C6_0 */ + 0x0000, /* R19468 - DACL_RETUNE_C7_1 */ + 0x0000, /* R19469 - DACL_RETUNE_C7_0 */ + 0x0000, /* R19470 - DACL_RETUNE_C8_1 */ + 0x0000, /* R19471 - DACL_RETUNE_C8_0 */ + 0x0000, /* R19472 - DACL_RETUNE_C9_1 */ + 0x0000, /* R19473 - DACL_RETUNE_C9_0 */ + 0x0000, /* R19474 - DACL_RETUNE_C10_1 */ + 0x0000, /* R19475 - DACL_RETUNE_C10_0 */ + 0x0000, /* R19476 - DACL_RETUNE_C11_1 */ + 0x0000, /* R19477 - DACL_RETUNE_C11_0 */ + 0x0000, /* R19478 - DACL_RETUNE_C12_1 */ + 0x0000, /* R19479 - DACL_RETUNE_C12_0 */ + 0x0000, /* R19480 - DACL_RETUNE_C13_1 */ + 0x0000, /* R19481 - DACL_RETUNE_C13_0 */ + 0x0000, /* R19482 - DACL_RETUNE_C14_1 */ + 0x0000, /* R19483 - DACL_RETUNE_C14_0 */ + 0x0000, /* R19484 - DACL_RETUNE_C15_1 */ + 0x0000, /* R19485 - DACL_RETUNE_C15_0 */ + 0x0000, /* R19486 - DACL_RETUNE_C16_1 */ + 0x0000, /* R19487 - DACL_RETUNE_C16_0 */ + 0x0000, /* R19488 - DACL_RETUNE_C17_1 */ + 0x0000, /* R19489 - DACL_RETUNE_C17_0 */ + 0x0000, /* R19490 - DACL_RETUNE_C18_1 */ + 0x0000, /* R19491 - DACL_RETUNE_C18_0 */ + 0x0000, /* R19492 - DACL_RETUNE_C19_1 */ + 0x0000, /* R19493 - DACL_RETUNE_C19_0 */ + 0x0000, /* R19494 - DACL_RETUNE_C20_1 */ + 0x0000, /* R19495 - DACL_RETUNE_C20_0 */ + 0x0000, /* R19496 - DACL_RETUNE_C21_1 */ + 0x0000, /* R19497 - DACL_RETUNE_C21_0 */ + 0x0000, /* R19498 - DACL_RETUNE_C22_1 */ + 0x0000, /* R19499 - DACL_RETUNE_C22_0 */ + 0x0000, /* R19500 - DACL_RETUNE_C23_1 */ + 0x0000, /* R19501 - DACL_RETUNE_C23_0 */ + 0x0000, /* R19502 - DACL_RETUNE_C24_1 */ + 0x0000, /* R19503 - DACL_RETUNE_C24_0 */ + 0x0000, /* R19504 - DACL_RETUNE_C25_1 */ + 0x0000, /* R19505 - DACL_RETUNE_C25_0 */ + 0x0000, /* R19506 - DACL_RETUNE_C26_1 */ + 0x0000, /* R19507 - DACL_RETUNE_C26_0 */ + 0x0000, /* R19508 - DACL_RETUNE_C27_1 */ + 0x0000, /* R19509 - DACL_RETUNE_C27_0 */ + 0x0000, /* R19510 - DACL_RETUNE_C28_1 */ + 0x0000, /* R19511 - DACL_RETUNE_C28_0 */ + 0x0000, /* R19512 - DACL_RETUNE_C29_1 */ + 0x0000, /* R19513 - DACL_RETUNE_C29_0 */ + 0x0000, /* R19514 - DACL_RETUNE_C30_1 */ + 0x0000, /* R19515 - DACL_RETUNE_C30_0 */ + 0x0000, /* R19516 - DACL_RETUNE_C31_1 */ + 0x0000, /* R19517 - DACL_RETUNE_C31_0 */ + 0x0000, /* R19518 - DACL_RETUNE_C32_1 */ + 0x0000, /* R19519 - DACL_RETUNE_C32_0 */ + 0x0000, /* R19520 */ + 0x0000, /* R19521 */ + 0x0000, /* R19522 */ + 0x0000, /* R19523 */ + 0x0000, /* R19524 */ + 0x0000, /* R19525 */ + 0x0000, /* R19526 */ + 0x0000, /* R19527 */ + 0x0000, /* R19528 */ + 0x0000, /* R19529 */ + 0x0000, /* R19530 */ + 0x0000, /* R19531 */ + 0x0000, /* R19532 */ + 0x0000, /* R19533 */ + 0x0000, /* R19534 */ + 0x0000, /* R19535 */ + 0x0000, /* R19536 */ + 0x0000, /* R19537 */ + 0x0000, /* R19538 */ + 0x0000, /* R19539 */ + 0x0000, /* R19540 */ + 0x0000, /* R19541 */ + 0x0000, /* R19542 */ + 0x0000, /* R19543 */ + 0x0000, /* R19544 */ + 0x0000, /* R19545 */ + 0x0000, /* R19546 */ + 0x0000, /* R19547 */ + 0x0000, /* R19548 */ + 0x0000, /* R19549 */ + 0x0000, /* R19550 */ + 0x0000, /* R19551 */ + 0x0000, /* R19552 */ + 0x0000, /* R19553 */ + 0x0000, /* R19554 */ + 0x0000, /* R19555 */ + 0x0000, /* R19556 */ + 0x0000, /* R19557 */ + 0x0000, /* R19558 */ + 0x0000, /* R19559 */ + 0x0000, /* R19560 */ + 0x0000, /* R19561 */ + 0x0000, /* R19562 */ + 0x0000, /* R19563 */ + 0x0000, /* R19564 */ + 0x0000, /* R19565 */ + 0x0000, /* R19566 */ + 0x0000, /* R19567 */ + 0x0000, /* R19568 */ + 0x0000, /* R19569 */ + 0x0000, /* R19570 */ + 0x0000, /* R19571 */ + 0x0000, /* R19572 */ + 0x0000, /* R19573 */ + 0x0000, /* R19574 */ + 0x0000, /* R19575 */ + 0x0000, /* R19576 */ + 0x0000, /* R19577 */ + 0x0000, /* R19578 */ + 0x0000, /* R19579 */ + 0x0000, /* R19580 */ + 0x0000, /* R19581 */ + 0x0000, /* R19582 */ + 0x0000, /* R19583 */ + 0x0000, /* R19584 */ + 0x0000, /* R19585 */ + 0x0000, /* R19586 */ + 0x0000, /* R19587 */ + 0x0000, /* R19588 */ + 0x0000, /* R19589 */ + 0x0000, /* R19590 */ + 0x0000, /* R19591 */ + 0x0000, /* R19592 */ + 0x0000, /* R19593 */ + 0x0000, /* R19594 */ + 0x0000, /* R19595 */ + 0x0000, /* R19596 */ + 0x0000, /* R19597 */ + 0x0000, /* R19598 */ + 0x0000, /* R19599 */ + 0x0000, /* R19600 */ + 0x0000, /* R19601 */ + 0x0000, /* R19602 */ + 0x0000, /* R19603 */ + 0x0000, /* R19604 */ + 0x0000, /* R19605 */ + 0x0000, /* R19606 */ + 0x0000, /* R19607 */ + 0x0000, /* R19608 */ + 0x0000, /* R19609 */ + 0x0000, /* R19610 */ + 0x0000, /* R19611 */ + 0x0000, /* R19612 */ + 0x0000, /* R19613 */ + 0x0000, /* R19614 */ + 0x0000, /* R19615 */ + 0x0000, /* R19616 */ + 0x0000, /* R19617 */ + 0x0000, /* R19618 */ + 0x0000, /* R19619 */ + 0x0000, /* R19620 */ + 0x0000, /* R19621 */ + 0x0000, /* R19622 */ + 0x0000, /* R19623 */ + 0x0000, /* R19624 */ + 0x0000, /* R19625 */ + 0x0000, /* R19626 */ + 0x0000, /* R19627 */ + 0x0000, /* R19628 */ + 0x0000, /* R19629 */ + 0x0000, /* R19630 */ + 0x0000, /* R19631 */ + 0x0000, /* R19632 */ + 0x0000, /* R19633 */ + 0x0000, /* R19634 */ + 0x0000, /* R19635 */ + 0x0000, /* R19636 */ + 0x0000, /* R19637 */ + 0x0000, /* R19638 */ + 0x0000, /* R19639 */ + 0x0000, /* R19640 */ + 0x0000, /* R19641 */ + 0x0000, /* R19642 */ + 0x0000, /* R19643 */ + 0x0000, /* R19644 */ + 0x0000, /* R19645 */ + 0x0000, /* R19646 */ + 0x0000, /* R19647 */ + 0x0000, /* R19648 */ + 0x0000, /* R19649 */ + 0x0000, /* R19650 */ + 0x0000, /* R19651 */ + 0x0000, /* R19652 */ + 0x0000, /* R19653 */ + 0x0000, /* R19654 */ + 0x0000, /* R19655 */ + 0x0000, /* R19656 */ + 0x0000, /* R19657 */ + 0x0000, /* R19658 */ + 0x0000, /* R19659 */ + 0x0000, /* R19660 */ + 0x0000, /* R19661 */ + 0x0000, /* R19662 */ + 0x0000, /* R19663 */ + 0x0000, /* R19664 */ + 0x0000, /* R19665 */ + 0x0000, /* R19666 */ + 0x0000, /* R19667 */ + 0x0000, /* R19668 */ + 0x0000, /* R19669 */ + 0x0000, /* R19670 */ + 0x0000, /* R19671 */ + 0x0000, /* R19672 */ + 0x0000, /* R19673 */ + 0x0000, /* R19674 */ + 0x0000, /* R19675 */ + 0x0000, /* R19676 */ + 0x0000, /* R19677 */ + 0x0000, /* R19678 */ + 0x0000, /* R19679 */ + 0x0000, /* R19680 */ + 0x0000, /* R19681 */ + 0x0000, /* R19682 */ + 0x0000, /* R19683 */ + 0x0000, /* R19684 */ + 0x0000, /* R19685 */ + 0x0000, /* R19686 */ + 0x0000, /* R19687 */ + 0x0000, /* R19688 */ + 0x0000, /* R19689 */ + 0x0000, /* R19690 */ + 0x0000, /* R19691 */ + 0x0000, /* R19692 */ + 0x0000, /* R19693 */ + 0x0000, /* R19694 */ + 0x0000, /* R19695 */ + 0x0000, /* R19696 */ + 0x0000, /* R19697 */ + 0x0000, /* R19698 */ + 0x0000, /* R19699 */ + 0x0000, /* R19700 */ + 0x0000, /* R19701 */ + 0x0000, /* R19702 */ + 0x0000, /* R19703 */ + 0x0000, /* R19704 */ + 0x0000, /* R19705 */ + 0x0000, /* R19706 */ + 0x0000, /* R19707 */ + 0x0000, /* R19708 */ + 0x0000, /* R19709 */ + 0x0000, /* R19710 */ + 0x0000, /* R19711 */ + 0x0000, /* R19712 */ + 0x0000, /* R19713 */ + 0x0000, /* R19714 */ + 0x0000, /* R19715 */ + 0x0000, /* R19716 */ + 0x0000, /* R19717 */ + 0x0000, /* R19718 */ + 0x0000, /* R19719 */ + 0x0000, /* R19720 */ + 0x0000, /* R19721 */ + 0x0000, /* R19722 */ + 0x0000, /* R19723 */ + 0x0000, /* R19724 */ + 0x0000, /* R19725 */ + 0x0000, /* R19726 */ + 0x0000, /* R19727 */ + 0x0000, /* R19728 */ + 0x0000, /* R19729 */ + 0x0000, /* R19730 */ + 0x0000, /* R19731 */ + 0x0000, /* R19732 */ + 0x0000, /* R19733 */ + 0x0000, /* R19734 */ + 0x0000, /* R19735 */ + 0x0000, /* R19736 */ + 0x0000, /* R19737 */ + 0x0000, /* R19738 */ + 0x0000, /* R19739 */ + 0x0000, /* R19740 */ + 0x0000, /* R19741 */ + 0x0000, /* R19742 */ + 0x0000, /* R19743 */ + 0x0000, /* R19744 */ + 0x0000, /* R19745 */ + 0x0000, /* R19746 */ + 0x0000, /* R19747 */ + 0x0000, /* R19748 */ + 0x0000, /* R19749 */ + 0x0000, /* R19750 */ + 0x0000, /* R19751 */ + 0x0000, /* R19752 */ + 0x0000, /* R19753 */ + 0x0000, /* R19754 */ + 0x0000, /* R19755 */ + 0x0000, /* R19756 */ + 0x0000, /* R19757 */ + 0x0000, /* R19758 */ + 0x0000, /* R19759 */ + 0x0000, /* R19760 */ + 0x0000, /* R19761 */ + 0x0000, /* R19762 */ + 0x0000, /* R19763 */ + 0x0000, /* R19764 */ + 0x0000, /* R19765 */ + 0x0000, /* R19766 */ + 0x0000, /* R19767 */ + 0x0000, /* R19768 */ + 0x0000, /* R19769 */ + 0x0000, /* R19770 */ + 0x0000, /* R19771 */ + 0x0000, /* R19772 */ + 0x0000, /* R19773 */ + 0x0000, /* R19774 */ + 0x0000, /* R19775 */ + 0x0000, /* R19776 */ + 0x0000, /* R19777 */ + 0x0000, /* R19778 */ + 0x0000, /* R19779 */ + 0x0000, /* R19780 */ + 0x0000, /* R19781 */ + 0x0000, /* R19782 */ + 0x0000, /* R19783 */ + 0x0000, /* R19784 */ + 0x0000, /* R19785 */ + 0x0000, /* R19786 */ + 0x0000, /* R19787 */ + 0x0000, /* R19788 */ + 0x0000, /* R19789 */ + 0x0000, /* R19790 */ + 0x0000, /* R19791 */ + 0x0000, /* R19792 */ + 0x0000, /* R19793 */ + 0x0000, /* R19794 */ + 0x0000, /* R19795 */ + 0x0000, /* R19796 */ + 0x0000, /* R19797 */ + 0x0000, /* R19798 */ + 0x0000, /* R19799 */ + 0x0000, /* R19800 */ + 0x0000, /* R19801 */ + 0x0000, /* R19802 */ + 0x0000, /* R19803 */ + 0x0000, /* R19804 */ + 0x0000, /* R19805 */ + 0x0000, /* R19806 */ + 0x0000, /* R19807 */ + 0x0000, /* R19808 */ + 0x0000, /* R19809 */ + 0x0000, /* R19810 */ + 0x0000, /* R19811 */ + 0x0000, /* R19812 */ + 0x0000, /* R19813 */ + 0x0000, /* R19814 */ + 0x0000, /* R19815 */ + 0x0000, /* R19816 */ + 0x0000, /* R19817 */ + 0x0000, /* R19818 */ + 0x0000, /* R19819 */ + 0x0000, /* R19820 */ + 0x0000, /* R19821 */ + 0x0000, /* R19822 */ + 0x0000, /* R19823 */ + 0x0000, /* R19824 */ + 0x0000, /* R19825 */ + 0x0000, /* R19826 */ + 0x0000, /* R19827 */ + 0x0000, /* R19828 */ + 0x0000, /* R19829 */ + 0x0000, /* R19830 */ + 0x0000, /* R19831 */ + 0x0000, /* R19832 */ + 0x0000, /* R19833 */ + 0x0000, /* R19834 */ + 0x0000, /* R19835 */ + 0x0000, /* R19836 */ + 0x0000, /* R19837 */ + 0x0000, /* R19838 */ + 0x0000, /* R19839 */ + 0x0000, /* R19840 */ + 0x0000, /* R19841 */ + 0x0000, /* R19842 */ + 0x0000, /* R19843 */ + 0x0000, /* R19844 */ + 0x0000, /* R19845 */ + 0x0000, /* R19846 */ + 0x0000, /* R19847 */ + 0x0000, /* R19848 */ + 0x0000, /* R19849 */ + 0x0000, /* R19850 */ + 0x0000, /* R19851 */ + 0x0000, /* R19852 */ + 0x0000, /* R19853 */ + 0x0000, /* R19854 */ + 0x0000, /* R19855 */ + 0x0000, /* R19856 */ + 0x0000, /* R19857 */ + 0x0000, /* R19858 */ + 0x0000, /* R19859 */ + 0x0000, /* R19860 */ + 0x0000, /* R19861 */ + 0x0000, /* R19862 */ + 0x0000, /* R19863 */ + 0x0000, /* R19864 */ + 0x0000, /* R19865 */ + 0x0000, /* R19866 */ + 0x0000, /* R19867 */ + 0x0000, /* R19868 */ + 0x0000, /* R19869 */ + 0x0000, /* R19870 */ + 0x0000, /* R19871 */ + 0x0000, /* R19872 */ + 0x0000, /* R19873 */ + 0x0000, /* R19874 */ + 0x0000, /* R19875 */ + 0x0000, /* R19876 */ + 0x0000, /* R19877 */ + 0x0000, /* R19878 */ + 0x0000, /* R19879 */ + 0x0000, /* R19880 */ + 0x0000, /* R19881 */ + 0x0000, /* R19882 */ + 0x0000, /* R19883 */ + 0x0000, /* R19884 */ + 0x0000, /* R19885 */ + 0x0000, /* R19886 */ + 0x0000, /* R19887 */ + 0x0000, /* R19888 */ + 0x0000, /* R19889 */ + 0x0000, /* R19890 */ + 0x0000, /* R19891 */ + 0x0000, /* R19892 */ + 0x0000, /* R19893 */ + 0x0000, /* R19894 */ + 0x0000, /* R19895 */ + 0x0000, /* R19896 */ + 0x0000, /* R19897 */ + 0x0000, /* R19898 */ + 0x0000, /* R19899 */ + 0x0000, /* R19900 */ + 0x0000, /* R19901 */ + 0x0000, /* R19902 */ + 0x0000, /* R19903 */ + 0x0000, /* R19904 */ + 0x0000, /* R19905 */ + 0x0000, /* R19906 */ + 0x0000, /* R19907 */ + 0x0000, /* R19908 */ + 0x0000, /* R19909 */ + 0x0000, /* R19910 */ + 0x0000, /* R19911 */ + 0x0000, /* R19912 */ + 0x0000, /* R19913 */ + 0x0000, /* R19914 */ + 0x0000, /* R19915 */ + 0x0000, /* R19916 */ + 0x0000, /* R19917 */ + 0x0000, /* R19918 */ + 0x0000, /* R19919 */ + 0x0000, /* R19920 */ + 0x0000, /* R19921 */ + 0x0000, /* R19922 */ + 0x0000, /* R19923 */ + 0x0000, /* R19924 */ + 0x0000, /* R19925 */ + 0x0000, /* R19926 */ + 0x0000, /* R19927 */ + 0x0000, /* R19928 */ + 0x0000, /* R19929 */ + 0x0000, /* R19930 */ + 0x0000, /* R19931 */ + 0x0000, /* R19932 */ + 0x0000, /* R19933 */ + 0x0000, /* R19934 */ + 0x0000, /* R19935 */ + 0x0000, /* R19936 */ + 0x0000, /* R19937 */ + 0x0000, /* R19938 */ + 0x0000, /* R19939 */ + 0x0000, /* R19940 */ + 0x0000, /* R19941 */ + 0x0000, /* R19942 */ + 0x0000, /* R19943 */ + 0x0000, /* R19944 */ + 0x0000, /* R19945 */ + 0x0000, /* R19946 */ + 0x0000, /* R19947 */ + 0x0000, /* R19948 */ + 0x0000, /* R19949 */ + 0x0000, /* R19950 */ + 0x0000, /* R19951 */ + 0x0000, /* R19952 */ + 0x0000, /* R19953 */ + 0x0000, /* R19954 */ + 0x0000, /* R19955 */ + 0x0000, /* R19956 */ + 0x0000, /* R19957 */ + 0x0000, /* R19958 */ + 0x0000, /* R19959 */ + 0x0000, /* R19960 */ + 0x0000, /* R19961 */ + 0x0000, /* R19962 */ + 0x0000, /* R19963 */ + 0x0000, /* R19964 */ + 0x0000, /* R19965 */ + 0x0000, /* R19966 */ + 0x0000, /* R19967 */ + 0x0020, /* R19968 - RETUNEDAC_PG2_1 */ + 0x0000, /* R19969 - RETUNEDAC_PG2_0 */ + 0x0040, /* R19970 - RETUNEDAC_PG_1 */ + 0x0000, /* R19971 - RETUNEDAC_PG_0 */ + 0x0000, /* R19972 */ + 0x0000, /* R19973 */ + 0x0000, /* R19974 */ + 0x0000, /* R19975 */ + 0x0000, /* R19976 */ + 0x0000, /* R19977 */ + 0x0000, /* R19978 */ + 0x0000, /* R19979 */ + 0x0000, /* R19980 */ + 0x0000, /* R19981 */ + 0x0000, /* R19982 */ + 0x0000, /* R19983 */ + 0x0000, /* R19984 */ + 0x0000, /* R19985 */ + 0x0000, /* R19986 */ + 0x0000, /* R19987 */ + 0x0000, /* R19988 */ + 0x0000, /* R19989 */ + 0x0000, /* R19990 */ + 0x0000, /* R19991 */ + 0x0000, /* R19992 */ + 0x0000, /* R19993 */ + 0x0000, /* R19994 */ + 0x0000, /* R19995 */ + 0x0000, /* R19996 */ + 0x0000, /* R19997 */ + 0x0000, /* R19998 */ + 0x0000, /* R19999 */ + 0x0000, /* R20000 */ + 0x0000, /* R20001 */ + 0x0000, /* R20002 */ + 0x0000, /* R20003 */ + 0x0000, /* R20004 */ + 0x0000, /* R20005 */ + 0x0000, /* R20006 */ + 0x0000, /* R20007 */ + 0x0000, /* R20008 */ + 0x0000, /* R20009 */ + 0x0000, /* R20010 */ + 0x0000, /* R20011 */ + 0x0000, /* R20012 */ + 0x0000, /* R20013 */ + 0x0000, /* R20014 */ + 0x0000, /* R20015 */ + 0x0000, /* R20016 */ + 0x0000, /* R20017 */ + 0x0000, /* R20018 */ + 0x0000, /* R20019 */ + 0x0000, /* R20020 */ + 0x0000, /* R20021 */ + 0x0000, /* R20022 */ + 0x0000, /* R20023 */ + 0x0000, /* R20024 */ + 0x0000, /* R20025 */ + 0x0000, /* R20026 */ + 0x0000, /* R20027 */ + 0x0000, /* R20028 */ + 0x0000, /* R20029 */ + 0x0000, /* R20030 */ + 0x0000, /* R20031 */ + 0x0000, /* R20032 */ + 0x0000, /* R20033 */ + 0x0000, /* R20034 */ + 0x0000, /* R20035 */ + 0x0000, /* R20036 */ + 0x0000, /* R20037 */ + 0x0000, /* R20038 */ + 0x0000, /* R20039 */ + 0x0000, /* R20040 */ + 0x0000, /* R20041 */ + 0x0000, /* R20042 */ + 0x0000, /* R20043 */ + 0x0000, /* R20044 */ + 0x0000, /* R20045 */ + 0x0000, /* R20046 */ + 0x0000, /* R20047 */ + 0x0000, /* R20048 */ + 0x0000, /* R20049 */ + 0x0000, /* R20050 */ + 0x0000, /* R20051 */ + 0x0000, /* R20052 */ + 0x0000, /* R20053 */ + 0x0000, /* R20054 */ + 0x0000, /* R20055 */ + 0x0000, /* R20056 */ + 0x0000, /* R20057 */ + 0x0000, /* R20058 */ + 0x0000, /* R20059 */ + 0x0000, /* R20060 */ + 0x0000, /* R20061 */ + 0x0000, /* R20062 */ + 0x0000, /* R20063 */ + 0x0000, /* R20064 */ + 0x0000, /* R20065 */ + 0x0000, /* R20066 */ + 0x0000, /* R20067 */ + 0x0000, /* R20068 */ + 0x0000, /* R20069 */ + 0x0000, /* R20070 */ + 0x0000, /* R20071 */ + 0x0000, /* R20072 */ + 0x0000, /* R20073 */ + 0x0000, /* R20074 */ + 0x0000, /* R20075 */ + 0x0000, /* R20076 */ + 0x0000, /* R20077 */ + 0x0000, /* R20078 */ + 0x0000, /* R20079 */ + 0x0000, /* R20080 */ + 0x0000, /* R20081 */ + 0x0000, /* R20082 */ + 0x0000, /* R20083 */ + 0x0000, /* R20084 */ + 0x0000, /* R20085 */ + 0x0000, /* R20086 */ + 0x0000, /* R20087 */ + 0x0000, /* R20088 */ + 0x0000, /* R20089 */ + 0x0000, /* R20090 */ + 0x0000, /* R20091 */ + 0x0000, /* R20092 */ + 0x0000, /* R20093 */ + 0x0000, /* R20094 */ + 0x0000, /* R20095 */ + 0x0000, /* R20096 */ + 0x0000, /* R20097 */ + 0x0000, /* R20098 */ + 0x0000, /* R20099 */ + 0x0000, /* R20100 */ + 0x0000, /* R20101 */ + 0x0000, /* R20102 */ + 0x0000, /* R20103 */ + 0x0000, /* R20104 */ + 0x0000, /* R20105 */ + 0x0000, /* R20106 */ + 0x0000, /* R20107 */ + 0x0000, /* R20108 */ + 0x0000, /* R20109 */ + 0x0000, /* R20110 */ + 0x0000, /* R20111 */ + 0x0000, /* R20112 */ + 0x0000, /* R20113 */ + 0x0000, /* R20114 */ + 0x0000, /* R20115 */ + 0x0000, /* R20116 */ + 0x0000, /* R20117 */ + 0x0000, /* R20118 */ + 0x0000, /* R20119 */ + 0x0000, /* R20120 */ + 0x0000, /* R20121 */ + 0x0000, /* R20122 */ + 0x0000, /* R20123 */ + 0x0000, /* R20124 */ + 0x0000, /* R20125 */ + 0x0000, /* R20126 */ + 0x0000, /* R20127 */ + 0x0000, /* R20128 */ + 0x0000, /* R20129 */ + 0x0000, /* R20130 */ + 0x0000, /* R20131 */ + 0x0000, /* R20132 */ + 0x0000, /* R20133 */ + 0x0000, /* R20134 */ + 0x0000, /* R20135 */ + 0x0000, /* R20136 */ + 0x0000, /* R20137 */ + 0x0000, /* R20138 */ + 0x0000, /* R20139 */ + 0x0000, /* R20140 */ + 0x0000, /* R20141 */ + 0x0000, /* R20142 */ + 0x0000, /* R20143 */ + 0x0000, /* R20144 */ + 0x0000, /* R20145 */ + 0x0000, /* R20146 */ + 0x0000, /* R20147 */ + 0x0000, /* R20148 */ + 0x0000, /* R20149 */ + 0x0000, /* R20150 */ + 0x0000, /* R20151 */ + 0x0000, /* R20152 */ + 0x0000, /* R20153 */ + 0x0000, /* R20154 */ + 0x0000, /* R20155 */ + 0x0000, /* R20156 */ + 0x0000, /* R20157 */ + 0x0000, /* R20158 */ + 0x0000, /* R20159 */ + 0x0000, /* R20160 */ + 0x0000, /* R20161 */ + 0x0000, /* R20162 */ + 0x0000, /* R20163 */ + 0x0000, /* R20164 */ + 0x0000, /* R20165 */ + 0x0000, /* R20166 */ + 0x0000, /* R20167 */ + 0x0000, /* R20168 */ + 0x0000, /* R20169 */ + 0x0000, /* R20170 */ + 0x0000, /* R20171 */ + 0x0000, /* R20172 */ + 0x0000, /* R20173 */ + 0x0000, /* R20174 */ + 0x0000, /* R20175 */ + 0x0000, /* R20176 */ + 0x0000, /* R20177 */ + 0x0000, /* R20178 */ + 0x0000, /* R20179 */ + 0x0000, /* R20180 */ + 0x0000, /* R20181 */ + 0x0000, /* R20182 */ + 0x0000, /* R20183 */ + 0x0000, /* R20184 */ + 0x0000, /* R20185 */ + 0x0000, /* R20186 */ + 0x0000, /* R20187 */ + 0x0000, /* R20188 */ + 0x0000, /* R20189 */ + 0x0000, /* R20190 */ + 0x0000, /* R20191 */ + 0x0000, /* R20192 */ + 0x0000, /* R20193 */ + 0x0000, /* R20194 */ + 0x0000, /* R20195 */ + 0x0000, /* R20196 */ + 0x0000, /* R20197 */ + 0x0000, /* R20198 */ + 0x0000, /* R20199 */ + 0x0000, /* R20200 */ + 0x0000, /* R20201 */ + 0x0000, /* R20202 */ + 0x0000, /* R20203 */ + 0x0000, /* R20204 */ + 0x0000, /* R20205 */ + 0x0000, /* R20206 */ + 0x0000, /* R20207 */ + 0x0000, /* R20208 */ + 0x0000, /* R20209 */ + 0x0000, /* R20210 */ + 0x0000, /* R20211 */ + 0x0000, /* R20212 */ + 0x0000, /* R20213 */ + 0x0000, /* R20214 */ + 0x0000, /* R20215 */ + 0x0000, /* R20216 */ + 0x0000, /* R20217 */ + 0x0000, /* R20218 */ + 0x0000, /* R20219 */ + 0x0000, /* R20220 */ + 0x0000, /* R20221 */ + 0x0000, /* R20222 */ + 0x0000, /* R20223 */ + 0x0000, /* R20224 */ + 0x0000, /* R20225 */ + 0x0000, /* R20226 */ + 0x0000, /* R20227 */ + 0x0000, /* R20228 */ + 0x0000, /* R20229 */ + 0x0000, /* R20230 */ + 0x0000, /* R20231 */ + 0x0000, /* R20232 */ + 0x0000, /* R20233 */ + 0x0000, /* R20234 */ + 0x0000, /* R20235 */ + 0x0000, /* R20236 */ + 0x0000, /* R20237 */ + 0x0000, /* R20238 */ + 0x0000, /* R20239 */ + 0x0000, /* R20240 */ + 0x0000, /* R20241 */ + 0x0000, /* R20242 */ + 0x0000, /* R20243 */ + 0x0000, /* R20244 */ + 0x0000, /* R20245 */ + 0x0000, /* R20246 */ + 0x0000, /* R20247 */ + 0x0000, /* R20248 */ + 0x0000, /* R20249 */ + 0x0000, /* R20250 */ + 0x0000, /* R20251 */ + 0x0000, /* R20252 */ + 0x0000, /* R20253 */ + 0x0000, /* R20254 */ + 0x0000, /* R20255 */ + 0x0000, /* R20256 */ + 0x0000, /* R20257 */ + 0x0000, /* R20258 */ + 0x0000, /* R20259 */ + 0x0000, /* R20260 */ + 0x0000, /* R20261 */ + 0x0000, /* R20262 */ + 0x0000, /* R20263 */ + 0x0000, /* R20264 */ + 0x0000, /* R20265 */ + 0x0000, /* R20266 */ + 0x0000, /* R20267 */ + 0x0000, /* R20268 */ + 0x0000, /* R20269 */ + 0x0000, /* R20270 */ + 0x0000, /* R20271 */ + 0x0000, /* R20272 */ + 0x0000, /* R20273 */ + 0x0000, /* R20274 */ + 0x0000, /* R20275 */ + 0x0000, /* R20276 */ + 0x0000, /* R20277 */ + 0x0000, /* R20278 */ + 0x0000, /* R20279 */ + 0x0000, /* R20280 */ + 0x0000, /* R20281 */ + 0x0000, /* R20282 */ + 0x0000, /* R20283 */ + 0x0000, /* R20284 */ + 0x0000, /* R20285 */ + 0x0000, /* R20286 */ + 0x0000, /* R20287 */ + 0x0000, /* R20288 */ + 0x0000, /* R20289 */ + 0x0000, /* R20290 */ + 0x0000, /* R20291 */ + 0x0000, /* R20292 */ + 0x0000, /* R20293 */ + 0x0000, /* R20294 */ + 0x0000, /* R20295 */ + 0x0000, /* R20296 */ + 0x0000, /* R20297 */ + 0x0000, /* R20298 */ + 0x0000, /* R20299 */ + 0x0000, /* R20300 */ + 0x0000, /* R20301 */ + 0x0000, /* R20302 */ + 0x0000, /* R20303 */ + 0x0000, /* R20304 */ + 0x0000, /* R20305 */ + 0x0000, /* R20306 */ + 0x0000, /* R20307 */ + 0x0000, /* R20308 */ + 0x0000, /* R20309 */ + 0x0000, /* R20310 */ + 0x0000, /* R20311 */ + 0x0000, /* R20312 */ + 0x0000, /* R20313 */ + 0x0000, /* R20314 */ + 0x0000, /* R20315 */ + 0x0000, /* R20316 */ + 0x0000, /* R20317 */ + 0x0000, /* R20318 */ + 0x0000, /* R20319 */ + 0x0000, /* R20320 */ + 0x0000, /* R20321 */ + 0x0000, /* R20322 */ + 0x0000, /* R20323 */ + 0x0000, /* R20324 */ + 0x0000, /* R20325 */ + 0x0000, /* R20326 */ + 0x0000, /* R20327 */ + 0x0000, /* R20328 */ + 0x0000, /* R20329 */ + 0x0000, /* R20330 */ + 0x0000, /* R20331 */ + 0x0000, /* R20332 */ + 0x0000, /* R20333 */ + 0x0000, /* R20334 */ + 0x0000, /* R20335 */ + 0x0000, /* R20336 */ + 0x0000, /* R20337 */ + 0x0000, /* R20338 */ + 0x0000, /* R20339 */ + 0x0000, /* R20340 */ + 0x0000, /* R20341 */ + 0x0000, /* R20342 */ + 0x0000, /* R20343 */ + 0x0000, /* R20344 */ + 0x0000, /* R20345 */ + 0x0000, /* R20346 */ + 0x0000, /* R20347 */ + 0x0000, /* R20348 */ + 0x0000, /* R20349 */ + 0x0000, /* R20350 */ + 0x0000, /* R20351 */ + 0x0000, /* R20352 */ + 0x0000, /* R20353 */ + 0x0000, /* R20354 */ + 0x0000, /* R20355 */ + 0x0000, /* R20356 */ + 0x0000, /* R20357 */ + 0x0000, /* R20358 */ + 0x0000, /* R20359 */ + 0x0000, /* R20360 */ + 0x0000, /* R20361 */ + 0x0000, /* R20362 */ + 0x0000, /* R20363 */ + 0x0000, /* R20364 */ + 0x0000, /* R20365 */ + 0x0000, /* R20366 */ + 0x0000, /* R20367 */ + 0x0000, /* R20368 */ + 0x0000, /* R20369 */ + 0x0000, /* R20370 */ + 0x0000, /* R20371 */ + 0x0000, /* R20372 */ + 0x0000, /* R20373 */ + 0x0000, /* R20374 */ + 0x0000, /* R20375 */ + 0x0000, /* R20376 */ + 0x0000, /* R20377 */ + 0x0000, /* R20378 */ + 0x0000, /* R20379 */ + 0x0000, /* R20380 */ + 0x0000, /* R20381 */ + 0x0000, /* R20382 */ + 0x0000, /* R20383 */ + 0x0000, /* R20384 */ + 0x0000, /* R20385 */ + 0x0000, /* R20386 */ + 0x0000, /* R20387 */ + 0x0000, /* R20388 */ + 0x0000, /* R20389 */ + 0x0000, /* R20390 */ + 0x0000, /* R20391 */ + 0x0000, /* R20392 */ + 0x0000, /* R20393 */ + 0x0000, /* R20394 */ + 0x0000, /* R20395 */ + 0x0000, /* R20396 */ + 0x0000, /* R20397 */ + 0x0000, /* R20398 */ + 0x0000, /* R20399 */ + 0x0000, /* R20400 */ + 0x0000, /* R20401 */ + 0x0000, /* R20402 */ + 0x0000, /* R20403 */ + 0x0000, /* R20404 */ + 0x0000, /* R20405 */ + 0x0000, /* R20406 */ + 0x0000, /* R20407 */ + 0x0000, /* R20408 */ + 0x0000, /* R20409 */ + 0x0000, /* R20410 */ + 0x0000, /* R20411 */ + 0x0000, /* R20412 */ + 0x0000, /* R20413 */ + 0x0000, /* R20414 */ + 0x0000, /* R20415 */ + 0x0000, /* R20416 */ + 0x0000, /* R20417 */ + 0x0000, /* R20418 */ + 0x0000, /* R20419 */ + 0x0000, /* R20420 */ + 0x0000, /* R20421 */ + 0x0000, /* R20422 */ + 0x0000, /* R20423 */ + 0x0000, /* R20424 */ + 0x0000, /* R20425 */ + 0x0000, /* R20426 */ + 0x0000, /* R20427 */ + 0x0000, /* R20428 */ + 0x0000, /* R20429 */ + 0x0000, /* R20430 */ + 0x0000, /* R20431 */ + 0x0000, /* R20432 */ + 0x0000, /* R20433 */ + 0x0000, /* R20434 */ + 0x0000, /* R20435 */ + 0x0000, /* R20436 */ + 0x0000, /* R20437 */ + 0x0000, /* R20438 */ + 0x0000, /* R20439 */ + 0x0000, /* R20440 */ + 0x0000, /* R20441 */ + 0x0000, /* R20442 */ + 0x0000, /* R20443 */ + 0x0000, /* R20444 */ + 0x0000, /* R20445 */ + 0x0000, /* R20446 */ + 0x0000, /* R20447 */ + 0x0000, /* R20448 */ + 0x0000, /* R20449 */ + 0x0000, /* R20450 */ + 0x0000, /* R20451 */ + 0x0000, /* R20452 */ + 0x0000, /* R20453 */ + 0x0000, /* R20454 */ + 0x0000, /* R20455 */ + 0x0000, /* R20456 */ + 0x0000, /* R20457 */ + 0x0000, /* R20458 */ + 0x0000, /* R20459 */ + 0x0000, /* R20460 */ + 0x0000, /* R20461 */ + 0x0000, /* R20462 */ + 0x0000, /* R20463 */ + 0x0000, /* R20464 */ + 0x0000, /* R20465 */ + 0x0000, /* R20466 */ + 0x0000, /* R20467 */ + 0x0000, /* R20468 */ + 0x0000, /* R20469 */ + 0x0000, /* R20470 */ + 0x0000, /* R20471 */ + 0x0000, /* R20472 */ + 0x0000, /* R20473 */ + 0x0000, /* R20474 */ + 0x0000, /* R20475 */ + 0x0000, /* R20476 */ + 0x0000, /* R20477 */ + 0x0000, /* R20478 */ + 0x0000, /* R20479 */ + 0x007F, /* R20480 - DACR_RETUNE_C1_1 */ + 0xFFFF, /* R20481 - DACR_RETUNE_C1_0 */ + 0x0000, /* R20482 - DACR_RETUNE_C2_1 */ + 0x0000, /* R20483 - DACR_RETUNE_C2_0 */ + 0x0000, /* R20484 - DACR_RETUNE_C3_1 */ + 0x0000, /* R20485 - DACR_RETUNE_C3_0 */ + 0x0000, /* R20486 - DACR_RETUNE_C4_1 */ + 0x0000, /* R20487 - DACR_RETUNE_C4_0 */ + 0x0000, /* R20488 - DACR_RETUNE_C5_1 */ + 0x0000, /* R20489 - DACR_RETUNE_C5_0 */ + 0x0000, /* R20490 - DACR_RETUNE_C6_1 */ + 0x0000, /* R20491 - DACR_RETUNE_C6_0 */ + 0x0000, /* R20492 - DACR_RETUNE_C7_1 */ + 0x0000, /* R20493 - DACR_RETUNE_C7_0 */ + 0x0000, /* R20494 - DACR_RETUNE_C8_1 */ + 0x0000, /* R20495 - DACR_RETUNE_C8_0 */ + 0x0000, /* R20496 - DACR_RETUNE_C9_1 */ + 0x0000, /* R20497 - DACR_RETUNE_C9_0 */ + 0x0000, /* R20498 - DACR_RETUNE_C10_1 */ + 0x0000, /* R20499 - DACR_RETUNE_C10_0 */ + 0x0000, /* R20500 - DACR_RETUNE_C11_1 */ + 0x0000, /* R20501 - DACR_RETUNE_C11_0 */ + 0x0000, /* R20502 - DACR_RETUNE_C12_1 */ + 0x0000, /* R20503 - DACR_RETUNE_C12_0 */ + 0x0000, /* R20504 - DACR_RETUNE_C13_1 */ + 0x0000, /* R20505 - DACR_RETUNE_C13_0 */ + 0x0000, /* R20506 - DACR_RETUNE_C14_1 */ + 0x0000, /* R20507 - DACR_RETUNE_C14_0 */ + 0x0000, /* R20508 - DACR_RETUNE_C15_1 */ + 0x0000, /* R20509 - DACR_RETUNE_C15_0 */ + 0x0000, /* R20510 - DACR_RETUNE_C16_1 */ + 0x0000, /* R20511 - DACR_RETUNE_C16_0 */ + 0x0000, /* R20512 - DACR_RETUNE_C17_1 */ + 0x0000, /* R20513 - DACR_RETUNE_C17_0 */ + 0x0000, /* R20514 - DACR_RETUNE_C18_1 */ + 0x0000, /* R20515 - DACR_RETUNE_C18_0 */ + 0x0000, /* R20516 - DACR_RETUNE_C19_1 */ + 0x0000, /* R20517 - DACR_RETUNE_C19_0 */ + 0x0000, /* R20518 - DACR_RETUNE_C20_1 */ + 0x0000, /* R20519 - DACR_RETUNE_C20_0 */ + 0x0000, /* R20520 - DACR_RETUNE_C21_1 */ + 0x0000, /* R20521 - DACR_RETUNE_C21_0 */ + 0x0000, /* R20522 - DACR_RETUNE_C22_1 */ + 0x0000, /* R20523 - DACR_RETUNE_C22_0 */ + 0x0000, /* R20524 - DACR_RETUNE_C23_1 */ + 0x0000, /* R20525 - DACR_RETUNE_C23_0 */ + 0x0000, /* R20526 - DACR_RETUNE_C24_1 */ + 0x0000, /* R20527 - DACR_RETUNE_C24_0 */ + 0x0000, /* R20528 - DACR_RETUNE_C25_1 */ + 0x0000, /* R20529 - DACR_RETUNE_C25_0 */ + 0x0000, /* R20530 - DACR_RETUNE_C26_1 */ + 0x0000, /* R20531 - DACR_RETUNE_C26_0 */ + 0x0000, /* R20532 - DACR_RETUNE_C27_1 */ + 0x0000, /* R20533 - DACR_RETUNE_C27_0 */ + 0x0000, /* R20534 - DACR_RETUNE_C28_1 */ + 0x0000, /* R20535 - DACR_RETUNE_C28_0 */ + 0x0000, /* R20536 - DACR_RETUNE_C29_1 */ + 0x0000, /* R20537 - DACR_RETUNE_C29_0 */ + 0x0000, /* R20538 - DACR_RETUNE_C30_1 */ + 0x0000, /* R20539 - DACR_RETUNE_C30_0 */ + 0x0000, /* R20540 - DACR_RETUNE_C31_1 */ + 0x0000, /* R20541 - DACR_RETUNE_C31_0 */ + 0x0000, /* R20542 - DACR_RETUNE_C32_1 */ + 0x0000, /* R20543 - DACR_RETUNE_C32_0 */ + 0x0000, /* R20544 */ + 0x0000, /* R20545 */ + 0x0000, /* R20546 */ + 0x0000, /* R20547 */ + 0x0000, /* R20548 */ + 0x0000, /* R20549 */ + 0x0000, /* R20550 */ + 0x0000, /* R20551 */ + 0x0000, /* R20552 */ + 0x0000, /* R20553 */ + 0x0000, /* R20554 */ + 0x0000, /* R20555 */ + 0x0000, /* R20556 */ + 0x0000, /* R20557 */ + 0x0000, /* R20558 */ + 0x0000, /* R20559 */ + 0x0000, /* R20560 */ + 0x0000, /* R20561 */ + 0x0000, /* R20562 */ + 0x0000, /* R20563 */ + 0x0000, /* R20564 */ + 0x0000, /* R20565 */ + 0x0000, /* R20566 */ + 0x0000, /* R20567 */ + 0x0000, /* R20568 */ + 0x0000, /* R20569 */ + 0x0000, /* R20570 */ + 0x0000, /* R20571 */ + 0x0000, /* R20572 */ + 0x0000, /* R20573 */ + 0x0000, /* R20574 */ + 0x0000, /* R20575 */ + 0x0000, /* R20576 */ + 0x0000, /* R20577 */ + 0x0000, /* R20578 */ + 0x0000, /* R20579 */ + 0x0000, /* R20580 */ + 0x0000, /* R20581 */ + 0x0000, /* R20582 */ + 0x0000, /* R20583 */ + 0x0000, /* R20584 */ + 0x0000, /* R20585 */ + 0x0000, /* R20586 */ + 0x0000, /* R20587 */ + 0x0000, /* R20588 */ + 0x0000, /* R20589 */ + 0x0000, /* R20590 */ + 0x0000, /* R20591 */ + 0x0000, /* R20592 */ + 0x0000, /* R20593 */ + 0x0000, /* R20594 */ + 0x0000, /* R20595 */ + 0x0000, /* R20596 */ + 0x0000, /* R20597 */ + 0x0000, /* R20598 */ + 0x0000, /* R20599 */ + 0x0000, /* R20600 */ + 0x0000, /* R20601 */ + 0x0000, /* R20602 */ + 0x0000, /* R20603 */ + 0x0000, /* R20604 */ + 0x0000, /* R20605 */ + 0x0000, /* R20606 */ + 0x0000, /* R20607 */ + 0x0000, /* R20608 */ + 0x0000, /* R20609 */ + 0x0000, /* R20610 */ + 0x0000, /* R20611 */ + 0x0000, /* R20612 */ + 0x0000, /* R20613 */ + 0x0000, /* R20614 */ + 0x0000, /* R20615 */ + 0x0000, /* R20616 */ + 0x0000, /* R20617 */ + 0x0000, /* R20618 */ + 0x0000, /* R20619 */ + 0x0000, /* R20620 */ + 0x0000, /* R20621 */ + 0x0000, /* R20622 */ + 0x0000, /* R20623 */ + 0x0000, /* R20624 */ + 0x0000, /* R20625 */ + 0x0000, /* R20626 */ + 0x0000, /* R20627 */ + 0x0000, /* R20628 */ + 0x0000, /* R20629 */ + 0x0000, /* R20630 */ + 0x0000, /* R20631 */ + 0x0000, /* R20632 */ + 0x0000, /* R20633 */ + 0x0000, /* R20634 */ + 0x0000, /* R20635 */ + 0x0000, /* R20636 */ + 0x0000, /* R20637 */ + 0x0000, /* R20638 */ + 0x0000, /* R20639 */ + 0x0000, /* R20640 */ + 0x0000, /* R20641 */ + 0x0000, /* R20642 */ + 0x0000, /* R20643 */ + 0x0000, /* R20644 */ + 0x0000, /* R20645 */ + 0x0000, /* R20646 */ + 0x0000, /* R20647 */ + 0x0000, /* R20648 */ + 0x0000, /* R20649 */ + 0x0000, /* R20650 */ + 0x0000, /* R20651 */ + 0x0000, /* R20652 */ + 0x0000, /* R20653 */ + 0x0000, /* R20654 */ + 0x0000, /* R20655 */ + 0x0000, /* R20656 */ + 0x0000, /* R20657 */ + 0x0000, /* R20658 */ + 0x0000, /* R20659 */ + 0x0000, /* R20660 */ + 0x0000, /* R20661 */ + 0x0000, /* R20662 */ + 0x0000, /* R20663 */ + 0x0000, /* R20664 */ + 0x0000, /* R20665 */ + 0x0000, /* R20666 */ + 0x0000, /* R20667 */ + 0x0000, /* R20668 */ + 0x0000, /* R20669 */ + 0x0000, /* R20670 */ + 0x0000, /* R20671 */ + 0x0000, /* R20672 */ + 0x0000, /* R20673 */ + 0x0000, /* R20674 */ + 0x0000, /* R20675 */ + 0x0000, /* R20676 */ + 0x0000, /* R20677 */ + 0x0000, /* R20678 */ + 0x0000, /* R20679 */ + 0x0000, /* R20680 */ + 0x0000, /* R20681 */ + 0x0000, /* R20682 */ + 0x0000, /* R20683 */ + 0x0000, /* R20684 */ + 0x0000, /* R20685 */ + 0x0000, /* R20686 */ + 0x0000, /* R20687 */ + 0x0000, /* R20688 */ + 0x0000, /* R20689 */ + 0x0000, /* R20690 */ + 0x0000, /* R20691 */ + 0x0000, /* R20692 */ + 0x0000, /* R20693 */ + 0x0000, /* R20694 */ + 0x0000, /* R20695 */ + 0x0000, /* R20696 */ + 0x0000, /* R20697 */ + 0x0000, /* R20698 */ + 0x0000, /* R20699 */ + 0x0000, /* R20700 */ + 0x0000, /* R20701 */ + 0x0000, /* R20702 */ + 0x0000, /* R20703 */ + 0x0000, /* R20704 */ + 0x0000, /* R20705 */ + 0x0000, /* R20706 */ + 0x0000, /* R20707 */ + 0x0000, /* R20708 */ + 0x0000, /* R20709 */ + 0x0000, /* R20710 */ + 0x0000, /* R20711 */ + 0x0000, /* R20712 */ + 0x0000, /* R20713 */ + 0x0000, /* R20714 */ + 0x0000, /* R20715 */ + 0x0000, /* R20716 */ + 0x0000, /* R20717 */ + 0x0000, /* R20718 */ + 0x0000, /* R20719 */ + 0x0000, /* R20720 */ + 0x0000, /* R20721 */ + 0x0000, /* R20722 */ + 0x0000, /* R20723 */ + 0x0000, /* R20724 */ + 0x0000, /* R20725 */ + 0x0000, /* R20726 */ + 0x0000, /* R20727 */ + 0x0000, /* R20728 */ + 0x0000, /* R20729 */ + 0x0000, /* R20730 */ + 0x0000, /* R20731 */ + 0x0000, /* R20732 */ + 0x0000, /* R20733 */ + 0x0000, /* R20734 */ + 0x0000, /* R20735 */ + 0x0000, /* R20736 */ + 0x0000, /* R20737 */ + 0x0000, /* R20738 */ + 0x0000, /* R20739 */ + 0x0000, /* R20740 */ + 0x0000, /* R20741 */ + 0x0000, /* R20742 */ + 0x0000, /* R20743 */ + 0x0000, /* R20744 */ + 0x0000, /* R20745 */ + 0x0000, /* R20746 */ + 0x0000, /* R20747 */ + 0x0000, /* R20748 */ + 0x0000, /* R20749 */ + 0x0000, /* R20750 */ + 0x0000, /* R20751 */ + 0x0000, /* R20752 */ + 0x0000, /* R20753 */ + 0x0000, /* R20754 */ + 0x0000, /* R20755 */ + 0x0000, /* R20756 */ + 0x0000, /* R20757 */ + 0x0000, /* R20758 */ + 0x0000, /* R20759 */ + 0x0000, /* R20760 */ + 0x0000, /* R20761 */ + 0x0000, /* R20762 */ + 0x0000, /* R20763 */ + 0x0000, /* R20764 */ + 0x0000, /* R20765 */ + 0x0000, /* R20766 */ + 0x0000, /* R20767 */ + 0x0000, /* R20768 */ + 0x0000, /* R20769 */ + 0x0000, /* R20770 */ + 0x0000, /* R20771 */ + 0x0000, /* R20772 */ + 0x0000, /* R20773 */ + 0x0000, /* R20774 */ + 0x0000, /* R20775 */ + 0x0000, /* R20776 */ + 0x0000, /* R20777 */ + 0x0000, /* R20778 */ + 0x0000, /* R20779 */ + 0x0000, /* R20780 */ + 0x0000, /* R20781 */ + 0x0000, /* R20782 */ + 0x0000, /* R20783 */ + 0x0000, /* R20784 */ + 0x0000, /* R20785 */ + 0x0000, /* R20786 */ + 0x0000, /* R20787 */ + 0x0000, /* R20788 */ + 0x0000, /* R20789 */ + 0x0000, /* R20790 */ + 0x0000, /* R20791 */ + 0x0000, /* R20792 */ + 0x0000, /* R20793 */ + 0x0000, /* R20794 */ + 0x0000, /* R20795 */ + 0x0000, /* R20796 */ + 0x0000, /* R20797 */ + 0x0000, /* R20798 */ + 0x0000, /* R20799 */ + 0x0000, /* R20800 */ + 0x0000, /* R20801 */ + 0x0000, /* R20802 */ + 0x0000, /* R20803 */ + 0x0000, /* R20804 */ + 0x0000, /* R20805 */ + 0x0000, /* R20806 */ + 0x0000, /* R20807 */ + 0x0000, /* R20808 */ + 0x0000, /* R20809 */ + 0x0000, /* R20810 */ + 0x0000, /* R20811 */ + 0x0000, /* R20812 */ + 0x0000, /* R20813 */ + 0x0000, /* R20814 */ + 0x0000, /* R20815 */ + 0x0000, /* R20816 */ + 0x0000, /* R20817 */ + 0x0000, /* R20818 */ + 0x0000, /* R20819 */ + 0x0000, /* R20820 */ + 0x0000, /* R20821 */ + 0x0000, /* R20822 */ + 0x0000, /* R20823 */ + 0x0000, /* R20824 */ + 0x0000, /* R20825 */ + 0x0000, /* R20826 */ + 0x0000, /* R20827 */ + 0x0000, /* R20828 */ + 0x0000, /* R20829 */ + 0x0000, /* R20830 */ + 0x0000, /* R20831 */ + 0x0000, /* R20832 */ + 0x0000, /* R20833 */ + 0x0000, /* R20834 */ + 0x0000, /* R20835 */ + 0x0000, /* R20836 */ + 0x0000, /* R20837 */ + 0x0000, /* R20838 */ + 0x0000, /* R20839 */ + 0x0000, /* R20840 */ + 0x0000, /* R20841 */ + 0x0000, /* R20842 */ + 0x0000, /* R20843 */ + 0x0000, /* R20844 */ + 0x0000, /* R20845 */ + 0x0000, /* R20846 */ + 0x0000, /* R20847 */ + 0x0000, /* R20848 */ + 0x0000, /* R20849 */ + 0x0000, /* R20850 */ + 0x0000, /* R20851 */ + 0x0000, /* R20852 */ + 0x0000, /* R20853 */ + 0x0000, /* R20854 */ + 0x0000, /* R20855 */ + 0x0000, /* R20856 */ + 0x0000, /* R20857 */ + 0x0000, /* R20858 */ + 0x0000, /* R20859 */ + 0x0000, /* R20860 */ + 0x0000, /* R20861 */ + 0x0000, /* R20862 */ + 0x0000, /* R20863 */ + 0x0000, /* R20864 */ + 0x0000, /* R20865 */ + 0x0000, /* R20866 */ + 0x0000, /* R20867 */ + 0x0000, /* R20868 */ + 0x0000, /* R20869 */ + 0x0000, /* R20870 */ + 0x0000, /* R20871 */ + 0x0000, /* R20872 */ + 0x0000, /* R20873 */ + 0x0000, /* R20874 */ + 0x0000, /* R20875 */ + 0x0000, /* R20876 */ + 0x0000, /* R20877 */ + 0x0000, /* R20878 */ + 0x0000, /* R20879 */ + 0x0000, /* R20880 */ + 0x0000, /* R20881 */ + 0x0000, /* R20882 */ + 0x0000, /* R20883 */ + 0x0000, /* R20884 */ + 0x0000, /* R20885 */ + 0x0000, /* R20886 */ + 0x0000, /* R20887 */ + 0x0000, /* R20888 */ + 0x0000, /* R20889 */ + 0x0000, /* R20890 */ + 0x0000, /* R20891 */ + 0x0000, /* R20892 */ + 0x0000, /* R20893 */ + 0x0000, /* R20894 */ + 0x0000, /* R20895 */ + 0x0000, /* R20896 */ + 0x0000, /* R20897 */ + 0x0000, /* R20898 */ + 0x0000, /* R20899 */ + 0x0000, /* R20900 */ + 0x0000, /* R20901 */ + 0x0000, /* R20902 */ + 0x0000, /* R20903 */ + 0x0000, /* R20904 */ + 0x0000, /* R20905 */ + 0x0000, /* R20906 */ + 0x0000, /* R20907 */ + 0x0000, /* R20908 */ + 0x0000, /* R20909 */ + 0x0000, /* R20910 */ + 0x0000, /* R20911 */ + 0x0000, /* R20912 */ + 0x0000, /* R20913 */ + 0x0000, /* R20914 */ + 0x0000, /* R20915 */ + 0x0000, /* R20916 */ + 0x0000, /* R20917 */ + 0x0000, /* R20918 */ + 0x0000, /* R20919 */ + 0x0000, /* R20920 */ + 0x0000, /* R20921 */ + 0x0000, /* R20922 */ + 0x0000, /* R20923 */ + 0x0000, /* R20924 */ + 0x0000, /* R20925 */ + 0x0000, /* R20926 */ + 0x0000, /* R20927 */ + 0x0000, /* R20928 */ + 0x0000, /* R20929 */ + 0x0000, /* R20930 */ + 0x0000, /* R20931 */ + 0x0000, /* R20932 */ + 0x0000, /* R20933 */ + 0x0000, /* R20934 */ + 0x0000, /* R20935 */ + 0x0000, /* R20936 */ + 0x0000, /* R20937 */ + 0x0000, /* R20938 */ + 0x0000, /* R20939 */ + 0x0000, /* R20940 */ + 0x0000, /* R20941 */ + 0x0000, /* R20942 */ + 0x0000, /* R20943 */ + 0x0000, /* R20944 */ + 0x0000, /* R20945 */ + 0x0000, /* R20946 */ + 0x0000, /* R20947 */ + 0x0000, /* R20948 */ + 0x0000, /* R20949 */ + 0x0000, /* R20950 */ + 0x0000, /* R20951 */ + 0x0000, /* R20952 */ + 0x0000, /* R20953 */ + 0x0000, /* R20954 */ + 0x0000, /* R20955 */ + 0x0000, /* R20956 */ + 0x0000, /* R20957 */ + 0x0000, /* R20958 */ + 0x0000, /* R20959 */ + 0x0000, /* R20960 */ + 0x0000, /* R20961 */ + 0x0000, /* R20962 */ + 0x0000, /* R20963 */ + 0x0000, /* R20964 */ + 0x0000, /* R20965 */ + 0x0000, /* R20966 */ + 0x0000, /* R20967 */ + 0x0000, /* R20968 */ + 0x0000, /* R20969 */ + 0x0000, /* R20970 */ + 0x0000, /* R20971 */ + 0x0000, /* R20972 */ + 0x0000, /* R20973 */ + 0x0000, /* R20974 */ + 0x0000, /* R20975 */ + 0x0000, /* R20976 */ + 0x0000, /* R20977 */ + 0x0000, /* R20978 */ + 0x0000, /* R20979 */ + 0x0000, /* R20980 */ + 0x0000, /* R20981 */ + 0x0000, /* R20982 */ + 0x0000, /* R20983 */ + 0x0000, /* R20984 */ + 0x0000, /* R20985 */ + 0x0000, /* R20986 */ + 0x0000, /* R20987 */ + 0x0000, /* R20988 */ + 0x0000, /* R20989 */ + 0x0000, /* R20990 */ + 0x0000, /* R20991 */ + 0x008C, /* R20992 - VSS_XHD2_1 */ + 0x0200, /* R20993 - VSS_XHD2_0 */ + 0x0035, /* R20994 - VSS_XHD3_1 */ + 0x0700, /* R20995 - VSS_XHD3_0 */ + 0x003A, /* R20996 - VSS_XHN1_1 */ + 0x4100, /* R20997 - VSS_XHN1_0 */ + 0x008B, /* R20998 - VSS_XHN2_1 */ + 0x7D00, /* R20999 - VSS_XHN2_0 */ + 0x003A, /* R21000 - VSS_XHN3_1 */ + 0x4100, /* R21001 - VSS_XHN3_0 */ + 0x008C, /* R21002 - VSS_XLA_1 */ + 0xFEE8, /* R21003 - VSS_XLA_0 */ + 0x0078, /* R21004 - VSS_XLB_1 */ + 0x0000, /* R21005 - VSS_XLB_0 */ + 0x003F, /* R21006 - VSS_XLG_1 */ + 0xB260, /* R21007 - VSS_XLG_0 */ + 0x002D, /* R21008 - VSS_PG2_1 */ + 0x1818, /* R21009 - VSS_PG2_0 */ + 0x0020, /* R21010 - VSS_PG_1 */ + 0x0000, /* R21011 - VSS_PG_0 */ + 0x00F1, /* R21012 - VSS_XTD1_1 */ + 0x8340, /* R21013 - VSS_XTD1_0 */ + 0x00FB, /* R21014 - VSS_XTD2_1 */ + 0x8300, /* R21015 - VSS_XTD2_0 */ + 0x00EE, /* R21016 - VSS_XTD3_1 */ + 0xAEC0, /* R21017 - VSS_XTD3_0 */ + 0x00FB, /* R21018 - VSS_XTD4_1 */ + 0xAC40, /* R21019 - VSS_XTD4_0 */ + 0x00F1, /* R21020 - VSS_XTD5_1 */ + 0x7F80, /* R21021 - VSS_XTD5_0 */ + 0x00F4, /* R21022 - VSS_XTD6_1 */ + 0x3B40, /* R21023 - VSS_XTD6_0 */ + 0x00F5, /* R21024 - VSS_XTD7_1 */ + 0xFB00, /* R21025 - VSS_XTD7_0 */ + 0x00EA, /* R21026 - VSS_XTD8_1 */ + 0x10C0, /* R21027 - VSS_XTD8_0 */ + 0x00FC, /* R21028 - VSS_XTD9_1 */ + 0xC580, /* R21029 - VSS_XTD9_0 */ + 0x00E2, /* R21030 - VSS_XTD10_1 */ + 0x75C0, /* R21031 - VSS_XTD10_0 */ + 0x0004, /* R21032 - VSS_XTD11_1 */ + 0xB480, /* R21033 - VSS_XTD11_0 */ + 0x00D4, /* R21034 - VSS_XTD12_1 */ + 0xF980, /* R21035 - VSS_XTD12_0 */ + 0x0004, /* R21036 - VSS_XTD13_1 */ + 0x9140, /* R21037 - VSS_XTD13_0 */ + 0x00D8, /* R21038 - VSS_XTD14_1 */ + 0xA480, /* R21039 - VSS_XTD14_0 */ + 0x0002, /* R21040 - VSS_XTD15_1 */ + 0x3DC0, /* R21041 - VSS_XTD15_0 */ + 0x00CF, /* R21042 - VSS_XTD16_1 */ + 0x7A80, /* R21043 - VSS_XTD16_0 */ + 0x00DC, /* R21044 - VSS_XTD17_1 */ + 0x0600, /* R21045 - VSS_XTD17_0 */ + 0x00F2, /* R21046 - VSS_XTD18_1 */ + 0xDAC0, /* R21047 - VSS_XTD18_0 */ + 0x00BA, /* R21048 - VSS_XTD19_1 */ + 0xF340, /* R21049 - VSS_XTD19_0 */ + 0x000A, /* R21050 - VSS_XTD20_1 */ + 0x7940, /* R21051 - VSS_XTD20_0 */ + 0x001C, /* R21052 - VSS_XTD21_1 */ + 0x0680, /* R21053 - VSS_XTD21_0 */ + 0x00FD, /* R21054 - VSS_XTD22_1 */ + 0x2D00, /* R21055 - VSS_XTD22_0 */ + 0x001C, /* R21056 - VSS_XTD23_1 */ + 0xE840, /* R21057 - VSS_XTD23_0 */ + 0x000D, /* R21058 - VSS_XTD24_1 */ + 0xDC40, /* R21059 - VSS_XTD24_0 */ + 0x00FC, /* R21060 - VSS_XTD25_1 */ + 0x9D00, /* R21061 - VSS_XTD25_0 */ + 0x0009, /* R21062 - VSS_XTD26_1 */ + 0x5580, /* R21063 - VSS_XTD26_0 */ + 0x00FE, /* R21064 - VSS_XTD27_1 */ + 0x7E80, /* R21065 - VSS_XTD27_0 */ + 0x000E, /* R21066 - VSS_XTD28_1 */ + 0xAB40, /* R21067 - VSS_XTD28_0 */ + 0x00F9, /* R21068 - VSS_XTD29_1 */ + 0x9880, /* R21069 - VSS_XTD29_0 */ + 0x0009, /* R21070 - VSS_XTD30_1 */ + 0x87C0, /* R21071 - VSS_XTD30_0 */ + 0x00FD, /* R21072 - VSS_XTD31_1 */ + 0x2C40, /* R21073 - VSS_XTD31_0 */ + 0x0009, /* R21074 - VSS_XTD32_1 */ + 0x4800, /* R21075 - VSS_XTD32_0 */ + 0x0003, /* R21076 - VSS_XTS1_1 */ + 0x5F40, /* R21077 - VSS_XTS1_0 */ + 0x0000, /* R21078 - VSS_XTS2_1 */ + 0x8700, /* R21079 - VSS_XTS2_0 */ + 0x00FA, /* R21080 - VSS_XTS3_1 */ + 0xE4C0, /* R21081 - VSS_XTS3_0 */ + 0x0000, /* R21082 - VSS_XTS4_1 */ + 0x0B40, /* R21083 - VSS_XTS4_0 */ + 0x0004, /* R21084 - VSS_XTS5_1 */ + 0xE180, /* R21085 - VSS_XTS5_0 */ + 0x0001, /* R21086 - VSS_XTS6_1 */ + 0x1F40, /* R21087 - VSS_XTS6_0 */ + 0x00F8, /* R21088 - VSS_XTS7_1 */ + 0xB000, /* R21089 - VSS_XTS7_0 */ + 0x00FB, /* R21090 - VSS_XTS8_1 */ + 0xCBC0, /* R21091 - VSS_XTS8_0 */ + 0x0004, /* R21092 - VSS_XTS9_1 */ + 0xF380, /* R21093 - VSS_XTS9_0 */ + 0x0007, /* R21094 - VSS_XTS10_1 */ + 0xDF40, /* R21095 - VSS_XTS10_0 */ + 0x00FF, /* R21096 - VSS_XTS11_1 */ + 0x0700, /* R21097 - VSS_XTS11_0 */ + 0x00EF, /* R21098 - VSS_XTS12_1 */ + 0xD700, /* R21099 - VSS_XTS12_0 */ + 0x00FB, /* R21100 - VSS_XTS13_1 */ + 0xAF40, /* R21101 - VSS_XTS13_0 */ + 0x0010, /* R21102 - VSS_XTS14_1 */ + 0x8A80, /* R21103 - VSS_XTS14_0 */ + 0x0011, /* R21104 - VSS_XTS15_1 */ + 0x07C0, /* R21105 - VSS_XTS15_0 */ + 0x00E0, /* R21106 - VSS_XTS16_1 */ + 0x0800, /* R21107 - VSS_XTS16_0 */ + 0x00D2, /* R21108 - VSS_XTS17_1 */ + 0x7600, /* R21109 - VSS_XTS17_0 */ + 0x0020, /* R21110 - VSS_XTS18_1 */ + 0xCF40, /* R21111 - VSS_XTS18_0 */ + 0x0030, /* R21112 - VSS_XTS19_1 */ + 0x2340, /* R21113 - VSS_XTS19_0 */ + 0x00FD, /* R21114 - VSS_XTS20_1 */ + 0x69C0, /* R21115 - VSS_XTS20_0 */ + 0x0028, /* R21116 - VSS_XTS21_1 */ + 0x3500, /* R21117 - VSS_XTS21_0 */ + 0x0006, /* R21118 - VSS_XTS22_1 */ + 0x3300, /* R21119 - VSS_XTS22_0 */ + 0x00D9, /* R21120 - VSS_XTS23_1 */ + 0xF6C0, /* R21121 - VSS_XTS23_0 */ + 0x00F3, /* R21122 - VSS_XTS24_1 */ + 0x3340, /* R21123 - VSS_XTS24_0 */ + 0x000F, /* R21124 - VSS_XTS25_1 */ + 0x4200, /* R21125 - VSS_XTS25_0 */ + 0x0004, /* R21126 - VSS_XTS26_1 */ + 0x0C80, /* R21127 - VSS_XTS26_0 */ + 0x00FB, /* R21128 - VSS_XTS27_1 */ + 0x3F80, /* R21129 - VSS_XTS27_0 */ + 0x00F7, /* R21130 - VSS_XTS28_1 */ + 0x57C0, /* R21131 - VSS_XTS28_0 */ + 0x0003, /* R21132 - VSS_XTS29_1 */ + 0x5400, /* R21133 - VSS_XTS29_0 */ + 0x0000, /* R21134 - VSS_XTS30_1 */ + 0xC6C0, /* R21135 - VSS_XTS30_0 */ + 0x0003, /* R21136 - VSS_XTS31_1 */ + 0x12C0, /* R21137 - VSS_XTS31_0 */ + 0x00FD, /* R21138 - VSS_XTS32_1 */ + 0x8580, /* R21139 - VSS_XTS32_0 */ +}; + +const struct wm8962_reg_access wm8962_reg_access[WM8962_MAX_REGISTER + 1] = { + { 0x00FF, 0x01FF, 0x0000 }, /* R0 - Left Input volume */ + { 0xFEFF, 0x01FF, 0xFFFF }, /* R1 - Right Input volume */ + { 0x00FF, 0x01FF, 0x0000 }, /* R2 - HPOUTL volume */ + { 0x00FF, 0x01FF, 0x0000 }, /* R3 - HPOUTR volume */ + { 0x07FE, 0x07FE, 0xFFFF }, /* R4 - Clocking1 */ + { 0x007F, 0x007F, 0x0000 }, /* R5 - ADC & DAC Control 1 */ + { 0x37ED, 0x37ED, 0x0000 }, /* R6 - ADC & DAC Control 2 */ + { 0x1FFF, 0x1FFF, 0x0000 }, /* R7 - Audio Interface 0 */ + { 0x0FEF, 0x0FEF, 0xFFFF }, /* R8 - Clocking2 */ + { 0x0B9F, 0x039F, 0x0000 }, /* R9 - Audio Interface 1 */ + { 0x00FF, 0x01FF, 0x0000 }, /* R10 - Left DAC volume */ + { 0x00FF, 0x01FF, 0x0000 }, /* R11 - Right DAC volume */ + { 0x0000, 0x0000, 0x0000 }, /* R12 */ + { 0x0000, 0x0000, 0x0000 }, /* R13 */ + { 0x07FF, 0x07FF, 0x0000 }, /* R14 - Audio Interface 2 */ + { 0xFFFF, 0xFFFF, 0xFFFF }, /* R15 - Software Reset */ + { 0x0000, 0x0000, 0x0000 }, /* R16 */ + { 0x07FF, 0x07FF, 0x0000 }, /* R17 - ALC1 */ + { 0xF8FF, 0x00FF, 0xFFFF }, /* R18 - ALC2 */ + { 0x1DFF, 0x1DFF, 0x0000 }, /* R19 - ALC3 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20 - Noise Gate */ + { 0x00FF, 0x01FF, 0x0000 }, /* R21 - Left ADC volume */ + { 0x00FF, 0x01FF, 0x0000 }, /* R22 - Right ADC volume */ + { 0x0161, 0x0161, 0x0000 }, /* R23 - Additional control(1) */ + { 0x0008, 0x0008, 0x0000 }, /* R24 - Additional control(2) */ + { 0x07FE, 0x07FE, 0x0000 }, /* R25 - Pwr Mgmt (1) */ + { 0x01FB, 0x01FB, 0x0000 }, /* R26 - Pwr Mgmt (2) */ + { 0x0017, 0x0017, 0x0000 }, /* R27 - Additional Control (3) */ + { 0x001C, 0x001C, 0x0000 }, /* R28 - Anti-pop */ + { 0x0000, 0x0000, 0x0000 }, /* R29 */ + { 0xFFFE, 0xFFFE, 0x0000 }, /* R30 - Clocking 3 */ + { 0x000F, 0x000F, 0x0000 }, /* R31 - Input mixer control (1) */ + { 0x01FF, 0x01FF, 0x0000 }, /* R32 - Left input mixer volume */ + { 0x01FF, 0x01FF, 0x0000 }, /* R33 - Right input mixer volume */ + { 0x003F, 0x003F, 0x0000 }, /* R34 - Input mixer control (2) */ + { 0x003F, 0x003F, 0x0000 }, /* R35 - Input bias control */ + { 0x0000, 0x0000, 0x0000 }, /* R36 */ + { 0x001F, 0x001F, 0x0000 }, /* R37 - Left input PGA control */ + { 0x001F, 0x001F, 0x0000 }, /* R38 - Right input PGA control */ + { 0x0000, 0x0000, 0x0000 }, /* R39 */ + { 0x00FF, 0x01FF, 0x0000 }, /* R40 - SPKOUTL volume */ + { 0x00FF, 0x01FF, 0x0000 }, /* R41 - SPKOUTR volume */ + { 0x0000, 0x0000, 0x0000 }, /* R42 */ + { 0x0000, 0x0000, 0x0000 }, /* R43 */ + { 0x0000, 0x0000, 0x0000 }, /* R44 */ + { 0x0000, 0x0000, 0x0000 }, /* R45 */ + { 0x0000, 0x0000, 0x0000 }, /* R46 */ + { 0x000F, 0x0000, 0x0000 }, /* R47 - Thermal Shutdown Status */ + { 0x7EC7, 0x7E07, 0x0000 }, /* R48 - Additional Control (4) */ + { 0x00D3, 0x00D7, 0xFFFF }, /* R49 - Class D Control 1 */ + { 0x0000, 0x0000, 0x0000 }, /* R50 */ + { 0x0047, 0x0047, 0x0000 }, /* R51 - Class D Control 2 */ + { 0x0000, 0x0000, 0x0000 }, /* R52 */ + { 0x0000, 0x0000, 0x0000 }, /* R53 */ + { 0x0000, 0x0000, 0x0000 }, /* R54 */ + { 0x0000, 0x0000, 0x0000 }, /* R55 */ + { 0x001E, 0x001E, 0x0000 }, /* R56 - Clocking 4 */ + { 0x02FC, 0x02FC, 0x0000 }, /* R57 - DAC DSP Mixing (1) */ + { 0x00FC, 0x00FC, 0x0000 }, /* R58 - DAC DSP Mixing (2) */ + { 0x0000, 0x0000, 0x0000 }, /* R59 */ + { 0x00CC, 0x00CC, 0x0000 }, /* R60 - DC Servo 0 */ + { 0x00DD, 0x00DD, 0x0000 }, /* R61 - DC Servo 1 */ + { 0x0000, 0x0000, 0x0000 }, /* R62 */ + { 0x0000, 0x0000, 0x0000 }, /* R63 */ + { 0x3F80, 0x3F80, 0x0000 }, /* R64 - DC Servo 4 */ + { 0x0000, 0x0000, 0x0000 }, /* R65 */ + { 0x0780, 0x0000, 0xFFFF }, /* R66 - DC Servo 6 */ + { 0x0000, 0x0000, 0x0000 }, /* R67 */ + { 0x0007, 0x0007, 0x0000 }, /* R68 - Analogue PGA Bias */ + { 0x00FF, 0x00FF, 0x0000 }, /* R69 - Analogue HP 0 */ + { 0x0000, 0x0000, 0x0000 }, /* R70 */ + { 0x01FF, 0x01FF, 0x0000 }, /* R71 - Analogue HP 2 */ + { 0x0001, 0x0001, 0x0000 }, /* R72 - Charge Pump 1 */ + { 0x0000, 0x0000, 0x0000 }, /* R73 */ + { 0x0000, 0x0000, 0x0000 }, /* R74 */ + { 0x0000, 0x0000, 0x0000 }, /* R75 */ + { 0x0000, 0x0000, 0x0000 }, /* R76 */ + { 0x0000, 0x0000, 0x0000 }, /* R77 */ + { 0x0000, 0x0000, 0x0000 }, /* R78 */ + { 0x0000, 0x0000, 0x0000 }, /* R79 */ + { 0x0000, 0x0000, 0x0000 }, /* R80 */ + { 0x0000, 0x0000, 0x0000 }, /* R81 */ + { 0x0001, 0x0001, 0x0000 }, /* R82 - Charge Pump B */ + { 0x0000, 0x0000, 0x0000 }, /* R83 */ + { 0x0000, 0x0000, 0x0000 }, /* R84 */ + { 0x0000, 0x0000, 0x0000 }, /* R85 */ + { 0x0000, 0x0000, 0x0000 }, /* R86 */ + { 0x00A0, 0x00A0, 0x0000 }, /* R87 - Write Sequencer Control 1 */ + { 0x0000, 0x0000, 0x0000 }, /* R88 */ + { 0x0000, 0x0000, 0x0000 }, /* R89 */ + { 0x007F, 0x01FF, 0x0000 }, /* R90 - Write Sequencer Control 2 */ + { 0x0000, 0x0000, 0x0000 }, /* R91 */ + { 0x0000, 0x0000, 0x0000 }, /* R92 */ + { 0x03F9, 0x0000, 0x0000 }, /* R93 - Write Sequencer Control 3 */ + { 0x0070, 0x0070, 0x0000 }, /* R94 - Control Interface */ + { 0x0000, 0x0000, 0x0000 }, /* R95 */ + { 0x0000, 0x0000, 0x0000 }, /* R96 */ + { 0x0000, 0x0000, 0x0000 }, /* R97 */ + { 0x0000, 0x0000, 0x0000 }, /* R98 */ + { 0x000F, 0x000F, 0x0000 }, /* R99 - Mixer Enables */ + { 0x00BF, 0x00BF, 0x0000 }, /* R100 - Headphone Mixer (1) */ + { 0x00BF, 0x00BF, 0x0000 }, /* R101 - Headphone Mixer (2) */ + { 0x01FF, 0x01FF, 0x0000 }, /* R102 - Headphone Mixer (3) */ + { 0x01FF, 0x01FF, 0x0000 }, /* R103 - Headphone Mixer (4) */ + { 0x0000, 0x0000, 0x0000 }, /* R104 */ + { 0x00BF, 0x00BF, 0x0000 }, /* R105 - Speaker Mixer (1) */ + { 0x00BF, 0x00BF, 0x0000 }, /* R106 - Speaker Mixer (2) */ + { 0x01FF, 0x01FF, 0x0000 }, /* R107 - Speaker Mixer (3) */ + { 0x01FF, 0x01FF, 0x0000 }, /* R108 - Speaker Mixer (4) */ + { 0x00F0, 0x00F0, 0x0000 }, /* R109 - Speaker Mixer (5) */ + { 0x00F7, 0x00F7, 0x0000 }, /* R110 - Beep Generator (1) */ + { 0x0000, 0x0000, 0x0000 }, /* R111 */ + { 0x0000, 0x0000, 0x0000 }, /* R112 */ + { 0x0000, 0x0000, 0x0000 }, /* R113 */ + { 0x0000, 0x0000, 0x0000 }, /* R114 */ + { 0x001F, 0x001F, 0x0000 }, /* R115 - Oscillator Trim (3) */ + { 0x001F, 0x001F, 0x0000 }, /* R116 - Oscillator Trim (4) */ + { 0x0000, 0x0000, 0x0000 }, /* R117 */ + { 0x0000, 0x0000, 0x0000 }, /* R118 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R119 - Oscillator Trim (7) */ + { 0x0000, 0x0000, 0x0000 }, /* R120 */ + { 0x0000, 0x0000, 0x0000 }, /* R121 */ + { 0x0000, 0x0000, 0x0000 }, /* R122 */ + { 0x0000, 0x0000, 0x0000 }, /* R123 */ + { 0x0079, 0x0079, 0x0000 }, /* R124 - Analogue Clocking1 */ + { 0x00DF, 0x00DF, 0x0000 }, /* R125 - Analogue Clocking2 */ + { 0x000D, 0x000D, 0x0000 }, /* R126 - Analogue Clocking3 */ + { 0x0000, 0xFFFF, 0x0000 }, /* R127 - PLL Software Reset */ + { 0x0000, 0x0000, 0x0000 }, /* R128 */ + { 0x00B0, 0x00B0, 0x0000 }, /* R129 - PLL2 */ + { 0x0000, 0x0000, 0x0000 }, /* R130 */ + { 0x0003, 0x0003, 0x0000 }, /* R131 - PLL 4 */ + { 0x0000, 0x0000, 0x0000 }, /* R132 */ + { 0x0000, 0x0000, 0x0000 }, /* R133 */ + { 0x0000, 0x0000, 0x0000 }, /* R134 */ + { 0x0000, 0x0000, 0x0000 }, /* R135 */ + { 0x005F, 0x005F, 0x0000 }, /* R136 - PLL 9 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R137 - PLL 10 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R138 - PLL 11 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R139 - PLL 12 */ + { 0x005F, 0x005F, 0x0000 }, /* R140 - PLL 13 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R141 - PLL 14 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R142 - PLL 15 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R143 - PLL 16 */ + { 0x0000, 0x0000, 0x0000 }, /* R144 */ + { 0x0000, 0x0000, 0x0000 }, /* R145 */ + { 0x0000, 0x0000, 0x0000 }, /* R146 */ + { 0x0000, 0x0000, 0x0000 }, /* R147 */ + { 0x0000, 0x0000, 0x0000 }, /* R148 */ + { 0x0000, 0x0000, 0x0000 }, /* R149 */ + { 0x0000, 0x0000, 0x0000 }, /* R150 */ + { 0x0000, 0x0000, 0x0000 }, /* R151 */ + { 0x0000, 0x0000, 0x0000 }, /* R152 */ + { 0x0000, 0x0000, 0x0000 }, /* R153 */ + { 0x0000, 0x0000, 0x0000 }, /* R154 */ + { 0x0067, 0x0067, 0x0000 }, /* R155 - FLL Control (1) */ + { 0x01FB, 0x01FB, 0x0000 }, /* R156 - FLL Control (2) */ + { 0x0007, 0x0007, 0x0000 }, /* R157 - FLL Control (3) */ + { 0x0000, 0x0000, 0x0000 }, /* R158 */ + { 0x007F, 0x007F, 0x0000 }, /* R159 - FLL Control (5) */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R160 - FLL Control (6) */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R161 - FLL Control (7) */ + { 0x03FF, 0x03FF, 0x0000 }, /* R162 - FLL Control (8) */ + { 0x0000, 0x0000, 0x0000 }, /* R163 */ + { 0x0000, 0x0000, 0x0000 }, /* R164 */ + { 0x0000, 0x0000, 0x0000 }, /* R165 */ + { 0x0000, 0x0000, 0x0000 }, /* R166 */ + { 0x0000, 0x0000, 0x0000 }, /* R167 */ + { 0x0000, 0x0000, 0x0000 }, /* R168 */ + { 0x0000, 0x0000, 0x0000 }, /* R169 */ + { 0x0000, 0x0000, 0x0000 }, /* R170 */ + { 0x0000, 0x0000, 0x0000 }, /* R171 */ + { 0x0000, 0x0000, 0x0000 }, /* R172 */ + { 0x0000, 0x0000, 0x0000 }, /* R173 */ + { 0x0000, 0x0000, 0x0000 }, /* R174 */ + { 0x0000, 0x0000, 0x0000 }, /* R175 */ + { 0x0000, 0x0000, 0x0000 }, /* R176 */ + { 0x0000, 0x0000, 0x0000 }, /* R177 */ + { 0x0000, 0x0000, 0x0000 }, /* R178 */ + { 0x0000, 0x0000, 0x0000 }, /* R179 */ + { 0x0000, 0x0000, 0x0000 }, /* R180 */ + { 0x0000, 0x0000, 0x0000 }, /* R181 */ + { 0x0000, 0x0000, 0x0000 }, /* R182 */ + { 0x0000, 0x0000, 0x0000 }, /* R183 */ + { 0x0000, 0x0000, 0x0000 }, /* R184 */ + { 0x0000, 0x0000, 0x0000 }, /* R185 */ + { 0x0000, 0x0000, 0x0000 }, /* R186 */ + { 0x0000, 0x0000, 0x0000 }, /* R187 */ + { 0x0000, 0x0000, 0x0000 }, /* R188 */ + { 0x0000, 0x0000, 0x0000 }, /* R189 */ + { 0x0000, 0x0000, 0x0000 }, /* R190 */ + { 0x0000, 0x0000, 0x0000 }, /* R191 */ + { 0x0000, 0x0000, 0x0000 }, /* R192 */ + { 0x0000, 0x0000, 0x0000 }, /* R193 */ + { 0x0000, 0x0000, 0x0000 }, /* R194 */ + { 0x0000, 0x0000, 0x0000 }, /* R195 */ + { 0x0000, 0x0000, 0x0000 }, /* R196 */ + { 0x0000, 0x0000, 0x0000 }, /* R197 */ + { 0x0000, 0x0000, 0x0000 }, /* R198 */ + { 0x0000, 0x0000, 0x0000 }, /* R199 */ + { 0x0000, 0x0000, 0x0000 }, /* R200 */ + { 0x0000, 0x0000, 0x0000 }, /* R201 */ + { 0x0000, 0x0000, 0x0000 }, /* R202 */ + { 0x0000, 0x0000, 0x0000 }, /* R203 */ + { 0x0000, 0x0000, 0x0000 }, /* R204 */ + { 0x0000, 0x0000, 0x0000 }, /* R205 */ + { 0x0000, 0x0000, 0x0000 }, /* R206 */ + { 0x0000, 0x0000, 0x0000 }, /* R207 */ + { 0x0000, 0x0000, 0x0000 }, /* R208 */ + { 0x0000, 0x0000, 0x0000 }, /* R209 */ + { 0x0000, 0x0000, 0x0000 }, /* R210 */ + { 0x0000, 0x0000, 0x0000 }, /* R211 */ + { 0x0000, 0x0000, 0x0000 }, /* R212 */ + { 0x0000, 0x0000, 0x0000 }, /* R213 */ + { 0x0000, 0x0000, 0x0000 }, /* R214 */ + { 0x0000, 0x0000, 0x0000 }, /* R215 */ + { 0x0000, 0x0000, 0x0000 }, /* R216 */ + { 0x0000, 0x0000, 0x0000 }, /* R217 */ + { 0x0000, 0x0000, 0x0000 }, /* R218 */ + { 0x0000, 0x0000, 0x0000 }, /* R219 */ + { 0x0000, 0x0000, 0x0000 }, /* R220 */ + { 0x0000, 0x0000, 0x0000 }, /* R221 */ + { 0x0000, 0x0000, 0x0000 }, /* R222 */ + { 0x0000, 0x0000, 0x0000 }, /* R223 */ + { 0x0000, 0x0000, 0x0000 }, /* R224 */ + { 0x0000, 0x0000, 0x0000 }, /* R225 */ + { 0x0000, 0x0000, 0x0000 }, /* R226 */ + { 0x0000, 0x0000, 0x0000 }, /* R227 */ + { 0x0000, 0x0000, 0x0000 }, /* R228 */ + { 0x0000, 0x0000, 0x0000 }, /* R229 */ + { 0x0000, 0x0000, 0x0000 }, /* R230 */ + { 0x0000, 0x0000, 0x0000 }, /* R231 */ + { 0x0000, 0x0000, 0x0000 }, /* R232 */ + { 0x0000, 0x0000, 0x0000 }, /* R233 */ + { 0x0000, 0x0000, 0x0000 }, /* R234 */ + { 0x0000, 0x0000, 0x0000 }, /* R235 */ + { 0x0000, 0x0000, 0x0000 }, /* R236 */ + { 0x0000, 0x0000, 0x0000 }, /* R237 */ + { 0x0000, 0x0000, 0x0000 }, /* R238 */ + { 0x0000, 0x0000, 0x0000 }, /* R239 */ + { 0x0000, 0x0000, 0x0000 }, /* R240 */ + { 0x0000, 0x0000, 0x0000 }, /* R241 */ + { 0x0000, 0x0000, 0x0000 }, /* R242 */ + { 0x0000, 0x0000, 0x0000 }, /* R243 */ + { 0x0000, 0x0000, 0x0000 }, /* R244 */ + { 0x0000, 0x0000, 0x0000 }, /* R245 */ + { 0x0000, 0x0000, 0x0000 }, /* R246 */ + { 0x0000, 0x0000, 0x0000 }, /* R247 */ + { 0x0000, 0x0000, 0x0000 }, /* R248 */ + { 0x0000, 0x0000, 0x0000 }, /* R249 */ + { 0x0000, 0x0000, 0x0000 }, /* R250 */ + { 0x0000, 0x0000, 0x0000 }, /* R251 */ + { 0x0005, 0x0005, 0x0000 }, /* R252 - General test 1 */ + { 0x0000, 0x0000, 0x0000 }, /* R253 */ + { 0x0000, 0x0000, 0x0000 }, /* R254 */ + { 0x0000, 0x0000, 0x0000 }, /* R255 */ + { 0x000F, 0x000F, 0x0000 }, /* R256 - DF1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R257 - DF2 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R258 - DF3 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R259 - DF4 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R260 - DF5 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R261 - DF6 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R262 - DF7 */ + { 0x0000, 0x0000, 0x0000 }, /* R263 */ + { 0x0003, 0x0003, 0x0000 }, /* R264 - LHPF1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R265 - LHPF2 */ + { 0x0000, 0x0000, 0x0000 }, /* R266 */ + { 0x0000, 0x0000, 0x0000 }, /* R267 */ + { 0x0077, 0x0077, 0x0000 }, /* R268 - THREED1 */ + { 0xFFFC, 0xFFFC, 0x0000 }, /* R269 - THREED2 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R270 - THREED3 */ + { 0xFFFC, 0xFFFC, 0x0000 }, /* R271 - THREED4 */ + { 0x0000, 0x0000, 0x0000 }, /* R272 */ + { 0x0000, 0x0000, 0x0000 }, /* R273 */ + { 0x0000, 0x0000, 0x0000 }, /* R274 */ + { 0x0000, 0x0000, 0x0000 }, /* R275 */ + { 0x7FFF, 0x7FFF, 0x0000 }, /* R276 - DRC 1 */ + { 0x1FFF, 0x1FFF, 0x0000 }, /* R277 - DRC 2 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R278 - DRC 3 */ + { 0x07FF, 0x07FF, 0x0000 }, /* R279 - DRC 4 */ + { 0x03FF, 0x03FF, 0x0000 }, /* R280 - DRC 5 */ + { 0x0000, 0x0000, 0x0000 }, /* R281 */ + { 0x0000, 0x0000, 0x0000 }, /* R282 */ + { 0x0000, 0x0000, 0x0000 }, /* R283 */ + { 0x0000, 0x0000, 0x0000 }, /* R284 */ + { 0x0003, 0x0003, 0x0000 }, /* R285 - Tloopback */ + { 0x0000, 0x0000, 0x0000 }, /* R286 */ + { 0x0000, 0x0000, 0x0000 }, /* R287 */ + { 0x0000, 0x0000, 0x0000 }, /* R288 */ + { 0x0000, 0x0000, 0x0000 }, /* R289 */ + { 0x0000, 0x0000, 0x0000 }, /* R290 */ + { 0x0000, 0x0000, 0x0000 }, /* R291 */ + { 0x0000, 0x0000, 0x0000 }, /* R292 */ + { 0x0000, 0x0000, 0x0000 }, /* R293 */ + { 0x0000, 0x0000, 0x0000 }, /* R294 */ + { 0x0000, 0x0000, 0x0000 }, /* R295 */ + { 0x0000, 0x0000, 0x0000 }, /* R296 */ + { 0x0000, 0x0000, 0x0000 }, /* R297 */ + { 0x0000, 0x0000, 0x0000 }, /* R298 */ + { 0x0000, 0x0000, 0x0000 }, /* R299 */ + { 0x0000, 0x0000, 0x0000 }, /* R300 */ + { 0x0000, 0x0000, 0x0000 }, /* R301 */ + { 0x0000, 0x0000, 0x0000 }, /* R302 */ + { 0x0000, 0x0000, 0x0000 }, /* R303 */ + { 0x0000, 0x0000, 0x0000 }, /* R304 */ + { 0x0000, 0x0000, 0x0000 }, /* R305 */ + { 0x0000, 0x0000, 0x0000 }, /* R306 */ + { 0x0000, 0x0000, 0x0000 }, /* R307 */ + { 0x0000, 0x0000, 0x0000 }, /* R308 */ + { 0x0000, 0x0000, 0x0000 }, /* R309 */ + { 0x0000, 0x0000, 0x0000 }, /* R310 */ + { 0x0000, 0x0000, 0x0000 }, /* R311 */ + { 0x0000, 0x0000, 0x0000 }, /* R312 */ + { 0x0000, 0x0000, 0x0000 }, /* R313 */ + { 0x0000, 0x0000, 0x0000 }, /* R314 */ + { 0x0000, 0x0000, 0x0000 }, /* R315 */ + { 0x0000, 0x0000, 0x0000 }, /* R316 */ + { 0x0000, 0x0000, 0x0000 }, /* R317 */ + { 0x0000, 0x0000, 0x0000 }, /* R318 */ + { 0x0000, 0x0000, 0x0000 }, /* R319 */ + { 0x0000, 0x0000, 0x0000 }, /* R320 */ + { 0x0000, 0x0000, 0x0000 }, /* R321 */ + { 0x0000, 0x0000, 0x0000 }, /* R322 */ + { 0x0000, 0x0000, 0x0000 }, /* R323 */ + { 0x0000, 0x0000, 0x0000 }, /* R324 */ + { 0x0000, 0x0000, 0x0000 }, /* R325 */ + { 0x0000, 0x0000, 0x0000 }, /* R326 */ + { 0x0000, 0x0000, 0x0000 }, /* R327 */ + { 0x0000, 0x0000, 0x0000 }, /* R328 */ + { 0x0000, 0x0000, 0x0000 }, /* R329 */ + { 0x0000, 0x0000, 0x0000 }, /* R330 */ + { 0x0000, 0x0000, 0x0000 }, /* R331 */ + { 0x0000, 0x0000, 0x0000 }, /* R332 */ + { 0x0000, 0x0000, 0x0000 }, /* R333 */ + { 0x0000, 0x0000, 0x0000 }, /* R334 */ + { 0x0007, 0x0007, 0x0000 }, /* R335 - EQ1 */ + { 0xFFFE, 0xFFFE, 0x0000 }, /* R336 - EQ2 */ + { 0xFFC0, 0xFFC0, 0x0000 }, /* R337 - EQ3 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R338 - EQ4 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R339 - EQ5 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R340 - EQ6 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R341 - EQ7 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R342 - EQ8 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R343 - EQ9 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R344 - EQ10 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R345 - EQ11 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R346 - EQ12 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R347 - EQ13 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R348 - EQ14 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R349 - EQ15 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R350 - EQ16 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R351 - EQ17 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R352 - EQ18 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R353 - EQ19 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R354 - EQ20 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R355 - EQ21 */ + { 0xFFFE, 0xFFFE, 0x0000 }, /* R356 - EQ22 */ + { 0xFFC0, 0xFFC0, 0x0000 }, /* R357 - EQ23 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R358 - EQ24 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R359 - EQ25 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R360 - EQ26 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R361 - EQ27 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R362 - EQ28 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R363 - EQ29 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R364 - EQ30 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R365 - EQ31 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R366 - EQ32 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R367 - EQ33 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R368 - EQ34 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R369 - EQ35 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R370 - EQ36 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R371 - EQ37 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R372 - EQ38 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R373 - EQ39 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R374 - EQ40 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R375 - EQ41 */ + { 0x0000, 0x0000, 0x0000 }, /* R376 */ + { 0x0000, 0x0000, 0x0000 }, /* R377 */ + { 0x0000, 0x0000, 0x0000 }, /* R378 */ + { 0x0000, 0x0000, 0x0000 }, /* R379 */ + { 0x0000, 0x0000, 0x0000 }, /* R380 */ + { 0x0000, 0x0000, 0x0000 }, /* R381 */ + { 0x0000, 0x0000, 0x0000 }, /* R382 */ + { 0x0000, 0x0000, 0x0000 }, /* R383 */ + { 0x0000, 0x0000, 0x0000 }, /* R384 */ + { 0x0000, 0x0000, 0x0000 }, /* R385 */ + { 0x0000, 0x0000, 0x0000 }, /* R386 */ + { 0x0000, 0x0000, 0x0000 }, /* R387 */ + { 0x0000, 0x0000, 0x0000 }, /* R388 */ + { 0x0000, 0x0000, 0x0000 }, /* R389 */ + { 0x0000, 0x0000, 0x0000 }, /* R390 */ + { 0x0000, 0x0000, 0x0000 }, /* R391 */ + { 0x0000, 0x0000, 0x0000 }, /* R392 */ + { 0x0000, 0x0000, 0x0000 }, /* R393 */ + { 0x0000, 0x0000, 0x0000 }, /* R394 */ + { 0x0000, 0x0000, 0x0000 }, /* R395 */ + { 0x0000, 0x0000, 0x0000 }, /* R396 */ + { 0x0000, 0x0000, 0x0000 }, /* R397 */ + { 0x0000, 0x0000, 0x0000 }, /* R398 */ + { 0x0000, 0x0000, 0x0000 }, /* R399 */ + { 0x0000, 0x0000, 0x0000 }, /* R400 */ + { 0x0000, 0x0000, 0x0000 }, /* R401 */ + { 0x0000, 0x0000, 0x0000 }, /* R402 */ + { 0x0000, 0x0000, 0x0000 }, /* R403 */ + { 0x0000, 0x0000, 0x0000 }, /* R404 */ + { 0x0000, 0x0000, 0x0000 }, /* R405 */ + { 0x0000, 0x0000, 0x0000 }, /* R406 */ + { 0x0000, 0x0000, 0x0000 }, /* R407 */ + { 0x0000, 0x0000, 0x0000 }, /* R408 */ + { 0x0000, 0x0000, 0x0000 }, /* R409 */ + { 0x0000, 0x0000, 0x0000 }, /* R410 */ + { 0x0000, 0x0000, 0x0000 }, /* R411 */ + { 0x0000, 0x0000, 0x0000 }, /* R412 */ + { 0x0000, 0x0000, 0x0000 }, /* R413 */ + { 0x0000, 0x0000, 0x0000 }, /* R414 */ + { 0x0000, 0x0000, 0x0000 }, /* R415 */ + { 0x0000, 0x0000, 0x0000 }, /* R416 */ + { 0x0000, 0x0000, 0x0000 }, /* R417 */ + { 0x0000, 0x0000, 0x0000 }, /* R418 */ + { 0x0000, 0x0000, 0x0000 }, /* R419 */ + { 0x0000, 0x0000, 0x0000 }, /* R420 */ + { 0x0000, 0x0000, 0x0000 }, /* R421 */ + { 0x0000, 0x0000, 0x0000 }, /* R422 */ + { 0x0000, 0x0000, 0x0000 }, /* R423 */ + { 0x0000, 0x0000, 0x0000 }, /* R424 */ + { 0x0000, 0x0000, 0x0000 }, /* R425 */ + { 0x0000, 0x0000, 0x0000 }, /* R426 */ + { 0x0000, 0x0000, 0x0000 }, /* R427 */ + { 0x0000, 0x0000, 0x0000 }, /* R428 */ + { 0x0000, 0x0000, 0x0000 }, /* R429 */ + { 0x0000, 0x0000, 0x0000 }, /* R430 */ + { 0x0000, 0x0000, 0x0000 }, /* R431 */ + { 0x0000, 0x0000, 0x0000 }, /* R432 */ + { 0x0000, 0x0000, 0x0000 }, /* R433 */ + { 0x0000, 0x0000, 0x0000 }, /* R434 */ + { 0x0000, 0x0000, 0x0000 }, /* R435 */ + { 0x0000, 0x0000, 0x0000 }, /* R436 */ + { 0x0000, 0x0000, 0x0000 }, /* R437 */ + { 0x0000, 0x0000, 0x0000 }, /* R438 */ + { 0x0000, 0x0000, 0x0000 }, /* R439 */ + { 0x0000, 0x0000, 0x0000 }, /* R440 */ + { 0x0000, 0x0000, 0x0000 }, /* R441 */ + { 0x0000, 0x0000, 0x0000 }, /* R442 */ + { 0x0000, 0x0000, 0x0000 }, /* R443 */ + { 0x0000, 0x0000, 0x0000 }, /* R444 */ + { 0x0000, 0x0000, 0x0000 }, /* R445 */ + { 0x0000, 0x0000, 0x0000 }, /* R446 */ + { 0x0000, 0x0000, 0x0000 }, /* R447 */ + { 0x0000, 0x0000, 0x0000 }, /* R448 */ + { 0x0000, 0x0000, 0x0000 }, /* R449 */ + { 0x0000, 0x0000, 0x0000 }, /* R450 */ + { 0x0000, 0x0000, 0x0000 }, /* R451 */ + { 0x0000, 0x0000, 0x0000 }, /* R452 */ + { 0x0000, 0x0000, 0x0000 }, /* R453 */ + { 0x0000, 0x0000, 0x0000 }, /* R454 */ + { 0x0000, 0x0000, 0x0000 }, /* R455 */ + { 0x0000, 0x0000, 0x0000 }, /* R456 */ + { 0x0000, 0x0000, 0x0000 }, /* R457 */ + { 0x0000, 0x0000, 0x0000 }, /* R458 */ + { 0x0000, 0x0000, 0x0000 }, /* R459 */ + { 0x0000, 0x0000, 0x0000 }, /* R460 */ + { 0x0000, 0x0000, 0x0000 }, /* R461 */ + { 0x0000, 0x0000, 0x0000 }, /* R462 */ + { 0x0000, 0x0000, 0x0000 }, /* R463 */ + { 0x0000, 0x0000, 0x0000 }, /* R464 */ + { 0x0000, 0x0000, 0x0000 }, /* R465 */ + { 0x0000, 0x0000, 0x0000 }, /* R466 */ + { 0x0000, 0x0000, 0x0000 }, /* R467 */ + { 0x0000, 0x0000, 0x0000 }, /* R468 */ + { 0x0000, 0x0000, 0x0000 }, /* R469 */ + { 0x0000, 0x0000, 0x0000 }, /* R470 */ + { 0x0000, 0x0000, 0x0000 }, /* R471 */ + { 0x0000, 0x0000, 0x0000 }, /* R472 */ + { 0x0000, 0x0000, 0x0000 }, /* R473 */ + { 0x0000, 0x0000, 0x0000 }, /* R474 */ + { 0x0000, 0x0000, 0x0000 }, /* R475 */ + { 0x0000, 0x0000, 0x0000 }, /* R476 */ + { 0x0000, 0x0000, 0x0000 }, /* R477 */ + { 0x0000, 0x0000, 0x0000 }, /* R478 */ + { 0x0000, 0x0000, 0x0000 }, /* R479 */ + { 0x0000, 0x0000, 0x0000 }, /* R480 */ + { 0x0000, 0x0000, 0x0000 }, /* R481 */ + { 0x0000, 0x0000, 0x0000 }, /* R482 */ + { 0x0000, 0x0000, 0x0000 }, /* R483 */ + { 0x0000, 0x0000, 0x0000 }, /* R484 */ + { 0x0000, 0x0000, 0x0000 }, /* R485 */ + { 0x0000, 0x0000, 0x0000 }, /* R486 */ + { 0x0000, 0x0000, 0x0000 }, /* R487 */ + { 0x0000, 0x0000, 0x0000 }, /* R488 */ + { 0x0000, 0x0000, 0x0000 }, /* R489 */ + { 0x0000, 0x0000, 0x0000 }, /* R490 */ + { 0x0000, 0x0000, 0x0000 }, /* R491 */ + { 0x0000, 0x0000, 0x0000 }, /* R492 */ + { 0x0000, 0x0000, 0x0000 }, /* R493 */ + { 0x0000, 0x0000, 0x0000 }, /* R494 */ + { 0x0000, 0x0000, 0x0000 }, /* R495 */ + { 0x0000, 0x0000, 0x0000 }, /* R496 */ + { 0x0000, 0x0000, 0x0000 }, /* R497 */ + { 0x0000, 0x0000, 0x0000 }, /* R498 */ + { 0x0000, 0x0000, 0x0000 }, /* R499 */ + { 0x0000, 0x0000, 0x0000 }, /* R500 */ + { 0x0000, 0x0000, 0x0000 }, /* R501 */ + { 0x0000, 0x0000, 0x0000 }, /* R502 */ + { 0x0000, 0x0000, 0x0000 }, /* R503 */ + { 0x0000, 0x0000, 0x0000 }, /* R504 */ + { 0x0000, 0x0000, 0x0000 }, /* R505 */ + { 0x0000, 0x0000, 0x0000 }, /* R506 */ + { 0x0000, 0x0000, 0x0000 }, /* R507 */ + { 0x0000, 0x0000, 0x0000 }, /* R508 */ + { 0x0000, 0x0000, 0x0000 }, /* R509 */ + { 0x0000, 0x0000, 0x0000 }, /* R510 */ + { 0x0000, 0x0000, 0x0000 }, /* R511 */ + { 0x0000, 0x0000, 0x0000 }, /* R512 */ + { 0x045F, 0x045F, 0x0000 }, /* R513 - GPIO 2 */ + { 0x045F, 0x045F, 0x0000 }, /* R514 - GPIO 3 */ + { 0x0000, 0x0000, 0x0000 }, /* R515 */ + { 0xE75F, 0xE75F, 0x0000 }, /* R516 - GPIO 5 */ + { 0xE75F, 0xE75F, 0x0000 }, /* R517 - GPIO 6 */ + { 0x0000, 0x0000, 0x0000 }, /* R518 */ + { 0x0000, 0x0000, 0x0000 }, /* R519 */ + { 0x0000, 0x0000, 0x0000 }, /* R520 */ + { 0x0000, 0x0000, 0x0000 }, /* R521 */ + { 0x0000, 0x0000, 0x0000 }, /* R522 */ + { 0x0000, 0x0000, 0x0000 }, /* R523 */ + { 0x0000, 0x0000, 0x0000 }, /* R524 */ + { 0x0000, 0x0000, 0x0000 }, /* R525 */ + { 0x0000, 0x0000, 0x0000 }, /* R526 */ + { 0x0000, 0x0000, 0x0000 }, /* R527 */ + { 0x0000, 0x0000, 0x0000 }, /* R528 */ + { 0x0000, 0x0000, 0x0000 }, /* R529 */ + { 0x0000, 0x0000, 0x0000 }, /* R530 */ + { 0x0000, 0x0000, 0x0000 }, /* R531 */ + { 0x0000, 0x0000, 0x0000 }, /* R532 */ + { 0x0000, 0x0000, 0x0000 }, /* R533 */ + { 0x0000, 0x0000, 0x0000 }, /* R534 */ + { 0x0000, 0x0000, 0x0000 }, /* R535 */ + { 0x0000, 0x0000, 0x0000 }, /* R536 */ + { 0x0000, 0x0000, 0x0000 }, /* R537 */ + { 0x0000, 0x0000, 0x0000 }, /* R538 */ + { 0x0000, 0x0000, 0x0000 }, /* R539 */ + { 0x0000, 0x0000, 0x0000 }, /* R540 */ + { 0x0000, 0x0000, 0x0000 }, /* R541 */ + { 0x0000, 0x0000, 0x0000 }, /* R542 */ + { 0x0000, 0x0000, 0x0000 }, /* R543 */ + { 0x0000, 0x0000, 0x0000 }, /* R544 */ + { 0x0000, 0x0000, 0x0000 }, /* R545 */ + { 0x0000, 0x0000, 0x0000 }, /* R546 */ + { 0x0000, 0x0000, 0x0000 }, /* R547 */ + { 0x0000, 0x0000, 0x0000 }, /* R548 */ + { 0x0000, 0x0000, 0x0000 }, /* R549 */ + { 0x0000, 0x0000, 0x0000 }, /* R550 */ + { 0x0000, 0x0000, 0x0000 }, /* R551 */ + { 0x0000, 0x0000, 0x0000 }, /* R552 */ + { 0x0000, 0x0000, 0x0000 }, /* R553 */ + { 0x0000, 0x0000, 0x0000 }, /* R554 */ + { 0x0000, 0x0000, 0x0000 }, /* R555 */ + { 0x0000, 0x0000, 0x0000 }, /* R556 */ + { 0x0000, 0x0000, 0x0000 }, /* R557 */ + { 0x0000, 0x0000, 0x0000 }, /* R558 */ + { 0x0000, 0x0000, 0x0000 }, /* R559 */ + { 0x0030, 0x0030, 0xFFFF }, /* R560 - Interrupt Status 1 */ + { 0xFFED, 0xFFED, 0xFFFF }, /* R561 - Interrupt Status 2 */ + { 0x0000, 0x0000, 0x0000 }, /* R562 */ + { 0x0000, 0x0000, 0x0000 }, /* R563 */ + { 0x0000, 0x0000, 0x0000 }, /* R564 */ + { 0x0000, 0x0000, 0x0000 }, /* R565 */ + { 0x0000, 0x0000, 0x0000 }, /* R566 */ + { 0x0000, 0x0000, 0x0000 }, /* R567 */ + { 0x0030, 0x0030, 0x0000 }, /* R568 - Interrupt Status 1 Mask */ + { 0xFFED, 0xFFED, 0x0000 }, /* R569 - Interrupt Status 2 Mask */ + { 0x0000, 0x0000, 0x0000 }, /* R570 */ + { 0x0000, 0x0000, 0x0000 }, /* R571 */ + { 0x0000, 0x0000, 0x0000 }, /* R572 */ + { 0x0000, 0x0000, 0x0000 }, /* R573 */ + { 0x0000, 0x0000, 0x0000 }, /* R574 */ + { 0x0000, 0x0000, 0x0000 }, /* R575 */ + { 0x0001, 0x0001, 0x0000 }, /* R576 - Interrupt Control */ + { 0x0000, 0x0000, 0x0000 }, /* R577 */ + { 0x0000, 0x0000, 0x0000 }, /* R578 */ + { 0x0000, 0x0000, 0x0000 }, /* R579 */ + { 0x0000, 0x0000, 0x0000 }, /* R580 */ + { 0x0000, 0x0000, 0x0000 }, /* R581 */ + { 0x0000, 0x0000, 0x0000 }, /* R582 */ + { 0x0000, 0x0000, 0x0000 }, /* R583 */ + { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */ + { 0x0000, 0x0000, 0x0000 }, /* R585 */ + { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */ + { 0x0000, 0x0000, 0x0000 }, /* R587 */ + { 0x0000, 0x0000, 0x0000 }, /* R588 */ + { 0x0000, 0x0000, 0x0000 }, /* R589 */ + { 0x0000, 0x0000, 0x0000 }, /* R590 */ + { 0x0000, 0x0000, 0x0000 }, /* R591 */ + { 0x0000, 0x0000, 0x0000 }, /* R592 */ + { 0x0000, 0x0000, 0x0000 }, /* R593 */ + { 0x0000, 0x0000, 0x0000 }, /* R594 */ + { 0x0000, 0x0000, 0x0000 }, /* R595 */ + { 0x0000, 0x0000, 0x0000 }, /* R596 */ + { 0x0000, 0x0000, 0x0000 }, /* R597 */ + { 0x0000, 0x0000, 0x0000 }, /* R598 */ + { 0x0000, 0x0000, 0x0000 }, /* R599 */ + { 0x0000, 0x0000, 0x0000 }, /* R600 */ + { 0x0000, 0x0000, 0x0000 }, /* R601 */ + { 0x0000, 0x0000, 0x0000 }, /* R602 */ + { 0x0000, 0x0000, 0x0000 }, /* R603 */ + { 0x0000, 0x0000, 0x0000 }, /* R604 */ + { 0x0000, 0x0000, 0x0000 }, /* R605 */ + { 0x0000, 0x0000, 0x0000 }, /* R606 */ + { 0x0000, 0x0000, 0x0000 }, /* R607 */ + { 0x0000, 0x0000, 0x0000 }, /* R608 */ + { 0x0000, 0x0000, 0x0000 }, /* R609 */ + { 0x0000, 0x0000, 0x0000 }, /* R610 */ + { 0x0000, 0x0000, 0x0000 }, /* R611 */ + { 0x0000, 0x0000, 0x0000 }, /* R612 */ + { 0x0000, 0x0000, 0x0000 }, /* R613 */ + { 0x0000, 0x0000, 0x0000 }, /* R614 */ + { 0x0000, 0x0000, 0x0000 }, /* R615 */ + { 0x0000, 0x0000, 0x0000 }, /* R616 */ + { 0x0000, 0x0000, 0x0000 }, /* R617 */ + { 0x0000, 0x0000, 0x0000 }, /* R618 */ + { 0x0000, 0x0000, 0x0000 }, /* R619 */ + { 0x0000, 0x0000, 0x0000 }, /* R620 */ + { 0x0000, 0x0000, 0x0000 }, /* R621 */ + { 0x0000, 0x0000, 0x0000 }, /* R622 */ + { 0x0000, 0x0000, 0x0000 }, /* R623 */ + { 0x0000, 0x0000, 0x0000 }, /* R624 */ + { 0x0000, 0x0000, 0x0000 }, /* R625 */ + { 0x0000, 0x0000, 0x0000 }, /* R626 */ + { 0x0000, 0x0000, 0x0000 }, /* R627 */ + { 0x0000, 0x0000, 0x0000 }, /* R628 */ + { 0x0000, 0x0000, 0x0000 }, /* R629 */ + { 0x0000, 0x0000, 0x0000 }, /* R630 */ + { 0x0000, 0x0000, 0x0000 }, /* R631 */ + { 0x0000, 0x0000, 0x0000 }, /* R632 */ + { 0x0000, 0x0000, 0x0000 }, /* R633 */ + { 0x0000, 0x0000, 0x0000 }, /* R634 */ + { 0x0000, 0x0000, 0x0000 }, /* R635 */ + { 0x0000, 0x0000, 0x0000 }, /* R636 */ + { 0x0000, 0x0000, 0x0000 }, /* R637 */ + { 0x0000, 0x0000, 0x0000 }, /* R638 */ + { 0x0000, 0x0000, 0x0000 }, /* R639 */ + { 0x0000, 0x0000, 0x0000 }, /* R640 */ + { 0x0000, 0x0000, 0x0000 }, /* R641 */ + { 0x0000, 0x0000, 0x0000 }, /* R642 */ + { 0x0000, 0x0000, 0x0000 }, /* R643 */ + { 0x0000, 0x0000, 0x0000 }, /* R644 */ + { 0x0000, 0x0000, 0x0000 }, /* R645 */ + { 0x0000, 0x0000, 0x0000 }, /* R646 */ + { 0x0000, 0x0000, 0x0000 }, /* R647 */ + { 0x0000, 0x0000, 0x0000 }, /* R648 */ + { 0x0000, 0x0000, 0x0000 }, /* R649 */ + { 0x0000, 0x0000, 0x0000 }, /* R650 */ + { 0x0000, 0x0000, 0x0000 }, /* R651 */ + { 0x0000, 0x0000, 0x0000 }, /* R652 */ + { 0x0000, 0x0000, 0x0000 }, /* R653 */ + { 0x0000, 0x0000, 0x0000 }, /* R654 */ + { 0x0000, 0x0000, 0x0000 }, /* R655 */ + { 0x0000, 0x0000, 0x0000 }, /* R656 */ + { 0x0000, 0x0000, 0x0000 }, /* R657 */ + { 0x0000, 0x0000, 0x0000 }, /* R658 */ + { 0x0000, 0x0000, 0x0000 }, /* R659 */ + { 0x0000, 0x0000, 0x0000 }, /* R660 */ + { 0x0000, 0x0000, 0x0000 }, /* R661 */ + { 0x0000, 0x0000, 0x0000 }, /* R662 */ + { 0x0000, 0x0000, 0x0000 }, /* R663 */ + { 0x0000, 0x0000, 0x0000 }, /* R664 */ + { 0x0000, 0x0000, 0x0000 }, /* R665 */ + { 0x0000, 0x0000, 0x0000 }, /* R666 */ + { 0x0000, 0x0000, 0x0000 }, /* R667 */ + { 0x0000, 0x0000, 0x0000 }, /* R668 */ + { 0x0000, 0x0000, 0x0000 }, /* R669 */ + { 0x0000, 0x0000, 0x0000 }, /* R670 */ + { 0x0000, 0x0000, 0x0000 }, /* R671 */ + { 0x0000, 0x0000, 0x0000 }, /* R672 */ + { 0x0000, 0x0000, 0x0000 }, /* R673 */ + { 0x0000, 0x0000, 0x0000 }, /* R674 */ + { 0x0000, 0x0000, 0x0000 }, /* R675 */ + { 0x0000, 0x0000, 0x0000 }, /* R676 */ + { 0x0000, 0x0000, 0x0000 }, /* R677 */ + { 0x0000, 0x0000, 0x0000 }, /* R678 */ + { 0x0000, 0x0000, 0x0000 }, /* R679 */ + { 0x0000, 0x0000, 0x0000 }, /* R680 */ + { 0x0000, 0x0000, 0x0000 }, /* R681 */ + { 0x0000, 0x0000, 0x0000 }, /* R682 */ + { 0x0000, 0x0000, 0x0000 }, /* R683 */ + { 0x0000, 0x0000, 0x0000 }, /* R684 */ + { 0x0000, 0x0000, 0x0000 }, /* R685 */ + { 0x0000, 0x0000, 0x0000 }, /* R686 */ + { 0x0000, 0x0000, 0x0000 }, /* R687 */ + { 0x0000, 0x0000, 0x0000 }, /* R688 */ + { 0x0000, 0x0000, 0x0000 }, /* R689 */ + { 0x0000, 0x0000, 0x0000 }, /* R690 */ + { 0x0000, 0x0000, 0x0000 }, /* R691 */ + { 0x0000, 0x0000, 0x0000 }, /* R692 */ + { 0x0000, 0x0000, 0x0000 }, /* R693 */ + { 0x0000, 0x0000, 0x0000 }, /* R694 */ + { 0x0000, 0x0000, 0x0000 }, /* R695 */ + { 0x0000, 0x0000, 0x0000 }, /* R696 */ + { 0x0000, 0x0000, 0x0000 }, /* R697 */ + { 0x0000, 0x0000, 0x0000 }, /* R698 */ + { 0x0000, 0x0000, 0x0000 }, /* R699 */ + { 0x0000, 0x0000, 0x0000 }, /* R700 */ + { 0x0000, 0x0000, 0x0000 }, /* R701 */ + { 0x0000, 0x0000, 0x0000 }, /* R702 */ + { 0x0000, 0x0000, 0x0000 }, /* R703 */ + { 0x0000, 0x0000, 0x0000 }, /* R704 */ + { 0x0000, 0x0000, 0x0000 }, /* R705 */ + { 0x0000, 0x0000, 0x0000 }, /* R706 */ + { 0x0000, 0x0000, 0x0000 }, /* R707 */ + { 0x0000, 0x0000, 0x0000 }, /* R708 */ + { 0x0000, 0x0000, 0x0000 }, /* R709 */ + { 0x0000, 0x0000, 0x0000 }, /* R710 */ + { 0x0000, 0x0000, 0x0000 }, /* R711 */ + { 0x0000, 0x0000, 0x0000 }, /* R712 */ + { 0x0000, 0x0000, 0x0000 }, /* R713 */ + { 0x0000, 0x0000, 0x0000 }, /* R714 */ + { 0x0000, 0x0000, 0x0000 }, /* R715 */ + { 0x0000, 0x0000, 0x0000 }, /* R716 */ + { 0x0000, 0x0000, 0x0000 }, /* R717 */ + { 0x0000, 0x0000, 0x0000 }, /* R718 */ + { 0x0000, 0x0000, 0x0000 }, /* R719 */ + { 0x0000, 0x0000, 0x0000 }, /* R720 */ + { 0x0000, 0x0000, 0x0000 }, /* R721 */ + { 0x0000, 0x0000, 0x0000 }, /* R722 */ + { 0x0000, 0x0000, 0x0000 }, /* R723 */ + { 0x0000, 0x0000, 0x0000 }, /* R724 */ + { 0x0000, 0x0000, 0x0000 }, /* R725 */ + { 0x0000, 0x0000, 0x0000 }, /* R726 */ + { 0x0000, 0x0000, 0x0000 }, /* R727 */ + { 0x0000, 0x0000, 0x0000 }, /* R728 */ + { 0x0000, 0x0000, 0x0000 }, /* R729 */ + { 0x0000, 0x0000, 0x0000 }, /* R730 */ + { 0x0000, 0x0000, 0x0000 }, /* R731 */ + { 0x0000, 0x0000, 0x0000 }, /* R732 */ + { 0x0000, 0x0000, 0x0000 }, /* R733 */ + { 0x0000, 0x0000, 0x0000 }, /* R734 */ + { 0x0000, 0x0000, 0x0000 }, /* R735 */ + { 0x0000, 0x0000, 0x0000 }, /* R736 */ + { 0x0000, 0x0000, 0x0000 }, /* R737 */ + { 0x0000, 0x0000, 0x0000 }, /* R738 */ + { 0x0000, 0x0000, 0x0000 }, /* R739 */ + { 0x0000, 0x0000, 0x0000 }, /* R740 */ + { 0x0000, 0x0000, 0x0000 }, /* R741 */ + { 0x0000, 0x0000, 0x0000 }, /* R742 */ + { 0x0000, 0x0000, 0x0000 }, /* R743 */ + { 0x0000, 0x0000, 0x0000 }, /* R744 */ + { 0x0000, 0x0000, 0x0000 }, /* R745 */ + { 0x0000, 0x0000, 0x0000 }, /* R746 */ + { 0x0000, 0x0000, 0x0000 }, /* R747 */ + { 0x0000, 0x0000, 0x0000 }, /* R748 */ + { 0x0000, 0x0000, 0x0000 }, /* R749 */ + { 0x0000, 0x0000, 0x0000 }, /* R750 */ + { 0x0000, 0x0000, 0x0000 }, /* R751 */ + { 0x0000, 0x0000, 0x0000 }, /* R752 */ + { 0x0000, 0x0000, 0x0000 }, /* R753 */ + { 0x0000, 0x0000, 0x0000 }, /* R754 */ + { 0x0000, 0x0000, 0x0000 }, /* R755 */ + { 0x0000, 0x0000, 0x0000 }, /* R756 */ + { 0x0000, 0x0000, 0x0000 }, /* R757 */ + { 0x0000, 0x0000, 0x0000 }, /* R758 */ + { 0x0000, 0x0000, 0x0000 }, /* R759 */ + { 0x0000, 0x0000, 0x0000 }, /* R760 */ + { 0x0000, 0x0000, 0x0000 }, /* R761 */ + { 0x0000, 0x0000, 0x0000 }, /* R762 */ + { 0x0000, 0x0000, 0x0000 }, /* R763 */ + { 0x0000, 0x0000, 0x0000 }, /* R764 */ + { 0x0000, 0x0000, 0x0000 }, /* R765 */ + { 0x0000, 0x0000, 0x0000 }, /* R766 */ + { 0x0000, 0x0000, 0x0000 }, /* R767 */ + { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */ + { 0x0000, 0x0000, 0x0000 }, /* R769 */ + { 0x0000, 0x0000, 0x0000 }, /* R770 */ + { 0x0000, 0x0000, 0x0000 }, /* R771 */ + { 0x0000, 0x0000, 0x0000 }, /* R772 */ + { 0x0000, 0x0000, 0x0000 }, /* R773 */ + { 0x0000, 0x0000, 0x0000 }, /* R774 */ + { 0x0000, 0x0000, 0x0000 }, /* R775 */ + { 0x0000, 0x0000, 0x0000 }, /* R776 */ + { 0x0000, 0x0000, 0x0000 }, /* R777 */ + { 0x0000, 0x0000, 0x0000 }, /* R778 */ + { 0x0000, 0x0000, 0x0000 }, /* R779 */ + { 0x0000, 0x0000, 0x0000 }, /* R780 */ + { 0x0000, 0x0000, 0x0000 }, /* R781 */ + { 0x0000, 0x0000, 0x0000 }, /* R782 */ + { 0x0000, 0x0000, 0x0000 }, /* R783 */ + { 0x0000, 0x0000, 0x0000 }, /* R784 */ + { 0x0000, 0x0000, 0x0000 }, /* R785 */ + { 0x0000, 0x0000, 0x0000 }, /* R786 */ + { 0x0000, 0x0000, 0x0000 }, /* R787 */ + { 0x0000, 0x0000, 0x0000 }, /* R788 */ + { 0x0000, 0x0000, 0x0000 }, /* R789 */ + { 0x0000, 0x0000, 0x0000 }, /* R790 */ + { 0x0000, 0x0000, 0x0000 }, /* R791 */ + { 0x0000, 0x0000, 0x0000 }, /* R792 */ + { 0x0000, 0x0000, 0x0000 }, /* R793 */ + { 0x0000, 0x0000, 0x0000 }, /* R794 */ + { 0x0000, 0x0000, 0x0000 }, /* R795 */ + { 0x0000, 0x0000, 0x0000 }, /* R796 */ + { 0x0000, 0x0000, 0x0000 }, /* R797 */ + { 0x0000, 0x0000, 0x0000 }, /* R798 */ + { 0x0000, 0x0000, 0x0000 }, /* R799 */ + { 0x0000, 0x0000, 0x0000 }, /* R800 */ + { 0x0000, 0x0000, 0x0000 }, /* R801 */ + { 0x0000, 0x0000, 0x0000 }, /* R802 */ + { 0x0000, 0x0000, 0x0000 }, /* R803 */ + { 0x0000, 0x0000, 0x0000 }, /* R804 */ + { 0x0000, 0x0000, 0x0000 }, /* R805 */ + { 0x0000, 0x0000, 0x0000 }, /* R806 */ + { 0x0000, 0x0000, 0x0000 }, /* R807 */ + { 0x0000, 0x0000, 0x0000 }, /* R808 */ + { 0x0000, 0x0000, 0x0000 }, /* R809 */ + { 0x0000, 0x0000, 0x0000 }, /* R810 */ + { 0x0000, 0x0000, 0x0000 }, /* R811 */ + { 0x0000, 0x0000, 0x0000 }, /* R812 */ + { 0x0000, 0x0000, 0x0000 }, /* R813 */ + { 0x0000, 0x0000, 0x0000 }, /* R814 */ + { 0x0000, 0x0000, 0x0000 }, /* R815 */ + { 0x0000, 0x0000, 0x0000 }, /* R816 */ + { 0x0000, 0x0000, 0x0000 }, /* R817 */ + { 0x0000, 0x0000, 0x0000 }, /* R818 */ + { 0x0000, 0x0000, 0x0000 }, /* R819 */ + { 0x0000, 0x0000, 0x0000 }, /* R820 */ + { 0x0000, 0x0000, 0x0000 }, /* R821 */ + { 0x0000, 0x0000, 0x0000 }, /* R822 */ + { 0x0000, 0x0000, 0x0000 }, /* R823 */ + { 0x0000, 0x0000, 0x0000 }, /* R824 */ + { 0x0000, 0x0000, 0x0000 }, /* R825 */ + { 0x0000, 0x0000, 0x0000 }, /* R826 */ + { 0x0000, 0x0000, 0x0000 }, /* R827 */ + { 0x0000, 0x0000, 0x0000 }, /* R828 */ + { 0x0000, 0x0000, 0x0000 }, /* R829 */ + { 0x0000, 0x0000, 0x0000 }, /* R830 */ + { 0x0000, 0x0000, 0x0000 }, /* R831 */ + { 0x0000, 0x0000, 0x0000 }, /* R832 */ + { 0x0000, 0x0000, 0x0000 }, /* R833 */ + { 0x0000, 0x0000, 0x0000 }, /* R834 */ + { 0x0000, 0x0000, 0x0000 }, /* R835 */ + { 0x0000, 0x0000, 0x0000 }, /* R836 */ + { 0x0000, 0x0000, 0x0000 }, /* R837 */ + { 0x0000, 0x0000, 0x0000 }, /* R838 */ + { 0x0000, 0x0000, 0x0000 }, /* R839 */ + { 0x0000, 0x0000, 0x0000 }, /* R840 */ + { 0x0000, 0x0000, 0x0000 }, /* R841 */ + { 0x0000, 0x0000, 0x0000 }, /* R842 */ + { 0x0000, 0x0000, 0x0000 }, /* R843 */ + { 0x0000, 0x0000, 0x0000 }, /* R844 */ + { 0x0000, 0x0000, 0x0000 }, /* R845 */ + { 0x0000, 0x0000, 0x0000 }, /* R846 */ + { 0x0000, 0x0000, 0x0000 }, /* R847 */ + { 0x0000, 0x0000, 0x0000 }, /* R848 */ + { 0x0000, 0x0000, 0x0000 }, /* R849 */ + { 0x0000, 0x0000, 0x0000 }, /* R850 */ + { 0x0000, 0x0000, 0x0000 }, /* R851 */ + { 0x0000, 0x0000, 0x0000 }, /* R852 */ + { 0x0000, 0x0000, 0x0000 }, /* R853 */ + { 0x0000, 0x0000, 0x0000 }, /* R854 */ + { 0x0000, 0x0000, 0x0000 }, /* R855 */ + { 0x0000, 0x0000, 0x0000 }, /* R856 */ + { 0x0000, 0x0000, 0x0000 }, /* R857 */ + { 0x0000, 0x0000, 0x0000 }, /* R858 */ + { 0x0000, 0x0000, 0x0000 }, /* R859 */ + { 0x0000, 0x0000, 0x0000 }, /* R860 */ + { 0x0000, 0x0000, 0x0000 }, /* R861 */ + { 0x0000, 0x0000, 0x0000 }, /* R862 */ + { 0x0000, 0x0000, 0x0000 }, /* R863 */ + { 0x0000, 0x0000, 0x0000 }, /* R864 */ + { 0x0000, 0x0000, 0x0000 }, /* R865 */ + { 0x0000, 0x0000, 0x0000 }, /* R866 */ + { 0x0000, 0x0000, 0x0000 }, /* R867 */ + { 0x0000, 0x0000, 0x0000 }, /* R868 */ + { 0x0000, 0x0000, 0x0000 }, /* R869 */ + { 0x0000, 0x0000, 0x0000 }, /* R870 */ + { 0x0000, 0x0000, 0x0000 }, /* R871 */ + { 0x0000, 0x0000, 0x0000 }, /* R872 */ + { 0x0000, 0x0000, 0x0000 }, /* R873 */ + { 0x0000, 0x0000, 0x0000 }, /* R874 */ + { 0x0000, 0x0000, 0x0000 }, /* R875 */ + { 0x0000, 0x0000, 0x0000 }, /* R876 */ + { 0x0000, 0x0000, 0x0000 }, /* R877 */ + { 0x0000, 0x0000, 0x0000 }, /* R878 */ + { 0x0000, 0x0000, 0x0000 }, /* R879 */ + { 0x0000, 0x0000, 0x0000 }, /* R880 */ + { 0x0000, 0x0000, 0x0000 }, /* R881 */ + { 0x0000, 0x0000, 0x0000 }, /* R882 */ + { 0x0000, 0x0000, 0x0000 }, /* R883 */ + { 0x0000, 0x0000, 0x0000 }, /* R884 */ + { 0x0000, 0x0000, 0x0000 }, /* R885 */ + { 0x0000, 0x0000, 0x0000 }, /* R886 */ + { 0x0000, 0x0000, 0x0000 }, /* R887 */ + { 0x0000, 0x0000, 0x0000 }, /* R888 */ + { 0x0000, 0x0000, 0x0000 }, /* R889 */ + { 0x0000, 0x0000, 0x0000 }, /* R890 */ + { 0x0000, 0x0000, 0x0000 }, /* R891 */ + { 0x0000, 0x0000, 0x0000 }, /* R892 */ + { 0x0000, 0x0000, 0x0000 }, /* R893 */ + { 0x0000, 0x0000, 0x0000 }, /* R894 */ + { 0x0000, 0x0000, 0x0000 }, /* R895 */ + { 0x0000, 0x0000, 0x0000 }, /* R896 */ + { 0x0000, 0x0000, 0x0000 }, /* R897 */ + { 0x0000, 0x0000, 0x0000 }, /* R898 */ + { 0x0000, 0x0000, 0x0000 }, /* R899 */ + { 0x0000, 0x0000, 0x0000 }, /* R900 */ + { 0x0000, 0x0000, 0x0000 }, /* R901 */ + { 0x0000, 0x0000, 0x0000 }, /* R902 */ + { 0x0000, 0x0000, 0x0000 }, /* R903 */ + { 0x0000, 0x0000, 0x0000 }, /* R904 */ + { 0x0000, 0x0000, 0x0000 }, /* R905 */ + { 0x0000, 0x0000, 0x0000 }, /* R906 */ + { 0x0000, 0x0000, 0x0000 }, /* R907 */ + { 0x0000, 0x0000, 0x0000 }, /* R908 */ + { 0x0000, 0x0000, 0x0000 }, /* R909 */ + { 0x0000, 0x0000, 0x0000 }, /* R910 */ + { 0x0000, 0x0000, 0x0000 }, /* R911 */ + { 0x0000, 0x0000, 0x0000 }, /* R912 */ + { 0x0000, 0x0000, 0x0000 }, /* R913 */ + { 0x0000, 0x0000, 0x0000 }, /* R914 */ + { 0x0000, 0x0000, 0x0000 }, /* R915 */ + { 0x0000, 0x0000, 0x0000 }, /* R916 */ + { 0x0000, 0x0000, 0x0000 }, /* R917 */ + { 0x0000, 0x0000, 0x0000 }, /* R918 */ + { 0x0000, 0x0000, 0x0000 }, /* R919 */ + { 0x0000, 0x0000, 0x0000 }, /* R920 */ + { 0x0000, 0x0000, 0x0000 }, /* R921 */ + { 0x0000, 0x0000, 0x0000 }, /* R922 */ + { 0x0000, 0x0000, 0x0000 }, /* R923 */ + { 0x0000, 0x0000, 0x0000 }, /* R924 */ + { 0x0000, 0x0000, 0x0000 }, /* R925 */ + { 0x0000, 0x0000, 0x0000 }, /* R926 */ + { 0x0000, 0x0000, 0x0000 }, /* R927 */ + { 0x0000, 0x0000, 0x0000 }, /* R928 */ + { 0x0000, 0x0000, 0x0000 }, /* R929 */ + { 0x0000, 0x0000, 0x0000 }, /* R930 */ + { 0x0000, 0x0000, 0x0000 }, /* R931 */ + { 0x0000, 0x0000, 0x0000 }, /* R932 */ + { 0x0000, 0x0000, 0x0000 }, /* R933 */ + { 0x0000, 0x0000, 0x0000 }, /* R934 */ + { 0x0000, 0x0000, 0x0000 }, /* R935 */ + { 0x0000, 0x0000, 0x0000 }, /* R936 */ + { 0x0000, 0x0000, 0x0000 }, /* R937 */ + { 0x0000, 0x0000, 0x0000 }, /* R938 */ + { 0x0000, 0x0000, 0x0000 }, /* R939 */ + { 0x0000, 0x0000, 0x0000 }, /* R940 */ + { 0x0000, 0x0000, 0x0000 }, /* R941 */ + { 0x0000, 0x0000, 0x0000 }, /* R942 */ + { 0x0000, 0x0000, 0x0000 }, /* R943 */ + { 0x0000, 0x0000, 0x0000 }, /* R944 */ + { 0x0000, 0x0000, 0x0000 }, /* R945 */ + { 0x0000, 0x0000, 0x0000 }, /* R946 */ + { 0x0000, 0x0000, 0x0000 }, /* R947 */ + { 0x0000, 0x0000, 0x0000 }, /* R948 */ + { 0x0000, 0x0000, 0x0000 }, /* R949 */ + { 0x0000, 0x0000, 0x0000 }, /* R950 */ + { 0x0000, 0x0000, 0x0000 }, /* R951 */ + { 0x0000, 0x0000, 0x0000 }, /* R952 */ + { 0x0000, 0x0000, 0x0000 }, /* R953 */ + { 0x0000, 0x0000, 0x0000 }, /* R954 */ + { 0x0000, 0x0000, 0x0000 }, /* R955 */ + { 0x0000, 0x0000, 0x0000 }, /* R956 */ + { 0x0000, 0x0000, 0x0000 }, /* R957 */ + { 0x0000, 0x0000, 0x0000 }, /* R958 */ + { 0x0000, 0x0000, 0x0000 }, /* R959 */ + { 0x0000, 0x0000, 0x0000 }, /* R960 */ + { 0x0000, 0x0000, 0x0000 }, /* R961 */ + { 0x0000, 0x0000, 0x0000 }, /* R962 */ + { 0x0000, 0x0000, 0x0000 }, /* R963 */ + { 0x0000, 0x0000, 0x0000 }, /* R964 */ + { 0x0000, 0x0000, 0x0000 }, /* R965 */ + { 0x0000, 0x0000, 0x0000 }, /* R966 */ + { 0x0000, 0x0000, 0x0000 }, /* R967 */ + { 0x0000, 0x0000, 0x0000 }, /* R968 */ + { 0x0000, 0x0000, 0x0000 }, /* R969 */ + { 0x0000, 0x0000, 0x0000 }, /* R970 */ + { 0x0000, 0x0000, 0x0000 }, /* R971 */ + { 0x0000, 0x0000, 0x0000 }, /* R972 */ + { 0x0000, 0x0000, 0x0000 }, /* R973 */ + { 0x0000, 0x0000, 0x0000 }, /* R974 */ + { 0x0000, 0x0000, 0x0000 }, /* R975 */ + { 0x0000, 0x0000, 0x0000 }, /* R976 */ + { 0x0000, 0x0000, 0x0000 }, /* R977 */ + { 0x0000, 0x0000, 0x0000 }, /* R978 */ + { 0x0000, 0x0000, 0x0000 }, /* R979 */ + { 0x0000, 0x0000, 0x0000 }, /* R980 */ + { 0x0000, 0x0000, 0x0000 }, /* R981 */ + { 0x0000, 0x0000, 0x0000 }, /* R982 */ + { 0x0000, 0x0000, 0x0000 }, /* R983 */ + { 0x0000, 0x0000, 0x0000 }, /* R984 */ + { 0x0000, 0x0000, 0x0000 }, /* R985 */ + { 0x0000, 0x0000, 0x0000 }, /* R986 */ + { 0x0000, 0x0000, 0x0000 }, /* R987 */ + { 0x0000, 0x0000, 0x0000 }, /* R988 */ + { 0x0000, 0x0000, 0x0000 }, /* R989 */ + { 0x0000, 0x0000, 0x0000 }, /* R990 */ + { 0x0000, 0x0000, 0x0000 }, /* R991 */ + { 0x0000, 0x0000, 0x0000 }, /* R992 */ + { 0x0000, 0x0000, 0x0000 }, /* R993 */ + { 0x0000, 0x0000, 0x0000 }, /* R994 */ + { 0x0000, 0x0000, 0x0000 }, /* R995 */ + { 0x0000, 0x0000, 0x0000 }, /* R996 */ + { 0x0000, 0x0000, 0x0000 }, /* R997 */ + { 0x0000, 0x0000, 0x0000 }, /* R998 */ + { 0x0000, 0x0000, 0x0000 }, /* R999 */ + { 0x0000, 0x0000, 0x0000 }, /* R1000 */ + { 0x0000, 0x0000, 0x0000 }, /* R1001 */ + { 0x0000, 0x0000, 0x0000 }, /* R1002 */ + { 0x0000, 0x0000, 0x0000 }, /* R1003 */ + { 0x0000, 0x0000, 0x0000 }, /* R1004 */ + { 0x0000, 0x0000, 0x0000 }, /* R1005 */ + { 0x0000, 0x0000, 0x0000 }, /* R1006 */ + { 0x0000, 0x0000, 0x0000 }, /* R1007 */ + { 0x0000, 0x0000, 0x0000 }, /* R1008 */ + { 0x0000, 0x0000, 0x0000 }, /* R1009 */ + { 0x0000, 0x0000, 0x0000 }, /* R1010 */ + { 0x0000, 0x0000, 0x0000 }, /* R1011 */ + { 0x0000, 0x0000, 0x0000 }, /* R1012 */ + { 0x0000, 0x0000, 0x0000 }, /* R1013 */ + { 0x0000, 0x0000, 0x0000 }, /* R1014 */ + { 0x0000, 0x0000, 0x0000 }, /* R1015 */ + { 0x0000, 0x0000, 0x0000 }, /* R1016 */ + { 0x0000, 0x0000, 0x0000 }, /* R1017 */ + { 0x0000, 0x0000, 0x0000 }, /* R1018 */ + { 0x0000, 0x0000, 0x0000 }, /* R1019 */ + { 0x0000, 0x0000, 0x0000 }, /* R1020 */ + { 0x0000, 0x0000, 0x0000 }, /* R1021 */ + { 0x0000, 0x0000, 0x0000 }, /* R1022 */ + { 0x0000, 0x0000, 0x0000 }, /* R1023 */ + { 0x0000, 0x0000, 0x0000 }, /* R1024 */ + { 0x0000, 0x0000, 0x0000 }, /* R1025 */ + { 0x0000, 0x0000, 0x0000 }, /* R1026 */ + { 0x0000, 0x0000, 0x0000 }, /* R1027 */ + { 0x0000, 0x0000, 0x0000 }, /* R1028 */ + { 0x0000, 0x0000, 0x0000 }, /* R1029 */ + { 0x0000, 0x0000, 0x0000 }, /* R1030 */ + { 0x0000, 0x0000, 0x0000 }, /* R1031 */ + { 0x0000, 0x0000, 0x0000 }, /* R1032 */ + { 0x0000, 0x0000, 0x0000 }, /* R1033 */ + { 0x0000, 0x0000, 0x0000 }, /* R1034 */ + { 0x0000, 0x0000, 0x0000 }, /* R1035 */ + { 0x0000, 0x0000, 0x0000 }, /* R1036 */ + { 0x0000, 0x003F, 0x0000 }, /* R1037 - DSP2_ExecControl */ + { 0x0000, 0x0000, 0x0000 }, /* R1038 */ + { 0x0000, 0x0000, 0x0000 }, /* R1039 */ + { 0x0000, 0x0000, 0x0000 }, /* R1040 */ + { 0x0000, 0x0000, 0x0000 }, /* R1041 */ + { 0x0000, 0x0000, 0x0000 }, /* R1042 */ + { 0x0000, 0x0000, 0x0000 }, /* R1043 */ + { 0x0000, 0x0000, 0x0000 }, /* R1044 */ + { 0x0000, 0x0000, 0x0000 }, /* R1045 */ + { 0x0000, 0x0000, 0x0000 }, /* R1046 */ + { 0x0000, 0x0000, 0x0000 }, /* R1047 */ + { 0x0000, 0x0000, 0x0000 }, /* R1048 */ + { 0x0000, 0x0000, 0x0000 }, /* R1049 */ + { 0x0000, 0x0000, 0x0000 }, /* R1050 */ + { 0x0000, 0x0000, 0x0000 }, /* R1051 */ + { 0x0000, 0x0000, 0x0000 }, /* R1052 */ + { 0x0000, 0x0000, 0x0000 }, /* R1053 */ + { 0x0000, 0x0000, 0x0000 }, /* R1054 */ + { 0x0000, 0x0000, 0x0000 }, /* R1055 */ + { 0x0000, 0x0000, 0x0000 }, /* R1056 */ + { 0x0000, 0x0000, 0x0000 }, /* R1057 */ + { 0x0000, 0x0000, 0x0000 }, /* R1058 */ + { 0x0000, 0x0000, 0x0000 }, /* R1059 */ + { 0x0000, 0x0000, 0x0000 }, /* R1060 */ + { 0x0000, 0x0000, 0x0000 }, /* R1061 */ + { 0x0000, 0x0000, 0x0000 }, /* R1062 */ + { 0x0000, 0x0000, 0x0000 }, /* R1063 */ + { 0x0000, 0x0000, 0x0000 }, /* R1064 */ + { 0x0000, 0x0000, 0x0000 }, /* R1065 */ + { 0x0000, 0x0000, 0x0000 }, /* R1066 */ + { 0x0000, 0x0000, 0x0000 }, /* R1067 */ + { 0x0000, 0x0000, 0x0000 }, /* R1068 */ + { 0x0000, 0x0000, 0x0000 }, /* R1069 */ + { 0x0000, 0x0000, 0x0000 }, /* R1070 */ + { 0x0000, 0x0000, 0x0000 }, /* R1071 */ + { 0x0000, 0x0000, 0x0000 }, /* R1072 */ + { 0x0000, 0x0000, 0x0000 }, /* R1073 */ + { 0x0000, 0x0000, 0x0000 }, /* R1074 */ + { 0x0000, 0x0000, 0x0000 }, /* R1075 */ + { 0x0000, 0x0000, 0x0000 }, /* R1076 */ + { 0x0000, 0x0000, 0x0000 }, /* R1077 */ + { 0x0000, 0x0000, 0x0000 }, /* R1078 */ + { 0x0000, 0x0000, 0x0000 }, /* R1079 */ + { 0x0000, 0x0000, 0x0000 }, /* R1080 */ + { 0x0000, 0x0000, 0x0000 }, /* R1081 */ + { 0x0000, 0x0000, 0x0000 }, /* R1082 */ + { 0x0000, 0x0000, 0x0000 }, /* R1083 */ + { 0x0000, 0x0000, 0x0000 }, /* R1084 */ + { 0x0000, 0x0000, 0x0000 }, /* R1085 */ + { 0x0000, 0x0000, 0x0000 }, /* R1086 */ + { 0x0000, 0x0000, 0x0000 }, /* R1087 */ + { 0x0000, 0x0000, 0x0000 }, /* R1088 */ + { 0x0000, 0x0000, 0x0000 }, /* R1089 */ + { 0x0000, 0x0000, 0x0000 }, /* R1090 */ + { 0x0000, 0x0000, 0x0000 }, /* R1091 */ + { 0x0000, 0x0000, 0x0000 }, /* R1092 */ + { 0x0000, 0x0000, 0x0000 }, /* R1093 */ + { 0x0000, 0x0000, 0x0000 }, /* R1094 */ + { 0x0000, 0x0000, 0x0000 }, /* R1095 */ + { 0x0000, 0x0000, 0x0000 }, /* R1096 */ + { 0x0000, 0x0000, 0x0000 }, /* R1097 */ + { 0x0000, 0x0000, 0x0000 }, /* R1098 */ + { 0x0000, 0x0000, 0x0000 }, /* R1099 */ + { 0x0000, 0x0000, 0x0000 }, /* R1100 */ + { 0x0000, 0x0000, 0x0000 }, /* R1101 */ + { 0x0000, 0x0000, 0x0000 }, /* R1102 */ + { 0x0000, 0x0000, 0x0000 }, /* R1103 */ + { 0x0000, 0x0000, 0x0000 }, /* R1104 */ + { 0x0000, 0x0000, 0x0000 }, /* R1105 */ + { 0x0000, 0x0000, 0x0000 }, /* R1106 */ + { 0x0000, 0x0000, 0x0000 }, /* R1107 */ + { 0x0000, 0x0000, 0x0000 }, /* R1108 */ + { 0x0000, 0x0000, 0x0000 }, /* R1109 */ + { 0x0000, 0x0000, 0x0000 }, /* R1110 */ + { 0x0000, 0x0000, 0x0000 }, /* R1111 */ + { 0x0000, 0x0000, 0x0000 }, /* R1112 */ + { 0x0000, 0x0000, 0x0000 }, /* R1113 */ + { 0x0000, 0x0000, 0x0000 }, /* R1114 */ + { 0x0000, 0x0000, 0x0000 }, /* R1115 */ + { 0x0000, 0x0000, 0x0000 }, /* R1116 */ + { 0x0000, 0x0000, 0x0000 }, /* R1117 */ + { 0x0000, 0x0000, 0x0000 }, /* R1118 */ + { 0x0000, 0x0000, 0x0000 }, /* R1119 */ + { 0x0000, 0x0000, 0x0000 }, /* R1120 */ + { 0x0000, 0x0000, 0x0000 }, /* R1121 */ + { 0x0000, 0x0000, 0x0000 }, /* R1122 */ + { 0x0000, 0x0000, 0x0000 }, /* R1123 */ + { 0x0000, 0x0000, 0x0000 }, /* R1124 */ + { 0x0000, 0x0000, 0x0000 }, /* R1125 */ + { 0x0000, 0x0000, 0x0000 }, /* R1126 */ + { 0x0000, 0x0000, 0x0000 }, /* R1127 */ + { 0x0000, 0x0000, 0x0000 }, /* R1128 */ + { 0x0000, 0x0000, 0x0000 }, /* R1129 */ + { 0x0000, 0x0000, 0x0000 }, /* R1130 */ + { 0x0000, 0x0000, 0x0000 }, /* R1131 */ + { 0x0000, 0x0000, 0x0000 }, /* R1132 */ + { 0x0000, 0x0000, 0x0000 }, /* R1133 */ + { 0x0000, 0x0000, 0x0000 }, /* R1134 */ + { 0x0000, 0x0000, 0x0000 }, /* R1135 */ + { 0x0000, 0x0000, 0x0000 }, /* R1136 */ + { 0x0000, 0x0000, 0x0000 }, /* R1137 */ + { 0x0000, 0x0000, 0x0000 }, /* R1138 */ + { 0x0000, 0x0000, 0x0000 }, /* R1139 */ + { 0x0000, 0x0000, 0x0000 }, /* R1140 */ + { 0x0000, 0x0000, 0x0000 }, /* R1141 */ + { 0x0000, 0x0000, 0x0000 }, /* R1142 */ + { 0x0000, 0x0000, 0x0000 }, /* R1143 */ + { 0x0000, 0x0000, 0x0000 }, /* R1144 */ + { 0x0000, 0x0000, 0x0000 }, /* R1145 */ + { 0x0000, 0x0000, 0x0000 }, /* R1146 */ + { 0x0000, 0x0000, 0x0000 }, /* R1147 */ + { 0x0000, 0x0000, 0x0000 }, /* R1148 */ + { 0x0000, 0x0000, 0x0000 }, /* R1149 */ + { 0x0000, 0x0000, 0x0000 }, /* R1150 */ + { 0x0000, 0x0000, 0x0000 }, /* R1151 */ + { 0x0000, 0x0000, 0x0000 }, /* R1152 */ + { 0x0000, 0x0000, 0x0000 }, /* R1153 */ + { 0x0000, 0x0000, 0x0000 }, /* R1154 */ + { 0x0000, 0x0000, 0x0000 }, /* R1155 */ + { 0x0000, 0x0000, 0x0000 }, /* R1156 */ + { 0x0000, 0x0000, 0x0000 }, /* R1157 */ + { 0x0000, 0x0000, 0x0000 }, /* R1158 */ + { 0x0000, 0x0000, 0x0000 }, /* R1159 */ + { 0x0000, 0x0000, 0x0000 }, /* R1160 */ + { 0x0000, 0x0000, 0x0000 }, /* R1161 */ + { 0x0000, 0x0000, 0x0000 }, /* R1162 */ + { 0x0000, 0x0000, 0x0000 }, /* R1163 */ + { 0x0000, 0x0000, 0x0000 }, /* R1164 */ + { 0x0000, 0x0000, 0x0000 }, /* R1165 */ + { 0x0000, 0x0000, 0x0000 }, /* R1166 */ + { 0x0000, 0x0000, 0x0000 }, /* R1167 */ + { 0x0000, 0x0000, 0x0000 }, /* R1168 */ + { 0x0000, 0x0000, 0x0000 }, /* R1169 */ + { 0x0000, 0x0000, 0x0000 }, /* R1170 */ + { 0x0000, 0x0000, 0x0000 }, /* R1171 */ + { 0x0000, 0x0000, 0x0000 }, /* R1172 */ + { 0x0000, 0x0000, 0x0000 }, /* R1173 */ + { 0x0000, 0x0000, 0x0000 }, /* R1174 */ + { 0x0000, 0x0000, 0x0000 }, /* R1175 */ + { 0x0000, 0x0000, 0x0000 }, /* R1176 */ + { 0x0000, 0x0000, 0x0000 }, /* R1177 */ + { 0x0000, 0x0000, 0x0000 }, /* R1178 */ + { 0x0000, 0x0000, 0x0000 }, /* R1179 */ + { 0x0000, 0x0000, 0x0000 }, /* R1180 */ + { 0x0000, 0x0000, 0x0000 }, /* R1181 */ + { 0x0000, 0x0000, 0x0000 }, /* R1182 */ + { 0x0000, 0x0000, 0x0000 }, /* R1183 */ + { 0x0000, 0x0000, 0x0000 }, /* R1184 */ + { 0x0000, 0x0000, 0x0000 }, /* R1185 */ + { 0x0000, 0x0000, 0x0000 }, /* R1186 */ + { 0x0000, 0x0000, 0x0000 }, /* R1187 */ + { 0x0000, 0x0000, 0x0000 }, /* R1188 */ + { 0x0000, 0x0000, 0x0000 }, /* R1189 */ + { 0x0000, 0x0000, 0x0000 }, /* R1190 */ + { 0x0000, 0x0000, 0x0000 }, /* R1191 */ + { 0x0000, 0x0000, 0x0000 }, /* R1192 */ + { 0x0000, 0x0000, 0x0000 }, /* R1193 */ + { 0x0000, 0x0000, 0x0000 }, /* R1194 */ + { 0x0000, 0x0000, 0x0000 }, /* R1195 */ + { 0x0000, 0x0000, 0x0000 }, /* R1196 */ + { 0x0000, 0x0000, 0x0000 }, /* R1197 */ + { 0x0000, 0x0000, 0x0000 }, /* R1198 */ + { 0x0000, 0x0000, 0x0000 }, /* R1199 */ + { 0x0000, 0x0000, 0x0000 }, /* R1200 */ + { 0x0000, 0x0000, 0x0000 }, /* R1201 */ + { 0x0000, 0x0000, 0x0000 }, /* R1202 */ + { 0x0000, 0x0000, 0x0000 }, /* R1203 */ + { 0x0000, 0x0000, 0x0000 }, /* R1204 */ + { 0x0000, 0x0000, 0x0000 }, /* R1205 */ + { 0x0000, 0x0000, 0x0000 }, /* R1206 */ + { 0x0000, 0x0000, 0x0000 }, /* R1207 */ + { 0x0000, 0x0000, 0x0000 }, /* R1208 */ + { 0x0000, 0x0000, 0x0000 }, /* R1209 */ + { 0x0000, 0x0000, 0x0000 }, /* R1210 */ + { 0x0000, 0x0000, 0x0000 }, /* R1211 */ + { 0x0000, 0x0000, 0x0000 }, /* R1212 */ + { 0x0000, 0x0000, 0x0000 }, /* R1213 */ + { 0x0000, 0x0000, 0x0000 }, /* R1214 */ + { 0x0000, 0x0000, 0x0000 }, /* R1215 */ + { 0x0000, 0x0000, 0x0000 }, /* R1216 */ + { 0x0000, 0x0000, 0x0000 }, /* R1217 */ + { 0x0000, 0x0000, 0x0000 }, /* R1218 */ + { 0x0000, 0x0000, 0x0000 }, /* R1219 */ + { 0x0000, 0x0000, 0x0000 }, /* R1220 */ + { 0x0000, 0x0000, 0x0000 }, /* R1221 */ + { 0x0000, 0x0000, 0x0000 }, /* R1222 */ + { 0x0000, 0x0000, 0x0000 }, /* R1223 */ + { 0x0000, 0x0000, 0x0000 }, /* R1224 */ + { 0x0000, 0x0000, 0x0000 }, /* R1225 */ + { 0x0000, 0x0000, 0x0000 }, /* R1226 */ + { 0x0000, 0x0000, 0x0000 }, /* R1227 */ + { 0x0000, 0x0000, 0x0000 }, /* R1228 */ + { 0x0000, 0x0000, 0x0000 }, /* R1229 */ + { 0x0000, 0x0000, 0x0000 }, /* R1230 */ + { 0x0000, 0x0000, 0x0000 }, /* R1231 */ + { 0x0000, 0x0000, 0x0000 }, /* R1232 */ + { 0x0000, 0x0000, 0x0000 }, /* R1233 */ + { 0x0000, 0x0000, 0x0000 }, /* R1234 */ + { 0x0000, 0x0000, 0x0000 }, /* R1235 */ + { 0x0000, 0x0000, 0x0000 }, /* R1236 */ + { 0x0000, 0x0000, 0x0000 }, /* R1237 */ + { 0x0000, 0x0000, 0x0000 }, /* R1238 */ + { 0x0000, 0x0000, 0x0000 }, /* R1239 */ + { 0x0000, 0x0000, 0x0000 }, /* R1240 */ + { 0x0000, 0x0000, 0x0000 }, /* R1241 */ + { 0x0000, 0x0000, 0x0000 }, /* R1242 */ + { 0x0000, 0x0000, 0x0000 }, /* R1243 */ + { 0x0000, 0x0000, 0x0000 }, /* R1244 */ + { 0x0000, 0x0000, 0x0000 }, /* R1245 */ + { 0x0000, 0x0000, 0x0000 }, /* R1246 */ + { 0x0000, 0x0000, 0x0000 }, /* R1247 */ + { 0x0000, 0x0000, 0x0000 }, /* R1248 */ + { 0x0000, 0x0000, 0x0000 }, /* R1249 */ + { 0x0000, 0x0000, 0x0000 }, /* R1250 */ + { 0x0000, 0x0000, 0x0000 }, /* R1251 */ + { 0x0000, 0x0000, 0x0000 }, /* R1252 */ + { 0x0000, 0x0000, 0x0000 }, /* R1253 */ + { 0x0000, 0x0000, 0x0000 }, /* R1254 */ + { 0x0000, 0x0000, 0x0000 }, /* R1255 */ + { 0x0000, 0x0000, 0x0000 }, /* R1256 */ + { 0x0000, 0x0000, 0x0000 }, /* R1257 */ + { 0x0000, 0x0000, 0x0000 }, /* R1258 */ + { 0x0000, 0x0000, 0x0000 }, /* R1259 */ + { 0x0000, 0x0000, 0x0000 }, /* R1260 */ + { 0x0000, 0x0000, 0x0000 }, /* R1261 */ + { 0x0000, 0x0000, 0x0000 }, /* R1262 */ + { 0x0000, 0x0000, 0x0000 }, /* R1263 */ + { 0x0000, 0x0000, 0x0000 }, /* R1264 */ + { 0x0000, 0x0000, 0x0000 }, /* R1265 */ + { 0x0000, 0x0000, 0x0000 }, /* R1266 */ + { 0x0000, 0x0000, 0x0000 }, /* R1267 */ + { 0x0000, 0x0000, 0x0000 }, /* R1268 */ + { 0x0000, 0x0000, 0x0000 }, /* R1269 */ + { 0x0000, 0x0000, 0x0000 }, /* R1270 */ + { 0x0000, 0x0000, 0x0000 }, /* R1271 */ + { 0x0000, 0x0000, 0x0000 }, /* R1272 */ + { 0x0000, 0x0000, 0x0000 }, /* R1273 */ + { 0x0000, 0x0000, 0x0000 }, /* R1274 */ + { 0x0000, 0x0000, 0x0000 }, /* R1275 */ + { 0x0000, 0x0000, 0x0000 }, /* R1276 */ + { 0x0000, 0x0000, 0x0000 }, /* R1277 */ + { 0x0000, 0x0000, 0x0000 }, /* R1278 */ + { 0x0000, 0x0000, 0x0000 }, /* R1279 */ + { 0x0000, 0x0000, 0x0000 }, /* R1280 */ + { 0x0000, 0x0000, 0x0000 }, /* R1281 */ + { 0x0000, 0x0000, 0x0000 }, /* R1282 */ + { 0x0000, 0x0000, 0x0000 }, /* R1283 */ + { 0x0000, 0x0000, 0x0000 }, /* R1284 */ + { 0x0000, 0x0000, 0x0000 }, /* R1285 */ + { 0x0000, 0x0000, 0x0000 }, /* R1286 */ + { 0x0000, 0x0000, 0x0000 }, /* R1287 */ + { 0x0000, 0x0000, 0x0000 }, /* R1288 */ + { 0x0000, 0x0000, 0x0000 }, /* R1289 */ + { 0x0000, 0x0000, 0x0000 }, /* R1290 */ + { 0x0000, 0x0000, 0x0000 }, /* R1291 */ + { 0x0000, 0x0000, 0x0000 }, /* R1292 */ + { 0x0000, 0x0000, 0x0000 }, /* R1293 */ + { 0x0000, 0x0000, 0x0000 }, /* R1294 */ + { 0x0000, 0x0000, 0x0000 }, /* R1295 */ + { 0x0000, 0x0000, 0x0000 }, /* R1296 */ + { 0x0000, 0x0000, 0x0000 }, /* R1297 */ + { 0x0000, 0x0000, 0x0000 }, /* R1298 */ + { 0x0000, 0x0000, 0x0000 }, /* R1299 */ + { 0x0000, 0x0000, 0x0000 }, /* R1300 */ + { 0x0000, 0x0000, 0x0000 }, /* R1301 */ + { 0x0000, 0x0000, 0x0000 }, /* R1302 */ + { 0x0000, 0x0000, 0x0000 }, /* R1303 */ + { 0x0000, 0x0000, 0x0000 }, /* R1304 */ + { 0x0000, 0x0000, 0x0000 }, /* R1305 */ + { 0x0000, 0x0000, 0x0000 }, /* R1306 */ + { 0x0000, 0x0000, 0x0000 }, /* R1307 */ + { 0x0000, 0x0000, 0x0000 }, /* R1308 */ + { 0x0000, 0x0000, 0x0000 }, /* R1309 */ + { 0x0000, 0x0000, 0x0000 }, /* R1310 */ + { 0x0000, 0x0000, 0x0000 }, /* R1311 */ + { 0x0000, 0x0000, 0x0000 }, /* R1312 */ + { 0x0000, 0x0000, 0x0000 }, /* R1313 */ + { 0x0000, 0x0000, 0x0000 }, /* R1314 */ + { 0x0000, 0x0000, 0x0000 }, /* R1315 */ + { 0x0000, 0x0000, 0x0000 }, /* R1316 */ + { 0x0000, 0x0000, 0x0000 }, /* R1317 */ + { 0x0000, 0x0000, 0x0000 }, /* R1318 */ + { 0x0000, 0x0000, 0x0000 }, /* R1319 */ + { 0x0000, 0x0000, 0x0000 }, /* R1320 */ + { 0x0000, 0x0000, 0x0000 }, /* R1321 */ + { 0x0000, 0x0000, 0x0000 }, /* R1322 */ + { 0x0000, 0x0000, 0x0000 }, /* R1323 */ + { 0x0000, 0x0000, 0x0000 }, /* R1324 */ + { 0x0000, 0x0000, 0x0000 }, /* R1325 */ + { 0x0000, 0x0000, 0x0000 }, /* R1326 */ + { 0x0000, 0x0000, 0x0000 }, /* R1327 */ + { 0x0000, 0x0000, 0x0000 }, /* R1328 */ + { 0x0000, 0x0000, 0x0000 }, /* R1329 */ + { 0x0000, 0x0000, 0x0000 }, /* R1330 */ + { 0x0000, 0x0000, 0x0000 }, /* R1331 */ + { 0x0000, 0x0000, 0x0000 }, /* R1332 */ + { 0x0000, 0x0000, 0x0000 }, /* R1333 */ + { 0x0000, 0x0000, 0x0000 }, /* R1334 */ + { 0x0000, 0x0000, 0x0000 }, /* R1335 */ + { 0x0000, 0x0000, 0x0000 }, /* R1336 */ + { 0x0000, 0x0000, 0x0000 }, /* R1337 */ + { 0x0000, 0x0000, 0x0000 }, /* R1338 */ + { 0x0000, 0x0000, 0x0000 }, /* R1339 */ + { 0x0000, 0x0000, 0x0000 }, /* R1340 */ + { 0x0000, 0x0000, 0x0000 }, /* R1341 */ + { 0x0000, 0x0000, 0x0000 }, /* R1342 */ + { 0x0000, 0x0000, 0x0000 }, /* R1343 */ + { 0x0000, 0x0000, 0x0000 }, /* R1344 */ + { 0x0000, 0x0000, 0x0000 }, /* R1345 */ + { 0x0000, 0x0000, 0x0000 }, /* R1346 */ + { 0x0000, 0x0000, 0x0000 }, /* R1347 */ + { 0x0000, 0x0000, 0x0000 }, /* R1348 */ + { 0x0000, 0x0000, 0x0000 }, /* R1349 */ + { 0x0000, 0x0000, 0x0000 }, /* R1350 */ + { 0x0000, 0x0000, 0x0000 }, /* R1351 */ + { 0x0000, 0x0000, 0x0000 }, /* R1352 */ + { 0x0000, 0x0000, 0x0000 }, /* R1353 */ + { 0x0000, 0x0000, 0x0000 }, /* R1354 */ + { 0x0000, 0x0000, 0x0000 }, /* R1355 */ + { 0x0000, 0x0000, 0x0000 }, /* R1356 */ + { 0x0000, 0x0000, 0x0000 }, /* R1357 */ + { 0x0000, 0x0000, 0x0000 }, /* R1358 */ + { 0x0000, 0x0000, 0x0000 }, /* R1359 */ + { 0x0000, 0x0000, 0x0000 }, /* R1360 */ + { 0x0000, 0x0000, 0x0000 }, /* R1361 */ + { 0x0000, 0x0000, 0x0000 }, /* R1362 */ + { 0x0000, 0x0000, 0x0000 }, /* R1363 */ + { 0x0000, 0x0000, 0x0000 }, /* R1364 */ + { 0x0000, 0x0000, 0x0000 }, /* R1365 */ + { 0x0000, 0x0000, 0x0000 }, /* R1366 */ + { 0x0000, 0x0000, 0x0000 }, /* R1367 */ + { 0x0000, 0x0000, 0x0000 }, /* R1368 */ + { 0x0000, 0x0000, 0x0000 }, /* R1369 */ + { 0x0000, 0x0000, 0x0000 }, /* R1370 */ + { 0x0000, 0x0000, 0x0000 }, /* R1371 */ + { 0x0000, 0x0000, 0x0000 }, /* R1372 */ + { 0x0000, 0x0000, 0x0000 }, /* R1373 */ + { 0x0000, 0x0000, 0x0000 }, /* R1374 */ + { 0x0000, 0x0000, 0x0000 }, /* R1375 */ + { 0x0000, 0x0000, 0x0000 }, /* R1376 */ + { 0x0000, 0x0000, 0x0000 }, /* R1377 */ + { 0x0000, 0x0000, 0x0000 }, /* R1378 */ + { 0x0000, 0x0000, 0x0000 }, /* R1379 */ + { 0x0000, 0x0000, 0x0000 }, /* R1380 */ + { 0x0000, 0x0000, 0x0000 }, /* R1381 */ + { 0x0000, 0x0000, 0x0000 }, /* R1382 */ + { 0x0000, 0x0000, 0x0000 }, /* R1383 */ + { 0x0000, 0x0000, 0x0000 }, /* R1384 */ + { 0x0000, 0x0000, 0x0000 }, /* R1385 */ + { 0x0000, 0x0000, 0x0000 }, /* R1386 */ + { 0x0000, 0x0000, 0x0000 }, /* R1387 */ + { 0x0000, 0x0000, 0x0000 }, /* R1388 */ + { 0x0000, 0x0000, 0x0000 }, /* R1389 */ + { 0x0000, 0x0000, 0x0000 }, /* R1390 */ + { 0x0000, 0x0000, 0x0000 }, /* R1391 */ + { 0x0000, 0x0000, 0x0000 }, /* R1392 */ + { 0x0000, 0x0000, 0x0000 }, /* R1393 */ + { 0x0000, 0x0000, 0x0000 }, /* R1394 */ + { 0x0000, 0x0000, 0x0000 }, /* R1395 */ + { 0x0000, 0x0000, 0x0000 }, /* R1396 */ + { 0x0000, 0x0000, 0x0000 }, /* R1397 */ + { 0x0000, 0x0000, 0x0000 }, /* R1398 */ + { 0x0000, 0x0000, 0x0000 }, /* R1399 */ + { 0x0000, 0x0000, 0x0000 }, /* R1400 */ + { 0x0000, 0x0000, 0x0000 }, /* R1401 */ + { 0x0000, 0x0000, 0x0000 }, /* R1402 */ + { 0x0000, 0x0000, 0x0000 }, /* R1403 */ + { 0x0000, 0x0000, 0x0000 }, /* R1404 */ + { 0x0000, 0x0000, 0x0000 }, /* R1405 */ + { 0x0000, 0x0000, 0x0000 }, /* R1406 */ + { 0x0000, 0x0000, 0x0000 }, /* R1407 */ + { 0x0000, 0x0000, 0x0000 }, /* R1408 */ + { 0x0000, 0x0000, 0x0000 }, /* R1409 */ + { 0x0000, 0x0000, 0x0000 }, /* R1410 */ + { 0x0000, 0x0000, 0x0000 }, /* R1411 */ + { 0x0000, 0x0000, 0x0000 }, /* R1412 */ + { 0x0000, 0x0000, 0x0000 }, /* R1413 */ + { 0x0000, 0x0000, 0x0000 }, /* R1414 */ + { 0x0000, 0x0000, 0x0000 }, /* R1415 */ + { 0x0000, 0x0000, 0x0000 }, /* R1416 */ + { 0x0000, 0x0000, 0x0000 }, /* R1417 */ + { 0x0000, 0x0000, 0x0000 }, /* R1418 */ + { 0x0000, 0x0000, 0x0000 }, /* R1419 */ + { 0x0000, 0x0000, 0x0000 }, /* R1420 */ + { 0x0000, 0x0000, 0x0000 }, /* R1421 */ + { 0x0000, 0x0000, 0x0000 }, /* R1422 */ + { 0x0000, 0x0000, 0x0000 }, /* R1423 */ + { 0x0000, 0x0000, 0x0000 }, /* R1424 */ + { 0x0000, 0x0000, 0x0000 }, /* R1425 */ + { 0x0000, 0x0000, 0x0000 }, /* R1426 */ + { 0x0000, 0x0000, 0x0000 }, /* R1427 */ + { 0x0000, 0x0000, 0x0000 }, /* R1428 */ + { 0x0000, 0x0000, 0x0000 }, /* R1429 */ + { 0x0000, 0x0000, 0x0000 }, /* R1430 */ + { 0x0000, 0x0000, 0x0000 }, /* R1431 */ + { 0x0000, 0x0000, 0x0000 }, /* R1432 */ + { 0x0000, 0x0000, 0x0000 }, /* R1433 */ + { 0x0000, 0x0000, 0x0000 }, /* R1434 */ + { 0x0000, 0x0000, 0x0000 }, /* R1435 */ + { 0x0000, 0x0000, 0x0000 }, /* R1436 */ + { 0x0000, 0x0000, 0x0000 }, /* R1437 */ + { 0x0000, 0x0000, 0x0000 }, /* R1438 */ + { 0x0000, 0x0000, 0x0000 }, /* R1439 */ + { 0x0000, 0x0000, 0x0000 }, /* R1440 */ + { 0x0000, 0x0000, 0x0000 }, /* R1441 */ + { 0x0000, 0x0000, 0x0000 }, /* R1442 */ + { 0x0000, 0x0000, 0x0000 }, /* R1443 */ + { 0x0000, 0x0000, 0x0000 }, /* R1444 */ + { 0x0000, 0x0000, 0x0000 }, /* R1445 */ + { 0x0000, 0x0000, 0x0000 }, /* R1446 */ + { 0x0000, 0x0000, 0x0000 }, /* R1447 */ + { 0x0000, 0x0000, 0x0000 }, /* R1448 */ + { 0x0000, 0x0000, 0x0000 }, /* R1449 */ + { 0x0000, 0x0000, 0x0000 }, /* R1450 */ + { 0x0000, 0x0000, 0x0000 }, /* R1451 */ + { 0x0000, 0x0000, 0x0000 }, /* R1452 */ + { 0x0000, 0x0000, 0x0000 }, /* R1453 */ + { 0x0000, 0x0000, 0x0000 }, /* R1454 */ + { 0x0000, 0x0000, 0x0000 }, /* R1455 */ + { 0x0000, 0x0000, 0x0000 }, /* R1456 */ + { 0x0000, 0x0000, 0x0000 }, /* R1457 */ + { 0x0000, 0x0000, 0x0000 }, /* R1458 */ + { 0x0000, 0x0000, 0x0000 }, /* R1459 */ + { 0x0000, 0x0000, 0x0000 }, /* R1460 */ + { 0x0000, 0x0000, 0x0000 }, /* R1461 */ + { 0x0000, 0x0000, 0x0000 }, /* R1462 */ + { 0x0000, 0x0000, 0x0000 }, /* R1463 */ + { 0x0000, 0x0000, 0x0000 }, /* R1464 */ + { 0x0000, 0x0000, 0x0000 }, /* R1465 */ + { 0x0000, 0x0000, 0x0000 }, /* R1466 */ + { 0x0000, 0x0000, 0x0000 }, /* R1467 */ + { 0x0000, 0x0000, 0x0000 }, /* R1468 */ + { 0x0000, 0x0000, 0x0000 }, /* R1469 */ + { 0x0000, 0x0000, 0x0000 }, /* R1470 */ + { 0x0000, 0x0000, 0x0000 }, /* R1471 */ + { 0x0000, 0x0000, 0x0000 }, /* R1472 */ + { 0x0000, 0x0000, 0x0000 }, /* R1473 */ + { 0x0000, 0x0000, 0x0000 }, /* R1474 */ + { 0x0000, 0x0000, 0x0000 }, /* R1475 */ + { 0x0000, 0x0000, 0x0000 }, /* R1476 */ + { 0x0000, 0x0000, 0x0000 }, /* R1477 */ + { 0x0000, 0x0000, 0x0000 }, /* R1478 */ + { 0x0000, 0x0000, 0x0000 }, /* R1479 */ + { 0x0000, 0x0000, 0x0000 }, /* R1480 */ + { 0x0000, 0x0000, 0x0000 }, /* R1481 */ + { 0x0000, 0x0000, 0x0000 }, /* R1482 */ + { 0x0000, 0x0000, 0x0000 }, /* R1483 */ + { 0x0000, 0x0000, 0x0000 }, /* R1484 */ + { 0x0000, 0x0000, 0x0000 }, /* R1485 */ + { 0x0000, 0x0000, 0x0000 }, /* R1486 */ + { 0x0000, 0x0000, 0x0000 }, /* R1487 */ + { 0x0000, 0x0000, 0x0000 }, /* R1488 */ + { 0x0000, 0x0000, 0x0000 }, /* R1489 */ + { 0x0000, 0x0000, 0x0000 }, /* R1490 */ + { 0x0000, 0x0000, 0x0000 }, /* R1491 */ + { 0x0000, 0x0000, 0x0000 }, /* R1492 */ + { 0x0000, 0x0000, 0x0000 }, /* R1493 */ + { 0x0000, 0x0000, 0x0000 }, /* R1494 */ + { 0x0000, 0x0000, 0x0000 }, /* R1495 */ + { 0x0000, 0x0000, 0x0000 }, /* R1496 */ + { 0x0000, 0x0000, 0x0000 }, /* R1497 */ + { 0x0000, 0x0000, 0x0000 }, /* R1498 */ + { 0x0000, 0x0000, 0x0000 }, /* R1499 */ + { 0x0000, 0x0000, 0x0000 }, /* R1500 */ + { 0x0000, 0x0000, 0x0000 }, /* R1501 */ + { 0x0000, 0x0000, 0x0000 }, /* R1502 */ + { 0x0000, 0x0000, 0x0000 }, /* R1503 */ + { 0x0000, 0x0000, 0x0000 }, /* R1504 */ + { 0x0000, 0x0000, 0x0000 }, /* R1505 */ + { 0x0000, 0x0000, 0x0000 }, /* R1506 */ + { 0x0000, 0x0000, 0x0000 }, /* R1507 */ + { 0x0000, 0x0000, 0x0000 }, /* R1508 */ + { 0x0000, 0x0000, 0x0000 }, /* R1509 */ + { 0x0000, 0x0000, 0x0000 }, /* R1510 */ + { 0x0000, 0x0000, 0x0000 }, /* R1511 */ + { 0x0000, 0x0000, 0x0000 }, /* R1512 */ + { 0x0000, 0x0000, 0x0000 }, /* R1513 */ + { 0x0000, 0x0000, 0x0000 }, /* R1514 */ + { 0x0000, 0x0000, 0x0000 }, /* R1515 */ + { 0x0000, 0x0000, 0x0000 }, /* R1516 */ + { 0x0000, 0x0000, 0x0000 }, /* R1517 */ + { 0x0000, 0x0000, 0x0000 }, /* R1518 */ + { 0x0000, 0x0000, 0x0000 }, /* R1519 */ + { 0x0000, 0x0000, 0x0000 }, /* R1520 */ + { 0x0000, 0x0000, 0x0000 }, /* R1521 */ + { 0x0000, 0x0000, 0x0000 }, /* R1522 */ + { 0x0000, 0x0000, 0x0000 }, /* R1523 */ + { 0x0000, 0x0000, 0x0000 }, /* R1524 */ + { 0x0000, 0x0000, 0x0000 }, /* R1525 */ + { 0x0000, 0x0000, 0x0000 }, /* R1526 */ + { 0x0000, 0x0000, 0x0000 }, /* R1527 */ + { 0x0000, 0x0000, 0x0000 }, /* R1528 */ + { 0x0000, 0x0000, 0x0000 }, /* R1529 */ + { 0x0000, 0x0000, 0x0000 }, /* R1530 */ + { 0x0000, 0x0000, 0x0000 }, /* R1531 */ + { 0x0000, 0x0000, 0x0000 }, /* R1532 */ + { 0x0000, 0x0000, 0x0000 }, /* R1533 */ + { 0x0000, 0x0000, 0x0000 }, /* R1534 */ + { 0x0000, 0x0000, 0x0000 }, /* R1535 */ + { 0x0000, 0x0000, 0x0000 }, /* R1536 */ + { 0x0000, 0x0000, 0x0000 }, /* R1537 */ + { 0x0000, 0x0000, 0x0000 }, /* R1538 */ + { 0x0000, 0x0000, 0x0000 }, /* R1539 */ + { 0x0000, 0x0000, 0x0000 }, /* R1540 */ + { 0x0000, 0x0000, 0x0000 }, /* R1541 */ + { 0x0000, 0x0000, 0x0000 }, /* R1542 */ + { 0x0000, 0x0000, 0x0000 }, /* R1543 */ + { 0x0000, 0x0000, 0x0000 }, /* R1544 */ + { 0x0000, 0x0000, 0x0000 }, /* R1545 */ + { 0x0000, 0x0000, 0x0000 }, /* R1546 */ + { 0x0000, 0x0000, 0x0000 }, /* R1547 */ + { 0x0000, 0x0000, 0x0000 }, /* R1548 */ + { 0x0000, 0x0000, 0x0000 }, /* R1549 */ + { 0x0000, 0x0000, 0x0000 }, /* R1550 */ + { 0x0000, 0x0000, 0x0000 }, /* R1551 */ + { 0x0000, 0x0000, 0x0000 }, /* R1552 */ + { 0x0000, 0x0000, 0x0000 }, /* R1553 */ + { 0x0000, 0x0000, 0x0000 }, /* R1554 */ + { 0x0000, 0x0000, 0x0000 }, /* R1555 */ + { 0x0000, 0x0000, 0x0000 }, /* R1556 */ + { 0x0000, 0x0000, 0x0000 }, /* R1557 */ + { 0x0000, 0x0000, 0x0000 }, /* R1558 */ + { 0x0000, 0x0000, 0x0000 }, /* R1559 */ + { 0x0000, 0x0000, 0x0000 }, /* R1560 */ + { 0x0000, 0x0000, 0x0000 }, /* R1561 */ + { 0x0000, 0x0000, 0x0000 }, /* R1562 */ + { 0x0000, 0x0000, 0x0000 }, /* R1563 */ + { 0x0000, 0x0000, 0x0000 }, /* R1564 */ + { 0x0000, 0x0000, 0x0000 }, /* R1565 */ + { 0x0000, 0x0000, 0x0000 }, /* R1566 */ + { 0x0000, 0x0000, 0x0000 }, /* R1567 */ + { 0x0000, 0x0000, 0x0000 }, /* R1568 */ + { 0x0000, 0x0000, 0x0000 }, /* R1569 */ + { 0x0000, 0x0000, 0x0000 }, /* R1570 */ + { 0x0000, 0x0000, 0x0000 }, /* R1571 */ + { 0x0000, 0x0000, 0x0000 }, /* R1572 */ + { 0x0000, 0x0000, 0x0000 }, /* R1573 */ + { 0x0000, 0x0000, 0x0000 }, /* R1574 */ + { 0x0000, 0x0000, 0x0000 }, /* R1575 */ + { 0x0000, 0x0000, 0x0000 }, /* R1576 */ + { 0x0000, 0x0000, 0x0000 }, /* R1577 */ + { 0x0000, 0x0000, 0x0000 }, /* R1578 */ + { 0x0000, 0x0000, 0x0000 }, /* R1579 */ + { 0x0000, 0x0000, 0x0000 }, /* R1580 */ + { 0x0000, 0x0000, 0x0000 }, /* R1581 */ + { 0x0000, 0x0000, 0x0000 }, /* R1582 */ + { 0x0000, 0x0000, 0x0000 }, /* R1583 */ + { 0x0000, 0x0000, 0x0000 }, /* R1584 */ + { 0x0000, 0x0000, 0x0000 }, /* R1585 */ + { 0x0000, 0x0000, 0x0000 }, /* R1586 */ + { 0x0000, 0x0000, 0x0000 }, /* R1587 */ + { 0x0000, 0x0000, 0x0000 }, /* R1588 */ + { 0x0000, 0x0000, 0x0000 }, /* R1589 */ + { 0x0000, 0x0000, 0x0000 }, /* R1590 */ + { 0x0000, 0x0000, 0x0000 }, /* R1591 */ + { 0x0000, 0x0000, 0x0000 }, /* R1592 */ + { 0x0000, 0x0000, 0x0000 }, /* R1593 */ + { 0x0000, 0x0000, 0x0000 }, /* R1594 */ + { 0x0000, 0x0000, 0x0000 }, /* R1595 */ + { 0x0000, 0x0000, 0x0000 }, /* R1596 */ + { 0x0000, 0x0000, 0x0000 }, /* R1597 */ + { 0x0000, 0x0000, 0x0000 }, /* R1598 */ + { 0x0000, 0x0000, 0x0000 }, /* R1599 */ + { 0x0000, 0x0000, 0x0000 }, /* R1600 */ + { 0x0000, 0x0000, 0x0000 }, /* R1601 */ + { 0x0000, 0x0000, 0x0000 }, /* R1602 */ + { 0x0000, 0x0000, 0x0000 }, /* R1603 */ + { 0x0000, 0x0000, 0x0000 }, /* R1604 */ + { 0x0000, 0x0000, 0x0000 }, /* R1605 */ + { 0x0000, 0x0000, 0x0000 }, /* R1606 */ + { 0x0000, 0x0000, 0x0000 }, /* R1607 */ + { 0x0000, 0x0000, 0x0000 }, /* R1608 */ + { 0x0000, 0x0000, 0x0000 }, /* R1609 */ + { 0x0000, 0x0000, 0x0000 }, /* R1610 */ + { 0x0000, 0x0000, 0x0000 }, /* R1611 */ + { 0x0000, 0x0000, 0x0000 }, /* R1612 */ + { 0x0000, 0x0000, 0x0000 }, /* R1613 */ + { 0x0000, 0x0000, 0x0000 }, /* R1614 */ + { 0x0000, 0x0000, 0x0000 }, /* R1615 */ + { 0x0000, 0x0000, 0x0000 }, /* R1616 */ + { 0x0000, 0x0000, 0x0000 }, /* R1617 */ + { 0x0000, 0x0000, 0x0000 }, /* R1618 */ + { 0x0000, 0x0000, 0x0000 }, /* R1619 */ + { 0x0000, 0x0000, 0x0000 }, /* R1620 */ + { 0x0000, 0x0000, 0x0000 }, /* R1621 */ + { 0x0000, 0x0000, 0x0000 }, /* R1622 */ + { 0x0000, 0x0000, 0x0000 }, /* R1623 */ + { 0x0000, 0x0000, 0x0000 }, /* R1624 */ + { 0x0000, 0x0000, 0x0000 }, /* R1625 */ + { 0x0000, 0x0000, 0x0000 }, /* R1626 */ + { 0x0000, 0x0000, 0x0000 }, /* R1627 */ + { 0x0000, 0x0000, 0x0000 }, /* R1628 */ + { 0x0000, 0x0000, 0x0000 }, /* R1629 */ + { 0x0000, 0x0000, 0x0000 }, /* R1630 */ + { 0x0000, 0x0000, 0x0000 }, /* R1631 */ + { 0x0000, 0x0000, 0x0000 }, /* R1632 */ + { 0x0000, 0x0000, 0x0000 }, /* R1633 */ + { 0x0000, 0x0000, 0x0000 }, /* R1634 */ + { 0x0000, 0x0000, 0x0000 }, /* R1635 */ + { 0x0000, 0x0000, 0x0000 }, /* R1636 */ + { 0x0000, 0x0000, 0x0000 }, /* R1637 */ + { 0x0000, 0x0000, 0x0000 }, /* R1638 */ + { 0x0000, 0x0000, 0x0000 }, /* R1639 */ + { 0x0000, 0x0000, 0x0000 }, /* R1640 */ + { 0x0000, 0x0000, 0x0000 }, /* R1641 */ + { 0x0000, 0x0000, 0x0000 }, /* R1642 */ + { 0x0000, 0x0000, 0x0000 }, /* R1643 */ + { 0x0000, 0x0000, 0x0000 }, /* R1644 */ + { 0x0000, 0x0000, 0x0000 }, /* R1645 */ + { 0x0000, 0x0000, 0x0000 }, /* R1646 */ + { 0x0000, 0x0000, 0x0000 }, /* R1647 */ + { 0x0000, 0x0000, 0x0000 }, /* R1648 */ + { 0x0000, 0x0000, 0x0000 }, /* R1649 */ + { 0x0000, 0x0000, 0x0000 }, /* R1650 */ + { 0x0000, 0x0000, 0x0000 }, /* R1651 */ + { 0x0000, 0x0000, 0x0000 }, /* R1652 */ + { 0x0000, 0x0000, 0x0000 }, /* R1653 */ + { 0x0000, 0x0000, 0x0000 }, /* R1654 */ + { 0x0000, 0x0000, 0x0000 }, /* R1655 */ + { 0x0000, 0x0000, 0x0000 }, /* R1656 */ + { 0x0000, 0x0000, 0x0000 }, /* R1657 */ + { 0x0000, 0x0000, 0x0000 }, /* R1658 */ + { 0x0000, 0x0000, 0x0000 }, /* R1659 */ + { 0x0000, 0x0000, 0x0000 }, /* R1660 */ + { 0x0000, 0x0000, 0x0000 }, /* R1661 */ + { 0x0000, 0x0000, 0x0000 }, /* R1662 */ + { 0x0000, 0x0000, 0x0000 }, /* R1663 */ + { 0x0000, 0x0000, 0x0000 }, /* R1664 */ + { 0x0000, 0x0000, 0x0000 }, /* R1665 */ + { 0x0000, 0x0000, 0x0000 }, /* R1666 */ + { 0x0000, 0x0000, 0x0000 }, /* R1667 */ + { 0x0000, 0x0000, 0x0000 }, /* R1668 */ + { 0x0000, 0x0000, 0x0000 }, /* R1669 */ + { 0x0000, 0x0000, 0x0000 }, /* R1670 */ + { 0x0000, 0x0000, 0x0000 }, /* R1671 */ + { 0x0000, 0x0000, 0x0000 }, /* R1672 */ + { 0x0000, 0x0000, 0x0000 }, /* R1673 */ + { 0x0000, 0x0000, 0x0000 }, /* R1674 */ + { 0x0000, 0x0000, 0x0000 }, /* R1675 */ + { 0x0000, 0x0000, 0x0000 }, /* R1676 */ + { 0x0000, 0x0000, 0x0000 }, /* R1677 */ + { 0x0000, 0x0000, 0x0000 }, /* R1678 */ + { 0x0000, 0x0000, 0x0000 }, /* R1679 */ + { 0x0000, 0x0000, 0x0000 }, /* R1680 */ + { 0x0000, 0x0000, 0x0000 }, /* R1681 */ + { 0x0000, 0x0000, 0x0000 }, /* R1682 */ + { 0x0000, 0x0000, 0x0000 }, /* R1683 */ + { 0x0000, 0x0000, 0x0000 }, /* R1684 */ + { 0x0000, 0x0000, 0x0000 }, /* R1685 */ + { 0x0000, 0x0000, 0x0000 }, /* R1686 */ + { 0x0000, 0x0000, 0x0000 }, /* R1687 */ + { 0x0000, 0x0000, 0x0000 }, /* R1688 */ + { 0x0000, 0x0000, 0x0000 }, /* R1689 */ + { 0x0000, 0x0000, 0x0000 }, /* R1690 */ + { 0x0000, 0x0000, 0x0000 }, /* R1691 */ + { 0x0000, 0x0000, 0x0000 }, /* R1692 */ + { 0x0000, 0x0000, 0x0000 }, /* R1693 */ + { 0x0000, 0x0000, 0x0000 }, /* R1694 */ + { 0x0000, 0x0000, 0x0000 }, /* R1695 */ + { 0x0000, 0x0000, 0x0000 }, /* R1696 */ + { 0x0000, 0x0000, 0x0000 }, /* R1697 */ + { 0x0000, 0x0000, 0x0000 }, /* R1698 */ + { 0x0000, 0x0000, 0x0000 }, /* R1699 */ + { 0x0000, 0x0000, 0x0000 }, /* R1700 */ + { 0x0000, 0x0000, 0x0000 }, /* R1701 */ + { 0x0000, 0x0000, 0x0000 }, /* R1702 */ + { 0x0000, 0x0000, 0x0000 }, /* R1703 */ + { 0x0000, 0x0000, 0x0000 }, /* R1704 */ + { 0x0000, 0x0000, 0x0000 }, /* R1705 */ + { 0x0000, 0x0000, 0x0000 }, /* R1706 */ + { 0x0000, 0x0000, 0x0000 }, /* R1707 */ + { 0x0000, 0x0000, 0x0000 }, /* R1708 */ + { 0x0000, 0x0000, 0x0000 }, /* R1709 */ + { 0x0000, 0x0000, 0x0000 }, /* R1710 */ + { 0x0000, 0x0000, 0x0000 }, /* R1711 */ + { 0x0000, 0x0000, 0x0000 }, /* R1712 */ + { 0x0000, 0x0000, 0x0000 }, /* R1713 */ + { 0x0000, 0x0000, 0x0000 }, /* R1714 */ + { 0x0000, 0x0000, 0x0000 }, /* R1715 */ + { 0x0000, 0x0000, 0x0000 }, /* R1716 */ + { 0x0000, 0x0000, 0x0000 }, /* R1717 */ + { 0x0000, 0x0000, 0x0000 }, /* R1718 */ + { 0x0000, 0x0000, 0x0000 }, /* R1719 */ + { 0x0000, 0x0000, 0x0000 }, /* R1720 */ + { 0x0000, 0x0000, 0x0000 }, /* R1721 */ + { 0x0000, 0x0000, 0x0000 }, /* R1722 */ + { 0x0000, 0x0000, 0x0000 }, /* R1723 */ + { 0x0000, 0x0000, 0x0000 }, /* R1724 */ + { 0x0000, 0x0000, 0x0000 }, /* R1725 */ + { 0x0000, 0x0000, 0x0000 }, /* R1726 */ + { 0x0000, 0x0000, 0x0000 }, /* R1727 */ + { 0x0000, 0x0000, 0x0000 }, /* R1728 */ + { 0x0000, 0x0000, 0x0000 }, /* R1729 */ + { 0x0000, 0x0000, 0x0000 }, /* R1730 */ + { 0x0000, 0x0000, 0x0000 }, /* R1731 */ + { 0x0000, 0x0000, 0x0000 }, /* R1732 */ + { 0x0000, 0x0000, 0x0000 }, /* R1733 */ + { 0x0000, 0x0000, 0x0000 }, /* R1734 */ + { 0x0000, 0x0000, 0x0000 }, /* R1735 */ + { 0x0000, 0x0000, 0x0000 }, /* R1736 */ + { 0x0000, 0x0000, 0x0000 }, /* R1737 */ + { 0x0000, 0x0000, 0x0000 }, /* R1738 */ + { 0x0000, 0x0000, 0x0000 }, /* R1739 */ + { 0x0000, 0x0000, 0x0000 }, /* R1740 */ + { 0x0000, 0x0000, 0x0000 }, /* R1741 */ + { 0x0000, 0x0000, 0x0000 }, /* R1742 */ + { 0x0000, 0x0000, 0x0000 }, /* R1743 */ + { 0x0000, 0x0000, 0x0000 }, /* R1744 */ + { 0x0000, 0x0000, 0x0000 }, /* R1745 */ + { 0x0000, 0x0000, 0x0000 }, /* R1746 */ + { 0x0000, 0x0000, 0x0000 }, /* R1747 */ + { 0x0000, 0x0000, 0x0000 }, /* R1748 */ + { 0x0000, 0x0000, 0x0000 }, /* R1749 */ + { 0x0000, 0x0000, 0x0000 }, /* R1750 */ + { 0x0000, 0x0000, 0x0000 }, /* R1751 */ + { 0x0000, 0x0000, 0x0000 }, /* R1752 */ + { 0x0000, 0x0000, 0x0000 }, /* R1753 */ + { 0x0000, 0x0000, 0x0000 }, /* R1754 */ + { 0x0000, 0x0000, 0x0000 }, /* R1755 */ + { 0x0000, 0x0000, 0x0000 }, /* R1756 */ + { 0x0000, 0x0000, 0x0000 }, /* R1757 */ + { 0x0000, 0x0000, 0x0000 }, /* R1758 */ + { 0x0000, 0x0000, 0x0000 }, /* R1759 */ + { 0x0000, 0x0000, 0x0000 }, /* R1760 */ + { 0x0000, 0x0000, 0x0000 }, /* R1761 */ + { 0x0000, 0x0000, 0x0000 }, /* R1762 */ + { 0x0000, 0x0000, 0x0000 }, /* R1763 */ + { 0x0000, 0x0000, 0x0000 }, /* R1764 */ + { 0x0000, 0x0000, 0x0000 }, /* R1765 */ + { 0x0000, 0x0000, 0x0000 }, /* R1766 */ + { 0x0000, 0x0000, 0x0000 }, /* R1767 */ + { 0x0000, 0x0000, 0x0000 }, /* R1768 */ + { 0x0000, 0x0000, 0x0000 }, /* R1769 */ + { 0x0000, 0x0000, 0x0000 }, /* R1770 */ + { 0x0000, 0x0000, 0x0000 }, /* R1771 */ + { 0x0000, 0x0000, 0x0000 }, /* R1772 */ + { 0x0000, 0x0000, 0x0000 }, /* R1773 */ + { 0x0000, 0x0000, 0x0000 }, /* R1774 */ + { 0x0000, 0x0000, 0x0000 }, /* R1775 */ + { 0x0000, 0x0000, 0x0000 }, /* R1776 */ + { 0x0000, 0x0000, 0x0000 }, /* R1777 */ + { 0x0000, 0x0000, 0x0000 }, /* R1778 */ + { 0x0000, 0x0000, 0x0000 }, /* R1779 */ + { 0x0000, 0x0000, 0x0000 }, /* R1780 */ + { 0x0000, 0x0000, 0x0000 }, /* R1781 */ + { 0x0000, 0x0000, 0x0000 }, /* R1782 */ + { 0x0000, 0x0000, 0x0000 }, /* R1783 */ + { 0x0000, 0x0000, 0x0000 }, /* R1784 */ + { 0x0000, 0x0000, 0x0000 }, /* R1785 */ + { 0x0000, 0x0000, 0x0000 }, /* R1786 */ + { 0x0000, 0x0000, 0x0000 }, /* R1787 */ + { 0x0000, 0x0000, 0x0000 }, /* R1788 */ + { 0x0000, 0x0000, 0x0000 }, /* R1789 */ + { 0x0000, 0x0000, 0x0000 }, /* R1790 */ + { 0x0000, 0x0000, 0x0000 }, /* R1791 */ + { 0x0000, 0x0000, 0x0000 }, /* R1792 */ + { 0x0000, 0x0000, 0x0000 }, /* R1793 */ + { 0x0000, 0x0000, 0x0000 }, /* R1794 */ + { 0x0000, 0x0000, 0x0000 }, /* R1795 */ + { 0x0000, 0x0000, 0x0000 }, /* R1796 */ + { 0x0000, 0x0000, 0x0000 }, /* R1797 */ + { 0x0000, 0x0000, 0x0000 }, /* R1798 */ + { 0x0000, 0x0000, 0x0000 }, /* R1799 */ + { 0x0000, 0x0000, 0x0000 }, /* R1800 */ + { 0x0000, 0x0000, 0x0000 }, /* R1801 */ + { 0x0000, 0x0000, 0x0000 }, /* R1802 */ + { 0x0000, 0x0000, 0x0000 }, /* R1803 */ + { 0x0000, 0x0000, 0x0000 }, /* R1804 */ + { 0x0000, 0x0000, 0x0000 }, /* R1805 */ + { 0x0000, 0x0000, 0x0000 }, /* R1806 */ + { 0x0000, 0x0000, 0x0000 }, /* R1807 */ + { 0x0000, 0x0000, 0x0000 }, /* R1808 */ + { 0x0000, 0x0000, 0x0000 }, /* R1809 */ + { 0x0000, 0x0000, 0x0000 }, /* R1810 */ + { 0x0000, 0x0000, 0x0000 }, /* R1811 */ + { 0x0000, 0x0000, 0x0000 }, /* R1812 */ + { 0x0000, 0x0000, 0x0000 }, /* R1813 */ + { 0x0000, 0x0000, 0x0000 }, /* R1814 */ + { 0x0000, 0x0000, 0x0000 }, /* R1815 */ + { 0x0000, 0x0000, 0x0000 }, /* R1816 */ + { 0x0000, 0x0000, 0x0000 }, /* R1817 */ + { 0x0000, 0x0000, 0x0000 }, /* R1818 */ + { 0x0000, 0x0000, 0x0000 }, /* R1819 */ + { 0x0000, 0x0000, 0x0000 }, /* R1820 */ + { 0x0000, 0x0000, 0x0000 }, /* R1821 */ + { 0x0000, 0x0000, 0x0000 }, /* R1822 */ + { 0x0000, 0x0000, 0x0000 }, /* R1823 */ + { 0x0000, 0x0000, 0x0000 }, /* R1824 */ + { 0x0000, 0x0000, 0x0000 }, /* R1825 */ + { 0x0000, 0x0000, 0x0000 }, /* R1826 */ + { 0x0000, 0x0000, 0x0000 }, /* R1827 */ + { 0x0000, 0x0000, 0x0000 }, /* R1828 */ + { 0x0000, 0x0000, 0x0000 }, /* R1829 */ + { 0x0000, 0x0000, 0x0000 }, /* R1830 */ + { 0x0000, 0x0000, 0x0000 }, /* R1831 */ + { 0x0000, 0x0000, 0x0000 }, /* R1832 */ + { 0x0000, 0x0000, 0x0000 }, /* R1833 */ + { 0x0000, 0x0000, 0x0000 }, /* R1834 */ + { 0x0000, 0x0000, 0x0000 }, /* R1835 */ + { 0x0000, 0x0000, 0x0000 }, /* R1836 */ + { 0x0000, 0x0000, 0x0000 }, /* R1837 */ + { 0x0000, 0x0000, 0x0000 }, /* R1838 */ + { 0x0000, 0x0000, 0x0000 }, /* R1839 */ + { 0x0000, 0x0000, 0x0000 }, /* R1840 */ + { 0x0000, 0x0000, 0x0000 }, /* R1841 */ + { 0x0000, 0x0000, 0x0000 }, /* R1842 */ + { 0x0000, 0x0000, 0x0000 }, /* R1843 */ + { 0x0000, 0x0000, 0x0000 }, /* R1844 */ + { 0x0000, 0x0000, 0x0000 }, /* R1845 */ + { 0x0000, 0x0000, 0x0000 }, /* R1846 */ + { 0x0000, 0x0000, 0x0000 }, /* R1847 */ + { 0x0000, 0x0000, 0x0000 }, /* R1848 */ + { 0x0000, 0x0000, 0x0000 }, /* R1849 */ + { 0x0000, 0x0000, 0x0000 }, /* R1850 */ + { 0x0000, 0x0000, 0x0000 }, /* R1851 */ + { 0x0000, 0x0000, 0x0000 }, /* R1852 */ + { 0x0000, 0x0000, 0x0000 }, /* R1853 */ + { 0x0000, 0x0000, 0x0000 }, /* R1854 */ + { 0x0000, 0x0000, 0x0000 }, /* R1855 */ + { 0x0000, 0x0000, 0x0000 }, /* R1856 */ + { 0x0000, 0x0000, 0x0000 }, /* R1857 */ + { 0x0000, 0x0000, 0x0000 }, /* R1858 */ + { 0x0000, 0x0000, 0x0000 }, /* R1859 */ + { 0x0000, 0x0000, 0x0000 }, /* R1860 */ + { 0x0000, 0x0000, 0x0000 }, /* R1861 */ + { 0x0000, 0x0000, 0x0000 }, /* R1862 */ + { 0x0000, 0x0000, 0x0000 }, /* R1863 */ + { 0x0000, 0x0000, 0x0000 }, /* R1864 */ + { 0x0000, 0x0000, 0x0000 }, /* R1865 */ + { 0x0000, 0x0000, 0x0000 }, /* R1866 */ + { 0x0000, 0x0000, 0x0000 }, /* R1867 */ + { 0x0000, 0x0000, 0x0000 }, /* R1868 */ + { 0x0000, 0x0000, 0x0000 }, /* R1869 */ + { 0x0000, 0x0000, 0x0000 }, /* R1870 */ + { 0x0000, 0x0000, 0x0000 }, /* R1871 */ + { 0x0000, 0x0000, 0x0000 }, /* R1872 */ + { 0x0000, 0x0000, 0x0000 }, /* R1873 */ + { 0x0000, 0x0000, 0x0000 }, /* R1874 */ + { 0x0000, 0x0000, 0x0000 }, /* R1875 */ + { 0x0000, 0x0000, 0x0000 }, /* R1876 */ + { 0x0000, 0x0000, 0x0000 }, /* R1877 */ + { 0x0000, 0x0000, 0x0000 }, /* R1878 */ + { 0x0000, 0x0000, 0x0000 }, /* R1879 */ + { 0x0000, 0x0000, 0x0000 }, /* R1880 */ + { 0x0000, 0x0000, 0x0000 }, /* R1881 */ + { 0x0000, 0x0000, 0x0000 }, /* R1882 */ + { 0x0000, 0x0000, 0x0000 }, /* R1883 */ + { 0x0000, 0x0000, 0x0000 }, /* R1884 */ + { 0x0000, 0x0000, 0x0000 }, /* R1885 */ + { 0x0000, 0x0000, 0x0000 }, /* R1886 */ + { 0x0000, 0x0000, 0x0000 }, /* R1887 */ + { 0x0000, 0x0000, 0x0000 }, /* R1888 */ + { 0x0000, 0x0000, 0x0000 }, /* R1889 */ + { 0x0000, 0x0000, 0x0000 }, /* R1890 */ + { 0x0000, 0x0000, 0x0000 }, /* R1891 */ + { 0x0000, 0x0000, 0x0000 }, /* R1892 */ + { 0x0000, 0x0000, 0x0000 }, /* R1893 */ + { 0x0000, 0x0000, 0x0000 }, /* R1894 */ + { 0x0000, 0x0000, 0x0000 }, /* R1895 */ + { 0x0000, 0x0000, 0x0000 }, /* R1896 */ + { 0x0000, 0x0000, 0x0000 }, /* R1897 */ + { 0x0000, 0x0000, 0x0000 }, /* R1898 */ + { 0x0000, 0x0000, 0x0000 }, /* R1899 */ + { 0x0000, 0x0000, 0x0000 }, /* R1900 */ + { 0x0000, 0x0000, 0x0000 }, /* R1901 */ + { 0x0000, 0x0000, 0x0000 }, /* R1902 */ + { 0x0000, 0x0000, 0x0000 }, /* R1903 */ + { 0x0000, 0x0000, 0x0000 }, /* R1904 */ + { 0x0000, 0x0000, 0x0000 }, /* R1905 */ + { 0x0000, 0x0000, 0x0000 }, /* R1906 */ + { 0x0000, 0x0000, 0x0000 }, /* R1907 */ + { 0x0000, 0x0000, 0x0000 }, /* R1908 */ + { 0x0000, 0x0000, 0x0000 }, /* R1909 */ + { 0x0000, 0x0000, 0x0000 }, /* R1910 */ + { 0x0000, 0x0000, 0x0000 }, /* R1911 */ + { 0x0000, 0x0000, 0x0000 }, /* R1912 */ + { 0x0000, 0x0000, 0x0000 }, /* R1913 */ + { 0x0000, 0x0000, 0x0000 }, /* R1914 */ + { 0x0000, 0x0000, 0x0000 }, /* R1915 */ + { 0x0000, 0x0000, 0x0000 }, /* R1916 */ + { 0x0000, 0x0000, 0x0000 }, /* R1917 */ + { 0x0000, 0x0000, 0x0000 }, /* R1918 */ + { 0x0000, 0x0000, 0x0000 }, /* R1919 */ + { 0x0000, 0x0000, 0x0000 }, /* R1920 */ + { 0x0000, 0x0000, 0x0000 }, /* R1921 */ + { 0x0000, 0x0000, 0x0000 }, /* R1922 */ + { 0x0000, 0x0000, 0x0000 }, /* R1923 */ + { 0x0000, 0x0000, 0x0000 }, /* R1924 */ + { 0x0000, 0x0000, 0x0000 }, /* R1925 */ + { 0x0000, 0x0000, 0x0000 }, /* R1926 */ + { 0x0000, 0x0000, 0x0000 }, /* R1927 */ + { 0x0000, 0x0000, 0x0000 }, /* R1928 */ + { 0x0000, 0x0000, 0x0000 }, /* R1929 */ + { 0x0000, 0x0000, 0x0000 }, /* R1930 */ + { 0x0000, 0x0000, 0x0000 }, /* R1931 */ + { 0x0000, 0x0000, 0x0000 }, /* R1932 */ + { 0x0000, 0x0000, 0x0000 }, /* R1933 */ + { 0x0000, 0x0000, 0x0000 }, /* R1934 */ + { 0x0000, 0x0000, 0x0000 }, /* R1935 */ + { 0x0000, 0x0000, 0x0000 }, /* R1936 */ + { 0x0000, 0x0000, 0x0000 }, /* R1937 */ + { 0x0000, 0x0000, 0x0000 }, /* R1938 */ + { 0x0000, 0x0000, 0x0000 }, /* R1939 */ + { 0x0000, 0x0000, 0x0000 }, /* R1940 */ + { 0x0000, 0x0000, 0x0000 }, /* R1941 */ + { 0x0000, 0x0000, 0x0000 }, /* R1942 */ + { 0x0000, 0x0000, 0x0000 }, /* R1943 */ + { 0x0000, 0x0000, 0x0000 }, /* R1944 */ + { 0x0000, 0x0000, 0x0000 }, /* R1945 */ + { 0x0000, 0x0000, 0x0000 }, /* R1946 */ + { 0x0000, 0x0000, 0x0000 }, /* R1947 */ + { 0x0000, 0x0000, 0x0000 }, /* R1948 */ + { 0x0000, 0x0000, 0x0000 }, /* R1949 */ + { 0x0000, 0x0000, 0x0000 }, /* R1950 */ + { 0x0000, 0x0000, 0x0000 }, /* R1951 */ + { 0x0000, 0x0000, 0x0000 }, /* R1952 */ + { 0x0000, 0x0000, 0x0000 }, /* R1953 */ + { 0x0000, 0x0000, 0x0000 }, /* R1954 */ + { 0x0000, 0x0000, 0x0000 }, /* R1955 */ + { 0x0000, 0x0000, 0x0000 }, /* R1956 */ + { 0x0000, 0x0000, 0x0000 }, /* R1957 */ + { 0x0000, 0x0000, 0x0000 }, /* R1958 */ + { 0x0000, 0x0000, 0x0000 }, /* R1959 */ + { 0x0000, 0x0000, 0x0000 }, /* R1960 */ + { 0x0000, 0x0000, 0x0000 }, /* R1961 */ + { 0x0000, 0x0000, 0x0000 }, /* R1962 */ + { 0x0000, 0x0000, 0x0000 }, /* R1963 */ + { 0x0000, 0x0000, 0x0000 }, /* R1964 */ + { 0x0000, 0x0000, 0x0000 }, /* R1965 */ + { 0x0000, 0x0000, 0x0000 }, /* R1966 */ + { 0x0000, 0x0000, 0x0000 }, /* R1967 */ + { 0x0000, 0x0000, 0x0000 }, /* R1968 */ + { 0x0000, 0x0000, 0x0000 }, /* R1969 */ + { 0x0000, 0x0000, 0x0000 }, /* R1970 */ + { 0x0000, 0x0000, 0x0000 }, /* R1971 */ + { 0x0000, 0x0000, 0x0000 }, /* R1972 */ + { 0x0000, 0x0000, 0x0000 }, /* R1973 */ + { 0x0000, 0x0000, 0x0000 }, /* R1974 */ + { 0x0000, 0x0000, 0x0000 }, /* R1975 */ + { 0x0000, 0x0000, 0x0000 }, /* R1976 */ + { 0x0000, 0x0000, 0x0000 }, /* R1977 */ + { 0x0000, 0x0000, 0x0000 }, /* R1978 */ + { 0x0000, 0x0000, 0x0000 }, /* R1979 */ + { 0x0000, 0x0000, 0x0000 }, /* R1980 */ + { 0x0000, 0x0000, 0x0000 }, /* R1981 */ + { 0x0000, 0x0000, 0x0000 }, /* R1982 */ + { 0x0000, 0x0000, 0x0000 }, /* R1983 */ + { 0x0000, 0x0000, 0x0000 }, /* R1984 */ + { 0x0000, 0x0000, 0x0000 }, /* R1985 */ + { 0x0000, 0x0000, 0x0000 }, /* R1986 */ + { 0x0000, 0x0000, 0x0000 }, /* R1987 */ + { 0x0000, 0x0000, 0x0000 }, /* R1988 */ + { 0x0000, 0x0000, 0x0000 }, /* R1989 */ + { 0x0000, 0x0000, 0x0000 }, /* R1990 */ + { 0x0000, 0x0000, 0x0000 }, /* R1991 */ + { 0x0000, 0x0000, 0x0000 }, /* R1992 */ + { 0x0000, 0x0000, 0x0000 }, /* R1993 */ + { 0x0000, 0x0000, 0x0000 }, /* R1994 */ + { 0x0000, 0x0000, 0x0000 }, /* R1995 */ + { 0x0000, 0x0000, 0x0000 }, /* R1996 */ + { 0x0000, 0x0000, 0x0000 }, /* R1997 */ + { 0x0000, 0x0000, 0x0000 }, /* R1998 */ + { 0x0000, 0x0000, 0x0000 }, /* R1999 */ + { 0x0000, 0x0000, 0x0000 }, /* R2000 */ + { 0x0000, 0x0000, 0x0000 }, /* R2001 */ + { 0x0000, 0x0000, 0x0000 }, /* R2002 */ + { 0x0000, 0x0000, 0x0000 }, /* R2003 */ + { 0x0000, 0x0000, 0x0000 }, /* R2004 */ + { 0x0000, 0x0000, 0x0000 }, /* R2005 */ + { 0x0000, 0x0000, 0x0000 }, /* R2006 */ + { 0x0000, 0x0000, 0x0000 }, /* R2007 */ + { 0x0000, 0x0000, 0x0000 }, /* R2008 */ + { 0x0000, 0x0000, 0x0000 }, /* R2009 */ + { 0x0000, 0x0000, 0x0000 }, /* R2010 */ + { 0x0000, 0x0000, 0x0000 }, /* R2011 */ + { 0x0000, 0x0000, 0x0000 }, /* R2012 */ + { 0x0000, 0x0000, 0x0000 }, /* R2013 */ + { 0x0000, 0x0000, 0x0000 }, /* R2014 */ + { 0x0000, 0x0000, 0x0000 }, /* R2015 */ + { 0x0000, 0x0000, 0x0000 }, /* R2016 */ + { 0x0000, 0x0000, 0x0000 }, /* R2017 */ + { 0x0000, 0x0000, 0x0000 }, /* R2018 */ + { 0x0000, 0x0000, 0x0000 }, /* R2019 */ + { 0x0000, 0x0000, 0x0000 }, /* R2020 */ + { 0x0000, 0x0000, 0x0000 }, /* R2021 */ + { 0x0000, 0x0000, 0x0000 }, /* R2022 */ + { 0x0000, 0x0000, 0x0000 }, /* R2023 */ + { 0x0000, 0x0000, 0x0000 }, /* R2024 */ + { 0x0000, 0x0000, 0x0000 }, /* R2025 */ + { 0x0000, 0x0000, 0x0000 }, /* R2026 */ + { 0x0000, 0x0000, 0x0000 }, /* R2027 */ + { 0x0000, 0x0000, 0x0000 }, /* R2028 */ + { 0x0000, 0x0000, 0x0000 }, /* R2029 */ + { 0x0000, 0x0000, 0x0000 }, /* R2030 */ + { 0x0000, 0x0000, 0x0000 }, /* R2031 */ + { 0x0000, 0x0000, 0x0000 }, /* R2032 */ + { 0x0000, 0x0000, 0x0000 }, /* R2033 */ + { 0x0000, 0x0000, 0x0000 }, /* R2034 */ + { 0x0000, 0x0000, 0x0000 }, /* R2035 */ + { 0x0000, 0x0000, 0x0000 }, /* R2036 */ + { 0x0000, 0x0000, 0x0000 }, /* R2037 */ + { 0x0000, 0x0000, 0x0000 }, /* R2038 */ + { 0x0000, 0x0000, 0x0000 }, /* R2039 */ + { 0x0000, 0x0000, 0x0000 }, /* R2040 */ + { 0x0000, 0x0000, 0x0000 }, /* R2041 */ + { 0x0000, 0x0000, 0x0000 }, /* R2042 */ + { 0x0000, 0x0000, 0x0000 }, /* R2043 */ + { 0x0000, 0x0000, 0x0000 }, /* R2044 */ + { 0x0000, 0x0000, 0x0000 }, /* R2045 */ + { 0x0000, 0x0000, 0x0000 }, /* R2046 */ + { 0x0000, 0x0000, 0x0000 }, /* R2047 */ + { 0x0000, 0x0000, 0x0000 }, /* R2048 */ + { 0x0000, 0x0000, 0x0000 }, /* R2049 */ + { 0x0000, 0x0000, 0x0000 }, /* R2050 */ + { 0x0000, 0x0000, 0x0000 }, /* R2051 */ + { 0x0000, 0x0000, 0x0000 }, /* R2052 */ + { 0x0000, 0x0000, 0x0000 }, /* R2053 */ + { 0x0000, 0x0000, 0x0000 }, /* R2054 */ + { 0x0000, 0x0000, 0x0000 }, /* R2055 */ + { 0x0000, 0x0000, 0x0000 }, /* R2056 */ + { 0x0000, 0x0000, 0x0000 }, /* R2057 */ + { 0x0000, 0x0000, 0x0000 }, /* R2058 */ + { 0x0000, 0x0000, 0x0000 }, /* R2059 */ + { 0x0000, 0x0000, 0x0000 }, /* R2060 */ + { 0x0000, 0x0000, 0x0000 }, /* R2061 */ + { 0x0000, 0x0000, 0x0000 }, /* R2062 */ + { 0x0000, 0x0000, 0x0000 }, /* R2063 */ + { 0x0000, 0x0000, 0x0000 }, /* R2064 */ + { 0x0000, 0x0000, 0x0000 }, /* R2065 */ + { 0x0000, 0x0000, 0x0000 }, /* R2066 */ + { 0x0000, 0x0000, 0x0000 }, /* R2067 */ + { 0x0000, 0x0000, 0x0000 }, /* R2068 */ + { 0x0000, 0x0000, 0x0000 }, /* R2069 */ + { 0x0000, 0x0000, 0x0000 }, /* R2070 */ + { 0x0000, 0x0000, 0x0000 }, /* R2071 */ + { 0x0000, 0x0000, 0x0000 }, /* R2072 */ + { 0x0000, 0x0000, 0x0000 }, /* R2073 */ + { 0x0000, 0x0000, 0x0000 }, /* R2074 */ + { 0x0000, 0x0000, 0x0000 }, /* R2075 */ + { 0x0000, 0x0000, 0x0000 }, /* R2076 */ + { 0x0000, 0x0000, 0x0000 }, /* R2077 */ + { 0x0000, 0x0000, 0x0000 }, /* R2078 */ + { 0x0000, 0x0000, 0x0000 }, /* R2079 */ + { 0x0000, 0x0000, 0x0000 }, /* R2080 */ + { 0x0000, 0x0000, 0x0000 }, /* R2081 */ + { 0x0000, 0x0000, 0x0000 }, /* R2082 */ + { 0x0000, 0x0000, 0x0000 }, /* R2083 */ + { 0x0000, 0x0000, 0x0000 }, /* R2084 */ + { 0x0000, 0x0000, 0x0000 }, /* R2085 */ + { 0x0000, 0x0000, 0x0000 }, /* R2086 */ + { 0x0000, 0x0000, 0x0000 }, /* R2087 */ + { 0x0000, 0x0000, 0x0000 }, /* R2088 */ + { 0x0000, 0x0000, 0x0000 }, /* R2089 */ + { 0x0000, 0x0000, 0x0000 }, /* R2090 */ + { 0x0000, 0x0000, 0x0000 }, /* R2091 */ + { 0x0000, 0x0000, 0x0000 }, /* R2092 */ + { 0x0000, 0x0000, 0x0000 }, /* R2093 */ + { 0x0000, 0x0000, 0x0000 }, /* R2094 */ + { 0x0000, 0x0000, 0x0000 }, /* R2095 */ + { 0x0000, 0x0000, 0x0000 }, /* R2096 */ + { 0x0000, 0x0000, 0x0000 }, /* R2097 */ + { 0x0000, 0x0000, 0x0000 }, /* R2098 */ + { 0x0000, 0x0000, 0x0000 }, /* R2099 */ + { 0x0000, 0x0000, 0x0000 }, /* R2100 */ + { 0x0000, 0x0000, 0x0000 }, /* R2101 */ + { 0x0000, 0x0000, 0x0000 }, /* R2102 */ + { 0x0000, 0x0000, 0x0000 }, /* R2103 */ + { 0x0000, 0x0000, 0x0000 }, /* R2104 */ + { 0x0000, 0x0000, 0x0000 }, /* R2105 */ + { 0x0000, 0x0000, 0x0000 }, /* R2106 */ + { 0x0000, 0x0000, 0x0000 }, /* R2107 */ + { 0x0000, 0x0000, 0x0000 }, /* R2108 */ + { 0x0000, 0x0000, 0x0000 }, /* R2109 */ + { 0x0000, 0x0000, 0x0000 }, /* R2110 */ + { 0x0000, 0x0000, 0x0000 }, /* R2111 */ + { 0x0000, 0x0000, 0x0000 }, /* R2112 */ + { 0x0000, 0x0000, 0x0000 }, /* R2113 */ + { 0x0000, 0x0000, 0x0000 }, /* R2114 */ + { 0x0000, 0x0000, 0x0000 }, /* R2115 */ + { 0x0000, 0x0000, 0x0000 }, /* R2116 */ + { 0x0000, 0x0000, 0x0000 }, /* R2117 */ + { 0x0000, 0x0000, 0x0000 }, /* R2118 */ + { 0x0000, 0x0000, 0x0000 }, /* R2119 */ + { 0x0000, 0x0000, 0x0000 }, /* R2120 */ + { 0x0000, 0x0000, 0x0000 }, /* R2121 */ + { 0x0000, 0x0000, 0x0000 }, /* R2122 */ + { 0x0000, 0x0000, 0x0000 }, /* R2123 */ + { 0x0000, 0x0000, 0x0000 }, /* R2124 */ + { 0x0000, 0x0000, 0x0000 }, /* R2125 */ + { 0x0000, 0x0000, 0x0000 }, /* R2126 */ + { 0x0000, 0x0000, 0x0000 }, /* R2127 */ + { 0x0000, 0x0000, 0x0000 }, /* R2128 */ + { 0x0000, 0x0000, 0x0000 }, /* R2129 */ + { 0x0000, 0x0000, 0x0000 }, /* R2130 */ + { 0x0000, 0x0000, 0x0000 }, /* R2131 */ + { 0x0000, 0x0000, 0x0000 }, /* R2132 */ + { 0x0000, 0x0000, 0x0000 }, /* R2133 */ + { 0x0000, 0x0000, 0x0000 }, /* R2134 */ + { 0x0000, 0x0000, 0x0000 }, /* R2135 */ + { 0x0000, 0x0000, 0x0000 }, /* R2136 */ + { 0x0000, 0x0000, 0x0000 }, /* R2137 */ + { 0x0000, 0x0000, 0x0000 }, /* R2138 */ + { 0x0000, 0x0000, 0x0000 }, /* R2139 */ + { 0x0000, 0x0000, 0x0000 }, /* R2140 */ + { 0x0000, 0x0000, 0x0000 }, /* R2141 */ + { 0x0000, 0x0000, 0x0000 }, /* R2142 */ + { 0x0000, 0x0000, 0x0000 }, /* R2143 */ + { 0x0000, 0x0000, 0x0000 }, /* R2144 */ + { 0x0000, 0x0000, 0x0000 }, /* R2145 */ + { 0x0000, 0x0000, 0x0000 }, /* R2146 */ + { 0x0000, 0x0000, 0x0000 }, /* R2147 */ + { 0x0000, 0x0000, 0x0000 }, /* R2148 */ + { 0x0000, 0x0000, 0x0000 }, /* R2149 */ + { 0x0000, 0x0000, 0x0000 }, /* R2150 */ + { 0x0000, 0x0000, 0x0000 }, /* R2151 */ + { 0x0000, 0x0000, 0x0000 }, /* R2152 */ + { 0x0000, 0x0000, 0x0000 }, /* R2153 */ + { 0x0000, 0x0000, 0x0000 }, /* R2154 */ + { 0x0000, 0x0000, 0x0000 }, /* R2155 */ + { 0x0000, 0x0000, 0x0000 }, /* R2156 */ + { 0x0000, 0x0000, 0x0000 }, /* R2157 */ + { 0x0000, 0x0000, 0x0000 }, /* R2158 */ + { 0x0000, 0x0000, 0x0000 }, /* R2159 */ + { 0x0000, 0x0000, 0x0000 }, /* R2160 */ + { 0x0000, 0x0000, 0x0000 }, /* R2161 */ + { 0x0000, 0x0000, 0x0000 }, /* R2162 */ + { 0x0000, 0x0000, 0x0000 }, /* R2163 */ + { 0x0000, 0x0000, 0x0000 }, /* R2164 */ + { 0x0000, 0x0000, 0x0000 }, /* R2165 */ + { 0x0000, 0x0000, 0x0000 }, /* R2166 */ + { 0x0000, 0x0000, 0x0000 }, /* R2167 */ + { 0x0000, 0x0000, 0x0000 }, /* R2168 */ + { 0x0000, 0x0000, 0x0000 }, /* R2169 */ + { 0x0000, 0x0000, 0x0000 }, /* R2170 */ + { 0x0000, 0x0000, 0x0000 }, /* R2171 */ + { 0x0000, 0x0000, 0x0000 }, /* R2172 */ + { 0x0000, 0x0000, 0x0000 }, /* R2173 */ + { 0x0000, 0x0000, 0x0000 }, /* R2174 */ + { 0x0000, 0x0000, 0x0000 }, /* R2175 */ + { 0x0000, 0x0000, 0x0000 }, /* R2176 */ + { 0x0000, 0x0000, 0x0000 }, /* R2177 */ + { 0x0000, 0x0000, 0x0000 }, /* R2178 */ + { 0x0000, 0x0000, 0x0000 }, /* R2179 */ + { 0x0000, 0x0000, 0x0000 }, /* R2180 */ + { 0x0000, 0x0000, 0x0000 }, /* R2181 */ + { 0x0000, 0x0000, 0x0000 }, /* R2182 */ + { 0x0000, 0x0000, 0x0000 }, /* R2183 */ + { 0x0000, 0x0000, 0x0000 }, /* R2184 */ + { 0x0000, 0x0000, 0x0000 }, /* R2185 */ + { 0x0000, 0x0000, 0x0000 }, /* R2186 */ + { 0x0000, 0x0000, 0x0000 }, /* R2187 */ + { 0x0000, 0x0000, 0x0000 }, /* R2188 */ + { 0x0000, 0x0000, 0x0000 }, /* R2189 */ + { 0x0000, 0x0000, 0x0000 }, /* R2190 */ + { 0x0000, 0x0000, 0x0000 }, /* R2191 */ + { 0x0000, 0x0000, 0x0000 }, /* R2192 */ + { 0x0000, 0x0000, 0x0000 }, /* R2193 */ + { 0x0000, 0x0000, 0x0000 }, /* R2194 */ + { 0x0000, 0x0000, 0x0000 }, /* R2195 */ + { 0x0000, 0x0000, 0x0000 }, /* R2196 */ + { 0x0000, 0x0000, 0x0000 }, /* R2197 */ + { 0x0000, 0x0000, 0x0000 }, /* R2198 */ + { 0x0000, 0x0000, 0x0000 }, /* R2199 */ + { 0x0000, 0x0000, 0x0000 }, /* R2200 */ + { 0x0000, 0x0000, 0x0000 }, /* R2201 */ + { 0x0000, 0x0000, 0x0000 }, /* R2202 */ + { 0x0000, 0x0000, 0x0000 }, /* R2203 */ + { 0x0000, 0x0000, 0x0000 }, /* R2204 */ + { 0x0000, 0x0000, 0x0000 }, /* R2205 */ + { 0x0000, 0x0000, 0x0000 }, /* R2206 */ + { 0x0000, 0x0000, 0x0000 }, /* R2207 */ + { 0x0000, 0x0000, 0x0000 }, /* R2208 */ + { 0x0000, 0x0000, 0x0000 }, /* R2209 */ + { 0x0000, 0x0000, 0x0000 }, /* R2210 */ + { 0x0000, 0x0000, 0x0000 }, /* R2211 */ + { 0x0000, 0x0000, 0x0000 }, /* R2212 */ + { 0x0000, 0x0000, 0x0000 }, /* R2213 */ + { 0x0000, 0x0000, 0x0000 }, /* R2214 */ + { 0x0000, 0x0000, 0x0000 }, /* R2215 */ + { 0x0000, 0x0000, 0x0000 }, /* R2216 */ + { 0x0000, 0x0000, 0x0000 }, /* R2217 */ + { 0x0000, 0x0000, 0x0000 }, /* R2218 */ + { 0x0000, 0x0000, 0x0000 }, /* R2219 */ + { 0x0000, 0x0000, 0x0000 }, /* R2220 */ + { 0x0000, 0x0000, 0x0000 }, /* R2221 */ + { 0x0000, 0x0000, 0x0000 }, /* R2222 */ + { 0x0000, 0x0000, 0x0000 }, /* R2223 */ + { 0x0000, 0x0000, 0x0000 }, /* R2224 */ + { 0x0000, 0x0000, 0x0000 }, /* R2225 */ + { 0x0000, 0x0000, 0x0000 }, /* R2226 */ + { 0x0000, 0x0000, 0x0000 }, /* R2227 */ + { 0x0000, 0x0000, 0x0000 }, /* R2228 */ + { 0x0000, 0x0000, 0x0000 }, /* R2229 */ + { 0x0000, 0x0000, 0x0000 }, /* R2230 */ + { 0x0000, 0x0000, 0x0000 }, /* R2231 */ + { 0x0000, 0x0000, 0x0000 }, /* R2232 */ + { 0x0000, 0x0000, 0x0000 }, /* R2233 */ + { 0x0000, 0x0000, 0x0000 }, /* R2234 */ + { 0x0000, 0x0000, 0x0000 }, /* R2235 */ + { 0x0000, 0x0000, 0x0000 }, /* R2236 */ + { 0x0000, 0x0000, 0x0000 }, /* R2237 */ + { 0x0000, 0x0000, 0x0000 }, /* R2238 */ + { 0x0000, 0x0000, 0x0000 }, /* R2239 */ + { 0x0000, 0x0000, 0x0000 }, /* R2240 */ + { 0x0000, 0x0000, 0x0000 }, /* R2241 */ + { 0x0000, 0x0000, 0x0000 }, /* R2242 */ + { 0x0000, 0x0000, 0x0000 }, /* R2243 */ + { 0x0000, 0x0000, 0x0000 }, /* R2244 */ + { 0x0000, 0x0000, 0x0000 }, /* R2245 */ + { 0x0000, 0x0000, 0x0000 }, /* R2246 */ + { 0x0000, 0x0000, 0x0000 }, /* R2247 */ + { 0x0000, 0x0000, 0x0000 }, /* R2248 */ + { 0x0000, 0x0000, 0x0000 }, /* R2249 */ + { 0x0000, 0x0000, 0x0000 }, /* R2250 */ + { 0x0000, 0x0000, 0x0000 }, /* R2251 */ + { 0x0000, 0x0000, 0x0000 }, /* R2252 */ + { 0x0000, 0x0000, 0x0000 }, /* R2253 */ + { 0x0000, 0x0000, 0x0000 }, /* R2254 */ + { 0x0000, 0x0000, 0x0000 }, /* R2255 */ + { 0x0000, 0x0000, 0x0000 }, /* R2256 */ + { 0x0000, 0x0000, 0x0000 }, /* R2257 */ + { 0x0000, 0x0000, 0x0000 }, /* R2258 */ + { 0x0000, 0x0000, 0x0000 }, /* R2259 */ + { 0x0000, 0x0000, 0x0000 }, /* R2260 */ + { 0x0000, 0x0000, 0x0000 }, /* R2261 */ + { 0x0000, 0x0000, 0x0000 }, /* R2262 */ + { 0x0000, 0x0000, 0x0000 }, /* R2263 */ + { 0x0000, 0x0000, 0x0000 }, /* R2264 */ + { 0x0000, 0x0000, 0x0000 }, /* R2265 */ + { 0x0000, 0x0000, 0x0000 }, /* R2266 */ + { 0x0000, 0x0000, 0x0000 }, /* R2267 */ + { 0x0000, 0x0000, 0x0000 }, /* R2268 */ + { 0x0000, 0x0000, 0x0000 }, /* R2269 */ + { 0x0000, 0x0000, 0x0000 }, /* R2270 */ + { 0x0000, 0x0000, 0x0000 }, /* R2271 */ + { 0x0000, 0x0000, 0x0000 }, /* R2272 */ + { 0x0000, 0x0000, 0x0000 }, /* R2273 */ + { 0x0000, 0x0000, 0x0000 }, /* R2274 */ + { 0x0000, 0x0000, 0x0000 }, /* R2275 */ + { 0x0000, 0x0000, 0x0000 }, /* R2276 */ + { 0x0000, 0x0000, 0x0000 }, /* R2277 */ + { 0x0000, 0x0000, 0x0000 }, /* R2278 */ + { 0x0000, 0x0000, 0x0000 }, /* R2279 */ + { 0x0000, 0x0000, 0x0000 }, /* R2280 */ + { 0x0000, 0x0000, 0x0000 }, /* R2281 */ + { 0x0000, 0x0000, 0x0000 }, /* R2282 */ + { 0x0000, 0x0000, 0x0000 }, /* R2283 */ + { 0x0000, 0x0000, 0x0000 }, /* R2284 */ + { 0x0000, 0x0000, 0x0000 }, /* R2285 */ + { 0x0000, 0x0000, 0x0000 }, /* R2286 */ + { 0x0000, 0x0000, 0x0000 }, /* R2287 */ + { 0x0000, 0x0000, 0x0000 }, /* R2288 */ + { 0x0000, 0x0000, 0x0000 }, /* R2289 */ + { 0x0000, 0x0000, 0x0000 }, /* R2290 */ + { 0x0000, 0x0000, 0x0000 }, /* R2291 */ + { 0x0000, 0x0000, 0x0000 }, /* R2292 */ + { 0x0000, 0x0000, 0x0000 }, /* R2293 */ + { 0x0000, 0x0000, 0x0000 }, /* R2294 */ + { 0x0000, 0x0000, 0x0000 }, /* R2295 */ + { 0x0000, 0x0000, 0x0000 }, /* R2296 */ + { 0x0000, 0x0000, 0x0000 }, /* R2297 */ + { 0x0000, 0x0000, 0x0000 }, /* R2298 */ + { 0x0000, 0x0000, 0x0000 }, /* R2299 */ + { 0x0000, 0x0000, 0x0000 }, /* R2300 */ + { 0x0000, 0x0000, 0x0000 }, /* R2301 */ + { 0x0000, 0x0000, 0x0000 }, /* R2302 */ + { 0x0000, 0x0000, 0x0000 }, /* R2303 */ + { 0x0000, 0x0000, 0x0000 }, /* R2304 */ + { 0x0000, 0x0000, 0x0000 }, /* R2305 */ + { 0x0000, 0x0000, 0x0000 }, /* R2306 */ + { 0x0000, 0x0000, 0x0000 }, /* R2307 */ + { 0x0000, 0x0000, 0x0000 }, /* R2308 */ + { 0x0000, 0x0000, 0x0000 }, /* R2309 */ + { 0x0000, 0x0000, 0x0000 }, /* R2310 */ + { 0x0000, 0x0000, 0x0000 }, /* R2311 */ + { 0x0000, 0x0000, 0x0000 }, /* R2312 */ + { 0x0000, 0x0000, 0x0000 }, /* R2313 */ + { 0x0000, 0x0000, 0x0000 }, /* R2314 */ + { 0x0000, 0x0000, 0x0000 }, /* R2315 */ + { 0x0000, 0x0000, 0x0000 }, /* R2316 */ + { 0x0000, 0x0000, 0x0000 }, /* R2317 */ + { 0x0000, 0x0000, 0x0000 }, /* R2318 */ + { 0x0000, 0x0000, 0x0000 }, /* R2319 */ + { 0x0000, 0x0000, 0x0000 }, /* R2320 */ + { 0x0000, 0x0000, 0x0000 }, /* R2321 */ + { 0x0000, 0x0000, 0x0000 }, /* R2322 */ + { 0x0000, 0x0000, 0x0000 }, /* R2323 */ + { 0x0000, 0x0000, 0x0000 }, /* R2324 */ + { 0x0000, 0x0000, 0x0000 }, /* R2325 */ + { 0x0000, 0x0000, 0x0000 }, /* R2326 */ + { 0x0000, 0x0000, 0x0000 }, /* R2327 */ + { 0x0000, 0x0000, 0x0000 }, /* R2328 */ + { 0x0000, 0x0000, 0x0000 }, /* R2329 */ + { 0x0000, 0x0000, 0x0000 }, /* R2330 */ + { 0x0000, 0x0000, 0x0000 }, /* R2331 */ + { 0x0000, 0x0000, 0x0000 }, /* R2332 */ + { 0x0000, 0x0000, 0x0000 }, /* R2333 */ + { 0x0000, 0x0000, 0x0000 }, /* R2334 */ + { 0x0000, 0x0000, 0x0000 }, /* R2335 */ + { 0x0000, 0x0000, 0x0000 }, /* R2336 */ + { 0x0000, 0x0000, 0x0000 }, /* R2337 */ + { 0x0000, 0x0000, 0x0000 }, /* R2338 */ + { 0x0000, 0x0000, 0x0000 }, /* R2339 */ + { 0x0000, 0x0000, 0x0000 }, /* R2340 */ + { 0x0000, 0x0000, 0x0000 }, /* R2341 */ + { 0x0000, 0x0000, 0x0000 }, /* R2342 */ + { 0x0000, 0x0000, 0x0000 }, /* R2343 */ + { 0x0000, 0x0000, 0x0000 }, /* R2344 */ + { 0x0000, 0x0000, 0x0000 }, /* R2345 */ + { 0x0000, 0x0000, 0x0000 }, /* R2346 */ + { 0x0000, 0x0000, 0x0000 }, /* R2347 */ + { 0x0000, 0x0000, 0x0000 }, /* R2348 */ + { 0x0000, 0x0000, 0x0000 }, /* R2349 */ + { 0x0000, 0x0000, 0x0000 }, /* R2350 */ + { 0x0000, 0x0000, 0x0000 }, /* R2351 */ + { 0x0000, 0x0000, 0x0000 }, /* R2352 */ + { 0x0000, 0x0000, 0x0000 }, /* R2353 */ + { 0x0000, 0x0000, 0x0000 }, /* R2354 */ + { 0x0000, 0x0000, 0x0000 }, /* R2355 */ + { 0x0000, 0x0000, 0x0000 }, /* R2356 */ + { 0x0000, 0x0000, 0x0000 }, /* R2357 */ + { 0x0000, 0x0000, 0x0000 }, /* R2358 */ + { 0x0000, 0x0000, 0x0000 }, /* R2359 */ + { 0x0000, 0x0000, 0x0000 }, /* R2360 */ + { 0x0000, 0x0000, 0x0000 }, /* R2361 */ + { 0x0000, 0x0000, 0x0000 }, /* R2362 */ + { 0x0000, 0x0000, 0x0000 }, /* R2363 */ + { 0x0000, 0x0000, 0x0000 }, /* R2364 */ + { 0x0000, 0x0000, 0x0000 }, /* R2365 */ + { 0x0000, 0x0000, 0x0000 }, /* R2366 */ + { 0x0000, 0x0000, 0x0000 }, /* R2367 */ + { 0x0000, 0x0000, 0x0000 }, /* R2368 */ + { 0x0000, 0x0000, 0x0000 }, /* R2369 */ + { 0x0000, 0x0000, 0x0000 }, /* R2370 */ + { 0x0000, 0x0000, 0x0000 }, /* R2371 */ + { 0x0000, 0x0000, 0x0000 }, /* R2372 */ + { 0x0000, 0x0000, 0x0000 }, /* R2373 */ + { 0x0000, 0x0000, 0x0000 }, /* R2374 */ + { 0x0000, 0x0000, 0x0000 }, /* R2375 */ + { 0x0000, 0x0000, 0x0000 }, /* R2376 */ + { 0x0000, 0x0000, 0x0000 }, /* R2377 */ + { 0x0000, 0x0000, 0x0000 }, /* R2378 */ + { 0x0000, 0x0000, 0x0000 }, /* R2379 */ + { 0x0000, 0x0000, 0x0000 }, /* R2380 */ + { 0x0000, 0x0000, 0x0000 }, /* R2381 */ + { 0x0000, 0x0000, 0x0000 }, /* R2382 */ + { 0x0000, 0x0000, 0x0000 }, /* R2383 */ + { 0x0000, 0x0000, 0x0000 }, /* R2384 */ + { 0x0000, 0x0000, 0x0000 }, /* R2385 */ + { 0x0000, 0x0000, 0x0000 }, /* R2386 */ + { 0x0000, 0x0000, 0x0000 }, /* R2387 */ + { 0x0000, 0x0000, 0x0000 }, /* R2388 */ + { 0x0000, 0x0000, 0x0000 }, /* R2389 */ + { 0x0000, 0x0000, 0x0000 }, /* R2390 */ + { 0x0000, 0x0000, 0x0000 }, /* R2391 */ + { 0x0000, 0x0000, 0x0000 }, /* R2392 */ + { 0x0000, 0x0000, 0x0000 }, /* R2393 */ + { 0x0000, 0x0000, 0x0000 }, /* R2394 */ + { 0x0000, 0x0000, 0x0000 }, /* R2395 */ + { 0x0000, 0x0000, 0x0000 }, /* R2396 */ + { 0x0000, 0x0000, 0x0000 }, /* R2397 */ + { 0x0000, 0x0000, 0x0000 }, /* R2398 */ + { 0x0000, 0x0000, 0x0000 }, /* R2399 */ + { 0x0000, 0x0000, 0x0000 }, /* R2400 */ + { 0x0000, 0x0000, 0x0000 }, /* R2401 */ + { 0x0000, 0x0000, 0x0000 }, /* R2402 */ + { 0x0000, 0x0000, 0x0000 }, /* R2403 */ + { 0x0000, 0x0000, 0x0000 }, /* R2404 */ + { 0x0000, 0x0000, 0x0000 }, /* R2405 */ + { 0x0000, 0x0000, 0x0000 }, /* R2406 */ + { 0x0000, 0x0000, 0x0000 }, /* R2407 */ + { 0x0000, 0x0000, 0x0000 }, /* R2408 */ + { 0x0000, 0x0000, 0x0000 }, /* R2409 */ + { 0x0000, 0x0000, 0x0000 }, /* R2410 */ + { 0x0000, 0x0000, 0x0000 }, /* R2411 */ + { 0x0000, 0x0000, 0x0000 }, /* R2412 */ + { 0x0000, 0x0000, 0x0000 }, /* R2413 */ + { 0x0000, 0x0000, 0x0000 }, /* R2414 */ + { 0x0000, 0x0000, 0x0000 }, /* R2415 */ + { 0x0000, 0x0000, 0x0000 }, /* R2416 */ + { 0x0000, 0x0000, 0x0000 }, /* R2417 */ + { 0x0000, 0x0000, 0x0000 }, /* R2418 */ + { 0x0000, 0x0000, 0x0000 }, /* R2419 */ + { 0x0000, 0x0000, 0x0000 }, /* R2420 */ + { 0x0000, 0x0000, 0x0000 }, /* R2421 */ + { 0x0000, 0x0000, 0x0000 }, /* R2422 */ + { 0x0000, 0x0000, 0x0000 }, /* R2423 */ + { 0x0000, 0x0000, 0x0000 }, /* R2424 */ + { 0x0000, 0x0000, 0x0000 }, /* R2425 */ + { 0x0000, 0x0000, 0x0000 }, /* R2426 */ + { 0x0000, 0x0000, 0x0000 }, /* R2427 */ + { 0x0000, 0x0000, 0x0000 }, /* R2428 */ + { 0x0000, 0x0000, 0x0000 }, /* R2429 */ + { 0x0000, 0x0000, 0x0000 }, /* R2430 */ + { 0x0000, 0x0000, 0x0000 }, /* R2431 */ + { 0x0000, 0x0000, 0x0000 }, /* R2432 */ + { 0x0000, 0x0000, 0x0000 }, /* R2433 */ + { 0x0000, 0x0000, 0x0000 }, /* R2434 */ + { 0x0000, 0x0000, 0x0000 }, /* R2435 */ + { 0x0000, 0x0000, 0x0000 }, /* R2436 */ + { 0x0000, 0x0000, 0x0000 }, /* R2437 */ + { 0x0000, 0x0000, 0x0000 }, /* R2438 */ + { 0x0000, 0x0000, 0x0000 }, /* R2439 */ + { 0x0000, 0x0000, 0x0000 }, /* R2440 */ + { 0x0000, 0x0000, 0x0000 }, /* R2441 */ + { 0x0000, 0x0000, 0x0000 }, /* R2442 */ + { 0x0000, 0x0000, 0x0000 }, /* R2443 */ + { 0x0000, 0x0000, 0x0000 }, /* R2444 */ + { 0x0000, 0x0000, 0x0000 }, /* R2445 */ + { 0x0000, 0x0000, 0x0000 }, /* R2446 */ + { 0x0000, 0x0000, 0x0000 }, /* R2447 */ + { 0x0000, 0x0000, 0x0000 }, /* R2448 */ + { 0x0000, 0x0000, 0x0000 }, /* R2449 */ + { 0x0000, 0x0000, 0x0000 }, /* R2450 */ + { 0x0000, 0x0000, 0x0000 }, /* R2451 */ + { 0x0000, 0x0000, 0x0000 }, /* R2452 */ + { 0x0000, 0x0000, 0x0000 }, /* R2453 */ + { 0x0000, 0x0000, 0x0000 }, /* R2454 */ + { 0x0000, 0x0000, 0x0000 }, /* R2455 */ + { 0x0000, 0x0000, 0x0000 }, /* R2456 */ + { 0x0000, 0x0000, 0x0000 }, /* R2457 */ + { 0x0000, 0x0000, 0x0000 }, /* R2458 */ + { 0x0000, 0x0000, 0x0000 }, /* R2459 */ + { 0x0000, 0x0000, 0x0000 }, /* R2460 */ + { 0x0000, 0x0000, 0x0000 }, /* R2461 */ + { 0x0000, 0x0000, 0x0000 }, /* R2462 */ + { 0x0000, 0x0000, 0x0000 }, /* R2463 */ + { 0x0000, 0x0000, 0x0000 }, /* R2464 */ + { 0x0000, 0x0000, 0x0000 }, /* R2465 */ + { 0x0000, 0x0000, 0x0000 }, /* R2466 */ + { 0x0000, 0x0000, 0x0000 }, /* R2467 */ + { 0x0000, 0x0000, 0x0000 }, /* R2468 */ + { 0x0000, 0x0000, 0x0000 }, /* R2469 */ + { 0x0000, 0x0000, 0x0000 }, /* R2470 */ + { 0x0000, 0x0000, 0x0000 }, /* R2471 */ + { 0x0000, 0x0000, 0x0000 }, /* R2472 */ + { 0x0000, 0x0000, 0x0000 }, /* R2473 */ + { 0x0000, 0x0000, 0x0000 }, /* R2474 */ + { 0x0000, 0x0000, 0x0000 }, /* R2475 */ + { 0x0000, 0x0000, 0x0000 }, /* R2476 */ + { 0x0000, 0x0000, 0x0000 }, /* R2477 */ + { 0x0000, 0x0000, 0x0000 }, /* R2478 */ + { 0x0000, 0x0000, 0x0000 }, /* R2479 */ + { 0x0000, 0x0000, 0x0000 }, /* R2480 */ + { 0x0000, 0x0000, 0x0000 }, /* R2481 */ + { 0x0000, 0x0000, 0x0000 }, /* R2482 */ + { 0x0000, 0x0000, 0x0000 }, /* R2483 */ + { 0x0000, 0x0000, 0x0000 }, /* R2484 */ + { 0x0000, 0x0000, 0x0000 }, /* R2485 */ + { 0x0000, 0x0000, 0x0000 }, /* R2486 */ + { 0x0000, 0x0000, 0x0000 }, /* R2487 */ + { 0x0000, 0x0000, 0x0000 }, /* R2488 */ + { 0x0000, 0x0000, 0x0000 }, /* R2489 */ + { 0x0000, 0x0000, 0x0000 }, /* R2490 */ + { 0x0000, 0x0000, 0x0000 }, /* R2491 */ + { 0x0000, 0x0000, 0x0000 }, /* R2492 */ + { 0x0000, 0x0000, 0x0000 }, /* R2493 */ + { 0x0000, 0x0000, 0x0000 }, /* R2494 */ + { 0x0000, 0x0000, 0x0000 }, /* R2495 */ + { 0x0000, 0x0000, 0x0000 }, /* R2496 */ + { 0x0000, 0x0000, 0x0000 }, /* R2497 */ + { 0x0000, 0x0000, 0x0000 }, /* R2498 */ + { 0x0000, 0x0000, 0x0000 }, /* R2499 */ + { 0x0000, 0x0000, 0x0000 }, /* R2500 */ + { 0x0000, 0x0000, 0x0000 }, /* R2501 */ + { 0x0000, 0x0000, 0x0000 }, /* R2502 */ + { 0x0000, 0x0000, 0x0000 }, /* R2503 */ + { 0x0000, 0x0000, 0x0000 }, /* R2504 */ + { 0x0000, 0x0000, 0x0000 }, /* R2505 */ + { 0x0000, 0x0000, 0x0000 }, /* R2506 */ + { 0x0000, 0x0000, 0x0000 }, /* R2507 */ + { 0x0000, 0x0000, 0x0000 }, /* R2508 */ + { 0x0000, 0x0000, 0x0000 }, /* R2509 */ + { 0x0000, 0x0000, 0x0000 }, /* R2510 */ + { 0x0000, 0x0000, 0x0000 }, /* R2511 */ + { 0x0000, 0x0000, 0x0000 }, /* R2512 */ + { 0x0000, 0x0000, 0x0000 }, /* R2513 */ + { 0x0000, 0x0000, 0x0000 }, /* R2514 */ + { 0x0000, 0x0000, 0x0000 }, /* R2515 */ + { 0x0000, 0x0000, 0x0000 }, /* R2516 */ + { 0x0000, 0x0000, 0x0000 }, /* R2517 */ + { 0x0000, 0x0000, 0x0000 }, /* R2518 */ + { 0x0000, 0x0000, 0x0000 }, /* R2519 */ + { 0x0000, 0x0000, 0x0000 }, /* R2520 */ + { 0x0000, 0x0000, 0x0000 }, /* R2521 */ + { 0x0000, 0x0000, 0x0000 }, /* R2522 */ + { 0x0000, 0x0000, 0x0000 }, /* R2523 */ + { 0x0000, 0x0000, 0x0000 }, /* R2524 */ + { 0x0000, 0x0000, 0x0000 }, /* R2525 */ + { 0x0000, 0x0000, 0x0000 }, /* R2526 */ + { 0x0000, 0x0000, 0x0000 }, /* R2527 */ + { 0x0000, 0x0000, 0x0000 }, /* R2528 */ + { 0x0000, 0x0000, 0x0000 }, /* R2529 */ + { 0x0000, 0x0000, 0x0000 }, /* R2530 */ + { 0x0000, 0x0000, 0x0000 }, /* R2531 */ + { 0x0000, 0x0000, 0x0000 }, /* R2532 */ + { 0x0000, 0x0000, 0x0000 }, /* R2533 */ + { 0x0000, 0x0000, 0x0000 }, /* R2534 */ + { 0x0000, 0x0000, 0x0000 }, /* R2535 */ + { 0x0000, 0x0000, 0x0000 }, /* R2536 */ + { 0x0000, 0x0000, 0x0000 }, /* R2537 */ + { 0x0000, 0x0000, 0x0000 }, /* R2538 */ + { 0x0000, 0x0000, 0x0000 }, /* R2539 */ + { 0x0000, 0x0000, 0x0000 }, /* R2540 */ + { 0x0000, 0x0000, 0x0000 }, /* R2541 */ + { 0x0000, 0x0000, 0x0000 }, /* R2542 */ + { 0x0000, 0x0000, 0x0000 }, /* R2543 */ + { 0x0000, 0x0000, 0x0000 }, /* R2544 */ + { 0x0000, 0x0000, 0x0000 }, /* R2545 */ + { 0x0000, 0x0000, 0x0000 }, /* R2546 */ + { 0x0000, 0x0000, 0x0000 }, /* R2547 */ + { 0x0000, 0x0000, 0x0000 }, /* R2548 */ + { 0x0000, 0x0000, 0x0000 }, /* R2549 */ + { 0x0000, 0x0000, 0x0000 }, /* R2550 */ + { 0x0000, 0x0000, 0x0000 }, /* R2551 */ + { 0x0000, 0x0000, 0x0000 }, /* R2552 */ + { 0x0000, 0x0000, 0x0000 }, /* R2553 */ + { 0x0000, 0x0000, 0x0000 }, /* R2554 */ + { 0x0000, 0x0000, 0x0000 }, /* R2555 */ + { 0x0000, 0x0000, 0x0000 }, /* R2556 */ + { 0x0000, 0x0000, 0x0000 }, /* R2557 */ + { 0x0000, 0x0000, 0x0000 }, /* R2558 */ + { 0x0000, 0x0000, 0x0000 }, /* R2559 */ + { 0x0000, 0x0000, 0x0000 }, /* R2560 */ + { 0x0000, 0x0000, 0x0000 }, /* R2561 */ + { 0x0000, 0x0000, 0x0000 }, /* R2562 */ + { 0x0000, 0x0000, 0x0000 }, /* R2563 */ + { 0x0000, 0x0000, 0x0000 }, /* R2564 */ + { 0x0000, 0x0000, 0x0000 }, /* R2565 */ + { 0x0000, 0x0000, 0x0000 }, /* R2566 */ + { 0x0000, 0x0000, 0x0000 }, /* R2567 */ + { 0x0000, 0x0000, 0x0000 }, /* R2568 */ + { 0x0000, 0x0000, 0x0000 }, /* R2569 */ + { 0x0000, 0x0000, 0x0000 }, /* R2570 */ + { 0x0000, 0x0000, 0x0000 }, /* R2571 */ + { 0x0000, 0x0000, 0x0000 }, /* R2572 */ + { 0x0000, 0x0000, 0x0000 }, /* R2573 */ + { 0x0000, 0x0000, 0x0000 }, /* R2574 */ + { 0x0000, 0x0000, 0x0000 }, /* R2575 */ + { 0x0000, 0x0000, 0x0000 }, /* R2576 */ + { 0x0000, 0x0000, 0x0000 }, /* R2577 */ + { 0x0000, 0x0000, 0x0000 }, /* R2578 */ + { 0x0000, 0x0000, 0x0000 }, /* R2579 */ + { 0x0000, 0x0000, 0x0000 }, /* R2580 */ + { 0x0000, 0x0000, 0x0000 }, /* R2581 */ + { 0x0000, 0x0000, 0x0000 }, /* R2582 */ + { 0x0000, 0x0000, 0x0000 }, /* R2583 */ + { 0x0000, 0x0000, 0x0000 }, /* R2584 */ + { 0x0000, 0x0000, 0x0000 }, /* R2585 */ + { 0x0000, 0x0000, 0x0000 }, /* R2586 */ + { 0x0000, 0x0000, 0x0000 }, /* R2587 */ + { 0x0000, 0x0000, 0x0000 }, /* R2588 */ + { 0x0000, 0x0000, 0x0000 }, /* R2589 */ + { 0x0000, 0x0000, 0x0000 }, /* R2590 */ + { 0x0000, 0x0000, 0x0000 }, /* R2591 */ + { 0x0000, 0x0000, 0x0000 }, /* R2592 */ + { 0x0000, 0x0000, 0x0000 }, /* R2593 */ + { 0x0000, 0x0000, 0x0000 }, /* R2594 */ + { 0x0000, 0x0000, 0x0000 }, /* R2595 */ + { 0x0000, 0x0000, 0x0000 }, /* R2596 */ + { 0x0000, 0x0000, 0x0000 }, /* R2597 */ + { 0x0000, 0x0000, 0x0000 }, /* R2598 */ + { 0x0000, 0x0000, 0x0000 }, /* R2599 */ + { 0x0000, 0x0000, 0x0000 }, /* R2600 */ + { 0x0000, 0x0000, 0x0000 }, /* R2601 */ + { 0x0000, 0x0000, 0x0000 }, /* R2602 */ + { 0x0000, 0x0000, 0x0000 }, /* R2603 */ + { 0x0000, 0x0000, 0x0000 }, /* R2604 */ + { 0x0000, 0x0000, 0x0000 }, /* R2605 */ + { 0x0000, 0x0000, 0x0000 }, /* R2606 */ + { 0x0000, 0x0000, 0x0000 }, /* R2607 */ + { 0x0000, 0x0000, 0x0000 }, /* R2608 */ + { 0x0000, 0x0000, 0x0000 }, /* R2609 */ + { 0x0000, 0x0000, 0x0000 }, /* R2610 */ + { 0x0000, 0x0000, 0x0000 }, /* R2611 */ + { 0x0000, 0x0000, 0x0000 }, /* R2612 */ + { 0x0000, 0x0000, 0x0000 }, /* R2613 */ + { 0x0000, 0x0000, 0x0000 }, /* R2614 */ + { 0x0000, 0x0000, 0x0000 }, /* R2615 */ + { 0x0000, 0x0000, 0x0000 }, /* R2616 */ + { 0x0000, 0x0000, 0x0000 }, /* R2617 */ + { 0x0000, 0x0000, 0x0000 }, /* R2618 */ + { 0x0000, 0x0000, 0x0000 }, /* R2619 */ + { 0x0000, 0x0000, 0x0000 }, /* R2620 */ + { 0x0000, 0x0000, 0x0000 }, /* R2621 */ + { 0x0000, 0x0000, 0x0000 }, /* R2622 */ + { 0x0000, 0x0000, 0x0000 }, /* R2623 */ + { 0x0000, 0x0000, 0x0000 }, /* R2624 */ + { 0x0000, 0x0000, 0x0000 }, /* R2625 */ + { 0x0000, 0x0000, 0x0000 }, /* R2626 */ + { 0x0000, 0x0000, 0x0000 }, /* R2627 */ + { 0x0000, 0x0000, 0x0000 }, /* R2628 */ + { 0x0000, 0x0000, 0x0000 }, /* R2629 */ + { 0x0000, 0x0000, 0x0000 }, /* R2630 */ + { 0x0000, 0x0000, 0x0000 }, /* R2631 */ + { 0x0000, 0x0000, 0x0000 }, /* R2632 */ + { 0x0000, 0x0000, 0x0000 }, /* R2633 */ + { 0x0000, 0x0000, 0x0000 }, /* R2634 */ + { 0x0000, 0x0000, 0x0000 }, /* R2635 */ + { 0x0000, 0x0000, 0x0000 }, /* R2636 */ + { 0x0000, 0x0000, 0x0000 }, /* R2637 */ + { 0x0000, 0x0000, 0x0000 }, /* R2638 */ + { 0x0000, 0x0000, 0x0000 }, /* R2639 */ + { 0x0000, 0x0000, 0x0000 }, /* R2640 */ + { 0x0000, 0x0000, 0x0000 }, /* R2641 */ + { 0x0000, 0x0000, 0x0000 }, /* R2642 */ + { 0x0000, 0x0000, 0x0000 }, /* R2643 */ + { 0x0000, 0x0000, 0x0000 }, /* R2644 */ + { 0x0000, 0x0000, 0x0000 }, /* R2645 */ + { 0x0000, 0x0000, 0x0000 }, /* R2646 */ + { 0x0000, 0x0000, 0x0000 }, /* R2647 */ + { 0x0000, 0x0000, 0x0000 }, /* R2648 */ + { 0x0000, 0x0000, 0x0000 }, /* R2649 */ + { 0x0000, 0x0000, 0x0000 }, /* R2650 */ + { 0x0000, 0x0000, 0x0000 }, /* R2651 */ + { 0x0000, 0x0000, 0x0000 }, /* R2652 */ + { 0x0000, 0x0000, 0x0000 }, /* R2653 */ + { 0x0000, 0x0000, 0x0000 }, /* R2654 */ + { 0x0000, 0x0000, 0x0000 }, /* R2655 */ + { 0x0000, 0x0000, 0x0000 }, /* R2656 */ + { 0x0000, 0x0000, 0x0000 }, /* R2657 */ + { 0x0000, 0x0000, 0x0000 }, /* R2658 */ + { 0x0000, 0x0000, 0x0000 }, /* R2659 */ + { 0x0000, 0x0000, 0x0000 }, /* R2660 */ + { 0x0000, 0x0000, 0x0000 }, /* R2661 */ + { 0x0000, 0x0000, 0x0000 }, /* R2662 */ + { 0x0000, 0x0000, 0x0000 }, /* R2663 */ + { 0x0000, 0x0000, 0x0000 }, /* R2664 */ + { 0x0000, 0x0000, 0x0000 }, /* R2665 */ + { 0x0000, 0x0000, 0x0000 }, /* R2666 */ + { 0x0000, 0x0000, 0x0000 }, /* R2667 */ + { 0x0000, 0x0000, 0x0000 }, /* R2668 */ + { 0x0000, 0x0000, 0x0000 }, /* R2669 */ + { 0x0000, 0x0000, 0x0000 }, /* R2670 */ + { 0x0000, 0x0000, 0x0000 }, /* R2671 */ + { 0x0000, 0x0000, 0x0000 }, /* R2672 */ + { 0x0000, 0x0000, 0x0000 }, /* R2673 */ + { 0x0000, 0x0000, 0x0000 }, /* R2674 */ + { 0x0000, 0x0000, 0x0000 }, /* R2675 */ + { 0x0000, 0x0000, 0x0000 }, /* R2676 */ + { 0x0000, 0x0000, 0x0000 }, /* R2677 */ + { 0x0000, 0x0000, 0x0000 }, /* R2678 */ + { 0x0000, 0x0000, 0x0000 }, /* R2679 */ + { 0x0000, 0x0000, 0x0000 }, /* R2680 */ + { 0x0000, 0x0000, 0x0000 }, /* R2681 */ + { 0x0000, 0x0000, 0x0000 }, /* R2682 */ + { 0x0000, 0x0000, 0x0000 }, /* R2683 */ + { 0x0000, 0x0000, 0x0000 }, /* R2684 */ + { 0x0000, 0x0000, 0x0000 }, /* R2685 */ + { 0x0000, 0x0000, 0x0000 }, /* R2686 */ + { 0x0000, 0x0000, 0x0000 }, /* R2687 */ + { 0x0000, 0x0000, 0x0000 }, /* R2688 */ + { 0x0000, 0x0000, 0x0000 }, /* R2689 */ + { 0x0000, 0x0000, 0x0000 }, /* R2690 */ + { 0x0000, 0x0000, 0x0000 }, /* R2691 */ + { 0x0000, 0x0000, 0x0000 }, /* R2692 */ + { 0x0000, 0x0000, 0x0000 }, /* R2693 */ + { 0x0000, 0x0000, 0x0000 }, /* R2694 */ + { 0x0000, 0x0000, 0x0000 }, /* R2695 */ + { 0x0000, 0x0000, 0x0000 }, /* R2696 */ + { 0x0000, 0x0000, 0x0000 }, /* R2697 */ + { 0x0000, 0x0000, 0x0000 }, /* R2698 */ + { 0x0000, 0x0000, 0x0000 }, /* R2699 */ + { 0x0000, 0x0000, 0x0000 }, /* R2700 */ + { 0x0000, 0x0000, 0x0000 }, /* R2701 */ + { 0x0000, 0x0000, 0x0000 }, /* R2702 */ + { 0x0000, 0x0000, 0x0000 }, /* R2703 */ + { 0x0000, 0x0000, 0x0000 }, /* R2704 */ + { 0x0000, 0x0000, 0x0000 }, /* R2705 */ + { 0x0000, 0x0000, 0x0000 }, /* R2706 */ + { 0x0000, 0x0000, 0x0000 }, /* R2707 */ + { 0x0000, 0x0000, 0x0000 }, /* R2708 */ + { 0x0000, 0x0000, 0x0000 }, /* R2709 */ + { 0x0000, 0x0000, 0x0000 }, /* R2710 */ + { 0x0000, 0x0000, 0x0000 }, /* R2711 */ + { 0x0000, 0x0000, 0x0000 }, /* R2712 */ + { 0x0000, 0x0000, 0x0000 }, /* R2713 */ + { 0x0000, 0x0000, 0x0000 }, /* R2714 */ + { 0x0000, 0x0000, 0x0000 }, /* R2715 */ + { 0x0000, 0x0000, 0x0000 }, /* R2716 */ + { 0x0000, 0x0000, 0x0000 }, /* R2717 */ + { 0x0000, 0x0000, 0x0000 }, /* R2718 */ + { 0x0000, 0x0000, 0x0000 }, /* R2719 */ + { 0x0000, 0x0000, 0x0000 }, /* R2720 */ + { 0x0000, 0x0000, 0x0000 }, /* R2721 */ + { 0x0000, 0x0000, 0x0000 }, /* R2722 */ + { 0x0000, 0x0000, 0x0000 }, /* R2723 */ + { 0x0000, 0x0000, 0x0000 }, /* R2724 */ + { 0x0000, 0x0000, 0x0000 }, /* R2725 */ + { 0x0000, 0x0000, 0x0000 }, /* R2726 */ + { 0x0000, 0x0000, 0x0000 }, /* R2727 */ + { 0x0000, 0x0000, 0x0000 }, /* R2728 */ + { 0x0000, 0x0000, 0x0000 }, /* R2729 */ + { 0x0000, 0x0000, 0x0000 }, /* R2730 */ + { 0x0000, 0x0000, 0x0000 }, /* R2731 */ + { 0x0000, 0x0000, 0x0000 }, /* R2732 */ + { 0x0000, 0x0000, 0x0000 }, /* R2733 */ + { 0x0000, 0x0000, 0x0000 }, /* R2734 */ + { 0x0000, 0x0000, 0x0000 }, /* R2735 */ + { 0x0000, 0x0000, 0x0000 }, /* R2736 */ + { 0x0000, 0x0000, 0x0000 }, /* R2737 */ + { 0x0000, 0x0000, 0x0000 }, /* R2738 */ + { 0x0000, 0x0000, 0x0000 }, /* R2739 */ + { 0x0000, 0x0000, 0x0000 }, /* R2740 */ + { 0x0000, 0x0000, 0x0000 }, /* R2741 */ + { 0x0000, 0x0000, 0x0000 }, /* R2742 */ + { 0x0000, 0x0000, 0x0000 }, /* R2743 */ + { 0x0000, 0x0000, 0x0000 }, /* R2744 */ + { 0x0000, 0x0000, 0x0000 }, /* R2745 */ + { 0x0000, 0x0000, 0x0000 }, /* R2746 */ + { 0x0000, 0x0000, 0x0000 }, /* R2747 */ + { 0x0000, 0x0000, 0x0000 }, /* R2748 */ + { 0x0000, 0x0000, 0x0000 }, /* R2749 */ + { 0x0000, 0x0000, 0x0000 }, /* R2750 */ + { 0x0000, 0x0000, 0x0000 }, /* R2751 */ + { 0x0000, 0x0000, 0x0000 }, /* R2752 */ + { 0x0000, 0x0000, 0x0000 }, /* R2753 */ + { 0x0000, 0x0000, 0x0000 }, /* R2754 */ + { 0x0000, 0x0000, 0x0000 }, /* R2755 */ + { 0x0000, 0x0000, 0x0000 }, /* R2756 */ + { 0x0000, 0x0000, 0x0000 }, /* R2757 */ + { 0x0000, 0x0000, 0x0000 }, /* R2758 */ + { 0x0000, 0x0000, 0x0000 }, /* R2759 */ + { 0x0000, 0x0000, 0x0000 }, /* R2760 */ + { 0x0000, 0x0000, 0x0000 }, /* R2761 */ + { 0x0000, 0x0000, 0x0000 }, /* R2762 */ + { 0x0000, 0x0000, 0x0000 }, /* R2763 */ + { 0x0000, 0x0000, 0x0000 }, /* R2764 */ + { 0x0000, 0x0000, 0x0000 }, /* R2765 */ + { 0x0000, 0x0000, 0x0000 }, /* R2766 */ + { 0x0000, 0x0000, 0x0000 }, /* R2767 */ + { 0x0000, 0x0000, 0x0000 }, /* R2768 */ + { 0x0000, 0x0000, 0x0000 }, /* R2769 */ + { 0x0000, 0x0000, 0x0000 }, /* R2770 */ + { 0x0000, 0x0000, 0x0000 }, /* R2771 */ + { 0x0000, 0x0000, 0x0000 }, /* R2772 */ + { 0x0000, 0x0000, 0x0000 }, /* R2773 */ + { 0x0000, 0x0000, 0x0000 }, /* R2774 */ + { 0x0000, 0x0000, 0x0000 }, /* R2775 */ + { 0x0000, 0x0000, 0x0000 }, /* R2776 */ + { 0x0000, 0x0000, 0x0000 }, /* R2777 */ + { 0x0000, 0x0000, 0x0000 }, /* R2778 */ + { 0x0000, 0x0000, 0x0000 }, /* R2779 */ + { 0x0000, 0x0000, 0x0000 }, /* R2780 */ + { 0x0000, 0x0000, 0x0000 }, /* R2781 */ + { 0x0000, 0x0000, 0x0000 }, /* R2782 */ + { 0x0000, 0x0000, 0x0000 }, /* R2783 */ + { 0x0000, 0x0000, 0x0000 }, /* R2784 */ + { 0x0000, 0x0000, 0x0000 }, /* R2785 */ + { 0x0000, 0x0000, 0x0000 }, /* R2786 */ + { 0x0000, 0x0000, 0x0000 }, /* R2787 */ + { 0x0000, 0x0000, 0x0000 }, /* R2788 */ + { 0x0000, 0x0000, 0x0000 }, /* R2789 */ + { 0x0000, 0x0000, 0x0000 }, /* R2790 */ + { 0x0000, 0x0000, 0x0000 }, /* R2791 */ + { 0x0000, 0x0000, 0x0000 }, /* R2792 */ + { 0x0000, 0x0000, 0x0000 }, /* R2793 */ + { 0x0000, 0x0000, 0x0000 }, /* R2794 */ + { 0x0000, 0x0000, 0x0000 }, /* R2795 */ + { 0x0000, 0x0000, 0x0000 }, /* R2796 */ + { 0x0000, 0x0000, 0x0000 }, /* R2797 */ + { 0x0000, 0x0000, 0x0000 }, /* R2798 */ + { 0x0000, 0x0000, 0x0000 }, /* R2799 */ + { 0x0000, 0x0000, 0x0000 }, /* R2800 */ + { 0x0000, 0x0000, 0x0000 }, /* R2801 */ + { 0x0000, 0x0000, 0x0000 }, /* R2802 */ + { 0x0000, 0x0000, 0x0000 }, /* R2803 */ + { 0x0000, 0x0000, 0x0000 }, /* R2804 */ + { 0x0000, 0x0000, 0x0000 }, /* R2805 */ + { 0x0000, 0x0000, 0x0000 }, /* R2806 */ + { 0x0000, 0x0000, 0x0000 }, /* R2807 */ + { 0x0000, 0x0000, 0x0000 }, /* R2808 */ + { 0x0000, 0x0000, 0x0000 }, /* R2809 */ + { 0x0000, 0x0000, 0x0000 }, /* R2810 */ + { 0x0000, 0x0000, 0x0000 }, /* R2811 */ + { 0x0000, 0x0000, 0x0000 }, /* R2812 */ + { 0x0000, 0x0000, 0x0000 }, /* R2813 */ + { 0x0000, 0x0000, 0x0000 }, /* R2814 */ + { 0x0000, 0x0000, 0x0000 }, /* R2815 */ + { 0x0000, 0x0000, 0x0000 }, /* R2816 */ + { 0x0000, 0x0000, 0x0000 }, /* R2817 */ + { 0x0000, 0x0000, 0x0000 }, /* R2818 */ + { 0x0000, 0x0000, 0x0000 }, /* R2819 */ + { 0x0000, 0x0000, 0x0000 }, /* R2820 */ + { 0x0000, 0x0000, 0x0000 }, /* R2821 */ + { 0x0000, 0x0000, 0x0000 }, /* R2822 */ + { 0x0000, 0x0000, 0x0000 }, /* R2823 */ + { 0x0000, 0x0000, 0x0000 }, /* R2824 */ + { 0x0000, 0x0000, 0x0000 }, /* R2825 */ + { 0x0000, 0x0000, 0x0000 }, /* R2826 */ + { 0x0000, 0x0000, 0x0000 }, /* R2827 */ + { 0x0000, 0x0000, 0x0000 }, /* R2828 */ + { 0x0000, 0x0000, 0x0000 }, /* R2829 */ + { 0x0000, 0x0000, 0x0000 }, /* R2830 */ + { 0x0000, 0x0000, 0x0000 }, /* R2831 */ + { 0x0000, 0x0000, 0x0000 }, /* R2832 */ + { 0x0000, 0x0000, 0x0000 }, /* R2833 */ + { 0x0000, 0x0000, 0x0000 }, /* R2834 */ + { 0x0000, 0x0000, 0x0000 }, /* R2835 */ + { 0x0000, 0x0000, 0x0000 }, /* R2836 */ + { 0x0000, 0x0000, 0x0000 }, /* R2837 */ + { 0x0000, 0x0000, 0x0000 }, /* R2838 */ + { 0x0000, 0x0000, 0x0000 }, /* R2839 */ + { 0x0000, 0x0000, 0x0000 }, /* R2840 */ + { 0x0000, 0x0000, 0x0000 }, /* R2841 */ + { 0x0000, 0x0000, 0x0000 }, /* R2842 */ + { 0x0000, 0x0000, 0x0000 }, /* R2843 */ + { 0x0000, 0x0000, 0x0000 }, /* R2844 */ + { 0x0000, 0x0000, 0x0000 }, /* R2845 */ + { 0x0000, 0x0000, 0x0000 }, /* R2846 */ + { 0x0000, 0x0000, 0x0000 }, /* R2847 */ + { 0x0000, 0x0000, 0x0000 }, /* R2848 */ + { 0x0000, 0x0000, 0x0000 }, /* R2849 */ + { 0x0000, 0x0000, 0x0000 }, /* R2850 */ + { 0x0000, 0x0000, 0x0000 }, /* R2851 */ + { 0x0000, 0x0000, 0x0000 }, /* R2852 */ + { 0x0000, 0x0000, 0x0000 }, /* R2853 */ + { 0x0000, 0x0000, 0x0000 }, /* R2854 */ + { 0x0000, 0x0000, 0x0000 }, /* R2855 */ + { 0x0000, 0x0000, 0x0000 }, /* R2856 */ + { 0x0000, 0x0000, 0x0000 }, /* R2857 */ + { 0x0000, 0x0000, 0x0000 }, /* R2858 */ + { 0x0000, 0x0000, 0x0000 }, /* R2859 */ + { 0x0000, 0x0000, 0x0000 }, /* R2860 */ + { 0x0000, 0x0000, 0x0000 }, /* R2861 */ + { 0x0000, 0x0000, 0x0000 }, /* R2862 */ + { 0x0000, 0x0000, 0x0000 }, /* R2863 */ + { 0x0000, 0x0000, 0x0000 }, /* R2864 */ + { 0x0000, 0x0000, 0x0000 }, /* R2865 */ + { 0x0000, 0x0000, 0x0000 }, /* R2866 */ + { 0x0000, 0x0000, 0x0000 }, /* R2867 */ + { 0x0000, 0x0000, 0x0000 }, /* R2868 */ + { 0x0000, 0x0000, 0x0000 }, /* R2869 */ + { 0x0000, 0x0000, 0x0000 }, /* R2870 */ + { 0x0000, 0x0000, 0x0000 }, /* R2871 */ + { 0x0000, 0x0000, 0x0000 }, /* R2872 */ + { 0x0000, 0x0000, 0x0000 }, /* R2873 */ + { 0x0000, 0x0000, 0x0000 }, /* R2874 */ + { 0x0000, 0x0000, 0x0000 }, /* R2875 */ + { 0x0000, 0x0000, 0x0000 }, /* R2876 */ + { 0x0000, 0x0000, 0x0000 }, /* R2877 */ + { 0x0000, 0x0000, 0x0000 }, /* R2878 */ + { 0x0000, 0x0000, 0x0000 }, /* R2879 */ + { 0x0000, 0x0000, 0x0000 }, /* R2880 */ + { 0x0000, 0x0000, 0x0000 }, /* R2881 */ + { 0x0000, 0x0000, 0x0000 }, /* R2882 */ + { 0x0000, 0x0000, 0x0000 }, /* R2883 */ + { 0x0000, 0x0000, 0x0000 }, /* R2884 */ + { 0x0000, 0x0000, 0x0000 }, /* R2885 */ + { 0x0000, 0x0000, 0x0000 }, /* R2886 */ + { 0x0000, 0x0000, 0x0000 }, /* R2887 */ + { 0x0000, 0x0000, 0x0000 }, /* R2888 */ + { 0x0000, 0x0000, 0x0000 }, /* R2889 */ + { 0x0000, 0x0000, 0x0000 }, /* R2890 */ + { 0x0000, 0x0000, 0x0000 }, /* R2891 */ + { 0x0000, 0x0000, 0x0000 }, /* R2892 */ + { 0x0000, 0x0000, 0x0000 }, /* R2893 */ + { 0x0000, 0x0000, 0x0000 }, /* R2894 */ + { 0x0000, 0x0000, 0x0000 }, /* R2895 */ + { 0x0000, 0x0000, 0x0000 }, /* R2896 */ + { 0x0000, 0x0000, 0x0000 }, /* R2897 */ + { 0x0000, 0x0000, 0x0000 }, /* R2898 */ + { 0x0000, 0x0000, 0x0000 }, /* R2899 */ + { 0x0000, 0x0000, 0x0000 }, /* R2900 */ + { 0x0000, 0x0000, 0x0000 }, /* R2901 */ + { 0x0000, 0x0000, 0x0000 }, /* R2902 */ + { 0x0000, 0x0000, 0x0000 }, /* R2903 */ + { 0x0000, 0x0000, 0x0000 }, /* R2904 */ + { 0x0000, 0x0000, 0x0000 }, /* R2905 */ + { 0x0000, 0x0000, 0x0000 }, /* R2906 */ + { 0x0000, 0x0000, 0x0000 }, /* R2907 */ + { 0x0000, 0x0000, 0x0000 }, /* R2908 */ + { 0x0000, 0x0000, 0x0000 }, /* R2909 */ + { 0x0000, 0x0000, 0x0000 }, /* R2910 */ + { 0x0000, 0x0000, 0x0000 }, /* R2911 */ + { 0x0000, 0x0000, 0x0000 }, /* R2912 */ + { 0x0000, 0x0000, 0x0000 }, /* R2913 */ + { 0x0000, 0x0000, 0x0000 }, /* R2914 */ + { 0x0000, 0x0000, 0x0000 }, /* R2915 */ + { 0x0000, 0x0000, 0x0000 }, /* R2916 */ + { 0x0000, 0x0000, 0x0000 }, /* R2917 */ + { 0x0000, 0x0000, 0x0000 }, /* R2918 */ + { 0x0000, 0x0000, 0x0000 }, /* R2919 */ + { 0x0000, 0x0000, 0x0000 }, /* R2920 */ + { 0x0000, 0x0000, 0x0000 }, /* R2921 */ + { 0x0000, 0x0000, 0x0000 }, /* R2922 */ + { 0x0000, 0x0000, 0x0000 }, /* R2923 */ + { 0x0000, 0x0000, 0x0000 }, /* R2924 */ + { 0x0000, 0x0000, 0x0000 }, /* R2925 */ + { 0x0000, 0x0000, 0x0000 }, /* R2926 */ + { 0x0000, 0x0000, 0x0000 }, /* R2927 */ + { 0x0000, 0x0000, 0x0000 }, /* R2928 */ + { 0x0000, 0x0000, 0x0000 }, /* R2929 */ + { 0x0000, 0x0000, 0x0000 }, /* R2930 */ + { 0x0000, 0x0000, 0x0000 }, /* R2931 */ + { 0x0000, 0x0000, 0x0000 }, /* R2932 */ + { 0x0000, 0x0000, 0x0000 }, /* R2933 */ + { 0x0000, 0x0000, 0x0000 }, /* R2934 */ + { 0x0000, 0x0000, 0x0000 }, /* R2935 */ + { 0x0000, 0x0000, 0x0000 }, /* R2936 */ + { 0x0000, 0x0000, 0x0000 }, /* R2937 */ + { 0x0000, 0x0000, 0x0000 }, /* R2938 */ + { 0x0000, 0x0000, 0x0000 }, /* R2939 */ + { 0x0000, 0x0000, 0x0000 }, /* R2940 */ + { 0x0000, 0x0000, 0x0000 }, /* R2941 */ + { 0x0000, 0x0000, 0x0000 }, /* R2942 */ + { 0x0000, 0x0000, 0x0000 }, /* R2943 */ + { 0x0000, 0x0000, 0x0000 }, /* R2944 */ + { 0x0000, 0x0000, 0x0000 }, /* R2945 */ + { 0x0000, 0x0000, 0x0000 }, /* R2946 */ + { 0x0000, 0x0000, 0x0000 }, /* R2947 */ + { 0x0000, 0x0000, 0x0000 }, /* R2948 */ + { 0x0000, 0x0000, 0x0000 }, /* R2949 */ + { 0x0000, 0x0000, 0x0000 }, /* R2950 */ + { 0x0000, 0x0000, 0x0000 }, /* R2951 */ + { 0x0000, 0x0000, 0x0000 }, /* R2952 */ + { 0x0000, 0x0000, 0x0000 }, /* R2953 */ + { 0x0000, 0x0000, 0x0000 }, /* R2954 */ + { 0x0000, 0x0000, 0x0000 }, /* R2955 */ + { 0x0000, 0x0000, 0x0000 }, /* R2956 */ + { 0x0000, 0x0000, 0x0000 }, /* R2957 */ + { 0x0000, 0x0000, 0x0000 }, /* R2958 */ + { 0x0000, 0x0000, 0x0000 }, /* R2959 */ + { 0x0000, 0x0000, 0x0000 }, /* R2960 */ + { 0x0000, 0x0000, 0x0000 }, /* R2961 */ + { 0x0000, 0x0000, 0x0000 }, /* R2962 */ + { 0x0000, 0x0000, 0x0000 }, /* R2963 */ + { 0x0000, 0x0000, 0x0000 }, /* R2964 */ + { 0x0000, 0x0000, 0x0000 }, /* R2965 */ + { 0x0000, 0x0000, 0x0000 }, /* R2966 */ + { 0x0000, 0x0000, 0x0000 }, /* R2967 */ + { 0x0000, 0x0000, 0x0000 }, /* R2968 */ + { 0x0000, 0x0000, 0x0000 }, /* R2969 */ + { 0x0000, 0x0000, 0x0000 }, /* R2970 */ + { 0x0000, 0x0000, 0x0000 }, /* R2971 */ + { 0x0000, 0x0000, 0x0000 }, /* R2972 */ + { 0x0000, 0x0000, 0x0000 }, /* R2973 */ + { 0x0000, 0x0000, 0x0000 }, /* R2974 */ + { 0x0000, 0x0000, 0x0000 }, /* R2975 */ + { 0x0000, 0x0000, 0x0000 }, /* R2976 */ + { 0x0000, 0x0000, 0x0000 }, /* R2977 */ + { 0x0000, 0x0000, 0x0000 }, /* R2978 */ + { 0x0000, 0x0000, 0x0000 }, /* R2979 */ + { 0x0000, 0x0000, 0x0000 }, /* R2980 */ + { 0x0000, 0x0000, 0x0000 }, /* R2981 */ + { 0x0000, 0x0000, 0x0000 }, /* R2982 */ + { 0x0000, 0x0000, 0x0000 }, /* R2983 */ + { 0x0000, 0x0000, 0x0000 }, /* R2984 */ + { 0x0000, 0x0000, 0x0000 }, /* R2985 */ + { 0x0000, 0x0000, 0x0000 }, /* R2986 */ + { 0x0000, 0x0000, 0x0000 }, /* R2987 */ + { 0x0000, 0x0000, 0x0000 }, /* R2988 */ + { 0x0000, 0x0000, 0x0000 }, /* R2989 */ + { 0x0000, 0x0000, 0x0000 }, /* R2990 */ + { 0x0000, 0x0000, 0x0000 }, /* R2991 */ + { 0x0000, 0x0000, 0x0000 }, /* R2992 */ + { 0x0000, 0x0000, 0x0000 }, /* R2993 */ + { 0x0000, 0x0000, 0x0000 }, /* R2994 */ + { 0x0000, 0x0000, 0x0000 }, /* R2995 */ + { 0x0000, 0x0000, 0x0000 }, /* R2996 */ + { 0x0000, 0x0000, 0x0000 }, /* R2997 */ + { 0x0000, 0x0000, 0x0000 }, /* R2998 */ + { 0x0000, 0x0000, 0x0000 }, /* R2999 */ + { 0x0000, 0x0000, 0x0000 }, /* R3000 */ + { 0x0000, 0x0000, 0x0000 }, /* R3001 */ + { 0x0000, 0x0000, 0x0000 }, /* R3002 */ + { 0x0000, 0x0000, 0x0000 }, /* R3003 */ + { 0x0000, 0x0000, 0x0000 }, /* R3004 */ + { 0x0000, 0x0000, 0x0000 }, /* R3005 */ + { 0x0000, 0x0000, 0x0000 }, /* R3006 */ + { 0x0000, 0x0000, 0x0000 }, /* R3007 */ + { 0x0000, 0x0000, 0x0000 }, /* R3008 */ + { 0x0000, 0x0000, 0x0000 }, /* R3009 */ + { 0x0000, 0x0000, 0x0000 }, /* R3010 */ + { 0x0000, 0x0000, 0x0000 }, /* R3011 */ + { 0x0000, 0x0000, 0x0000 }, /* R3012 */ + { 0x0000, 0x0000, 0x0000 }, /* R3013 */ + { 0x0000, 0x0000, 0x0000 }, /* R3014 */ + { 0x0000, 0x0000, 0x0000 }, /* R3015 */ + { 0x0000, 0x0000, 0x0000 }, /* R3016 */ + { 0x0000, 0x0000, 0x0000 }, /* R3017 */ + { 0x0000, 0x0000, 0x0000 }, /* R3018 */ + { 0x0000, 0x0000, 0x0000 }, /* R3019 */ + { 0x0000, 0x0000, 0x0000 }, /* R3020 */ + { 0x0000, 0x0000, 0x0000 }, /* R3021 */ + { 0x0000, 0x0000, 0x0000 }, /* R3022 */ + { 0x0000, 0x0000, 0x0000 }, /* R3023 */ + { 0x0000, 0x0000, 0x0000 }, /* R3024 */ + { 0x0000, 0x0000, 0x0000 }, /* R3025 */ + { 0x0000, 0x0000, 0x0000 }, /* R3026 */ + { 0x0000, 0x0000, 0x0000 }, /* R3027 */ + { 0x0000, 0x0000, 0x0000 }, /* R3028 */ + { 0x0000, 0x0000, 0x0000 }, /* R3029 */ + { 0x0000, 0x0000, 0x0000 }, /* R3030 */ + { 0x0000, 0x0000, 0x0000 }, /* R3031 */ + { 0x0000, 0x0000, 0x0000 }, /* R3032 */ + { 0x0000, 0x0000, 0x0000 }, /* R3033 */ + { 0x0000, 0x0000, 0x0000 }, /* R3034 */ + { 0x0000, 0x0000, 0x0000 }, /* R3035 */ + { 0x0000, 0x0000, 0x0000 }, /* R3036 */ + { 0x0000, 0x0000, 0x0000 }, /* R3037 */ + { 0x0000, 0x0000, 0x0000 }, /* R3038 */ + { 0x0000, 0x0000, 0x0000 }, /* R3039 */ + { 0x0000, 0x0000, 0x0000 }, /* R3040 */ + { 0x0000, 0x0000, 0x0000 }, /* R3041 */ + { 0x0000, 0x0000, 0x0000 }, /* R3042 */ + { 0x0000, 0x0000, 0x0000 }, /* R3043 */ + { 0x0000, 0x0000, 0x0000 }, /* R3044 */ + { 0x0000, 0x0000, 0x0000 }, /* R3045 */ + { 0x0000, 0x0000, 0x0000 }, /* R3046 */ + { 0x0000, 0x0000, 0x0000 }, /* R3047 */ + { 0x0000, 0x0000, 0x0000 }, /* R3048 */ + { 0x0000, 0x0000, 0x0000 }, /* R3049 */ + { 0x0000, 0x0000, 0x0000 }, /* R3050 */ + { 0x0000, 0x0000, 0x0000 }, /* R3051 */ + { 0x0000, 0x0000, 0x0000 }, /* R3052 */ + { 0x0000, 0x0000, 0x0000 }, /* R3053 */ + { 0x0000, 0x0000, 0x0000 }, /* R3054 */ + { 0x0000, 0x0000, 0x0000 }, /* R3055 */ + { 0x0000, 0x0000, 0x0000 }, /* R3056 */ + { 0x0000, 0x0000, 0x0000 }, /* R3057 */ + { 0x0000, 0x0000, 0x0000 }, /* R3058 */ + { 0x0000, 0x0000, 0x0000 }, /* R3059 */ + { 0x0000, 0x0000, 0x0000 }, /* R3060 */ + { 0x0000, 0x0000, 0x0000 }, /* R3061 */ + { 0x0000, 0x0000, 0x0000 }, /* R3062 */ + { 0x0000, 0x0000, 0x0000 }, /* R3063 */ + { 0x0000, 0x0000, 0x0000 }, /* R3064 */ + { 0x0000, 0x0000, 0x0000 }, /* R3065 */ + { 0x0000, 0x0000, 0x0000 }, /* R3066 */ + { 0x0000, 0x0000, 0x0000 }, /* R3067 */ + { 0x0000, 0x0000, 0x0000 }, /* R3068 */ + { 0x0000, 0x0000, 0x0000 }, /* R3069 */ + { 0x0000, 0x0000, 0x0000 }, /* R3070 */ + { 0x0000, 0x0000, 0x0000 }, /* R3071 */ + { 0x0000, 0x0000, 0x0000 }, /* R3072 */ + { 0x0000, 0x0000, 0x0000 }, /* R3073 */ + { 0x0000, 0x0000, 0x0000 }, /* R3074 */ + { 0x0000, 0x0000, 0x0000 }, /* R3075 */ + { 0x0000, 0x0000, 0x0000 }, /* R3076 */ + { 0x0000, 0x0000, 0x0000 }, /* R3077 */ + { 0x0000, 0x0000, 0x0000 }, /* R3078 */ + { 0x0000, 0x0000, 0x0000 }, /* R3079 */ + { 0x0000, 0x0000, 0x0000 }, /* R3080 */ + { 0x0000, 0x0000, 0x0000 }, /* R3081 */ + { 0x0000, 0x0000, 0x0000 }, /* R3082 */ + { 0x0000, 0x0000, 0x0000 }, /* R3083 */ + { 0x0000, 0x0000, 0x0000 }, /* R3084 */ + { 0x0000, 0x0000, 0x0000 }, /* R3085 */ + { 0x0000, 0x0000, 0x0000 }, /* R3086 */ + { 0x0000, 0x0000, 0x0000 }, /* R3087 */ + { 0x0000, 0x0000, 0x0000 }, /* R3088 */ + { 0x0000, 0x0000, 0x0000 }, /* R3089 */ + { 0x0000, 0x0000, 0x0000 }, /* R3090 */ + { 0x0000, 0x0000, 0x0000 }, /* R3091 */ + { 0x0000, 0x0000, 0x0000 }, /* R3092 */ + { 0x0000, 0x0000, 0x0000 }, /* R3093 */ + { 0x0000, 0x0000, 0x0000 }, /* R3094 */ + { 0x0000, 0x0000, 0x0000 }, /* R3095 */ + { 0x0000, 0x0000, 0x0000 }, /* R3096 */ + { 0x0000, 0x0000, 0x0000 }, /* R3097 */ + { 0x0000, 0x0000, 0x0000 }, /* R3098 */ + { 0x0000, 0x0000, 0x0000 }, /* R3099 */ + { 0x0000, 0x0000, 0x0000 }, /* R3100 */ + { 0x0000, 0x0000, 0x0000 }, /* R3101 */ + { 0x0000, 0x0000, 0x0000 }, /* R3102 */ + { 0x0000, 0x0000, 0x0000 }, /* R3103 */ + { 0x0000, 0x0000, 0x0000 }, /* R3104 */ + { 0x0000, 0x0000, 0x0000 }, /* R3105 */ + { 0x0000, 0x0000, 0x0000 }, /* R3106 */ + { 0x0000, 0x0000, 0x0000 }, /* R3107 */ + { 0x0000, 0x0000, 0x0000 }, /* R3108 */ + { 0x0000, 0x0000, 0x0000 }, /* R3109 */ + { 0x0000, 0x0000, 0x0000 }, /* R3110 */ + { 0x0000, 0x0000, 0x0000 }, /* R3111 */ + { 0x0000, 0x0000, 0x0000 }, /* R3112 */ + { 0x0000, 0x0000, 0x0000 }, /* R3113 */ + { 0x0000, 0x0000, 0x0000 }, /* R3114 */ + { 0x0000, 0x0000, 0x0000 }, /* R3115 */ + { 0x0000, 0x0000, 0x0000 }, /* R3116 */ + { 0x0000, 0x0000, 0x0000 }, /* R3117 */ + { 0x0000, 0x0000, 0x0000 }, /* R3118 */ + { 0x0000, 0x0000, 0x0000 }, /* R3119 */ + { 0x0000, 0x0000, 0x0000 }, /* R3120 */ + { 0x0000, 0x0000, 0x0000 }, /* R3121 */ + { 0x0000, 0x0000, 0x0000 }, /* R3122 */ + { 0x0000, 0x0000, 0x0000 }, /* R3123 */ + { 0x0000, 0x0000, 0x0000 }, /* R3124 */ + { 0x0000, 0x0000, 0x0000 }, /* R3125 */ + { 0x0000, 0x0000, 0x0000 }, /* R3126 */ + { 0x0000, 0x0000, 0x0000 }, /* R3127 */ + { 0x0000, 0x0000, 0x0000 }, /* R3128 */ + { 0x0000, 0x0000, 0x0000 }, /* R3129 */ + { 0x0000, 0x0000, 0x0000 }, /* R3130 */ + { 0x0000, 0x0000, 0x0000 }, /* R3131 */ + { 0x0000, 0x0000, 0x0000 }, /* R3132 */ + { 0x0000, 0x0000, 0x0000 }, /* R3133 */ + { 0x0000, 0x0000, 0x0000 }, /* R3134 */ + { 0x0000, 0x0000, 0x0000 }, /* R3135 */ + { 0x0000, 0x0000, 0x0000 }, /* R3136 */ + { 0x0000, 0x0000, 0x0000 }, /* R3137 */ + { 0x0000, 0x0000, 0x0000 }, /* R3138 */ + { 0x0000, 0x0000, 0x0000 }, /* R3139 */ + { 0x0000, 0x0000, 0x0000 }, /* R3140 */ + { 0x0000, 0x0000, 0x0000 }, /* R3141 */ + { 0x0000, 0x0000, 0x0000 }, /* R3142 */ + { 0x0000, 0x0000, 0x0000 }, /* R3143 */ + { 0x0000, 0x0000, 0x0000 }, /* R3144 */ + { 0x0000, 0x0000, 0x0000 }, /* R3145 */ + { 0x0000, 0x0000, 0x0000 }, /* R3146 */ + { 0x0000, 0x0000, 0x0000 }, /* R3147 */ + { 0x0000, 0x0000, 0x0000 }, /* R3148 */ + { 0x0000, 0x0000, 0x0000 }, /* R3149 */ + { 0x0000, 0x0000, 0x0000 }, /* R3150 */ + { 0x0000, 0x0000, 0x0000 }, /* R3151 */ + { 0x0000, 0x0000, 0x0000 }, /* R3152 */ + { 0x0000, 0x0000, 0x0000 }, /* R3153 */ + { 0x0000, 0x0000, 0x0000 }, /* R3154 */ + { 0x0000, 0x0000, 0x0000 }, /* R3155 */ + { 0x0000, 0x0000, 0x0000 }, /* R3156 */ + { 0x0000, 0x0000, 0x0000 }, /* R3157 */ + { 0x0000, 0x0000, 0x0000 }, /* R3158 */ + { 0x0000, 0x0000, 0x0000 }, /* R3159 */ + { 0x0000, 0x0000, 0x0000 }, /* R3160 */ + { 0x0000, 0x0000, 0x0000 }, /* R3161 */ + { 0x0000, 0x0000, 0x0000 }, /* R3162 */ + { 0x0000, 0x0000, 0x0000 }, /* R3163 */ + { 0x0000, 0x0000, 0x0000 }, /* R3164 */ + { 0x0000, 0x0000, 0x0000 }, /* R3165 */ + { 0x0000, 0x0000, 0x0000 }, /* R3166 */ + { 0x0000, 0x0000, 0x0000 }, /* R3167 */ + { 0x0000, 0x0000, 0x0000 }, /* R3168 */ + { 0x0000, 0x0000, 0x0000 }, /* R3169 */ + { 0x0000, 0x0000, 0x0000 }, /* R3170 */ + { 0x0000, 0x0000, 0x0000 }, /* R3171 */ + { 0x0000, 0x0000, 0x0000 }, /* R3172 */ + { 0x0000, 0x0000, 0x0000 }, /* R3173 */ + { 0x0000, 0x0000, 0x0000 }, /* R3174 */ + { 0x0000, 0x0000, 0x0000 }, /* R3175 */ + { 0x0000, 0x0000, 0x0000 }, /* R3176 */ + { 0x0000, 0x0000, 0x0000 }, /* R3177 */ + { 0x0000, 0x0000, 0x0000 }, /* R3178 */ + { 0x0000, 0x0000, 0x0000 }, /* R3179 */ + { 0x0000, 0x0000, 0x0000 }, /* R3180 */ + { 0x0000, 0x0000, 0x0000 }, /* R3181 */ + { 0x0000, 0x0000, 0x0000 }, /* R3182 */ + { 0x0000, 0x0000, 0x0000 }, /* R3183 */ + { 0x0000, 0x0000, 0x0000 }, /* R3184 */ + { 0x0000, 0x0000, 0x0000 }, /* R3185 */ + { 0x0000, 0x0000, 0x0000 }, /* R3186 */ + { 0x0000, 0x0000, 0x0000 }, /* R3187 */ + { 0x0000, 0x0000, 0x0000 }, /* R3188 */ + { 0x0000, 0x0000, 0x0000 }, /* R3189 */ + { 0x0000, 0x0000, 0x0000 }, /* R3190 */ + { 0x0000, 0x0000, 0x0000 }, /* R3191 */ + { 0x0000, 0x0000, 0x0000 }, /* R3192 */ + { 0x0000, 0x0000, 0x0000 }, /* R3193 */ + { 0x0000, 0x0000, 0x0000 }, /* R3194 */ + { 0x0000, 0x0000, 0x0000 }, /* R3195 */ + { 0x0000, 0x0000, 0x0000 }, /* R3196 */ + { 0x0000, 0x0000, 0x0000 }, /* R3197 */ + { 0x0000, 0x0000, 0x0000 }, /* R3198 */ + { 0x0000, 0x0000, 0x0000 }, /* R3199 */ + { 0x0000, 0x0000, 0x0000 }, /* R3200 */ + { 0x0000, 0x0000, 0x0000 }, /* R3201 */ + { 0x0000, 0x0000, 0x0000 }, /* R3202 */ + { 0x0000, 0x0000, 0x0000 }, /* R3203 */ + { 0x0000, 0x0000, 0x0000 }, /* R3204 */ + { 0x0000, 0x0000, 0x0000 }, /* R3205 */ + { 0x0000, 0x0000, 0x0000 }, /* R3206 */ + { 0x0000, 0x0000, 0x0000 }, /* R3207 */ + { 0x0000, 0x0000, 0x0000 }, /* R3208 */ + { 0x0000, 0x0000, 0x0000 }, /* R3209 */ + { 0x0000, 0x0000, 0x0000 }, /* R3210 */ + { 0x0000, 0x0000, 0x0000 }, /* R3211 */ + { 0x0000, 0x0000, 0x0000 }, /* R3212 */ + { 0x0000, 0x0000, 0x0000 }, /* R3213 */ + { 0x0000, 0x0000, 0x0000 }, /* R3214 */ + { 0x0000, 0x0000, 0x0000 }, /* R3215 */ + { 0x0000, 0x0000, 0x0000 }, /* R3216 */ + { 0x0000, 0x0000, 0x0000 }, /* R3217 */ + { 0x0000, 0x0000, 0x0000 }, /* R3218 */ + { 0x0000, 0x0000, 0x0000 }, /* R3219 */ + { 0x0000, 0x0000, 0x0000 }, /* R3220 */ + { 0x0000, 0x0000, 0x0000 }, /* R3221 */ + { 0x0000, 0x0000, 0x0000 }, /* R3222 */ + { 0x0000, 0x0000, 0x0000 }, /* R3223 */ + { 0x0000, 0x0000, 0x0000 }, /* R3224 */ + { 0x0000, 0x0000, 0x0000 }, /* R3225 */ + { 0x0000, 0x0000, 0x0000 }, /* R3226 */ + { 0x0000, 0x0000, 0x0000 }, /* R3227 */ + { 0x0000, 0x0000, 0x0000 }, /* R3228 */ + { 0x0000, 0x0000, 0x0000 }, /* R3229 */ + { 0x0000, 0x0000, 0x0000 }, /* R3230 */ + { 0x0000, 0x0000, 0x0000 }, /* R3231 */ + { 0x0000, 0x0000, 0x0000 }, /* R3232 */ + { 0x0000, 0x0000, 0x0000 }, /* R3233 */ + { 0x0000, 0x0000, 0x0000 }, /* R3234 */ + { 0x0000, 0x0000, 0x0000 }, /* R3235 */ + { 0x0000, 0x0000, 0x0000 }, /* R3236 */ + { 0x0000, 0x0000, 0x0000 }, /* R3237 */ + { 0x0000, 0x0000, 0x0000 }, /* R3238 */ + { 0x0000, 0x0000, 0x0000 }, /* R3239 */ + { 0x0000, 0x0000, 0x0000 }, /* R3240 */ + { 0x0000, 0x0000, 0x0000 }, /* R3241 */ + { 0x0000, 0x0000, 0x0000 }, /* R3242 */ + { 0x0000, 0x0000, 0x0000 }, /* R3243 */ + { 0x0000, 0x0000, 0x0000 }, /* R3244 */ + { 0x0000, 0x0000, 0x0000 }, /* R3245 */ + { 0x0000, 0x0000, 0x0000 }, /* R3246 */ + { 0x0000, 0x0000, 0x0000 }, /* R3247 */ + { 0x0000, 0x0000, 0x0000 }, /* R3248 */ + { 0x0000, 0x0000, 0x0000 }, /* R3249 */ + { 0x0000, 0x0000, 0x0000 }, /* R3250 */ + { 0x0000, 0x0000, 0x0000 }, /* R3251 */ + { 0x0000, 0x0000, 0x0000 }, /* R3252 */ + { 0x0000, 0x0000, 0x0000 }, /* R3253 */ + { 0x0000, 0x0000, 0x0000 }, /* R3254 */ + { 0x0000, 0x0000, 0x0000 }, /* R3255 */ + { 0x0000, 0x0000, 0x0000 }, /* R3256 */ + { 0x0000, 0x0000, 0x0000 }, /* R3257 */ + { 0x0000, 0x0000, 0x0000 }, /* R3258 */ + { 0x0000, 0x0000, 0x0000 }, /* R3259 */ + { 0x0000, 0x0000, 0x0000 }, /* R3260 */ + { 0x0000, 0x0000, 0x0000 }, /* R3261 */ + { 0x0000, 0x0000, 0x0000 }, /* R3262 */ + { 0x0000, 0x0000, 0x0000 }, /* R3263 */ + { 0x0000, 0x0000, 0x0000 }, /* R3264 */ + { 0x0000, 0x0000, 0x0000 }, /* R3265 */ + { 0x0000, 0x0000, 0x0000 }, /* R3266 */ + { 0x0000, 0x0000, 0x0000 }, /* R3267 */ + { 0x0000, 0x0000, 0x0000 }, /* R3268 */ + { 0x0000, 0x0000, 0x0000 }, /* R3269 */ + { 0x0000, 0x0000, 0x0000 }, /* R3270 */ + { 0x0000, 0x0000, 0x0000 }, /* R3271 */ + { 0x0000, 0x0000, 0x0000 }, /* R3272 */ + { 0x0000, 0x0000, 0x0000 }, /* R3273 */ + { 0x0000, 0x0000, 0x0000 }, /* R3274 */ + { 0x0000, 0x0000, 0x0000 }, /* R3275 */ + { 0x0000, 0x0000, 0x0000 }, /* R3276 */ + { 0x0000, 0x0000, 0x0000 }, /* R3277 */ + { 0x0000, 0x0000, 0x0000 }, /* R3278 */ + { 0x0000, 0x0000, 0x0000 }, /* R3279 */ + { 0x0000, 0x0000, 0x0000 }, /* R3280 */ + { 0x0000, 0x0000, 0x0000 }, /* R3281 */ + { 0x0000, 0x0000, 0x0000 }, /* R3282 */ + { 0x0000, 0x0000, 0x0000 }, /* R3283 */ + { 0x0000, 0x0000, 0x0000 }, /* R3284 */ + { 0x0000, 0x0000, 0x0000 }, /* R3285 */ + { 0x0000, 0x0000, 0x0000 }, /* R3286 */ + { 0x0000, 0x0000, 0x0000 }, /* R3287 */ + { 0x0000, 0x0000, 0x0000 }, /* R3288 */ + { 0x0000, 0x0000, 0x0000 }, /* R3289 */ + { 0x0000, 0x0000, 0x0000 }, /* R3290 */ + { 0x0000, 0x0000, 0x0000 }, /* R3291 */ + { 0x0000, 0x0000, 0x0000 }, /* R3292 */ + { 0x0000, 0x0000, 0x0000 }, /* R3293 */ + { 0x0000, 0x0000, 0x0000 }, /* R3294 */ + { 0x0000, 0x0000, 0x0000 }, /* R3295 */ + { 0x0000, 0x0000, 0x0000 }, /* R3296 */ + { 0x0000, 0x0000, 0x0000 }, /* R3297 */ + { 0x0000, 0x0000, 0x0000 }, /* R3298 */ + { 0x0000, 0x0000, 0x0000 }, /* R3299 */ + { 0x0000, 0x0000, 0x0000 }, /* R3300 */ + { 0x0000, 0x0000, 0x0000 }, /* R3301 */ + { 0x0000, 0x0000, 0x0000 }, /* R3302 */ + { 0x0000, 0x0000, 0x0000 }, /* R3303 */ + { 0x0000, 0x0000, 0x0000 }, /* R3304 */ + { 0x0000, 0x0000, 0x0000 }, /* R3305 */ + { 0x0000, 0x0000, 0x0000 }, /* R3306 */ + { 0x0000, 0x0000, 0x0000 }, /* R3307 */ + { 0x0000, 0x0000, 0x0000 }, /* R3308 */ + { 0x0000, 0x0000, 0x0000 }, /* R3309 */ + { 0x0000, 0x0000, 0x0000 }, /* R3310 */ + { 0x0000, 0x0000, 0x0000 }, /* R3311 */ + { 0x0000, 0x0000, 0x0000 }, /* R3312 */ + { 0x0000, 0x0000, 0x0000 }, /* R3313 */ + { 0x0000, 0x0000, 0x0000 }, /* R3314 */ + { 0x0000, 0x0000, 0x0000 }, /* R3315 */ + { 0x0000, 0x0000, 0x0000 }, /* R3316 */ + { 0x0000, 0x0000, 0x0000 }, /* R3317 */ + { 0x0000, 0x0000, 0x0000 }, /* R3318 */ + { 0x0000, 0x0000, 0x0000 }, /* R3319 */ + { 0x0000, 0x0000, 0x0000 }, /* R3320 */ + { 0x0000, 0x0000, 0x0000 }, /* R3321 */ + { 0x0000, 0x0000, 0x0000 }, /* R3322 */ + { 0x0000, 0x0000, 0x0000 }, /* R3323 */ + { 0x0000, 0x0000, 0x0000 }, /* R3324 */ + { 0x0000, 0x0000, 0x0000 }, /* R3325 */ + { 0x0000, 0x0000, 0x0000 }, /* R3326 */ + { 0x0000, 0x0000, 0x0000 }, /* R3327 */ + { 0x0000, 0x0000, 0x0000 }, /* R3328 */ + { 0x0000, 0x0000, 0x0000 }, /* R3329 */ + { 0x0000, 0x0000, 0x0000 }, /* R3330 */ + { 0x0000, 0x0000, 0x0000 }, /* R3331 */ + { 0x0000, 0x0000, 0x0000 }, /* R3332 */ + { 0x0000, 0x0000, 0x0000 }, /* R3333 */ + { 0x0000, 0x0000, 0x0000 }, /* R3334 */ + { 0x0000, 0x0000, 0x0000 }, /* R3335 */ + { 0x0000, 0x0000, 0x0000 }, /* R3336 */ + { 0x0000, 0x0000, 0x0000 }, /* R3337 */ + { 0x0000, 0x0000, 0x0000 }, /* R3338 */ + { 0x0000, 0x0000, 0x0000 }, /* R3339 */ + { 0x0000, 0x0000, 0x0000 }, /* R3340 */ + { 0x0000, 0x0000, 0x0000 }, /* R3341 */ + { 0x0000, 0x0000, 0x0000 }, /* R3342 */ + { 0x0000, 0x0000, 0x0000 }, /* R3343 */ + { 0x0000, 0x0000, 0x0000 }, /* R3344 */ + { 0x0000, 0x0000, 0x0000 }, /* R3345 */ + { 0x0000, 0x0000, 0x0000 }, /* R3346 */ + { 0x0000, 0x0000, 0x0000 }, /* R3347 */ + { 0x0000, 0x0000, 0x0000 }, /* R3348 */ + { 0x0000, 0x0000, 0x0000 }, /* R3349 */ + { 0x0000, 0x0000, 0x0000 }, /* R3350 */ + { 0x0000, 0x0000, 0x0000 }, /* R3351 */ + { 0x0000, 0x0000, 0x0000 }, /* R3352 */ + { 0x0000, 0x0000, 0x0000 }, /* R3353 */ + { 0x0000, 0x0000, 0x0000 }, /* R3354 */ + { 0x0000, 0x0000, 0x0000 }, /* R3355 */ + { 0x0000, 0x0000, 0x0000 }, /* R3356 */ + { 0x0000, 0x0000, 0x0000 }, /* R3357 */ + { 0x0000, 0x0000, 0x0000 }, /* R3358 */ + { 0x0000, 0x0000, 0x0000 }, /* R3359 */ + { 0x0000, 0x0000, 0x0000 }, /* R3360 */ + { 0x0000, 0x0000, 0x0000 }, /* R3361 */ + { 0x0000, 0x0000, 0x0000 }, /* R3362 */ + { 0x0000, 0x0000, 0x0000 }, /* R3363 */ + { 0x0000, 0x0000, 0x0000 }, /* R3364 */ + { 0x0000, 0x0000, 0x0000 }, /* R3365 */ + { 0x0000, 0x0000, 0x0000 }, /* R3366 */ + { 0x0000, 0x0000, 0x0000 }, /* R3367 */ + { 0x0000, 0x0000, 0x0000 }, /* R3368 */ + { 0x0000, 0x0000, 0x0000 }, /* R3369 */ + { 0x0000, 0x0000, 0x0000 }, /* R3370 */ + { 0x0000, 0x0000, 0x0000 }, /* R3371 */ + { 0x0000, 0x0000, 0x0000 }, /* R3372 */ + { 0x0000, 0x0000, 0x0000 }, /* R3373 */ + { 0x0000, 0x0000, 0x0000 }, /* R3374 */ + { 0x0000, 0x0000, 0x0000 }, /* R3375 */ + { 0x0000, 0x0000, 0x0000 }, /* R3376 */ + { 0x0000, 0x0000, 0x0000 }, /* R3377 */ + { 0x0000, 0x0000, 0x0000 }, /* R3378 */ + { 0x0000, 0x0000, 0x0000 }, /* R3379 */ + { 0x0000, 0x0000, 0x0000 }, /* R3380 */ + { 0x0000, 0x0000, 0x0000 }, /* R3381 */ + { 0x0000, 0x0000, 0x0000 }, /* R3382 */ + { 0x0000, 0x0000, 0x0000 }, /* R3383 */ + { 0x0000, 0x0000, 0x0000 }, /* R3384 */ + { 0x0000, 0x0000, 0x0000 }, /* R3385 */ + { 0x0000, 0x0000, 0x0000 }, /* R3386 */ + { 0x0000, 0x0000, 0x0000 }, /* R3387 */ + { 0x0000, 0x0000, 0x0000 }, /* R3388 */ + { 0x0000, 0x0000, 0x0000 }, /* R3389 */ + { 0x0000, 0x0000, 0x0000 }, /* R3390 */ + { 0x0000, 0x0000, 0x0000 }, /* R3391 */ + { 0x0000, 0x0000, 0x0000 }, /* R3392 */ + { 0x0000, 0x0000, 0x0000 }, /* R3393 */ + { 0x0000, 0x0000, 0x0000 }, /* R3394 */ + { 0x0000, 0x0000, 0x0000 }, /* R3395 */ + { 0x0000, 0x0000, 0x0000 }, /* R3396 */ + { 0x0000, 0x0000, 0x0000 }, /* R3397 */ + { 0x0000, 0x0000, 0x0000 }, /* R3398 */ + { 0x0000, 0x0000, 0x0000 }, /* R3399 */ + { 0x0000, 0x0000, 0x0000 }, /* R3400 */ + { 0x0000, 0x0000, 0x0000 }, /* R3401 */ + { 0x0000, 0x0000, 0x0000 }, /* R3402 */ + { 0x0000, 0x0000, 0x0000 }, /* R3403 */ + { 0x0000, 0x0000, 0x0000 }, /* R3404 */ + { 0x0000, 0x0000, 0x0000 }, /* R3405 */ + { 0x0000, 0x0000, 0x0000 }, /* R3406 */ + { 0x0000, 0x0000, 0x0000 }, /* R3407 */ + { 0x0000, 0x0000, 0x0000 }, /* R3408 */ + { 0x0000, 0x0000, 0x0000 }, /* R3409 */ + { 0x0000, 0x0000, 0x0000 }, /* R3410 */ + { 0x0000, 0x0000, 0x0000 }, /* R3411 */ + { 0x0000, 0x0000, 0x0000 }, /* R3412 */ + { 0x0000, 0x0000, 0x0000 }, /* R3413 */ + { 0x0000, 0x0000, 0x0000 }, /* R3414 */ + { 0x0000, 0x0000, 0x0000 }, /* R3415 */ + { 0x0000, 0x0000, 0x0000 }, /* R3416 */ + { 0x0000, 0x0000, 0x0000 }, /* R3417 */ + { 0x0000, 0x0000, 0x0000 }, /* R3418 */ + { 0x0000, 0x0000, 0x0000 }, /* R3419 */ + { 0x0000, 0x0000, 0x0000 }, /* R3420 */ + { 0x0000, 0x0000, 0x0000 }, /* R3421 */ + { 0x0000, 0x0000, 0x0000 }, /* R3422 */ + { 0x0000, 0x0000, 0x0000 }, /* R3423 */ + { 0x0000, 0x0000, 0x0000 }, /* R3424 */ + { 0x0000, 0x0000, 0x0000 }, /* R3425 */ + { 0x0000, 0x0000, 0x0000 }, /* R3426 */ + { 0x0000, 0x0000, 0x0000 }, /* R3427 */ + { 0x0000, 0x0000, 0x0000 }, /* R3428 */ + { 0x0000, 0x0000, 0x0000 }, /* R3429 */ + { 0x0000, 0x0000, 0x0000 }, /* R3430 */ + { 0x0000, 0x0000, 0x0000 }, /* R3431 */ + { 0x0000, 0x0000, 0x0000 }, /* R3432 */ + { 0x0000, 0x0000, 0x0000 }, /* R3433 */ + { 0x0000, 0x0000, 0x0000 }, /* R3434 */ + { 0x0000, 0x0000, 0x0000 }, /* R3435 */ + { 0x0000, 0x0000, 0x0000 }, /* R3436 */ + { 0x0000, 0x0000, 0x0000 }, /* R3437 */ + { 0x0000, 0x0000, 0x0000 }, /* R3438 */ + { 0x0000, 0x0000, 0x0000 }, /* R3439 */ + { 0x0000, 0x0000, 0x0000 }, /* R3440 */ + { 0x0000, 0x0000, 0x0000 }, /* R3441 */ + { 0x0000, 0x0000, 0x0000 }, /* R3442 */ + { 0x0000, 0x0000, 0x0000 }, /* R3443 */ + { 0x0000, 0x0000, 0x0000 }, /* R3444 */ + { 0x0000, 0x0000, 0x0000 }, /* R3445 */ + { 0x0000, 0x0000, 0x0000 }, /* R3446 */ + { 0x0000, 0x0000, 0x0000 }, /* R3447 */ + { 0x0000, 0x0000, 0x0000 }, /* R3448 */ + { 0x0000, 0x0000, 0x0000 }, /* R3449 */ + { 0x0000, 0x0000, 0x0000 }, /* R3450 */ + { 0x0000, 0x0000, 0x0000 }, /* R3451 */ + { 0x0000, 0x0000, 0x0000 }, /* R3452 */ + { 0x0000, 0x0000, 0x0000 }, /* R3453 */ + { 0x0000, 0x0000, 0x0000 }, /* R3454 */ + { 0x0000, 0x0000, 0x0000 }, /* R3455 */ + { 0x0000, 0x0000, 0x0000 }, /* R3456 */ + { 0x0000, 0x0000, 0x0000 }, /* R3457 */ + { 0x0000, 0x0000, 0x0000 }, /* R3458 */ + { 0x0000, 0x0000, 0x0000 }, /* R3459 */ + { 0x0000, 0x0000, 0x0000 }, /* R3460 */ + { 0x0000, 0x0000, 0x0000 }, /* R3461 */ + { 0x0000, 0x0000, 0x0000 }, /* R3462 */ + { 0x0000, 0x0000, 0x0000 }, /* R3463 */ + { 0x0000, 0x0000, 0x0000 }, /* R3464 */ + { 0x0000, 0x0000, 0x0000 }, /* R3465 */ + { 0x0000, 0x0000, 0x0000 }, /* R3466 */ + { 0x0000, 0x0000, 0x0000 }, /* R3467 */ + { 0x0000, 0x0000, 0x0000 }, /* R3468 */ + { 0x0000, 0x0000, 0x0000 }, /* R3469 */ + { 0x0000, 0x0000, 0x0000 }, /* R3470 */ + { 0x0000, 0x0000, 0x0000 }, /* R3471 */ + { 0x0000, 0x0000, 0x0000 }, /* R3472 */ + { 0x0000, 0x0000, 0x0000 }, /* R3473 */ + { 0x0000, 0x0000, 0x0000 }, /* R3474 */ + { 0x0000, 0x0000, 0x0000 }, /* R3475 */ + { 0x0000, 0x0000, 0x0000 }, /* R3476 */ + { 0x0000, 0x0000, 0x0000 }, /* R3477 */ + { 0x0000, 0x0000, 0x0000 }, /* R3478 */ + { 0x0000, 0x0000, 0x0000 }, /* R3479 */ + { 0x0000, 0x0000, 0x0000 }, /* R3480 */ + { 0x0000, 0x0000, 0x0000 }, /* R3481 */ + { 0x0000, 0x0000, 0x0000 }, /* R3482 */ + { 0x0000, 0x0000, 0x0000 }, /* R3483 */ + { 0x0000, 0x0000, 0x0000 }, /* R3484 */ + { 0x0000, 0x0000, 0x0000 }, /* R3485 */ + { 0x0000, 0x0000, 0x0000 }, /* R3486 */ + { 0x0000, 0x0000, 0x0000 }, /* R3487 */ + { 0x0000, 0x0000, 0x0000 }, /* R3488 */ + { 0x0000, 0x0000, 0x0000 }, /* R3489 */ + { 0x0000, 0x0000, 0x0000 }, /* R3490 */ + { 0x0000, 0x0000, 0x0000 }, /* R3491 */ + { 0x0000, 0x0000, 0x0000 }, /* R3492 */ + { 0x0000, 0x0000, 0x0000 }, /* R3493 */ + { 0x0000, 0x0000, 0x0000 }, /* R3494 */ + { 0x0000, 0x0000, 0x0000 }, /* R3495 */ + { 0x0000, 0x0000, 0x0000 }, /* R3496 */ + { 0x0000, 0x0000, 0x0000 }, /* R3497 */ + { 0x0000, 0x0000, 0x0000 }, /* R3498 */ + { 0x0000, 0x0000, 0x0000 }, /* R3499 */ + { 0x0000, 0x0000, 0x0000 }, /* R3500 */ + { 0x0000, 0x0000, 0x0000 }, /* R3501 */ + { 0x0000, 0x0000, 0x0000 }, /* R3502 */ + { 0x0000, 0x0000, 0x0000 }, /* R3503 */ + { 0x0000, 0x0000, 0x0000 }, /* R3504 */ + { 0x0000, 0x0000, 0x0000 }, /* R3505 */ + { 0x0000, 0x0000, 0x0000 }, /* R3506 */ + { 0x0000, 0x0000, 0x0000 }, /* R3507 */ + { 0x0000, 0x0000, 0x0000 }, /* R3508 */ + { 0x0000, 0x0000, 0x0000 }, /* R3509 */ + { 0x0000, 0x0000, 0x0000 }, /* R3510 */ + { 0x0000, 0x0000, 0x0000 }, /* R3511 */ + { 0x0000, 0x0000, 0x0000 }, /* R3512 */ + { 0x0000, 0x0000, 0x0000 }, /* R3513 */ + { 0x0000, 0x0000, 0x0000 }, /* R3514 */ + { 0x0000, 0x0000, 0x0000 }, /* R3515 */ + { 0x0000, 0x0000, 0x0000 }, /* R3516 */ + { 0x0000, 0x0000, 0x0000 }, /* R3517 */ + { 0x0000, 0x0000, 0x0000 }, /* R3518 */ + { 0x0000, 0x0000, 0x0000 }, /* R3519 */ + { 0x0000, 0x0000, 0x0000 }, /* R3520 */ + { 0x0000, 0x0000, 0x0000 }, /* R3521 */ + { 0x0000, 0x0000, 0x0000 }, /* R3522 */ + { 0x0000, 0x0000, 0x0000 }, /* R3523 */ + { 0x0000, 0x0000, 0x0000 }, /* R3524 */ + { 0x0000, 0x0000, 0x0000 }, /* R3525 */ + { 0x0000, 0x0000, 0x0000 }, /* R3526 */ + { 0x0000, 0x0000, 0x0000 }, /* R3527 */ + { 0x0000, 0x0000, 0x0000 }, /* R3528 */ + { 0x0000, 0x0000, 0x0000 }, /* R3529 */ + { 0x0000, 0x0000, 0x0000 }, /* R3530 */ + { 0x0000, 0x0000, 0x0000 }, /* R3531 */ + { 0x0000, 0x0000, 0x0000 }, /* R3532 */ + { 0x0000, 0x0000, 0x0000 }, /* R3533 */ + { 0x0000, 0x0000, 0x0000 }, /* R3534 */ + { 0x0000, 0x0000, 0x0000 }, /* R3535 */ + { 0x0000, 0x0000, 0x0000 }, /* R3536 */ + { 0x0000, 0x0000, 0x0000 }, /* R3537 */ + { 0x0000, 0x0000, 0x0000 }, /* R3538 */ + { 0x0000, 0x0000, 0x0000 }, /* R3539 */ + { 0x0000, 0x0000, 0x0000 }, /* R3540 */ + { 0x0000, 0x0000, 0x0000 }, /* R3541 */ + { 0x0000, 0x0000, 0x0000 }, /* R3542 */ + { 0x0000, 0x0000, 0x0000 }, /* R3543 */ + { 0x0000, 0x0000, 0x0000 }, /* R3544 */ + { 0x0000, 0x0000, 0x0000 }, /* R3545 */ + { 0x0000, 0x0000, 0x0000 }, /* R3546 */ + { 0x0000, 0x0000, 0x0000 }, /* R3547 */ + { 0x0000, 0x0000, 0x0000 }, /* R3548 */ + { 0x0000, 0x0000, 0x0000 }, /* R3549 */ + { 0x0000, 0x0000, 0x0000 }, /* R3550 */ + { 0x0000, 0x0000, 0x0000 }, /* R3551 */ + { 0x0000, 0x0000, 0x0000 }, /* R3552 */ + { 0x0000, 0x0000, 0x0000 }, /* R3553 */ + { 0x0000, 0x0000, 0x0000 }, /* R3554 */ + { 0x0000, 0x0000, 0x0000 }, /* R3555 */ + { 0x0000, 0x0000, 0x0000 }, /* R3556 */ + { 0x0000, 0x0000, 0x0000 }, /* R3557 */ + { 0x0000, 0x0000, 0x0000 }, /* R3558 */ + { 0x0000, 0x0000, 0x0000 }, /* R3559 */ + { 0x0000, 0x0000, 0x0000 }, /* R3560 */ + { 0x0000, 0x0000, 0x0000 }, /* R3561 */ + { 0x0000, 0x0000, 0x0000 }, /* R3562 */ + { 0x0000, 0x0000, 0x0000 }, /* R3563 */ + { 0x0000, 0x0000, 0x0000 }, /* R3564 */ + { 0x0000, 0x0000, 0x0000 }, /* R3565 */ + { 0x0000, 0x0000, 0x0000 }, /* R3566 */ + { 0x0000, 0x0000, 0x0000 }, /* R3567 */ + { 0x0000, 0x0000, 0x0000 }, /* R3568 */ + { 0x0000, 0x0000, 0x0000 }, /* R3569 */ + { 0x0000, 0x0000, 0x0000 }, /* R3570 */ + { 0x0000, 0x0000, 0x0000 }, /* R3571 */ + { 0x0000, 0x0000, 0x0000 }, /* R3572 */ + { 0x0000, 0x0000, 0x0000 }, /* R3573 */ + { 0x0000, 0x0000, 0x0000 }, /* R3574 */ + { 0x0000, 0x0000, 0x0000 }, /* R3575 */ + { 0x0000, 0x0000, 0x0000 }, /* R3576 */ + { 0x0000, 0x0000, 0x0000 }, /* R3577 */ + { 0x0000, 0x0000, 0x0000 }, /* R3578 */ + { 0x0000, 0x0000, 0x0000 }, /* R3579 */ + { 0x0000, 0x0000, 0x0000 }, /* R3580 */ + { 0x0000, 0x0000, 0x0000 }, /* R3581 */ + { 0x0000, 0x0000, 0x0000 }, /* R3582 */ + { 0x0000, 0x0000, 0x0000 }, /* R3583 */ + { 0x0000, 0x0000, 0x0000 }, /* R3584 */ + { 0x0000, 0x0000, 0x0000 }, /* R3585 */ + { 0x0000, 0x0000, 0x0000 }, /* R3586 */ + { 0x0000, 0x0000, 0x0000 }, /* R3587 */ + { 0x0000, 0x0000, 0x0000 }, /* R3588 */ + { 0x0000, 0x0000, 0x0000 }, /* R3589 */ + { 0x0000, 0x0000, 0x0000 }, /* R3590 */ + { 0x0000, 0x0000, 0x0000 }, /* R3591 */ + { 0x0000, 0x0000, 0x0000 }, /* R3592 */ + { 0x0000, 0x0000, 0x0000 }, /* R3593 */ + { 0x0000, 0x0000, 0x0000 }, /* R3594 */ + { 0x0000, 0x0000, 0x0000 }, /* R3595 */ + { 0x0000, 0x0000, 0x0000 }, /* R3596 */ + { 0x0000, 0x0000, 0x0000 }, /* R3597 */ + { 0x0000, 0x0000, 0x0000 }, /* R3598 */ + { 0x0000, 0x0000, 0x0000 }, /* R3599 */ + { 0x0000, 0x0000, 0x0000 }, /* R3600 */ + { 0x0000, 0x0000, 0x0000 }, /* R3601 */ + { 0x0000, 0x0000, 0x0000 }, /* R3602 */ + { 0x0000, 0x0000, 0x0000 }, /* R3603 */ + { 0x0000, 0x0000, 0x0000 }, /* R3604 */ + { 0x0000, 0x0000, 0x0000 }, /* R3605 */ + { 0x0000, 0x0000, 0x0000 }, /* R3606 */ + { 0x0000, 0x0000, 0x0000 }, /* R3607 */ + { 0x0000, 0x0000, 0x0000 }, /* R3608 */ + { 0x0000, 0x0000, 0x0000 }, /* R3609 */ + { 0x0000, 0x0000, 0x0000 }, /* R3610 */ + { 0x0000, 0x0000, 0x0000 }, /* R3611 */ + { 0x0000, 0x0000, 0x0000 }, /* R3612 */ + { 0x0000, 0x0000, 0x0000 }, /* R3613 */ + { 0x0000, 0x0000, 0x0000 }, /* R3614 */ + { 0x0000, 0x0000, 0x0000 }, /* R3615 */ + { 0x0000, 0x0000, 0x0000 }, /* R3616 */ + { 0x0000, 0x0000, 0x0000 }, /* R3617 */ + { 0x0000, 0x0000, 0x0000 }, /* R3618 */ + { 0x0000, 0x0000, 0x0000 }, /* R3619 */ + { 0x0000, 0x0000, 0x0000 }, /* R3620 */ + { 0x0000, 0x0000, 0x0000 }, /* R3621 */ + { 0x0000, 0x0000, 0x0000 }, /* R3622 */ + { 0x0000, 0x0000, 0x0000 }, /* R3623 */ + { 0x0000, 0x0000, 0x0000 }, /* R3624 */ + { 0x0000, 0x0000, 0x0000 }, /* R3625 */ + { 0x0000, 0x0000, 0x0000 }, /* R3626 */ + { 0x0000, 0x0000, 0x0000 }, /* R3627 */ + { 0x0000, 0x0000, 0x0000 }, /* R3628 */ + { 0x0000, 0x0000, 0x0000 }, /* R3629 */ + { 0x0000, 0x0000, 0x0000 }, /* R3630 */ + { 0x0000, 0x0000, 0x0000 }, /* R3631 */ + { 0x0000, 0x0000, 0x0000 }, /* R3632 */ + { 0x0000, 0x0000, 0x0000 }, /* R3633 */ + { 0x0000, 0x0000, 0x0000 }, /* R3634 */ + { 0x0000, 0x0000, 0x0000 }, /* R3635 */ + { 0x0000, 0x0000, 0x0000 }, /* R3636 */ + { 0x0000, 0x0000, 0x0000 }, /* R3637 */ + { 0x0000, 0x0000, 0x0000 }, /* R3638 */ + { 0x0000, 0x0000, 0x0000 }, /* R3639 */ + { 0x0000, 0x0000, 0x0000 }, /* R3640 */ + { 0x0000, 0x0000, 0x0000 }, /* R3641 */ + { 0x0000, 0x0000, 0x0000 }, /* R3642 */ + { 0x0000, 0x0000, 0x0000 }, /* R3643 */ + { 0x0000, 0x0000, 0x0000 }, /* R3644 */ + { 0x0000, 0x0000, 0x0000 }, /* R3645 */ + { 0x0000, 0x0000, 0x0000 }, /* R3646 */ + { 0x0000, 0x0000, 0x0000 }, /* R3647 */ + { 0x0000, 0x0000, 0x0000 }, /* R3648 */ + { 0x0000, 0x0000, 0x0000 }, /* R3649 */ + { 0x0000, 0x0000, 0x0000 }, /* R3650 */ + { 0x0000, 0x0000, 0x0000 }, /* R3651 */ + { 0x0000, 0x0000, 0x0000 }, /* R3652 */ + { 0x0000, 0x0000, 0x0000 }, /* R3653 */ + { 0x0000, 0x0000, 0x0000 }, /* R3654 */ + { 0x0000, 0x0000, 0x0000 }, /* R3655 */ + { 0x0000, 0x0000, 0x0000 }, /* R3656 */ + { 0x0000, 0x0000, 0x0000 }, /* R3657 */ + { 0x0000, 0x0000, 0x0000 }, /* R3658 */ + { 0x0000, 0x0000, 0x0000 }, /* R3659 */ + { 0x0000, 0x0000, 0x0000 }, /* R3660 */ + { 0x0000, 0x0000, 0x0000 }, /* R3661 */ + { 0x0000, 0x0000, 0x0000 }, /* R3662 */ + { 0x0000, 0x0000, 0x0000 }, /* R3663 */ + { 0x0000, 0x0000, 0x0000 }, /* R3664 */ + { 0x0000, 0x0000, 0x0000 }, /* R3665 */ + { 0x0000, 0x0000, 0x0000 }, /* R3666 */ + { 0x0000, 0x0000, 0x0000 }, /* R3667 */ + { 0x0000, 0x0000, 0x0000 }, /* R3668 */ + { 0x0000, 0x0000, 0x0000 }, /* R3669 */ + { 0x0000, 0x0000, 0x0000 }, /* R3670 */ + { 0x0000, 0x0000, 0x0000 }, /* R3671 */ + { 0x0000, 0x0000, 0x0000 }, /* R3672 */ + { 0x0000, 0x0000, 0x0000 }, /* R3673 */ + { 0x0000, 0x0000, 0x0000 }, /* R3674 */ + { 0x0000, 0x0000, 0x0000 }, /* R3675 */ + { 0x0000, 0x0000, 0x0000 }, /* R3676 */ + { 0x0000, 0x0000, 0x0000 }, /* R3677 */ + { 0x0000, 0x0000, 0x0000 }, /* R3678 */ + { 0x0000, 0x0000, 0x0000 }, /* R3679 */ + { 0x0000, 0x0000, 0x0000 }, /* R3680 */ + { 0x0000, 0x0000, 0x0000 }, /* R3681 */ + { 0x0000, 0x0000, 0x0000 }, /* R3682 */ + { 0x0000, 0x0000, 0x0000 }, /* R3683 */ + { 0x0000, 0x0000, 0x0000 }, /* R3684 */ + { 0x0000, 0x0000, 0x0000 }, /* R3685 */ + { 0x0000, 0x0000, 0x0000 }, /* R3686 */ + { 0x0000, 0x0000, 0x0000 }, /* R3687 */ + { 0x0000, 0x0000, 0x0000 }, /* R3688 */ + { 0x0000, 0x0000, 0x0000 }, /* R3689 */ + { 0x0000, 0x0000, 0x0000 }, /* R3690 */ + { 0x0000, 0x0000, 0x0000 }, /* R3691 */ + { 0x0000, 0x0000, 0x0000 }, /* R3692 */ + { 0x0000, 0x0000, 0x0000 }, /* R3693 */ + { 0x0000, 0x0000, 0x0000 }, /* R3694 */ + { 0x0000, 0x0000, 0x0000 }, /* R3695 */ + { 0x0000, 0x0000, 0x0000 }, /* R3696 */ + { 0x0000, 0x0000, 0x0000 }, /* R3697 */ + { 0x0000, 0x0000, 0x0000 }, /* R3698 */ + { 0x0000, 0x0000, 0x0000 }, /* R3699 */ + { 0x0000, 0x0000, 0x0000 }, /* R3700 */ + { 0x0000, 0x0000, 0x0000 }, /* R3701 */ + { 0x0000, 0x0000, 0x0000 }, /* R3702 */ + { 0x0000, 0x0000, 0x0000 }, /* R3703 */ + { 0x0000, 0x0000, 0x0000 }, /* R3704 */ + { 0x0000, 0x0000, 0x0000 }, /* R3705 */ + { 0x0000, 0x0000, 0x0000 }, /* R3706 */ + { 0x0000, 0x0000, 0x0000 }, /* R3707 */ + { 0x0000, 0x0000, 0x0000 }, /* R3708 */ + { 0x0000, 0x0000, 0x0000 }, /* R3709 */ + { 0x0000, 0x0000, 0x0000 }, /* R3710 */ + { 0x0000, 0x0000, 0x0000 }, /* R3711 */ + { 0x0000, 0x0000, 0x0000 }, /* R3712 */ + { 0x0000, 0x0000, 0x0000 }, /* R3713 */ + { 0x0000, 0x0000, 0x0000 }, /* R3714 */ + { 0x0000, 0x0000, 0x0000 }, /* R3715 */ + { 0x0000, 0x0000, 0x0000 }, /* R3716 */ + { 0x0000, 0x0000, 0x0000 }, /* R3717 */ + { 0x0000, 0x0000, 0x0000 }, /* R3718 */ + { 0x0000, 0x0000, 0x0000 }, /* R3719 */ + { 0x0000, 0x0000, 0x0000 }, /* R3720 */ + { 0x0000, 0x0000, 0x0000 }, /* R3721 */ + { 0x0000, 0x0000, 0x0000 }, /* R3722 */ + { 0x0000, 0x0000, 0x0000 }, /* R3723 */ + { 0x0000, 0x0000, 0x0000 }, /* R3724 */ + { 0x0000, 0x0000, 0x0000 }, /* R3725 */ + { 0x0000, 0x0000, 0x0000 }, /* R3726 */ + { 0x0000, 0x0000, 0x0000 }, /* R3727 */ + { 0x0000, 0x0000, 0x0000 }, /* R3728 */ + { 0x0000, 0x0000, 0x0000 }, /* R3729 */ + { 0x0000, 0x0000, 0x0000 }, /* R3730 */ + { 0x0000, 0x0000, 0x0000 }, /* R3731 */ + { 0x0000, 0x0000, 0x0000 }, /* R3732 */ + { 0x0000, 0x0000, 0x0000 }, /* R3733 */ + { 0x0000, 0x0000, 0x0000 }, /* R3734 */ + { 0x0000, 0x0000, 0x0000 }, /* R3735 */ + { 0x0000, 0x0000, 0x0000 }, /* R3736 */ + { 0x0000, 0x0000, 0x0000 }, /* R3737 */ + { 0x0000, 0x0000, 0x0000 }, /* R3738 */ + { 0x0000, 0x0000, 0x0000 }, /* R3739 */ + { 0x0000, 0x0000, 0x0000 }, /* R3740 */ + { 0x0000, 0x0000, 0x0000 }, /* R3741 */ + { 0x0000, 0x0000, 0x0000 }, /* R3742 */ + { 0x0000, 0x0000, 0x0000 }, /* R3743 */ + { 0x0000, 0x0000, 0x0000 }, /* R3744 */ + { 0x0000, 0x0000, 0x0000 }, /* R3745 */ + { 0x0000, 0x0000, 0x0000 }, /* R3746 */ + { 0x0000, 0x0000, 0x0000 }, /* R3747 */ + { 0x0000, 0x0000, 0x0000 }, /* R3748 */ + { 0x0000, 0x0000, 0x0000 }, /* R3749 */ + { 0x0000, 0x0000, 0x0000 }, /* R3750 */ + { 0x0000, 0x0000, 0x0000 }, /* R3751 */ + { 0x0000, 0x0000, 0x0000 }, /* R3752 */ + { 0x0000, 0x0000, 0x0000 }, /* R3753 */ + { 0x0000, 0x0000, 0x0000 }, /* R3754 */ + { 0x0000, 0x0000, 0x0000 }, /* R3755 */ + { 0x0000, 0x0000, 0x0000 }, /* R3756 */ + { 0x0000, 0x0000, 0x0000 }, /* R3757 */ + { 0x0000, 0x0000, 0x0000 }, /* R3758 */ + { 0x0000, 0x0000, 0x0000 }, /* R3759 */ + { 0x0000, 0x0000, 0x0000 }, /* R3760 */ + { 0x0000, 0x0000, 0x0000 }, /* R3761 */ + { 0x0000, 0x0000, 0x0000 }, /* R3762 */ + { 0x0000, 0x0000, 0x0000 }, /* R3763 */ + { 0x0000, 0x0000, 0x0000 }, /* R3764 */ + { 0x0000, 0x0000, 0x0000 }, /* R3765 */ + { 0x0000, 0x0000, 0x0000 }, /* R3766 */ + { 0x0000, 0x0000, 0x0000 }, /* R3767 */ + { 0x0000, 0x0000, 0x0000 }, /* R3768 */ + { 0x0000, 0x0000, 0x0000 }, /* R3769 */ + { 0x0000, 0x0000, 0x0000 }, /* R3770 */ + { 0x0000, 0x0000, 0x0000 }, /* R3771 */ + { 0x0000, 0x0000, 0x0000 }, /* R3772 */ + { 0x0000, 0x0000, 0x0000 }, /* R3773 */ + { 0x0000, 0x0000, 0x0000 }, /* R3774 */ + { 0x0000, 0x0000, 0x0000 }, /* R3775 */ + { 0x0000, 0x0000, 0x0000 }, /* R3776 */ + { 0x0000, 0x0000, 0x0000 }, /* R3777 */ + { 0x0000, 0x0000, 0x0000 }, /* R3778 */ + { 0x0000, 0x0000, 0x0000 }, /* R3779 */ + { 0x0000, 0x0000, 0x0000 }, /* R3780 */ + { 0x0000, 0x0000, 0x0000 }, /* R3781 */ + { 0x0000, 0x0000, 0x0000 }, /* R3782 */ + { 0x0000, 0x0000, 0x0000 }, /* R3783 */ + { 0x0000, 0x0000, 0x0000 }, /* R3784 */ + { 0x0000, 0x0000, 0x0000 }, /* R3785 */ + { 0x0000, 0x0000, 0x0000 }, /* R3786 */ + { 0x0000, 0x0000, 0x0000 }, /* R3787 */ + { 0x0000, 0x0000, 0x0000 }, /* R3788 */ + { 0x0000, 0x0000, 0x0000 }, /* R3789 */ + { 0x0000, 0x0000, 0x0000 }, /* R3790 */ + { 0x0000, 0x0000, 0x0000 }, /* R3791 */ + { 0x0000, 0x0000, 0x0000 }, /* R3792 */ + { 0x0000, 0x0000, 0x0000 }, /* R3793 */ + { 0x0000, 0x0000, 0x0000 }, /* R3794 */ + { 0x0000, 0x0000, 0x0000 }, /* R3795 */ + { 0x0000, 0x0000, 0x0000 }, /* R3796 */ + { 0x0000, 0x0000, 0x0000 }, /* R3797 */ + { 0x0000, 0x0000, 0x0000 }, /* R3798 */ + { 0x0000, 0x0000, 0x0000 }, /* R3799 */ + { 0x0000, 0x0000, 0x0000 }, /* R3800 */ + { 0x0000, 0x0000, 0x0000 }, /* R3801 */ + { 0x0000, 0x0000, 0x0000 }, /* R3802 */ + { 0x0000, 0x0000, 0x0000 }, /* R3803 */ + { 0x0000, 0x0000, 0x0000 }, /* R3804 */ + { 0x0000, 0x0000, 0x0000 }, /* R3805 */ + { 0x0000, 0x0000, 0x0000 }, /* R3806 */ + { 0x0000, 0x0000, 0x0000 }, /* R3807 */ + { 0x0000, 0x0000, 0x0000 }, /* R3808 */ + { 0x0000, 0x0000, 0x0000 }, /* R3809 */ + { 0x0000, 0x0000, 0x0000 }, /* R3810 */ + { 0x0000, 0x0000, 0x0000 }, /* R3811 */ + { 0x0000, 0x0000, 0x0000 }, /* R3812 */ + { 0x0000, 0x0000, 0x0000 }, /* R3813 */ + { 0x0000, 0x0000, 0x0000 }, /* R3814 */ + { 0x0000, 0x0000, 0x0000 }, /* R3815 */ + { 0x0000, 0x0000, 0x0000 }, /* R3816 */ + { 0x0000, 0x0000, 0x0000 }, /* R3817 */ + { 0x0000, 0x0000, 0x0000 }, /* R3818 */ + { 0x0000, 0x0000, 0x0000 }, /* R3819 */ + { 0x0000, 0x0000, 0x0000 }, /* R3820 */ + { 0x0000, 0x0000, 0x0000 }, /* R3821 */ + { 0x0000, 0x0000, 0x0000 }, /* R3822 */ + { 0x0000, 0x0000, 0x0000 }, /* R3823 */ + { 0x0000, 0x0000, 0x0000 }, /* R3824 */ + { 0x0000, 0x0000, 0x0000 }, /* R3825 */ + { 0x0000, 0x0000, 0x0000 }, /* R3826 */ + { 0x0000, 0x0000, 0x0000 }, /* R3827 */ + { 0x0000, 0x0000, 0x0000 }, /* R3828 */ + { 0x0000, 0x0000, 0x0000 }, /* R3829 */ + { 0x0000, 0x0000, 0x0000 }, /* R3830 */ + { 0x0000, 0x0000, 0x0000 }, /* R3831 */ + { 0x0000, 0x0000, 0x0000 }, /* R3832 */ + { 0x0000, 0x0000, 0x0000 }, /* R3833 */ + { 0x0000, 0x0000, 0x0000 }, /* R3834 */ + { 0x0000, 0x0000, 0x0000 }, /* R3835 */ + { 0x0000, 0x0000, 0x0000 }, /* R3836 */ + { 0x0000, 0x0000, 0x0000 }, /* R3837 */ + { 0x0000, 0x0000, 0x0000 }, /* R3838 */ + { 0x0000, 0x0000, 0x0000 }, /* R3839 */ + { 0x0000, 0x0000, 0x0000 }, /* R3840 */ + { 0x0000, 0x0000, 0x0000 }, /* R3841 */ + { 0x0000, 0x0000, 0x0000 }, /* R3842 */ + { 0x0000, 0x0000, 0x0000 }, /* R3843 */ + { 0x0000, 0x0000, 0x0000 }, /* R3844 */ + { 0x0000, 0x0000, 0x0000 }, /* R3845 */ + { 0x0000, 0x0000, 0x0000 }, /* R3846 */ + { 0x0000, 0x0000, 0x0000 }, /* R3847 */ + { 0x0000, 0x0000, 0x0000 }, /* R3848 */ + { 0x0000, 0x0000, 0x0000 }, /* R3849 */ + { 0x0000, 0x0000, 0x0000 }, /* R3850 */ + { 0x0000, 0x0000, 0x0000 }, /* R3851 */ + { 0x0000, 0x0000, 0x0000 }, /* R3852 */ + { 0x0000, 0x0000, 0x0000 }, /* R3853 */ + { 0x0000, 0x0000, 0x0000 }, /* R3854 */ + { 0x0000, 0x0000, 0x0000 }, /* R3855 */ + { 0x0000, 0x0000, 0x0000 }, /* R3856 */ + { 0x0000, 0x0000, 0x0000 }, /* R3857 */ + { 0x0000, 0x0000, 0x0000 }, /* R3858 */ + { 0x0000, 0x0000, 0x0000 }, /* R3859 */ + { 0x0000, 0x0000, 0x0000 }, /* R3860 */ + { 0x0000, 0x0000, 0x0000 }, /* R3861 */ + { 0x0000, 0x0000, 0x0000 }, /* R3862 */ + { 0x0000, 0x0000, 0x0000 }, /* R3863 */ + { 0x0000, 0x0000, 0x0000 }, /* R3864 */ + { 0x0000, 0x0000, 0x0000 }, /* R3865 */ + { 0x0000, 0x0000, 0x0000 }, /* R3866 */ + { 0x0000, 0x0000, 0x0000 }, /* R3867 */ + { 0x0000, 0x0000, 0x0000 }, /* R3868 */ + { 0x0000, 0x0000, 0x0000 }, /* R3869 */ + { 0x0000, 0x0000, 0x0000 }, /* R3870 */ + { 0x0000, 0x0000, 0x0000 }, /* R3871 */ + { 0x0000, 0x0000, 0x0000 }, /* R3872 */ + { 0x0000, 0x0000, 0x0000 }, /* R3873 */ + { 0x0000, 0x0000, 0x0000 }, /* R3874 */ + { 0x0000, 0x0000, 0x0000 }, /* R3875 */ + { 0x0000, 0x0000, 0x0000 }, /* R3876 */ + { 0x0000, 0x0000, 0x0000 }, /* R3877 */ + { 0x0000, 0x0000, 0x0000 }, /* R3878 */ + { 0x0000, 0x0000, 0x0000 }, /* R3879 */ + { 0x0000, 0x0000, 0x0000 }, /* R3880 */ + { 0x0000, 0x0000, 0x0000 }, /* R3881 */ + { 0x0000, 0x0000, 0x0000 }, /* R3882 */ + { 0x0000, 0x0000, 0x0000 }, /* R3883 */ + { 0x0000, 0x0000, 0x0000 }, /* R3884 */ + { 0x0000, 0x0000, 0x0000 }, /* R3885 */ + { 0x0000, 0x0000, 0x0000 }, /* R3886 */ + { 0x0000, 0x0000, 0x0000 }, /* R3887 */ + { 0x0000, 0x0000, 0x0000 }, /* R3888 */ + { 0x0000, 0x0000, 0x0000 }, /* R3889 */ + { 0x0000, 0x0000, 0x0000 }, /* R3890 */ + { 0x0000, 0x0000, 0x0000 }, /* R3891 */ + { 0x0000, 0x0000, 0x0000 }, /* R3892 */ + { 0x0000, 0x0000, 0x0000 }, /* R3893 */ + { 0x0000, 0x0000, 0x0000 }, /* R3894 */ + { 0x0000, 0x0000, 0x0000 }, /* R3895 */ + { 0x0000, 0x0000, 0x0000 }, /* R3896 */ + { 0x0000, 0x0000, 0x0000 }, /* R3897 */ + { 0x0000, 0x0000, 0x0000 }, /* R3898 */ + { 0x0000, 0x0000, 0x0000 }, /* R3899 */ + { 0x0000, 0x0000, 0x0000 }, /* R3900 */ + { 0x0000, 0x0000, 0x0000 }, /* R3901 */ + { 0x0000, 0x0000, 0x0000 }, /* R3902 */ + { 0x0000, 0x0000, 0x0000 }, /* R3903 */ + { 0x0000, 0x0000, 0x0000 }, /* R3904 */ + { 0x0000, 0x0000, 0x0000 }, /* R3905 */ + { 0x0000, 0x0000, 0x0000 }, /* R3906 */ + { 0x0000, 0x0000, 0x0000 }, /* R3907 */ + { 0x0000, 0x0000, 0x0000 }, /* R3908 */ + { 0x0000, 0x0000, 0x0000 }, /* R3909 */ + { 0x0000, 0x0000, 0x0000 }, /* R3910 */ + { 0x0000, 0x0000, 0x0000 }, /* R3911 */ + { 0x0000, 0x0000, 0x0000 }, /* R3912 */ + { 0x0000, 0x0000, 0x0000 }, /* R3913 */ + { 0x0000, 0x0000, 0x0000 }, /* R3914 */ + { 0x0000, 0x0000, 0x0000 }, /* R3915 */ + { 0x0000, 0x0000, 0x0000 }, /* R3916 */ + { 0x0000, 0x0000, 0x0000 }, /* R3917 */ + { 0x0000, 0x0000, 0x0000 }, /* R3918 */ + { 0x0000, 0x0000, 0x0000 }, /* R3919 */ + { 0x0000, 0x0000, 0x0000 }, /* R3920 */ + { 0x0000, 0x0000, 0x0000 }, /* R3921 */ + { 0x0000, 0x0000, 0x0000 }, /* R3922 */ + { 0x0000, 0x0000, 0x0000 }, /* R3923 */ + { 0x0000, 0x0000, 0x0000 }, /* R3924 */ + { 0x0000, 0x0000, 0x0000 }, /* R3925 */ + { 0x0000, 0x0000, 0x0000 }, /* R3926 */ + { 0x0000, 0x0000, 0x0000 }, /* R3927 */ + { 0x0000, 0x0000, 0x0000 }, /* R3928 */ + { 0x0000, 0x0000, 0x0000 }, /* R3929 */ + { 0x0000, 0x0000, 0x0000 }, /* R3930 */ + { 0x0000, 0x0000, 0x0000 }, /* R3931 */ + { 0x0000, 0x0000, 0x0000 }, /* R3932 */ + { 0x0000, 0x0000, 0x0000 }, /* R3933 */ + { 0x0000, 0x0000, 0x0000 }, /* R3934 */ + { 0x0000, 0x0000, 0x0000 }, /* R3935 */ + { 0x0000, 0x0000, 0x0000 }, /* R3936 */ + { 0x0000, 0x0000, 0x0000 }, /* R3937 */ + { 0x0000, 0x0000, 0x0000 }, /* R3938 */ + { 0x0000, 0x0000, 0x0000 }, /* R3939 */ + { 0x0000, 0x0000, 0x0000 }, /* R3940 */ + { 0x0000, 0x0000, 0x0000 }, /* R3941 */ + { 0x0000, 0x0000, 0x0000 }, /* R3942 */ + { 0x0000, 0x0000, 0x0000 }, /* R3943 */ + { 0x0000, 0x0000, 0x0000 }, /* R3944 */ + { 0x0000, 0x0000, 0x0000 }, /* R3945 */ + { 0x0000, 0x0000, 0x0000 }, /* R3946 */ + { 0x0000, 0x0000, 0x0000 }, /* R3947 */ + { 0x0000, 0x0000, 0x0000 }, /* R3948 */ + { 0x0000, 0x0000, 0x0000 }, /* R3949 */ + { 0x0000, 0x0000, 0x0000 }, /* R3950 */ + { 0x0000, 0x0000, 0x0000 }, /* R3951 */ + { 0x0000, 0x0000, 0x0000 }, /* R3952 */ + { 0x0000, 0x0000, 0x0000 }, /* R3953 */ + { 0x0000, 0x0000, 0x0000 }, /* R3954 */ + { 0x0000, 0x0000, 0x0000 }, /* R3955 */ + { 0x0000, 0x0000, 0x0000 }, /* R3956 */ + { 0x0000, 0x0000, 0x0000 }, /* R3957 */ + { 0x0000, 0x0000, 0x0000 }, /* R3958 */ + { 0x0000, 0x0000, 0x0000 }, /* R3959 */ + { 0x0000, 0x0000, 0x0000 }, /* R3960 */ + { 0x0000, 0x0000, 0x0000 }, /* R3961 */ + { 0x0000, 0x0000, 0x0000 }, /* R3962 */ + { 0x0000, 0x0000, 0x0000 }, /* R3963 */ + { 0x0000, 0x0000, 0x0000 }, /* R3964 */ + { 0x0000, 0x0000, 0x0000 }, /* R3965 */ + { 0x0000, 0x0000, 0x0000 }, /* R3966 */ + { 0x0000, 0x0000, 0x0000 }, /* R3967 */ + { 0x0000, 0x0000, 0x0000 }, /* R3968 */ + { 0x0000, 0x0000, 0x0000 }, /* R3969 */ + { 0x0000, 0x0000, 0x0000 }, /* R3970 */ + { 0x0000, 0x0000, 0x0000 }, /* R3971 */ + { 0x0000, 0x0000, 0x0000 }, /* R3972 */ + { 0x0000, 0x0000, 0x0000 }, /* R3973 */ + { 0x0000, 0x0000, 0x0000 }, /* R3974 */ + { 0x0000, 0x0000, 0x0000 }, /* R3975 */ + { 0x0000, 0x0000, 0x0000 }, /* R3976 */ + { 0x0000, 0x0000, 0x0000 }, /* R3977 */ + { 0x0000, 0x0000, 0x0000 }, /* R3978 */ + { 0x0000, 0x0000, 0x0000 }, /* R3979 */ + { 0x0000, 0x0000, 0x0000 }, /* R3980 */ + { 0x0000, 0x0000, 0x0000 }, /* R3981 */ + { 0x0000, 0x0000, 0x0000 }, /* R3982 */ + { 0x0000, 0x0000, 0x0000 }, /* R3983 */ + { 0x0000, 0x0000, 0x0000 }, /* R3984 */ + { 0x0000, 0x0000, 0x0000 }, /* R3985 */ + { 0x0000, 0x0000, 0x0000 }, /* R3986 */ + { 0x0000, 0x0000, 0x0000 }, /* R3987 */ + { 0x0000, 0x0000, 0x0000 }, /* R3988 */ + { 0x0000, 0x0000, 0x0000 }, /* R3989 */ + { 0x0000, 0x0000, 0x0000 }, /* R3990 */ + { 0x0000, 0x0000, 0x0000 }, /* R3991 */ + { 0x0000, 0x0000, 0x0000 }, /* R3992 */ + { 0x0000, 0x0000, 0x0000 }, /* R3993 */ + { 0x0000, 0x0000, 0x0000 }, /* R3994 */ + { 0x0000, 0x0000, 0x0000 }, /* R3995 */ + { 0x0000, 0x0000, 0x0000 }, /* R3996 */ + { 0x0000, 0x0000, 0x0000 }, /* R3997 */ + { 0x0000, 0x0000, 0x0000 }, /* R3998 */ + { 0x0000, 0x0000, 0x0000 }, /* R3999 */ + { 0x0000, 0x0000, 0x0000 }, /* R4000 */ + { 0x0000, 0x0000, 0x0000 }, /* R4001 */ + { 0x0000, 0x0000, 0x0000 }, /* R4002 */ + { 0x0000, 0x0000, 0x0000 }, /* R4003 */ + { 0x0000, 0x0000, 0x0000 }, /* R4004 */ + { 0x0000, 0x0000, 0x0000 }, /* R4005 */ + { 0x0000, 0x0000, 0x0000 }, /* R4006 */ + { 0x0000, 0x0000, 0x0000 }, /* R4007 */ + { 0x0000, 0x0000, 0x0000 }, /* R4008 */ + { 0x0000, 0x0000, 0x0000 }, /* R4009 */ + { 0x0000, 0x0000, 0x0000 }, /* R4010 */ + { 0x0000, 0x0000, 0x0000 }, /* R4011 */ + { 0x0000, 0x0000, 0x0000 }, /* R4012 */ + { 0x0000, 0x0000, 0x0000 }, /* R4013 */ + { 0x0000, 0x0000, 0x0000 }, /* R4014 */ + { 0x0000, 0x0000, 0x0000 }, /* R4015 */ + { 0x0000, 0x0000, 0x0000 }, /* R4016 */ + { 0x0000, 0x0000, 0x0000 }, /* R4017 */ + { 0x0000, 0x0000, 0x0000 }, /* R4018 */ + { 0x0000, 0x0000, 0x0000 }, /* R4019 */ + { 0x0000, 0x0000, 0x0000 }, /* R4020 */ + { 0x0000, 0x0000, 0x0000 }, /* R4021 */ + { 0x0000, 0x0000, 0x0000 }, /* R4022 */ + { 0x0000, 0x0000, 0x0000 }, /* R4023 */ + { 0x0000, 0x0000, 0x0000 }, /* R4024 */ + { 0x0000, 0x0000, 0x0000 }, /* R4025 */ + { 0x0000, 0x0000, 0x0000 }, /* R4026 */ + { 0x0000, 0x0000, 0x0000 }, /* R4027 */ + { 0x0000, 0x0000, 0x0000 }, /* R4028 */ + { 0x0000, 0x0000, 0x0000 }, /* R4029 */ + { 0x0000, 0x0000, 0x0000 }, /* R4030 */ + { 0x0000, 0x0000, 0x0000 }, /* R4031 */ + { 0x0000, 0x0000, 0x0000 }, /* R4032 */ + { 0x0000, 0x0000, 0x0000 }, /* R4033 */ + { 0x0000, 0x0000, 0x0000 }, /* R4034 */ + { 0x0000, 0x0000, 0x0000 }, /* R4035 */ + { 0x0000, 0x0000, 0x0000 }, /* R4036 */ + { 0x0000, 0x0000, 0x0000 }, /* R4037 */ + { 0x0000, 0x0000, 0x0000 }, /* R4038 */ + { 0x0000, 0x0000, 0x0000 }, /* R4039 */ + { 0x0000, 0x0000, 0x0000 }, /* R4040 */ + { 0x0000, 0x0000, 0x0000 }, /* R4041 */ + { 0x0000, 0x0000, 0x0000 }, /* R4042 */ + { 0x0000, 0x0000, 0x0000 }, /* R4043 */ + { 0x0000, 0x0000, 0x0000 }, /* R4044 */ + { 0x0000, 0x0000, 0x0000 }, /* R4045 */ + { 0x0000, 0x0000, 0x0000 }, /* R4046 */ + { 0x0000, 0x0000, 0x0000 }, /* R4047 */ + { 0x0000, 0x0000, 0x0000 }, /* R4048 */ + { 0x0000, 0x0000, 0x0000 }, /* R4049 */ + { 0x0000, 0x0000, 0x0000 }, /* R4050 */ + { 0x0000, 0x0000, 0x0000 }, /* R4051 */ + { 0x0000, 0x0000, 0x0000 }, /* R4052 */ + { 0x0000, 0x0000, 0x0000 }, /* R4053 */ + { 0x0000, 0x0000, 0x0000 }, /* R4054 */ + { 0x0000, 0x0000, 0x0000 }, /* R4055 */ + { 0x0000, 0x0000, 0x0000 }, /* R4056 */ + { 0x0000, 0x0000, 0x0000 }, /* R4057 */ + { 0x0000, 0x0000, 0x0000 }, /* R4058 */ + { 0x0000, 0x0000, 0x0000 }, /* R4059 */ + { 0x0000, 0x0000, 0x0000 }, /* R4060 */ + { 0x0000, 0x0000, 0x0000 }, /* R4061 */ + { 0x0000, 0x0000, 0x0000 }, /* R4062 */ + { 0x0000, 0x0000, 0x0000 }, /* R4063 */ + { 0x0000, 0x0000, 0x0000 }, /* R4064 */ + { 0x0000, 0x0000, 0x0000 }, /* R4065 */ + { 0x0000, 0x0000, 0x0000 }, /* R4066 */ + { 0x0000, 0x0000, 0x0000 }, /* R4067 */ + { 0x0000, 0x0000, 0x0000 }, /* R4068 */ + { 0x0000, 0x0000, 0x0000 }, /* R4069 */ + { 0x0000, 0x0000, 0x0000 }, /* R4070 */ + { 0x0000, 0x0000, 0x0000 }, /* R4071 */ + { 0x0000, 0x0000, 0x0000 }, /* R4072 */ + { 0x0000, 0x0000, 0x0000 }, /* R4073 */ + { 0x0000, 0x0000, 0x0000 }, /* R4074 */ + { 0x0000, 0x0000, 0x0000 }, /* R4075 */ + { 0x0000, 0x0000, 0x0000 }, /* R4076 */ + { 0x0000, 0x0000, 0x0000 }, /* R4077 */ + { 0x0000, 0x0000, 0x0000 }, /* R4078 */ + { 0x0000, 0x0000, 0x0000 }, /* R4079 */ + { 0x0000, 0x0000, 0x0000 }, /* R4080 */ + { 0x0000, 0x0000, 0x0000 }, /* R4081 */ + { 0x0000, 0x0000, 0x0000 }, /* R4082 */ + { 0x0000, 0x0000, 0x0000 }, /* R4083 */ + { 0x0000, 0x0000, 0x0000 }, /* R4084 */ + { 0x0000, 0x0000, 0x0000 }, /* R4085 */ + { 0x0000, 0x0000, 0x0000 }, /* R4086 */ + { 0x0000, 0x0000, 0x0000 }, /* R4087 */ + { 0x0000, 0x0000, 0x0000 }, /* R4088 */ + { 0x0000, 0x0000, 0x0000 }, /* R4089 */ + { 0x0000, 0x0000, 0x0000 }, /* R4090 */ + { 0x0000, 0x0000, 0x0000 }, /* R4091 */ + { 0x0000, 0x0000, 0x0000 }, /* R4092 */ + { 0x0000, 0x0000, 0x0000 }, /* R4093 */ + { 0x0000, 0x0000, 0x0000 }, /* R4094 */ + { 0x0000, 0x0000, 0x0000 }, /* R4095 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */ + { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */ + { 0x010F, 0x010F, 0x0000 }, /* R4099 - Write Sequencer 3 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4100 - Write Sequencer 4 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4101 - Write Sequencer 5 */ + { 0x070F, 0x070F, 0x0000 }, /* R4102 - Write Sequencer 6 */ + { 0x010F, 0x010F, 0x0000 }, /* R4103 - Write Sequencer 7 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4104 - Write Sequencer 8 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4105 - Write Sequencer 9 */ + { 0x070F, 0x070F, 0x0000 }, /* R4106 - Write Sequencer 10 */ + { 0x010F, 0x010F, 0x0000 }, /* R4107 - Write Sequencer 11 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4108 - Write Sequencer 12 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4109 - Write Sequencer 13 */ + { 0x070F, 0x070F, 0x0000 }, /* R4110 - Write Sequencer 14 */ + { 0x010F, 0x010F, 0x0000 }, /* R4111 - Write Sequencer 15 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4112 - Write Sequencer 16 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4113 - Write Sequencer 17 */ + { 0x070F, 0x070F, 0x0000 }, /* R4114 - Write Sequencer 18 */ + { 0x010F, 0x010F, 0x0000 }, /* R4115 - Write Sequencer 19 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4116 - Write Sequencer 20 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4117 - Write Sequencer 21 */ + { 0x070F, 0x070F, 0x0000 }, /* R4118 - Write Sequencer 22 */ + { 0x010F, 0x010F, 0x0000 }, /* R4119 - Write Sequencer 23 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4120 - Write Sequencer 24 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4121 - Write Sequencer 25 */ + { 0x070F, 0x070F, 0x0000 }, /* R4122 - Write Sequencer 26 */ + { 0x010F, 0x010F, 0x0000 }, /* R4123 - Write Sequencer 27 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4124 - Write Sequencer 28 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4125 - Write Sequencer 29 */ + { 0x070F, 0x070F, 0x0000 }, /* R4126 - Write Sequencer 30 */ + { 0x010F, 0x010F, 0x0000 }, /* R4127 - Write Sequencer 31 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4128 - Write Sequencer 32 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4129 - Write Sequencer 33 */ + { 0x070F, 0x070F, 0x0000 }, /* R4130 - Write Sequencer 34 */ + { 0x010F, 0x010F, 0x0000 }, /* R4131 - Write Sequencer 35 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4132 - Write Sequencer 36 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4133 - Write Sequencer 37 */ + { 0x070F, 0x070F, 0x0000 }, /* R4134 - Write Sequencer 38 */ + { 0x010F, 0x010F, 0x0000 }, /* R4135 - Write Sequencer 39 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4136 - Write Sequencer 40 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4137 - Write Sequencer 41 */ + { 0x070F, 0x070F, 0x0000 }, /* R4138 - Write Sequencer 42 */ + { 0x010F, 0x010F, 0x0000 }, /* R4139 - Write Sequencer 43 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4140 - Write Sequencer 44 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4141 - Write Sequencer 45 */ + { 0x070F, 0x070F, 0x0000 }, /* R4142 - Write Sequencer 46 */ + { 0x010F, 0x010F, 0x0000 }, /* R4143 - Write Sequencer 47 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4144 - Write Sequencer 48 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4145 - Write Sequencer 49 */ + { 0x070F, 0x070F, 0x0000 }, /* R4146 - Write Sequencer 50 */ + { 0x010F, 0x010F, 0x0000 }, /* R4147 - Write Sequencer 51 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4148 - Write Sequencer 52 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4149 - Write Sequencer 53 */ + { 0x070F, 0x070F, 0x0000 }, /* R4150 - Write Sequencer 54 */ + { 0x010F, 0x010F, 0x0000 }, /* R4151 - Write Sequencer 55 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4152 - Write Sequencer 56 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4153 - Write Sequencer 57 */ + { 0x070F, 0x070F, 0x0000 }, /* R4154 - Write Sequencer 58 */ + { 0x010F, 0x010F, 0x0000 }, /* R4155 - Write Sequencer 59 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4156 - Write Sequencer 60 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4157 - Write Sequencer 61 */ + { 0x070F, 0x070F, 0x0000 }, /* R4158 - Write Sequencer 62 */ + { 0x010F, 0x010F, 0x0000 }, /* R4159 - Write Sequencer 63 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4160 - Write Sequencer 64 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4161 - Write Sequencer 65 */ + { 0x070F, 0x070F, 0x0000 }, /* R4162 - Write Sequencer 66 */ + { 0x010F, 0x010F, 0x0000 }, /* R4163 - Write Sequencer 67 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4164 - Write Sequencer 68 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4165 - Write Sequencer 69 */ + { 0x070F, 0x070F, 0x0000 }, /* R4166 - Write Sequencer 70 */ + { 0x010F, 0x010F, 0x0000 }, /* R4167 - Write Sequencer 71 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4168 - Write Sequencer 72 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4169 - Write Sequencer 73 */ + { 0x070F, 0x070F, 0x0000 }, /* R4170 - Write Sequencer 74 */ + { 0x010F, 0x010F, 0x0000 }, /* R4171 - Write Sequencer 75 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4172 - Write Sequencer 76 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4173 - Write Sequencer 77 */ + { 0x070F, 0x070F, 0x0000 }, /* R4174 - Write Sequencer 78 */ + { 0x010F, 0x010F, 0x0000 }, /* R4175 - Write Sequencer 79 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4176 - Write Sequencer 80 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4177 - Write Sequencer 81 */ + { 0x070F, 0x070F, 0x0000 }, /* R4178 - Write Sequencer 82 */ + { 0x010F, 0x010F, 0x0000 }, /* R4179 - Write Sequencer 83 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4180 - Write Sequencer 84 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4181 - Write Sequencer 85 */ + { 0x070F, 0x070F, 0x0000 }, /* R4182 - Write Sequencer 86 */ + { 0x010F, 0x010F, 0x0000 }, /* R4183 - Write Sequencer 87 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4184 - Write Sequencer 88 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4185 - Write Sequencer 89 */ + { 0x070F, 0x070F, 0x0000 }, /* R4186 - Write Sequencer 90 */ + { 0x010F, 0x010F, 0x0000 }, /* R4187 - Write Sequencer 91 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4188 - Write Sequencer 92 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4189 - Write Sequencer 93 */ + { 0x070F, 0x070F, 0x0000 }, /* R4190 - Write Sequencer 94 */ + { 0x010F, 0x010F, 0x0000 }, /* R4191 - Write Sequencer 95 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4192 - Write Sequencer 96 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4193 - Write Sequencer 97 */ + { 0x070F, 0x070F, 0x0000 }, /* R4194 - Write Sequencer 98 */ + { 0x010F, 0x010F, 0x0000 }, /* R4195 - Write Sequencer 99 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4196 - Write Sequencer 100 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4197 - Write Sequencer 101 */ + { 0x070F, 0x070F, 0x0000 }, /* R4198 - Write Sequencer 102 */ + { 0x010F, 0x010F, 0x0000 }, /* R4199 - Write Sequencer 103 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4200 - Write Sequencer 104 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4201 - Write Sequencer 105 */ + { 0x070F, 0x070F, 0x0000 }, /* R4202 - Write Sequencer 106 */ + { 0x010F, 0x010F, 0x0000 }, /* R4203 - Write Sequencer 107 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4204 - Write Sequencer 108 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4205 - Write Sequencer 109 */ + { 0x070F, 0x070F, 0x0000 }, /* R4206 - Write Sequencer 110 */ + { 0x010F, 0x010F, 0x0000 }, /* R4207 - Write Sequencer 111 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4208 - Write Sequencer 112 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4209 - Write Sequencer 113 */ + { 0x070F, 0x070F, 0x0000 }, /* R4210 - Write Sequencer 114 */ + { 0x010F, 0x010F, 0x0000 }, /* R4211 - Write Sequencer 115 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4212 - Write Sequencer 116 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4213 - Write Sequencer 117 */ + { 0x070F, 0x070F, 0x0000 }, /* R4214 - Write Sequencer 118 */ + { 0x010F, 0x010F, 0x0000 }, /* R4215 - Write Sequencer 119 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4216 - Write Sequencer 120 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4217 - Write Sequencer 121 */ + { 0x070F, 0x070F, 0x0000 }, /* R4218 - Write Sequencer 122 */ + { 0x010F, 0x010F, 0x0000 }, /* R4219 - Write Sequencer 123 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4220 - Write Sequencer 124 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4221 - Write Sequencer 125 */ + { 0x070F, 0x070F, 0x0000 }, /* R4222 - Write Sequencer 126 */ + { 0x010F, 0x010F, 0x0000 }, /* R4223 - Write Sequencer 127 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4224 - Write Sequencer 128 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4225 - Write Sequencer 129 */ + { 0x070F, 0x070F, 0x0000 }, /* R4226 - Write Sequencer 130 */ + { 0x010F, 0x010F, 0x0000 }, /* R4227 - Write Sequencer 131 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4228 - Write Sequencer 132 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4229 - Write Sequencer 133 */ + { 0x070F, 0x070F, 0x0000 }, /* R4230 - Write Sequencer 134 */ + { 0x010F, 0x010F, 0x0000 }, /* R4231 - Write Sequencer 135 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4232 - Write Sequencer 136 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4233 - Write Sequencer 137 */ + { 0x070F, 0x070F, 0x0000 }, /* R4234 - Write Sequencer 138 */ + { 0x010F, 0x010F, 0x0000 }, /* R4235 - Write Sequencer 139 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4236 - Write Sequencer 140 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4237 - Write Sequencer 141 */ + { 0x070F, 0x070F, 0x0000 }, /* R4238 - Write Sequencer 142 */ + { 0x010F, 0x010F, 0x0000 }, /* R4239 - Write Sequencer 143 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4240 - Write Sequencer 144 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4241 - Write Sequencer 145 */ + { 0x070F, 0x070F, 0x0000 }, /* R4242 - Write Sequencer 146 */ + { 0x010F, 0x010F, 0x0000 }, /* R4243 - Write Sequencer 147 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4244 - Write Sequencer 148 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4245 - Write Sequencer 149 */ + { 0x070F, 0x070F, 0x0000 }, /* R4246 - Write Sequencer 150 */ + { 0x010F, 0x010F, 0x0000 }, /* R4247 - Write Sequencer 151 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4248 - Write Sequencer 152 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4249 - Write Sequencer 153 */ + { 0x070F, 0x070F, 0x0000 }, /* R4250 - Write Sequencer 154 */ + { 0x010F, 0x010F, 0x0000 }, /* R4251 - Write Sequencer 155 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4252 - Write Sequencer 156 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4253 - Write Sequencer 157 */ + { 0x070F, 0x070F, 0x0000 }, /* R4254 - Write Sequencer 158 */ + { 0x010F, 0x010F, 0x0000 }, /* R4255 - Write Sequencer 159 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4256 - Write Sequencer 160 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4257 - Write Sequencer 161 */ + { 0x070F, 0x070F, 0x0000 }, /* R4258 - Write Sequencer 162 */ + { 0x010F, 0x010F, 0x0000 }, /* R4259 - Write Sequencer 163 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4260 - Write Sequencer 164 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4261 - Write Sequencer 165 */ + { 0x070F, 0x070F, 0x0000 }, /* R4262 - Write Sequencer 166 */ + { 0x010F, 0x010F, 0x0000 }, /* R4263 - Write Sequencer 167 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4264 - Write Sequencer 168 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4265 - Write Sequencer 169 */ + { 0x070F, 0x070F, 0x0000 }, /* R4266 - Write Sequencer 170 */ + { 0x010F, 0x010F, 0x0000 }, /* R4267 - Write Sequencer 171 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4268 - Write Sequencer 172 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4269 - Write Sequencer 173 */ + { 0x070F, 0x070F, 0x0000 }, /* R4270 - Write Sequencer 174 */ + { 0x010F, 0x010F, 0x0000 }, /* R4271 - Write Sequencer 175 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4272 - Write Sequencer 176 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4273 - Write Sequencer 177 */ + { 0x070F, 0x070F, 0x0000 }, /* R4274 - Write Sequencer 178 */ + { 0x010F, 0x010F, 0x0000 }, /* R4275 - Write Sequencer 179 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4276 - Write Sequencer 180 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4277 - Write Sequencer 181 */ + { 0x070F, 0x070F, 0x0000 }, /* R4278 - Write Sequencer 182 */ + { 0x010F, 0x010F, 0x0000 }, /* R4279 - Write Sequencer 183 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4280 - Write Sequencer 184 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4281 - Write Sequencer 185 */ + { 0x070F, 0x070F, 0x0000 }, /* R4282 - Write Sequencer 186 */ + { 0x010F, 0x010F, 0x0000 }, /* R4283 - Write Sequencer 187 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4284 - Write Sequencer 188 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4285 - Write Sequencer 189 */ + { 0x070F, 0x070F, 0x0000 }, /* R4286 - Write Sequencer 190 */ + { 0x010F, 0x010F, 0x0000 }, /* R4287 - Write Sequencer 191 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4288 - Write Sequencer 192 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4289 - Write Sequencer 193 */ + { 0x070F, 0x070F, 0x0000 }, /* R4290 - Write Sequencer 194 */ + { 0x010F, 0x010F, 0x0000 }, /* R4291 - Write Sequencer 195 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4292 - Write Sequencer 196 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4293 - Write Sequencer 197 */ + { 0x070F, 0x070F, 0x0000 }, /* R4294 - Write Sequencer 198 */ + { 0x010F, 0x010F, 0x0000 }, /* R4295 - Write Sequencer 199 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4296 - Write Sequencer 200 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4297 - Write Sequencer 201 */ + { 0x070F, 0x070F, 0x0000 }, /* R4298 - Write Sequencer 202 */ + { 0x010F, 0x010F, 0x0000 }, /* R4299 - Write Sequencer 203 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4300 - Write Sequencer 204 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4301 - Write Sequencer 205 */ + { 0x070F, 0x070F, 0x0000 }, /* R4302 - Write Sequencer 206 */ + { 0x010F, 0x010F, 0x0000 }, /* R4303 - Write Sequencer 207 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4304 - Write Sequencer 208 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4305 - Write Sequencer 209 */ + { 0x070F, 0x070F, 0x0000 }, /* R4306 - Write Sequencer 210 */ + { 0x010F, 0x010F, 0x0000 }, /* R4307 - Write Sequencer 211 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4308 - Write Sequencer 212 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4309 - Write Sequencer 213 */ + { 0x070F, 0x070F, 0x0000 }, /* R4310 - Write Sequencer 214 */ + { 0x010F, 0x010F, 0x0000 }, /* R4311 - Write Sequencer 215 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4312 - Write Sequencer 216 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4313 - Write Sequencer 217 */ + { 0x070F, 0x070F, 0x0000 }, /* R4314 - Write Sequencer 218 */ + { 0x010F, 0x010F, 0x0000 }, /* R4315 - Write Sequencer 219 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4316 - Write Sequencer 220 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4317 - Write Sequencer 221 */ + { 0x070F, 0x070F, 0x0000 }, /* R4318 - Write Sequencer 222 */ + { 0x010F, 0x010F, 0x0000 }, /* R4319 - Write Sequencer 223 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4320 - Write Sequencer 224 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4321 - Write Sequencer 225 */ + { 0x070F, 0x070F, 0x0000 }, /* R4322 - Write Sequencer 226 */ + { 0x010F, 0x010F, 0x0000 }, /* R4323 - Write Sequencer 227 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4324 - Write Sequencer 228 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4325 - Write Sequencer 229 */ + { 0x070F, 0x070F, 0x0000 }, /* R4326 - Write Sequencer 230 */ + { 0x010F, 0x010F, 0x0000 }, /* R4327 - Write Sequencer 231 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4328 - Write Sequencer 232 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4329 - Write Sequencer 233 */ + { 0x070F, 0x070F, 0x0000 }, /* R4330 - Write Sequencer 234 */ + { 0x010F, 0x010F, 0x0000 }, /* R4331 - Write Sequencer 235 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4332 - Write Sequencer 236 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4333 - Write Sequencer 237 */ + { 0x070F, 0x070F, 0x0000 }, /* R4334 - Write Sequencer 238 */ + { 0x010F, 0x010F, 0x0000 }, /* R4335 - Write Sequencer 239 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4336 - Write Sequencer 240 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4337 - Write Sequencer 241 */ + { 0x070F, 0x070F, 0x0000 }, /* R4338 - Write Sequencer 242 */ + { 0x010F, 0x010F, 0x0000 }, /* R4339 - Write Sequencer 243 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4340 - Write Sequencer 244 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4341 - Write Sequencer 245 */ + { 0x070F, 0x070F, 0x0000 }, /* R4342 - Write Sequencer 246 */ + { 0x010F, 0x010F, 0x0000 }, /* R4343 - Write Sequencer 247 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4344 - Write Sequencer 248 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4345 - Write Sequencer 249 */ + { 0x070F, 0x070F, 0x0000 }, /* R4346 - Write Sequencer 250 */ + { 0x010F, 0x010F, 0x0000 }, /* R4347 - Write Sequencer 251 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4348 - Write Sequencer 252 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4349 - Write Sequencer 253 */ + { 0x070F, 0x070F, 0x0000 }, /* R4350 - Write Sequencer 254 */ + { 0x010F, 0x010F, 0x0000 }, /* R4351 - Write Sequencer 255 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4352 - Write Sequencer 256 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4353 - Write Sequencer 257 */ + { 0x070F, 0x070F, 0x0000 }, /* R4354 - Write Sequencer 258 */ + { 0x010F, 0x010F, 0x0000 }, /* R4355 - Write Sequencer 259 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4356 - Write Sequencer 260 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4357 - Write Sequencer 261 */ + { 0x070F, 0x070F, 0x0000 }, /* R4358 - Write Sequencer 262 */ + { 0x010F, 0x010F, 0x0000 }, /* R4359 - Write Sequencer 263 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4360 - Write Sequencer 264 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4361 - Write Sequencer 265 */ + { 0x070F, 0x070F, 0x0000 }, /* R4362 - Write Sequencer 266 */ + { 0x010F, 0x010F, 0x0000 }, /* R4363 - Write Sequencer 267 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4364 - Write Sequencer 268 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4365 - Write Sequencer 269 */ + { 0x070F, 0x070F, 0x0000 }, /* R4366 - Write Sequencer 270 */ + { 0x010F, 0x010F, 0x0000 }, /* R4367 - Write Sequencer 271 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4368 - Write Sequencer 272 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4369 - Write Sequencer 273 */ + { 0x070F, 0x070F, 0x0000 }, /* R4370 - Write Sequencer 274 */ + { 0x010F, 0x010F, 0x0000 }, /* R4371 - Write Sequencer 275 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4372 - Write Sequencer 276 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4373 - Write Sequencer 277 */ + { 0x070F, 0x070F, 0x0000 }, /* R4374 - Write Sequencer 278 */ + { 0x010F, 0x010F, 0x0000 }, /* R4375 - Write Sequencer 279 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4376 - Write Sequencer 280 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4377 - Write Sequencer 281 */ + { 0x070F, 0x070F, 0x0000 }, /* R4378 - Write Sequencer 282 */ + { 0x010F, 0x010F, 0x0000 }, /* R4379 - Write Sequencer 283 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4380 - Write Sequencer 284 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4381 - Write Sequencer 285 */ + { 0x070F, 0x070F, 0x0000 }, /* R4382 - Write Sequencer 286 */ + { 0x010F, 0x010F, 0x0000 }, /* R4383 - Write Sequencer 287 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4384 - Write Sequencer 288 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4385 - Write Sequencer 289 */ + { 0x070F, 0x070F, 0x0000 }, /* R4386 - Write Sequencer 290 */ + { 0x010F, 0x010F, 0x0000 }, /* R4387 - Write Sequencer 291 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4388 - Write Sequencer 292 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4389 - Write Sequencer 293 */ + { 0x070F, 0x070F, 0x0000 }, /* R4390 - Write Sequencer 294 */ + { 0x010F, 0x010F, 0x0000 }, /* R4391 - Write Sequencer 295 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4392 - Write Sequencer 296 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4393 - Write Sequencer 297 */ + { 0x070F, 0x070F, 0x0000 }, /* R4394 - Write Sequencer 298 */ + { 0x010F, 0x010F, 0x0000 }, /* R4395 - Write Sequencer 299 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4396 - Write Sequencer 300 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4397 - Write Sequencer 301 */ + { 0x070F, 0x070F, 0x0000 }, /* R4398 - Write Sequencer 302 */ + { 0x010F, 0x010F, 0x0000 }, /* R4399 - Write Sequencer 303 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4400 - Write Sequencer 304 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4401 - Write Sequencer 305 */ + { 0x070F, 0x070F, 0x0000 }, /* R4402 - Write Sequencer 306 */ + { 0x010F, 0x010F, 0x0000 }, /* R4403 - Write Sequencer 307 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4404 - Write Sequencer 308 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4405 - Write Sequencer 309 */ + { 0x070F, 0x070F, 0x0000 }, /* R4406 - Write Sequencer 310 */ + { 0x010F, 0x010F, 0x0000 }, /* R4407 - Write Sequencer 311 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4408 - Write Sequencer 312 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4409 - Write Sequencer 313 */ + { 0x070F, 0x070F, 0x0000 }, /* R4410 - Write Sequencer 314 */ + { 0x010F, 0x010F, 0x0000 }, /* R4411 - Write Sequencer 315 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4412 - Write Sequencer 316 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4413 - Write Sequencer 317 */ + { 0x070F, 0x070F, 0x0000 }, /* R4414 - Write Sequencer 318 */ + { 0x010F, 0x010F, 0x0000 }, /* R4415 - Write Sequencer 319 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4416 - Write Sequencer 320 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4417 - Write Sequencer 321 */ + { 0x070F, 0x070F, 0x0000 }, /* R4418 - Write Sequencer 322 */ + { 0x010F, 0x010F, 0x0000 }, /* R4419 - Write Sequencer 323 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4420 - Write Sequencer 324 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4421 - Write Sequencer 325 */ + { 0x070F, 0x070F, 0x0000 }, /* R4422 - Write Sequencer 326 */ + { 0x010F, 0x010F, 0x0000 }, /* R4423 - Write Sequencer 327 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4424 - Write Sequencer 328 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4425 - Write Sequencer 329 */ + { 0x070F, 0x070F, 0x0000 }, /* R4426 - Write Sequencer 330 */ + { 0x010F, 0x010F, 0x0000 }, /* R4427 - Write Sequencer 331 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4428 - Write Sequencer 332 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4429 - Write Sequencer 333 */ + { 0x070F, 0x070F, 0x0000 }, /* R4430 - Write Sequencer 334 */ + { 0x010F, 0x010F, 0x0000 }, /* R4431 - Write Sequencer 335 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4432 - Write Sequencer 336 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4433 - Write Sequencer 337 */ + { 0x070F, 0x070F, 0x0000 }, /* R4434 - Write Sequencer 338 */ + { 0x010F, 0x010F, 0x0000 }, /* R4435 - Write Sequencer 339 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4436 - Write Sequencer 340 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4437 - Write Sequencer 341 */ + { 0x070F, 0x070F, 0x0000 }, /* R4438 - Write Sequencer 342 */ + { 0x010F, 0x010F, 0x0000 }, /* R4439 - Write Sequencer 343 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4440 - Write Sequencer 344 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4441 - Write Sequencer 345 */ + { 0x070F, 0x070F, 0x0000 }, /* R4442 - Write Sequencer 346 */ + { 0x010F, 0x010F, 0x0000 }, /* R4443 - Write Sequencer 347 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4444 - Write Sequencer 348 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4445 - Write Sequencer 349 */ + { 0x070F, 0x070F, 0x0000 }, /* R4446 - Write Sequencer 350 */ + { 0x010F, 0x010F, 0x0000 }, /* R4447 - Write Sequencer 351 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4448 - Write Sequencer 352 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4449 - Write Sequencer 353 */ + { 0x070F, 0x070F, 0x0000 }, /* R4450 - Write Sequencer 354 */ + { 0x010F, 0x010F, 0x0000 }, /* R4451 - Write Sequencer 355 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4452 - Write Sequencer 356 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4453 - Write Sequencer 357 */ + { 0x070F, 0x070F, 0x0000 }, /* R4454 - Write Sequencer 358 */ + { 0x010F, 0x010F, 0x0000 }, /* R4455 - Write Sequencer 359 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4456 - Write Sequencer 360 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4457 - Write Sequencer 361 */ + { 0x070F, 0x070F, 0x0000 }, /* R4458 - Write Sequencer 362 */ + { 0x010F, 0x010F, 0x0000 }, /* R4459 - Write Sequencer 363 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4460 - Write Sequencer 364 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4461 - Write Sequencer 365 */ + { 0x070F, 0x070F, 0x0000 }, /* R4462 - Write Sequencer 366 */ + { 0x010F, 0x010F, 0x0000 }, /* R4463 - Write Sequencer 367 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4464 - Write Sequencer 368 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4465 - Write Sequencer 369 */ + { 0x070F, 0x070F, 0x0000 }, /* R4466 - Write Sequencer 370 */ + { 0x010F, 0x010F, 0x0000 }, /* R4467 - Write Sequencer 371 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4468 - Write Sequencer 372 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4469 - Write Sequencer 373 */ + { 0x070F, 0x070F, 0x0000 }, /* R4470 - Write Sequencer 374 */ + { 0x010F, 0x010F, 0x0000 }, /* R4471 - Write Sequencer 375 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4472 - Write Sequencer 376 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4473 - Write Sequencer 377 */ + { 0x070F, 0x070F, 0x0000 }, /* R4474 - Write Sequencer 378 */ + { 0x010F, 0x010F, 0x0000 }, /* R4475 - Write Sequencer 379 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4476 - Write Sequencer 380 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4477 - Write Sequencer 381 */ + { 0x070F, 0x070F, 0x0000 }, /* R4478 - Write Sequencer 382 */ + { 0x010F, 0x010F, 0x0000 }, /* R4479 - Write Sequencer 383 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4480 - Write Sequencer 384 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4481 - Write Sequencer 385 */ + { 0x070F, 0x070F, 0x0000 }, /* R4482 - Write Sequencer 386 */ + { 0x010F, 0x010F, 0x0000 }, /* R4483 - Write Sequencer 387 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4484 - Write Sequencer 388 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4485 - Write Sequencer 389 */ + { 0x070F, 0x070F, 0x0000 }, /* R4486 - Write Sequencer 390 */ + { 0x010F, 0x010F, 0x0000 }, /* R4487 - Write Sequencer 391 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4488 - Write Sequencer 392 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4489 - Write Sequencer 393 */ + { 0x070F, 0x070F, 0x0000 }, /* R4490 - Write Sequencer 394 */ + { 0x010F, 0x010F, 0x0000 }, /* R4491 - Write Sequencer 395 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4492 - Write Sequencer 396 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4493 - Write Sequencer 397 */ + { 0x070F, 0x070F, 0x0000 }, /* R4494 - Write Sequencer 398 */ + { 0x010F, 0x010F, 0x0000 }, /* R4495 - Write Sequencer 399 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4496 - Write Sequencer 400 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4497 - Write Sequencer 401 */ + { 0x070F, 0x070F, 0x0000 }, /* R4498 - Write Sequencer 402 */ + { 0x010F, 0x010F, 0x0000 }, /* R4499 - Write Sequencer 403 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4500 - Write Sequencer 404 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4501 - Write Sequencer 405 */ + { 0x070F, 0x070F, 0x0000 }, /* R4502 - Write Sequencer 406 */ + { 0x010F, 0x010F, 0x0000 }, /* R4503 - Write Sequencer 407 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4504 - Write Sequencer 408 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4505 - Write Sequencer 409 */ + { 0x070F, 0x070F, 0x0000 }, /* R4506 - Write Sequencer 410 */ + { 0x010F, 0x010F, 0x0000 }, /* R4507 - Write Sequencer 411 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4508 - Write Sequencer 412 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4509 - Write Sequencer 413 */ + { 0x070F, 0x070F, 0x0000 }, /* R4510 - Write Sequencer 414 */ + { 0x010F, 0x010F, 0x0000 }, /* R4511 - Write Sequencer 415 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4512 - Write Sequencer 416 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4513 - Write Sequencer 417 */ + { 0x070F, 0x070F, 0x0000 }, /* R4514 - Write Sequencer 418 */ + { 0x010F, 0x010F, 0x0000 }, /* R4515 - Write Sequencer 419 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4516 - Write Sequencer 420 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4517 - Write Sequencer 421 */ + { 0x070F, 0x070F, 0x0000 }, /* R4518 - Write Sequencer 422 */ + { 0x010F, 0x010F, 0x0000 }, /* R4519 - Write Sequencer 423 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4520 - Write Sequencer 424 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4521 - Write Sequencer 425 */ + { 0x070F, 0x070F, 0x0000 }, /* R4522 - Write Sequencer 426 */ + { 0x010F, 0x010F, 0x0000 }, /* R4523 - Write Sequencer 427 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4524 - Write Sequencer 428 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4525 - Write Sequencer 429 */ + { 0x070F, 0x070F, 0x0000 }, /* R4526 - Write Sequencer 430 */ + { 0x010F, 0x010F, 0x0000 }, /* R4527 - Write Sequencer 431 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4528 - Write Sequencer 432 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4529 - Write Sequencer 433 */ + { 0x070F, 0x070F, 0x0000 }, /* R4530 - Write Sequencer 434 */ + { 0x010F, 0x010F, 0x0000 }, /* R4531 - Write Sequencer 435 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4532 - Write Sequencer 436 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4533 - Write Sequencer 437 */ + { 0x070F, 0x070F, 0x0000 }, /* R4534 - Write Sequencer 438 */ + { 0x010F, 0x010F, 0x0000 }, /* R4535 - Write Sequencer 439 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4536 - Write Sequencer 440 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4537 - Write Sequencer 441 */ + { 0x070F, 0x070F, 0x0000 }, /* R4538 - Write Sequencer 442 */ + { 0x010F, 0x010F, 0x0000 }, /* R4539 - Write Sequencer 443 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4540 - Write Sequencer 444 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4541 - Write Sequencer 445 */ + { 0x070F, 0x070F, 0x0000 }, /* R4542 - Write Sequencer 446 */ + { 0x010F, 0x010F, 0x0000 }, /* R4543 - Write Sequencer 447 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4544 - Write Sequencer 448 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4545 - Write Sequencer 449 */ + { 0x070F, 0x070F, 0x0000 }, /* R4546 - Write Sequencer 450 */ + { 0x010F, 0x010F, 0x0000 }, /* R4547 - Write Sequencer 451 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4548 - Write Sequencer 452 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4549 - Write Sequencer 453 */ + { 0x070F, 0x070F, 0x0000 }, /* R4550 - Write Sequencer 454 */ + { 0x010F, 0x010F, 0x0000 }, /* R4551 - Write Sequencer 455 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4552 - Write Sequencer 456 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4553 - Write Sequencer 457 */ + { 0x070F, 0x070F, 0x0000 }, /* R4554 - Write Sequencer 458 */ + { 0x010F, 0x010F, 0x0000 }, /* R4555 - Write Sequencer 459 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4556 - Write Sequencer 460 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4557 - Write Sequencer 461 */ + { 0x070F, 0x070F, 0x0000 }, /* R4558 - Write Sequencer 462 */ + { 0x010F, 0x010F, 0x0000 }, /* R4559 - Write Sequencer 463 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4560 - Write Sequencer 464 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4561 - Write Sequencer 465 */ + { 0x070F, 0x070F, 0x0000 }, /* R4562 - Write Sequencer 466 */ + { 0x010F, 0x010F, 0x0000 }, /* R4563 - Write Sequencer 467 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4564 - Write Sequencer 468 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4565 - Write Sequencer 469 */ + { 0x070F, 0x070F, 0x0000 }, /* R4566 - Write Sequencer 470 */ + { 0x010F, 0x010F, 0x0000 }, /* R4567 - Write Sequencer 471 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4568 - Write Sequencer 472 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4569 - Write Sequencer 473 */ + { 0x070F, 0x070F, 0x0000 }, /* R4570 - Write Sequencer 474 */ + { 0x010F, 0x010F, 0x0000 }, /* R4571 - Write Sequencer 475 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4572 - Write Sequencer 476 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4573 - Write Sequencer 477 */ + { 0x070F, 0x070F, 0x0000 }, /* R4574 - Write Sequencer 478 */ + { 0x010F, 0x010F, 0x0000 }, /* R4575 - Write Sequencer 479 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4576 - Write Sequencer 480 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4577 - Write Sequencer 481 */ + { 0x070F, 0x070F, 0x0000 }, /* R4578 - Write Sequencer 482 */ + { 0x010F, 0x010F, 0x0000 }, /* R4579 - Write Sequencer 483 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4580 - Write Sequencer 484 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4581 - Write Sequencer 485 */ + { 0x070F, 0x070F, 0x0000 }, /* R4582 - Write Sequencer 486 */ + { 0x010F, 0x010F, 0x0000 }, /* R4583 - Write Sequencer 487 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4584 - Write Sequencer 488 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4585 - Write Sequencer 489 */ + { 0x070F, 0x070F, 0x0000 }, /* R4586 - Write Sequencer 490 */ + { 0x010F, 0x010F, 0x0000 }, /* R4587 - Write Sequencer 491 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4588 - Write Sequencer 492 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4589 - Write Sequencer 493 */ + { 0x070F, 0x070F, 0x0000 }, /* R4590 - Write Sequencer 494 */ + { 0x010F, 0x010F, 0x0000 }, /* R4591 - Write Sequencer 495 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4592 - Write Sequencer 496 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4593 - Write Sequencer 497 */ + { 0x070F, 0x070F, 0x0000 }, /* R4594 - Write Sequencer 498 */ + { 0x010F, 0x010F, 0x0000 }, /* R4595 - Write Sequencer 499 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4596 - Write Sequencer 500 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4597 - Write Sequencer 501 */ + { 0x070F, 0x070F, 0x0000 }, /* R4598 - Write Sequencer 502 */ + { 0x010F, 0x010F, 0x0000 }, /* R4599 - Write Sequencer 503 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4600 - Write Sequencer 504 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4601 - Write Sequencer 505 */ + { 0x070F, 0x070F, 0x0000 }, /* R4602 - Write Sequencer 506 */ + { 0x010F, 0x010F, 0x0000 }, /* R4603 - Write Sequencer 507 */ + { 0x3FFF, 0x3FFF, 0x0000 }, /* R4604 - Write Sequencer 508 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R4605 - Write Sequencer 509 */ + { 0x070F, 0x070F, 0x0000 }, /* R4606 - Write Sequencer 510 */ + { 0x010F, 0x010F, 0x0000 }, /* R4607 - Write Sequencer 511 */ + { 0x0000, 0x0000, 0x0000 }, /* R4608 */ + { 0x0000, 0x0000, 0x0000 }, /* R4609 */ + { 0x0000, 0x0000, 0x0000 }, /* R4610 */ + { 0x0000, 0x0000, 0x0000 }, /* R4611 */ + { 0x0000, 0x0000, 0x0000 }, /* R4612 */ + { 0x0000, 0x0000, 0x0000 }, /* R4613 */ + { 0x0000, 0x0000, 0x0000 }, /* R4614 */ + { 0x0000, 0x0000, 0x0000 }, /* R4615 */ + { 0x0000, 0x0000, 0x0000 }, /* R4616 */ + { 0x0000, 0x0000, 0x0000 }, /* R4617 */ + { 0x0000, 0x0000, 0x0000 }, /* R4618 */ + { 0x0000, 0x0000, 0x0000 }, /* R4619 */ + { 0x0000, 0x0000, 0x0000 }, /* R4620 */ + { 0x0000, 0x0000, 0x0000 }, /* R4621 */ + { 0x0000, 0x0000, 0x0000 }, /* R4622 */ + { 0x0000, 0x0000, 0x0000 }, /* R4623 */ + { 0x0000, 0x0000, 0x0000 }, /* R4624 */ + { 0x0000, 0x0000, 0x0000 }, /* R4625 */ + { 0x0000, 0x0000, 0x0000 }, /* R4626 */ + { 0x0000, 0x0000, 0x0000 }, /* R4627 */ + { 0x0000, 0x0000, 0x0000 }, /* R4628 */ + { 0x0000, 0x0000, 0x0000 }, /* R4629 */ + { 0x0000, 0x0000, 0x0000 }, /* R4630 */ + { 0x0000, 0x0000, 0x0000 }, /* R4631 */ + { 0x0000, 0x0000, 0x0000 }, /* R4632 */ + { 0x0000, 0x0000, 0x0000 }, /* R4633 */ + { 0x0000, 0x0000, 0x0000 }, /* R4634 */ + { 0x0000, 0x0000, 0x0000 }, /* R4635 */ + { 0x0000, 0x0000, 0x0000 }, /* R4636 */ + { 0x0000, 0x0000, 0x0000 }, /* R4637 */ + { 0x0000, 0x0000, 0x0000 }, /* R4638 */ + { 0x0000, 0x0000, 0x0000 }, /* R4639 */ + { 0x0000, 0x0000, 0x0000 }, /* R4640 */ + { 0x0000, 0x0000, 0x0000 }, /* R4641 */ + { 0x0000, 0x0000, 0x0000 }, /* R4642 */ + { 0x0000, 0x0000, 0x0000 }, /* R4643 */ + { 0x0000, 0x0000, 0x0000 }, /* R4644 */ + { 0x0000, 0x0000, 0x0000 }, /* R4645 */ + { 0x0000, 0x0000, 0x0000 }, /* R4646 */ + { 0x0000, 0x0000, 0x0000 }, /* R4647 */ + { 0x0000, 0x0000, 0x0000 }, /* R4648 */ + { 0x0000, 0x0000, 0x0000 }, /* R4649 */ + { 0x0000, 0x0000, 0x0000 }, /* R4650 */ + { 0x0000, 0x0000, 0x0000 }, /* R4651 */ + { 0x0000, 0x0000, 0x0000 }, /* R4652 */ + { 0x0000, 0x0000, 0x0000 }, /* R4653 */ + { 0x0000, 0x0000, 0x0000 }, /* R4654 */ + { 0x0000, 0x0000, 0x0000 }, /* R4655 */ + { 0x0000, 0x0000, 0x0000 }, /* R4656 */ + { 0x0000, 0x0000, 0x0000 }, /* R4657 */ + { 0x0000, 0x0000, 0x0000 }, /* R4658 */ + { 0x0000, 0x0000, 0x0000 }, /* R4659 */ + { 0x0000, 0x0000, 0x0000 }, /* R4660 */ + { 0x0000, 0x0000, 0x0000 }, /* R4661 */ + { 0x0000, 0x0000, 0x0000 }, /* R4662 */ + { 0x0000, 0x0000, 0x0000 }, /* R4663 */ + { 0x0000, 0x0000, 0x0000 }, /* R4664 */ + { 0x0000, 0x0000, 0x0000 }, /* R4665 */ + { 0x0000, 0x0000, 0x0000 }, /* R4666 */ + { 0x0000, 0x0000, 0x0000 }, /* R4667 */ + { 0x0000, 0x0000, 0x0000 }, /* R4668 */ + { 0x0000, 0x0000, 0x0000 }, /* R4669 */ + { 0x0000, 0x0000, 0x0000 }, /* R4670 */ + { 0x0000, 0x0000, 0x0000 }, /* R4671 */ + { 0x0000, 0x0000, 0x0000 }, /* R4672 */ + { 0x0000, 0x0000, 0x0000 }, /* R4673 */ + { 0x0000, 0x0000, 0x0000 }, /* R4674 */ + { 0x0000, 0x0000, 0x0000 }, /* R4675 */ + { 0x0000, 0x0000, 0x0000 }, /* R4676 */ + { 0x0000, 0x0000, 0x0000 }, /* R4677 */ + { 0x0000, 0x0000, 0x0000 }, /* R4678 */ + { 0x0000, 0x0000, 0x0000 }, /* R4679 */ + { 0x0000, 0x0000, 0x0000 }, /* R4680 */ + { 0x0000, 0x0000, 0x0000 }, /* R4681 */ + { 0x0000, 0x0000, 0x0000 }, /* R4682 */ + { 0x0000, 0x0000, 0x0000 }, /* R4683 */ + { 0x0000, 0x0000, 0x0000 }, /* R4684 */ + { 0x0000, 0x0000, 0x0000 }, /* R4685 */ + { 0x0000, 0x0000, 0x0000 }, /* R4686 */ + { 0x0000, 0x0000, 0x0000 }, /* R4687 */ + { 0x0000, 0x0000, 0x0000 }, /* R4688 */ + { 0x0000, 0x0000, 0x0000 }, /* R4689 */ + { 0x0000, 0x0000, 0x0000 }, /* R4690 */ + { 0x0000, 0x0000, 0x0000 }, /* R4691 */ + { 0x0000, 0x0000, 0x0000 }, /* R4692 */ + { 0x0000, 0x0000, 0x0000 }, /* R4693 */ + { 0x0000, 0x0000, 0x0000 }, /* R4694 */ + { 0x0000, 0x0000, 0x0000 }, /* R4695 */ + { 0x0000, 0x0000, 0x0000 }, /* R4696 */ + { 0x0000, 0x0000, 0x0000 }, /* R4697 */ + { 0x0000, 0x0000, 0x0000 }, /* R4698 */ + { 0x0000, 0x0000, 0x0000 }, /* R4699 */ + { 0x0000, 0x0000, 0x0000 }, /* R4700 */ + { 0x0000, 0x0000, 0x0000 }, /* R4701 */ + { 0x0000, 0x0000, 0x0000 }, /* R4702 */ + { 0x0000, 0x0000, 0x0000 }, /* R4703 */ + { 0x0000, 0x0000, 0x0000 }, /* R4704 */ + { 0x0000, 0x0000, 0x0000 }, /* R4705 */ + { 0x0000, 0x0000, 0x0000 }, /* R4706 */ + { 0x0000, 0x0000, 0x0000 }, /* R4707 */ + { 0x0000, 0x0000, 0x0000 }, /* R4708 */ + { 0x0000, 0x0000, 0x0000 }, /* R4709 */ + { 0x0000, 0x0000, 0x0000 }, /* R4710 */ + { 0x0000, 0x0000, 0x0000 }, /* R4711 */ + { 0x0000, 0x0000, 0x0000 }, /* R4712 */ + { 0x0000, 0x0000, 0x0000 }, /* R4713 */ + { 0x0000, 0x0000, 0x0000 }, /* R4714 */ + { 0x0000, 0x0000, 0x0000 }, /* R4715 */ + { 0x0000, 0x0000, 0x0000 }, /* R4716 */ + { 0x0000, 0x0000, 0x0000 }, /* R4717 */ + { 0x0000, 0x0000, 0x0000 }, /* R4718 */ + { 0x0000, 0x0000, 0x0000 }, /* R4719 */ + { 0x0000, 0x0000, 0x0000 }, /* R4720 */ + { 0x0000, 0x0000, 0x0000 }, /* R4721 */ + { 0x0000, 0x0000, 0x0000 }, /* R4722 */ + { 0x0000, 0x0000, 0x0000 }, /* R4723 */ + { 0x0000, 0x0000, 0x0000 }, /* R4724 */ + { 0x0000, 0x0000, 0x0000 }, /* R4725 */ + { 0x0000, 0x0000, 0x0000 }, /* R4726 */ + { 0x0000, 0x0000, 0x0000 }, /* R4727 */ + { 0x0000, 0x0000, 0x0000 }, /* R4728 */ + { 0x0000, 0x0000, 0x0000 }, /* R4729 */ + { 0x0000, 0x0000, 0x0000 }, /* R4730 */ + { 0x0000, 0x0000, 0x0000 }, /* R4731 */ + { 0x0000, 0x0000, 0x0000 }, /* R4732 */ + { 0x0000, 0x0000, 0x0000 }, /* R4733 */ + { 0x0000, 0x0000, 0x0000 }, /* R4734 */ + { 0x0000, 0x0000, 0x0000 }, /* R4735 */ + { 0x0000, 0x0000, 0x0000 }, /* R4736 */ + { 0x0000, 0x0000, 0x0000 }, /* R4737 */ + { 0x0000, 0x0000, 0x0000 }, /* R4738 */ + { 0x0000, 0x0000, 0x0000 }, /* R4739 */ + { 0x0000, 0x0000, 0x0000 }, /* R4740 */ + { 0x0000, 0x0000, 0x0000 }, /* R4741 */ + { 0x0000, 0x0000, 0x0000 }, /* R4742 */ + { 0x0000, 0x0000, 0x0000 }, /* R4743 */ + { 0x0000, 0x0000, 0x0000 }, /* R4744 */ + { 0x0000, 0x0000, 0x0000 }, /* R4745 */ + { 0x0000, 0x0000, 0x0000 }, /* R4746 */ + { 0x0000, 0x0000, 0x0000 }, /* R4747 */ + { 0x0000, 0x0000, 0x0000 }, /* R4748 */ + { 0x0000, 0x0000, 0x0000 }, /* R4749 */ + { 0x0000, 0x0000, 0x0000 }, /* R4750 */ + { 0x0000, 0x0000, 0x0000 }, /* R4751 */ + { 0x0000, 0x0000, 0x0000 }, /* R4752 */ + { 0x0000, 0x0000, 0x0000 }, /* R4753 */ + { 0x0000, 0x0000, 0x0000 }, /* R4754 */ + { 0x0000, 0x0000, 0x0000 }, /* R4755 */ + { 0x0000, 0x0000, 0x0000 }, /* R4756 */ + { 0x0000, 0x0000, 0x0000 }, /* R4757 */ + { 0x0000, 0x0000, 0x0000 }, /* R4758 */ + { 0x0000, 0x0000, 0x0000 }, /* R4759 */ + { 0x0000, 0x0000, 0x0000 }, /* R4760 */ + { 0x0000, 0x0000, 0x0000 }, /* R4761 */ + { 0x0000, 0x0000, 0x0000 }, /* R4762 */ + { 0x0000, 0x0000, 0x0000 }, /* R4763 */ + { 0x0000, 0x0000, 0x0000 }, /* R4764 */ + { 0x0000, 0x0000, 0x0000 }, /* R4765 */ + { 0x0000, 0x0000, 0x0000 }, /* R4766 */ + { 0x0000, 0x0000, 0x0000 }, /* R4767 */ + { 0x0000, 0x0000, 0x0000 }, /* R4768 */ + { 0x0000, 0x0000, 0x0000 }, /* R4769 */ + { 0x0000, 0x0000, 0x0000 }, /* R4770 */ + { 0x0000, 0x0000, 0x0000 }, /* R4771 */ + { 0x0000, 0x0000, 0x0000 }, /* R4772 */ + { 0x0000, 0x0000, 0x0000 }, /* R4773 */ + { 0x0000, 0x0000, 0x0000 }, /* R4774 */ + { 0x0000, 0x0000, 0x0000 }, /* R4775 */ + { 0x0000, 0x0000, 0x0000 }, /* R4776 */ + { 0x0000, 0x0000, 0x0000 }, /* R4777 */ + { 0x0000, 0x0000, 0x0000 }, /* R4778 */ + { 0x0000, 0x0000, 0x0000 }, /* R4779 */ + { 0x0000, 0x0000, 0x0000 }, /* R4780 */ + { 0x0000, 0x0000, 0x0000 }, /* R4781 */ + { 0x0000, 0x0000, 0x0000 }, /* R4782 */ + { 0x0000, 0x0000, 0x0000 }, /* R4783 */ + { 0x0000, 0x0000, 0x0000 }, /* R4784 */ + { 0x0000, 0x0000, 0x0000 }, /* R4785 */ + { 0x0000, 0x0000, 0x0000 }, /* R4786 */ + { 0x0000, 0x0000, 0x0000 }, /* R4787 */ + { 0x0000, 0x0000, 0x0000 }, /* R4788 */ + { 0x0000, 0x0000, 0x0000 }, /* R4789 */ + { 0x0000, 0x0000, 0x0000 }, /* R4790 */ + { 0x0000, 0x0000, 0x0000 }, /* R4791 */ + { 0x0000, 0x0000, 0x0000 }, /* R4792 */ + { 0x0000, 0x0000, 0x0000 }, /* R4793 */ + { 0x0000, 0x0000, 0x0000 }, /* R4794 */ + { 0x0000, 0x0000, 0x0000 }, /* R4795 */ + { 0x0000, 0x0000, 0x0000 }, /* R4796 */ + { 0x0000, 0x0000, 0x0000 }, /* R4797 */ + { 0x0000, 0x0000, 0x0000 }, /* R4798 */ + { 0x0000, 0x0000, 0x0000 }, /* R4799 */ + { 0x0000, 0x0000, 0x0000 }, /* R4800 */ + { 0x0000, 0x0000, 0x0000 }, /* R4801 */ + { 0x0000, 0x0000, 0x0000 }, /* R4802 */ + { 0x0000, 0x0000, 0x0000 }, /* R4803 */ + { 0x0000, 0x0000, 0x0000 }, /* R4804 */ + { 0x0000, 0x0000, 0x0000 }, /* R4805 */ + { 0x0000, 0x0000, 0x0000 }, /* R4806 */ + { 0x0000, 0x0000, 0x0000 }, /* R4807 */ + { 0x0000, 0x0000, 0x0000 }, /* R4808 */ + { 0x0000, 0x0000, 0x0000 }, /* R4809 */ + { 0x0000, 0x0000, 0x0000 }, /* R4810 */ + { 0x0000, 0x0000, 0x0000 }, /* R4811 */ + { 0x0000, 0x0000, 0x0000 }, /* R4812 */ + { 0x0000, 0x0000, 0x0000 }, /* R4813 */ + { 0x0000, 0x0000, 0x0000 }, /* R4814 */ + { 0x0000, 0x0000, 0x0000 }, /* R4815 */ + { 0x0000, 0x0000, 0x0000 }, /* R4816 */ + { 0x0000, 0x0000, 0x0000 }, /* R4817 */ + { 0x0000, 0x0000, 0x0000 }, /* R4818 */ + { 0x0000, 0x0000, 0x0000 }, /* R4819 */ + { 0x0000, 0x0000, 0x0000 }, /* R4820 */ + { 0x0000, 0x0000, 0x0000 }, /* R4821 */ + { 0x0000, 0x0000, 0x0000 }, /* R4822 */ + { 0x0000, 0x0000, 0x0000 }, /* R4823 */ + { 0x0000, 0x0000, 0x0000 }, /* R4824 */ + { 0x0000, 0x0000, 0x0000 }, /* R4825 */ + { 0x0000, 0x0000, 0x0000 }, /* R4826 */ + { 0x0000, 0x0000, 0x0000 }, /* R4827 */ + { 0x0000, 0x0000, 0x0000 }, /* R4828 */ + { 0x0000, 0x0000, 0x0000 }, /* R4829 */ + { 0x0000, 0x0000, 0x0000 }, /* R4830 */ + { 0x0000, 0x0000, 0x0000 }, /* R4831 */ + { 0x0000, 0x0000, 0x0000 }, /* R4832 */ + { 0x0000, 0x0000, 0x0000 }, /* R4833 */ + { 0x0000, 0x0000, 0x0000 }, /* R4834 */ + { 0x0000, 0x0000, 0x0000 }, /* R4835 */ + { 0x0000, 0x0000, 0x0000 }, /* R4836 */ + { 0x0000, 0x0000, 0x0000 }, /* R4837 */ + { 0x0000, 0x0000, 0x0000 }, /* R4838 */ + { 0x0000, 0x0000, 0x0000 }, /* R4839 */ + { 0x0000, 0x0000, 0x0000 }, /* R4840 */ + { 0x0000, 0x0000, 0x0000 }, /* R4841 */ + { 0x0000, 0x0000, 0x0000 }, /* R4842 */ + { 0x0000, 0x0000, 0x0000 }, /* R4843 */ + { 0x0000, 0x0000, 0x0000 }, /* R4844 */ + { 0x0000, 0x0000, 0x0000 }, /* R4845 */ + { 0x0000, 0x0000, 0x0000 }, /* R4846 */ + { 0x0000, 0x0000, 0x0000 }, /* R4847 */ + { 0x0000, 0x0000, 0x0000 }, /* R4848 */ + { 0x0000, 0x0000, 0x0000 }, /* R4849 */ + { 0x0000, 0x0000, 0x0000 }, /* R4850 */ + { 0x0000, 0x0000, 0x0000 }, /* R4851 */ + { 0x0000, 0x0000, 0x0000 }, /* R4852 */ + { 0x0000, 0x0000, 0x0000 }, /* R4853 */ + { 0x0000, 0x0000, 0x0000 }, /* R4854 */ + { 0x0000, 0x0000, 0x0000 }, /* R4855 */ + { 0x0000, 0x0000, 0x0000 }, /* R4856 */ + { 0x0000, 0x0000, 0x0000 }, /* R4857 */ + { 0x0000, 0x0000, 0x0000 }, /* R4858 */ + { 0x0000, 0x0000, 0x0000 }, /* R4859 */ + { 0x0000, 0x0000, 0x0000 }, /* R4860 */ + { 0x0000, 0x0000, 0x0000 }, /* R4861 */ + { 0x0000, 0x0000, 0x0000 }, /* R4862 */ + { 0x0000, 0x0000, 0x0000 }, /* R4863 */ + { 0x0000, 0x0000, 0x0000 }, /* R4864 */ + { 0x0000, 0x0000, 0x0000 }, /* R4865 */ + { 0x0000, 0x0000, 0x0000 }, /* R4866 */ + { 0x0000, 0x0000, 0x0000 }, /* R4867 */ + { 0x0000, 0x0000, 0x0000 }, /* R4868 */ + { 0x0000, 0x0000, 0x0000 }, /* R4869 */ + { 0x0000, 0x0000, 0x0000 }, /* R4870 */ + { 0x0000, 0x0000, 0x0000 }, /* R4871 */ + { 0x0000, 0x0000, 0x0000 }, /* R4872 */ + { 0x0000, 0x0000, 0x0000 }, /* R4873 */ + { 0x0000, 0x0000, 0x0000 }, /* R4874 */ + { 0x0000, 0x0000, 0x0000 }, /* R4875 */ + { 0x0000, 0x0000, 0x0000 }, /* R4876 */ + { 0x0000, 0x0000, 0x0000 }, /* R4877 */ + { 0x0000, 0x0000, 0x0000 }, /* R4878 */ + { 0x0000, 0x0000, 0x0000 }, /* R4879 */ + { 0x0000, 0x0000, 0x0000 }, /* R4880 */ + { 0x0000, 0x0000, 0x0000 }, /* R4881 */ + { 0x0000, 0x0000, 0x0000 }, /* R4882 */ + { 0x0000, 0x0000, 0x0000 }, /* R4883 */ + { 0x0000, 0x0000, 0x0000 }, /* R4884 */ + { 0x0000, 0x0000, 0x0000 }, /* R4885 */ + { 0x0000, 0x0000, 0x0000 }, /* R4886 */ + { 0x0000, 0x0000, 0x0000 }, /* R4887 */ + { 0x0000, 0x0000, 0x0000 }, /* R4888 */ + { 0x0000, 0x0000, 0x0000 }, /* R4889 */ + { 0x0000, 0x0000, 0x0000 }, /* R4890 */ + { 0x0000, 0x0000, 0x0000 }, /* R4891 */ + { 0x0000, 0x0000, 0x0000 }, /* R4892 */ + { 0x0000, 0x0000, 0x0000 }, /* R4893 */ + { 0x0000, 0x0000, 0x0000 }, /* R4894 */ + { 0x0000, 0x0000, 0x0000 }, /* R4895 */ + { 0x0000, 0x0000, 0x0000 }, /* R4896 */ + { 0x0000, 0x0000, 0x0000 }, /* R4897 */ + { 0x0000, 0x0000, 0x0000 }, /* R4898 */ + { 0x0000, 0x0000, 0x0000 }, /* R4899 */ + { 0x0000, 0x0000, 0x0000 }, /* R4900 */ + { 0x0000, 0x0000, 0x0000 }, /* R4901 */ + { 0x0000, 0x0000, 0x0000 }, /* R4902 */ + { 0x0000, 0x0000, 0x0000 }, /* R4903 */ + { 0x0000, 0x0000, 0x0000 }, /* R4904 */ + { 0x0000, 0x0000, 0x0000 }, /* R4905 */ + { 0x0000, 0x0000, 0x0000 }, /* R4906 */ + { 0x0000, 0x0000, 0x0000 }, /* R4907 */ + { 0x0000, 0x0000, 0x0000 }, /* R4908 */ + { 0x0000, 0x0000, 0x0000 }, /* R4909 */ + { 0x0000, 0x0000, 0x0000 }, /* R4910 */ + { 0x0000, 0x0000, 0x0000 }, /* R4911 */ + { 0x0000, 0x0000, 0x0000 }, /* R4912 */ + { 0x0000, 0x0000, 0x0000 }, /* R4913 */ + { 0x0000, 0x0000, 0x0000 }, /* R4914 */ + { 0x0000, 0x0000, 0x0000 }, /* R4915 */ + { 0x0000, 0x0000, 0x0000 }, /* R4916 */ + { 0x0000, 0x0000, 0x0000 }, /* R4917 */ + { 0x0000, 0x0000, 0x0000 }, /* R4918 */ + { 0x0000, 0x0000, 0x0000 }, /* R4919 */ + { 0x0000, 0x0000, 0x0000 }, /* R4920 */ + { 0x0000, 0x0000, 0x0000 }, /* R4921 */ + { 0x0000, 0x0000, 0x0000 }, /* R4922 */ + { 0x0000, 0x0000, 0x0000 }, /* R4923 */ + { 0x0000, 0x0000, 0x0000 }, /* R4924 */ + { 0x0000, 0x0000, 0x0000 }, /* R4925 */ + { 0x0000, 0x0000, 0x0000 }, /* R4926 */ + { 0x0000, 0x0000, 0x0000 }, /* R4927 */ + { 0x0000, 0x0000, 0x0000 }, /* R4928 */ + { 0x0000, 0x0000, 0x0000 }, /* R4929 */ + { 0x0000, 0x0000, 0x0000 }, /* R4930 */ + { 0x0000, 0x0000, 0x0000 }, /* R4931 */ + { 0x0000, 0x0000, 0x0000 }, /* R4932 */ + { 0x0000, 0x0000, 0x0000 }, /* R4933 */ + { 0x0000, 0x0000, 0x0000 }, /* R4934 */ + { 0x0000, 0x0000, 0x0000 }, /* R4935 */ + { 0x0000, 0x0000, 0x0000 }, /* R4936 */ + { 0x0000, 0x0000, 0x0000 }, /* R4937 */ + { 0x0000, 0x0000, 0x0000 }, /* R4938 */ + { 0x0000, 0x0000, 0x0000 }, /* R4939 */ + { 0x0000, 0x0000, 0x0000 }, /* R4940 */ + { 0x0000, 0x0000, 0x0000 }, /* R4941 */ + { 0x0000, 0x0000, 0x0000 }, /* R4942 */ + { 0x0000, 0x0000, 0x0000 }, /* R4943 */ + { 0x0000, 0x0000, 0x0000 }, /* R4944 */ + { 0x0000, 0x0000, 0x0000 }, /* R4945 */ + { 0x0000, 0x0000, 0x0000 }, /* R4946 */ + { 0x0000, 0x0000, 0x0000 }, /* R4947 */ + { 0x0000, 0x0000, 0x0000 }, /* R4948 */ + { 0x0000, 0x0000, 0x0000 }, /* R4949 */ + { 0x0000, 0x0000, 0x0000 }, /* R4950 */ + { 0x0000, 0x0000, 0x0000 }, /* R4951 */ + { 0x0000, 0x0000, 0x0000 }, /* R4952 */ + { 0x0000, 0x0000, 0x0000 }, /* R4953 */ + { 0x0000, 0x0000, 0x0000 }, /* R4954 */ + { 0x0000, 0x0000, 0x0000 }, /* R4955 */ + { 0x0000, 0x0000, 0x0000 }, /* R4956 */ + { 0x0000, 0x0000, 0x0000 }, /* R4957 */ + { 0x0000, 0x0000, 0x0000 }, /* R4958 */ + { 0x0000, 0x0000, 0x0000 }, /* R4959 */ + { 0x0000, 0x0000, 0x0000 }, /* R4960 */ + { 0x0000, 0x0000, 0x0000 }, /* R4961 */ + { 0x0000, 0x0000, 0x0000 }, /* R4962 */ + { 0x0000, 0x0000, 0x0000 }, /* R4963 */ + { 0x0000, 0x0000, 0x0000 }, /* R4964 */ + { 0x0000, 0x0000, 0x0000 }, /* R4965 */ + { 0x0000, 0x0000, 0x0000 }, /* R4966 */ + { 0x0000, 0x0000, 0x0000 }, /* R4967 */ + { 0x0000, 0x0000, 0x0000 }, /* R4968 */ + { 0x0000, 0x0000, 0x0000 }, /* R4969 */ + { 0x0000, 0x0000, 0x0000 }, /* R4970 */ + { 0x0000, 0x0000, 0x0000 }, /* R4971 */ + { 0x0000, 0x0000, 0x0000 }, /* R4972 */ + { 0x0000, 0x0000, 0x0000 }, /* R4973 */ + { 0x0000, 0x0000, 0x0000 }, /* R4974 */ + { 0x0000, 0x0000, 0x0000 }, /* R4975 */ + { 0x0000, 0x0000, 0x0000 }, /* R4976 */ + { 0x0000, 0x0000, 0x0000 }, /* R4977 */ + { 0x0000, 0x0000, 0x0000 }, /* R4978 */ + { 0x0000, 0x0000, 0x0000 }, /* R4979 */ + { 0x0000, 0x0000, 0x0000 }, /* R4980 */ + { 0x0000, 0x0000, 0x0000 }, /* R4981 */ + { 0x0000, 0x0000, 0x0000 }, /* R4982 */ + { 0x0000, 0x0000, 0x0000 }, /* R4983 */ + { 0x0000, 0x0000, 0x0000 }, /* R4984 */ + { 0x0000, 0x0000, 0x0000 }, /* R4985 */ + { 0x0000, 0x0000, 0x0000 }, /* R4986 */ + { 0x0000, 0x0000, 0x0000 }, /* R4987 */ + { 0x0000, 0x0000, 0x0000 }, /* R4988 */ + { 0x0000, 0x0000, 0x0000 }, /* R4989 */ + { 0x0000, 0x0000, 0x0000 }, /* R4990 */ + { 0x0000, 0x0000, 0x0000 }, /* R4991 */ + { 0x0000, 0x0000, 0x0000 }, /* R4992 */ + { 0x0000, 0x0000, 0x0000 }, /* R4993 */ + { 0x0000, 0x0000, 0x0000 }, /* R4994 */ + { 0x0000, 0x0000, 0x0000 }, /* R4995 */ + { 0x0000, 0x0000, 0x0000 }, /* R4996 */ + { 0x0000, 0x0000, 0x0000 }, /* R4997 */ + { 0x0000, 0x0000, 0x0000 }, /* R4998 */ + { 0x0000, 0x0000, 0x0000 }, /* R4999 */ + { 0x0000, 0x0000, 0x0000 }, /* R5000 */ + { 0x0000, 0x0000, 0x0000 }, /* R5001 */ + { 0x0000, 0x0000, 0x0000 }, /* R5002 */ + { 0x0000, 0x0000, 0x0000 }, /* R5003 */ + { 0x0000, 0x0000, 0x0000 }, /* R5004 */ + { 0x0000, 0x0000, 0x0000 }, /* R5005 */ + { 0x0000, 0x0000, 0x0000 }, /* R5006 */ + { 0x0000, 0x0000, 0x0000 }, /* R5007 */ + { 0x0000, 0x0000, 0x0000 }, /* R5008 */ + { 0x0000, 0x0000, 0x0000 }, /* R5009 */ + { 0x0000, 0x0000, 0x0000 }, /* R5010 */ + { 0x0000, 0x0000, 0x0000 }, /* R5011 */ + { 0x0000, 0x0000, 0x0000 }, /* R5012 */ + { 0x0000, 0x0000, 0x0000 }, /* R5013 */ + { 0x0000, 0x0000, 0x0000 }, /* R5014 */ + { 0x0000, 0x0000, 0x0000 }, /* R5015 */ + { 0x0000, 0x0000, 0x0000 }, /* R5016 */ + { 0x0000, 0x0000, 0x0000 }, /* R5017 */ + { 0x0000, 0x0000, 0x0000 }, /* R5018 */ + { 0x0000, 0x0000, 0x0000 }, /* R5019 */ + { 0x0000, 0x0000, 0x0000 }, /* R5020 */ + { 0x0000, 0x0000, 0x0000 }, /* R5021 */ + { 0x0000, 0x0000, 0x0000 }, /* R5022 */ + { 0x0000, 0x0000, 0x0000 }, /* R5023 */ + { 0x0000, 0x0000, 0x0000 }, /* R5024 */ + { 0x0000, 0x0000, 0x0000 }, /* R5025 */ + { 0x0000, 0x0000, 0x0000 }, /* R5026 */ + { 0x0000, 0x0000, 0x0000 }, /* R5027 */ + { 0x0000, 0x0000, 0x0000 }, /* R5028 */ + { 0x0000, 0x0000, 0x0000 }, /* R5029 */ + { 0x0000, 0x0000, 0x0000 }, /* R5030 */ + { 0x0000, 0x0000, 0x0000 }, /* R5031 */ + { 0x0000, 0x0000, 0x0000 }, /* R5032 */ + { 0x0000, 0x0000, 0x0000 }, /* R5033 */ + { 0x0000, 0x0000, 0x0000 }, /* R5034 */ + { 0x0000, 0x0000, 0x0000 }, /* R5035 */ + { 0x0000, 0x0000, 0x0000 }, /* R5036 */ + { 0x0000, 0x0000, 0x0000 }, /* R5037 */ + { 0x0000, 0x0000, 0x0000 }, /* R5038 */ + { 0x0000, 0x0000, 0x0000 }, /* R5039 */ + { 0x0000, 0x0000, 0x0000 }, /* R5040 */ + { 0x0000, 0x0000, 0x0000 }, /* R5041 */ + { 0x0000, 0x0000, 0x0000 }, /* R5042 */ + { 0x0000, 0x0000, 0x0000 }, /* R5043 */ + { 0x0000, 0x0000, 0x0000 }, /* R5044 */ + { 0x0000, 0x0000, 0x0000 }, /* R5045 */ + { 0x0000, 0x0000, 0x0000 }, /* R5046 */ + { 0x0000, 0x0000, 0x0000 }, /* R5047 */ + { 0x0000, 0x0000, 0x0000 }, /* R5048 */ + { 0x0000, 0x0000, 0x0000 }, /* R5049 */ + { 0x0000, 0x0000, 0x0000 }, /* R5050 */ + { 0x0000, 0x0000, 0x0000 }, /* R5051 */ + { 0x0000, 0x0000, 0x0000 }, /* R5052 */ + { 0x0000, 0x0000, 0x0000 }, /* R5053 */ + { 0x0000, 0x0000, 0x0000 }, /* R5054 */ + { 0x0000, 0x0000, 0x0000 }, /* R5055 */ + { 0x0000, 0x0000, 0x0000 }, /* R5056 */ + { 0x0000, 0x0000, 0x0000 }, /* R5057 */ + { 0x0000, 0x0000, 0x0000 }, /* R5058 */ + { 0x0000, 0x0000, 0x0000 }, /* R5059 */ + { 0x0000, 0x0000, 0x0000 }, /* R5060 */ + { 0x0000, 0x0000, 0x0000 }, /* R5061 */ + { 0x0000, 0x0000, 0x0000 }, /* R5062 */ + { 0x0000, 0x0000, 0x0000 }, /* R5063 */ + { 0x0000, 0x0000, 0x0000 }, /* R5064 */ + { 0x0000, 0x0000, 0x0000 }, /* R5065 */ + { 0x0000, 0x0000, 0x0000 }, /* R5066 */ + { 0x0000, 0x0000, 0x0000 }, /* R5067 */ + { 0x0000, 0x0000, 0x0000 }, /* R5068 */ + { 0x0000, 0x0000, 0x0000 }, /* R5069 */ + { 0x0000, 0x0000, 0x0000 }, /* R5070 */ + { 0x0000, 0x0000, 0x0000 }, /* R5071 */ + { 0x0000, 0x0000, 0x0000 }, /* R5072 */ + { 0x0000, 0x0000, 0x0000 }, /* R5073 */ + { 0x0000, 0x0000, 0x0000 }, /* R5074 */ + { 0x0000, 0x0000, 0x0000 }, /* R5075 */ + { 0x0000, 0x0000, 0x0000 }, /* R5076 */ + { 0x0000, 0x0000, 0x0000 }, /* R5077 */ + { 0x0000, 0x0000, 0x0000 }, /* R5078 */ + { 0x0000, 0x0000, 0x0000 }, /* R5079 */ + { 0x0000, 0x0000, 0x0000 }, /* R5080 */ + { 0x0000, 0x0000, 0x0000 }, /* R5081 */ + { 0x0000, 0x0000, 0x0000 }, /* R5082 */ + { 0x0000, 0x0000, 0x0000 }, /* R5083 */ + { 0x0000, 0x0000, 0x0000 }, /* R5084 */ + { 0x0000, 0x0000, 0x0000 }, /* R5085 */ + { 0x0000, 0x0000, 0x0000 }, /* R5086 */ + { 0x0000, 0x0000, 0x0000 }, /* R5087 */ + { 0x0000, 0x0000, 0x0000 }, /* R5088 */ + { 0x0000, 0x0000, 0x0000 }, /* R5089 */ + { 0x0000, 0x0000, 0x0000 }, /* R5090 */ + { 0x0000, 0x0000, 0x0000 }, /* R5091 */ + { 0x0000, 0x0000, 0x0000 }, /* R5092 */ + { 0x0000, 0x0000, 0x0000 }, /* R5093 */ + { 0x0000, 0x0000, 0x0000 }, /* R5094 */ + { 0x0000, 0x0000, 0x0000 }, /* R5095 */ + { 0x0000, 0x0000, 0x0000 }, /* R5096 */ + { 0x0000, 0x0000, 0x0000 }, /* R5097 */ + { 0x0000, 0x0000, 0x0000 }, /* R5098 */ + { 0x0000, 0x0000, 0x0000 }, /* R5099 */ + { 0x0000, 0x0000, 0x0000 }, /* R5100 */ + { 0x0000, 0x0000, 0x0000 }, /* R5101 */ + { 0x0000, 0x0000, 0x0000 }, /* R5102 */ + { 0x0000, 0x0000, 0x0000 }, /* R5103 */ + { 0x0000, 0x0000, 0x0000 }, /* R5104 */ + { 0x0000, 0x0000, 0x0000 }, /* R5105 */ + { 0x0000, 0x0000, 0x0000 }, /* R5106 */ + { 0x0000, 0x0000, 0x0000 }, /* R5107 */ + { 0x0000, 0x0000, 0x0000 }, /* R5108 */ + { 0x0000, 0x0000, 0x0000 }, /* R5109 */ + { 0x0000, 0x0000, 0x0000 }, /* R5110 */ + { 0x0000, 0x0000, 0x0000 }, /* R5111 */ + { 0x0000, 0x0000, 0x0000 }, /* R5112 */ + { 0x0000, 0x0000, 0x0000 }, /* R5113 */ + { 0x0000, 0x0000, 0x0000 }, /* R5114 */ + { 0x0000, 0x0000, 0x0000 }, /* R5115 */ + { 0x0000, 0x0000, 0x0000 }, /* R5116 */ + { 0x0000, 0x0000, 0x0000 }, /* R5117 */ + { 0x0000, 0x0000, 0x0000 }, /* R5118 */ + { 0x0000, 0x0000, 0x0000 }, /* R5119 */ + { 0x0000, 0x0000, 0x0000 }, /* R5120 */ + { 0x0000, 0x0000, 0x0000 }, /* R5121 */ + { 0x0000, 0x0000, 0x0000 }, /* R5122 */ + { 0x0000, 0x0000, 0x0000 }, /* R5123 */ + { 0x0000, 0x0000, 0x0000 }, /* R5124 */ + { 0x0000, 0x0000, 0x0000 }, /* R5125 */ + { 0x0000, 0x0000, 0x0000 }, /* R5126 */ + { 0x0000, 0x0000, 0x0000 }, /* R5127 */ + { 0x0000, 0x0000, 0x0000 }, /* R5128 */ + { 0x0000, 0x0000, 0x0000 }, /* R5129 */ + { 0x0000, 0x0000, 0x0000 }, /* R5130 */ + { 0x0000, 0x0000, 0x0000 }, /* R5131 */ + { 0x0000, 0x0000, 0x0000 }, /* R5132 */ + { 0x0000, 0x0000, 0x0000 }, /* R5133 */ + { 0x0000, 0x0000, 0x0000 }, /* R5134 */ + { 0x0000, 0x0000, 0x0000 }, /* R5135 */ + { 0x0000, 0x0000, 0x0000 }, /* R5136 */ + { 0x0000, 0x0000, 0x0000 }, /* R5137 */ + { 0x0000, 0x0000, 0x0000 }, /* R5138 */ + { 0x0000, 0x0000, 0x0000 }, /* R5139 */ + { 0x0000, 0x0000, 0x0000 }, /* R5140 */ + { 0x0000, 0x0000, 0x0000 }, /* R5141 */ + { 0x0000, 0x0000, 0x0000 }, /* R5142 */ + { 0x0000, 0x0000, 0x0000 }, /* R5143 */ + { 0x0000, 0x0000, 0x0000 }, /* R5144 */ + { 0x0000, 0x0000, 0x0000 }, /* R5145 */ + { 0x0000, 0x0000, 0x0000 }, /* R5146 */ + { 0x0000, 0x0000, 0x0000 }, /* R5147 */ + { 0x0000, 0x0000, 0x0000 }, /* R5148 */ + { 0x0000, 0x0000, 0x0000 }, /* R5149 */ + { 0x0000, 0x0000, 0x0000 }, /* R5150 */ + { 0x0000, 0x0000, 0x0000 }, /* R5151 */ + { 0x0000, 0x0000, 0x0000 }, /* R5152 */ + { 0x0000, 0x0000, 0x0000 }, /* R5153 */ + { 0x0000, 0x0000, 0x0000 }, /* R5154 */ + { 0x0000, 0x0000, 0x0000 }, /* R5155 */ + { 0x0000, 0x0000, 0x0000 }, /* R5156 */ + { 0x0000, 0x0000, 0x0000 }, /* R5157 */ + { 0x0000, 0x0000, 0x0000 }, /* R5158 */ + { 0x0000, 0x0000, 0x0000 }, /* R5159 */ + { 0x0000, 0x0000, 0x0000 }, /* R5160 */ + { 0x0000, 0x0000, 0x0000 }, /* R5161 */ + { 0x0000, 0x0000, 0x0000 }, /* R5162 */ + { 0x0000, 0x0000, 0x0000 }, /* R5163 */ + { 0x0000, 0x0000, 0x0000 }, /* R5164 */ + { 0x0000, 0x0000, 0x0000 }, /* R5165 */ + { 0x0000, 0x0000, 0x0000 }, /* R5166 */ + { 0x0000, 0x0000, 0x0000 }, /* R5167 */ + { 0x0000, 0x0000, 0x0000 }, /* R5168 */ + { 0x0000, 0x0000, 0x0000 }, /* R5169 */ + { 0x0000, 0x0000, 0x0000 }, /* R5170 */ + { 0x0000, 0x0000, 0x0000 }, /* R5171 */ + { 0x0000, 0x0000, 0x0000 }, /* R5172 */ + { 0x0000, 0x0000, 0x0000 }, /* R5173 */ + { 0x0000, 0x0000, 0x0000 }, /* R5174 */ + { 0x0000, 0x0000, 0x0000 }, /* R5175 */ + { 0x0000, 0x0000, 0x0000 }, /* R5176 */ + { 0x0000, 0x0000, 0x0000 }, /* R5177 */ + { 0x0000, 0x0000, 0x0000 }, /* R5178 */ + { 0x0000, 0x0000, 0x0000 }, /* R5179 */ + { 0x0000, 0x0000, 0x0000 }, /* R5180 */ + { 0x0000, 0x0000, 0x0000 }, /* R5181 */ + { 0x0000, 0x0000, 0x0000 }, /* R5182 */ + { 0x0000, 0x0000, 0x0000 }, /* R5183 */ + { 0x0000, 0x0000, 0x0000 }, /* R5184 */ + { 0x0000, 0x0000, 0x0000 }, /* R5185 */ + { 0x0000, 0x0000, 0x0000 }, /* R5186 */ + { 0x0000, 0x0000, 0x0000 }, /* R5187 */ + { 0x0000, 0x0000, 0x0000 }, /* R5188 */ + { 0x0000, 0x0000, 0x0000 }, /* R5189 */ + { 0x0000, 0x0000, 0x0000 }, /* R5190 */ + { 0x0000, 0x0000, 0x0000 }, /* R5191 */ + { 0x0000, 0x0000, 0x0000 }, /* R5192 */ + { 0x0000, 0x0000, 0x0000 }, /* R5193 */ + { 0x0000, 0x0000, 0x0000 }, /* R5194 */ + { 0x0000, 0x0000, 0x0000 }, /* R5195 */ + { 0x0000, 0x0000, 0x0000 }, /* R5196 */ + { 0x0000, 0x0000, 0x0000 }, /* R5197 */ + { 0x0000, 0x0000, 0x0000 }, /* R5198 */ + { 0x0000, 0x0000, 0x0000 }, /* R5199 */ + { 0x0000, 0x0000, 0x0000 }, /* R5200 */ + { 0x0000, 0x0000, 0x0000 }, /* R5201 */ + { 0x0000, 0x0000, 0x0000 }, /* R5202 */ + { 0x0000, 0x0000, 0x0000 }, /* R5203 */ + { 0x0000, 0x0000, 0x0000 }, /* R5204 */ + { 0x0000, 0x0000, 0x0000 }, /* R5205 */ + { 0x0000, 0x0000, 0x0000 }, /* R5206 */ + { 0x0000, 0x0000, 0x0000 }, /* R5207 */ + { 0x0000, 0x0000, 0x0000 }, /* R5208 */ + { 0x0000, 0x0000, 0x0000 }, /* R5209 */ + { 0x0000, 0x0000, 0x0000 }, /* R5210 */ + { 0x0000, 0x0000, 0x0000 }, /* R5211 */ + { 0x0000, 0x0000, 0x0000 }, /* R5212 */ + { 0x0000, 0x0000, 0x0000 }, /* R5213 */ + { 0x0000, 0x0000, 0x0000 }, /* R5214 */ + { 0x0000, 0x0000, 0x0000 }, /* R5215 */ + { 0x0000, 0x0000, 0x0000 }, /* R5216 */ + { 0x0000, 0x0000, 0x0000 }, /* R5217 */ + { 0x0000, 0x0000, 0x0000 }, /* R5218 */ + { 0x0000, 0x0000, 0x0000 }, /* R5219 */ + { 0x0000, 0x0000, 0x0000 }, /* R5220 */ + { 0x0000, 0x0000, 0x0000 }, /* R5221 */ + { 0x0000, 0x0000, 0x0000 }, /* R5222 */ + { 0x0000, 0x0000, 0x0000 }, /* R5223 */ + { 0x0000, 0x0000, 0x0000 }, /* R5224 */ + { 0x0000, 0x0000, 0x0000 }, /* R5225 */ + { 0x0000, 0x0000, 0x0000 }, /* R5226 */ + { 0x0000, 0x0000, 0x0000 }, /* R5227 */ + { 0x0000, 0x0000, 0x0000 }, /* R5228 */ + { 0x0000, 0x0000, 0x0000 }, /* R5229 */ + { 0x0000, 0x0000, 0x0000 }, /* R5230 */ + { 0x0000, 0x0000, 0x0000 }, /* R5231 */ + { 0x0000, 0x0000, 0x0000 }, /* R5232 */ + { 0x0000, 0x0000, 0x0000 }, /* R5233 */ + { 0x0000, 0x0000, 0x0000 }, /* R5234 */ + { 0x0000, 0x0000, 0x0000 }, /* R5235 */ + { 0x0000, 0x0000, 0x0000 }, /* R5236 */ + { 0x0000, 0x0000, 0x0000 }, /* R5237 */ + { 0x0000, 0x0000, 0x0000 }, /* R5238 */ + { 0x0000, 0x0000, 0x0000 }, /* R5239 */ + { 0x0000, 0x0000, 0x0000 }, /* R5240 */ + { 0x0000, 0x0000, 0x0000 }, /* R5241 */ + { 0x0000, 0x0000, 0x0000 }, /* R5242 */ + { 0x0000, 0x0000, 0x0000 }, /* R5243 */ + { 0x0000, 0x0000, 0x0000 }, /* R5244 */ + { 0x0000, 0x0000, 0x0000 }, /* R5245 */ + { 0x0000, 0x0000, 0x0000 }, /* R5246 */ + { 0x0000, 0x0000, 0x0000 }, /* R5247 */ + { 0x0000, 0x0000, 0x0000 }, /* R5248 */ + { 0x0000, 0x0000, 0x0000 }, /* R5249 */ + { 0x0000, 0x0000, 0x0000 }, /* R5250 */ + { 0x0000, 0x0000, 0x0000 }, /* R5251 */ + { 0x0000, 0x0000, 0x0000 }, /* R5252 */ + { 0x0000, 0x0000, 0x0000 }, /* R5253 */ + { 0x0000, 0x0000, 0x0000 }, /* R5254 */ + { 0x0000, 0x0000, 0x0000 }, /* R5255 */ + { 0x0000, 0x0000, 0x0000 }, /* R5256 */ + { 0x0000, 0x0000, 0x0000 }, /* R5257 */ + { 0x0000, 0x0000, 0x0000 }, /* R5258 */ + { 0x0000, 0x0000, 0x0000 }, /* R5259 */ + { 0x0000, 0x0000, 0x0000 }, /* R5260 */ + { 0x0000, 0x0000, 0x0000 }, /* R5261 */ + { 0x0000, 0x0000, 0x0000 }, /* R5262 */ + { 0x0000, 0x0000, 0x0000 }, /* R5263 */ + { 0x0000, 0x0000, 0x0000 }, /* R5264 */ + { 0x0000, 0x0000, 0x0000 }, /* R5265 */ + { 0x0000, 0x0000, 0x0000 }, /* R5266 */ + { 0x0000, 0x0000, 0x0000 }, /* R5267 */ + { 0x0000, 0x0000, 0x0000 }, /* R5268 */ + { 0x0000, 0x0000, 0x0000 }, /* R5269 */ + { 0x0000, 0x0000, 0x0000 }, /* R5270 */ + { 0x0000, 0x0000, 0x0000 }, /* R5271 */ + { 0x0000, 0x0000, 0x0000 }, /* R5272 */ + { 0x0000, 0x0000, 0x0000 }, /* R5273 */ + { 0x0000, 0x0000, 0x0000 }, /* R5274 */ + { 0x0000, 0x0000, 0x0000 }, /* R5275 */ + { 0x0000, 0x0000, 0x0000 }, /* R5276 */ + { 0x0000, 0x0000, 0x0000 }, /* R5277 */ + { 0x0000, 0x0000, 0x0000 }, /* R5278 */ + { 0x0000, 0x0000, 0x0000 }, /* R5279 */ + { 0x0000, 0x0000, 0x0000 }, /* R5280 */ + { 0x0000, 0x0000, 0x0000 }, /* R5281 */ + { 0x0000, 0x0000, 0x0000 }, /* R5282 */ + { 0x0000, 0x0000, 0x0000 }, /* R5283 */ + { 0x0000, 0x0000, 0x0000 }, /* R5284 */ + { 0x0000, 0x0000, 0x0000 }, /* R5285 */ + { 0x0000, 0x0000, 0x0000 }, /* R5286 */ + { 0x0000, 0x0000, 0x0000 }, /* R5287 */ + { 0x0000, 0x0000, 0x0000 }, /* R5288 */ + { 0x0000, 0x0000, 0x0000 }, /* R5289 */ + { 0x0000, 0x0000, 0x0000 }, /* R5290 */ + { 0x0000, 0x0000, 0x0000 }, /* R5291 */ + { 0x0000, 0x0000, 0x0000 }, /* R5292 */ + { 0x0000, 0x0000, 0x0000 }, /* R5293 */ + { 0x0000, 0x0000, 0x0000 }, /* R5294 */ + { 0x0000, 0x0000, 0x0000 }, /* R5295 */ + { 0x0000, 0x0000, 0x0000 }, /* R5296 */ + { 0x0000, 0x0000, 0x0000 }, /* R5297 */ + { 0x0000, 0x0000, 0x0000 }, /* R5298 */ + { 0x0000, 0x0000, 0x0000 }, /* R5299 */ + { 0x0000, 0x0000, 0x0000 }, /* R5300 */ + { 0x0000, 0x0000, 0x0000 }, /* R5301 */ + { 0x0000, 0x0000, 0x0000 }, /* R5302 */ + { 0x0000, 0x0000, 0x0000 }, /* R5303 */ + { 0x0000, 0x0000, 0x0000 }, /* R5304 */ + { 0x0000, 0x0000, 0x0000 }, /* R5305 */ + { 0x0000, 0x0000, 0x0000 }, /* R5306 */ + { 0x0000, 0x0000, 0x0000 }, /* R5307 */ + { 0x0000, 0x0000, 0x0000 }, /* R5308 */ + { 0x0000, 0x0000, 0x0000 }, /* R5309 */ + { 0x0000, 0x0000, 0x0000 }, /* R5310 */ + { 0x0000, 0x0000, 0x0000 }, /* R5311 */ + { 0x0000, 0x0000, 0x0000 }, /* R5312 */ + { 0x0000, 0x0000, 0x0000 }, /* R5313 */ + { 0x0000, 0x0000, 0x0000 }, /* R5314 */ + { 0x0000, 0x0000, 0x0000 }, /* R5315 */ + { 0x0000, 0x0000, 0x0000 }, /* R5316 */ + { 0x0000, 0x0000, 0x0000 }, /* R5317 */ + { 0x0000, 0x0000, 0x0000 }, /* R5318 */ + { 0x0000, 0x0000, 0x0000 }, /* R5319 */ + { 0x0000, 0x0000, 0x0000 }, /* R5320 */ + { 0x0000, 0x0000, 0x0000 }, /* R5321 */ + { 0x0000, 0x0000, 0x0000 }, /* R5322 */ + { 0x0000, 0x0000, 0x0000 }, /* R5323 */ + { 0x0000, 0x0000, 0x0000 }, /* R5324 */ + { 0x0000, 0x0000, 0x0000 }, /* R5325 */ + { 0x0000, 0x0000, 0x0000 }, /* R5326 */ + { 0x0000, 0x0000, 0x0000 }, /* R5327 */ + { 0x0000, 0x0000, 0x0000 }, /* R5328 */ + { 0x0000, 0x0000, 0x0000 }, /* R5329 */ + { 0x0000, 0x0000, 0x0000 }, /* R5330 */ + { 0x0000, 0x0000, 0x0000 }, /* R5331 */ + { 0x0000, 0x0000, 0x0000 }, /* R5332 */ + { 0x0000, 0x0000, 0x0000 }, /* R5333 */ + { 0x0000, 0x0000, 0x0000 }, /* R5334 */ + { 0x0000, 0x0000, 0x0000 }, /* R5335 */ + { 0x0000, 0x0000, 0x0000 }, /* R5336 */ + { 0x0000, 0x0000, 0x0000 }, /* R5337 */ + { 0x0000, 0x0000, 0x0000 }, /* R5338 */ + { 0x0000, 0x0000, 0x0000 }, /* R5339 */ + { 0x0000, 0x0000, 0x0000 }, /* R5340 */ + { 0x0000, 0x0000, 0x0000 }, /* R5341 */ + { 0x0000, 0x0000, 0x0000 }, /* R5342 */ + { 0x0000, 0x0000, 0x0000 }, /* R5343 */ + { 0x0000, 0x0000, 0x0000 }, /* R5344 */ + { 0x0000, 0x0000, 0x0000 }, /* R5345 */ + { 0x0000, 0x0000, 0x0000 }, /* R5346 */ + { 0x0000, 0x0000, 0x0000 }, /* R5347 */ + { 0x0000, 0x0000, 0x0000 }, /* R5348 */ + { 0x0000, 0x0000, 0x0000 }, /* R5349 */ + { 0x0000, 0x0000, 0x0000 }, /* R5350 */ + { 0x0000, 0x0000, 0x0000 }, /* R5351 */ + { 0x0000, 0x0000, 0x0000 }, /* R5352 */ + { 0x0000, 0x0000, 0x0000 }, /* R5353 */ + { 0x0000, 0x0000, 0x0000 }, /* R5354 */ + { 0x0000, 0x0000, 0x0000 }, /* R5355 */ + { 0x0000, 0x0000, 0x0000 }, /* R5356 */ + { 0x0000, 0x0000, 0x0000 }, /* R5357 */ + { 0x0000, 0x0000, 0x0000 }, /* R5358 */ + { 0x0000, 0x0000, 0x0000 }, /* R5359 */ + { 0x0000, 0x0000, 0x0000 }, /* R5360 */ + { 0x0000, 0x0000, 0x0000 }, /* R5361 */ + { 0x0000, 0x0000, 0x0000 }, /* R5362 */ + { 0x0000, 0x0000, 0x0000 }, /* R5363 */ + { 0x0000, 0x0000, 0x0000 }, /* R5364 */ + { 0x0000, 0x0000, 0x0000 }, /* R5365 */ + { 0x0000, 0x0000, 0x0000 }, /* R5366 */ + { 0x0000, 0x0000, 0x0000 }, /* R5367 */ + { 0x0000, 0x0000, 0x0000 }, /* R5368 */ + { 0x0000, 0x0000, 0x0000 }, /* R5369 */ + { 0x0000, 0x0000, 0x0000 }, /* R5370 */ + { 0x0000, 0x0000, 0x0000 }, /* R5371 */ + { 0x0000, 0x0000, 0x0000 }, /* R5372 */ + { 0x0000, 0x0000, 0x0000 }, /* R5373 */ + { 0x0000, 0x0000, 0x0000 }, /* R5374 */ + { 0x0000, 0x0000, 0x0000 }, /* R5375 */ + { 0x0000, 0x0000, 0x0000 }, /* R5376 */ + { 0x0000, 0x0000, 0x0000 }, /* R5377 */ + { 0x0000, 0x0000, 0x0000 }, /* R5378 */ + { 0x0000, 0x0000, 0x0000 }, /* R5379 */ + { 0x0000, 0x0000, 0x0000 }, /* R5380 */ + { 0x0000, 0x0000, 0x0000 }, /* R5381 */ + { 0x0000, 0x0000, 0x0000 }, /* R5382 */ + { 0x0000, 0x0000, 0x0000 }, /* R5383 */ + { 0x0000, 0x0000, 0x0000 }, /* R5384 */ + { 0x0000, 0x0000, 0x0000 }, /* R5385 */ + { 0x0000, 0x0000, 0x0000 }, /* R5386 */ + { 0x0000, 0x0000, 0x0000 }, /* R5387 */ + { 0x0000, 0x0000, 0x0000 }, /* R5388 */ + { 0x0000, 0x0000, 0x0000 }, /* R5389 */ + { 0x0000, 0x0000, 0x0000 }, /* R5390 */ + { 0x0000, 0x0000, 0x0000 }, /* R5391 */ + { 0x0000, 0x0000, 0x0000 }, /* R5392 */ + { 0x0000, 0x0000, 0x0000 }, /* R5393 */ + { 0x0000, 0x0000, 0x0000 }, /* R5394 */ + { 0x0000, 0x0000, 0x0000 }, /* R5395 */ + { 0x0000, 0x0000, 0x0000 }, /* R5396 */ + { 0x0000, 0x0000, 0x0000 }, /* R5397 */ + { 0x0000, 0x0000, 0x0000 }, /* R5398 */ + { 0x0000, 0x0000, 0x0000 }, /* R5399 */ + { 0x0000, 0x0000, 0x0000 }, /* R5400 */ + { 0x0000, 0x0000, 0x0000 }, /* R5401 */ + { 0x0000, 0x0000, 0x0000 }, /* R5402 */ + { 0x0000, 0x0000, 0x0000 }, /* R5403 */ + { 0x0000, 0x0000, 0x0000 }, /* R5404 */ + { 0x0000, 0x0000, 0x0000 }, /* R5405 */ + { 0x0000, 0x0000, 0x0000 }, /* R5406 */ + { 0x0000, 0x0000, 0x0000 }, /* R5407 */ + { 0x0000, 0x0000, 0x0000 }, /* R5408 */ + { 0x0000, 0x0000, 0x0000 }, /* R5409 */ + { 0x0000, 0x0000, 0x0000 }, /* R5410 */ + { 0x0000, 0x0000, 0x0000 }, /* R5411 */ + { 0x0000, 0x0000, 0x0000 }, /* R5412 */ + { 0x0000, 0x0000, 0x0000 }, /* R5413 */ + { 0x0000, 0x0000, 0x0000 }, /* R5414 */ + { 0x0000, 0x0000, 0x0000 }, /* R5415 */ + { 0x0000, 0x0000, 0x0000 }, /* R5416 */ + { 0x0000, 0x0000, 0x0000 }, /* R5417 */ + { 0x0000, 0x0000, 0x0000 }, /* R5418 */ + { 0x0000, 0x0000, 0x0000 }, /* R5419 */ + { 0x0000, 0x0000, 0x0000 }, /* R5420 */ + { 0x0000, 0x0000, 0x0000 }, /* R5421 */ + { 0x0000, 0x0000, 0x0000 }, /* R5422 */ + { 0x0000, 0x0000, 0x0000 }, /* R5423 */ + { 0x0000, 0x0000, 0x0000 }, /* R5424 */ + { 0x0000, 0x0000, 0x0000 }, /* R5425 */ + { 0x0000, 0x0000, 0x0000 }, /* R5426 */ + { 0x0000, 0x0000, 0x0000 }, /* R5427 */ + { 0x0000, 0x0000, 0x0000 }, /* R5428 */ + { 0x0000, 0x0000, 0x0000 }, /* R5429 */ + { 0x0000, 0x0000, 0x0000 }, /* R5430 */ + { 0x0000, 0x0000, 0x0000 }, /* R5431 */ + { 0x0000, 0x0000, 0x0000 }, /* R5432 */ + { 0x0000, 0x0000, 0x0000 }, /* R5433 */ + { 0x0000, 0x0000, 0x0000 }, /* R5434 */ + { 0x0000, 0x0000, 0x0000 }, /* R5435 */ + { 0x0000, 0x0000, 0x0000 }, /* R5436 */ + { 0x0000, 0x0000, 0x0000 }, /* R5437 */ + { 0x0000, 0x0000, 0x0000 }, /* R5438 */ + { 0x0000, 0x0000, 0x0000 }, /* R5439 */ + { 0x0000, 0x0000, 0x0000 }, /* R5440 */ + { 0x0000, 0x0000, 0x0000 }, /* R5441 */ + { 0x0000, 0x0000, 0x0000 }, /* R5442 */ + { 0x0000, 0x0000, 0x0000 }, /* R5443 */ + { 0x0000, 0x0000, 0x0000 }, /* R5444 */ + { 0x0000, 0x0000, 0x0000 }, /* R5445 */ + { 0x0000, 0x0000, 0x0000 }, /* R5446 */ + { 0x0000, 0x0000, 0x0000 }, /* R5447 */ + { 0x0000, 0x0000, 0x0000 }, /* R5448 */ + { 0x0000, 0x0000, 0x0000 }, /* R5449 */ + { 0x0000, 0x0000, 0x0000 }, /* R5450 */ + { 0x0000, 0x0000, 0x0000 }, /* R5451 */ + { 0x0000, 0x0000, 0x0000 }, /* R5452 */ + { 0x0000, 0x0000, 0x0000 }, /* R5453 */ + { 0x0000, 0x0000, 0x0000 }, /* R5454 */ + { 0x0000, 0x0000, 0x0000 }, /* R5455 */ + { 0x0000, 0x0000, 0x0000 }, /* R5456 */ + { 0x0000, 0x0000, 0x0000 }, /* R5457 */ + { 0x0000, 0x0000, 0x0000 }, /* R5458 */ + { 0x0000, 0x0000, 0x0000 }, /* R5459 */ + { 0x0000, 0x0000, 0x0000 }, /* R5460 */ + { 0x0000, 0x0000, 0x0000 }, /* R5461 */ + { 0x0000, 0x0000, 0x0000 }, /* R5462 */ + { 0x0000, 0x0000, 0x0000 }, /* R5463 */ + { 0x0000, 0x0000, 0x0000 }, /* R5464 */ + { 0x0000, 0x0000, 0x0000 }, /* R5465 */ + { 0x0000, 0x0000, 0x0000 }, /* R5466 */ + { 0x0000, 0x0000, 0x0000 }, /* R5467 */ + { 0x0000, 0x0000, 0x0000 }, /* R5468 */ + { 0x0000, 0x0000, 0x0000 }, /* R5469 */ + { 0x0000, 0x0000, 0x0000 }, /* R5470 */ + { 0x0000, 0x0000, 0x0000 }, /* R5471 */ + { 0x0000, 0x0000, 0x0000 }, /* R5472 */ + { 0x0000, 0x0000, 0x0000 }, /* R5473 */ + { 0x0000, 0x0000, 0x0000 }, /* R5474 */ + { 0x0000, 0x0000, 0x0000 }, /* R5475 */ + { 0x0000, 0x0000, 0x0000 }, /* R5476 */ + { 0x0000, 0x0000, 0x0000 }, /* R5477 */ + { 0x0000, 0x0000, 0x0000 }, /* R5478 */ + { 0x0000, 0x0000, 0x0000 }, /* R5479 */ + { 0x0000, 0x0000, 0x0000 }, /* R5480 */ + { 0x0000, 0x0000, 0x0000 }, /* R5481 */ + { 0x0000, 0x0000, 0x0000 }, /* R5482 */ + { 0x0000, 0x0000, 0x0000 }, /* R5483 */ + { 0x0000, 0x0000, 0x0000 }, /* R5484 */ + { 0x0000, 0x0000, 0x0000 }, /* R5485 */ + { 0x0000, 0x0000, 0x0000 }, /* R5486 */ + { 0x0000, 0x0000, 0x0000 }, /* R5487 */ + { 0x0000, 0x0000, 0x0000 }, /* R5488 */ + { 0x0000, 0x0000, 0x0000 }, /* R5489 */ + { 0x0000, 0x0000, 0x0000 }, /* R5490 */ + { 0x0000, 0x0000, 0x0000 }, /* R5491 */ + { 0x0000, 0x0000, 0x0000 }, /* R5492 */ + { 0x0000, 0x0000, 0x0000 }, /* R5493 */ + { 0x0000, 0x0000, 0x0000 }, /* R5494 */ + { 0x0000, 0x0000, 0x0000 }, /* R5495 */ + { 0x0000, 0x0000, 0x0000 }, /* R5496 */ + { 0x0000, 0x0000, 0x0000 }, /* R5497 */ + { 0x0000, 0x0000, 0x0000 }, /* R5498 */ + { 0x0000, 0x0000, 0x0000 }, /* R5499 */ + { 0x0000, 0x0000, 0x0000 }, /* R5500 */ + { 0x0000, 0x0000, 0x0000 }, /* R5501 */ + { 0x0000, 0x0000, 0x0000 }, /* R5502 */ + { 0x0000, 0x0000, 0x0000 }, /* R5503 */ + { 0x0000, 0x0000, 0x0000 }, /* R5504 */ + { 0x0000, 0x0000, 0x0000 }, /* R5505 */ + { 0x0000, 0x0000, 0x0000 }, /* R5506 */ + { 0x0000, 0x0000, 0x0000 }, /* R5507 */ + { 0x0000, 0x0000, 0x0000 }, /* R5508 */ + { 0x0000, 0x0000, 0x0000 }, /* R5509 */ + { 0x0000, 0x0000, 0x0000 }, /* R5510 */ + { 0x0000, 0x0000, 0x0000 }, /* R5511 */ + { 0x0000, 0x0000, 0x0000 }, /* R5512 */ + { 0x0000, 0x0000, 0x0000 }, /* R5513 */ + { 0x0000, 0x0000, 0x0000 }, /* R5514 */ + { 0x0000, 0x0000, 0x0000 }, /* R5515 */ + { 0x0000, 0x0000, 0x0000 }, /* R5516 */ + { 0x0000, 0x0000, 0x0000 }, /* R5517 */ + { 0x0000, 0x0000, 0x0000 }, /* R5518 */ + { 0x0000, 0x0000, 0x0000 }, /* R5519 */ + { 0x0000, 0x0000, 0x0000 }, /* R5520 */ + { 0x0000, 0x0000, 0x0000 }, /* R5521 */ + { 0x0000, 0x0000, 0x0000 }, /* R5522 */ + { 0x0000, 0x0000, 0x0000 }, /* R5523 */ + { 0x0000, 0x0000, 0x0000 }, /* R5524 */ + { 0x0000, 0x0000, 0x0000 }, /* R5525 */ + { 0x0000, 0x0000, 0x0000 }, /* R5526 */ + { 0x0000, 0x0000, 0x0000 }, /* R5527 */ + { 0x0000, 0x0000, 0x0000 }, /* R5528 */ + { 0x0000, 0x0000, 0x0000 }, /* R5529 */ + { 0x0000, 0x0000, 0x0000 }, /* R5530 */ + { 0x0000, 0x0000, 0x0000 }, /* R5531 */ + { 0x0000, 0x0000, 0x0000 }, /* R5532 */ + { 0x0000, 0x0000, 0x0000 }, /* R5533 */ + { 0x0000, 0x0000, 0x0000 }, /* R5534 */ + { 0x0000, 0x0000, 0x0000 }, /* R5535 */ + { 0x0000, 0x0000, 0x0000 }, /* R5536 */ + { 0x0000, 0x0000, 0x0000 }, /* R5537 */ + { 0x0000, 0x0000, 0x0000 }, /* R5538 */ + { 0x0000, 0x0000, 0x0000 }, /* R5539 */ + { 0x0000, 0x0000, 0x0000 }, /* R5540 */ + { 0x0000, 0x0000, 0x0000 }, /* R5541 */ + { 0x0000, 0x0000, 0x0000 }, /* R5542 */ + { 0x0000, 0x0000, 0x0000 }, /* R5543 */ + { 0x0000, 0x0000, 0x0000 }, /* R5544 */ + { 0x0000, 0x0000, 0x0000 }, /* R5545 */ + { 0x0000, 0x0000, 0x0000 }, /* R5546 */ + { 0x0000, 0x0000, 0x0000 }, /* R5547 */ + { 0x0000, 0x0000, 0x0000 }, /* R5548 */ + { 0x0000, 0x0000, 0x0000 }, /* R5549 */ + { 0x0000, 0x0000, 0x0000 }, /* R5550 */ + { 0x0000, 0x0000, 0x0000 }, /* R5551 */ + { 0x0000, 0x0000, 0x0000 }, /* R5552 */ + { 0x0000, 0x0000, 0x0000 }, /* R5553 */ + { 0x0000, 0x0000, 0x0000 }, /* R5554 */ + { 0x0000, 0x0000, 0x0000 }, /* R5555 */ + { 0x0000, 0x0000, 0x0000 }, /* R5556 */ + { 0x0000, 0x0000, 0x0000 }, /* R5557 */ + { 0x0000, 0x0000, 0x0000 }, /* R5558 */ + { 0x0000, 0x0000, 0x0000 }, /* R5559 */ + { 0x0000, 0x0000, 0x0000 }, /* R5560 */ + { 0x0000, 0x0000, 0x0000 }, /* R5561 */ + { 0x0000, 0x0000, 0x0000 }, /* R5562 */ + { 0x0000, 0x0000, 0x0000 }, /* R5563 */ + { 0x0000, 0x0000, 0x0000 }, /* R5564 */ + { 0x0000, 0x0000, 0x0000 }, /* R5565 */ + { 0x0000, 0x0000, 0x0000 }, /* R5566 */ + { 0x0000, 0x0000, 0x0000 }, /* R5567 */ + { 0x0000, 0x0000, 0x0000 }, /* R5568 */ + { 0x0000, 0x0000, 0x0000 }, /* R5569 */ + { 0x0000, 0x0000, 0x0000 }, /* R5570 */ + { 0x0000, 0x0000, 0x0000 }, /* R5571 */ + { 0x0000, 0x0000, 0x0000 }, /* R5572 */ + { 0x0000, 0x0000, 0x0000 }, /* R5573 */ + { 0x0000, 0x0000, 0x0000 }, /* R5574 */ + { 0x0000, 0x0000, 0x0000 }, /* R5575 */ + { 0x0000, 0x0000, 0x0000 }, /* R5576 */ + { 0x0000, 0x0000, 0x0000 }, /* R5577 */ + { 0x0000, 0x0000, 0x0000 }, /* R5578 */ + { 0x0000, 0x0000, 0x0000 }, /* R5579 */ + { 0x0000, 0x0000, 0x0000 }, /* R5580 */ + { 0x0000, 0x0000, 0x0000 }, /* R5581 */ + { 0x0000, 0x0000, 0x0000 }, /* R5582 */ + { 0x0000, 0x0000, 0x0000 }, /* R5583 */ + { 0x0000, 0x0000, 0x0000 }, /* R5584 */ + { 0x0000, 0x0000, 0x0000 }, /* R5585 */ + { 0x0000, 0x0000, 0x0000 }, /* R5586 */ + { 0x0000, 0x0000, 0x0000 }, /* R5587 */ + { 0x0000, 0x0000, 0x0000 }, /* R5588 */ + { 0x0000, 0x0000, 0x0000 }, /* R5589 */ + { 0x0000, 0x0000, 0x0000 }, /* R5590 */ + { 0x0000, 0x0000, 0x0000 }, /* R5591 */ + { 0x0000, 0x0000, 0x0000 }, /* R5592 */ + { 0x0000, 0x0000, 0x0000 }, /* R5593 */ + { 0x0000, 0x0000, 0x0000 }, /* R5594 */ + { 0x0000, 0x0000, 0x0000 }, /* R5595 */ + { 0x0000, 0x0000, 0x0000 }, /* R5596 */ + { 0x0000, 0x0000, 0x0000 }, /* R5597 */ + { 0x0000, 0x0000, 0x0000 }, /* R5598 */ + { 0x0000, 0x0000, 0x0000 }, /* R5599 */ + { 0x0000, 0x0000, 0x0000 }, /* R5600 */ + { 0x0000, 0x0000, 0x0000 }, /* R5601 */ + { 0x0000, 0x0000, 0x0000 }, /* R5602 */ + { 0x0000, 0x0000, 0x0000 }, /* R5603 */ + { 0x0000, 0x0000, 0x0000 }, /* R5604 */ + { 0x0000, 0x0000, 0x0000 }, /* R5605 */ + { 0x0000, 0x0000, 0x0000 }, /* R5606 */ + { 0x0000, 0x0000, 0x0000 }, /* R5607 */ + { 0x0000, 0x0000, 0x0000 }, /* R5608 */ + { 0x0000, 0x0000, 0x0000 }, /* R5609 */ + { 0x0000, 0x0000, 0x0000 }, /* R5610 */ + { 0x0000, 0x0000, 0x0000 }, /* R5611 */ + { 0x0000, 0x0000, 0x0000 }, /* R5612 */ + { 0x0000, 0x0000, 0x0000 }, /* R5613 */ + { 0x0000, 0x0000, 0x0000 }, /* R5614 */ + { 0x0000, 0x0000, 0x0000 }, /* R5615 */ + { 0x0000, 0x0000, 0x0000 }, /* R5616 */ + { 0x0000, 0x0000, 0x0000 }, /* R5617 */ + { 0x0000, 0x0000, 0x0000 }, /* R5618 */ + { 0x0000, 0x0000, 0x0000 }, /* R5619 */ + { 0x0000, 0x0000, 0x0000 }, /* R5620 */ + { 0x0000, 0x0000, 0x0000 }, /* R5621 */ + { 0x0000, 0x0000, 0x0000 }, /* R5622 */ + { 0x0000, 0x0000, 0x0000 }, /* R5623 */ + { 0x0000, 0x0000, 0x0000 }, /* R5624 */ + { 0x0000, 0x0000, 0x0000 }, /* R5625 */ + { 0x0000, 0x0000, 0x0000 }, /* R5626 */ + { 0x0000, 0x0000, 0x0000 }, /* R5627 */ + { 0x0000, 0x0000, 0x0000 }, /* R5628 */ + { 0x0000, 0x0000, 0x0000 }, /* R5629 */ + { 0x0000, 0x0000, 0x0000 }, /* R5630 */ + { 0x0000, 0x0000, 0x0000 }, /* R5631 */ + { 0x0000, 0x0000, 0x0000 }, /* R5632 */ + { 0x0000, 0x0000, 0x0000 }, /* R5633 */ + { 0x0000, 0x0000, 0x0000 }, /* R5634 */ + { 0x0000, 0x0000, 0x0000 }, /* R5635 */ + { 0x0000, 0x0000, 0x0000 }, /* R5636 */ + { 0x0000, 0x0000, 0x0000 }, /* R5637 */ + { 0x0000, 0x0000, 0x0000 }, /* R5638 */ + { 0x0000, 0x0000, 0x0000 }, /* R5639 */ + { 0x0000, 0x0000, 0x0000 }, /* R5640 */ + { 0x0000, 0x0000, 0x0000 }, /* R5641 */ + { 0x0000, 0x0000, 0x0000 }, /* R5642 */ + { 0x0000, 0x0000, 0x0000 }, /* R5643 */ + { 0x0000, 0x0000, 0x0000 }, /* R5644 */ + { 0x0000, 0x0000, 0x0000 }, /* R5645 */ + { 0x0000, 0x0000, 0x0000 }, /* R5646 */ + { 0x0000, 0x0000, 0x0000 }, /* R5647 */ + { 0x0000, 0x0000, 0x0000 }, /* R5648 */ + { 0x0000, 0x0000, 0x0000 }, /* R5649 */ + { 0x0000, 0x0000, 0x0000 }, /* R5650 */ + { 0x0000, 0x0000, 0x0000 }, /* R5651 */ + { 0x0000, 0x0000, 0x0000 }, /* R5652 */ + { 0x0000, 0x0000, 0x0000 }, /* R5653 */ + { 0x0000, 0x0000, 0x0000 }, /* R5654 */ + { 0x0000, 0x0000, 0x0000 }, /* R5655 */ + { 0x0000, 0x0000, 0x0000 }, /* R5656 */ + { 0x0000, 0x0000, 0x0000 }, /* R5657 */ + { 0x0000, 0x0000, 0x0000 }, /* R5658 */ + { 0x0000, 0x0000, 0x0000 }, /* R5659 */ + { 0x0000, 0x0000, 0x0000 }, /* R5660 */ + { 0x0000, 0x0000, 0x0000 }, /* R5661 */ + { 0x0000, 0x0000, 0x0000 }, /* R5662 */ + { 0x0000, 0x0000, 0x0000 }, /* R5663 */ + { 0x0000, 0x0000, 0x0000 }, /* R5664 */ + { 0x0000, 0x0000, 0x0000 }, /* R5665 */ + { 0x0000, 0x0000, 0x0000 }, /* R5666 */ + { 0x0000, 0x0000, 0x0000 }, /* R5667 */ + { 0x0000, 0x0000, 0x0000 }, /* R5668 */ + { 0x0000, 0x0000, 0x0000 }, /* R5669 */ + { 0x0000, 0x0000, 0x0000 }, /* R5670 */ + { 0x0000, 0x0000, 0x0000 }, /* R5671 */ + { 0x0000, 0x0000, 0x0000 }, /* R5672 */ + { 0x0000, 0x0000, 0x0000 }, /* R5673 */ + { 0x0000, 0x0000, 0x0000 }, /* R5674 */ + { 0x0000, 0x0000, 0x0000 }, /* R5675 */ + { 0x0000, 0x0000, 0x0000 }, /* R5676 */ + { 0x0000, 0x0000, 0x0000 }, /* R5677 */ + { 0x0000, 0x0000, 0x0000 }, /* R5678 */ + { 0x0000, 0x0000, 0x0000 }, /* R5679 */ + { 0x0000, 0x0000, 0x0000 }, /* R5680 */ + { 0x0000, 0x0000, 0x0000 }, /* R5681 */ + { 0x0000, 0x0000, 0x0000 }, /* R5682 */ + { 0x0000, 0x0000, 0x0000 }, /* R5683 */ + { 0x0000, 0x0000, 0x0000 }, /* R5684 */ + { 0x0000, 0x0000, 0x0000 }, /* R5685 */ + { 0x0000, 0x0000, 0x0000 }, /* R5686 */ + { 0x0000, 0x0000, 0x0000 }, /* R5687 */ + { 0x0000, 0x0000, 0x0000 }, /* R5688 */ + { 0x0000, 0x0000, 0x0000 }, /* R5689 */ + { 0x0000, 0x0000, 0x0000 }, /* R5690 */ + { 0x0000, 0x0000, 0x0000 }, /* R5691 */ + { 0x0000, 0x0000, 0x0000 }, /* R5692 */ + { 0x0000, 0x0000, 0x0000 }, /* R5693 */ + { 0x0000, 0x0000, 0x0000 }, /* R5694 */ + { 0x0000, 0x0000, 0x0000 }, /* R5695 */ + { 0x0000, 0x0000, 0x0000 }, /* R5696 */ + { 0x0000, 0x0000, 0x0000 }, /* R5697 */ + { 0x0000, 0x0000, 0x0000 }, /* R5698 */ + { 0x0000, 0x0000, 0x0000 }, /* R5699 */ + { 0x0000, 0x0000, 0x0000 }, /* R5700 */ + { 0x0000, 0x0000, 0x0000 }, /* R5701 */ + { 0x0000, 0x0000, 0x0000 }, /* R5702 */ + { 0x0000, 0x0000, 0x0000 }, /* R5703 */ + { 0x0000, 0x0000, 0x0000 }, /* R5704 */ + { 0x0000, 0x0000, 0x0000 }, /* R5705 */ + { 0x0000, 0x0000, 0x0000 }, /* R5706 */ + { 0x0000, 0x0000, 0x0000 }, /* R5707 */ + { 0x0000, 0x0000, 0x0000 }, /* R5708 */ + { 0x0000, 0x0000, 0x0000 }, /* R5709 */ + { 0x0000, 0x0000, 0x0000 }, /* R5710 */ + { 0x0000, 0x0000, 0x0000 }, /* R5711 */ + { 0x0000, 0x0000, 0x0000 }, /* R5712 */ + { 0x0000, 0x0000, 0x0000 }, /* R5713 */ + { 0x0000, 0x0000, 0x0000 }, /* R5714 */ + { 0x0000, 0x0000, 0x0000 }, /* R5715 */ + { 0x0000, 0x0000, 0x0000 }, /* R5716 */ + { 0x0000, 0x0000, 0x0000 }, /* R5717 */ + { 0x0000, 0x0000, 0x0000 }, /* R5718 */ + { 0x0000, 0x0000, 0x0000 }, /* R5719 */ + { 0x0000, 0x0000, 0x0000 }, /* R5720 */ + { 0x0000, 0x0000, 0x0000 }, /* R5721 */ + { 0x0000, 0x0000, 0x0000 }, /* R5722 */ + { 0x0000, 0x0000, 0x0000 }, /* R5723 */ + { 0x0000, 0x0000, 0x0000 }, /* R5724 */ + { 0x0000, 0x0000, 0x0000 }, /* R5725 */ + { 0x0000, 0x0000, 0x0000 }, /* R5726 */ + { 0x0000, 0x0000, 0x0000 }, /* R5727 */ + { 0x0000, 0x0000, 0x0000 }, /* R5728 */ + { 0x0000, 0x0000, 0x0000 }, /* R5729 */ + { 0x0000, 0x0000, 0x0000 }, /* R5730 */ + { 0x0000, 0x0000, 0x0000 }, /* R5731 */ + { 0x0000, 0x0000, 0x0000 }, /* R5732 */ + { 0x0000, 0x0000, 0x0000 }, /* R5733 */ + { 0x0000, 0x0000, 0x0000 }, /* R5734 */ + { 0x0000, 0x0000, 0x0000 }, /* R5735 */ + { 0x0000, 0x0000, 0x0000 }, /* R5736 */ + { 0x0000, 0x0000, 0x0000 }, /* R5737 */ + { 0x0000, 0x0000, 0x0000 }, /* R5738 */ + { 0x0000, 0x0000, 0x0000 }, /* R5739 */ + { 0x0000, 0x0000, 0x0000 }, /* R5740 */ + { 0x0000, 0x0000, 0x0000 }, /* R5741 */ + { 0x0000, 0x0000, 0x0000 }, /* R5742 */ + { 0x0000, 0x0000, 0x0000 }, /* R5743 */ + { 0x0000, 0x0000, 0x0000 }, /* R5744 */ + { 0x0000, 0x0000, 0x0000 }, /* R5745 */ + { 0x0000, 0x0000, 0x0000 }, /* R5746 */ + { 0x0000, 0x0000, 0x0000 }, /* R5747 */ + { 0x0000, 0x0000, 0x0000 }, /* R5748 */ + { 0x0000, 0x0000, 0x0000 }, /* R5749 */ + { 0x0000, 0x0000, 0x0000 }, /* R5750 */ + { 0x0000, 0x0000, 0x0000 }, /* R5751 */ + { 0x0000, 0x0000, 0x0000 }, /* R5752 */ + { 0x0000, 0x0000, 0x0000 }, /* R5753 */ + { 0x0000, 0x0000, 0x0000 }, /* R5754 */ + { 0x0000, 0x0000, 0x0000 }, /* R5755 */ + { 0x0000, 0x0000, 0x0000 }, /* R5756 */ + { 0x0000, 0x0000, 0x0000 }, /* R5757 */ + { 0x0000, 0x0000, 0x0000 }, /* R5758 */ + { 0x0000, 0x0000, 0x0000 }, /* R5759 */ + { 0x0000, 0x0000, 0x0000 }, /* R5760 */ + { 0x0000, 0x0000, 0x0000 }, /* R5761 */ + { 0x0000, 0x0000, 0x0000 }, /* R5762 */ + { 0x0000, 0x0000, 0x0000 }, /* R5763 */ + { 0x0000, 0x0000, 0x0000 }, /* R5764 */ + { 0x0000, 0x0000, 0x0000 }, /* R5765 */ + { 0x0000, 0x0000, 0x0000 }, /* R5766 */ + { 0x0000, 0x0000, 0x0000 }, /* R5767 */ + { 0x0000, 0x0000, 0x0000 }, /* R5768 */ + { 0x0000, 0x0000, 0x0000 }, /* R5769 */ + { 0x0000, 0x0000, 0x0000 }, /* R5770 */ + { 0x0000, 0x0000, 0x0000 }, /* R5771 */ + { 0x0000, 0x0000, 0x0000 }, /* R5772 */ + { 0x0000, 0x0000, 0x0000 }, /* R5773 */ + { 0x0000, 0x0000, 0x0000 }, /* R5774 */ + { 0x0000, 0x0000, 0x0000 }, /* R5775 */ + { 0x0000, 0x0000, 0x0000 }, /* R5776 */ + { 0x0000, 0x0000, 0x0000 }, /* R5777 */ + { 0x0000, 0x0000, 0x0000 }, /* R5778 */ + { 0x0000, 0x0000, 0x0000 }, /* R5779 */ + { 0x0000, 0x0000, 0x0000 }, /* R5780 */ + { 0x0000, 0x0000, 0x0000 }, /* R5781 */ + { 0x0000, 0x0000, 0x0000 }, /* R5782 */ + { 0x0000, 0x0000, 0x0000 }, /* R5783 */ + { 0x0000, 0x0000, 0x0000 }, /* R5784 */ + { 0x0000, 0x0000, 0x0000 }, /* R5785 */ + { 0x0000, 0x0000, 0x0000 }, /* R5786 */ + { 0x0000, 0x0000, 0x0000 }, /* R5787 */ + { 0x0000, 0x0000, 0x0000 }, /* R5788 */ + { 0x0000, 0x0000, 0x0000 }, /* R5789 */ + { 0x0000, 0x0000, 0x0000 }, /* R5790 */ + { 0x0000, 0x0000, 0x0000 }, /* R5791 */ + { 0x0000, 0x0000, 0x0000 }, /* R5792 */ + { 0x0000, 0x0000, 0x0000 }, /* R5793 */ + { 0x0000, 0x0000, 0x0000 }, /* R5794 */ + { 0x0000, 0x0000, 0x0000 }, /* R5795 */ + { 0x0000, 0x0000, 0x0000 }, /* R5796 */ + { 0x0000, 0x0000, 0x0000 }, /* R5797 */ + { 0x0000, 0x0000, 0x0000 }, /* R5798 */ + { 0x0000, 0x0000, 0x0000 }, /* R5799 */ + { 0x0000, 0x0000, 0x0000 }, /* R5800 */ + { 0x0000, 0x0000, 0x0000 }, /* R5801 */ + { 0x0000, 0x0000, 0x0000 }, /* R5802 */ + { 0x0000, 0x0000, 0x0000 }, /* R5803 */ + { 0x0000, 0x0000, 0x0000 }, /* R5804 */ + { 0x0000, 0x0000, 0x0000 }, /* R5805 */ + { 0x0000, 0x0000, 0x0000 }, /* R5806 */ + { 0x0000, 0x0000, 0x0000 }, /* R5807 */ + { 0x0000, 0x0000, 0x0000 }, /* R5808 */ + { 0x0000, 0x0000, 0x0000 }, /* R5809 */ + { 0x0000, 0x0000, 0x0000 }, /* R5810 */ + { 0x0000, 0x0000, 0x0000 }, /* R5811 */ + { 0x0000, 0x0000, 0x0000 }, /* R5812 */ + { 0x0000, 0x0000, 0x0000 }, /* R5813 */ + { 0x0000, 0x0000, 0x0000 }, /* R5814 */ + { 0x0000, 0x0000, 0x0000 }, /* R5815 */ + { 0x0000, 0x0000, 0x0000 }, /* R5816 */ + { 0x0000, 0x0000, 0x0000 }, /* R5817 */ + { 0x0000, 0x0000, 0x0000 }, /* R5818 */ + { 0x0000, 0x0000, 0x0000 }, /* R5819 */ + { 0x0000, 0x0000, 0x0000 }, /* R5820 */ + { 0x0000, 0x0000, 0x0000 }, /* R5821 */ + { 0x0000, 0x0000, 0x0000 }, /* R5822 */ + { 0x0000, 0x0000, 0x0000 }, /* R5823 */ + { 0x0000, 0x0000, 0x0000 }, /* R5824 */ + { 0x0000, 0x0000, 0x0000 }, /* R5825 */ + { 0x0000, 0x0000, 0x0000 }, /* R5826 */ + { 0x0000, 0x0000, 0x0000 }, /* R5827 */ + { 0x0000, 0x0000, 0x0000 }, /* R5828 */ + { 0x0000, 0x0000, 0x0000 }, /* R5829 */ + { 0x0000, 0x0000, 0x0000 }, /* R5830 */ + { 0x0000, 0x0000, 0x0000 }, /* R5831 */ + { 0x0000, 0x0000, 0x0000 }, /* R5832 */ + { 0x0000, 0x0000, 0x0000 }, /* R5833 */ + { 0x0000, 0x0000, 0x0000 }, /* R5834 */ + { 0x0000, 0x0000, 0x0000 }, /* R5835 */ + { 0x0000, 0x0000, 0x0000 }, /* R5836 */ + { 0x0000, 0x0000, 0x0000 }, /* R5837 */ + { 0x0000, 0x0000, 0x0000 }, /* R5838 */ + { 0x0000, 0x0000, 0x0000 }, /* R5839 */ + { 0x0000, 0x0000, 0x0000 }, /* R5840 */ + { 0x0000, 0x0000, 0x0000 }, /* R5841 */ + { 0x0000, 0x0000, 0x0000 }, /* R5842 */ + { 0x0000, 0x0000, 0x0000 }, /* R5843 */ + { 0x0000, 0x0000, 0x0000 }, /* R5844 */ + { 0x0000, 0x0000, 0x0000 }, /* R5845 */ + { 0x0000, 0x0000, 0x0000 }, /* R5846 */ + { 0x0000, 0x0000, 0x0000 }, /* R5847 */ + { 0x0000, 0x0000, 0x0000 }, /* R5848 */ + { 0x0000, 0x0000, 0x0000 }, /* R5849 */ + { 0x0000, 0x0000, 0x0000 }, /* R5850 */ + { 0x0000, 0x0000, 0x0000 }, /* R5851 */ + { 0x0000, 0x0000, 0x0000 }, /* R5852 */ + { 0x0000, 0x0000, 0x0000 }, /* R5853 */ + { 0x0000, 0x0000, 0x0000 }, /* R5854 */ + { 0x0000, 0x0000, 0x0000 }, /* R5855 */ + { 0x0000, 0x0000, 0x0000 }, /* R5856 */ + { 0x0000, 0x0000, 0x0000 }, /* R5857 */ + { 0x0000, 0x0000, 0x0000 }, /* R5858 */ + { 0x0000, 0x0000, 0x0000 }, /* R5859 */ + { 0x0000, 0x0000, 0x0000 }, /* R5860 */ + { 0x0000, 0x0000, 0x0000 }, /* R5861 */ + { 0x0000, 0x0000, 0x0000 }, /* R5862 */ + { 0x0000, 0x0000, 0x0000 }, /* R5863 */ + { 0x0000, 0x0000, 0x0000 }, /* R5864 */ + { 0x0000, 0x0000, 0x0000 }, /* R5865 */ + { 0x0000, 0x0000, 0x0000 }, /* R5866 */ + { 0x0000, 0x0000, 0x0000 }, /* R5867 */ + { 0x0000, 0x0000, 0x0000 }, /* R5868 */ + { 0x0000, 0x0000, 0x0000 }, /* R5869 */ + { 0x0000, 0x0000, 0x0000 }, /* R5870 */ + { 0x0000, 0x0000, 0x0000 }, /* R5871 */ + { 0x0000, 0x0000, 0x0000 }, /* R5872 */ + { 0x0000, 0x0000, 0x0000 }, /* R5873 */ + { 0x0000, 0x0000, 0x0000 }, /* R5874 */ + { 0x0000, 0x0000, 0x0000 }, /* R5875 */ + { 0x0000, 0x0000, 0x0000 }, /* R5876 */ + { 0x0000, 0x0000, 0x0000 }, /* R5877 */ + { 0x0000, 0x0000, 0x0000 }, /* R5878 */ + { 0x0000, 0x0000, 0x0000 }, /* R5879 */ + { 0x0000, 0x0000, 0x0000 }, /* R5880 */ + { 0x0000, 0x0000, 0x0000 }, /* R5881 */ + { 0x0000, 0x0000, 0x0000 }, /* R5882 */ + { 0x0000, 0x0000, 0x0000 }, /* R5883 */ + { 0x0000, 0x0000, 0x0000 }, /* R5884 */ + { 0x0000, 0x0000, 0x0000 }, /* R5885 */ + { 0x0000, 0x0000, 0x0000 }, /* R5886 */ + { 0x0000, 0x0000, 0x0000 }, /* R5887 */ + { 0x0000, 0x0000, 0x0000 }, /* R5888 */ + { 0x0000, 0x0000, 0x0000 }, /* R5889 */ + { 0x0000, 0x0000, 0x0000 }, /* R5890 */ + { 0x0000, 0x0000, 0x0000 }, /* R5891 */ + { 0x0000, 0x0000, 0x0000 }, /* R5892 */ + { 0x0000, 0x0000, 0x0000 }, /* R5893 */ + { 0x0000, 0x0000, 0x0000 }, /* R5894 */ + { 0x0000, 0x0000, 0x0000 }, /* R5895 */ + { 0x0000, 0x0000, 0x0000 }, /* R5896 */ + { 0x0000, 0x0000, 0x0000 }, /* R5897 */ + { 0x0000, 0x0000, 0x0000 }, /* R5898 */ + { 0x0000, 0x0000, 0x0000 }, /* R5899 */ + { 0x0000, 0x0000, 0x0000 }, /* R5900 */ + { 0x0000, 0x0000, 0x0000 }, /* R5901 */ + { 0x0000, 0x0000, 0x0000 }, /* R5902 */ + { 0x0000, 0x0000, 0x0000 }, /* R5903 */ + { 0x0000, 0x0000, 0x0000 }, /* R5904 */ + { 0x0000, 0x0000, 0x0000 }, /* R5905 */ + { 0x0000, 0x0000, 0x0000 }, /* R5906 */ + { 0x0000, 0x0000, 0x0000 }, /* R5907 */ + { 0x0000, 0x0000, 0x0000 }, /* R5908 */ + { 0x0000, 0x0000, 0x0000 }, /* R5909 */ + { 0x0000, 0x0000, 0x0000 }, /* R5910 */ + { 0x0000, 0x0000, 0x0000 }, /* R5911 */ + { 0x0000, 0x0000, 0x0000 }, /* R5912 */ + { 0x0000, 0x0000, 0x0000 }, /* R5913 */ + { 0x0000, 0x0000, 0x0000 }, /* R5914 */ + { 0x0000, 0x0000, 0x0000 }, /* R5915 */ + { 0x0000, 0x0000, 0x0000 }, /* R5916 */ + { 0x0000, 0x0000, 0x0000 }, /* R5917 */ + { 0x0000, 0x0000, 0x0000 }, /* R5918 */ + { 0x0000, 0x0000, 0x0000 }, /* R5919 */ + { 0x0000, 0x0000, 0x0000 }, /* R5920 */ + { 0x0000, 0x0000, 0x0000 }, /* R5921 */ + { 0x0000, 0x0000, 0x0000 }, /* R5922 */ + { 0x0000, 0x0000, 0x0000 }, /* R5923 */ + { 0x0000, 0x0000, 0x0000 }, /* R5924 */ + { 0x0000, 0x0000, 0x0000 }, /* R5925 */ + { 0x0000, 0x0000, 0x0000 }, /* R5926 */ + { 0x0000, 0x0000, 0x0000 }, /* R5927 */ + { 0x0000, 0x0000, 0x0000 }, /* R5928 */ + { 0x0000, 0x0000, 0x0000 }, /* R5929 */ + { 0x0000, 0x0000, 0x0000 }, /* R5930 */ + { 0x0000, 0x0000, 0x0000 }, /* R5931 */ + { 0x0000, 0x0000, 0x0000 }, /* R5932 */ + { 0x0000, 0x0000, 0x0000 }, /* R5933 */ + { 0x0000, 0x0000, 0x0000 }, /* R5934 */ + { 0x0000, 0x0000, 0x0000 }, /* R5935 */ + { 0x0000, 0x0000, 0x0000 }, /* R5936 */ + { 0x0000, 0x0000, 0x0000 }, /* R5937 */ + { 0x0000, 0x0000, 0x0000 }, /* R5938 */ + { 0x0000, 0x0000, 0x0000 }, /* R5939 */ + { 0x0000, 0x0000, 0x0000 }, /* R5940 */ + { 0x0000, 0x0000, 0x0000 }, /* R5941 */ + { 0x0000, 0x0000, 0x0000 }, /* R5942 */ + { 0x0000, 0x0000, 0x0000 }, /* R5943 */ + { 0x0000, 0x0000, 0x0000 }, /* R5944 */ + { 0x0000, 0x0000, 0x0000 }, /* R5945 */ + { 0x0000, 0x0000, 0x0000 }, /* R5946 */ + { 0x0000, 0x0000, 0x0000 }, /* R5947 */ + { 0x0000, 0x0000, 0x0000 }, /* R5948 */ + { 0x0000, 0x0000, 0x0000 }, /* R5949 */ + { 0x0000, 0x0000, 0x0000 }, /* R5950 */ + { 0x0000, 0x0000, 0x0000 }, /* R5951 */ + { 0x0000, 0x0000, 0x0000 }, /* R5952 */ + { 0x0000, 0x0000, 0x0000 }, /* R5953 */ + { 0x0000, 0x0000, 0x0000 }, /* R5954 */ + { 0x0000, 0x0000, 0x0000 }, /* R5955 */ + { 0x0000, 0x0000, 0x0000 }, /* R5956 */ + { 0x0000, 0x0000, 0x0000 }, /* R5957 */ + { 0x0000, 0x0000, 0x0000 }, /* R5958 */ + { 0x0000, 0x0000, 0x0000 }, /* R5959 */ + { 0x0000, 0x0000, 0x0000 }, /* R5960 */ + { 0x0000, 0x0000, 0x0000 }, /* R5961 */ + { 0x0000, 0x0000, 0x0000 }, /* R5962 */ + { 0x0000, 0x0000, 0x0000 }, /* R5963 */ + { 0x0000, 0x0000, 0x0000 }, /* R5964 */ + { 0x0000, 0x0000, 0x0000 }, /* R5965 */ + { 0x0000, 0x0000, 0x0000 }, /* R5966 */ + { 0x0000, 0x0000, 0x0000 }, /* R5967 */ + { 0x0000, 0x0000, 0x0000 }, /* R5968 */ + { 0x0000, 0x0000, 0x0000 }, /* R5969 */ + { 0x0000, 0x0000, 0x0000 }, /* R5970 */ + { 0x0000, 0x0000, 0x0000 }, /* R5971 */ + { 0x0000, 0x0000, 0x0000 }, /* R5972 */ + { 0x0000, 0x0000, 0x0000 }, /* R5973 */ + { 0x0000, 0x0000, 0x0000 }, /* R5974 */ + { 0x0000, 0x0000, 0x0000 }, /* R5975 */ + { 0x0000, 0x0000, 0x0000 }, /* R5976 */ + { 0x0000, 0x0000, 0x0000 }, /* R5977 */ + { 0x0000, 0x0000, 0x0000 }, /* R5978 */ + { 0x0000, 0x0000, 0x0000 }, /* R5979 */ + { 0x0000, 0x0000, 0x0000 }, /* R5980 */ + { 0x0000, 0x0000, 0x0000 }, /* R5981 */ + { 0x0000, 0x0000, 0x0000 }, /* R5982 */ + { 0x0000, 0x0000, 0x0000 }, /* R5983 */ + { 0x0000, 0x0000, 0x0000 }, /* R5984 */ + { 0x0000, 0x0000, 0x0000 }, /* R5985 */ + { 0x0000, 0x0000, 0x0000 }, /* R5986 */ + { 0x0000, 0x0000, 0x0000 }, /* R5987 */ + { 0x0000, 0x0000, 0x0000 }, /* R5988 */ + { 0x0000, 0x0000, 0x0000 }, /* R5989 */ + { 0x0000, 0x0000, 0x0000 }, /* R5990 */ + { 0x0000, 0x0000, 0x0000 }, /* R5991 */ + { 0x0000, 0x0000, 0x0000 }, /* R5992 */ + { 0x0000, 0x0000, 0x0000 }, /* R5993 */ + { 0x0000, 0x0000, 0x0000 }, /* R5994 */ + { 0x0000, 0x0000, 0x0000 }, /* R5995 */ + { 0x0000, 0x0000, 0x0000 }, /* R5996 */ + { 0x0000, 0x0000, 0x0000 }, /* R5997 */ + { 0x0000, 0x0000, 0x0000 }, /* R5998 */ + { 0x0000, 0x0000, 0x0000 }, /* R5999 */ + { 0x0000, 0x0000, 0x0000 }, /* R6000 */ + { 0x0000, 0x0000, 0x0000 }, /* R6001 */ + { 0x0000, 0x0000, 0x0000 }, /* R6002 */ + { 0x0000, 0x0000, 0x0000 }, /* R6003 */ + { 0x0000, 0x0000, 0x0000 }, /* R6004 */ + { 0x0000, 0x0000, 0x0000 }, /* R6005 */ + { 0x0000, 0x0000, 0x0000 }, /* R6006 */ + { 0x0000, 0x0000, 0x0000 }, /* R6007 */ + { 0x0000, 0x0000, 0x0000 }, /* R6008 */ + { 0x0000, 0x0000, 0x0000 }, /* R6009 */ + { 0x0000, 0x0000, 0x0000 }, /* R6010 */ + { 0x0000, 0x0000, 0x0000 }, /* R6011 */ + { 0x0000, 0x0000, 0x0000 }, /* R6012 */ + { 0x0000, 0x0000, 0x0000 }, /* R6013 */ + { 0x0000, 0x0000, 0x0000 }, /* R6014 */ + { 0x0000, 0x0000, 0x0000 }, /* R6015 */ + { 0x0000, 0x0000, 0x0000 }, /* R6016 */ + { 0x0000, 0x0000, 0x0000 }, /* R6017 */ + { 0x0000, 0x0000, 0x0000 }, /* R6018 */ + { 0x0000, 0x0000, 0x0000 }, /* R6019 */ + { 0x0000, 0x0000, 0x0000 }, /* R6020 */ + { 0x0000, 0x0000, 0x0000 }, /* R6021 */ + { 0x0000, 0x0000, 0x0000 }, /* R6022 */ + { 0x0000, 0x0000, 0x0000 }, /* R6023 */ + { 0x0000, 0x0000, 0x0000 }, /* R6024 */ + { 0x0000, 0x0000, 0x0000 }, /* R6025 */ + { 0x0000, 0x0000, 0x0000 }, /* R6026 */ + { 0x0000, 0x0000, 0x0000 }, /* R6027 */ + { 0x0000, 0x0000, 0x0000 }, /* R6028 */ + { 0x0000, 0x0000, 0x0000 }, /* R6029 */ + { 0x0000, 0x0000, 0x0000 }, /* R6030 */ + { 0x0000, 0x0000, 0x0000 }, /* R6031 */ + { 0x0000, 0x0000, 0x0000 }, /* R6032 */ + { 0x0000, 0x0000, 0x0000 }, /* R6033 */ + { 0x0000, 0x0000, 0x0000 }, /* R6034 */ + { 0x0000, 0x0000, 0x0000 }, /* R6035 */ + { 0x0000, 0x0000, 0x0000 }, /* R6036 */ + { 0x0000, 0x0000, 0x0000 }, /* R6037 */ + { 0x0000, 0x0000, 0x0000 }, /* R6038 */ + { 0x0000, 0x0000, 0x0000 }, /* R6039 */ + { 0x0000, 0x0000, 0x0000 }, /* R6040 */ + { 0x0000, 0x0000, 0x0000 }, /* R6041 */ + { 0x0000, 0x0000, 0x0000 }, /* R6042 */ + { 0x0000, 0x0000, 0x0000 }, /* R6043 */ + { 0x0000, 0x0000, 0x0000 }, /* R6044 */ + { 0x0000, 0x0000, 0x0000 }, /* R6045 */ + { 0x0000, 0x0000, 0x0000 }, /* R6046 */ + { 0x0000, 0x0000, 0x0000 }, /* R6047 */ + { 0x0000, 0x0000, 0x0000 }, /* R6048 */ + { 0x0000, 0x0000, 0x0000 }, /* R6049 */ + { 0x0000, 0x0000, 0x0000 }, /* R6050 */ + { 0x0000, 0x0000, 0x0000 }, /* R6051 */ + { 0x0000, 0x0000, 0x0000 }, /* R6052 */ + { 0x0000, 0x0000, 0x0000 }, /* R6053 */ + { 0x0000, 0x0000, 0x0000 }, /* R6054 */ + { 0x0000, 0x0000, 0x0000 }, /* R6055 */ + { 0x0000, 0x0000, 0x0000 }, /* R6056 */ + { 0x0000, 0x0000, 0x0000 }, /* R6057 */ + { 0x0000, 0x0000, 0x0000 }, /* R6058 */ + { 0x0000, 0x0000, 0x0000 }, /* R6059 */ + { 0x0000, 0x0000, 0x0000 }, /* R6060 */ + { 0x0000, 0x0000, 0x0000 }, /* R6061 */ + { 0x0000, 0x0000, 0x0000 }, /* R6062 */ + { 0x0000, 0x0000, 0x0000 }, /* R6063 */ + { 0x0000, 0x0000, 0x0000 }, /* R6064 */ + { 0x0000, 0x0000, 0x0000 }, /* R6065 */ + { 0x0000, 0x0000, 0x0000 }, /* R6066 */ + { 0x0000, 0x0000, 0x0000 }, /* R6067 */ + { 0x0000, 0x0000, 0x0000 }, /* R6068 */ + { 0x0000, 0x0000, 0x0000 }, /* R6069 */ + { 0x0000, 0x0000, 0x0000 }, /* R6070 */ + { 0x0000, 0x0000, 0x0000 }, /* R6071 */ + { 0x0000, 0x0000, 0x0000 }, /* R6072 */ + { 0x0000, 0x0000, 0x0000 }, /* R6073 */ + { 0x0000, 0x0000, 0x0000 }, /* R6074 */ + { 0x0000, 0x0000, 0x0000 }, /* R6075 */ + { 0x0000, 0x0000, 0x0000 }, /* R6076 */ + { 0x0000, 0x0000, 0x0000 }, /* R6077 */ + { 0x0000, 0x0000, 0x0000 }, /* R6078 */ + { 0x0000, 0x0000, 0x0000 }, /* R6079 */ + { 0x0000, 0x0000, 0x0000 }, /* R6080 */ + { 0x0000, 0x0000, 0x0000 }, /* R6081 */ + { 0x0000, 0x0000, 0x0000 }, /* R6082 */ + { 0x0000, 0x0000, 0x0000 }, /* R6083 */ + { 0x0000, 0x0000, 0x0000 }, /* R6084 */ + { 0x0000, 0x0000, 0x0000 }, /* R6085 */ + { 0x0000, 0x0000, 0x0000 }, /* R6086 */ + { 0x0000, 0x0000, 0x0000 }, /* R6087 */ + { 0x0000, 0x0000, 0x0000 }, /* R6088 */ + { 0x0000, 0x0000, 0x0000 }, /* R6089 */ + { 0x0000, 0x0000, 0x0000 }, /* R6090 */ + { 0x0000, 0x0000, 0x0000 }, /* R6091 */ + { 0x0000, 0x0000, 0x0000 }, /* R6092 */ + { 0x0000, 0x0000, 0x0000 }, /* R6093 */ + { 0x0000, 0x0000, 0x0000 }, /* R6094 */ + { 0x0000, 0x0000, 0x0000 }, /* R6095 */ + { 0x0000, 0x0000, 0x0000 }, /* R6096 */ + { 0x0000, 0x0000, 0x0000 }, /* R6097 */ + { 0x0000, 0x0000, 0x0000 }, /* R6098 */ + { 0x0000, 0x0000, 0x0000 }, /* R6099 */ + { 0x0000, 0x0000, 0x0000 }, /* R6100 */ + { 0x0000, 0x0000, 0x0000 }, /* R6101 */ + { 0x0000, 0x0000, 0x0000 }, /* R6102 */ + { 0x0000, 0x0000, 0x0000 }, /* R6103 */ + { 0x0000, 0x0000, 0x0000 }, /* R6104 */ + { 0x0000, 0x0000, 0x0000 }, /* R6105 */ + { 0x0000, 0x0000, 0x0000 }, /* R6106 */ + { 0x0000, 0x0000, 0x0000 }, /* R6107 */ + { 0x0000, 0x0000, 0x0000 }, /* R6108 */ + { 0x0000, 0x0000, 0x0000 }, /* R6109 */ + { 0x0000, 0x0000, 0x0000 }, /* R6110 */ + { 0x0000, 0x0000, 0x0000 }, /* R6111 */ + { 0x0000, 0x0000, 0x0000 }, /* R6112 */ + { 0x0000, 0x0000, 0x0000 }, /* R6113 */ + { 0x0000, 0x0000, 0x0000 }, /* R6114 */ + { 0x0000, 0x0000, 0x0000 }, /* R6115 */ + { 0x0000, 0x0000, 0x0000 }, /* R6116 */ + { 0x0000, 0x0000, 0x0000 }, /* R6117 */ + { 0x0000, 0x0000, 0x0000 }, /* R6118 */ + { 0x0000, 0x0000, 0x0000 }, /* R6119 */ + { 0x0000, 0x0000, 0x0000 }, /* R6120 */ + { 0x0000, 0x0000, 0x0000 }, /* R6121 */ + { 0x0000, 0x0000, 0x0000 }, /* R6122 */ + { 0x0000, 0x0000, 0x0000 }, /* R6123 */ + { 0x0000, 0x0000, 0x0000 }, /* R6124 */ + { 0x0000, 0x0000, 0x0000 }, /* R6125 */ + { 0x0000, 0x0000, 0x0000 }, /* R6126 */ + { 0x0000, 0x0000, 0x0000 }, /* R6127 */ + { 0x0000, 0x0000, 0x0000 }, /* R6128 */ + { 0x0000, 0x0000, 0x0000 }, /* R6129 */ + { 0x0000, 0x0000, 0x0000 }, /* R6130 */ + { 0x0000, 0x0000, 0x0000 }, /* R6131 */ + { 0x0000, 0x0000, 0x0000 }, /* R6132 */ + { 0x0000, 0x0000, 0x0000 }, /* R6133 */ + { 0x0000, 0x0000, 0x0000 }, /* R6134 */ + { 0x0000, 0x0000, 0x0000 }, /* R6135 */ + { 0x0000, 0x0000, 0x0000 }, /* R6136 */ + { 0x0000, 0x0000, 0x0000 }, /* R6137 */ + { 0x0000, 0x0000, 0x0000 }, /* R6138 */ + { 0x0000, 0x0000, 0x0000 }, /* R6139 */ + { 0x0000, 0x0000, 0x0000 }, /* R6140 */ + { 0x0000, 0x0000, 0x0000 }, /* R6141 */ + { 0x0000, 0x0000, 0x0000 }, /* R6142 */ + { 0x0000, 0x0000, 0x0000 }, /* R6143 */ + { 0x0000, 0x0000, 0x0000 }, /* R6144 */ + { 0x0000, 0x0000, 0x0000 }, /* R6145 */ + { 0x0000, 0x0000, 0x0000 }, /* R6146 */ + { 0x0000, 0x0000, 0x0000 }, /* R6147 */ + { 0x0000, 0x0000, 0x0000 }, /* R6148 */ + { 0x0000, 0x0000, 0x0000 }, /* R6149 */ + { 0x0000, 0x0000, 0x0000 }, /* R6150 */ + { 0x0000, 0x0000, 0x0000 }, /* R6151 */ + { 0x0000, 0x0000, 0x0000 }, /* R6152 */ + { 0x0000, 0x0000, 0x0000 }, /* R6153 */ + { 0x0000, 0x0000, 0x0000 }, /* R6154 */ + { 0x0000, 0x0000, 0x0000 }, /* R6155 */ + { 0x0000, 0x0000, 0x0000 }, /* R6156 */ + { 0x0000, 0x0000, 0x0000 }, /* R6157 */ + { 0x0000, 0x0000, 0x0000 }, /* R6158 */ + { 0x0000, 0x0000, 0x0000 }, /* R6159 */ + { 0x0000, 0x0000, 0x0000 }, /* R6160 */ + { 0x0000, 0x0000, 0x0000 }, /* R6161 */ + { 0x0000, 0x0000, 0x0000 }, /* R6162 */ + { 0x0000, 0x0000, 0x0000 }, /* R6163 */ + { 0x0000, 0x0000, 0x0000 }, /* R6164 */ + { 0x0000, 0x0000, 0x0000 }, /* R6165 */ + { 0x0000, 0x0000, 0x0000 }, /* R6166 */ + { 0x0000, 0x0000, 0x0000 }, /* R6167 */ + { 0x0000, 0x0000, 0x0000 }, /* R6168 */ + { 0x0000, 0x0000, 0x0000 }, /* R6169 */ + { 0x0000, 0x0000, 0x0000 }, /* R6170 */ + { 0x0000, 0x0000, 0x0000 }, /* R6171 */ + { 0x0000, 0x0000, 0x0000 }, /* R6172 */ + { 0x0000, 0x0000, 0x0000 }, /* R6173 */ + { 0x0000, 0x0000, 0x0000 }, /* R6174 */ + { 0x0000, 0x0000, 0x0000 }, /* R6175 */ + { 0x0000, 0x0000, 0x0000 }, /* R6176 */ + { 0x0000, 0x0000, 0x0000 }, /* R6177 */ + { 0x0000, 0x0000, 0x0000 }, /* R6178 */ + { 0x0000, 0x0000, 0x0000 }, /* R6179 */ + { 0x0000, 0x0000, 0x0000 }, /* R6180 */ + { 0x0000, 0x0000, 0x0000 }, /* R6181 */ + { 0x0000, 0x0000, 0x0000 }, /* R6182 */ + { 0x0000, 0x0000, 0x0000 }, /* R6183 */ + { 0x0000, 0x0000, 0x0000 }, /* R6184 */ + { 0x0000, 0x0000, 0x0000 }, /* R6185 */ + { 0x0000, 0x0000, 0x0000 }, /* R6186 */ + { 0x0000, 0x0000, 0x0000 }, /* R6187 */ + { 0x0000, 0x0000, 0x0000 }, /* R6188 */ + { 0x0000, 0x0000, 0x0000 }, /* R6189 */ + { 0x0000, 0x0000, 0x0000 }, /* R6190 */ + { 0x0000, 0x0000, 0x0000 }, /* R6191 */ + { 0x0000, 0x0000, 0x0000 }, /* R6192 */ + { 0x0000, 0x0000, 0x0000 }, /* R6193 */ + { 0x0000, 0x0000, 0x0000 }, /* R6194 */ + { 0x0000, 0x0000, 0x0000 }, /* R6195 */ + { 0x0000, 0x0000, 0x0000 }, /* R6196 */ + { 0x0000, 0x0000, 0x0000 }, /* R6197 */ + { 0x0000, 0x0000, 0x0000 }, /* R6198 */ + { 0x0000, 0x0000, 0x0000 }, /* R6199 */ + { 0x0000, 0x0000, 0x0000 }, /* R6200 */ + { 0x0000, 0x0000, 0x0000 }, /* R6201 */ + { 0x0000, 0x0000, 0x0000 }, /* R6202 */ + { 0x0000, 0x0000, 0x0000 }, /* R6203 */ + { 0x0000, 0x0000, 0x0000 }, /* R6204 */ + { 0x0000, 0x0000, 0x0000 }, /* R6205 */ + { 0x0000, 0x0000, 0x0000 }, /* R6206 */ + { 0x0000, 0x0000, 0x0000 }, /* R6207 */ + { 0x0000, 0x0000, 0x0000 }, /* R6208 */ + { 0x0000, 0x0000, 0x0000 }, /* R6209 */ + { 0x0000, 0x0000, 0x0000 }, /* R6210 */ + { 0x0000, 0x0000, 0x0000 }, /* R6211 */ + { 0x0000, 0x0000, 0x0000 }, /* R6212 */ + { 0x0000, 0x0000, 0x0000 }, /* R6213 */ + { 0x0000, 0x0000, 0x0000 }, /* R6214 */ + { 0x0000, 0x0000, 0x0000 }, /* R6215 */ + { 0x0000, 0x0000, 0x0000 }, /* R6216 */ + { 0x0000, 0x0000, 0x0000 }, /* R6217 */ + { 0x0000, 0x0000, 0x0000 }, /* R6218 */ + { 0x0000, 0x0000, 0x0000 }, /* R6219 */ + { 0x0000, 0x0000, 0x0000 }, /* R6220 */ + { 0x0000, 0x0000, 0x0000 }, /* R6221 */ + { 0x0000, 0x0000, 0x0000 }, /* R6222 */ + { 0x0000, 0x0000, 0x0000 }, /* R6223 */ + { 0x0000, 0x0000, 0x0000 }, /* R6224 */ + { 0x0000, 0x0000, 0x0000 }, /* R6225 */ + { 0x0000, 0x0000, 0x0000 }, /* R6226 */ + { 0x0000, 0x0000, 0x0000 }, /* R6227 */ + { 0x0000, 0x0000, 0x0000 }, /* R6228 */ + { 0x0000, 0x0000, 0x0000 }, /* R6229 */ + { 0x0000, 0x0000, 0x0000 }, /* R6230 */ + { 0x0000, 0x0000, 0x0000 }, /* R6231 */ + { 0x0000, 0x0000, 0x0000 }, /* R6232 */ + { 0x0000, 0x0000, 0x0000 }, /* R6233 */ + { 0x0000, 0x0000, 0x0000 }, /* R6234 */ + { 0x0000, 0x0000, 0x0000 }, /* R6235 */ + { 0x0000, 0x0000, 0x0000 }, /* R6236 */ + { 0x0000, 0x0000, 0x0000 }, /* R6237 */ + { 0x0000, 0x0000, 0x0000 }, /* R6238 */ + { 0x0000, 0x0000, 0x0000 }, /* R6239 */ + { 0x0000, 0x0000, 0x0000 }, /* R6240 */ + { 0x0000, 0x0000, 0x0000 }, /* R6241 */ + { 0x0000, 0x0000, 0x0000 }, /* R6242 */ + { 0x0000, 0x0000, 0x0000 }, /* R6243 */ + { 0x0000, 0x0000, 0x0000 }, /* R6244 */ + { 0x0000, 0x0000, 0x0000 }, /* R6245 */ + { 0x0000, 0x0000, 0x0000 }, /* R6246 */ + { 0x0000, 0x0000, 0x0000 }, /* R6247 */ + { 0x0000, 0x0000, 0x0000 }, /* R6248 */ + { 0x0000, 0x0000, 0x0000 }, /* R6249 */ + { 0x0000, 0x0000, 0x0000 }, /* R6250 */ + { 0x0000, 0x0000, 0x0000 }, /* R6251 */ + { 0x0000, 0x0000, 0x0000 }, /* R6252 */ + { 0x0000, 0x0000, 0x0000 }, /* R6253 */ + { 0x0000, 0x0000, 0x0000 }, /* R6254 */ + { 0x0000, 0x0000, 0x0000 }, /* R6255 */ + { 0x0000, 0x0000, 0x0000 }, /* R6256 */ + { 0x0000, 0x0000, 0x0000 }, /* R6257 */ + { 0x0000, 0x0000, 0x0000 }, /* R6258 */ + { 0x0000, 0x0000, 0x0000 }, /* R6259 */ + { 0x0000, 0x0000, 0x0000 }, /* R6260 */ + { 0x0000, 0x0000, 0x0000 }, /* R6261 */ + { 0x0000, 0x0000, 0x0000 }, /* R6262 */ + { 0x0000, 0x0000, 0x0000 }, /* R6263 */ + { 0x0000, 0x0000, 0x0000 }, /* R6264 */ + { 0x0000, 0x0000, 0x0000 }, /* R6265 */ + { 0x0000, 0x0000, 0x0000 }, /* R6266 */ + { 0x0000, 0x0000, 0x0000 }, /* R6267 */ + { 0x0000, 0x0000, 0x0000 }, /* R6268 */ + { 0x0000, 0x0000, 0x0000 }, /* R6269 */ + { 0x0000, 0x0000, 0x0000 }, /* R6270 */ + { 0x0000, 0x0000, 0x0000 }, /* R6271 */ + { 0x0000, 0x0000, 0x0000 }, /* R6272 */ + { 0x0000, 0x0000, 0x0000 }, /* R6273 */ + { 0x0000, 0x0000, 0x0000 }, /* R6274 */ + { 0x0000, 0x0000, 0x0000 }, /* R6275 */ + { 0x0000, 0x0000, 0x0000 }, /* R6276 */ + { 0x0000, 0x0000, 0x0000 }, /* R6277 */ + { 0x0000, 0x0000, 0x0000 }, /* R6278 */ + { 0x0000, 0x0000, 0x0000 }, /* R6279 */ + { 0x0000, 0x0000, 0x0000 }, /* R6280 */ + { 0x0000, 0x0000, 0x0000 }, /* R6281 */ + { 0x0000, 0x0000, 0x0000 }, /* R6282 */ + { 0x0000, 0x0000, 0x0000 }, /* R6283 */ + { 0x0000, 0x0000, 0x0000 }, /* R6284 */ + { 0x0000, 0x0000, 0x0000 }, /* R6285 */ + { 0x0000, 0x0000, 0x0000 }, /* R6286 */ + { 0x0000, 0x0000, 0x0000 }, /* R6287 */ + { 0x0000, 0x0000, 0x0000 }, /* R6288 */ + { 0x0000, 0x0000, 0x0000 }, /* R6289 */ + { 0x0000, 0x0000, 0x0000 }, /* R6290 */ + { 0x0000, 0x0000, 0x0000 }, /* R6291 */ + { 0x0000, 0x0000, 0x0000 }, /* R6292 */ + { 0x0000, 0x0000, 0x0000 }, /* R6293 */ + { 0x0000, 0x0000, 0x0000 }, /* R6294 */ + { 0x0000, 0x0000, 0x0000 }, /* R6295 */ + { 0x0000, 0x0000, 0x0000 }, /* R6296 */ + { 0x0000, 0x0000, 0x0000 }, /* R6297 */ + { 0x0000, 0x0000, 0x0000 }, /* R6298 */ + { 0x0000, 0x0000, 0x0000 }, /* R6299 */ + { 0x0000, 0x0000, 0x0000 }, /* R6300 */ + { 0x0000, 0x0000, 0x0000 }, /* R6301 */ + { 0x0000, 0x0000, 0x0000 }, /* R6302 */ + { 0x0000, 0x0000, 0x0000 }, /* R6303 */ + { 0x0000, 0x0000, 0x0000 }, /* R6304 */ + { 0x0000, 0x0000, 0x0000 }, /* R6305 */ + { 0x0000, 0x0000, 0x0000 }, /* R6306 */ + { 0x0000, 0x0000, 0x0000 }, /* R6307 */ + { 0x0000, 0x0000, 0x0000 }, /* R6308 */ + { 0x0000, 0x0000, 0x0000 }, /* R6309 */ + { 0x0000, 0x0000, 0x0000 }, /* R6310 */ + { 0x0000, 0x0000, 0x0000 }, /* R6311 */ + { 0x0000, 0x0000, 0x0000 }, /* R6312 */ + { 0x0000, 0x0000, 0x0000 }, /* R6313 */ + { 0x0000, 0x0000, 0x0000 }, /* R6314 */ + { 0x0000, 0x0000, 0x0000 }, /* R6315 */ + { 0x0000, 0x0000, 0x0000 }, /* R6316 */ + { 0x0000, 0x0000, 0x0000 }, /* R6317 */ + { 0x0000, 0x0000, 0x0000 }, /* R6318 */ + { 0x0000, 0x0000, 0x0000 }, /* R6319 */ + { 0x0000, 0x0000, 0x0000 }, /* R6320 */ + { 0x0000, 0x0000, 0x0000 }, /* R6321 */ + { 0x0000, 0x0000, 0x0000 }, /* R6322 */ + { 0x0000, 0x0000, 0x0000 }, /* R6323 */ + { 0x0000, 0x0000, 0x0000 }, /* R6324 */ + { 0x0000, 0x0000, 0x0000 }, /* R6325 */ + { 0x0000, 0x0000, 0x0000 }, /* R6326 */ + { 0x0000, 0x0000, 0x0000 }, /* R6327 */ + { 0x0000, 0x0000, 0x0000 }, /* R6328 */ + { 0x0000, 0x0000, 0x0000 }, /* R6329 */ + { 0x0000, 0x0000, 0x0000 }, /* R6330 */ + { 0x0000, 0x0000, 0x0000 }, /* R6331 */ + { 0x0000, 0x0000, 0x0000 }, /* R6332 */ + { 0x0000, 0x0000, 0x0000 }, /* R6333 */ + { 0x0000, 0x0000, 0x0000 }, /* R6334 */ + { 0x0000, 0x0000, 0x0000 }, /* R6335 */ + { 0x0000, 0x0000, 0x0000 }, /* R6336 */ + { 0x0000, 0x0000, 0x0000 }, /* R6337 */ + { 0x0000, 0x0000, 0x0000 }, /* R6338 */ + { 0x0000, 0x0000, 0x0000 }, /* R6339 */ + { 0x0000, 0x0000, 0x0000 }, /* R6340 */ + { 0x0000, 0x0000, 0x0000 }, /* R6341 */ + { 0x0000, 0x0000, 0x0000 }, /* R6342 */ + { 0x0000, 0x0000, 0x0000 }, /* R6343 */ + { 0x0000, 0x0000, 0x0000 }, /* R6344 */ + { 0x0000, 0x0000, 0x0000 }, /* R6345 */ + { 0x0000, 0x0000, 0x0000 }, /* R6346 */ + { 0x0000, 0x0000, 0x0000 }, /* R6347 */ + { 0x0000, 0x0000, 0x0000 }, /* R6348 */ + { 0x0000, 0x0000, 0x0000 }, /* R6349 */ + { 0x0000, 0x0000, 0x0000 }, /* R6350 */ + { 0x0000, 0x0000, 0x0000 }, /* R6351 */ + { 0x0000, 0x0000, 0x0000 }, /* R6352 */ + { 0x0000, 0x0000, 0x0000 }, /* R6353 */ + { 0x0000, 0x0000, 0x0000 }, /* R6354 */ + { 0x0000, 0x0000, 0x0000 }, /* R6355 */ + { 0x0000, 0x0000, 0x0000 }, /* R6356 */ + { 0x0000, 0x0000, 0x0000 }, /* R6357 */ + { 0x0000, 0x0000, 0x0000 }, /* R6358 */ + { 0x0000, 0x0000, 0x0000 }, /* R6359 */ + { 0x0000, 0x0000, 0x0000 }, /* R6360 */ + { 0x0000, 0x0000, 0x0000 }, /* R6361 */ + { 0x0000, 0x0000, 0x0000 }, /* R6362 */ + { 0x0000, 0x0000, 0x0000 }, /* R6363 */ + { 0x0000, 0x0000, 0x0000 }, /* R6364 */ + { 0x0000, 0x0000, 0x0000 }, /* R6365 */ + { 0x0000, 0x0000, 0x0000 }, /* R6366 */ + { 0x0000, 0x0000, 0x0000 }, /* R6367 */ + { 0x0000, 0x0000, 0x0000 }, /* R6368 */ + { 0x0000, 0x0000, 0x0000 }, /* R6369 */ + { 0x0000, 0x0000, 0x0000 }, /* R6370 */ + { 0x0000, 0x0000, 0x0000 }, /* R6371 */ + { 0x0000, 0x0000, 0x0000 }, /* R6372 */ + { 0x0000, 0x0000, 0x0000 }, /* R6373 */ + { 0x0000, 0x0000, 0x0000 }, /* R6374 */ + { 0x0000, 0x0000, 0x0000 }, /* R6375 */ + { 0x0000, 0x0000, 0x0000 }, /* R6376 */ + { 0x0000, 0x0000, 0x0000 }, /* R6377 */ + { 0x0000, 0x0000, 0x0000 }, /* R6378 */ + { 0x0000, 0x0000, 0x0000 }, /* R6379 */ + { 0x0000, 0x0000, 0x0000 }, /* R6380 */ + { 0x0000, 0x0000, 0x0000 }, /* R6381 */ + { 0x0000, 0x0000, 0x0000 }, /* R6382 */ + { 0x0000, 0x0000, 0x0000 }, /* R6383 */ + { 0x0000, 0x0000, 0x0000 }, /* R6384 */ + { 0x0000, 0x0000, 0x0000 }, /* R6385 */ + { 0x0000, 0x0000, 0x0000 }, /* R6386 */ + { 0x0000, 0x0000, 0x0000 }, /* R6387 */ + { 0x0000, 0x0000, 0x0000 }, /* R6388 */ + { 0x0000, 0x0000, 0x0000 }, /* R6389 */ + { 0x0000, 0x0000, 0x0000 }, /* R6390 */ + { 0x0000, 0x0000, 0x0000 }, /* R6391 */ + { 0x0000, 0x0000, 0x0000 }, /* R6392 */ + { 0x0000, 0x0000, 0x0000 }, /* R6393 */ + { 0x0000, 0x0000, 0x0000 }, /* R6394 */ + { 0x0000, 0x0000, 0x0000 }, /* R6395 */ + { 0x0000, 0x0000, 0x0000 }, /* R6396 */ + { 0x0000, 0x0000, 0x0000 }, /* R6397 */ + { 0x0000, 0x0000, 0x0000 }, /* R6398 */ + { 0x0000, 0x0000, 0x0000 }, /* R6399 */ + { 0x0000, 0x0000, 0x0000 }, /* R6400 */ + { 0x0000, 0x0000, 0x0000 }, /* R6401 */ + { 0x0000, 0x0000, 0x0000 }, /* R6402 */ + { 0x0000, 0x0000, 0x0000 }, /* R6403 */ + { 0x0000, 0x0000, 0x0000 }, /* R6404 */ + { 0x0000, 0x0000, 0x0000 }, /* R6405 */ + { 0x0000, 0x0000, 0x0000 }, /* R6406 */ + { 0x0000, 0x0000, 0x0000 }, /* R6407 */ + { 0x0000, 0x0000, 0x0000 }, /* R6408 */ + { 0x0000, 0x0000, 0x0000 }, /* R6409 */ + { 0x0000, 0x0000, 0x0000 }, /* R6410 */ + { 0x0000, 0x0000, 0x0000 }, /* R6411 */ + { 0x0000, 0x0000, 0x0000 }, /* R6412 */ + { 0x0000, 0x0000, 0x0000 }, /* R6413 */ + { 0x0000, 0x0000, 0x0000 }, /* R6414 */ + { 0x0000, 0x0000, 0x0000 }, /* R6415 */ + { 0x0000, 0x0000, 0x0000 }, /* R6416 */ + { 0x0000, 0x0000, 0x0000 }, /* R6417 */ + { 0x0000, 0x0000, 0x0000 }, /* R6418 */ + { 0x0000, 0x0000, 0x0000 }, /* R6419 */ + { 0x0000, 0x0000, 0x0000 }, /* R6420 */ + { 0x0000, 0x0000, 0x0000 }, /* R6421 */ + { 0x0000, 0x0000, 0x0000 }, /* R6422 */ + { 0x0000, 0x0000, 0x0000 }, /* R6423 */ + { 0x0000, 0x0000, 0x0000 }, /* R6424 */ + { 0x0000, 0x0000, 0x0000 }, /* R6425 */ + { 0x0000, 0x0000, 0x0000 }, /* R6426 */ + { 0x0000, 0x0000, 0x0000 }, /* R6427 */ + { 0x0000, 0x0000, 0x0000 }, /* R6428 */ + { 0x0000, 0x0000, 0x0000 }, /* R6429 */ + { 0x0000, 0x0000, 0x0000 }, /* R6430 */ + { 0x0000, 0x0000, 0x0000 }, /* R6431 */ + { 0x0000, 0x0000, 0x0000 }, /* R6432 */ + { 0x0000, 0x0000, 0x0000 }, /* R6433 */ + { 0x0000, 0x0000, 0x0000 }, /* R6434 */ + { 0x0000, 0x0000, 0x0000 }, /* R6435 */ + { 0x0000, 0x0000, 0x0000 }, /* R6436 */ + { 0x0000, 0x0000, 0x0000 }, /* R6437 */ + { 0x0000, 0x0000, 0x0000 }, /* R6438 */ + { 0x0000, 0x0000, 0x0000 }, /* R6439 */ + { 0x0000, 0x0000, 0x0000 }, /* R6440 */ + { 0x0000, 0x0000, 0x0000 }, /* R6441 */ + { 0x0000, 0x0000, 0x0000 }, /* R6442 */ + { 0x0000, 0x0000, 0x0000 }, /* R6443 */ + { 0x0000, 0x0000, 0x0000 }, /* R6444 */ + { 0x0000, 0x0000, 0x0000 }, /* R6445 */ + { 0x0000, 0x0000, 0x0000 }, /* R6446 */ + { 0x0000, 0x0000, 0x0000 }, /* R6447 */ + { 0x0000, 0x0000, 0x0000 }, /* R6448 */ + { 0x0000, 0x0000, 0x0000 }, /* R6449 */ + { 0x0000, 0x0000, 0x0000 }, /* R6450 */ + { 0x0000, 0x0000, 0x0000 }, /* R6451 */ + { 0x0000, 0x0000, 0x0000 }, /* R6452 */ + { 0x0000, 0x0000, 0x0000 }, /* R6453 */ + { 0x0000, 0x0000, 0x0000 }, /* R6454 */ + { 0x0000, 0x0000, 0x0000 }, /* R6455 */ + { 0x0000, 0x0000, 0x0000 }, /* R6456 */ + { 0x0000, 0x0000, 0x0000 }, /* R6457 */ + { 0x0000, 0x0000, 0x0000 }, /* R6458 */ + { 0x0000, 0x0000, 0x0000 }, /* R6459 */ + { 0x0000, 0x0000, 0x0000 }, /* R6460 */ + { 0x0000, 0x0000, 0x0000 }, /* R6461 */ + { 0x0000, 0x0000, 0x0000 }, /* R6462 */ + { 0x0000, 0x0000, 0x0000 }, /* R6463 */ + { 0x0000, 0x0000, 0x0000 }, /* R6464 */ + { 0x0000, 0x0000, 0x0000 }, /* R6465 */ + { 0x0000, 0x0000, 0x0000 }, /* R6466 */ + { 0x0000, 0x0000, 0x0000 }, /* R6467 */ + { 0x0000, 0x0000, 0x0000 }, /* R6468 */ + { 0x0000, 0x0000, 0x0000 }, /* R6469 */ + { 0x0000, 0x0000, 0x0000 }, /* R6470 */ + { 0x0000, 0x0000, 0x0000 }, /* R6471 */ + { 0x0000, 0x0000, 0x0000 }, /* R6472 */ + { 0x0000, 0x0000, 0x0000 }, /* R6473 */ + { 0x0000, 0x0000, 0x0000 }, /* R6474 */ + { 0x0000, 0x0000, 0x0000 }, /* R6475 */ + { 0x0000, 0x0000, 0x0000 }, /* R6476 */ + { 0x0000, 0x0000, 0x0000 }, /* R6477 */ + { 0x0000, 0x0000, 0x0000 }, /* R6478 */ + { 0x0000, 0x0000, 0x0000 }, /* R6479 */ + { 0x0000, 0x0000, 0x0000 }, /* R6480 */ + { 0x0000, 0x0000, 0x0000 }, /* R6481 */ + { 0x0000, 0x0000, 0x0000 }, /* R6482 */ + { 0x0000, 0x0000, 0x0000 }, /* R6483 */ + { 0x0000, 0x0000, 0x0000 }, /* R6484 */ + { 0x0000, 0x0000, 0x0000 }, /* R6485 */ + { 0x0000, 0x0000, 0x0000 }, /* R6486 */ + { 0x0000, 0x0000, 0x0000 }, /* R6487 */ + { 0x0000, 0x0000, 0x0000 }, /* R6488 */ + { 0x0000, 0x0000, 0x0000 }, /* R6489 */ + { 0x0000, 0x0000, 0x0000 }, /* R6490 */ + { 0x0000, 0x0000, 0x0000 }, /* R6491 */ + { 0x0000, 0x0000, 0x0000 }, /* R6492 */ + { 0x0000, 0x0000, 0x0000 }, /* R6493 */ + { 0x0000, 0x0000, 0x0000 }, /* R6494 */ + { 0x0000, 0x0000, 0x0000 }, /* R6495 */ + { 0x0000, 0x0000, 0x0000 }, /* R6496 */ + { 0x0000, 0x0000, 0x0000 }, /* R6497 */ + { 0x0000, 0x0000, 0x0000 }, /* R6498 */ + { 0x0000, 0x0000, 0x0000 }, /* R6499 */ + { 0x0000, 0x0000, 0x0000 }, /* R6500 */ + { 0x0000, 0x0000, 0x0000 }, /* R6501 */ + { 0x0000, 0x0000, 0x0000 }, /* R6502 */ + { 0x0000, 0x0000, 0x0000 }, /* R6503 */ + { 0x0000, 0x0000, 0x0000 }, /* R6504 */ + { 0x0000, 0x0000, 0x0000 }, /* R6505 */ + { 0x0000, 0x0000, 0x0000 }, /* R6506 */ + { 0x0000, 0x0000, 0x0000 }, /* R6507 */ + { 0x0000, 0x0000, 0x0000 }, /* R6508 */ + { 0x0000, 0x0000, 0x0000 }, /* R6509 */ + { 0x0000, 0x0000, 0x0000 }, /* R6510 */ + { 0x0000, 0x0000, 0x0000 }, /* R6511 */ + { 0x0000, 0x0000, 0x0000 }, /* R6512 */ + { 0x0000, 0x0000, 0x0000 }, /* R6513 */ + { 0x0000, 0x0000, 0x0000 }, /* R6514 */ + { 0x0000, 0x0000, 0x0000 }, /* R6515 */ + { 0x0000, 0x0000, 0x0000 }, /* R6516 */ + { 0x0000, 0x0000, 0x0000 }, /* R6517 */ + { 0x0000, 0x0000, 0x0000 }, /* R6518 */ + { 0x0000, 0x0000, 0x0000 }, /* R6519 */ + { 0x0000, 0x0000, 0x0000 }, /* R6520 */ + { 0x0000, 0x0000, 0x0000 }, /* R6521 */ + { 0x0000, 0x0000, 0x0000 }, /* R6522 */ + { 0x0000, 0x0000, 0x0000 }, /* R6523 */ + { 0x0000, 0x0000, 0x0000 }, /* R6524 */ + { 0x0000, 0x0000, 0x0000 }, /* R6525 */ + { 0x0000, 0x0000, 0x0000 }, /* R6526 */ + { 0x0000, 0x0000, 0x0000 }, /* R6527 */ + { 0x0000, 0x0000, 0x0000 }, /* R6528 */ + { 0x0000, 0x0000, 0x0000 }, /* R6529 */ + { 0x0000, 0x0000, 0x0000 }, /* R6530 */ + { 0x0000, 0x0000, 0x0000 }, /* R6531 */ + { 0x0000, 0x0000, 0x0000 }, /* R6532 */ + { 0x0000, 0x0000, 0x0000 }, /* R6533 */ + { 0x0000, 0x0000, 0x0000 }, /* R6534 */ + { 0x0000, 0x0000, 0x0000 }, /* R6535 */ + { 0x0000, 0x0000, 0x0000 }, /* R6536 */ + { 0x0000, 0x0000, 0x0000 }, /* R6537 */ + { 0x0000, 0x0000, 0x0000 }, /* R6538 */ + { 0x0000, 0x0000, 0x0000 }, /* R6539 */ + { 0x0000, 0x0000, 0x0000 }, /* R6540 */ + { 0x0000, 0x0000, 0x0000 }, /* R6541 */ + { 0x0000, 0x0000, 0x0000 }, /* R6542 */ + { 0x0000, 0x0000, 0x0000 }, /* R6543 */ + { 0x0000, 0x0000, 0x0000 }, /* R6544 */ + { 0x0000, 0x0000, 0x0000 }, /* R6545 */ + { 0x0000, 0x0000, 0x0000 }, /* R6546 */ + { 0x0000, 0x0000, 0x0000 }, /* R6547 */ + { 0x0000, 0x0000, 0x0000 }, /* R6548 */ + { 0x0000, 0x0000, 0x0000 }, /* R6549 */ + { 0x0000, 0x0000, 0x0000 }, /* R6550 */ + { 0x0000, 0x0000, 0x0000 }, /* R6551 */ + { 0x0000, 0x0000, 0x0000 }, /* R6552 */ + { 0x0000, 0x0000, 0x0000 }, /* R6553 */ + { 0x0000, 0x0000, 0x0000 }, /* R6554 */ + { 0x0000, 0x0000, 0x0000 }, /* R6555 */ + { 0x0000, 0x0000, 0x0000 }, /* R6556 */ + { 0x0000, 0x0000, 0x0000 }, /* R6557 */ + { 0x0000, 0x0000, 0x0000 }, /* R6558 */ + { 0x0000, 0x0000, 0x0000 }, /* R6559 */ + { 0x0000, 0x0000, 0x0000 }, /* R6560 */ + { 0x0000, 0x0000, 0x0000 }, /* R6561 */ + { 0x0000, 0x0000, 0x0000 }, /* R6562 */ + { 0x0000, 0x0000, 0x0000 }, /* R6563 */ + { 0x0000, 0x0000, 0x0000 }, /* R6564 */ + { 0x0000, 0x0000, 0x0000 }, /* R6565 */ + { 0x0000, 0x0000, 0x0000 }, /* R6566 */ + { 0x0000, 0x0000, 0x0000 }, /* R6567 */ + { 0x0000, 0x0000, 0x0000 }, /* R6568 */ + { 0x0000, 0x0000, 0x0000 }, /* R6569 */ + { 0x0000, 0x0000, 0x0000 }, /* R6570 */ + { 0x0000, 0x0000, 0x0000 }, /* R6571 */ + { 0x0000, 0x0000, 0x0000 }, /* R6572 */ + { 0x0000, 0x0000, 0x0000 }, /* R6573 */ + { 0x0000, 0x0000, 0x0000 }, /* R6574 */ + { 0x0000, 0x0000, 0x0000 }, /* R6575 */ + { 0x0000, 0x0000, 0x0000 }, /* R6576 */ + { 0x0000, 0x0000, 0x0000 }, /* R6577 */ + { 0x0000, 0x0000, 0x0000 }, /* R6578 */ + { 0x0000, 0x0000, 0x0000 }, /* R6579 */ + { 0x0000, 0x0000, 0x0000 }, /* R6580 */ + { 0x0000, 0x0000, 0x0000 }, /* R6581 */ + { 0x0000, 0x0000, 0x0000 }, /* R6582 */ + { 0x0000, 0x0000, 0x0000 }, /* R6583 */ + { 0x0000, 0x0000, 0x0000 }, /* R6584 */ + { 0x0000, 0x0000, 0x0000 }, /* R6585 */ + { 0x0000, 0x0000, 0x0000 }, /* R6586 */ + { 0x0000, 0x0000, 0x0000 }, /* R6587 */ + { 0x0000, 0x0000, 0x0000 }, /* R6588 */ + { 0x0000, 0x0000, 0x0000 }, /* R6589 */ + { 0x0000, 0x0000, 0x0000 }, /* R6590 */ + { 0x0000, 0x0000, 0x0000 }, /* R6591 */ + { 0x0000, 0x0000, 0x0000 }, /* R6592 */ + { 0x0000, 0x0000, 0x0000 }, /* R6593 */ + { 0x0000, 0x0000, 0x0000 }, /* R6594 */ + { 0x0000, 0x0000, 0x0000 }, /* R6595 */ + { 0x0000, 0x0000, 0x0000 }, /* R6596 */ + { 0x0000, 0x0000, 0x0000 }, /* R6597 */ + { 0x0000, 0x0000, 0x0000 }, /* R6598 */ + { 0x0000, 0x0000, 0x0000 }, /* R6599 */ + { 0x0000, 0x0000, 0x0000 }, /* R6600 */ + { 0x0000, 0x0000, 0x0000 }, /* R6601 */ + { 0x0000, 0x0000, 0x0000 }, /* R6602 */ + { 0x0000, 0x0000, 0x0000 }, /* R6603 */ + { 0x0000, 0x0000, 0x0000 }, /* R6604 */ + { 0x0000, 0x0000, 0x0000 }, /* R6605 */ + { 0x0000, 0x0000, 0x0000 }, /* R6606 */ + { 0x0000, 0x0000, 0x0000 }, /* R6607 */ + { 0x0000, 0x0000, 0x0000 }, /* R6608 */ + { 0x0000, 0x0000, 0x0000 }, /* R6609 */ + { 0x0000, 0x0000, 0x0000 }, /* R6610 */ + { 0x0000, 0x0000, 0x0000 }, /* R6611 */ + { 0x0000, 0x0000, 0x0000 }, /* R6612 */ + { 0x0000, 0x0000, 0x0000 }, /* R6613 */ + { 0x0000, 0x0000, 0x0000 }, /* R6614 */ + { 0x0000, 0x0000, 0x0000 }, /* R6615 */ + { 0x0000, 0x0000, 0x0000 }, /* R6616 */ + { 0x0000, 0x0000, 0x0000 }, /* R6617 */ + { 0x0000, 0x0000, 0x0000 }, /* R6618 */ + { 0x0000, 0x0000, 0x0000 }, /* R6619 */ + { 0x0000, 0x0000, 0x0000 }, /* R6620 */ + { 0x0000, 0x0000, 0x0000 }, /* R6621 */ + { 0x0000, 0x0000, 0x0000 }, /* R6622 */ + { 0x0000, 0x0000, 0x0000 }, /* R6623 */ + { 0x0000, 0x0000, 0x0000 }, /* R6624 */ + { 0x0000, 0x0000, 0x0000 }, /* R6625 */ + { 0x0000, 0x0000, 0x0000 }, /* R6626 */ + { 0x0000, 0x0000, 0x0000 }, /* R6627 */ + { 0x0000, 0x0000, 0x0000 }, /* R6628 */ + { 0x0000, 0x0000, 0x0000 }, /* R6629 */ + { 0x0000, 0x0000, 0x0000 }, /* R6630 */ + { 0x0000, 0x0000, 0x0000 }, /* R6631 */ + { 0x0000, 0x0000, 0x0000 }, /* R6632 */ + { 0x0000, 0x0000, 0x0000 }, /* R6633 */ + { 0x0000, 0x0000, 0x0000 }, /* R6634 */ + { 0x0000, 0x0000, 0x0000 }, /* R6635 */ + { 0x0000, 0x0000, 0x0000 }, /* R6636 */ + { 0x0000, 0x0000, 0x0000 }, /* R6637 */ + { 0x0000, 0x0000, 0x0000 }, /* R6638 */ + { 0x0000, 0x0000, 0x0000 }, /* R6639 */ + { 0x0000, 0x0000, 0x0000 }, /* R6640 */ + { 0x0000, 0x0000, 0x0000 }, /* R6641 */ + { 0x0000, 0x0000, 0x0000 }, /* R6642 */ + { 0x0000, 0x0000, 0x0000 }, /* R6643 */ + { 0x0000, 0x0000, 0x0000 }, /* R6644 */ + { 0x0000, 0x0000, 0x0000 }, /* R6645 */ + { 0x0000, 0x0000, 0x0000 }, /* R6646 */ + { 0x0000, 0x0000, 0x0000 }, /* R6647 */ + { 0x0000, 0x0000, 0x0000 }, /* R6648 */ + { 0x0000, 0x0000, 0x0000 }, /* R6649 */ + { 0x0000, 0x0000, 0x0000 }, /* R6650 */ + { 0x0000, 0x0000, 0x0000 }, /* R6651 */ + { 0x0000, 0x0000, 0x0000 }, /* R6652 */ + { 0x0000, 0x0000, 0x0000 }, /* R6653 */ + { 0x0000, 0x0000, 0x0000 }, /* R6654 */ + { 0x0000, 0x0000, 0x0000 }, /* R6655 */ + { 0x0000, 0x0000, 0x0000 }, /* R6656 */ + { 0x0000, 0x0000, 0x0000 }, /* R6657 */ + { 0x0000, 0x0000, 0x0000 }, /* R6658 */ + { 0x0000, 0x0000, 0x0000 }, /* R6659 */ + { 0x0000, 0x0000, 0x0000 }, /* R6660 */ + { 0x0000, 0x0000, 0x0000 }, /* R6661 */ + { 0x0000, 0x0000, 0x0000 }, /* R6662 */ + { 0x0000, 0x0000, 0x0000 }, /* R6663 */ + { 0x0000, 0x0000, 0x0000 }, /* R6664 */ + { 0x0000, 0x0000, 0x0000 }, /* R6665 */ + { 0x0000, 0x0000, 0x0000 }, /* R6666 */ + { 0x0000, 0x0000, 0x0000 }, /* R6667 */ + { 0x0000, 0x0000, 0x0000 }, /* R6668 */ + { 0x0000, 0x0000, 0x0000 }, /* R6669 */ + { 0x0000, 0x0000, 0x0000 }, /* R6670 */ + { 0x0000, 0x0000, 0x0000 }, /* R6671 */ + { 0x0000, 0x0000, 0x0000 }, /* R6672 */ + { 0x0000, 0x0000, 0x0000 }, /* R6673 */ + { 0x0000, 0x0000, 0x0000 }, /* R6674 */ + { 0x0000, 0x0000, 0x0000 }, /* R6675 */ + { 0x0000, 0x0000, 0x0000 }, /* R6676 */ + { 0x0000, 0x0000, 0x0000 }, /* R6677 */ + { 0x0000, 0x0000, 0x0000 }, /* R6678 */ + { 0x0000, 0x0000, 0x0000 }, /* R6679 */ + { 0x0000, 0x0000, 0x0000 }, /* R6680 */ + { 0x0000, 0x0000, 0x0000 }, /* R6681 */ + { 0x0000, 0x0000, 0x0000 }, /* R6682 */ + { 0x0000, 0x0000, 0x0000 }, /* R6683 */ + { 0x0000, 0x0000, 0x0000 }, /* R6684 */ + { 0x0000, 0x0000, 0x0000 }, /* R6685 */ + { 0x0000, 0x0000, 0x0000 }, /* R6686 */ + { 0x0000, 0x0000, 0x0000 }, /* R6687 */ + { 0x0000, 0x0000, 0x0000 }, /* R6688 */ + { 0x0000, 0x0000, 0x0000 }, /* R6689 */ + { 0x0000, 0x0000, 0x0000 }, /* R6690 */ + { 0x0000, 0x0000, 0x0000 }, /* R6691 */ + { 0x0000, 0x0000, 0x0000 }, /* R6692 */ + { 0x0000, 0x0000, 0x0000 }, /* R6693 */ + { 0x0000, 0x0000, 0x0000 }, /* R6694 */ + { 0x0000, 0x0000, 0x0000 }, /* R6695 */ + { 0x0000, 0x0000, 0x0000 }, /* R6696 */ + { 0x0000, 0x0000, 0x0000 }, /* R6697 */ + { 0x0000, 0x0000, 0x0000 }, /* R6698 */ + { 0x0000, 0x0000, 0x0000 }, /* R6699 */ + { 0x0000, 0x0000, 0x0000 }, /* R6700 */ + { 0x0000, 0x0000, 0x0000 }, /* R6701 */ + { 0x0000, 0x0000, 0x0000 }, /* R6702 */ + { 0x0000, 0x0000, 0x0000 }, /* R6703 */ + { 0x0000, 0x0000, 0x0000 }, /* R6704 */ + { 0x0000, 0x0000, 0x0000 }, /* R6705 */ + { 0x0000, 0x0000, 0x0000 }, /* R6706 */ + { 0x0000, 0x0000, 0x0000 }, /* R6707 */ + { 0x0000, 0x0000, 0x0000 }, /* R6708 */ + { 0x0000, 0x0000, 0x0000 }, /* R6709 */ + { 0x0000, 0x0000, 0x0000 }, /* R6710 */ + { 0x0000, 0x0000, 0x0000 }, /* R6711 */ + { 0x0000, 0x0000, 0x0000 }, /* R6712 */ + { 0x0000, 0x0000, 0x0000 }, /* R6713 */ + { 0x0000, 0x0000, 0x0000 }, /* R6714 */ + { 0x0000, 0x0000, 0x0000 }, /* R6715 */ + { 0x0000, 0x0000, 0x0000 }, /* R6716 */ + { 0x0000, 0x0000, 0x0000 }, /* R6717 */ + { 0x0000, 0x0000, 0x0000 }, /* R6718 */ + { 0x0000, 0x0000, 0x0000 }, /* R6719 */ + { 0x0000, 0x0000, 0x0000 }, /* R6720 */ + { 0x0000, 0x0000, 0x0000 }, /* R6721 */ + { 0x0000, 0x0000, 0x0000 }, /* R6722 */ + { 0x0000, 0x0000, 0x0000 }, /* R6723 */ + { 0x0000, 0x0000, 0x0000 }, /* R6724 */ + { 0x0000, 0x0000, 0x0000 }, /* R6725 */ + { 0x0000, 0x0000, 0x0000 }, /* R6726 */ + { 0x0000, 0x0000, 0x0000 }, /* R6727 */ + { 0x0000, 0x0000, 0x0000 }, /* R6728 */ + { 0x0000, 0x0000, 0x0000 }, /* R6729 */ + { 0x0000, 0x0000, 0x0000 }, /* R6730 */ + { 0x0000, 0x0000, 0x0000 }, /* R6731 */ + { 0x0000, 0x0000, 0x0000 }, /* R6732 */ + { 0x0000, 0x0000, 0x0000 }, /* R6733 */ + { 0x0000, 0x0000, 0x0000 }, /* R6734 */ + { 0x0000, 0x0000, 0x0000 }, /* R6735 */ + { 0x0000, 0x0000, 0x0000 }, /* R6736 */ + { 0x0000, 0x0000, 0x0000 }, /* R6737 */ + { 0x0000, 0x0000, 0x0000 }, /* R6738 */ + { 0x0000, 0x0000, 0x0000 }, /* R6739 */ + { 0x0000, 0x0000, 0x0000 }, /* R6740 */ + { 0x0000, 0x0000, 0x0000 }, /* R6741 */ + { 0x0000, 0x0000, 0x0000 }, /* R6742 */ + { 0x0000, 0x0000, 0x0000 }, /* R6743 */ + { 0x0000, 0x0000, 0x0000 }, /* R6744 */ + { 0x0000, 0x0000, 0x0000 }, /* R6745 */ + { 0x0000, 0x0000, 0x0000 }, /* R6746 */ + { 0x0000, 0x0000, 0x0000 }, /* R6747 */ + { 0x0000, 0x0000, 0x0000 }, /* R6748 */ + { 0x0000, 0x0000, 0x0000 }, /* R6749 */ + { 0x0000, 0x0000, 0x0000 }, /* R6750 */ + { 0x0000, 0x0000, 0x0000 }, /* R6751 */ + { 0x0000, 0x0000, 0x0000 }, /* R6752 */ + { 0x0000, 0x0000, 0x0000 }, /* R6753 */ + { 0x0000, 0x0000, 0x0000 }, /* R6754 */ + { 0x0000, 0x0000, 0x0000 }, /* R6755 */ + { 0x0000, 0x0000, 0x0000 }, /* R6756 */ + { 0x0000, 0x0000, 0x0000 }, /* R6757 */ + { 0x0000, 0x0000, 0x0000 }, /* R6758 */ + { 0x0000, 0x0000, 0x0000 }, /* R6759 */ + { 0x0000, 0x0000, 0x0000 }, /* R6760 */ + { 0x0000, 0x0000, 0x0000 }, /* R6761 */ + { 0x0000, 0x0000, 0x0000 }, /* R6762 */ + { 0x0000, 0x0000, 0x0000 }, /* R6763 */ + { 0x0000, 0x0000, 0x0000 }, /* R6764 */ + { 0x0000, 0x0000, 0x0000 }, /* R6765 */ + { 0x0000, 0x0000, 0x0000 }, /* R6766 */ + { 0x0000, 0x0000, 0x0000 }, /* R6767 */ + { 0x0000, 0x0000, 0x0000 }, /* R6768 */ + { 0x0000, 0x0000, 0x0000 }, /* R6769 */ + { 0x0000, 0x0000, 0x0000 }, /* R6770 */ + { 0x0000, 0x0000, 0x0000 }, /* R6771 */ + { 0x0000, 0x0000, 0x0000 }, /* R6772 */ + { 0x0000, 0x0000, 0x0000 }, /* R6773 */ + { 0x0000, 0x0000, 0x0000 }, /* R6774 */ + { 0x0000, 0x0000, 0x0000 }, /* R6775 */ + { 0x0000, 0x0000, 0x0000 }, /* R6776 */ + { 0x0000, 0x0000, 0x0000 }, /* R6777 */ + { 0x0000, 0x0000, 0x0000 }, /* R6778 */ + { 0x0000, 0x0000, 0x0000 }, /* R6779 */ + { 0x0000, 0x0000, 0x0000 }, /* R6780 */ + { 0x0000, 0x0000, 0x0000 }, /* R6781 */ + { 0x0000, 0x0000, 0x0000 }, /* R6782 */ + { 0x0000, 0x0000, 0x0000 }, /* R6783 */ + { 0x0000, 0x0000, 0x0000 }, /* R6784 */ + { 0x0000, 0x0000, 0x0000 }, /* R6785 */ + { 0x0000, 0x0000, 0x0000 }, /* R6786 */ + { 0x0000, 0x0000, 0x0000 }, /* R6787 */ + { 0x0000, 0x0000, 0x0000 }, /* R6788 */ + { 0x0000, 0x0000, 0x0000 }, /* R6789 */ + { 0x0000, 0x0000, 0x0000 }, /* R6790 */ + { 0x0000, 0x0000, 0x0000 }, /* R6791 */ + { 0x0000, 0x0000, 0x0000 }, /* R6792 */ + { 0x0000, 0x0000, 0x0000 }, /* R6793 */ + { 0x0000, 0x0000, 0x0000 }, /* R6794 */ + { 0x0000, 0x0000, 0x0000 }, /* R6795 */ + { 0x0000, 0x0000, 0x0000 }, /* R6796 */ + { 0x0000, 0x0000, 0x0000 }, /* R6797 */ + { 0x0000, 0x0000, 0x0000 }, /* R6798 */ + { 0x0000, 0x0000, 0x0000 }, /* R6799 */ + { 0x0000, 0x0000, 0x0000 }, /* R6800 */ + { 0x0000, 0x0000, 0x0000 }, /* R6801 */ + { 0x0000, 0x0000, 0x0000 }, /* R6802 */ + { 0x0000, 0x0000, 0x0000 }, /* R6803 */ + { 0x0000, 0x0000, 0x0000 }, /* R6804 */ + { 0x0000, 0x0000, 0x0000 }, /* R6805 */ + { 0x0000, 0x0000, 0x0000 }, /* R6806 */ + { 0x0000, 0x0000, 0x0000 }, /* R6807 */ + { 0x0000, 0x0000, 0x0000 }, /* R6808 */ + { 0x0000, 0x0000, 0x0000 }, /* R6809 */ + { 0x0000, 0x0000, 0x0000 }, /* R6810 */ + { 0x0000, 0x0000, 0x0000 }, /* R6811 */ + { 0x0000, 0x0000, 0x0000 }, /* R6812 */ + { 0x0000, 0x0000, 0x0000 }, /* R6813 */ + { 0x0000, 0x0000, 0x0000 }, /* R6814 */ + { 0x0000, 0x0000, 0x0000 }, /* R6815 */ + { 0x0000, 0x0000, 0x0000 }, /* R6816 */ + { 0x0000, 0x0000, 0x0000 }, /* R6817 */ + { 0x0000, 0x0000, 0x0000 }, /* R6818 */ + { 0x0000, 0x0000, 0x0000 }, /* R6819 */ + { 0x0000, 0x0000, 0x0000 }, /* R6820 */ + { 0x0000, 0x0000, 0x0000 }, /* R6821 */ + { 0x0000, 0x0000, 0x0000 }, /* R6822 */ + { 0x0000, 0x0000, 0x0000 }, /* R6823 */ + { 0x0000, 0x0000, 0x0000 }, /* R6824 */ + { 0x0000, 0x0000, 0x0000 }, /* R6825 */ + { 0x0000, 0x0000, 0x0000 }, /* R6826 */ + { 0x0000, 0x0000, 0x0000 }, /* R6827 */ + { 0x0000, 0x0000, 0x0000 }, /* R6828 */ + { 0x0000, 0x0000, 0x0000 }, /* R6829 */ + { 0x0000, 0x0000, 0x0000 }, /* R6830 */ + { 0x0000, 0x0000, 0x0000 }, /* R6831 */ + { 0x0000, 0x0000, 0x0000 }, /* R6832 */ + { 0x0000, 0x0000, 0x0000 }, /* R6833 */ + { 0x0000, 0x0000, 0x0000 }, /* R6834 */ + { 0x0000, 0x0000, 0x0000 }, /* R6835 */ + { 0x0000, 0x0000, 0x0000 }, /* R6836 */ + { 0x0000, 0x0000, 0x0000 }, /* R6837 */ + { 0x0000, 0x0000, 0x0000 }, /* R6838 */ + { 0x0000, 0x0000, 0x0000 }, /* R6839 */ + { 0x0000, 0x0000, 0x0000 }, /* R6840 */ + { 0x0000, 0x0000, 0x0000 }, /* R6841 */ + { 0x0000, 0x0000, 0x0000 }, /* R6842 */ + { 0x0000, 0x0000, 0x0000 }, /* R6843 */ + { 0x0000, 0x0000, 0x0000 }, /* R6844 */ + { 0x0000, 0x0000, 0x0000 }, /* R6845 */ + { 0x0000, 0x0000, 0x0000 }, /* R6846 */ + { 0x0000, 0x0000, 0x0000 }, /* R6847 */ + { 0x0000, 0x0000, 0x0000 }, /* R6848 */ + { 0x0000, 0x0000, 0x0000 }, /* R6849 */ + { 0x0000, 0x0000, 0x0000 }, /* R6850 */ + { 0x0000, 0x0000, 0x0000 }, /* R6851 */ + { 0x0000, 0x0000, 0x0000 }, /* R6852 */ + { 0x0000, 0x0000, 0x0000 }, /* R6853 */ + { 0x0000, 0x0000, 0x0000 }, /* R6854 */ + { 0x0000, 0x0000, 0x0000 }, /* R6855 */ + { 0x0000, 0x0000, 0x0000 }, /* R6856 */ + { 0x0000, 0x0000, 0x0000 }, /* R6857 */ + { 0x0000, 0x0000, 0x0000 }, /* R6858 */ + { 0x0000, 0x0000, 0x0000 }, /* R6859 */ + { 0x0000, 0x0000, 0x0000 }, /* R6860 */ + { 0x0000, 0x0000, 0x0000 }, /* R6861 */ + { 0x0000, 0x0000, 0x0000 }, /* R6862 */ + { 0x0000, 0x0000, 0x0000 }, /* R6863 */ + { 0x0000, 0x0000, 0x0000 }, /* R6864 */ + { 0x0000, 0x0000, 0x0000 }, /* R6865 */ + { 0x0000, 0x0000, 0x0000 }, /* R6866 */ + { 0x0000, 0x0000, 0x0000 }, /* R6867 */ + { 0x0000, 0x0000, 0x0000 }, /* R6868 */ + { 0x0000, 0x0000, 0x0000 }, /* R6869 */ + { 0x0000, 0x0000, 0x0000 }, /* R6870 */ + { 0x0000, 0x0000, 0x0000 }, /* R6871 */ + { 0x0000, 0x0000, 0x0000 }, /* R6872 */ + { 0x0000, 0x0000, 0x0000 }, /* R6873 */ + { 0x0000, 0x0000, 0x0000 }, /* R6874 */ + { 0x0000, 0x0000, 0x0000 }, /* R6875 */ + { 0x0000, 0x0000, 0x0000 }, /* R6876 */ + { 0x0000, 0x0000, 0x0000 }, /* R6877 */ + { 0x0000, 0x0000, 0x0000 }, /* R6878 */ + { 0x0000, 0x0000, 0x0000 }, /* R6879 */ + { 0x0000, 0x0000, 0x0000 }, /* R6880 */ + { 0x0000, 0x0000, 0x0000 }, /* R6881 */ + { 0x0000, 0x0000, 0x0000 }, /* R6882 */ + { 0x0000, 0x0000, 0x0000 }, /* R6883 */ + { 0x0000, 0x0000, 0x0000 }, /* R6884 */ + { 0x0000, 0x0000, 0x0000 }, /* R6885 */ + { 0x0000, 0x0000, 0x0000 }, /* R6886 */ + { 0x0000, 0x0000, 0x0000 }, /* R6887 */ + { 0x0000, 0x0000, 0x0000 }, /* R6888 */ + { 0x0000, 0x0000, 0x0000 }, /* R6889 */ + { 0x0000, 0x0000, 0x0000 }, /* R6890 */ + { 0x0000, 0x0000, 0x0000 }, /* R6891 */ + { 0x0000, 0x0000, 0x0000 }, /* R6892 */ + { 0x0000, 0x0000, 0x0000 }, /* R6893 */ + { 0x0000, 0x0000, 0x0000 }, /* R6894 */ + { 0x0000, 0x0000, 0x0000 }, /* R6895 */ + { 0x0000, 0x0000, 0x0000 }, /* R6896 */ + { 0x0000, 0x0000, 0x0000 }, /* R6897 */ + { 0x0000, 0x0000, 0x0000 }, /* R6898 */ + { 0x0000, 0x0000, 0x0000 }, /* R6899 */ + { 0x0000, 0x0000, 0x0000 }, /* R6900 */ + { 0x0000, 0x0000, 0x0000 }, /* R6901 */ + { 0x0000, 0x0000, 0x0000 }, /* R6902 */ + { 0x0000, 0x0000, 0x0000 }, /* R6903 */ + { 0x0000, 0x0000, 0x0000 }, /* R6904 */ + { 0x0000, 0x0000, 0x0000 }, /* R6905 */ + { 0x0000, 0x0000, 0x0000 }, /* R6906 */ + { 0x0000, 0x0000, 0x0000 }, /* R6907 */ + { 0x0000, 0x0000, 0x0000 }, /* R6908 */ + { 0x0000, 0x0000, 0x0000 }, /* R6909 */ + { 0x0000, 0x0000, 0x0000 }, /* R6910 */ + { 0x0000, 0x0000, 0x0000 }, /* R6911 */ + { 0x0000, 0x0000, 0x0000 }, /* R6912 */ + { 0x0000, 0x0000, 0x0000 }, /* R6913 */ + { 0x0000, 0x0000, 0x0000 }, /* R6914 */ + { 0x0000, 0x0000, 0x0000 }, /* R6915 */ + { 0x0000, 0x0000, 0x0000 }, /* R6916 */ + { 0x0000, 0x0000, 0x0000 }, /* R6917 */ + { 0x0000, 0x0000, 0x0000 }, /* R6918 */ + { 0x0000, 0x0000, 0x0000 }, /* R6919 */ + { 0x0000, 0x0000, 0x0000 }, /* R6920 */ + { 0x0000, 0x0000, 0x0000 }, /* R6921 */ + { 0x0000, 0x0000, 0x0000 }, /* R6922 */ + { 0x0000, 0x0000, 0x0000 }, /* R6923 */ + { 0x0000, 0x0000, 0x0000 }, /* R6924 */ + { 0x0000, 0x0000, 0x0000 }, /* R6925 */ + { 0x0000, 0x0000, 0x0000 }, /* R6926 */ + { 0x0000, 0x0000, 0x0000 }, /* R6927 */ + { 0x0000, 0x0000, 0x0000 }, /* R6928 */ + { 0x0000, 0x0000, 0x0000 }, /* R6929 */ + { 0x0000, 0x0000, 0x0000 }, /* R6930 */ + { 0x0000, 0x0000, 0x0000 }, /* R6931 */ + { 0x0000, 0x0000, 0x0000 }, /* R6932 */ + { 0x0000, 0x0000, 0x0000 }, /* R6933 */ + { 0x0000, 0x0000, 0x0000 }, /* R6934 */ + { 0x0000, 0x0000, 0x0000 }, /* R6935 */ + { 0x0000, 0x0000, 0x0000 }, /* R6936 */ + { 0x0000, 0x0000, 0x0000 }, /* R6937 */ + { 0x0000, 0x0000, 0x0000 }, /* R6938 */ + { 0x0000, 0x0000, 0x0000 }, /* R6939 */ + { 0x0000, 0x0000, 0x0000 }, /* R6940 */ + { 0x0000, 0x0000, 0x0000 }, /* R6941 */ + { 0x0000, 0x0000, 0x0000 }, /* R6942 */ + { 0x0000, 0x0000, 0x0000 }, /* R6943 */ + { 0x0000, 0x0000, 0x0000 }, /* R6944 */ + { 0x0000, 0x0000, 0x0000 }, /* R6945 */ + { 0x0000, 0x0000, 0x0000 }, /* R6946 */ + { 0x0000, 0x0000, 0x0000 }, /* R6947 */ + { 0x0000, 0x0000, 0x0000 }, /* R6948 */ + { 0x0000, 0x0000, 0x0000 }, /* R6949 */ + { 0x0000, 0x0000, 0x0000 }, /* R6950 */ + { 0x0000, 0x0000, 0x0000 }, /* R6951 */ + { 0x0000, 0x0000, 0x0000 }, /* R6952 */ + { 0x0000, 0x0000, 0x0000 }, /* R6953 */ + { 0x0000, 0x0000, 0x0000 }, /* R6954 */ + { 0x0000, 0x0000, 0x0000 }, /* R6955 */ + { 0x0000, 0x0000, 0x0000 }, /* R6956 */ + { 0x0000, 0x0000, 0x0000 }, /* R6957 */ + { 0x0000, 0x0000, 0x0000 }, /* R6958 */ + { 0x0000, 0x0000, 0x0000 }, /* R6959 */ + { 0x0000, 0x0000, 0x0000 }, /* R6960 */ + { 0x0000, 0x0000, 0x0000 }, /* R6961 */ + { 0x0000, 0x0000, 0x0000 }, /* R6962 */ + { 0x0000, 0x0000, 0x0000 }, /* R6963 */ + { 0x0000, 0x0000, 0x0000 }, /* R6964 */ + { 0x0000, 0x0000, 0x0000 }, /* R6965 */ + { 0x0000, 0x0000, 0x0000 }, /* R6966 */ + { 0x0000, 0x0000, 0x0000 }, /* R6967 */ + { 0x0000, 0x0000, 0x0000 }, /* R6968 */ + { 0x0000, 0x0000, 0x0000 }, /* R6969 */ + { 0x0000, 0x0000, 0x0000 }, /* R6970 */ + { 0x0000, 0x0000, 0x0000 }, /* R6971 */ + { 0x0000, 0x0000, 0x0000 }, /* R6972 */ + { 0x0000, 0x0000, 0x0000 }, /* R6973 */ + { 0x0000, 0x0000, 0x0000 }, /* R6974 */ + { 0x0000, 0x0000, 0x0000 }, /* R6975 */ + { 0x0000, 0x0000, 0x0000 }, /* R6976 */ + { 0x0000, 0x0000, 0x0000 }, /* R6977 */ + { 0x0000, 0x0000, 0x0000 }, /* R6978 */ + { 0x0000, 0x0000, 0x0000 }, /* R6979 */ + { 0x0000, 0x0000, 0x0000 }, /* R6980 */ + { 0x0000, 0x0000, 0x0000 }, /* R6981 */ + { 0x0000, 0x0000, 0x0000 }, /* R6982 */ + { 0x0000, 0x0000, 0x0000 }, /* R6983 */ + { 0x0000, 0x0000, 0x0000 }, /* R6984 */ + { 0x0000, 0x0000, 0x0000 }, /* R6985 */ + { 0x0000, 0x0000, 0x0000 }, /* R6986 */ + { 0x0000, 0x0000, 0x0000 }, /* R6987 */ + { 0x0000, 0x0000, 0x0000 }, /* R6988 */ + { 0x0000, 0x0000, 0x0000 }, /* R6989 */ + { 0x0000, 0x0000, 0x0000 }, /* R6990 */ + { 0x0000, 0x0000, 0x0000 }, /* R6991 */ + { 0x0000, 0x0000, 0x0000 }, /* R6992 */ + { 0x0000, 0x0000, 0x0000 }, /* R6993 */ + { 0x0000, 0x0000, 0x0000 }, /* R6994 */ + { 0x0000, 0x0000, 0x0000 }, /* R6995 */ + { 0x0000, 0x0000, 0x0000 }, /* R6996 */ + { 0x0000, 0x0000, 0x0000 }, /* R6997 */ + { 0x0000, 0x0000, 0x0000 }, /* R6998 */ + { 0x0000, 0x0000, 0x0000 }, /* R6999 */ + { 0x0000, 0x0000, 0x0000 }, /* R7000 */ + { 0x0000, 0x0000, 0x0000 }, /* R7001 */ + { 0x0000, 0x0000, 0x0000 }, /* R7002 */ + { 0x0000, 0x0000, 0x0000 }, /* R7003 */ + { 0x0000, 0x0000, 0x0000 }, /* R7004 */ + { 0x0000, 0x0000, 0x0000 }, /* R7005 */ + { 0x0000, 0x0000, 0x0000 }, /* R7006 */ + { 0x0000, 0x0000, 0x0000 }, /* R7007 */ + { 0x0000, 0x0000, 0x0000 }, /* R7008 */ + { 0x0000, 0x0000, 0x0000 }, /* R7009 */ + { 0x0000, 0x0000, 0x0000 }, /* R7010 */ + { 0x0000, 0x0000, 0x0000 }, /* R7011 */ + { 0x0000, 0x0000, 0x0000 }, /* R7012 */ + { 0x0000, 0x0000, 0x0000 }, /* R7013 */ + { 0x0000, 0x0000, 0x0000 }, /* R7014 */ + { 0x0000, 0x0000, 0x0000 }, /* R7015 */ + { 0x0000, 0x0000, 0x0000 }, /* R7016 */ + { 0x0000, 0x0000, 0x0000 }, /* R7017 */ + { 0x0000, 0x0000, 0x0000 }, /* R7018 */ + { 0x0000, 0x0000, 0x0000 }, /* R7019 */ + { 0x0000, 0x0000, 0x0000 }, /* R7020 */ + { 0x0000, 0x0000, 0x0000 }, /* R7021 */ + { 0x0000, 0x0000, 0x0000 }, /* R7022 */ + { 0x0000, 0x0000, 0x0000 }, /* R7023 */ + { 0x0000, 0x0000, 0x0000 }, /* R7024 */ + { 0x0000, 0x0000, 0x0000 }, /* R7025 */ + { 0x0000, 0x0000, 0x0000 }, /* R7026 */ + { 0x0000, 0x0000, 0x0000 }, /* R7027 */ + { 0x0000, 0x0000, 0x0000 }, /* R7028 */ + { 0x0000, 0x0000, 0x0000 }, /* R7029 */ + { 0x0000, 0x0000, 0x0000 }, /* R7030 */ + { 0x0000, 0x0000, 0x0000 }, /* R7031 */ + { 0x0000, 0x0000, 0x0000 }, /* R7032 */ + { 0x0000, 0x0000, 0x0000 }, /* R7033 */ + { 0x0000, 0x0000, 0x0000 }, /* R7034 */ + { 0x0000, 0x0000, 0x0000 }, /* R7035 */ + { 0x0000, 0x0000, 0x0000 }, /* R7036 */ + { 0x0000, 0x0000, 0x0000 }, /* R7037 */ + { 0x0000, 0x0000, 0x0000 }, /* R7038 */ + { 0x0000, 0x0000, 0x0000 }, /* R7039 */ + { 0x0000, 0x0000, 0x0000 }, /* R7040 */ + { 0x0000, 0x0000, 0x0000 }, /* R7041 */ + { 0x0000, 0x0000, 0x0000 }, /* R7042 */ + { 0x0000, 0x0000, 0x0000 }, /* R7043 */ + { 0x0000, 0x0000, 0x0000 }, /* R7044 */ + { 0x0000, 0x0000, 0x0000 }, /* R7045 */ + { 0x0000, 0x0000, 0x0000 }, /* R7046 */ + { 0x0000, 0x0000, 0x0000 }, /* R7047 */ + { 0x0000, 0x0000, 0x0000 }, /* R7048 */ + { 0x0000, 0x0000, 0x0000 }, /* R7049 */ + { 0x0000, 0x0000, 0x0000 }, /* R7050 */ + { 0x0000, 0x0000, 0x0000 }, /* R7051 */ + { 0x0000, 0x0000, 0x0000 }, /* R7052 */ + { 0x0000, 0x0000, 0x0000 }, /* R7053 */ + { 0x0000, 0x0000, 0x0000 }, /* R7054 */ + { 0x0000, 0x0000, 0x0000 }, /* R7055 */ + { 0x0000, 0x0000, 0x0000 }, /* R7056 */ + { 0x0000, 0x0000, 0x0000 }, /* R7057 */ + { 0x0000, 0x0000, 0x0000 }, /* R7058 */ + { 0x0000, 0x0000, 0x0000 }, /* R7059 */ + { 0x0000, 0x0000, 0x0000 }, /* R7060 */ + { 0x0000, 0x0000, 0x0000 }, /* R7061 */ + { 0x0000, 0x0000, 0x0000 }, /* R7062 */ + { 0x0000, 0x0000, 0x0000 }, /* R7063 */ + { 0x0000, 0x0000, 0x0000 }, /* R7064 */ + { 0x0000, 0x0000, 0x0000 }, /* R7065 */ + { 0x0000, 0x0000, 0x0000 }, /* R7066 */ + { 0x0000, 0x0000, 0x0000 }, /* R7067 */ + { 0x0000, 0x0000, 0x0000 }, /* R7068 */ + { 0x0000, 0x0000, 0x0000 }, /* R7069 */ + { 0x0000, 0x0000, 0x0000 }, /* R7070 */ + { 0x0000, 0x0000, 0x0000 }, /* R7071 */ + { 0x0000, 0x0000, 0x0000 }, /* R7072 */ + { 0x0000, 0x0000, 0x0000 }, /* R7073 */ + { 0x0000, 0x0000, 0x0000 }, /* R7074 */ + { 0x0000, 0x0000, 0x0000 }, /* R7075 */ + { 0x0000, 0x0000, 0x0000 }, /* R7076 */ + { 0x0000, 0x0000, 0x0000 }, /* R7077 */ + { 0x0000, 0x0000, 0x0000 }, /* R7078 */ + { 0x0000, 0x0000, 0x0000 }, /* R7079 */ + { 0x0000, 0x0000, 0x0000 }, /* R7080 */ + { 0x0000, 0x0000, 0x0000 }, /* R7081 */ + { 0x0000, 0x0000, 0x0000 }, /* R7082 */ + { 0x0000, 0x0000, 0x0000 }, /* R7083 */ + { 0x0000, 0x0000, 0x0000 }, /* R7084 */ + { 0x0000, 0x0000, 0x0000 }, /* R7085 */ + { 0x0000, 0x0000, 0x0000 }, /* R7086 */ + { 0x0000, 0x0000, 0x0000 }, /* R7087 */ + { 0x0000, 0x0000, 0x0000 }, /* R7088 */ + { 0x0000, 0x0000, 0x0000 }, /* R7089 */ + { 0x0000, 0x0000, 0x0000 }, /* R7090 */ + { 0x0000, 0x0000, 0x0000 }, /* R7091 */ + { 0x0000, 0x0000, 0x0000 }, /* R7092 */ + { 0x0000, 0x0000, 0x0000 }, /* R7093 */ + { 0x0000, 0x0000, 0x0000 }, /* R7094 */ + { 0x0000, 0x0000, 0x0000 }, /* R7095 */ + { 0x0000, 0x0000, 0x0000 }, /* R7096 */ + { 0x0000, 0x0000, 0x0000 }, /* R7097 */ + { 0x0000, 0x0000, 0x0000 }, /* R7098 */ + { 0x0000, 0x0000, 0x0000 }, /* R7099 */ + { 0x0000, 0x0000, 0x0000 }, /* R7100 */ + { 0x0000, 0x0000, 0x0000 }, /* R7101 */ + { 0x0000, 0x0000, 0x0000 }, /* R7102 */ + { 0x0000, 0x0000, 0x0000 }, /* R7103 */ + { 0x0000, 0x0000, 0x0000 }, /* R7104 */ + { 0x0000, 0x0000, 0x0000 }, /* R7105 */ + { 0x0000, 0x0000, 0x0000 }, /* R7106 */ + { 0x0000, 0x0000, 0x0000 }, /* R7107 */ + { 0x0000, 0x0000, 0x0000 }, /* R7108 */ + { 0x0000, 0x0000, 0x0000 }, /* R7109 */ + { 0x0000, 0x0000, 0x0000 }, /* R7110 */ + { 0x0000, 0x0000, 0x0000 }, /* R7111 */ + { 0x0000, 0x0000, 0x0000 }, /* R7112 */ + { 0x0000, 0x0000, 0x0000 }, /* R7113 */ + { 0x0000, 0x0000, 0x0000 }, /* R7114 */ + { 0x0000, 0x0000, 0x0000 }, /* R7115 */ + { 0x0000, 0x0000, 0x0000 }, /* R7116 */ + { 0x0000, 0x0000, 0x0000 }, /* R7117 */ + { 0x0000, 0x0000, 0x0000 }, /* R7118 */ + { 0x0000, 0x0000, 0x0000 }, /* R7119 */ + { 0x0000, 0x0000, 0x0000 }, /* R7120 */ + { 0x0000, 0x0000, 0x0000 }, /* R7121 */ + { 0x0000, 0x0000, 0x0000 }, /* R7122 */ + { 0x0000, 0x0000, 0x0000 }, /* R7123 */ + { 0x0000, 0x0000, 0x0000 }, /* R7124 */ + { 0x0000, 0x0000, 0x0000 }, /* R7125 */ + { 0x0000, 0x0000, 0x0000 }, /* R7126 */ + { 0x0000, 0x0000, 0x0000 }, /* R7127 */ + { 0x0000, 0x0000, 0x0000 }, /* R7128 */ + { 0x0000, 0x0000, 0x0000 }, /* R7129 */ + { 0x0000, 0x0000, 0x0000 }, /* R7130 */ + { 0x0000, 0x0000, 0x0000 }, /* R7131 */ + { 0x0000, 0x0000, 0x0000 }, /* R7132 */ + { 0x0000, 0x0000, 0x0000 }, /* R7133 */ + { 0x0000, 0x0000, 0x0000 }, /* R7134 */ + { 0x0000, 0x0000, 0x0000 }, /* R7135 */ + { 0x0000, 0x0000, 0x0000 }, /* R7136 */ + { 0x0000, 0x0000, 0x0000 }, /* R7137 */ + { 0x0000, 0x0000, 0x0000 }, /* R7138 */ + { 0x0000, 0x0000, 0x0000 }, /* R7139 */ + { 0x0000, 0x0000, 0x0000 }, /* R7140 */ + { 0x0000, 0x0000, 0x0000 }, /* R7141 */ + { 0x0000, 0x0000, 0x0000 }, /* R7142 */ + { 0x0000, 0x0000, 0x0000 }, /* R7143 */ + { 0x0000, 0x0000, 0x0000 }, /* R7144 */ + { 0x0000, 0x0000, 0x0000 }, /* R7145 */ + { 0x0000, 0x0000, 0x0000 }, /* R7146 */ + { 0x0000, 0x0000, 0x0000 }, /* R7147 */ + { 0x0000, 0x0000, 0x0000 }, /* R7148 */ + { 0x0000, 0x0000, 0x0000 }, /* R7149 */ + { 0x0000, 0x0000, 0x0000 }, /* R7150 */ + { 0x0000, 0x0000, 0x0000 }, /* R7151 */ + { 0x0000, 0x0000, 0x0000 }, /* R7152 */ + { 0x0000, 0x0000, 0x0000 }, /* R7153 */ + { 0x0000, 0x0000, 0x0000 }, /* R7154 */ + { 0x0000, 0x0000, 0x0000 }, /* R7155 */ + { 0x0000, 0x0000, 0x0000 }, /* R7156 */ + { 0x0000, 0x0000, 0x0000 }, /* R7157 */ + { 0x0000, 0x0000, 0x0000 }, /* R7158 */ + { 0x0000, 0x0000, 0x0000 }, /* R7159 */ + { 0x0000, 0x0000, 0x0000 }, /* R7160 */ + { 0x0000, 0x0000, 0x0000 }, /* R7161 */ + { 0x0000, 0x0000, 0x0000 }, /* R7162 */ + { 0x0000, 0x0000, 0x0000 }, /* R7163 */ + { 0x0000, 0x0000, 0x0000 }, /* R7164 */ + { 0x0000, 0x0000, 0x0000 }, /* R7165 */ + { 0x0000, 0x0000, 0x0000 }, /* R7166 */ + { 0x0000, 0x0000, 0x0000 }, /* R7167 */ + { 0x0000, 0x0000, 0x0000 }, /* R7168 */ + { 0x0000, 0x0000, 0x0000 }, /* R7169 */ + { 0x0000, 0x0000, 0x0000 }, /* R7170 */ + { 0x0000, 0x0000, 0x0000 }, /* R7171 */ + { 0x0000, 0x0000, 0x0000 }, /* R7172 */ + { 0x0000, 0x0000, 0x0000 }, /* R7173 */ + { 0x0000, 0x0000, 0x0000 }, /* R7174 */ + { 0x0000, 0x0000, 0x0000 }, /* R7175 */ + { 0x0000, 0x0000, 0x0000 }, /* R7176 */ + { 0x0000, 0x0000, 0x0000 }, /* R7177 */ + { 0x0000, 0x0000, 0x0000 }, /* R7178 */ + { 0x0000, 0x0000, 0x0000 }, /* R7179 */ + { 0x0000, 0x0000, 0x0000 }, /* R7180 */ + { 0x0000, 0x0000, 0x0000 }, /* R7181 */ + { 0x0000, 0x0000, 0x0000 }, /* R7182 */ + { 0x0000, 0x0000, 0x0000 }, /* R7183 */ + { 0x0000, 0x0000, 0x0000 }, /* R7184 */ + { 0x0000, 0x0000, 0x0000 }, /* R7185 */ + { 0x0000, 0x0000, 0x0000 }, /* R7186 */ + { 0x0000, 0x0000, 0x0000 }, /* R7187 */ + { 0x0000, 0x0000, 0x0000 }, /* R7188 */ + { 0x0000, 0x0000, 0x0000 }, /* R7189 */ + { 0x0000, 0x0000, 0x0000 }, /* R7190 */ + { 0x0000, 0x0000, 0x0000 }, /* R7191 */ + { 0x0000, 0x0000, 0x0000 }, /* R7192 */ + { 0x0000, 0x0000, 0x0000 }, /* R7193 */ + { 0x0000, 0x0000, 0x0000 }, /* R7194 */ + { 0x0000, 0x0000, 0x0000 }, /* R7195 */ + { 0x0000, 0x0000, 0x0000 }, /* R7196 */ + { 0x0000, 0x0000, 0x0000 }, /* R7197 */ + { 0x0000, 0x0000, 0x0000 }, /* R7198 */ + { 0x0000, 0x0000, 0x0000 }, /* R7199 */ + { 0x0000, 0x0000, 0x0000 }, /* R7200 */ + { 0x0000, 0x0000, 0x0000 }, /* R7201 */ + { 0x0000, 0x0000, 0x0000 }, /* R7202 */ + { 0x0000, 0x0000, 0x0000 }, /* R7203 */ + { 0x0000, 0x0000, 0x0000 }, /* R7204 */ + { 0x0000, 0x0000, 0x0000 }, /* R7205 */ + { 0x0000, 0x0000, 0x0000 }, /* R7206 */ + { 0x0000, 0x0000, 0x0000 }, /* R7207 */ + { 0x0000, 0x0000, 0x0000 }, /* R7208 */ + { 0x0000, 0x0000, 0x0000 }, /* R7209 */ + { 0x0000, 0x0000, 0x0000 }, /* R7210 */ + { 0x0000, 0x0000, 0x0000 }, /* R7211 */ + { 0x0000, 0x0000, 0x0000 }, /* R7212 */ + { 0x0000, 0x0000, 0x0000 }, /* R7213 */ + { 0x0000, 0x0000, 0x0000 }, /* R7214 */ + { 0x0000, 0x0000, 0x0000 }, /* R7215 */ + { 0x0000, 0x0000, 0x0000 }, /* R7216 */ + { 0x0000, 0x0000, 0x0000 }, /* R7217 */ + { 0x0000, 0x0000, 0x0000 }, /* R7218 */ + { 0x0000, 0x0000, 0x0000 }, /* R7219 */ + { 0x0000, 0x0000, 0x0000 }, /* R7220 */ + { 0x0000, 0x0000, 0x0000 }, /* R7221 */ + { 0x0000, 0x0000, 0x0000 }, /* R7222 */ + { 0x0000, 0x0000, 0x0000 }, /* R7223 */ + { 0x0000, 0x0000, 0x0000 }, /* R7224 */ + { 0x0000, 0x0000, 0x0000 }, /* R7225 */ + { 0x0000, 0x0000, 0x0000 }, /* R7226 */ + { 0x0000, 0x0000, 0x0000 }, /* R7227 */ + { 0x0000, 0x0000, 0x0000 }, /* R7228 */ + { 0x0000, 0x0000, 0x0000 }, /* R7229 */ + { 0x0000, 0x0000, 0x0000 }, /* R7230 */ + { 0x0000, 0x0000, 0x0000 }, /* R7231 */ + { 0x0000, 0x0000, 0x0000 }, /* R7232 */ + { 0x0000, 0x0000, 0x0000 }, /* R7233 */ + { 0x0000, 0x0000, 0x0000 }, /* R7234 */ + { 0x0000, 0x0000, 0x0000 }, /* R7235 */ + { 0x0000, 0x0000, 0x0000 }, /* R7236 */ + { 0x0000, 0x0000, 0x0000 }, /* R7237 */ + { 0x0000, 0x0000, 0x0000 }, /* R7238 */ + { 0x0000, 0x0000, 0x0000 }, /* R7239 */ + { 0x0000, 0x0000, 0x0000 }, /* R7240 */ + { 0x0000, 0x0000, 0x0000 }, /* R7241 */ + { 0x0000, 0x0000, 0x0000 }, /* R7242 */ + { 0x0000, 0x0000, 0x0000 }, /* R7243 */ + { 0x0000, 0x0000, 0x0000 }, /* R7244 */ + { 0x0000, 0x0000, 0x0000 }, /* R7245 */ + { 0x0000, 0x0000, 0x0000 }, /* R7246 */ + { 0x0000, 0x0000, 0x0000 }, /* R7247 */ + { 0x0000, 0x0000, 0x0000 }, /* R7248 */ + { 0x0000, 0x0000, 0x0000 }, /* R7249 */ + { 0x0000, 0x0000, 0x0000 }, /* R7250 */ + { 0x0000, 0x0000, 0x0000 }, /* R7251 */ + { 0x0000, 0x0000, 0x0000 }, /* R7252 */ + { 0x0000, 0x0000, 0x0000 }, /* R7253 */ + { 0x0000, 0x0000, 0x0000 }, /* R7254 */ + { 0x0000, 0x0000, 0x0000 }, /* R7255 */ + { 0x0000, 0x0000, 0x0000 }, /* R7256 */ + { 0x0000, 0x0000, 0x0000 }, /* R7257 */ + { 0x0000, 0x0000, 0x0000 }, /* R7258 */ + { 0x0000, 0x0000, 0x0000 }, /* R7259 */ + { 0x0000, 0x0000, 0x0000 }, /* R7260 */ + { 0x0000, 0x0000, 0x0000 }, /* R7261 */ + { 0x0000, 0x0000, 0x0000 }, /* R7262 */ + { 0x0000, 0x0000, 0x0000 }, /* R7263 */ + { 0x0000, 0x0000, 0x0000 }, /* R7264 */ + { 0x0000, 0x0000, 0x0000 }, /* R7265 */ + { 0x0000, 0x0000, 0x0000 }, /* R7266 */ + { 0x0000, 0x0000, 0x0000 }, /* R7267 */ + { 0x0000, 0x0000, 0x0000 }, /* R7268 */ + { 0x0000, 0x0000, 0x0000 }, /* R7269 */ + { 0x0000, 0x0000, 0x0000 }, /* R7270 */ + { 0x0000, 0x0000, 0x0000 }, /* R7271 */ + { 0x0000, 0x0000, 0x0000 }, /* R7272 */ + { 0x0000, 0x0000, 0x0000 }, /* R7273 */ + { 0x0000, 0x0000, 0x0000 }, /* R7274 */ + { 0x0000, 0x0000, 0x0000 }, /* R7275 */ + { 0x0000, 0x0000, 0x0000 }, /* R7276 */ + { 0x0000, 0x0000, 0x0000 }, /* R7277 */ + { 0x0000, 0x0000, 0x0000 }, /* R7278 */ + { 0x0000, 0x0000, 0x0000 }, /* R7279 */ + { 0x0000, 0x0000, 0x0000 }, /* R7280 */ + { 0x0000, 0x0000, 0x0000 }, /* R7281 */ + { 0x0000, 0x0000, 0x0000 }, /* R7282 */ + { 0x0000, 0x0000, 0x0000 }, /* R7283 */ + { 0x0000, 0x0000, 0x0000 }, /* R7284 */ + { 0x0000, 0x0000, 0x0000 }, /* R7285 */ + { 0x0000, 0x0000, 0x0000 }, /* R7286 */ + { 0x0000, 0x0000, 0x0000 }, /* R7287 */ + { 0x0000, 0x0000, 0x0000 }, /* R7288 */ + { 0x0000, 0x0000, 0x0000 }, /* R7289 */ + { 0x0000, 0x0000, 0x0000 }, /* R7290 */ + { 0x0000, 0x0000, 0x0000 }, /* R7291 */ + { 0x0000, 0x0000, 0x0000 }, /* R7292 */ + { 0x0000, 0x0000, 0x0000 }, /* R7293 */ + { 0x0000, 0x0000, 0x0000 }, /* R7294 */ + { 0x0000, 0x0000, 0x0000 }, /* R7295 */ + { 0x0000, 0x0000, 0x0000 }, /* R7296 */ + { 0x0000, 0x0000, 0x0000 }, /* R7297 */ + { 0x0000, 0x0000, 0x0000 }, /* R7298 */ + { 0x0000, 0x0000, 0x0000 }, /* R7299 */ + { 0x0000, 0x0000, 0x0000 }, /* R7300 */ + { 0x0000, 0x0000, 0x0000 }, /* R7301 */ + { 0x0000, 0x0000, 0x0000 }, /* R7302 */ + { 0x0000, 0x0000, 0x0000 }, /* R7303 */ + { 0x0000, 0x0000, 0x0000 }, /* R7304 */ + { 0x0000, 0x0000, 0x0000 }, /* R7305 */ + { 0x0000, 0x0000, 0x0000 }, /* R7306 */ + { 0x0000, 0x0000, 0x0000 }, /* R7307 */ + { 0x0000, 0x0000, 0x0000 }, /* R7308 */ + { 0x0000, 0x0000, 0x0000 }, /* R7309 */ + { 0x0000, 0x0000, 0x0000 }, /* R7310 */ + { 0x0000, 0x0000, 0x0000 }, /* R7311 */ + { 0x0000, 0x0000, 0x0000 }, /* R7312 */ + { 0x0000, 0x0000, 0x0000 }, /* R7313 */ + { 0x0000, 0x0000, 0x0000 }, /* R7314 */ + { 0x0000, 0x0000, 0x0000 }, /* R7315 */ + { 0x0000, 0x0000, 0x0000 }, /* R7316 */ + { 0x0000, 0x0000, 0x0000 }, /* R7317 */ + { 0x0000, 0x0000, 0x0000 }, /* R7318 */ + { 0x0000, 0x0000, 0x0000 }, /* R7319 */ + { 0x0000, 0x0000, 0x0000 }, /* R7320 */ + { 0x0000, 0x0000, 0x0000 }, /* R7321 */ + { 0x0000, 0x0000, 0x0000 }, /* R7322 */ + { 0x0000, 0x0000, 0x0000 }, /* R7323 */ + { 0x0000, 0x0000, 0x0000 }, /* R7324 */ + { 0x0000, 0x0000, 0x0000 }, /* R7325 */ + { 0x0000, 0x0000, 0x0000 }, /* R7326 */ + { 0x0000, 0x0000, 0x0000 }, /* R7327 */ + { 0x0000, 0x0000, 0x0000 }, /* R7328 */ + { 0x0000, 0x0000, 0x0000 }, /* R7329 */ + { 0x0000, 0x0000, 0x0000 }, /* R7330 */ + { 0x0000, 0x0000, 0x0000 }, /* R7331 */ + { 0x0000, 0x0000, 0x0000 }, /* R7332 */ + { 0x0000, 0x0000, 0x0000 }, /* R7333 */ + { 0x0000, 0x0000, 0x0000 }, /* R7334 */ + { 0x0000, 0x0000, 0x0000 }, /* R7335 */ + { 0x0000, 0x0000, 0x0000 }, /* R7336 */ + { 0x0000, 0x0000, 0x0000 }, /* R7337 */ + { 0x0000, 0x0000, 0x0000 }, /* R7338 */ + { 0x0000, 0x0000, 0x0000 }, /* R7339 */ + { 0x0000, 0x0000, 0x0000 }, /* R7340 */ + { 0x0000, 0x0000, 0x0000 }, /* R7341 */ + { 0x0000, 0x0000, 0x0000 }, /* R7342 */ + { 0x0000, 0x0000, 0x0000 }, /* R7343 */ + { 0x0000, 0x0000, 0x0000 }, /* R7344 */ + { 0x0000, 0x0000, 0x0000 }, /* R7345 */ + { 0x0000, 0x0000, 0x0000 }, /* R7346 */ + { 0x0000, 0x0000, 0x0000 }, /* R7347 */ + { 0x0000, 0x0000, 0x0000 }, /* R7348 */ + { 0x0000, 0x0000, 0x0000 }, /* R7349 */ + { 0x0000, 0x0000, 0x0000 }, /* R7350 */ + { 0x0000, 0x0000, 0x0000 }, /* R7351 */ + { 0x0000, 0x0000, 0x0000 }, /* R7352 */ + { 0x0000, 0x0000, 0x0000 }, /* R7353 */ + { 0x0000, 0x0000, 0x0000 }, /* R7354 */ + { 0x0000, 0x0000, 0x0000 }, /* R7355 */ + { 0x0000, 0x0000, 0x0000 }, /* R7356 */ + { 0x0000, 0x0000, 0x0000 }, /* R7357 */ + { 0x0000, 0x0000, 0x0000 }, /* R7358 */ + { 0x0000, 0x0000, 0x0000 }, /* R7359 */ + { 0x0000, 0x0000, 0x0000 }, /* R7360 */ + { 0x0000, 0x0000, 0x0000 }, /* R7361 */ + { 0x0000, 0x0000, 0x0000 }, /* R7362 */ + { 0x0000, 0x0000, 0x0000 }, /* R7363 */ + { 0x0000, 0x0000, 0x0000 }, /* R7364 */ + { 0x0000, 0x0000, 0x0000 }, /* R7365 */ + { 0x0000, 0x0000, 0x0000 }, /* R7366 */ + { 0x0000, 0x0000, 0x0000 }, /* R7367 */ + { 0x0000, 0x0000, 0x0000 }, /* R7368 */ + { 0x0000, 0x0000, 0x0000 }, /* R7369 */ + { 0x0000, 0x0000, 0x0000 }, /* R7370 */ + { 0x0000, 0x0000, 0x0000 }, /* R7371 */ + { 0x0000, 0x0000, 0x0000 }, /* R7372 */ + { 0x0000, 0x0000, 0x0000 }, /* R7373 */ + { 0x0000, 0x0000, 0x0000 }, /* R7374 */ + { 0x0000, 0x0000, 0x0000 }, /* R7375 */ + { 0x0000, 0x0000, 0x0000 }, /* R7376 */ + { 0x0000, 0x0000, 0x0000 }, /* R7377 */ + { 0x0000, 0x0000, 0x0000 }, /* R7378 */ + { 0x0000, 0x0000, 0x0000 }, /* R7379 */ + { 0x0000, 0x0000, 0x0000 }, /* R7380 */ + { 0x0000, 0x0000, 0x0000 }, /* R7381 */ + { 0x0000, 0x0000, 0x0000 }, /* R7382 */ + { 0x0000, 0x0000, 0x0000 }, /* R7383 */ + { 0x0000, 0x0000, 0x0000 }, /* R7384 */ + { 0x0000, 0x0000, 0x0000 }, /* R7385 */ + { 0x0000, 0x0000, 0x0000 }, /* R7386 */ + { 0x0000, 0x0000, 0x0000 }, /* R7387 */ + { 0x0000, 0x0000, 0x0000 }, /* R7388 */ + { 0x0000, 0x0000, 0x0000 }, /* R7389 */ + { 0x0000, 0x0000, 0x0000 }, /* R7390 */ + { 0x0000, 0x0000, 0x0000 }, /* R7391 */ + { 0x0000, 0x0000, 0x0000 }, /* R7392 */ + { 0x0000, 0x0000, 0x0000 }, /* R7393 */ + { 0x0000, 0x0000, 0x0000 }, /* R7394 */ + { 0x0000, 0x0000, 0x0000 }, /* R7395 */ + { 0x0000, 0x0000, 0x0000 }, /* R7396 */ + { 0x0000, 0x0000, 0x0000 }, /* R7397 */ + { 0x0000, 0x0000, 0x0000 }, /* R7398 */ + { 0x0000, 0x0000, 0x0000 }, /* R7399 */ + { 0x0000, 0x0000, 0x0000 }, /* R7400 */ + { 0x0000, 0x0000, 0x0000 }, /* R7401 */ + { 0x0000, 0x0000, 0x0000 }, /* R7402 */ + { 0x0000, 0x0000, 0x0000 }, /* R7403 */ + { 0x0000, 0x0000, 0x0000 }, /* R7404 */ + { 0x0000, 0x0000, 0x0000 }, /* R7405 */ + { 0x0000, 0x0000, 0x0000 }, /* R7406 */ + { 0x0000, 0x0000, 0x0000 }, /* R7407 */ + { 0x0000, 0x0000, 0x0000 }, /* R7408 */ + { 0x0000, 0x0000, 0x0000 }, /* R7409 */ + { 0x0000, 0x0000, 0x0000 }, /* R7410 */ + { 0x0000, 0x0000, 0x0000 }, /* R7411 */ + { 0x0000, 0x0000, 0x0000 }, /* R7412 */ + { 0x0000, 0x0000, 0x0000 }, /* R7413 */ + { 0x0000, 0x0000, 0x0000 }, /* R7414 */ + { 0x0000, 0x0000, 0x0000 }, /* R7415 */ + { 0x0000, 0x0000, 0x0000 }, /* R7416 */ + { 0x0000, 0x0000, 0x0000 }, /* R7417 */ + { 0x0000, 0x0000, 0x0000 }, /* R7418 */ + { 0x0000, 0x0000, 0x0000 }, /* R7419 */ + { 0x0000, 0x0000, 0x0000 }, /* R7420 */ + { 0x0000, 0x0000, 0x0000 }, /* R7421 */ + { 0x0000, 0x0000, 0x0000 }, /* R7422 */ + { 0x0000, 0x0000, 0x0000 }, /* R7423 */ + { 0x0000, 0x0000, 0x0000 }, /* R7424 */ + { 0x0000, 0x0000, 0x0000 }, /* R7425 */ + { 0x0000, 0x0000, 0x0000 }, /* R7426 */ + { 0x0000, 0x0000, 0x0000 }, /* R7427 */ + { 0x0000, 0x0000, 0x0000 }, /* R7428 */ + { 0x0000, 0x0000, 0x0000 }, /* R7429 */ + { 0x0000, 0x0000, 0x0000 }, /* R7430 */ + { 0x0000, 0x0000, 0x0000 }, /* R7431 */ + { 0x0000, 0x0000, 0x0000 }, /* R7432 */ + { 0x0000, 0x0000, 0x0000 }, /* R7433 */ + { 0x0000, 0x0000, 0x0000 }, /* R7434 */ + { 0x0000, 0x0000, 0x0000 }, /* R7435 */ + { 0x0000, 0x0000, 0x0000 }, /* R7436 */ + { 0x0000, 0x0000, 0x0000 }, /* R7437 */ + { 0x0000, 0x0000, 0x0000 }, /* R7438 */ + { 0x0000, 0x0000, 0x0000 }, /* R7439 */ + { 0x0000, 0x0000, 0x0000 }, /* R7440 */ + { 0x0000, 0x0000, 0x0000 }, /* R7441 */ + { 0x0000, 0x0000, 0x0000 }, /* R7442 */ + { 0x0000, 0x0000, 0x0000 }, /* R7443 */ + { 0x0000, 0x0000, 0x0000 }, /* R7444 */ + { 0x0000, 0x0000, 0x0000 }, /* R7445 */ + { 0x0000, 0x0000, 0x0000 }, /* R7446 */ + { 0x0000, 0x0000, 0x0000 }, /* R7447 */ + { 0x0000, 0x0000, 0x0000 }, /* R7448 */ + { 0x0000, 0x0000, 0x0000 }, /* R7449 */ + { 0x0000, 0x0000, 0x0000 }, /* R7450 */ + { 0x0000, 0x0000, 0x0000 }, /* R7451 */ + { 0x0000, 0x0000, 0x0000 }, /* R7452 */ + { 0x0000, 0x0000, 0x0000 }, /* R7453 */ + { 0x0000, 0x0000, 0x0000 }, /* R7454 */ + { 0x0000, 0x0000, 0x0000 }, /* R7455 */ + { 0x0000, 0x0000, 0x0000 }, /* R7456 */ + { 0x0000, 0x0000, 0x0000 }, /* R7457 */ + { 0x0000, 0x0000, 0x0000 }, /* R7458 */ + { 0x0000, 0x0000, 0x0000 }, /* R7459 */ + { 0x0000, 0x0000, 0x0000 }, /* R7460 */ + { 0x0000, 0x0000, 0x0000 }, /* R7461 */ + { 0x0000, 0x0000, 0x0000 }, /* R7462 */ + { 0x0000, 0x0000, 0x0000 }, /* R7463 */ + { 0x0000, 0x0000, 0x0000 }, /* R7464 */ + { 0x0000, 0x0000, 0x0000 }, /* R7465 */ + { 0x0000, 0x0000, 0x0000 }, /* R7466 */ + { 0x0000, 0x0000, 0x0000 }, /* R7467 */ + { 0x0000, 0x0000, 0x0000 }, /* R7468 */ + { 0x0000, 0x0000, 0x0000 }, /* R7469 */ + { 0x0000, 0x0000, 0x0000 }, /* R7470 */ + { 0x0000, 0x0000, 0x0000 }, /* R7471 */ + { 0x0000, 0x0000, 0x0000 }, /* R7472 */ + { 0x0000, 0x0000, 0x0000 }, /* R7473 */ + { 0x0000, 0x0000, 0x0000 }, /* R7474 */ + { 0x0000, 0x0000, 0x0000 }, /* R7475 */ + { 0x0000, 0x0000, 0x0000 }, /* R7476 */ + { 0x0000, 0x0000, 0x0000 }, /* R7477 */ + { 0x0000, 0x0000, 0x0000 }, /* R7478 */ + { 0x0000, 0x0000, 0x0000 }, /* R7479 */ + { 0x0000, 0x0000, 0x0000 }, /* R7480 */ + { 0x0000, 0x0000, 0x0000 }, /* R7481 */ + { 0x0000, 0x0000, 0x0000 }, /* R7482 */ + { 0x0000, 0x0000, 0x0000 }, /* R7483 */ + { 0x0000, 0x0000, 0x0000 }, /* R7484 */ + { 0x0000, 0x0000, 0x0000 }, /* R7485 */ + { 0x0000, 0x0000, 0x0000 }, /* R7486 */ + { 0x0000, 0x0000, 0x0000 }, /* R7487 */ + { 0x0000, 0x0000, 0x0000 }, /* R7488 */ + { 0x0000, 0x0000, 0x0000 }, /* R7489 */ + { 0x0000, 0x0000, 0x0000 }, /* R7490 */ + { 0x0000, 0x0000, 0x0000 }, /* R7491 */ + { 0x0000, 0x0000, 0x0000 }, /* R7492 */ + { 0x0000, 0x0000, 0x0000 }, /* R7493 */ + { 0x0000, 0x0000, 0x0000 }, /* R7494 */ + { 0x0000, 0x0000, 0x0000 }, /* R7495 */ + { 0x0000, 0x0000, 0x0000 }, /* R7496 */ + { 0x0000, 0x0000, 0x0000 }, /* R7497 */ + { 0x0000, 0x0000, 0x0000 }, /* R7498 */ + { 0x0000, 0x0000, 0x0000 }, /* R7499 */ + { 0x0000, 0x0000, 0x0000 }, /* R7500 */ + { 0x0000, 0x0000, 0x0000 }, /* R7501 */ + { 0x0000, 0x0000, 0x0000 }, /* R7502 */ + { 0x0000, 0x0000, 0x0000 }, /* R7503 */ + { 0x0000, 0x0000, 0x0000 }, /* R7504 */ + { 0x0000, 0x0000, 0x0000 }, /* R7505 */ + { 0x0000, 0x0000, 0x0000 }, /* R7506 */ + { 0x0000, 0x0000, 0x0000 }, /* R7507 */ + { 0x0000, 0x0000, 0x0000 }, /* R7508 */ + { 0x0000, 0x0000, 0x0000 }, /* R7509 */ + { 0x0000, 0x0000, 0x0000 }, /* R7510 */ + { 0x0000, 0x0000, 0x0000 }, /* R7511 */ + { 0x0000, 0x0000, 0x0000 }, /* R7512 */ + { 0x0000, 0x0000, 0x0000 }, /* R7513 */ + { 0x0000, 0x0000, 0x0000 }, /* R7514 */ + { 0x0000, 0x0000, 0x0000 }, /* R7515 */ + { 0x0000, 0x0000, 0x0000 }, /* R7516 */ + { 0x0000, 0x0000, 0x0000 }, /* R7517 */ + { 0x0000, 0x0000, 0x0000 }, /* R7518 */ + { 0x0000, 0x0000, 0x0000 }, /* R7519 */ + { 0x0000, 0x0000, 0x0000 }, /* R7520 */ + { 0x0000, 0x0000, 0x0000 }, /* R7521 */ + { 0x0000, 0x0000, 0x0000 }, /* R7522 */ + { 0x0000, 0x0000, 0x0000 }, /* R7523 */ + { 0x0000, 0x0000, 0x0000 }, /* R7524 */ + { 0x0000, 0x0000, 0x0000 }, /* R7525 */ + { 0x0000, 0x0000, 0x0000 }, /* R7526 */ + { 0x0000, 0x0000, 0x0000 }, /* R7527 */ + { 0x0000, 0x0000, 0x0000 }, /* R7528 */ + { 0x0000, 0x0000, 0x0000 }, /* R7529 */ + { 0x0000, 0x0000, 0x0000 }, /* R7530 */ + { 0x0000, 0x0000, 0x0000 }, /* R7531 */ + { 0x0000, 0x0000, 0x0000 }, /* R7532 */ + { 0x0000, 0x0000, 0x0000 }, /* R7533 */ + { 0x0000, 0x0000, 0x0000 }, /* R7534 */ + { 0x0000, 0x0000, 0x0000 }, /* R7535 */ + { 0x0000, 0x0000, 0x0000 }, /* R7536 */ + { 0x0000, 0x0000, 0x0000 }, /* R7537 */ + { 0x0000, 0x0000, 0x0000 }, /* R7538 */ + { 0x0000, 0x0000, 0x0000 }, /* R7539 */ + { 0x0000, 0x0000, 0x0000 }, /* R7540 */ + { 0x0000, 0x0000, 0x0000 }, /* R7541 */ + { 0x0000, 0x0000, 0x0000 }, /* R7542 */ + { 0x0000, 0x0000, 0x0000 }, /* R7543 */ + { 0x0000, 0x0000, 0x0000 }, /* R7544 */ + { 0x0000, 0x0000, 0x0000 }, /* R7545 */ + { 0x0000, 0x0000, 0x0000 }, /* R7546 */ + { 0x0000, 0x0000, 0x0000 }, /* R7547 */ + { 0x0000, 0x0000, 0x0000 }, /* R7548 */ + { 0x0000, 0x0000, 0x0000 }, /* R7549 */ + { 0x0000, 0x0000, 0x0000 }, /* R7550 */ + { 0x0000, 0x0000, 0x0000 }, /* R7551 */ + { 0x0000, 0x0000, 0x0000 }, /* R7552 */ + { 0x0000, 0x0000, 0x0000 }, /* R7553 */ + { 0x0000, 0x0000, 0x0000 }, /* R7554 */ + { 0x0000, 0x0000, 0x0000 }, /* R7555 */ + { 0x0000, 0x0000, 0x0000 }, /* R7556 */ + { 0x0000, 0x0000, 0x0000 }, /* R7557 */ + { 0x0000, 0x0000, 0x0000 }, /* R7558 */ + { 0x0000, 0x0000, 0x0000 }, /* R7559 */ + { 0x0000, 0x0000, 0x0000 }, /* R7560 */ + { 0x0000, 0x0000, 0x0000 }, /* R7561 */ + { 0x0000, 0x0000, 0x0000 }, /* R7562 */ + { 0x0000, 0x0000, 0x0000 }, /* R7563 */ + { 0x0000, 0x0000, 0x0000 }, /* R7564 */ + { 0x0000, 0x0000, 0x0000 }, /* R7565 */ + { 0x0000, 0x0000, 0x0000 }, /* R7566 */ + { 0x0000, 0x0000, 0x0000 }, /* R7567 */ + { 0x0000, 0x0000, 0x0000 }, /* R7568 */ + { 0x0000, 0x0000, 0x0000 }, /* R7569 */ + { 0x0000, 0x0000, 0x0000 }, /* R7570 */ + { 0x0000, 0x0000, 0x0000 }, /* R7571 */ + { 0x0000, 0x0000, 0x0000 }, /* R7572 */ + { 0x0000, 0x0000, 0x0000 }, /* R7573 */ + { 0x0000, 0x0000, 0x0000 }, /* R7574 */ + { 0x0000, 0x0000, 0x0000 }, /* R7575 */ + { 0x0000, 0x0000, 0x0000 }, /* R7576 */ + { 0x0000, 0x0000, 0x0000 }, /* R7577 */ + { 0x0000, 0x0000, 0x0000 }, /* R7578 */ + { 0x0000, 0x0000, 0x0000 }, /* R7579 */ + { 0x0000, 0x0000, 0x0000 }, /* R7580 */ + { 0x0000, 0x0000, 0x0000 }, /* R7581 */ + { 0x0000, 0x0000, 0x0000 }, /* R7582 */ + { 0x0000, 0x0000, 0x0000 }, /* R7583 */ + { 0x0000, 0x0000, 0x0000 }, /* R7584 */ + { 0x0000, 0x0000, 0x0000 }, /* R7585 */ + { 0x0000, 0x0000, 0x0000 }, /* R7586 */ + { 0x0000, 0x0000, 0x0000 }, /* R7587 */ + { 0x0000, 0x0000, 0x0000 }, /* R7588 */ + { 0x0000, 0x0000, 0x0000 }, /* R7589 */ + { 0x0000, 0x0000, 0x0000 }, /* R7590 */ + { 0x0000, 0x0000, 0x0000 }, /* R7591 */ + { 0x0000, 0x0000, 0x0000 }, /* R7592 */ + { 0x0000, 0x0000, 0x0000 }, /* R7593 */ + { 0x0000, 0x0000, 0x0000 }, /* R7594 */ + { 0x0000, 0x0000, 0x0000 }, /* R7595 */ + { 0x0000, 0x0000, 0x0000 }, /* R7596 */ + { 0x0000, 0x0000, 0x0000 }, /* R7597 */ + { 0x0000, 0x0000, 0x0000 }, /* R7598 */ + { 0x0000, 0x0000, 0x0000 }, /* R7599 */ + { 0x0000, 0x0000, 0x0000 }, /* R7600 */ + { 0x0000, 0x0000, 0x0000 }, /* R7601 */ + { 0x0000, 0x0000, 0x0000 }, /* R7602 */ + { 0x0000, 0x0000, 0x0000 }, /* R7603 */ + { 0x0000, 0x0000, 0x0000 }, /* R7604 */ + { 0x0000, 0x0000, 0x0000 }, /* R7605 */ + { 0x0000, 0x0000, 0x0000 }, /* R7606 */ + { 0x0000, 0x0000, 0x0000 }, /* R7607 */ + { 0x0000, 0x0000, 0x0000 }, /* R7608 */ + { 0x0000, 0x0000, 0x0000 }, /* R7609 */ + { 0x0000, 0x0000, 0x0000 }, /* R7610 */ + { 0x0000, 0x0000, 0x0000 }, /* R7611 */ + { 0x0000, 0x0000, 0x0000 }, /* R7612 */ + { 0x0000, 0x0000, 0x0000 }, /* R7613 */ + { 0x0000, 0x0000, 0x0000 }, /* R7614 */ + { 0x0000, 0x0000, 0x0000 }, /* R7615 */ + { 0x0000, 0x0000, 0x0000 }, /* R7616 */ + { 0x0000, 0x0000, 0x0000 }, /* R7617 */ + { 0x0000, 0x0000, 0x0000 }, /* R7618 */ + { 0x0000, 0x0000, 0x0000 }, /* R7619 */ + { 0x0000, 0x0000, 0x0000 }, /* R7620 */ + { 0x0000, 0x0000, 0x0000 }, /* R7621 */ + { 0x0000, 0x0000, 0x0000 }, /* R7622 */ + { 0x0000, 0x0000, 0x0000 }, /* R7623 */ + { 0x0000, 0x0000, 0x0000 }, /* R7624 */ + { 0x0000, 0x0000, 0x0000 }, /* R7625 */ + { 0x0000, 0x0000, 0x0000 }, /* R7626 */ + { 0x0000, 0x0000, 0x0000 }, /* R7627 */ + { 0x0000, 0x0000, 0x0000 }, /* R7628 */ + { 0x0000, 0x0000, 0x0000 }, /* R7629 */ + { 0x0000, 0x0000, 0x0000 }, /* R7630 */ + { 0x0000, 0x0000, 0x0000 }, /* R7631 */ + { 0x0000, 0x0000, 0x0000 }, /* R7632 */ + { 0x0000, 0x0000, 0x0000 }, /* R7633 */ + { 0x0000, 0x0000, 0x0000 }, /* R7634 */ + { 0x0000, 0x0000, 0x0000 }, /* R7635 */ + { 0x0000, 0x0000, 0x0000 }, /* R7636 */ + { 0x0000, 0x0000, 0x0000 }, /* R7637 */ + { 0x0000, 0x0000, 0x0000 }, /* R7638 */ + { 0x0000, 0x0000, 0x0000 }, /* R7639 */ + { 0x0000, 0x0000, 0x0000 }, /* R7640 */ + { 0x0000, 0x0000, 0x0000 }, /* R7641 */ + { 0x0000, 0x0000, 0x0000 }, /* R7642 */ + { 0x0000, 0x0000, 0x0000 }, /* R7643 */ + { 0x0000, 0x0000, 0x0000 }, /* R7644 */ + { 0x0000, 0x0000, 0x0000 }, /* R7645 */ + { 0x0000, 0x0000, 0x0000 }, /* R7646 */ + { 0x0000, 0x0000, 0x0000 }, /* R7647 */ + { 0x0000, 0x0000, 0x0000 }, /* R7648 */ + { 0x0000, 0x0000, 0x0000 }, /* R7649 */ + { 0x0000, 0x0000, 0x0000 }, /* R7650 */ + { 0x0000, 0x0000, 0x0000 }, /* R7651 */ + { 0x0000, 0x0000, 0x0000 }, /* R7652 */ + { 0x0000, 0x0000, 0x0000 }, /* R7653 */ + { 0x0000, 0x0000, 0x0000 }, /* R7654 */ + { 0x0000, 0x0000, 0x0000 }, /* R7655 */ + { 0x0000, 0x0000, 0x0000 }, /* R7656 */ + { 0x0000, 0x0000, 0x0000 }, /* R7657 */ + { 0x0000, 0x0000, 0x0000 }, /* R7658 */ + { 0x0000, 0x0000, 0x0000 }, /* R7659 */ + { 0x0000, 0x0000, 0x0000 }, /* R7660 */ + { 0x0000, 0x0000, 0x0000 }, /* R7661 */ + { 0x0000, 0x0000, 0x0000 }, /* R7662 */ + { 0x0000, 0x0000, 0x0000 }, /* R7663 */ + { 0x0000, 0x0000, 0x0000 }, /* R7664 */ + { 0x0000, 0x0000, 0x0000 }, /* R7665 */ + { 0x0000, 0x0000, 0x0000 }, /* R7666 */ + { 0x0000, 0x0000, 0x0000 }, /* R7667 */ + { 0x0000, 0x0000, 0x0000 }, /* R7668 */ + { 0x0000, 0x0000, 0x0000 }, /* R7669 */ + { 0x0000, 0x0000, 0x0000 }, /* R7670 */ + { 0x0000, 0x0000, 0x0000 }, /* R7671 */ + { 0x0000, 0x0000, 0x0000 }, /* R7672 */ + { 0x0000, 0x0000, 0x0000 }, /* R7673 */ + { 0x0000, 0x0000, 0x0000 }, /* R7674 */ + { 0x0000, 0x0000, 0x0000 }, /* R7675 */ + { 0x0000, 0x0000, 0x0000 }, /* R7676 */ + { 0x0000, 0x0000, 0x0000 }, /* R7677 */ + { 0x0000, 0x0000, 0x0000 }, /* R7678 */ + { 0x0000, 0x0000, 0x0000 }, /* R7679 */ + { 0x0000, 0x0000, 0x0000 }, /* R7680 */ + { 0x0000, 0x0000, 0x0000 }, /* R7681 */ + { 0x0000, 0x0000, 0x0000 }, /* R7682 */ + { 0x0000, 0x0000, 0x0000 }, /* R7683 */ + { 0x0000, 0x0000, 0x0000 }, /* R7684 */ + { 0x0000, 0x0000, 0x0000 }, /* R7685 */ + { 0x0000, 0x0000, 0x0000 }, /* R7686 */ + { 0x0000, 0x0000, 0x0000 }, /* R7687 */ + { 0x0000, 0x0000, 0x0000 }, /* R7688 */ + { 0x0000, 0x0000, 0x0000 }, /* R7689 */ + { 0x0000, 0x0000, 0x0000 }, /* R7690 */ + { 0x0000, 0x0000, 0x0000 }, /* R7691 */ + { 0x0000, 0x0000, 0x0000 }, /* R7692 */ + { 0x0000, 0x0000, 0x0000 }, /* R7693 */ + { 0x0000, 0x0000, 0x0000 }, /* R7694 */ + { 0x0000, 0x0000, 0x0000 }, /* R7695 */ + { 0x0000, 0x0000, 0x0000 }, /* R7696 */ + { 0x0000, 0x0000, 0x0000 }, /* R7697 */ + { 0x0000, 0x0000, 0x0000 }, /* R7698 */ + { 0x0000, 0x0000, 0x0000 }, /* R7699 */ + { 0x0000, 0x0000, 0x0000 }, /* R7700 */ + { 0x0000, 0x0000, 0x0000 }, /* R7701 */ + { 0x0000, 0x0000, 0x0000 }, /* R7702 */ + { 0x0000, 0x0000, 0x0000 }, /* R7703 */ + { 0x0000, 0x0000, 0x0000 }, /* R7704 */ + { 0x0000, 0x0000, 0x0000 }, /* R7705 */ + { 0x0000, 0x0000, 0x0000 }, /* R7706 */ + { 0x0000, 0x0000, 0x0000 }, /* R7707 */ + { 0x0000, 0x0000, 0x0000 }, /* R7708 */ + { 0x0000, 0x0000, 0x0000 }, /* R7709 */ + { 0x0000, 0x0000, 0x0000 }, /* R7710 */ + { 0x0000, 0x0000, 0x0000 }, /* R7711 */ + { 0x0000, 0x0000, 0x0000 }, /* R7712 */ + { 0x0000, 0x0000, 0x0000 }, /* R7713 */ + { 0x0000, 0x0000, 0x0000 }, /* R7714 */ + { 0x0000, 0x0000, 0x0000 }, /* R7715 */ + { 0x0000, 0x0000, 0x0000 }, /* R7716 */ + { 0x0000, 0x0000, 0x0000 }, /* R7717 */ + { 0x0000, 0x0000, 0x0000 }, /* R7718 */ + { 0x0000, 0x0000, 0x0000 }, /* R7719 */ + { 0x0000, 0x0000, 0x0000 }, /* R7720 */ + { 0x0000, 0x0000, 0x0000 }, /* R7721 */ + { 0x0000, 0x0000, 0x0000 }, /* R7722 */ + { 0x0000, 0x0000, 0x0000 }, /* R7723 */ + { 0x0000, 0x0000, 0x0000 }, /* R7724 */ + { 0x0000, 0x0000, 0x0000 }, /* R7725 */ + { 0x0000, 0x0000, 0x0000 }, /* R7726 */ + { 0x0000, 0x0000, 0x0000 }, /* R7727 */ + { 0x0000, 0x0000, 0x0000 }, /* R7728 */ + { 0x0000, 0x0000, 0x0000 }, /* R7729 */ + { 0x0000, 0x0000, 0x0000 }, /* R7730 */ + { 0x0000, 0x0000, 0x0000 }, /* R7731 */ + { 0x0000, 0x0000, 0x0000 }, /* R7732 */ + { 0x0000, 0x0000, 0x0000 }, /* R7733 */ + { 0x0000, 0x0000, 0x0000 }, /* R7734 */ + { 0x0000, 0x0000, 0x0000 }, /* R7735 */ + { 0x0000, 0x0000, 0x0000 }, /* R7736 */ + { 0x0000, 0x0000, 0x0000 }, /* R7737 */ + { 0x0000, 0x0000, 0x0000 }, /* R7738 */ + { 0x0000, 0x0000, 0x0000 }, /* R7739 */ + { 0x0000, 0x0000, 0x0000 }, /* R7740 */ + { 0x0000, 0x0000, 0x0000 }, /* R7741 */ + { 0x0000, 0x0000, 0x0000 }, /* R7742 */ + { 0x0000, 0x0000, 0x0000 }, /* R7743 */ + { 0x0000, 0x0000, 0x0000 }, /* R7744 */ + { 0x0000, 0x0000, 0x0000 }, /* R7745 */ + { 0x0000, 0x0000, 0x0000 }, /* R7746 */ + { 0x0000, 0x0000, 0x0000 }, /* R7747 */ + { 0x0000, 0x0000, 0x0000 }, /* R7748 */ + { 0x0000, 0x0000, 0x0000 }, /* R7749 */ + { 0x0000, 0x0000, 0x0000 }, /* R7750 */ + { 0x0000, 0x0000, 0x0000 }, /* R7751 */ + { 0x0000, 0x0000, 0x0000 }, /* R7752 */ + { 0x0000, 0x0000, 0x0000 }, /* R7753 */ + { 0x0000, 0x0000, 0x0000 }, /* R7754 */ + { 0x0000, 0x0000, 0x0000 }, /* R7755 */ + { 0x0000, 0x0000, 0x0000 }, /* R7756 */ + { 0x0000, 0x0000, 0x0000 }, /* R7757 */ + { 0x0000, 0x0000, 0x0000 }, /* R7758 */ + { 0x0000, 0x0000, 0x0000 }, /* R7759 */ + { 0x0000, 0x0000, 0x0000 }, /* R7760 */ + { 0x0000, 0x0000, 0x0000 }, /* R7761 */ + { 0x0000, 0x0000, 0x0000 }, /* R7762 */ + { 0x0000, 0x0000, 0x0000 }, /* R7763 */ + { 0x0000, 0x0000, 0x0000 }, /* R7764 */ + { 0x0000, 0x0000, 0x0000 }, /* R7765 */ + { 0x0000, 0x0000, 0x0000 }, /* R7766 */ + { 0x0000, 0x0000, 0x0000 }, /* R7767 */ + { 0x0000, 0x0000, 0x0000 }, /* R7768 */ + { 0x0000, 0x0000, 0x0000 }, /* R7769 */ + { 0x0000, 0x0000, 0x0000 }, /* R7770 */ + { 0x0000, 0x0000, 0x0000 }, /* R7771 */ + { 0x0000, 0x0000, 0x0000 }, /* R7772 */ + { 0x0000, 0x0000, 0x0000 }, /* R7773 */ + { 0x0000, 0x0000, 0x0000 }, /* R7774 */ + { 0x0000, 0x0000, 0x0000 }, /* R7775 */ + { 0x0000, 0x0000, 0x0000 }, /* R7776 */ + { 0x0000, 0x0000, 0x0000 }, /* R7777 */ + { 0x0000, 0x0000, 0x0000 }, /* R7778 */ + { 0x0000, 0x0000, 0x0000 }, /* R7779 */ + { 0x0000, 0x0000, 0x0000 }, /* R7780 */ + { 0x0000, 0x0000, 0x0000 }, /* R7781 */ + { 0x0000, 0x0000, 0x0000 }, /* R7782 */ + { 0x0000, 0x0000, 0x0000 }, /* R7783 */ + { 0x0000, 0x0000, 0x0000 }, /* R7784 */ + { 0x0000, 0x0000, 0x0000 }, /* R7785 */ + { 0x0000, 0x0000, 0x0000 }, /* R7786 */ + { 0x0000, 0x0000, 0x0000 }, /* R7787 */ + { 0x0000, 0x0000, 0x0000 }, /* R7788 */ + { 0x0000, 0x0000, 0x0000 }, /* R7789 */ + { 0x0000, 0x0000, 0x0000 }, /* R7790 */ + { 0x0000, 0x0000, 0x0000 }, /* R7791 */ + { 0x0000, 0x0000, 0x0000 }, /* R7792 */ + { 0x0000, 0x0000, 0x0000 }, /* R7793 */ + { 0x0000, 0x0000, 0x0000 }, /* R7794 */ + { 0x0000, 0x0000, 0x0000 }, /* R7795 */ + { 0x0000, 0x0000, 0x0000 }, /* R7796 */ + { 0x0000, 0x0000, 0x0000 }, /* R7797 */ + { 0x0000, 0x0000, 0x0000 }, /* R7798 */ + { 0x0000, 0x0000, 0x0000 }, /* R7799 */ + { 0x0000, 0x0000, 0x0000 }, /* R7800 */ + { 0x0000, 0x0000, 0x0000 }, /* R7801 */ + { 0x0000, 0x0000, 0x0000 }, /* R7802 */ + { 0x0000, 0x0000, 0x0000 }, /* R7803 */ + { 0x0000, 0x0000, 0x0000 }, /* R7804 */ + { 0x0000, 0x0000, 0x0000 }, /* R7805 */ + { 0x0000, 0x0000, 0x0000 }, /* R7806 */ + { 0x0000, 0x0000, 0x0000 }, /* R7807 */ + { 0x0000, 0x0000, 0x0000 }, /* R7808 */ + { 0x0000, 0x0000, 0x0000 }, /* R7809 */ + { 0x0000, 0x0000, 0x0000 }, /* R7810 */ + { 0x0000, 0x0000, 0x0000 }, /* R7811 */ + { 0x0000, 0x0000, 0x0000 }, /* R7812 */ + { 0x0000, 0x0000, 0x0000 }, /* R7813 */ + { 0x0000, 0x0000, 0x0000 }, /* R7814 */ + { 0x0000, 0x0000, 0x0000 }, /* R7815 */ + { 0x0000, 0x0000, 0x0000 }, /* R7816 */ + { 0x0000, 0x0000, 0x0000 }, /* R7817 */ + { 0x0000, 0x0000, 0x0000 }, /* R7818 */ + { 0x0000, 0x0000, 0x0000 }, /* R7819 */ + { 0x0000, 0x0000, 0x0000 }, /* R7820 */ + { 0x0000, 0x0000, 0x0000 }, /* R7821 */ + { 0x0000, 0x0000, 0x0000 }, /* R7822 */ + { 0x0000, 0x0000, 0x0000 }, /* R7823 */ + { 0x0000, 0x0000, 0x0000 }, /* R7824 */ + { 0x0000, 0x0000, 0x0000 }, /* R7825 */ + { 0x0000, 0x0000, 0x0000 }, /* R7826 */ + { 0x0000, 0x0000, 0x0000 }, /* R7827 */ + { 0x0000, 0x0000, 0x0000 }, /* R7828 */ + { 0x0000, 0x0000, 0x0000 }, /* R7829 */ + { 0x0000, 0x0000, 0x0000 }, /* R7830 */ + { 0x0000, 0x0000, 0x0000 }, /* R7831 */ + { 0x0000, 0x0000, 0x0000 }, /* R7832 */ + { 0x0000, 0x0000, 0x0000 }, /* R7833 */ + { 0x0000, 0x0000, 0x0000 }, /* R7834 */ + { 0x0000, 0x0000, 0x0000 }, /* R7835 */ + { 0x0000, 0x0000, 0x0000 }, /* R7836 */ + { 0x0000, 0x0000, 0x0000 }, /* R7837 */ + { 0x0000, 0x0000, 0x0000 }, /* R7838 */ + { 0x0000, 0x0000, 0x0000 }, /* R7839 */ + { 0x0000, 0x0000, 0x0000 }, /* R7840 */ + { 0x0000, 0x0000, 0x0000 }, /* R7841 */ + { 0x0000, 0x0000, 0x0000 }, /* R7842 */ + { 0x0000, 0x0000, 0x0000 }, /* R7843 */ + { 0x0000, 0x0000, 0x0000 }, /* R7844 */ + { 0x0000, 0x0000, 0x0000 }, /* R7845 */ + { 0x0000, 0x0000, 0x0000 }, /* R7846 */ + { 0x0000, 0x0000, 0x0000 }, /* R7847 */ + { 0x0000, 0x0000, 0x0000 }, /* R7848 */ + { 0x0000, 0x0000, 0x0000 }, /* R7849 */ + { 0x0000, 0x0000, 0x0000 }, /* R7850 */ + { 0x0000, 0x0000, 0x0000 }, /* R7851 */ + { 0x0000, 0x0000, 0x0000 }, /* R7852 */ + { 0x0000, 0x0000, 0x0000 }, /* R7853 */ + { 0x0000, 0x0000, 0x0000 }, /* R7854 */ + { 0x0000, 0x0000, 0x0000 }, /* R7855 */ + { 0x0000, 0x0000, 0x0000 }, /* R7856 */ + { 0x0000, 0x0000, 0x0000 }, /* R7857 */ + { 0x0000, 0x0000, 0x0000 }, /* R7858 */ + { 0x0000, 0x0000, 0x0000 }, /* R7859 */ + { 0x0000, 0x0000, 0x0000 }, /* R7860 */ + { 0x0000, 0x0000, 0x0000 }, /* R7861 */ + { 0x0000, 0x0000, 0x0000 }, /* R7862 */ + { 0x0000, 0x0000, 0x0000 }, /* R7863 */ + { 0x0000, 0x0000, 0x0000 }, /* R7864 */ + { 0x0000, 0x0000, 0x0000 }, /* R7865 */ + { 0x0000, 0x0000, 0x0000 }, /* R7866 */ + { 0x0000, 0x0000, 0x0000 }, /* R7867 */ + { 0x0000, 0x0000, 0x0000 }, /* R7868 */ + { 0x0000, 0x0000, 0x0000 }, /* R7869 */ + { 0x0000, 0x0000, 0x0000 }, /* R7870 */ + { 0x0000, 0x0000, 0x0000 }, /* R7871 */ + { 0x0000, 0x0000, 0x0000 }, /* R7872 */ + { 0x0000, 0x0000, 0x0000 }, /* R7873 */ + { 0x0000, 0x0000, 0x0000 }, /* R7874 */ + { 0x0000, 0x0000, 0x0000 }, /* R7875 */ + { 0x0000, 0x0000, 0x0000 }, /* R7876 */ + { 0x0000, 0x0000, 0x0000 }, /* R7877 */ + { 0x0000, 0x0000, 0x0000 }, /* R7878 */ + { 0x0000, 0x0000, 0x0000 }, /* R7879 */ + { 0x0000, 0x0000, 0x0000 }, /* R7880 */ + { 0x0000, 0x0000, 0x0000 }, /* R7881 */ + { 0x0000, 0x0000, 0x0000 }, /* R7882 */ + { 0x0000, 0x0000, 0x0000 }, /* R7883 */ + { 0x0000, 0x0000, 0x0000 }, /* R7884 */ + { 0x0000, 0x0000, 0x0000 }, /* R7885 */ + { 0x0000, 0x0000, 0x0000 }, /* R7886 */ + { 0x0000, 0x0000, 0x0000 }, /* R7887 */ + { 0x0000, 0x0000, 0x0000 }, /* R7888 */ + { 0x0000, 0x0000, 0x0000 }, /* R7889 */ + { 0x0000, 0x0000, 0x0000 }, /* R7890 */ + { 0x0000, 0x0000, 0x0000 }, /* R7891 */ + { 0x0000, 0x0000, 0x0000 }, /* R7892 */ + { 0x0000, 0x0000, 0x0000 }, /* R7893 */ + { 0x0000, 0x0000, 0x0000 }, /* R7894 */ + { 0x0000, 0x0000, 0x0000 }, /* R7895 */ + { 0x0000, 0x0000, 0x0000 }, /* R7896 */ + { 0x0000, 0x0000, 0x0000 }, /* R7897 */ + { 0x0000, 0x0000, 0x0000 }, /* R7898 */ + { 0x0000, 0x0000, 0x0000 }, /* R7899 */ + { 0x0000, 0x0000, 0x0000 }, /* R7900 */ + { 0x0000, 0x0000, 0x0000 }, /* R7901 */ + { 0x0000, 0x0000, 0x0000 }, /* R7902 */ + { 0x0000, 0x0000, 0x0000 }, /* R7903 */ + { 0x0000, 0x0000, 0x0000 }, /* R7904 */ + { 0x0000, 0x0000, 0x0000 }, /* R7905 */ + { 0x0000, 0x0000, 0x0000 }, /* R7906 */ + { 0x0000, 0x0000, 0x0000 }, /* R7907 */ + { 0x0000, 0x0000, 0x0000 }, /* R7908 */ + { 0x0000, 0x0000, 0x0000 }, /* R7909 */ + { 0x0000, 0x0000, 0x0000 }, /* R7910 */ + { 0x0000, 0x0000, 0x0000 }, /* R7911 */ + { 0x0000, 0x0000, 0x0000 }, /* R7912 */ + { 0x0000, 0x0000, 0x0000 }, /* R7913 */ + { 0x0000, 0x0000, 0x0000 }, /* R7914 */ + { 0x0000, 0x0000, 0x0000 }, /* R7915 */ + { 0x0000, 0x0000, 0x0000 }, /* R7916 */ + { 0x0000, 0x0000, 0x0000 }, /* R7917 */ + { 0x0000, 0x0000, 0x0000 }, /* R7918 */ + { 0x0000, 0x0000, 0x0000 }, /* R7919 */ + { 0x0000, 0x0000, 0x0000 }, /* R7920 */ + { 0x0000, 0x0000, 0x0000 }, /* R7921 */ + { 0x0000, 0x0000, 0x0000 }, /* R7922 */ + { 0x0000, 0x0000, 0x0000 }, /* R7923 */ + { 0x0000, 0x0000, 0x0000 }, /* R7924 */ + { 0x0000, 0x0000, 0x0000 }, /* R7925 */ + { 0x0000, 0x0000, 0x0000 }, /* R7926 */ + { 0x0000, 0x0000, 0x0000 }, /* R7927 */ + { 0x0000, 0x0000, 0x0000 }, /* R7928 */ + { 0x0000, 0x0000, 0x0000 }, /* R7929 */ + { 0x0000, 0x0000, 0x0000 }, /* R7930 */ + { 0x0000, 0x0000, 0x0000 }, /* R7931 */ + { 0x0000, 0x0000, 0x0000 }, /* R7932 */ + { 0x0000, 0x0000, 0x0000 }, /* R7933 */ + { 0x0000, 0x0000, 0x0000 }, /* R7934 */ + { 0x0000, 0x0000, 0x0000 }, /* R7935 */ + { 0x0000, 0x0000, 0x0000 }, /* R7936 */ + { 0x0000, 0x0000, 0x0000 }, /* R7937 */ + { 0x0000, 0x0000, 0x0000 }, /* R7938 */ + { 0x0000, 0x0000, 0x0000 }, /* R7939 */ + { 0x0000, 0x0000, 0x0000 }, /* R7940 */ + { 0x0000, 0x0000, 0x0000 }, /* R7941 */ + { 0x0000, 0x0000, 0x0000 }, /* R7942 */ + { 0x0000, 0x0000, 0x0000 }, /* R7943 */ + { 0x0000, 0x0000, 0x0000 }, /* R7944 */ + { 0x0000, 0x0000, 0x0000 }, /* R7945 */ + { 0x0000, 0x0000, 0x0000 }, /* R7946 */ + { 0x0000, 0x0000, 0x0000 }, /* R7947 */ + { 0x0000, 0x0000, 0x0000 }, /* R7948 */ + { 0x0000, 0x0000, 0x0000 }, /* R7949 */ + { 0x0000, 0x0000, 0x0000 }, /* R7950 */ + { 0x0000, 0x0000, 0x0000 }, /* R7951 */ + { 0x0000, 0x0000, 0x0000 }, /* R7952 */ + { 0x0000, 0x0000, 0x0000 }, /* R7953 */ + { 0x0000, 0x0000, 0x0000 }, /* R7954 */ + { 0x0000, 0x0000, 0x0000 }, /* R7955 */ + { 0x0000, 0x0000, 0x0000 }, /* R7956 */ + { 0x0000, 0x0000, 0x0000 }, /* R7957 */ + { 0x0000, 0x0000, 0x0000 }, /* R7958 */ + { 0x0000, 0x0000, 0x0000 }, /* R7959 */ + { 0x0000, 0x0000, 0x0000 }, /* R7960 */ + { 0x0000, 0x0000, 0x0000 }, /* R7961 */ + { 0x0000, 0x0000, 0x0000 }, /* R7962 */ + { 0x0000, 0x0000, 0x0000 }, /* R7963 */ + { 0x0000, 0x0000, 0x0000 }, /* R7964 */ + { 0x0000, 0x0000, 0x0000 }, /* R7965 */ + { 0x0000, 0x0000, 0x0000 }, /* R7966 */ + { 0x0000, 0x0000, 0x0000 }, /* R7967 */ + { 0x0000, 0x0000, 0x0000 }, /* R7968 */ + { 0x0000, 0x0000, 0x0000 }, /* R7969 */ + { 0x0000, 0x0000, 0x0000 }, /* R7970 */ + { 0x0000, 0x0000, 0x0000 }, /* R7971 */ + { 0x0000, 0x0000, 0x0000 }, /* R7972 */ + { 0x0000, 0x0000, 0x0000 }, /* R7973 */ + { 0x0000, 0x0000, 0x0000 }, /* R7974 */ + { 0x0000, 0x0000, 0x0000 }, /* R7975 */ + { 0x0000, 0x0000, 0x0000 }, /* R7976 */ + { 0x0000, 0x0000, 0x0000 }, /* R7977 */ + { 0x0000, 0x0000, 0x0000 }, /* R7978 */ + { 0x0000, 0x0000, 0x0000 }, /* R7979 */ + { 0x0000, 0x0000, 0x0000 }, /* R7980 */ + { 0x0000, 0x0000, 0x0000 }, /* R7981 */ + { 0x0000, 0x0000, 0x0000 }, /* R7982 */ + { 0x0000, 0x0000, 0x0000 }, /* R7983 */ + { 0x0000, 0x0000, 0x0000 }, /* R7984 */ + { 0x0000, 0x0000, 0x0000 }, /* R7985 */ + { 0x0000, 0x0000, 0x0000 }, /* R7986 */ + { 0x0000, 0x0000, 0x0000 }, /* R7987 */ + { 0x0000, 0x0000, 0x0000 }, /* R7988 */ + { 0x0000, 0x0000, 0x0000 }, /* R7989 */ + { 0x0000, 0x0000, 0x0000 }, /* R7990 */ + { 0x0000, 0x0000, 0x0000 }, /* R7991 */ + { 0x0000, 0x0000, 0x0000 }, /* R7992 */ + { 0x0000, 0x0000, 0x0000 }, /* R7993 */ + { 0x0000, 0x0000, 0x0000 }, /* R7994 */ + { 0x0000, 0x0000, 0x0000 }, /* R7995 */ + { 0x0000, 0x0000, 0x0000 }, /* R7996 */ + { 0x0000, 0x0000, 0x0000 }, /* R7997 */ + { 0x0000, 0x0000, 0x0000 }, /* R7998 */ + { 0x0000, 0x0000, 0x0000 }, /* R7999 */ + { 0x0000, 0x0000, 0x0000 }, /* R8000 */ + { 0x0000, 0x0000, 0x0000 }, /* R8001 */ + { 0x0000, 0x0000, 0x0000 }, /* R8002 */ + { 0x0000, 0x0000, 0x0000 }, /* R8003 */ + { 0x0000, 0x0000, 0x0000 }, /* R8004 */ + { 0x0000, 0x0000, 0x0000 }, /* R8005 */ + { 0x0000, 0x0000, 0x0000 }, /* R8006 */ + { 0x0000, 0x0000, 0x0000 }, /* R8007 */ + { 0x0000, 0x0000, 0x0000 }, /* R8008 */ + { 0x0000, 0x0000, 0x0000 }, /* R8009 */ + { 0x0000, 0x0000, 0x0000 }, /* R8010 */ + { 0x0000, 0x0000, 0x0000 }, /* R8011 */ + { 0x0000, 0x0000, 0x0000 }, /* R8012 */ + { 0x0000, 0x0000, 0x0000 }, /* R8013 */ + { 0x0000, 0x0000, 0x0000 }, /* R8014 */ + { 0x0000, 0x0000, 0x0000 }, /* R8015 */ + { 0x0000, 0x0000, 0x0000 }, /* R8016 */ + { 0x0000, 0x0000, 0x0000 }, /* R8017 */ + { 0x0000, 0x0000, 0x0000 }, /* R8018 */ + { 0x0000, 0x0000, 0x0000 }, /* R8019 */ + { 0x0000, 0x0000, 0x0000 }, /* R8020 */ + { 0x0000, 0x0000, 0x0000 }, /* R8021 */ + { 0x0000, 0x0000, 0x0000 }, /* R8022 */ + { 0x0000, 0x0000, 0x0000 }, /* R8023 */ + { 0x0000, 0x0000, 0x0000 }, /* R8024 */ + { 0x0000, 0x0000, 0x0000 }, /* R8025 */ + { 0x0000, 0x0000, 0x0000 }, /* R8026 */ + { 0x0000, 0x0000, 0x0000 }, /* R8027 */ + { 0x0000, 0x0000, 0x0000 }, /* R8028 */ + { 0x0000, 0x0000, 0x0000 }, /* R8029 */ + { 0x0000, 0x0000, 0x0000 }, /* R8030 */ + { 0x0000, 0x0000, 0x0000 }, /* R8031 */ + { 0x0000, 0x0000, 0x0000 }, /* R8032 */ + { 0x0000, 0x0000, 0x0000 }, /* R8033 */ + { 0x0000, 0x0000, 0x0000 }, /* R8034 */ + { 0x0000, 0x0000, 0x0000 }, /* R8035 */ + { 0x0000, 0x0000, 0x0000 }, /* R8036 */ + { 0x0000, 0x0000, 0x0000 }, /* R8037 */ + { 0x0000, 0x0000, 0x0000 }, /* R8038 */ + { 0x0000, 0x0000, 0x0000 }, /* R8039 */ + { 0x0000, 0x0000, 0x0000 }, /* R8040 */ + { 0x0000, 0x0000, 0x0000 }, /* R8041 */ + { 0x0000, 0x0000, 0x0000 }, /* R8042 */ + { 0x0000, 0x0000, 0x0000 }, /* R8043 */ + { 0x0000, 0x0000, 0x0000 }, /* R8044 */ + { 0x0000, 0x0000, 0x0000 }, /* R8045 */ + { 0x0000, 0x0000, 0x0000 }, /* R8046 */ + { 0x0000, 0x0000, 0x0000 }, /* R8047 */ + { 0x0000, 0x0000, 0x0000 }, /* R8048 */ + { 0x0000, 0x0000, 0x0000 }, /* R8049 */ + { 0x0000, 0x0000, 0x0000 }, /* R8050 */ + { 0x0000, 0x0000, 0x0000 }, /* R8051 */ + { 0x0000, 0x0000, 0x0000 }, /* R8052 */ + { 0x0000, 0x0000, 0x0000 }, /* R8053 */ + { 0x0000, 0x0000, 0x0000 }, /* R8054 */ + { 0x0000, 0x0000, 0x0000 }, /* R8055 */ + { 0x0000, 0x0000, 0x0000 }, /* R8056 */ + { 0x0000, 0x0000, 0x0000 }, /* R8057 */ + { 0x0000, 0x0000, 0x0000 }, /* R8058 */ + { 0x0000, 0x0000, 0x0000 }, /* R8059 */ + { 0x0000, 0x0000, 0x0000 }, /* R8060 */ + { 0x0000, 0x0000, 0x0000 }, /* R8061 */ + { 0x0000, 0x0000, 0x0000 }, /* R8062 */ + { 0x0000, 0x0000, 0x0000 }, /* R8063 */ + { 0x0000, 0x0000, 0x0000 }, /* R8064 */ + { 0x0000, 0x0000, 0x0000 }, /* R8065 */ + { 0x0000, 0x0000, 0x0000 }, /* R8066 */ + { 0x0000, 0x0000, 0x0000 }, /* R8067 */ + { 0x0000, 0x0000, 0x0000 }, /* R8068 */ + { 0x0000, 0x0000, 0x0000 }, /* R8069 */ + { 0x0000, 0x0000, 0x0000 }, /* R8070 */ + { 0x0000, 0x0000, 0x0000 }, /* R8071 */ + { 0x0000, 0x0000, 0x0000 }, /* R8072 */ + { 0x0000, 0x0000, 0x0000 }, /* R8073 */ + { 0x0000, 0x0000, 0x0000 }, /* R8074 */ + { 0x0000, 0x0000, 0x0000 }, /* R8075 */ + { 0x0000, 0x0000, 0x0000 }, /* R8076 */ + { 0x0000, 0x0000, 0x0000 }, /* R8077 */ + { 0x0000, 0x0000, 0x0000 }, /* R8078 */ + { 0x0000, 0x0000, 0x0000 }, /* R8079 */ + { 0x0000, 0x0000, 0x0000 }, /* R8080 */ + { 0x0000, 0x0000, 0x0000 }, /* R8081 */ + { 0x0000, 0x0000, 0x0000 }, /* R8082 */ + { 0x0000, 0x0000, 0x0000 }, /* R8083 */ + { 0x0000, 0x0000, 0x0000 }, /* R8084 */ + { 0x0000, 0x0000, 0x0000 }, /* R8085 */ + { 0x0000, 0x0000, 0x0000 }, /* R8086 */ + { 0x0000, 0x0000, 0x0000 }, /* R8087 */ + { 0x0000, 0x0000, 0x0000 }, /* R8088 */ + { 0x0000, 0x0000, 0x0000 }, /* R8089 */ + { 0x0000, 0x0000, 0x0000 }, /* R8090 */ + { 0x0000, 0x0000, 0x0000 }, /* R8091 */ + { 0x0000, 0x0000, 0x0000 }, /* R8092 */ + { 0x0000, 0x0000, 0x0000 }, /* R8093 */ + { 0x0000, 0x0000, 0x0000 }, /* R8094 */ + { 0x0000, 0x0000, 0x0000 }, /* R8095 */ + { 0x0000, 0x0000, 0x0000 }, /* R8096 */ + { 0x0000, 0x0000, 0x0000 }, /* R8097 */ + { 0x0000, 0x0000, 0x0000 }, /* R8098 */ + { 0x0000, 0x0000, 0x0000 }, /* R8099 */ + { 0x0000, 0x0000, 0x0000 }, /* R8100 */ + { 0x0000, 0x0000, 0x0000 }, /* R8101 */ + { 0x0000, 0x0000, 0x0000 }, /* R8102 */ + { 0x0000, 0x0000, 0x0000 }, /* R8103 */ + { 0x0000, 0x0000, 0x0000 }, /* R8104 */ + { 0x0000, 0x0000, 0x0000 }, /* R8105 */ + { 0x0000, 0x0000, 0x0000 }, /* R8106 */ + { 0x0000, 0x0000, 0x0000 }, /* R8107 */ + { 0x0000, 0x0000, 0x0000 }, /* R8108 */ + { 0x0000, 0x0000, 0x0000 }, /* R8109 */ + { 0x0000, 0x0000, 0x0000 }, /* R8110 */ + { 0x0000, 0x0000, 0x0000 }, /* R8111 */ + { 0x0000, 0x0000, 0x0000 }, /* R8112 */ + { 0x0000, 0x0000, 0x0000 }, /* R8113 */ + { 0x0000, 0x0000, 0x0000 }, /* R8114 */ + { 0x0000, 0x0000, 0x0000 }, /* R8115 */ + { 0x0000, 0x0000, 0x0000 }, /* R8116 */ + { 0x0000, 0x0000, 0x0000 }, /* R8117 */ + { 0x0000, 0x0000, 0x0000 }, /* R8118 */ + { 0x0000, 0x0000, 0x0000 }, /* R8119 */ + { 0x0000, 0x0000, 0x0000 }, /* R8120 */ + { 0x0000, 0x0000, 0x0000 }, /* R8121 */ + { 0x0000, 0x0000, 0x0000 }, /* R8122 */ + { 0x0000, 0x0000, 0x0000 }, /* R8123 */ + { 0x0000, 0x0000, 0x0000 }, /* R8124 */ + { 0x0000, 0x0000, 0x0000 }, /* R8125 */ + { 0x0000, 0x0000, 0x0000 }, /* R8126 */ + { 0x0000, 0x0000, 0x0000 }, /* R8127 */ + { 0x0000, 0x0000, 0x0000 }, /* R8128 */ + { 0x0000, 0x0000, 0x0000 }, /* R8129 */ + { 0x0000, 0x0000, 0x0000 }, /* R8130 */ + { 0x0000, 0x0000, 0x0000 }, /* R8131 */ + { 0x0000, 0x0000, 0x0000 }, /* R8132 */ + { 0x0000, 0x0000, 0x0000 }, /* R8133 */ + { 0x0000, 0x0000, 0x0000 }, /* R8134 */ + { 0x0000, 0x0000, 0x0000 }, /* R8135 */ + { 0x0000, 0x0000, 0x0000 }, /* R8136 */ + { 0x0000, 0x0000, 0x0000 }, /* R8137 */ + { 0x0000, 0x0000, 0x0000 }, /* R8138 */ + { 0x0000, 0x0000, 0x0000 }, /* R8139 */ + { 0x0000, 0x0000, 0x0000 }, /* R8140 */ + { 0x0000, 0x0000, 0x0000 }, /* R8141 */ + { 0x0000, 0x0000, 0x0000 }, /* R8142 */ + { 0x0000, 0x0000, 0x0000 }, /* R8143 */ + { 0x0000, 0x0000, 0x0000 }, /* R8144 */ + { 0x0000, 0x0000, 0x0000 }, /* R8145 */ + { 0x0000, 0x0000, 0x0000 }, /* R8146 */ + { 0x0000, 0x0000, 0x0000 }, /* R8147 */ + { 0x0000, 0x0000, 0x0000 }, /* R8148 */ + { 0x0000, 0x0000, 0x0000 }, /* R8149 */ + { 0x0000, 0x0000, 0x0000 }, /* R8150 */ + { 0x0000, 0x0000, 0x0000 }, /* R8151 */ + { 0x0000, 0x0000, 0x0000 }, /* R8152 */ + { 0x0000, 0x0000, 0x0000 }, /* R8153 */ + { 0x0000, 0x0000, 0x0000 }, /* R8154 */ + { 0x0000, 0x0000, 0x0000 }, /* R8155 */ + { 0x0000, 0x0000, 0x0000 }, /* R8156 */ + { 0x0000, 0x0000, 0x0000 }, /* R8157 */ + { 0x0000, 0x0000, 0x0000 }, /* R8158 */ + { 0x0000, 0x0000, 0x0000 }, /* R8159 */ + { 0x0000, 0x0000, 0x0000 }, /* R8160 */ + { 0x0000, 0x0000, 0x0000 }, /* R8161 */ + { 0x0000, 0x0000, 0x0000 }, /* R8162 */ + { 0x0000, 0x0000, 0x0000 }, /* R8163 */ + { 0x0000, 0x0000, 0x0000 }, /* R8164 */ + { 0x0000, 0x0000, 0x0000 }, /* R8165 */ + { 0x0000, 0x0000, 0x0000 }, /* R8166 */ + { 0x0000, 0x0000, 0x0000 }, /* R8167 */ + { 0x0000, 0x0000, 0x0000 }, /* R8168 */ + { 0x0000, 0x0000, 0x0000 }, /* R8169 */ + { 0x0000, 0x0000, 0x0000 }, /* R8170 */ + { 0x0000, 0x0000, 0x0000 }, /* R8171 */ + { 0x0000, 0x0000, 0x0000 }, /* R8172 */ + { 0x0000, 0x0000, 0x0000 }, /* R8173 */ + { 0x0000, 0x0000, 0x0000 }, /* R8174 */ + { 0x0000, 0x0000, 0x0000 }, /* R8175 */ + { 0x0000, 0x0000, 0x0000 }, /* R8176 */ + { 0x0000, 0x0000, 0x0000 }, /* R8177 */ + { 0x0000, 0x0000, 0x0000 }, /* R8178 */ + { 0x0000, 0x0000, 0x0000 }, /* R8179 */ + { 0x0000, 0x0000, 0x0000 }, /* R8180 */ + { 0x0000, 0x0000, 0x0000 }, /* R8181 */ + { 0x0000, 0x0000, 0x0000 }, /* R8182 */ + { 0x0000, 0x0000, 0x0000 }, /* R8183 */ + { 0x0000, 0x0000, 0x0000 }, /* R8184 */ + { 0x0000, 0x0000, 0x0000 }, /* R8185 */ + { 0x0000, 0x0000, 0x0000 }, /* R8186 */ + { 0x0000, 0x0000, 0x0000 }, /* R8187 */ + { 0x0000, 0x0000, 0x0000 }, /* R8188 */ + { 0x0000, 0x0000, 0x0000 }, /* R8189 */ + { 0x0000, 0x0000, 0x0000 }, /* R8190 */ + { 0x0000, 0x0000, 0x0000 }, /* R8191 */ + { 0x03FF, 0x03FF, 0x0000 }, /* R8192 - DSP2 Instruction RAM 0 */ + { 0x0000, 0x0000, 0x0000 }, /* R8193 */ + { 0x0000, 0x0000, 0x0000 }, /* R8194 */ + { 0x0000, 0x0000, 0x0000 }, /* R8195 */ + { 0x0000, 0x0000, 0x0000 }, /* R8196 */ + { 0x0000, 0x0000, 0x0000 }, /* R8197 */ + { 0x0000, 0x0000, 0x0000 }, /* R8198 */ + { 0x0000, 0x0000, 0x0000 }, /* R8199 */ + { 0x0000, 0x0000, 0x0000 }, /* R8200 */ + { 0x0000, 0x0000, 0x0000 }, /* R8201 */ + { 0x0000, 0x0000, 0x0000 }, /* R8202 */ + { 0x0000, 0x0000, 0x0000 }, /* R8203 */ + { 0x0000, 0x0000, 0x0000 }, /* R8204 */ + { 0x0000, 0x0000, 0x0000 }, /* R8205 */ + { 0x0000, 0x0000, 0x0000 }, /* R8206 */ + { 0x0000, 0x0000, 0x0000 }, /* R8207 */ + { 0x0000, 0x0000, 0x0000 }, /* R8208 */ + { 0x0000, 0x0000, 0x0000 }, /* R8209 */ + { 0x0000, 0x0000, 0x0000 }, /* R8210 */ + { 0x0000, 0x0000, 0x0000 }, /* R8211 */ + { 0x0000, 0x0000, 0x0000 }, /* R8212 */ + { 0x0000, 0x0000, 0x0000 }, /* R8213 */ + { 0x0000, 0x0000, 0x0000 }, /* R8214 */ + { 0x0000, 0x0000, 0x0000 }, /* R8215 */ + { 0x0000, 0x0000, 0x0000 }, /* R8216 */ + { 0x0000, 0x0000, 0x0000 }, /* R8217 */ + { 0x0000, 0x0000, 0x0000 }, /* R8218 */ + { 0x0000, 0x0000, 0x0000 }, /* R8219 */ + { 0x0000, 0x0000, 0x0000 }, /* R8220 */ + { 0x0000, 0x0000, 0x0000 }, /* R8221 */ + { 0x0000, 0x0000, 0x0000 }, /* R8222 */ + { 0x0000, 0x0000, 0x0000 }, /* R8223 */ + { 0x0000, 0x0000, 0x0000 }, /* R8224 */ + { 0x0000, 0x0000, 0x0000 }, /* R8225 */ + { 0x0000, 0x0000, 0x0000 }, /* R8226 */ + { 0x0000, 0x0000, 0x0000 }, /* R8227 */ + { 0x0000, 0x0000, 0x0000 }, /* R8228 */ + { 0x0000, 0x0000, 0x0000 }, /* R8229 */ + { 0x0000, 0x0000, 0x0000 }, /* R8230 */ + { 0x0000, 0x0000, 0x0000 }, /* R8231 */ + { 0x0000, 0x0000, 0x0000 }, /* R8232 */ + { 0x0000, 0x0000, 0x0000 }, /* R8233 */ + { 0x0000, 0x0000, 0x0000 }, /* R8234 */ + { 0x0000, 0x0000, 0x0000 }, /* R8235 */ + { 0x0000, 0x0000, 0x0000 }, /* R8236 */ + { 0x0000, 0x0000, 0x0000 }, /* R8237 */ + { 0x0000, 0x0000, 0x0000 }, /* R8238 */ + { 0x0000, 0x0000, 0x0000 }, /* R8239 */ + { 0x0000, 0x0000, 0x0000 }, /* R8240 */ + { 0x0000, 0x0000, 0x0000 }, /* R8241 */ + { 0x0000, 0x0000, 0x0000 }, /* R8242 */ + { 0x0000, 0x0000, 0x0000 }, /* R8243 */ + { 0x0000, 0x0000, 0x0000 }, /* R8244 */ + { 0x0000, 0x0000, 0x0000 }, /* R8245 */ + { 0x0000, 0x0000, 0x0000 }, /* R8246 */ + { 0x0000, 0x0000, 0x0000 }, /* R8247 */ + { 0x0000, 0x0000, 0x0000 }, /* R8248 */ + { 0x0000, 0x0000, 0x0000 }, /* R8249 */ + { 0x0000, 0x0000, 0x0000 }, /* R8250 */ + { 0x0000, 0x0000, 0x0000 }, /* R8251 */ + { 0x0000, 0x0000, 0x0000 }, /* R8252 */ + { 0x0000, 0x0000, 0x0000 }, /* R8253 */ + { 0x0000, 0x0000, 0x0000 }, /* R8254 */ + { 0x0000, 0x0000, 0x0000 }, /* R8255 */ + { 0x0000, 0x0000, 0x0000 }, /* R8256 */ + { 0x0000, 0x0000, 0x0000 }, /* R8257 */ + { 0x0000, 0x0000, 0x0000 }, /* R8258 */ + { 0x0000, 0x0000, 0x0000 }, /* R8259 */ + { 0x0000, 0x0000, 0x0000 }, /* R8260 */ + { 0x0000, 0x0000, 0x0000 }, /* R8261 */ + { 0x0000, 0x0000, 0x0000 }, /* R8262 */ + { 0x0000, 0x0000, 0x0000 }, /* R8263 */ + { 0x0000, 0x0000, 0x0000 }, /* R8264 */ + { 0x0000, 0x0000, 0x0000 }, /* R8265 */ + { 0x0000, 0x0000, 0x0000 }, /* R8266 */ + { 0x0000, 0x0000, 0x0000 }, /* R8267 */ + { 0x0000, 0x0000, 0x0000 }, /* R8268 */ + { 0x0000, 0x0000, 0x0000 }, /* R8269 */ + { 0x0000, 0x0000, 0x0000 }, /* R8270 */ + { 0x0000, 0x0000, 0x0000 }, /* R8271 */ + { 0x0000, 0x0000, 0x0000 }, /* R8272 */ + { 0x0000, 0x0000, 0x0000 }, /* R8273 */ + { 0x0000, 0x0000, 0x0000 }, /* R8274 */ + { 0x0000, 0x0000, 0x0000 }, /* R8275 */ + { 0x0000, 0x0000, 0x0000 }, /* R8276 */ + { 0x0000, 0x0000, 0x0000 }, /* R8277 */ + { 0x0000, 0x0000, 0x0000 }, /* R8278 */ + { 0x0000, 0x0000, 0x0000 }, /* R8279 */ + { 0x0000, 0x0000, 0x0000 }, /* R8280 */ + { 0x0000, 0x0000, 0x0000 }, /* R8281 */ + { 0x0000, 0x0000, 0x0000 }, /* R8282 */ + { 0x0000, 0x0000, 0x0000 }, /* R8283 */ + { 0x0000, 0x0000, 0x0000 }, /* R8284 */ + { 0x0000, 0x0000, 0x0000 }, /* R8285 */ + { 0x0000, 0x0000, 0x0000 }, /* R8286 */ + { 0x0000, 0x0000, 0x0000 }, /* R8287 */ + { 0x0000, 0x0000, 0x0000 }, /* R8288 */ + { 0x0000, 0x0000, 0x0000 }, /* R8289 */ + { 0x0000, 0x0000, 0x0000 }, /* R8290 */ + { 0x0000, 0x0000, 0x0000 }, /* R8291 */ + { 0x0000, 0x0000, 0x0000 }, /* R8292 */ + { 0x0000, 0x0000, 0x0000 }, /* R8293 */ + { 0x0000, 0x0000, 0x0000 }, /* R8294 */ + { 0x0000, 0x0000, 0x0000 }, /* R8295 */ + { 0x0000, 0x0000, 0x0000 }, /* R8296 */ + { 0x0000, 0x0000, 0x0000 }, /* R8297 */ + { 0x0000, 0x0000, 0x0000 }, /* R8298 */ + { 0x0000, 0x0000, 0x0000 }, /* R8299 */ + { 0x0000, 0x0000, 0x0000 }, /* R8300 */ + { 0x0000, 0x0000, 0x0000 }, /* R8301 */ + { 0x0000, 0x0000, 0x0000 }, /* R8302 */ + { 0x0000, 0x0000, 0x0000 }, /* R8303 */ + { 0x0000, 0x0000, 0x0000 }, /* R8304 */ + { 0x0000, 0x0000, 0x0000 }, /* R8305 */ + { 0x0000, 0x0000, 0x0000 }, /* R8306 */ + { 0x0000, 0x0000, 0x0000 }, /* R8307 */ + { 0x0000, 0x0000, 0x0000 }, /* R8308 */ + { 0x0000, 0x0000, 0x0000 }, /* R8309 */ + { 0x0000, 0x0000, 0x0000 }, /* R8310 */ + { 0x0000, 0x0000, 0x0000 }, /* R8311 */ + { 0x0000, 0x0000, 0x0000 }, /* R8312 */ + { 0x0000, 0x0000, 0x0000 }, /* R8313 */ + { 0x0000, 0x0000, 0x0000 }, /* R8314 */ + { 0x0000, 0x0000, 0x0000 }, /* R8315 */ + { 0x0000, 0x0000, 0x0000 }, /* R8316 */ + { 0x0000, 0x0000, 0x0000 }, /* R8317 */ + { 0x0000, 0x0000, 0x0000 }, /* R8318 */ + { 0x0000, 0x0000, 0x0000 }, /* R8319 */ + { 0x0000, 0x0000, 0x0000 }, /* R8320 */ + { 0x0000, 0x0000, 0x0000 }, /* R8321 */ + { 0x0000, 0x0000, 0x0000 }, /* R8322 */ + { 0x0000, 0x0000, 0x0000 }, /* R8323 */ + { 0x0000, 0x0000, 0x0000 }, /* R8324 */ + { 0x0000, 0x0000, 0x0000 }, /* R8325 */ + { 0x0000, 0x0000, 0x0000 }, /* R8326 */ + { 0x0000, 0x0000, 0x0000 }, /* R8327 */ + { 0x0000, 0x0000, 0x0000 }, /* R8328 */ + { 0x0000, 0x0000, 0x0000 }, /* R8329 */ + { 0x0000, 0x0000, 0x0000 }, /* R8330 */ + { 0x0000, 0x0000, 0x0000 }, /* R8331 */ + { 0x0000, 0x0000, 0x0000 }, /* R8332 */ + { 0x0000, 0x0000, 0x0000 }, /* R8333 */ + { 0x0000, 0x0000, 0x0000 }, /* R8334 */ + { 0x0000, 0x0000, 0x0000 }, /* R8335 */ + { 0x0000, 0x0000, 0x0000 }, /* R8336 */ + { 0x0000, 0x0000, 0x0000 }, /* R8337 */ + { 0x0000, 0x0000, 0x0000 }, /* R8338 */ + { 0x0000, 0x0000, 0x0000 }, /* R8339 */ + { 0x0000, 0x0000, 0x0000 }, /* R8340 */ + { 0x0000, 0x0000, 0x0000 }, /* R8341 */ + { 0x0000, 0x0000, 0x0000 }, /* R8342 */ + { 0x0000, 0x0000, 0x0000 }, /* R8343 */ + { 0x0000, 0x0000, 0x0000 }, /* R8344 */ + { 0x0000, 0x0000, 0x0000 }, /* R8345 */ + { 0x0000, 0x0000, 0x0000 }, /* R8346 */ + { 0x0000, 0x0000, 0x0000 }, /* R8347 */ + { 0x0000, 0x0000, 0x0000 }, /* R8348 */ + { 0x0000, 0x0000, 0x0000 }, /* R8349 */ + { 0x0000, 0x0000, 0x0000 }, /* R8350 */ + { 0x0000, 0x0000, 0x0000 }, /* R8351 */ + { 0x0000, 0x0000, 0x0000 }, /* R8352 */ + { 0x0000, 0x0000, 0x0000 }, /* R8353 */ + { 0x0000, 0x0000, 0x0000 }, /* R8354 */ + { 0x0000, 0x0000, 0x0000 }, /* R8355 */ + { 0x0000, 0x0000, 0x0000 }, /* R8356 */ + { 0x0000, 0x0000, 0x0000 }, /* R8357 */ + { 0x0000, 0x0000, 0x0000 }, /* R8358 */ + { 0x0000, 0x0000, 0x0000 }, /* R8359 */ + { 0x0000, 0x0000, 0x0000 }, /* R8360 */ + { 0x0000, 0x0000, 0x0000 }, /* R8361 */ + { 0x0000, 0x0000, 0x0000 }, /* R8362 */ + { 0x0000, 0x0000, 0x0000 }, /* R8363 */ + { 0x0000, 0x0000, 0x0000 }, /* R8364 */ + { 0x0000, 0x0000, 0x0000 }, /* R8365 */ + { 0x0000, 0x0000, 0x0000 }, /* R8366 */ + { 0x0000, 0x0000, 0x0000 }, /* R8367 */ + { 0x0000, 0x0000, 0x0000 }, /* R8368 */ + { 0x0000, 0x0000, 0x0000 }, /* R8369 */ + { 0x0000, 0x0000, 0x0000 }, /* R8370 */ + { 0x0000, 0x0000, 0x0000 }, /* R8371 */ + { 0x0000, 0x0000, 0x0000 }, /* R8372 */ + { 0x0000, 0x0000, 0x0000 }, /* R8373 */ + { 0x0000, 0x0000, 0x0000 }, /* R8374 */ + { 0x0000, 0x0000, 0x0000 }, /* R8375 */ + { 0x0000, 0x0000, 0x0000 }, /* R8376 */ + { 0x0000, 0x0000, 0x0000 }, /* R8377 */ + { 0x0000, 0x0000, 0x0000 }, /* R8378 */ + { 0x0000, 0x0000, 0x0000 }, /* R8379 */ + { 0x0000, 0x0000, 0x0000 }, /* R8380 */ + { 0x0000, 0x0000, 0x0000 }, /* R8381 */ + { 0x0000, 0x0000, 0x0000 }, /* R8382 */ + { 0x0000, 0x0000, 0x0000 }, /* R8383 */ + { 0x0000, 0x0000, 0x0000 }, /* R8384 */ + { 0x0000, 0x0000, 0x0000 }, /* R8385 */ + { 0x0000, 0x0000, 0x0000 }, /* R8386 */ + { 0x0000, 0x0000, 0x0000 }, /* R8387 */ + { 0x0000, 0x0000, 0x0000 }, /* R8388 */ + { 0x0000, 0x0000, 0x0000 }, /* R8389 */ + { 0x0000, 0x0000, 0x0000 }, /* R8390 */ + { 0x0000, 0x0000, 0x0000 }, /* R8391 */ + { 0x0000, 0x0000, 0x0000 }, /* R8392 */ + { 0x0000, 0x0000, 0x0000 }, /* R8393 */ + { 0x0000, 0x0000, 0x0000 }, /* R8394 */ + { 0x0000, 0x0000, 0x0000 }, /* R8395 */ + { 0x0000, 0x0000, 0x0000 }, /* R8396 */ + { 0x0000, 0x0000, 0x0000 }, /* R8397 */ + { 0x0000, 0x0000, 0x0000 }, /* R8398 */ + { 0x0000, 0x0000, 0x0000 }, /* R8399 */ + { 0x0000, 0x0000, 0x0000 }, /* R8400 */ + { 0x0000, 0x0000, 0x0000 }, /* R8401 */ + { 0x0000, 0x0000, 0x0000 }, /* R8402 */ + { 0x0000, 0x0000, 0x0000 }, /* R8403 */ + { 0x0000, 0x0000, 0x0000 }, /* R8404 */ + { 0x0000, 0x0000, 0x0000 }, /* R8405 */ + { 0x0000, 0x0000, 0x0000 }, /* R8406 */ + { 0x0000, 0x0000, 0x0000 }, /* R8407 */ + { 0x0000, 0x0000, 0x0000 }, /* R8408 */ + { 0x0000, 0x0000, 0x0000 }, /* R8409 */ + { 0x0000, 0x0000, 0x0000 }, /* R8410 */ + { 0x0000, 0x0000, 0x0000 }, /* R8411 */ + { 0x0000, 0x0000, 0x0000 }, /* R8412 */ + { 0x0000, 0x0000, 0x0000 }, /* R8413 */ + { 0x0000, 0x0000, 0x0000 }, /* R8414 */ + { 0x0000, 0x0000, 0x0000 }, /* R8415 */ + { 0x0000, 0x0000, 0x0000 }, /* R8416 */ + { 0x0000, 0x0000, 0x0000 }, /* R8417 */ + { 0x0000, 0x0000, 0x0000 }, /* R8418 */ + { 0x0000, 0x0000, 0x0000 }, /* R8419 */ + { 0x0000, 0x0000, 0x0000 }, /* R8420 */ + { 0x0000, 0x0000, 0x0000 }, /* R8421 */ + { 0x0000, 0x0000, 0x0000 }, /* R8422 */ + { 0x0000, 0x0000, 0x0000 }, /* R8423 */ + { 0x0000, 0x0000, 0x0000 }, /* R8424 */ + { 0x0000, 0x0000, 0x0000 }, /* R8425 */ + { 0x0000, 0x0000, 0x0000 }, /* R8426 */ + { 0x0000, 0x0000, 0x0000 }, /* R8427 */ + { 0x0000, 0x0000, 0x0000 }, /* R8428 */ + { 0x0000, 0x0000, 0x0000 }, /* R8429 */ + { 0x0000, 0x0000, 0x0000 }, /* R8430 */ + { 0x0000, 0x0000, 0x0000 }, /* R8431 */ + { 0x0000, 0x0000, 0x0000 }, /* R8432 */ + { 0x0000, 0x0000, 0x0000 }, /* R8433 */ + { 0x0000, 0x0000, 0x0000 }, /* R8434 */ + { 0x0000, 0x0000, 0x0000 }, /* R8435 */ + { 0x0000, 0x0000, 0x0000 }, /* R8436 */ + { 0x0000, 0x0000, 0x0000 }, /* R8437 */ + { 0x0000, 0x0000, 0x0000 }, /* R8438 */ + { 0x0000, 0x0000, 0x0000 }, /* R8439 */ + { 0x0000, 0x0000, 0x0000 }, /* R8440 */ + { 0x0000, 0x0000, 0x0000 }, /* R8441 */ + { 0x0000, 0x0000, 0x0000 }, /* R8442 */ + { 0x0000, 0x0000, 0x0000 }, /* R8443 */ + { 0x0000, 0x0000, 0x0000 }, /* R8444 */ + { 0x0000, 0x0000, 0x0000 }, /* R8445 */ + { 0x0000, 0x0000, 0x0000 }, /* R8446 */ + { 0x0000, 0x0000, 0x0000 }, /* R8447 */ + { 0x0000, 0x0000, 0x0000 }, /* R8448 */ + { 0x0000, 0x0000, 0x0000 }, /* R8449 */ + { 0x0000, 0x0000, 0x0000 }, /* R8450 */ + { 0x0000, 0x0000, 0x0000 }, /* R8451 */ + { 0x0000, 0x0000, 0x0000 }, /* R8452 */ + { 0x0000, 0x0000, 0x0000 }, /* R8453 */ + { 0x0000, 0x0000, 0x0000 }, /* R8454 */ + { 0x0000, 0x0000, 0x0000 }, /* R8455 */ + { 0x0000, 0x0000, 0x0000 }, /* R8456 */ + { 0x0000, 0x0000, 0x0000 }, /* R8457 */ + { 0x0000, 0x0000, 0x0000 }, /* R8458 */ + { 0x0000, 0x0000, 0x0000 }, /* R8459 */ + { 0x0000, 0x0000, 0x0000 }, /* R8460 */ + { 0x0000, 0x0000, 0x0000 }, /* R8461 */ + { 0x0000, 0x0000, 0x0000 }, /* R8462 */ + { 0x0000, 0x0000, 0x0000 }, /* R8463 */ + { 0x0000, 0x0000, 0x0000 }, /* R8464 */ + { 0x0000, 0x0000, 0x0000 }, /* R8465 */ + { 0x0000, 0x0000, 0x0000 }, /* R8466 */ + { 0x0000, 0x0000, 0x0000 }, /* R8467 */ + { 0x0000, 0x0000, 0x0000 }, /* R8468 */ + { 0x0000, 0x0000, 0x0000 }, /* R8469 */ + { 0x0000, 0x0000, 0x0000 }, /* R8470 */ + { 0x0000, 0x0000, 0x0000 }, /* R8471 */ + { 0x0000, 0x0000, 0x0000 }, /* R8472 */ + { 0x0000, 0x0000, 0x0000 }, /* R8473 */ + { 0x0000, 0x0000, 0x0000 }, /* R8474 */ + { 0x0000, 0x0000, 0x0000 }, /* R8475 */ + { 0x0000, 0x0000, 0x0000 }, /* R8476 */ + { 0x0000, 0x0000, 0x0000 }, /* R8477 */ + { 0x0000, 0x0000, 0x0000 }, /* R8478 */ + { 0x0000, 0x0000, 0x0000 }, /* R8479 */ + { 0x0000, 0x0000, 0x0000 }, /* R8480 */ + { 0x0000, 0x0000, 0x0000 }, /* R8481 */ + { 0x0000, 0x0000, 0x0000 }, /* R8482 */ + { 0x0000, 0x0000, 0x0000 }, /* R8483 */ + { 0x0000, 0x0000, 0x0000 }, /* R8484 */ + { 0x0000, 0x0000, 0x0000 }, /* R8485 */ + { 0x0000, 0x0000, 0x0000 }, /* R8486 */ + { 0x0000, 0x0000, 0x0000 }, /* R8487 */ + { 0x0000, 0x0000, 0x0000 }, /* R8488 */ + { 0x0000, 0x0000, 0x0000 }, /* R8489 */ + { 0x0000, 0x0000, 0x0000 }, /* R8490 */ + { 0x0000, 0x0000, 0x0000 }, /* R8491 */ + { 0x0000, 0x0000, 0x0000 }, /* R8492 */ + { 0x0000, 0x0000, 0x0000 }, /* R8493 */ + { 0x0000, 0x0000, 0x0000 }, /* R8494 */ + { 0x0000, 0x0000, 0x0000 }, /* R8495 */ + { 0x0000, 0x0000, 0x0000 }, /* R8496 */ + { 0x0000, 0x0000, 0x0000 }, /* R8497 */ + { 0x0000, 0x0000, 0x0000 }, /* R8498 */ + { 0x0000, 0x0000, 0x0000 }, /* R8499 */ + { 0x0000, 0x0000, 0x0000 }, /* R8500 */ + { 0x0000, 0x0000, 0x0000 }, /* R8501 */ + { 0x0000, 0x0000, 0x0000 }, /* R8502 */ + { 0x0000, 0x0000, 0x0000 }, /* R8503 */ + { 0x0000, 0x0000, 0x0000 }, /* R8504 */ + { 0x0000, 0x0000, 0x0000 }, /* R8505 */ + { 0x0000, 0x0000, 0x0000 }, /* R8506 */ + { 0x0000, 0x0000, 0x0000 }, /* R8507 */ + { 0x0000, 0x0000, 0x0000 }, /* R8508 */ + { 0x0000, 0x0000, 0x0000 }, /* R8509 */ + { 0x0000, 0x0000, 0x0000 }, /* R8510 */ + { 0x0000, 0x0000, 0x0000 }, /* R8511 */ + { 0x0000, 0x0000, 0x0000 }, /* R8512 */ + { 0x0000, 0x0000, 0x0000 }, /* R8513 */ + { 0x0000, 0x0000, 0x0000 }, /* R8514 */ + { 0x0000, 0x0000, 0x0000 }, /* R8515 */ + { 0x0000, 0x0000, 0x0000 }, /* R8516 */ + { 0x0000, 0x0000, 0x0000 }, /* R8517 */ + { 0x0000, 0x0000, 0x0000 }, /* R8518 */ + { 0x0000, 0x0000, 0x0000 }, /* R8519 */ + { 0x0000, 0x0000, 0x0000 }, /* R8520 */ + { 0x0000, 0x0000, 0x0000 }, /* R8521 */ + { 0x0000, 0x0000, 0x0000 }, /* R8522 */ + { 0x0000, 0x0000, 0x0000 }, /* R8523 */ + { 0x0000, 0x0000, 0x0000 }, /* R8524 */ + { 0x0000, 0x0000, 0x0000 }, /* R8525 */ + { 0x0000, 0x0000, 0x0000 }, /* R8526 */ + { 0x0000, 0x0000, 0x0000 }, /* R8527 */ + { 0x0000, 0x0000, 0x0000 }, /* R8528 */ + { 0x0000, 0x0000, 0x0000 }, /* R8529 */ + { 0x0000, 0x0000, 0x0000 }, /* R8530 */ + { 0x0000, 0x0000, 0x0000 }, /* R8531 */ + { 0x0000, 0x0000, 0x0000 }, /* R8532 */ + { 0x0000, 0x0000, 0x0000 }, /* R8533 */ + { 0x0000, 0x0000, 0x0000 }, /* R8534 */ + { 0x0000, 0x0000, 0x0000 }, /* R8535 */ + { 0x0000, 0x0000, 0x0000 }, /* R8536 */ + { 0x0000, 0x0000, 0x0000 }, /* R8537 */ + { 0x0000, 0x0000, 0x0000 }, /* R8538 */ + { 0x0000, 0x0000, 0x0000 }, /* R8539 */ + { 0x0000, 0x0000, 0x0000 }, /* R8540 */ + { 0x0000, 0x0000, 0x0000 }, /* R8541 */ + { 0x0000, 0x0000, 0x0000 }, /* R8542 */ + { 0x0000, 0x0000, 0x0000 }, /* R8543 */ + { 0x0000, 0x0000, 0x0000 }, /* R8544 */ + { 0x0000, 0x0000, 0x0000 }, /* R8545 */ + { 0x0000, 0x0000, 0x0000 }, /* R8546 */ + { 0x0000, 0x0000, 0x0000 }, /* R8547 */ + { 0x0000, 0x0000, 0x0000 }, /* R8548 */ + { 0x0000, 0x0000, 0x0000 }, /* R8549 */ + { 0x0000, 0x0000, 0x0000 }, /* R8550 */ + { 0x0000, 0x0000, 0x0000 }, /* R8551 */ + { 0x0000, 0x0000, 0x0000 }, /* R8552 */ + { 0x0000, 0x0000, 0x0000 }, /* R8553 */ + { 0x0000, 0x0000, 0x0000 }, /* R8554 */ + { 0x0000, 0x0000, 0x0000 }, /* R8555 */ + { 0x0000, 0x0000, 0x0000 }, /* R8556 */ + { 0x0000, 0x0000, 0x0000 }, /* R8557 */ + { 0x0000, 0x0000, 0x0000 }, /* R8558 */ + { 0x0000, 0x0000, 0x0000 }, /* R8559 */ + { 0x0000, 0x0000, 0x0000 }, /* R8560 */ + { 0x0000, 0x0000, 0x0000 }, /* R8561 */ + { 0x0000, 0x0000, 0x0000 }, /* R8562 */ + { 0x0000, 0x0000, 0x0000 }, /* R8563 */ + { 0x0000, 0x0000, 0x0000 }, /* R8564 */ + { 0x0000, 0x0000, 0x0000 }, /* R8565 */ + { 0x0000, 0x0000, 0x0000 }, /* R8566 */ + { 0x0000, 0x0000, 0x0000 }, /* R8567 */ + { 0x0000, 0x0000, 0x0000 }, /* R8568 */ + { 0x0000, 0x0000, 0x0000 }, /* R8569 */ + { 0x0000, 0x0000, 0x0000 }, /* R8570 */ + { 0x0000, 0x0000, 0x0000 }, /* R8571 */ + { 0x0000, 0x0000, 0x0000 }, /* R8572 */ + { 0x0000, 0x0000, 0x0000 }, /* R8573 */ + { 0x0000, 0x0000, 0x0000 }, /* R8574 */ + { 0x0000, 0x0000, 0x0000 }, /* R8575 */ + { 0x0000, 0x0000, 0x0000 }, /* R8576 */ + { 0x0000, 0x0000, 0x0000 }, /* R8577 */ + { 0x0000, 0x0000, 0x0000 }, /* R8578 */ + { 0x0000, 0x0000, 0x0000 }, /* R8579 */ + { 0x0000, 0x0000, 0x0000 }, /* R8580 */ + { 0x0000, 0x0000, 0x0000 }, /* R8581 */ + { 0x0000, 0x0000, 0x0000 }, /* R8582 */ + { 0x0000, 0x0000, 0x0000 }, /* R8583 */ + { 0x0000, 0x0000, 0x0000 }, /* R8584 */ + { 0x0000, 0x0000, 0x0000 }, /* R8585 */ + { 0x0000, 0x0000, 0x0000 }, /* R8586 */ + { 0x0000, 0x0000, 0x0000 }, /* R8587 */ + { 0x0000, 0x0000, 0x0000 }, /* R8588 */ + { 0x0000, 0x0000, 0x0000 }, /* R8589 */ + { 0x0000, 0x0000, 0x0000 }, /* R8590 */ + { 0x0000, 0x0000, 0x0000 }, /* R8591 */ + { 0x0000, 0x0000, 0x0000 }, /* R8592 */ + { 0x0000, 0x0000, 0x0000 }, /* R8593 */ + { 0x0000, 0x0000, 0x0000 }, /* R8594 */ + { 0x0000, 0x0000, 0x0000 }, /* R8595 */ + { 0x0000, 0x0000, 0x0000 }, /* R8596 */ + { 0x0000, 0x0000, 0x0000 }, /* R8597 */ + { 0x0000, 0x0000, 0x0000 }, /* R8598 */ + { 0x0000, 0x0000, 0x0000 }, /* R8599 */ + { 0x0000, 0x0000, 0x0000 }, /* R8600 */ + { 0x0000, 0x0000, 0x0000 }, /* R8601 */ + { 0x0000, 0x0000, 0x0000 }, /* R8602 */ + { 0x0000, 0x0000, 0x0000 }, /* R8603 */ + { 0x0000, 0x0000, 0x0000 }, /* R8604 */ + { 0x0000, 0x0000, 0x0000 }, /* R8605 */ + { 0x0000, 0x0000, 0x0000 }, /* R8606 */ + { 0x0000, 0x0000, 0x0000 }, /* R8607 */ + { 0x0000, 0x0000, 0x0000 }, /* R8608 */ + { 0x0000, 0x0000, 0x0000 }, /* R8609 */ + { 0x0000, 0x0000, 0x0000 }, /* R8610 */ + { 0x0000, 0x0000, 0x0000 }, /* R8611 */ + { 0x0000, 0x0000, 0x0000 }, /* R8612 */ + { 0x0000, 0x0000, 0x0000 }, /* R8613 */ + { 0x0000, 0x0000, 0x0000 }, /* R8614 */ + { 0x0000, 0x0000, 0x0000 }, /* R8615 */ + { 0x0000, 0x0000, 0x0000 }, /* R8616 */ + { 0x0000, 0x0000, 0x0000 }, /* R8617 */ + { 0x0000, 0x0000, 0x0000 }, /* R8618 */ + { 0x0000, 0x0000, 0x0000 }, /* R8619 */ + { 0x0000, 0x0000, 0x0000 }, /* R8620 */ + { 0x0000, 0x0000, 0x0000 }, /* R8621 */ + { 0x0000, 0x0000, 0x0000 }, /* R8622 */ + { 0x0000, 0x0000, 0x0000 }, /* R8623 */ + { 0x0000, 0x0000, 0x0000 }, /* R8624 */ + { 0x0000, 0x0000, 0x0000 }, /* R8625 */ + { 0x0000, 0x0000, 0x0000 }, /* R8626 */ + { 0x0000, 0x0000, 0x0000 }, /* R8627 */ + { 0x0000, 0x0000, 0x0000 }, /* R8628 */ + { 0x0000, 0x0000, 0x0000 }, /* R8629 */ + { 0x0000, 0x0000, 0x0000 }, /* R8630 */ + { 0x0000, 0x0000, 0x0000 }, /* R8631 */ + { 0x0000, 0x0000, 0x0000 }, /* R8632 */ + { 0x0000, 0x0000, 0x0000 }, /* R8633 */ + { 0x0000, 0x0000, 0x0000 }, /* R8634 */ + { 0x0000, 0x0000, 0x0000 }, /* R8635 */ + { 0x0000, 0x0000, 0x0000 }, /* R8636 */ + { 0x0000, 0x0000, 0x0000 }, /* R8637 */ + { 0x0000, 0x0000, 0x0000 }, /* R8638 */ + { 0x0000, 0x0000, 0x0000 }, /* R8639 */ + { 0x0000, 0x0000, 0x0000 }, /* R8640 */ + { 0x0000, 0x0000, 0x0000 }, /* R8641 */ + { 0x0000, 0x0000, 0x0000 }, /* R8642 */ + { 0x0000, 0x0000, 0x0000 }, /* R8643 */ + { 0x0000, 0x0000, 0x0000 }, /* R8644 */ + { 0x0000, 0x0000, 0x0000 }, /* R8645 */ + { 0x0000, 0x0000, 0x0000 }, /* R8646 */ + { 0x0000, 0x0000, 0x0000 }, /* R8647 */ + { 0x0000, 0x0000, 0x0000 }, /* R8648 */ + { 0x0000, 0x0000, 0x0000 }, /* R8649 */ + { 0x0000, 0x0000, 0x0000 }, /* R8650 */ + { 0x0000, 0x0000, 0x0000 }, /* R8651 */ + { 0x0000, 0x0000, 0x0000 }, /* R8652 */ + { 0x0000, 0x0000, 0x0000 }, /* R8653 */ + { 0x0000, 0x0000, 0x0000 }, /* R8654 */ + { 0x0000, 0x0000, 0x0000 }, /* R8655 */ + { 0x0000, 0x0000, 0x0000 }, /* R8656 */ + { 0x0000, 0x0000, 0x0000 }, /* R8657 */ + { 0x0000, 0x0000, 0x0000 }, /* R8658 */ + { 0x0000, 0x0000, 0x0000 }, /* R8659 */ + { 0x0000, 0x0000, 0x0000 }, /* R8660 */ + { 0x0000, 0x0000, 0x0000 }, /* R8661 */ + { 0x0000, 0x0000, 0x0000 }, /* R8662 */ + { 0x0000, 0x0000, 0x0000 }, /* R8663 */ + { 0x0000, 0x0000, 0x0000 }, /* R8664 */ + { 0x0000, 0x0000, 0x0000 }, /* R8665 */ + { 0x0000, 0x0000, 0x0000 }, /* R8666 */ + { 0x0000, 0x0000, 0x0000 }, /* R8667 */ + { 0x0000, 0x0000, 0x0000 }, /* R8668 */ + { 0x0000, 0x0000, 0x0000 }, /* R8669 */ + { 0x0000, 0x0000, 0x0000 }, /* R8670 */ + { 0x0000, 0x0000, 0x0000 }, /* R8671 */ + { 0x0000, 0x0000, 0x0000 }, /* R8672 */ + { 0x0000, 0x0000, 0x0000 }, /* R8673 */ + { 0x0000, 0x0000, 0x0000 }, /* R8674 */ + { 0x0000, 0x0000, 0x0000 }, /* R8675 */ + { 0x0000, 0x0000, 0x0000 }, /* R8676 */ + { 0x0000, 0x0000, 0x0000 }, /* R8677 */ + { 0x0000, 0x0000, 0x0000 }, /* R8678 */ + { 0x0000, 0x0000, 0x0000 }, /* R8679 */ + { 0x0000, 0x0000, 0x0000 }, /* R8680 */ + { 0x0000, 0x0000, 0x0000 }, /* R8681 */ + { 0x0000, 0x0000, 0x0000 }, /* R8682 */ + { 0x0000, 0x0000, 0x0000 }, /* R8683 */ + { 0x0000, 0x0000, 0x0000 }, /* R8684 */ + { 0x0000, 0x0000, 0x0000 }, /* R8685 */ + { 0x0000, 0x0000, 0x0000 }, /* R8686 */ + { 0x0000, 0x0000, 0x0000 }, /* R8687 */ + { 0x0000, 0x0000, 0x0000 }, /* R8688 */ + { 0x0000, 0x0000, 0x0000 }, /* R8689 */ + { 0x0000, 0x0000, 0x0000 }, /* R8690 */ + { 0x0000, 0x0000, 0x0000 }, /* R8691 */ + { 0x0000, 0x0000, 0x0000 }, /* R8692 */ + { 0x0000, 0x0000, 0x0000 }, /* R8693 */ + { 0x0000, 0x0000, 0x0000 }, /* R8694 */ + { 0x0000, 0x0000, 0x0000 }, /* R8695 */ + { 0x0000, 0x0000, 0x0000 }, /* R8696 */ + { 0x0000, 0x0000, 0x0000 }, /* R8697 */ + { 0x0000, 0x0000, 0x0000 }, /* R8698 */ + { 0x0000, 0x0000, 0x0000 }, /* R8699 */ + { 0x0000, 0x0000, 0x0000 }, /* R8700 */ + { 0x0000, 0x0000, 0x0000 }, /* R8701 */ + { 0x0000, 0x0000, 0x0000 }, /* R8702 */ + { 0x0000, 0x0000, 0x0000 }, /* R8703 */ + { 0x0000, 0x0000, 0x0000 }, /* R8704 */ + { 0x0000, 0x0000, 0x0000 }, /* R8705 */ + { 0x0000, 0x0000, 0x0000 }, /* R8706 */ + { 0x0000, 0x0000, 0x0000 }, /* R8707 */ + { 0x0000, 0x0000, 0x0000 }, /* R8708 */ + { 0x0000, 0x0000, 0x0000 }, /* R8709 */ + { 0x0000, 0x0000, 0x0000 }, /* R8710 */ + { 0x0000, 0x0000, 0x0000 }, /* R8711 */ + { 0x0000, 0x0000, 0x0000 }, /* R8712 */ + { 0x0000, 0x0000, 0x0000 }, /* R8713 */ + { 0x0000, 0x0000, 0x0000 }, /* R8714 */ + { 0x0000, 0x0000, 0x0000 }, /* R8715 */ + { 0x0000, 0x0000, 0x0000 }, /* R8716 */ + { 0x0000, 0x0000, 0x0000 }, /* R8717 */ + { 0x0000, 0x0000, 0x0000 }, /* R8718 */ + { 0x0000, 0x0000, 0x0000 }, /* R8719 */ + { 0x0000, 0x0000, 0x0000 }, /* R8720 */ + { 0x0000, 0x0000, 0x0000 }, /* R8721 */ + { 0x0000, 0x0000, 0x0000 }, /* R8722 */ + { 0x0000, 0x0000, 0x0000 }, /* R8723 */ + { 0x0000, 0x0000, 0x0000 }, /* R8724 */ + { 0x0000, 0x0000, 0x0000 }, /* R8725 */ + { 0x0000, 0x0000, 0x0000 }, /* R8726 */ + { 0x0000, 0x0000, 0x0000 }, /* R8727 */ + { 0x0000, 0x0000, 0x0000 }, /* R8728 */ + { 0x0000, 0x0000, 0x0000 }, /* R8729 */ + { 0x0000, 0x0000, 0x0000 }, /* R8730 */ + { 0x0000, 0x0000, 0x0000 }, /* R8731 */ + { 0x0000, 0x0000, 0x0000 }, /* R8732 */ + { 0x0000, 0x0000, 0x0000 }, /* R8733 */ + { 0x0000, 0x0000, 0x0000 }, /* R8734 */ + { 0x0000, 0x0000, 0x0000 }, /* R8735 */ + { 0x0000, 0x0000, 0x0000 }, /* R8736 */ + { 0x0000, 0x0000, 0x0000 }, /* R8737 */ + { 0x0000, 0x0000, 0x0000 }, /* R8738 */ + { 0x0000, 0x0000, 0x0000 }, /* R8739 */ + { 0x0000, 0x0000, 0x0000 }, /* R8740 */ + { 0x0000, 0x0000, 0x0000 }, /* R8741 */ + { 0x0000, 0x0000, 0x0000 }, /* R8742 */ + { 0x0000, 0x0000, 0x0000 }, /* R8743 */ + { 0x0000, 0x0000, 0x0000 }, /* R8744 */ + { 0x0000, 0x0000, 0x0000 }, /* R8745 */ + { 0x0000, 0x0000, 0x0000 }, /* R8746 */ + { 0x0000, 0x0000, 0x0000 }, /* R8747 */ + { 0x0000, 0x0000, 0x0000 }, /* R8748 */ + { 0x0000, 0x0000, 0x0000 }, /* R8749 */ + { 0x0000, 0x0000, 0x0000 }, /* R8750 */ + { 0x0000, 0x0000, 0x0000 }, /* R8751 */ + { 0x0000, 0x0000, 0x0000 }, /* R8752 */ + { 0x0000, 0x0000, 0x0000 }, /* R8753 */ + { 0x0000, 0x0000, 0x0000 }, /* R8754 */ + { 0x0000, 0x0000, 0x0000 }, /* R8755 */ + { 0x0000, 0x0000, 0x0000 }, /* R8756 */ + { 0x0000, 0x0000, 0x0000 }, /* R8757 */ + { 0x0000, 0x0000, 0x0000 }, /* R8758 */ + { 0x0000, 0x0000, 0x0000 }, /* R8759 */ + { 0x0000, 0x0000, 0x0000 }, /* R8760 */ + { 0x0000, 0x0000, 0x0000 }, /* R8761 */ + { 0x0000, 0x0000, 0x0000 }, /* R8762 */ + { 0x0000, 0x0000, 0x0000 }, /* R8763 */ + { 0x0000, 0x0000, 0x0000 }, /* R8764 */ + { 0x0000, 0x0000, 0x0000 }, /* R8765 */ + { 0x0000, 0x0000, 0x0000 }, /* R8766 */ + { 0x0000, 0x0000, 0x0000 }, /* R8767 */ + { 0x0000, 0x0000, 0x0000 }, /* R8768 */ + { 0x0000, 0x0000, 0x0000 }, /* R8769 */ + { 0x0000, 0x0000, 0x0000 }, /* R8770 */ + { 0x0000, 0x0000, 0x0000 }, /* R8771 */ + { 0x0000, 0x0000, 0x0000 }, /* R8772 */ + { 0x0000, 0x0000, 0x0000 }, /* R8773 */ + { 0x0000, 0x0000, 0x0000 }, /* R8774 */ + { 0x0000, 0x0000, 0x0000 }, /* R8775 */ + { 0x0000, 0x0000, 0x0000 }, /* R8776 */ + { 0x0000, 0x0000, 0x0000 }, /* R8777 */ + { 0x0000, 0x0000, 0x0000 }, /* R8778 */ + { 0x0000, 0x0000, 0x0000 }, /* R8779 */ + { 0x0000, 0x0000, 0x0000 }, /* R8780 */ + { 0x0000, 0x0000, 0x0000 }, /* R8781 */ + { 0x0000, 0x0000, 0x0000 }, /* R8782 */ + { 0x0000, 0x0000, 0x0000 }, /* R8783 */ + { 0x0000, 0x0000, 0x0000 }, /* R8784 */ + { 0x0000, 0x0000, 0x0000 }, /* R8785 */ + { 0x0000, 0x0000, 0x0000 }, /* R8786 */ + { 0x0000, 0x0000, 0x0000 }, /* R8787 */ + { 0x0000, 0x0000, 0x0000 }, /* R8788 */ + { 0x0000, 0x0000, 0x0000 }, /* R8789 */ + { 0x0000, 0x0000, 0x0000 }, /* R8790 */ + { 0x0000, 0x0000, 0x0000 }, /* R8791 */ + { 0x0000, 0x0000, 0x0000 }, /* R8792 */ + { 0x0000, 0x0000, 0x0000 }, /* R8793 */ + { 0x0000, 0x0000, 0x0000 }, /* R8794 */ + { 0x0000, 0x0000, 0x0000 }, /* R8795 */ + { 0x0000, 0x0000, 0x0000 }, /* R8796 */ + { 0x0000, 0x0000, 0x0000 }, /* R8797 */ + { 0x0000, 0x0000, 0x0000 }, /* R8798 */ + { 0x0000, 0x0000, 0x0000 }, /* R8799 */ + { 0x0000, 0x0000, 0x0000 }, /* R8800 */ + { 0x0000, 0x0000, 0x0000 }, /* R8801 */ + { 0x0000, 0x0000, 0x0000 }, /* R8802 */ + { 0x0000, 0x0000, 0x0000 }, /* R8803 */ + { 0x0000, 0x0000, 0x0000 }, /* R8804 */ + { 0x0000, 0x0000, 0x0000 }, /* R8805 */ + { 0x0000, 0x0000, 0x0000 }, /* R8806 */ + { 0x0000, 0x0000, 0x0000 }, /* R8807 */ + { 0x0000, 0x0000, 0x0000 }, /* R8808 */ + { 0x0000, 0x0000, 0x0000 }, /* R8809 */ + { 0x0000, 0x0000, 0x0000 }, /* R8810 */ + { 0x0000, 0x0000, 0x0000 }, /* R8811 */ + { 0x0000, 0x0000, 0x0000 }, /* R8812 */ + { 0x0000, 0x0000, 0x0000 }, /* R8813 */ + { 0x0000, 0x0000, 0x0000 }, /* R8814 */ + { 0x0000, 0x0000, 0x0000 }, /* R8815 */ + { 0x0000, 0x0000, 0x0000 }, /* R8816 */ + { 0x0000, 0x0000, 0x0000 }, /* R8817 */ + { 0x0000, 0x0000, 0x0000 }, /* R8818 */ + { 0x0000, 0x0000, 0x0000 }, /* R8819 */ + { 0x0000, 0x0000, 0x0000 }, /* R8820 */ + { 0x0000, 0x0000, 0x0000 }, /* R8821 */ + { 0x0000, 0x0000, 0x0000 }, /* R8822 */ + { 0x0000, 0x0000, 0x0000 }, /* R8823 */ + { 0x0000, 0x0000, 0x0000 }, /* R8824 */ + { 0x0000, 0x0000, 0x0000 }, /* R8825 */ + { 0x0000, 0x0000, 0x0000 }, /* R8826 */ + { 0x0000, 0x0000, 0x0000 }, /* R8827 */ + { 0x0000, 0x0000, 0x0000 }, /* R8828 */ + { 0x0000, 0x0000, 0x0000 }, /* R8829 */ + { 0x0000, 0x0000, 0x0000 }, /* R8830 */ + { 0x0000, 0x0000, 0x0000 }, /* R8831 */ + { 0x0000, 0x0000, 0x0000 }, /* R8832 */ + { 0x0000, 0x0000, 0x0000 }, /* R8833 */ + { 0x0000, 0x0000, 0x0000 }, /* R8834 */ + { 0x0000, 0x0000, 0x0000 }, /* R8835 */ + { 0x0000, 0x0000, 0x0000 }, /* R8836 */ + { 0x0000, 0x0000, 0x0000 }, /* R8837 */ + { 0x0000, 0x0000, 0x0000 }, /* R8838 */ + { 0x0000, 0x0000, 0x0000 }, /* R8839 */ + { 0x0000, 0x0000, 0x0000 }, /* R8840 */ + { 0x0000, 0x0000, 0x0000 }, /* R8841 */ + { 0x0000, 0x0000, 0x0000 }, /* R8842 */ + { 0x0000, 0x0000, 0x0000 }, /* R8843 */ + { 0x0000, 0x0000, 0x0000 }, /* R8844 */ + { 0x0000, 0x0000, 0x0000 }, /* R8845 */ + { 0x0000, 0x0000, 0x0000 }, /* R8846 */ + { 0x0000, 0x0000, 0x0000 }, /* R8847 */ + { 0x0000, 0x0000, 0x0000 }, /* R8848 */ + { 0x0000, 0x0000, 0x0000 }, /* R8849 */ + { 0x0000, 0x0000, 0x0000 }, /* R8850 */ + { 0x0000, 0x0000, 0x0000 }, /* R8851 */ + { 0x0000, 0x0000, 0x0000 }, /* R8852 */ + { 0x0000, 0x0000, 0x0000 }, /* R8853 */ + { 0x0000, 0x0000, 0x0000 }, /* R8854 */ + { 0x0000, 0x0000, 0x0000 }, /* R8855 */ + { 0x0000, 0x0000, 0x0000 }, /* R8856 */ + { 0x0000, 0x0000, 0x0000 }, /* R8857 */ + { 0x0000, 0x0000, 0x0000 }, /* R8858 */ + { 0x0000, 0x0000, 0x0000 }, /* R8859 */ + { 0x0000, 0x0000, 0x0000 }, /* R8860 */ + { 0x0000, 0x0000, 0x0000 }, /* R8861 */ + { 0x0000, 0x0000, 0x0000 }, /* R8862 */ + { 0x0000, 0x0000, 0x0000 }, /* R8863 */ + { 0x0000, 0x0000, 0x0000 }, /* R8864 */ + { 0x0000, 0x0000, 0x0000 }, /* R8865 */ + { 0x0000, 0x0000, 0x0000 }, /* R8866 */ + { 0x0000, 0x0000, 0x0000 }, /* R8867 */ + { 0x0000, 0x0000, 0x0000 }, /* R8868 */ + { 0x0000, 0x0000, 0x0000 }, /* R8869 */ + { 0x0000, 0x0000, 0x0000 }, /* R8870 */ + { 0x0000, 0x0000, 0x0000 }, /* R8871 */ + { 0x0000, 0x0000, 0x0000 }, /* R8872 */ + { 0x0000, 0x0000, 0x0000 }, /* R8873 */ + { 0x0000, 0x0000, 0x0000 }, /* R8874 */ + { 0x0000, 0x0000, 0x0000 }, /* R8875 */ + { 0x0000, 0x0000, 0x0000 }, /* R8876 */ + { 0x0000, 0x0000, 0x0000 }, /* R8877 */ + { 0x0000, 0x0000, 0x0000 }, /* R8878 */ + { 0x0000, 0x0000, 0x0000 }, /* R8879 */ + { 0x0000, 0x0000, 0x0000 }, /* R8880 */ + { 0x0000, 0x0000, 0x0000 }, /* R8881 */ + { 0x0000, 0x0000, 0x0000 }, /* R8882 */ + { 0x0000, 0x0000, 0x0000 }, /* R8883 */ + { 0x0000, 0x0000, 0x0000 }, /* R8884 */ + { 0x0000, 0x0000, 0x0000 }, /* R8885 */ + { 0x0000, 0x0000, 0x0000 }, /* R8886 */ + { 0x0000, 0x0000, 0x0000 }, /* R8887 */ + { 0x0000, 0x0000, 0x0000 }, /* R8888 */ + { 0x0000, 0x0000, 0x0000 }, /* R8889 */ + { 0x0000, 0x0000, 0x0000 }, /* R8890 */ + { 0x0000, 0x0000, 0x0000 }, /* R8891 */ + { 0x0000, 0x0000, 0x0000 }, /* R8892 */ + { 0x0000, 0x0000, 0x0000 }, /* R8893 */ + { 0x0000, 0x0000, 0x0000 }, /* R8894 */ + { 0x0000, 0x0000, 0x0000 }, /* R8895 */ + { 0x0000, 0x0000, 0x0000 }, /* R8896 */ + { 0x0000, 0x0000, 0x0000 }, /* R8897 */ + { 0x0000, 0x0000, 0x0000 }, /* R8898 */ + { 0x0000, 0x0000, 0x0000 }, /* R8899 */ + { 0x0000, 0x0000, 0x0000 }, /* R8900 */ + { 0x0000, 0x0000, 0x0000 }, /* R8901 */ + { 0x0000, 0x0000, 0x0000 }, /* R8902 */ + { 0x0000, 0x0000, 0x0000 }, /* R8903 */ + { 0x0000, 0x0000, 0x0000 }, /* R8904 */ + { 0x0000, 0x0000, 0x0000 }, /* R8905 */ + { 0x0000, 0x0000, 0x0000 }, /* R8906 */ + { 0x0000, 0x0000, 0x0000 }, /* R8907 */ + { 0x0000, 0x0000, 0x0000 }, /* R8908 */ + { 0x0000, 0x0000, 0x0000 }, /* R8909 */ + { 0x0000, 0x0000, 0x0000 }, /* R8910 */ + { 0x0000, 0x0000, 0x0000 }, /* R8911 */ + { 0x0000, 0x0000, 0x0000 }, /* R8912 */ + { 0x0000, 0x0000, 0x0000 }, /* R8913 */ + { 0x0000, 0x0000, 0x0000 }, /* R8914 */ + { 0x0000, 0x0000, 0x0000 }, /* R8915 */ + { 0x0000, 0x0000, 0x0000 }, /* R8916 */ + { 0x0000, 0x0000, 0x0000 }, /* R8917 */ + { 0x0000, 0x0000, 0x0000 }, /* R8918 */ + { 0x0000, 0x0000, 0x0000 }, /* R8919 */ + { 0x0000, 0x0000, 0x0000 }, /* R8920 */ + { 0x0000, 0x0000, 0x0000 }, /* R8921 */ + { 0x0000, 0x0000, 0x0000 }, /* R8922 */ + { 0x0000, 0x0000, 0x0000 }, /* R8923 */ + { 0x0000, 0x0000, 0x0000 }, /* R8924 */ + { 0x0000, 0x0000, 0x0000 }, /* R8925 */ + { 0x0000, 0x0000, 0x0000 }, /* R8926 */ + { 0x0000, 0x0000, 0x0000 }, /* R8927 */ + { 0x0000, 0x0000, 0x0000 }, /* R8928 */ + { 0x0000, 0x0000, 0x0000 }, /* R8929 */ + { 0x0000, 0x0000, 0x0000 }, /* R8930 */ + { 0x0000, 0x0000, 0x0000 }, /* R8931 */ + { 0x0000, 0x0000, 0x0000 }, /* R8932 */ + { 0x0000, 0x0000, 0x0000 }, /* R8933 */ + { 0x0000, 0x0000, 0x0000 }, /* R8934 */ + { 0x0000, 0x0000, 0x0000 }, /* R8935 */ + { 0x0000, 0x0000, 0x0000 }, /* R8936 */ + { 0x0000, 0x0000, 0x0000 }, /* R8937 */ + { 0x0000, 0x0000, 0x0000 }, /* R8938 */ + { 0x0000, 0x0000, 0x0000 }, /* R8939 */ + { 0x0000, 0x0000, 0x0000 }, /* R8940 */ + { 0x0000, 0x0000, 0x0000 }, /* R8941 */ + { 0x0000, 0x0000, 0x0000 }, /* R8942 */ + { 0x0000, 0x0000, 0x0000 }, /* R8943 */ + { 0x0000, 0x0000, 0x0000 }, /* R8944 */ + { 0x0000, 0x0000, 0x0000 }, /* R8945 */ + { 0x0000, 0x0000, 0x0000 }, /* R8946 */ + { 0x0000, 0x0000, 0x0000 }, /* R8947 */ + { 0x0000, 0x0000, 0x0000 }, /* R8948 */ + { 0x0000, 0x0000, 0x0000 }, /* R8949 */ + { 0x0000, 0x0000, 0x0000 }, /* R8950 */ + { 0x0000, 0x0000, 0x0000 }, /* R8951 */ + { 0x0000, 0x0000, 0x0000 }, /* R8952 */ + { 0x0000, 0x0000, 0x0000 }, /* R8953 */ + { 0x0000, 0x0000, 0x0000 }, /* R8954 */ + { 0x0000, 0x0000, 0x0000 }, /* R8955 */ + { 0x0000, 0x0000, 0x0000 }, /* R8956 */ + { 0x0000, 0x0000, 0x0000 }, /* R8957 */ + { 0x0000, 0x0000, 0x0000 }, /* R8958 */ + { 0x0000, 0x0000, 0x0000 }, /* R8959 */ + { 0x0000, 0x0000, 0x0000 }, /* R8960 */ + { 0x0000, 0x0000, 0x0000 }, /* R8961 */ + { 0x0000, 0x0000, 0x0000 }, /* R8962 */ + { 0x0000, 0x0000, 0x0000 }, /* R8963 */ + { 0x0000, 0x0000, 0x0000 }, /* R8964 */ + { 0x0000, 0x0000, 0x0000 }, /* R8965 */ + { 0x0000, 0x0000, 0x0000 }, /* R8966 */ + { 0x0000, 0x0000, 0x0000 }, /* R8967 */ + { 0x0000, 0x0000, 0x0000 }, /* R8968 */ + { 0x0000, 0x0000, 0x0000 }, /* R8969 */ + { 0x0000, 0x0000, 0x0000 }, /* R8970 */ + { 0x0000, 0x0000, 0x0000 }, /* R8971 */ + { 0x0000, 0x0000, 0x0000 }, /* R8972 */ + { 0x0000, 0x0000, 0x0000 }, /* R8973 */ + { 0x0000, 0x0000, 0x0000 }, /* R8974 */ + { 0x0000, 0x0000, 0x0000 }, /* R8975 */ + { 0x0000, 0x0000, 0x0000 }, /* R8976 */ + { 0x0000, 0x0000, 0x0000 }, /* R8977 */ + { 0x0000, 0x0000, 0x0000 }, /* R8978 */ + { 0x0000, 0x0000, 0x0000 }, /* R8979 */ + { 0x0000, 0x0000, 0x0000 }, /* R8980 */ + { 0x0000, 0x0000, 0x0000 }, /* R8981 */ + { 0x0000, 0x0000, 0x0000 }, /* R8982 */ + { 0x0000, 0x0000, 0x0000 }, /* R8983 */ + { 0x0000, 0x0000, 0x0000 }, /* R8984 */ + { 0x0000, 0x0000, 0x0000 }, /* R8985 */ + { 0x0000, 0x0000, 0x0000 }, /* R8986 */ + { 0x0000, 0x0000, 0x0000 }, /* R8987 */ + { 0x0000, 0x0000, 0x0000 }, /* R8988 */ + { 0x0000, 0x0000, 0x0000 }, /* R8989 */ + { 0x0000, 0x0000, 0x0000 }, /* R8990 */ + { 0x0000, 0x0000, 0x0000 }, /* R8991 */ + { 0x0000, 0x0000, 0x0000 }, /* R8992 */ + { 0x0000, 0x0000, 0x0000 }, /* R8993 */ + { 0x0000, 0x0000, 0x0000 }, /* R8994 */ + { 0x0000, 0x0000, 0x0000 }, /* R8995 */ + { 0x0000, 0x0000, 0x0000 }, /* R8996 */ + { 0x0000, 0x0000, 0x0000 }, /* R8997 */ + { 0x0000, 0x0000, 0x0000 }, /* R8998 */ + { 0x0000, 0x0000, 0x0000 }, /* R8999 */ + { 0x0000, 0x0000, 0x0000 }, /* R9000 */ + { 0x0000, 0x0000, 0x0000 }, /* R9001 */ + { 0x0000, 0x0000, 0x0000 }, /* R9002 */ + { 0x0000, 0x0000, 0x0000 }, /* R9003 */ + { 0x0000, 0x0000, 0x0000 }, /* R9004 */ + { 0x0000, 0x0000, 0x0000 }, /* R9005 */ + { 0x0000, 0x0000, 0x0000 }, /* R9006 */ + { 0x0000, 0x0000, 0x0000 }, /* R9007 */ + { 0x0000, 0x0000, 0x0000 }, /* R9008 */ + { 0x0000, 0x0000, 0x0000 }, /* R9009 */ + { 0x0000, 0x0000, 0x0000 }, /* R9010 */ + { 0x0000, 0x0000, 0x0000 }, /* R9011 */ + { 0x0000, 0x0000, 0x0000 }, /* R9012 */ + { 0x0000, 0x0000, 0x0000 }, /* R9013 */ + { 0x0000, 0x0000, 0x0000 }, /* R9014 */ + { 0x0000, 0x0000, 0x0000 }, /* R9015 */ + { 0x0000, 0x0000, 0x0000 }, /* R9016 */ + { 0x0000, 0x0000, 0x0000 }, /* R9017 */ + { 0x0000, 0x0000, 0x0000 }, /* R9018 */ + { 0x0000, 0x0000, 0x0000 }, /* R9019 */ + { 0x0000, 0x0000, 0x0000 }, /* R9020 */ + { 0x0000, 0x0000, 0x0000 }, /* R9021 */ + { 0x0000, 0x0000, 0x0000 }, /* R9022 */ + { 0x0000, 0x0000, 0x0000 }, /* R9023 */ + { 0x0000, 0x0000, 0x0000 }, /* R9024 */ + { 0x0000, 0x0000, 0x0000 }, /* R9025 */ + { 0x0000, 0x0000, 0x0000 }, /* R9026 */ + { 0x0000, 0x0000, 0x0000 }, /* R9027 */ + { 0x0000, 0x0000, 0x0000 }, /* R9028 */ + { 0x0000, 0x0000, 0x0000 }, /* R9029 */ + { 0x0000, 0x0000, 0x0000 }, /* R9030 */ + { 0x0000, 0x0000, 0x0000 }, /* R9031 */ + { 0x0000, 0x0000, 0x0000 }, /* R9032 */ + { 0x0000, 0x0000, 0x0000 }, /* R9033 */ + { 0x0000, 0x0000, 0x0000 }, /* R9034 */ + { 0x0000, 0x0000, 0x0000 }, /* R9035 */ + { 0x0000, 0x0000, 0x0000 }, /* R9036 */ + { 0x0000, 0x0000, 0x0000 }, /* R9037 */ + { 0x0000, 0x0000, 0x0000 }, /* R9038 */ + { 0x0000, 0x0000, 0x0000 }, /* R9039 */ + { 0x0000, 0x0000, 0x0000 }, /* R9040 */ + { 0x0000, 0x0000, 0x0000 }, /* R9041 */ + { 0x0000, 0x0000, 0x0000 }, /* R9042 */ + { 0x0000, 0x0000, 0x0000 }, /* R9043 */ + { 0x0000, 0x0000, 0x0000 }, /* R9044 */ + { 0x0000, 0x0000, 0x0000 }, /* R9045 */ + { 0x0000, 0x0000, 0x0000 }, /* R9046 */ + { 0x0000, 0x0000, 0x0000 }, /* R9047 */ + { 0x0000, 0x0000, 0x0000 }, /* R9048 */ + { 0x0000, 0x0000, 0x0000 }, /* R9049 */ + { 0x0000, 0x0000, 0x0000 }, /* R9050 */ + { 0x0000, 0x0000, 0x0000 }, /* R9051 */ + { 0x0000, 0x0000, 0x0000 }, /* R9052 */ + { 0x0000, 0x0000, 0x0000 }, /* R9053 */ + { 0x0000, 0x0000, 0x0000 }, /* R9054 */ + { 0x0000, 0x0000, 0x0000 }, /* R9055 */ + { 0x0000, 0x0000, 0x0000 }, /* R9056 */ + { 0x0000, 0x0000, 0x0000 }, /* R9057 */ + { 0x0000, 0x0000, 0x0000 }, /* R9058 */ + { 0x0000, 0x0000, 0x0000 }, /* R9059 */ + { 0x0000, 0x0000, 0x0000 }, /* R9060 */ + { 0x0000, 0x0000, 0x0000 }, /* R9061 */ + { 0x0000, 0x0000, 0x0000 }, /* R9062 */ + { 0x0000, 0x0000, 0x0000 }, /* R9063 */ + { 0x0000, 0x0000, 0x0000 }, /* R9064 */ + { 0x0000, 0x0000, 0x0000 }, /* R9065 */ + { 0x0000, 0x0000, 0x0000 }, /* R9066 */ + { 0x0000, 0x0000, 0x0000 }, /* R9067 */ + { 0x0000, 0x0000, 0x0000 }, /* R9068 */ + { 0x0000, 0x0000, 0x0000 }, /* R9069 */ + { 0x0000, 0x0000, 0x0000 }, /* R9070 */ + { 0x0000, 0x0000, 0x0000 }, /* R9071 */ + { 0x0000, 0x0000, 0x0000 }, /* R9072 */ + { 0x0000, 0x0000, 0x0000 }, /* R9073 */ + { 0x0000, 0x0000, 0x0000 }, /* R9074 */ + { 0x0000, 0x0000, 0x0000 }, /* R9075 */ + { 0x0000, 0x0000, 0x0000 }, /* R9076 */ + { 0x0000, 0x0000, 0x0000 }, /* R9077 */ + { 0x0000, 0x0000, 0x0000 }, /* R9078 */ + { 0x0000, 0x0000, 0x0000 }, /* R9079 */ + { 0x0000, 0x0000, 0x0000 }, /* R9080 */ + { 0x0000, 0x0000, 0x0000 }, /* R9081 */ + { 0x0000, 0x0000, 0x0000 }, /* R9082 */ + { 0x0000, 0x0000, 0x0000 }, /* R9083 */ + { 0x0000, 0x0000, 0x0000 }, /* R9084 */ + { 0x0000, 0x0000, 0x0000 }, /* R9085 */ + { 0x0000, 0x0000, 0x0000 }, /* R9086 */ + { 0x0000, 0x0000, 0x0000 }, /* R9087 */ + { 0x0000, 0x0000, 0x0000 }, /* R9088 */ + { 0x0000, 0x0000, 0x0000 }, /* R9089 */ + { 0x0000, 0x0000, 0x0000 }, /* R9090 */ + { 0x0000, 0x0000, 0x0000 }, /* R9091 */ + { 0x0000, 0x0000, 0x0000 }, /* R9092 */ + { 0x0000, 0x0000, 0x0000 }, /* R9093 */ + { 0x0000, 0x0000, 0x0000 }, /* R9094 */ + { 0x0000, 0x0000, 0x0000 }, /* R9095 */ + { 0x0000, 0x0000, 0x0000 }, /* R9096 */ + { 0x0000, 0x0000, 0x0000 }, /* R9097 */ + { 0x0000, 0x0000, 0x0000 }, /* R9098 */ + { 0x0000, 0x0000, 0x0000 }, /* R9099 */ + { 0x0000, 0x0000, 0x0000 }, /* R9100 */ + { 0x0000, 0x0000, 0x0000 }, /* R9101 */ + { 0x0000, 0x0000, 0x0000 }, /* R9102 */ + { 0x0000, 0x0000, 0x0000 }, /* R9103 */ + { 0x0000, 0x0000, 0x0000 }, /* R9104 */ + { 0x0000, 0x0000, 0x0000 }, /* R9105 */ + { 0x0000, 0x0000, 0x0000 }, /* R9106 */ + { 0x0000, 0x0000, 0x0000 }, /* R9107 */ + { 0x0000, 0x0000, 0x0000 }, /* R9108 */ + { 0x0000, 0x0000, 0x0000 }, /* R9109 */ + { 0x0000, 0x0000, 0x0000 }, /* R9110 */ + { 0x0000, 0x0000, 0x0000 }, /* R9111 */ + { 0x0000, 0x0000, 0x0000 }, /* R9112 */ + { 0x0000, 0x0000, 0x0000 }, /* R9113 */ + { 0x0000, 0x0000, 0x0000 }, /* R9114 */ + { 0x0000, 0x0000, 0x0000 }, /* R9115 */ + { 0x0000, 0x0000, 0x0000 }, /* R9116 */ + { 0x0000, 0x0000, 0x0000 }, /* R9117 */ + { 0x0000, 0x0000, 0x0000 }, /* R9118 */ + { 0x0000, 0x0000, 0x0000 }, /* R9119 */ + { 0x0000, 0x0000, 0x0000 }, /* R9120 */ + { 0x0000, 0x0000, 0x0000 }, /* R9121 */ + { 0x0000, 0x0000, 0x0000 }, /* R9122 */ + { 0x0000, 0x0000, 0x0000 }, /* R9123 */ + { 0x0000, 0x0000, 0x0000 }, /* R9124 */ + { 0x0000, 0x0000, 0x0000 }, /* R9125 */ + { 0x0000, 0x0000, 0x0000 }, /* R9126 */ + { 0x0000, 0x0000, 0x0000 }, /* R9127 */ + { 0x0000, 0x0000, 0x0000 }, /* R9128 */ + { 0x0000, 0x0000, 0x0000 }, /* R9129 */ + { 0x0000, 0x0000, 0x0000 }, /* R9130 */ + { 0x0000, 0x0000, 0x0000 }, /* R9131 */ + { 0x0000, 0x0000, 0x0000 }, /* R9132 */ + { 0x0000, 0x0000, 0x0000 }, /* R9133 */ + { 0x0000, 0x0000, 0x0000 }, /* R9134 */ + { 0x0000, 0x0000, 0x0000 }, /* R9135 */ + { 0x0000, 0x0000, 0x0000 }, /* R9136 */ + { 0x0000, 0x0000, 0x0000 }, /* R9137 */ + { 0x0000, 0x0000, 0x0000 }, /* R9138 */ + { 0x0000, 0x0000, 0x0000 }, /* R9139 */ + { 0x0000, 0x0000, 0x0000 }, /* R9140 */ + { 0x0000, 0x0000, 0x0000 }, /* R9141 */ + { 0x0000, 0x0000, 0x0000 }, /* R9142 */ + { 0x0000, 0x0000, 0x0000 }, /* R9143 */ + { 0x0000, 0x0000, 0x0000 }, /* R9144 */ + { 0x0000, 0x0000, 0x0000 }, /* R9145 */ + { 0x0000, 0x0000, 0x0000 }, /* R9146 */ + { 0x0000, 0x0000, 0x0000 }, /* R9147 */ + { 0x0000, 0x0000, 0x0000 }, /* R9148 */ + { 0x0000, 0x0000, 0x0000 }, /* R9149 */ + { 0x0000, 0x0000, 0x0000 }, /* R9150 */ + { 0x0000, 0x0000, 0x0000 }, /* R9151 */ + { 0x0000, 0x0000, 0x0000 }, /* R9152 */ + { 0x0000, 0x0000, 0x0000 }, /* R9153 */ + { 0x0000, 0x0000, 0x0000 }, /* R9154 */ + { 0x0000, 0x0000, 0x0000 }, /* R9155 */ + { 0x0000, 0x0000, 0x0000 }, /* R9156 */ + { 0x0000, 0x0000, 0x0000 }, /* R9157 */ + { 0x0000, 0x0000, 0x0000 }, /* R9158 */ + { 0x0000, 0x0000, 0x0000 }, /* R9159 */ + { 0x0000, 0x0000, 0x0000 }, /* R9160 */ + { 0x0000, 0x0000, 0x0000 }, /* R9161 */ + { 0x0000, 0x0000, 0x0000 }, /* R9162 */ + { 0x0000, 0x0000, 0x0000 }, /* R9163 */ + { 0x0000, 0x0000, 0x0000 }, /* R9164 */ + { 0x0000, 0x0000, 0x0000 }, /* R9165 */ + { 0x0000, 0x0000, 0x0000 }, /* R9166 */ + { 0x0000, 0x0000, 0x0000 }, /* R9167 */ + { 0x0000, 0x0000, 0x0000 }, /* R9168 */ + { 0x0000, 0x0000, 0x0000 }, /* R9169 */ + { 0x0000, 0x0000, 0x0000 }, /* R9170 */ + { 0x0000, 0x0000, 0x0000 }, /* R9171 */ + { 0x0000, 0x0000, 0x0000 }, /* R9172 */ + { 0x0000, 0x0000, 0x0000 }, /* R9173 */ + { 0x0000, 0x0000, 0x0000 }, /* R9174 */ + { 0x0000, 0x0000, 0x0000 }, /* R9175 */ + { 0x0000, 0x0000, 0x0000 }, /* R9176 */ + { 0x0000, 0x0000, 0x0000 }, /* R9177 */ + { 0x0000, 0x0000, 0x0000 }, /* R9178 */ + { 0x0000, 0x0000, 0x0000 }, /* R9179 */ + { 0x0000, 0x0000, 0x0000 }, /* R9180 */ + { 0x0000, 0x0000, 0x0000 }, /* R9181 */ + { 0x0000, 0x0000, 0x0000 }, /* R9182 */ + { 0x0000, 0x0000, 0x0000 }, /* R9183 */ + { 0x0000, 0x0000, 0x0000 }, /* R9184 */ + { 0x0000, 0x0000, 0x0000 }, /* R9185 */ + { 0x0000, 0x0000, 0x0000 }, /* R9186 */ + { 0x0000, 0x0000, 0x0000 }, /* R9187 */ + { 0x0000, 0x0000, 0x0000 }, /* R9188 */ + { 0x0000, 0x0000, 0x0000 }, /* R9189 */ + { 0x0000, 0x0000, 0x0000 }, /* R9190 */ + { 0x0000, 0x0000, 0x0000 }, /* R9191 */ + { 0x0000, 0x0000, 0x0000 }, /* R9192 */ + { 0x0000, 0x0000, 0x0000 }, /* R9193 */ + { 0x0000, 0x0000, 0x0000 }, /* R9194 */ + { 0x0000, 0x0000, 0x0000 }, /* R9195 */ + { 0x0000, 0x0000, 0x0000 }, /* R9196 */ + { 0x0000, 0x0000, 0x0000 }, /* R9197 */ + { 0x0000, 0x0000, 0x0000 }, /* R9198 */ + { 0x0000, 0x0000, 0x0000 }, /* R9199 */ + { 0x0000, 0x0000, 0x0000 }, /* R9200 */ + { 0x0000, 0x0000, 0x0000 }, /* R9201 */ + { 0x0000, 0x0000, 0x0000 }, /* R9202 */ + { 0x0000, 0x0000, 0x0000 }, /* R9203 */ + { 0x0000, 0x0000, 0x0000 }, /* R9204 */ + { 0x0000, 0x0000, 0x0000 }, /* R9205 */ + { 0x0000, 0x0000, 0x0000 }, /* R9206 */ + { 0x0000, 0x0000, 0x0000 }, /* R9207 */ + { 0x0000, 0x0000, 0x0000 }, /* R9208 */ + { 0x0000, 0x0000, 0x0000 }, /* R9209 */ + { 0x0000, 0x0000, 0x0000 }, /* R9210 */ + { 0x0000, 0x0000, 0x0000 }, /* R9211 */ + { 0x0000, 0x0000, 0x0000 }, /* R9212 */ + { 0x0000, 0x0000, 0x0000 }, /* R9213 */ + { 0x0000, 0x0000, 0x0000 }, /* R9214 */ + { 0x0000, 0x0000, 0x0000 }, /* R9215 */ + { 0x003F, 0x003F, 0x0000 }, /* R9216 - DSP2 Address RAM 2 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R9217 - DSP2 Address RAM 1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R9218 - DSP2 Address RAM 0 */ + { 0x0000, 0x0000, 0x0000 }, /* R9219 */ + { 0x0000, 0x0000, 0x0000 }, /* R9220 */ + { 0x0000, 0x0000, 0x0000 }, /* R9221 */ + { 0x0000, 0x0000, 0x0000 }, /* R9222 */ + { 0x0000, 0x0000, 0x0000 }, /* R9223 */ + { 0x0000, 0x0000, 0x0000 }, /* R9224 */ + { 0x0000, 0x0000, 0x0000 }, /* R9225 */ + { 0x0000, 0x0000, 0x0000 }, /* R9226 */ + { 0x0000, 0x0000, 0x0000 }, /* R9227 */ + { 0x0000, 0x0000, 0x0000 }, /* R9228 */ + { 0x0000, 0x0000, 0x0000 }, /* R9229 */ + { 0x0000, 0x0000, 0x0000 }, /* R9230 */ + { 0x0000, 0x0000, 0x0000 }, /* R9231 */ + { 0x0000, 0x0000, 0x0000 }, /* R9232 */ + { 0x0000, 0x0000, 0x0000 }, /* R9233 */ + { 0x0000, 0x0000, 0x0000 }, /* R9234 */ + { 0x0000, 0x0000, 0x0000 }, /* R9235 */ + { 0x0000, 0x0000, 0x0000 }, /* R9236 */ + { 0x0000, 0x0000, 0x0000 }, /* R9237 */ + { 0x0000, 0x0000, 0x0000 }, /* R9238 */ + { 0x0000, 0x0000, 0x0000 }, /* R9239 */ + { 0x0000, 0x0000, 0x0000 }, /* R9240 */ + { 0x0000, 0x0000, 0x0000 }, /* R9241 */ + { 0x0000, 0x0000, 0x0000 }, /* R9242 */ + { 0x0000, 0x0000, 0x0000 }, /* R9243 */ + { 0x0000, 0x0000, 0x0000 }, /* R9244 */ + { 0x0000, 0x0000, 0x0000 }, /* R9245 */ + { 0x0000, 0x0000, 0x0000 }, /* R9246 */ + { 0x0000, 0x0000, 0x0000 }, /* R9247 */ + { 0x0000, 0x0000, 0x0000 }, /* R9248 */ + { 0x0000, 0x0000, 0x0000 }, /* R9249 */ + { 0x0000, 0x0000, 0x0000 }, /* R9250 */ + { 0x0000, 0x0000, 0x0000 }, /* R9251 */ + { 0x0000, 0x0000, 0x0000 }, /* R9252 */ + { 0x0000, 0x0000, 0x0000 }, /* R9253 */ + { 0x0000, 0x0000, 0x0000 }, /* R9254 */ + { 0x0000, 0x0000, 0x0000 }, /* R9255 */ + { 0x0000, 0x0000, 0x0000 }, /* R9256 */ + { 0x0000, 0x0000, 0x0000 }, /* R9257 */ + { 0x0000, 0x0000, 0x0000 }, /* R9258 */ + { 0x0000, 0x0000, 0x0000 }, /* R9259 */ + { 0x0000, 0x0000, 0x0000 }, /* R9260 */ + { 0x0000, 0x0000, 0x0000 }, /* R9261 */ + { 0x0000, 0x0000, 0x0000 }, /* R9262 */ + { 0x0000, 0x0000, 0x0000 }, /* R9263 */ + { 0x0000, 0x0000, 0x0000 }, /* R9264 */ + { 0x0000, 0x0000, 0x0000 }, /* R9265 */ + { 0x0000, 0x0000, 0x0000 }, /* R9266 */ + { 0x0000, 0x0000, 0x0000 }, /* R9267 */ + { 0x0000, 0x0000, 0x0000 }, /* R9268 */ + { 0x0000, 0x0000, 0x0000 }, /* R9269 */ + { 0x0000, 0x0000, 0x0000 }, /* R9270 */ + { 0x0000, 0x0000, 0x0000 }, /* R9271 */ + { 0x0000, 0x0000, 0x0000 }, /* R9272 */ + { 0x0000, 0x0000, 0x0000 }, /* R9273 */ + { 0x0000, 0x0000, 0x0000 }, /* R9274 */ + { 0x0000, 0x0000, 0x0000 }, /* R9275 */ + { 0x0000, 0x0000, 0x0000 }, /* R9276 */ + { 0x0000, 0x0000, 0x0000 }, /* R9277 */ + { 0x0000, 0x0000, 0x0000 }, /* R9278 */ + { 0x0000, 0x0000, 0x0000 }, /* R9279 */ + { 0x0000, 0x0000, 0x0000 }, /* R9280 */ + { 0x0000, 0x0000, 0x0000 }, /* R9281 */ + { 0x0000, 0x0000, 0x0000 }, /* R9282 */ + { 0x0000, 0x0000, 0x0000 }, /* R9283 */ + { 0x0000, 0x0000, 0x0000 }, /* R9284 */ + { 0x0000, 0x0000, 0x0000 }, /* R9285 */ + { 0x0000, 0x0000, 0x0000 }, /* R9286 */ + { 0x0000, 0x0000, 0x0000 }, /* R9287 */ + { 0x0000, 0x0000, 0x0000 }, /* R9288 */ + { 0x0000, 0x0000, 0x0000 }, /* R9289 */ + { 0x0000, 0x0000, 0x0000 }, /* R9290 */ + { 0x0000, 0x0000, 0x0000 }, /* R9291 */ + { 0x0000, 0x0000, 0x0000 }, /* R9292 */ + { 0x0000, 0x0000, 0x0000 }, /* R9293 */ + { 0x0000, 0x0000, 0x0000 }, /* R9294 */ + { 0x0000, 0x0000, 0x0000 }, /* R9295 */ + { 0x0000, 0x0000, 0x0000 }, /* R9296 */ + { 0x0000, 0x0000, 0x0000 }, /* R9297 */ + { 0x0000, 0x0000, 0x0000 }, /* R9298 */ + { 0x0000, 0x0000, 0x0000 }, /* R9299 */ + { 0x0000, 0x0000, 0x0000 }, /* R9300 */ + { 0x0000, 0x0000, 0x0000 }, /* R9301 */ + { 0x0000, 0x0000, 0x0000 }, /* R9302 */ + { 0x0000, 0x0000, 0x0000 }, /* R9303 */ + { 0x0000, 0x0000, 0x0000 }, /* R9304 */ + { 0x0000, 0x0000, 0x0000 }, /* R9305 */ + { 0x0000, 0x0000, 0x0000 }, /* R9306 */ + { 0x0000, 0x0000, 0x0000 }, /* R9307 */ + { 0x0000, 0x0000, 0x0000 }, /* R9308 */ + { 0x0000, 0x0000, 0x0000 }, /* R9309 */ + { 0x0000, 0x0000, 0x0000 }, /* R9310 */ + { 0x0000, 0x0000, 0x0000 }, /* R9311 */ + { 0x0000, 0x0000, 0x0000 }, /* R9312 */ + { 0x0000, 0x0000, 0x0000 }, /* R9313 */ + { 0x0000, 0x0000, 0x0000 }, /* R9314 */ + { 0x0000, 0x0000, 0x0000 }, /* R9315 */ + { 0x0000, 0x0000, 0x0000 }, /* R9316 */ + { 0x0000, 0x0000, 0x0000 }, /* R9317 */ + { 0x0000, 0x0000, 0x0000 }, /* R9318 */ + { 0x0000, 0x0000, 0x0000 }, /* R9319 */ + { 0x0000, 0x0000, 0x0000 }, /* R9320 */ + { 0x0000, 0x0000, 0x0000 }, /* R9321 */ + { 0x0000, 0x0000, 0x0000 }, /* R9322 */ + { 0x0000, 0x0000, 0x0000 }, /* R9323 */ + { 0x0000, 0x0000, 0x0000 }, /* R9324 */ + { 0x0000, 0x0000, 0x0000 }, /* R9325 */ + { 0x0000, 0x0000, 0x0000 }, /* R9326 */ + { 0x0000, 0x0000, 0x0000 }, /* R9327 */ + { 0x0000, 0x0000, 0x0000 }, /* R9328 */ + { 0x0000, 0x0000, 0x0000 }, /* R9329 */ + { 0x0000, 0x0000, 0x0000 }, /* R9330 */ + { 0x0000, 0x0000, 0x0000 }, /* R9331 */ + { 0x0000, 0x0000, 0x0000 }, /* R9332 */ + { 0x0000, 0x0000, 0x0000 }, /* R9333 */ + { 0x0000, 0x0000, 0x0000 }, /* R9334 */ + { 0x0000, 0x0000, 0x0000 }, /* R9335 */ + { 0x0000, 0x0000, 0x0000 }, /* R9336 */ + { 0x0000, 0x0000, 0x0000 }, /* R9337 */ + { 0x0000, 0x0000, 0x0000 }, /* R9338 */ + { 0x0000, 0x0000, 0x0000 }, /* R9339 */ + { 0x0000, 0x0000, 0x0000 }, /* R9340 */ + { 0x0000, 0x0000, 0x0000 }, /* R9341 */ + { 0x0000, 0x0000, 0x0000 }, /* R9342 */ + { 0x0000, 0x0000, 0x0000 }, /* R9343 */ + { 0x0000, 0x0000, 0x0000 }, /* R9344 */ + { 0x0000, 0x0000, 0x0000 }, /* R9345 */ + { 0x0000, 0x0000, 0x0000 }, /* R9346 */ + { 0x0000, 0x0000, 0x0000 }, /* R9347 */ + { 0x0000, 0x0000, 0x0000 }, /* R9348 */ + { 0x0000, 0x0000, 0x0000 }, /* R9349 */ + { 0x0000, 0x0000, 0x0000 }, /* R9350 */ + { 0x0000, 0x0000, 0x0000 }, /* R9351 */ + { 0x0000, 0x0000, 0x0000 }, /* R9352 */ + { 0x0000, 0x0000, 0x0000 }, /* R9353 */ + { 0x0000, 0x0000, 0x0000 }, /* R9354 */ + { 0x0000, 0x0000, 0x0000 }, /* R9355 */ + { 0x0000, 0x0000, 0x0000 }, /* R9356 */ + { 0x0000, 0x0000, 0x0000 }, /* R9357 */ + { 0x0000, 0x0000, 0x0000 }, /* R9358 */ + { 0x0000, 0x0000, 0x0000 }, /* R9359 */ + { 0x0000, 0x0000, 0x0000 }, /* R9360 */ + { 0x0000, 0x0000, 0x0000 }, /* R9361 */ + { 0x0000, 0x0000, 0x0000 }, /* R9362 */ + { 0x0000, 0x0000, 0x0000 }, /* R9363 */ + { 0x0000, 0x0000, 0x0000 }, /* R9364 */ + { 0x0000, 0x0000, 0x0000 }, /* R9365 */ + { 0x0000, 0x0000, 0x0000 }, /* R9366 */ + { 0x0000, 0x0000, 0x0000 }, /* R9367 */ + { 0x0000, 0x0000, 0x0000 }, /* R9368 */ + { 0x0000, 0x0000, 0x0000 }, /* R9369 */ + { 0x0000, 0x0000, 0x0000 }, /* R9370 */ + { 0x0000, 0x0000, 0x0000 }, /* R9371 */ + { 0x0000, 0x0000, 0x0000 }, /* R9372 */ + { 0x0000, 0x0000, 0x0000 }, /* R9373 */ + { 0x0000, 0x0000, 0x0000 }, /* R9374 */ + { 0x0000, 0x0000, 0x0000 }, /* R9375 */ + { 0x0000, 0x0000, 0x0000 }, /* R9376 */ + { 0x0000, 0x0000, 0x0000 }, /* R9377 */ + { 0x0000, 0x0000, 0x0000 }, /* R9378 */ + { 0x0000, 0x0000, 0x0000 }, /* R9379 */ + { 0x0000, 0x0000, 0x0000 }, /* R9380 */ + { 0x0000, 0x0000, 0x0000 }, /* R9381 */ + { 0x0000, 0x0000, 0x0000 }, /* R9382 */ + { 0x0000, 0x0000, 0x0000 }, /* R9383 */ + { 0x0000, 0x0000, 0x0000 }, /* R9384 */ + { 0x0000, 0x0000, 0x0000 }, /* R9385 */ + { 0x0000, 0x0000, 0x0000 }, /* R9386 */ + { 0x0000, 0x0000, 0x0000 }, /* R9387 */ + { 0x0000, 0x0000, 0x0000 }, /* R9388 */ + { 0x0000, 0x0000, 0x0000 }, /* R9389 */ + { 0x0000, 0x0000, 0x0000 }, /* R9390 */ + { 0x0000, 0x0000, 0x0000 }, /* R9391 */ + { 0x0000, 0x0000, 0x0000 }, /* R9392 */ + { 0x0000, 0x0000, 0x0000 }, /* R9393 */ + { 0x0000, 0x0000, 0x0000 }, /* R9394 */ + { 0x0000, 0x0000, 0x0000 }, /* R9395 */ + { 0x0000, 0x0000, 0x0000 }, /* R9396 */ + { 0x0000, 0x0000, 0x0000 }, /* R9397 */ + { 0x0000, 0x0000, 0x0000 }, /* R9398 */ + { 0x0000, 0x0000, 0x0000 }, /* R9399 */ + { 0x0000, 0x0000, 0x0000 }, /* R9400 */ + { 0x0000, 0x0000, 0x0000 }, /* R9401 */ + { 0x0000, 0x0000, 0x0000 }, /* R9402 */ + { 0x0000, 0x0000, 0x0000 }, /* R9403 */ + { 0x0000, 0x0000, 0x0000 }, /* R9404 */ + { 0x0000, 0x0000, 0x0000 }, /* R9405 */ + { 0x0000, 0x0000, 0x0000 }, /* R9406 */ + { 0x0000, 0x0000, 0x0000 }, /* R9407 */ + { 0x0000, 0x0000, 0x0000 }, /* R9408 */ + { 0x0000, 0x0000, 0x0000 }, /* R9409 */ + { 0x0000, 0x0000, 0x0000 }, /* R9410 */ + { 0x0000, 0x0000, 0x0000 }, /* R9411 */ + { 0x0000, 0x0000, 0x0000 }, /* R9412 */ + { 0x0000, 0x0000, 0x0000 }, /* R9413 */ + { 0x0000, 0x0000, 0x0000 }, /* R9414 */ + { 0x0000, 0x0000, 0x0000 }, /* R9415 */ + { 0x0000, 0x0000, 0x0000 }, /* R9416 */ + { 0x0000, 0x0000, 0x0000 }, /* R9417 */ + { 0x0000, 0x0000, 0x0000 }, /* R9418 */ + { 0x0000, 0x0000, 0x0000 }, /* R9419 */ + { 0x0000, 0x0000, 0x0000 }, /* R9420 */ + { 0x0000, 0x0000, 0x0000 }, /* R9421 */ + { 0x0000, 0x0000, 0x0000 }, /* R9422 */ + { 0x0000, 0x0000, 0x0000 }, /* R9423 */ + { 0x0000, 0x0000, 0x0000 }, /* R9424 */ + { 0x0000, 0x0000, 0x0000 }, /* R9425 */ + { 0x0000, 0x0000, 0x0000 }, /* R9426 */ + { 0x0000, 0x0000, 0x0000 }, /* R9427 */ + { 0x0000, 0x0000, 0x0000 }, /* R9428 */ + { 0x0000, 0x0000, 0x0000 }, /* R9429 */ + { 0x0000, 0x0000, 0x0000 }, /* R9430 */ + { 0x0000, 0x0000, 0x0000 }, /* R9431 */ + { 0x0000, 0x0000, 0x0000 }, /* R9432 */ + { 0x0000, 0x0000, 0x0000 }, /* R9433 */ + { 0x0000, 0x0000, 0x0000 }, /* R9434 */ + { 0x0000, 0x0000, 0x0000 }, /* R9435 */ + { 0x0000, 0x0000, 0x0000 }, /* R9436 */ + { 0x0000, 0x0000, 0x0000 }, /* R9437 */ + { 0x0000, 0x0000, 0x0000 }, /* R9438 */ + { 0x0000, 0x0000, 0x0000 }, /* R9439 */ + { 0x0000, 0x0000, 0x0000 }, /* R9440 */ + { 0x0000, 0x0000, 0x0000 }, /* R9441 */ + { 0x0000, 0x0000, 0x0000 }, /* R9442 */ + { 0x0000, 0x0000, 0x0000 }, /* R9443 */ + { 0x0000, 0x0000, 0x0000 }, /* R9444 */ + { 0x0000, 0x0000, 0x0000 }, /* R9445 */ + { 0x0000, 0x0000, 0x0000 }, /* R9446 */ + { 0x0000, 0x0000, 0x0000 }, /* R9447 */ + { 0x0000, 0x0000, 0x0000 }, /* R9448 */ + { 0x0000, 0x0000, 0x0000 }, /* R9449 */ + { 0x0000, 0x0000, 0x0000 }, /* R9450 */ + { 0x0000, 0x0000, 0x0000 }, /* R9451 */ + { 0x0000, 0x0000, 0x0000 }, /* R9452 */ + { 0x0000, 0x0000, 0x0000 }, /* R9453 */ + { 0x0000, 0x0000, 0x0000 }, /* R9454 */ + { 0x0000, 0x0000, 0x0000 }, /* R9455 */ + { 0x0000, 0x0000, 0x0000 }, /* R9456 */ + { 0x0000, 0x0000, 0x0000 }, /* R9457 */ + { 0x0000, 0x0000, 0x0000 }, /* R9458 */ + { 0x0000, 0x0000, 0x0000 }, /* R9459 */ + { 0x0000, 0x0000, 0x0000 }, /* R9460 */ + { 0x0000, 0x0000, 0x0000 }, /* R9461 */ + { 0x0000, 0x0000, 0x0000 }, /* R9462 */ + { 0x0000, 0x0000, 0x0000 }, /* R9463 */ + { 0x0000, 0x0000, 0x0000 }, /* R9464 */ + { 0x0000, 0x0000, 0x0000 }, /* R9465 */ + { 0x0000, 0x0000, 0x0000 }, /* R9466 */ + { 0x0000, 0x0000, 0x0000 }, /* R9467 */ + { 0x0000, 0x0000, 0x0000 }, /* R9468 */ + { 0x0000, 0x0000, 0x0000 }, /* R9469 */ + { 0x0000, 0x0000, 0x0000 }, /* R9470 */ + { 0x0000, 0x0000, 0x0000 }, /* R9471 */ + { 0x0000, 0x0000, 0x0000 }, /* R9472 */ + { 0x0000, 0x0000, 0x0000 }, /* R9473 */ + { 0x0000, 0x0000, 0x0000 }, /* R9474 */ + { 0x0000, 0x0000, 0x0000 }, /* R9475 */ + { 0x0000, 0x0000, 0x0000 }, /* R9476 */ + { 0x0000, 0x0000, 0x0000 }, /* R9477 */ + { 0x0000, 0x0000, 0x0000 }, /* R9478 */ + { 0x0000, 0x0000, 0x0000 }, /* R9479 */ + { 0x0000, 0x0000, 0x0000 }, /* R9480 */ + { 0x0000, 0x0000, 0x0000 }, /* R9481 */ + { 0x0000, 0x0000, 0x0000 }, /* R9482 */ + { 0x0000, 0x0000, 0x0000 }, /* R9483 */ + { 0x0000, 0x0000, 0x0000 }, /* R9484 */ + { 0x0000, 0x0000, 0x0000 }, /* R9485 */ + { 0x0000, 0x0000, 0x0000 }, /* R9486 */ + { 0x0000, 0x0000, 0x0000 }, /* R9487 */ + { 0x0000, 0x0000, 0x0000 }, /* R9488 */ + { 0x0000, 0x0000, 0x0000 }, /* R9489 */ + { 0x0000, 0x0000, 0x0000 }, /* R9490 */ + { 0x0000, 0x0000, 0x0000 }, /* R9491 */ + { 0x0000, 0x0000, 0x0000 }, /* R9492 */ + { 0x0000, 0x0000, 0x0000 }, /* R9493 */ + { 0x0000, 0x0000, 0x0000 }, /* R9494 */ + { 0x0000, 0x0000, 0x0000 }, /* R9495 */ + { 0x0000, 0x0000, 0x0000 }, /* R9496 */ + { 0x0000, 0x0000, 0x0000 }, /* R9497 */ + { 0x0000, 0x0000, 0x0000 }, /* R9498 */ + { 0x0000, 0x0000, 0x0000 }, /* R9499 */ + { 0x0000, 0x0000, 0x0000 }, /* R9500 */ + { 0x0000, 0x0000, 0x0000 }, /* R9501 */ + { 0x0000, 0x0000, 0x0000 }, /* R9502 */ + { 0x0000, 0x0000, 0x0000 }, /* R9503 */ + { 0x0000, 0x0000, 0x0000 }, /* R9504 */ + { 0x0000, 0x0000, 0x0000 }, /* R9505 */ + { 0x0000, 0x0000, 0x0000 }, /* R9506 */ + { 0x0000, 0x0000, 0x0000 }, /* R9507 */ + { 0x0000, 0x0000, 0x0000 }, /* R9508 */ + { 0x0000, 0x0000, 0x0000 }, /* R9509 */ + { 0x0000, 0x0000, 0x0000 }, /* R9510 */ + { 0x0000, 0x0000, 0x0000 }, /* R9511 */ + { 0x0000, 0x0000, 0x0000 }, /* R9512 */ + { 0x0000, 0x0000, 0x0000 }, /* R9513 */ + { 0x0000, 0x0000, 0x0000 }, /* R9514 */ + { 0x0000, 0x0000, 0x0000 }, /* R9515 */ + { 0x0000, 0x0000, 0x0000 }, /* R9516 */ + { 0x0000, 0x0000, 0x0000 }, /* R9517 */ + { 0x0000, 0x0000, 0x0000 }, /* R9518 */ + { 0x0000, 0x0000, 0x0000 }, /* R9519 */ + { 0x0000, 0x0000, 0x0000 }, /* R9520 */ + { 0x0000, 0x0000, 0x0000 }, /* R9521 */ + { 0x0000, 0x0000, 0x0000 }, /* R9522 */ + { 0x0000, 0x0000, 0x0000 }, /* R9523 */ + { 0x0000, 0x0000, 0x0000 }, /* R9524 */ + { 0x0000, 0x0000, 0x0000 }, /* R9525 */ + { 0x0000, 0x0000, 0x0000 }, /* R9526 */ + { 0x0000, 0x0000, 0x0000 }, /* R9527 */ + { 0x0000, 0x0000, 0x0000 }, /* R9528 */ + { 0x0000, 0x0000, 0x0000 }, /* R9529 */ + { 0x0000, 0x0000, 0x0000 }, /* R9530 */ + { 0x0000, 0x0000, 0x0000 }, /* R9531 */ + { 0x0000, 0x0000, 0x0000 }, /* R9532 */ + { 0x0000, 0x0000, 0x0000 }, /* R9533 */ + { 0x0000, 0x0000, 0x0000 }, /* R9534 */ + { 0x0000, 0x0000, 0x0000 }, /* R9535 */ + { 0x0000, 0x0000, 0x0000 }, /* R9536 */ + { 0x0000, 0x0000, 0x0000 }, /* R9537 */ + { 0x0000, 0x0000, 0x0000 }, /* R9538 */ + { 0x0000, 0x0000, 0x0000 }, /* R9539 */ + { 0x0000, 0x0000, 0x0000 }, /* R9540 */ + { 0x0000, 0x0000, 0x0000 }, /* R9541 */ + { 0x0000, 0x0000, 0x0000 }, /* R9542 */ + { 0x0000, 0x0000, 0x0000 }, /* R9543 */ + { 0x0000, 0x0000, 0x0000 }, /* R9544 */ + { 0x0000, 0x0000, 0x0000 }, /* R9545 */ + { 0x0000, 0x0000, 0x0000 }, /* R9546 */ + { 0x0000, 0x0000, 0x0000 }, /* R9547 */ + { 0x0000, 0x0000, 0x0000 }, /* R9548 */ + { 0x0000, 0x0000, 0x0000 }, /* R9549 */ + { 0x0000, 0x0000, 0x0000 }, /* R9550 */ + { 0x0000, 0x0000, 0x0000 }, /* R9551 */ + { 0x0000, 0x0000, 0x0000 }, /* R9552 */ + { 0x0000, 0x0000, 0x0000 }, /* R9553 */ + { 0x0000, 0x0000, 0x0000 }, /* R9554 */ + { 0x0000, 0x0000, 0x0000 }, /* R9555 */ + { 0x0000, 0x0000, 0x0000 }, /* R9556 */ + { 0x0000, 0x0000, 0x0000 }, /* R9557 */ + { 0x0000, 0x0000, 0x0000 }, /* R9558 */ + { 0x0000, 0x0000, 0x0000 }, /* R9559 */ + { 0x0000, 0x0000, 0x0000 }, /* R9560 */ + { 0x0000, 0x0000, 0x0000 }, /* R9561 */ + { 0x0000, 0x0000, 0x0000 }, /* R9562 */ + { 0x0000, 0x0000, 0x0000 }, /* R9563 */ + { 0x0000, 0x0000, 0x0000 }, /* R9564 */ + { 0x0000, 0x0000, 0x0000 }, /* R9565 */ + { 0x0000, 0x0000, 0x0000 }, /* R9566 */ + { 0x0000, 0x0000, 0x0000 }, /* R9567 */ + { 0x0000, 0x0000, 0x0000 }, /* R9568 */ + { 0x0000, 0x0000, 0x0000 }, /* R9569 */ + { 0x0000, 0x0000, 0x0000 }, /* R9570 */ + { 0x0000, 0x0000, 0x0000 }, /* R9571 */ + { 0x0000, 0x0000, 0x0000 }, /* R9572 */ + { 0x0000, 0x0000, 0x0000 }, /* R9573 */ + { 0x0000, 0x0000, 0x0000 }, /* R9574 */ + { 0x0000, 0x0000, 0x0000 }, /* R9575 */ + { 0x0000, 0x0000, 0x0000 }, /* R9576 */ + { 0x0000, 0x0000, 0x0000 }, /* R9577 */ + { 0x0000, 0x0000, 0x0000 }, /* R9578 */ + { 0x0000, 0x0000, 0x0000 }, /* R9579 */ + { 0x0000, 0x0000, 0x0000 }, /* R9580 */ + { 0x0000, 0x0000, 0x0000 }, /* R9581 */ + { 0x0000, 0x0000, 0x0000 }, /* R9582 */ + { 0x0000, 0x0000, 0x0000 }, /* R9583 */ + { 0x0000, 0x0000, 0x0000 }, /* R9584 */ + { 0x0000, 0x0000, 0x0000 }, /* R9585 */ + { 0x0000, 0x0000, 0x0000 }, /* R9586 */ + { 0x0000, 0x0000, 0x0000 }, /* R9587 */ + { 0x0000, 0x0000, 0x0000 }, /* R9588 */ + { 0x0000, 0x0000, 0x0000 }, /* R9589 */ + { 0x0000, 0x0000, 0x0000 }, /* R9590 */ + { 0x0000, 0x0000, 0x0000 }, /* R9591 */ + { 0x0000, 0x0000, 0x0000 }, /* R9592 */ + { 0x0000, 0x0000, 0x0000 }, /* R9593 */ + { 0x0000, 0x0000, 0x0000 }, /* R9594 */ + { 0x0000, 0x0000, 0x0000 }, /* R9595 */ + { 0x0000, 0x0000, 0x0000 }, /* R9596 */ + { 0x0000, 0x0000, 0x0000 }, /* R9597 */ + { 0x0000, 0x0000, 0x0000 }, /* R9598 */ + { 0x0000, 0x0000, 0x0000 }, /* R9599 */ + { 0x0000, 0x0000, 0x0000 }, /* R9600 */ + { 0x0000, 0x0000, 0x0000 }, /* R9601 */ + { 0x0000, 0x0000, 0x0000 }, /* R9602 */ + { 0x0000, 0x0000, 0x0000 }, /* R9603 */ + { 0x0000, 0x0000, 0x0000 }, /* R9604 */ + { 0x0000, 0x0000, 0x0000 }, /* R9605 */ + { 0x0000, 0x0000, 0x0000 }, /* R9606 */ + { 0x0000, 0x0000, 0x0000 }, /* R9607 */ + { 0x0000, 0x0000, 0x0000 }, /* R9608 */ + { 0x0000, 0x0000, 0x0000 }, /* R9609 */ + { 0x0000, 0x0000, 0x0000 }, /* R9610 */ + { 0x0000, 0x0000, 0x0000 }, /* R9611 */ + { 0x0000, 0x0000, 0x0000 }, /* R9612 */ + { 0x0000, 0x0000, 0x0000 }, /* R9613 */ + { 0x0000, 0x0000, 0x0000 }, /* R9614 */ + { 0x0000, 0x0000, 0x0000 }, /* R9615 */ + { 0x0000, 0x0000, 0x0000 }, /* R9616 */ + { 0x0000, 0x0000, 0x0000 }, /* R9617 */ + { 0x0000, 0x0000, 0x0000 }, /* R9618 */ + { 0x0000, 0x0000, 0x0000 }, /* R9619 */ + { 0x0000, 0x0000, 0x0000 }, /* R9620 */ + { 0x0000, 0x0000, 0x0000 }, /* R9621 */ + { 0x0000, 0x0000, 0x0000 }, /* R9622 */ + { 0x0000, 0x0000, 0x0000 }, /* R9623 */ + { 0x0000, 0x0000, 0x0000 }, /* R9624 */ + { 0x0000, 0x0000, 0x0000 }, /* R9625 */ + { 0x0000, 0x0000, 0x0000 }, /* R9626 */ + { 0x0000, 0x0000, 0x0000 }, /* R9627 */ + { 0x0000, 0x0000, 0x0000 }, /* R9628 */ + { 0x0000, 0x0000, 0x0000 }, /* R9629 */ + { 0x0000, 0x0000, 0x0000 }, /* R9630 */ + { 0x0000, 0x0000, 0x0000 }, /* R9631 */ + { 0x0000, 0x0000, 0x0000 }, /* R9632 */ + { 0x0000, 0x0000, 0x0000 }, /* R9633 */ + { 0x0000, 0x0000, 0x0000 }, /* R9634 */ + { 0x0000, 0x0000, 0x0000 }, /* R9635 */ + { 0x0000, 0x0000, 0x0000 }, /* R9636 */ + { 0x0000, 0x0000, 0x0000 }, /* R9637 */ + { 0x0000, 0x0000, 0x0000 }, /* R9638 */ + { 0x0000, 0x0000, 0x0000 }, /* R9639 */ + { 0x0000, 0x0000, 0x0000 }, /* R9640 */ + { 0x0000, 0x0000, 0x0000 }, /* R9641 */ + { 0x0000, 0x0000, 0x0000 }, /* R9642 */ + { 0x0000, 0x0000, 0x0000 }, /* R9643 */ + { 0x0000, 0x0000, 0x0000 }, /* R9644 */ + { 0x0000, 0x0000, 0x0000 }, /* R9645 */ + { 0x0000, 0x0000, 0x0000 }, /* R9646 */ + { 0x0000, 0x0000, 0x0000 }, /* R9647 */ + { 0x0000, 0x0000, 0x0000 }, /* R9648 */ + { 0x0000, 0x0000, 0x0000 }, /* R9649 */ + { 0x0000, 0x0000, 0x0000 }, /* R9650 */ + { 0x0000, 0x0000, 0x0000 }, /* R9651 */ + { 0x0000, 0x0000, 0x0000 }, /* R9652 */ + { 0x0000, 0x0000, 0x0000 }, /* R9653 */ + { 0x0000, 0x0000, 0x0000 }, /* R9654 */ + { 0x0000, 0x0000, 0x0000 }, /* R9655 */ + { 0x0000, 0x0000, 0x0000 }, /* R9656 */ + { 0x0000, 0x0000, 0x0000 }, /* R9657 */ + { 0x0000, 0x0000, 0x0000 }, /* R9658 */ + { 0x0000, 0x0000, 0x0000 }, /* R9659 */ + { 0x0000, 0x0000, 0x0000 }, /* R9660 */ + { 0x0000, 0x0000, 0x0000 }, /* R9661 */ + { 0x0000, 0x0000, 0x0000 }, /* R9662 */ + { 0x0000, 0x0000, 0x0000 }, /* R9663 */ + { 0x0000, 0x0000, 0x0000 }, /* R9664 */ + { 0x0000, 0x0000, 0x0000 }, /* R9665 */ + { 0x0000, 0x0000, 0x0000 }, /* R9666 */ + { 0x0000, 0x0000, 0x0000 }, /* R9667 */ + { 0x0000, 0x0000, 0x0000 }, /* R9668 */ + { 0x0000, 0x0000, 0x0000 }, /* R9669 */ + { 0x0000, 0x0000, 0x0000 }, /* R9670 */ + { 0x0000, 0x0000, 0x0000 }, /* R9671 */ + { 0x0000, 0x0000, 0x0000 }, /* R9672 */ + { 0x0000, 0x0000, 0x0000 }, /* R9673 */ + { 0x0000, 0x0000, 0x0000 }, /* R9674 */ + { 0x0000, 0x0000, 0x0000 }, /* R9675 */ + { 0x0000, 0x0000, 0x0000 }, /* R9676 */ + { 0x0000, 0x0000, 0x0000 }, /* R9677 */ + { 0x0000, 0x0000, 0x0000 }, /* R9678 */ + { 0x0000, 0x0000, 0x0000 }, /* R9679 */ + { 0x0000, 0x0000, 0x0000 }, /* R9680 */ + { 0x0000, 0x0000, 0x0000 }, /* R9681 */ + { 0x0000, 0x0000, 0x0000 }, /* R9682 */ + { 0x0000, 0x0000, 0x0000 }, /* R9683 */ + { 0x0000, 0x0000, 0x0000 }, /* R9684 */ + { 0x0000, 0x0000, 0x0000 }, /* R9685 */ + { 0x0000, 0x0000, 0x0000 }, /* R9686 */ + { 0x0000, 0x0000, 0x0000 }, /* R9687 */ + { 0x0000, 0x0000, 0x0000 }, /* R9688 */ + { 0x0000, 0x0000, 0x0000 }, /* R9689 */ + { 0x0000, 0x0000, 0x0000 }, /* R9690 */ + { 0x0000, 0x0000, 0x0000 }, /* R9691 */ + { 0x0000, 0x0000, 0x0000 }, /* R9692 */ + { 0x0000, 0x0000, 0x0000 }, /* R9693 */ + { 0x0000, 0x0000, 0x0000 }, /* R9694 */ + { 0x0000, 0x0000, 0x0000 }, /* R9695 */ + { 0x0000, 0x0000, 0x0000 }, /* R9696 */ + { 0x0000, 0x0000, 0x0000 }, /* R9697 */ + { 0x0000, 0x0000, 0x0000 }, /* R9698 */ + { 0x0000, 0x0000, 0x0000 }, /* R9699 */ + { 0x0000, 0x0000, 0x0000 }, /* R9700 */ + { 0x0000, 0x0000, 0x0000 }, /* R9701 */ + { 0x0000, 0x0000, 0x0000 }, /* R9702 */ + { 0x0000, 0x0000, 0x0000 }, /* R9703 */ + { 0x0000, 0x0000, 0x0000 }, /* R9704 */ + { 0x0000, 0x0000, 0x0000 }, /* R9705 */ + { 0x0000, 0x0000, 0x0000 }, /* R9706 */ + { 0x0000, 0x0000, 0x0000 }, /* R9707 */ + { 0x0000, 0x0000, 0x0000 }, /* R9708 */ + { 0x0000, 0x0000, 0x0000 }, /* R9709 */ + { 0x0000, 0x0000, 0x0000 }, /* R9710 */ + { 0x0000, 0x0000, 0x0000 }, /* R9711 */ + { 0x0000, 0x0000, 0x0000 }, /* R9712 */ + { 0x0000, 0x0000, 0x0000 }, /* R9713 */ + { 0x0000, 0x0000, 0x0000 }, /* R9714 */ + { 0x0000, 0x0000, 0x0000 }, /* R9715 */ + { 0x0000, 0x0000, 0x0000 }, /* R9716 */ + { 0x0000, 0x0000, 0x0000 }, /* R9717 */ + { 0x0000, 0x0000, 0x0000 }, /* R9718 */ + { 0x0000, 0x0000, 0x0000 }, /* R9719 */ + { 0x0000, 0x0000, 0x0000 }, /* R9720 */ + { 0x0000, 0x0000, 0x0000 }, /* R9721 */ + { 0x0000, 0x0000, 0x0000 }, /* R9722 */ + { 0x0000, 0x0000, 0x0000 }, /* R9723 */ + { 0x0000, 0x0000, 0x0000 }, /* R9724 */ + { 0x0000, 0x0000, 0x0000 }, /* R9725 */ + { 0x0000, 0x0000, 0x0000 }, /* R9726 */ + { 0x0000, 0x0000, 0x0000 }, /* R9727 */ + { 0x0000, 0x0000, 0x0000 }, /* R9728 */ + { 0x0000, 0x0000, 0x0000 }, /* R9729 */ + { 0x0000, 0x0000, 0x0000 }, /* R9730 */ + { 0x0000, 0x0000, 0x0000 }, /* R9731 */ + { 0x0000, 0x0000, 0x0000 }, /* R9732 */ + { 0x0000, 0x0000, 0x0000 }, /* R9733 */ + { 0x0000, 0x0000, 0x0000 }, /* R9734 */ + { 0x0000, 0x0000, 0x0000 }, /* R9735 */ + { 0x0000, 0x0000, 0x0000 }, /* R9736 */ + { 0x0000, 0x0000, 0x0000 }, /* R9737 */ + { 0x0000, 0x0000, 0x0000 }, /* R9738 */ + { 0x0000, 0x0000, 0x0000 }, /* R9739 */ + { 0x0000, 0x0000, 0x0000 }, /* R9740 */ + { 0x0000, 0x0000, 0x0000 }, /* R9741 */ + { 0x0000, 0x0000, 0x0000 }, /* R9742 */ + { 0x0000, 0x0000, 0x0000 }, /* R9743 */ + { 0x0000, 0x0000, 0x0000 }, /* R9744 */ + { 0x0000, 0x0000, 0x0000 }, /* R9745 */ + { 0x0000, 0x0000, 0x0000 }, /* R9746 */ + { 0x0000, 0x0000, 0x0000 }, /* R9747 */ + { 0x0000, 0x0000, 0x0000 }, /* R9748 */ + { 0x0000, 0x0000, 0x0000 }, /* R9749 */ + { 0x0000, 0x0000, 0x0000 }, /* R9750 */ + { 0x0000, 0x0000, 0x0000 }, /* R9751 */ + { 0x0000, 0x0000, 0x0000 }, /* R9752 */ + { 0x0000, 0x0000, 0x0000 }, /* R9753 */ + { 0x0000, 0x0000, 0x0000 }, /* R9754 */ + { 0x0000, 0x0000, 0x0000 }, /* R9755 */ + { 0x0000, 0x0000, 0x0000 }, /* R9756 */ + { 0x0000, 0x0000, 0x0000 }, /* R9757 */ + { 0x0000, 0x0000, 0x0000 }, /* R9758 */ + { 0x0000, 0x0000, 0x0000 }, /* R9759 */ + { 0x0000, 0x0000, 0x0000 }, /* R9760 */ + { 0x0000, 0x0000, 0x0000 }, /* R9761 */ + { 0x0000, 0x0000, 0x0000 }, /* R9762 */ + { 0x0000, 0x0000, 0x0000 }, /* R9763 */ + { 0x0000, 0x0000, 0x0000 }, /* R9764 */ + { 0x0000, 0x0000, 0x0000 }, /* R9765 */ + { 0x0000, 0x0000, 0x0000 }, /* R9766 */ + { 0x0000, 0x0000, 0x0000 }, /* R9767 */ + { 0x0000, 0x0000, 0x0000 }, /* R9768 */ + { 0x0000, 0x0000, 0x0000 }, /* R9769 */ + { 0x0000, 0x0000, 0x0000 }, /* R9770 */ + { 0x0000, 0x0000, 0x0000 }, /* R9771 */ + { 0x0000, 0x0000, 0x0000 }, /* R9772 */ + { 0x0000, 0x0000, 0x0000 }, /* R9773 */ + { 0x0000, 0x0000, 0x0000 }, /* R9774 */ + { 0x0000, 0x0000, 0x0000 }, /* R9775 */ + { 0x0000, 0x0000, 0x0000 }, /* R9776 */ + { 0x0000, 0x0000, 0x0000 }, /* R9777 */ + { 0x0000, 0x0000, 0x0000 }, /* R9778 */ + { 0x0000, 0x0000, 0x0000 }, /* R9779 */ + { 0x0000, 0x0000, 0x0000 }, /* R9780 */ + { 0x0000, 0x0000, 0x0000 }, /* R9781 */ + { 0x0000, 0x0000, 0x0000 }, /* R9782 */ + { 0x0000, 0x0000, 0x0000 }, /* R9783 */ + { 0x0000, 0x0000, 0x0000 }, /* R9784 */ + { 0x0000, 0x0000, 0x0000 }, /* R9785 */ + { 0x0000, 0x0000, 0x0000 }, /* R9786 */ + { 0x0000, 0x0000, 0x0000 }, /* R9787 */ + { 0x0000, 0x0000, 0x0000 }, /* R9788 */ + { 0x0000, 0x0000, 0x0000 }, /* R9789 */ + { 0x0000, 0x0000, 0x0000 }, /* R9790 */ + { 0x0000, 0x0000, 0x0000 }, /* R9791 */ + { 0x0000, 0x0000, 0x0000 }, /* R9792 */ + { 0x0000, 0x0000, 0x0000 }, /* R9793 */ + { 0x0000, 0x0000, 0x0000 }, /* R9794 */ + { 0x0000, 0x0000, 0x0000 }, /* R9795 */ + { 0x0000, 0x0000, 0x0000 }, /* R9796 */ + { 0x0000, 0x0000, 0x0000 }, /* R9797 */ + { 0x0000, 0x0000, 0x0000 }, /* R9798 */ + { 0x0000, 0x0000, 0x0000 }, /* R9799 */ + { 0x0000, 0x0000, 0x0000 }, /* R9800 */ + { 0x0000, 0x0000, 0x0000 }, /* R9801 */ + { 0x0000, 0x0000, 0x0000 }, /* R9802 */ + { 0x0000, 0x0000, 0x0000 }, /* R9803 */ + { 0x0000, 0x0000, 0x0000 }, /* R9804 */ + { 0x0000, 0x0000, 0x0000 }, /* R9805 */ + { 0x0000, 0x0000, 0x0000 }, /* R9806 */ + { 0x0000, 0x0000, 0x0000 }, /* R9807 */ + { 0x0000, 0x0000, 0x0000 }, /* R9808 */ + { 0x0000, 0x0000, 0x0000 }, /* R9809 */ + { 0x0000, 0x0000, 0x0000 }, /* R9810 */ + { 0x0000, 0x0000, 0x0000 }, /* R9811 */ + { 0x0000, 0x0000, 0x0000 }, /* R9812 */ + { 0x0000, 0x0000, 0x0000 }, /* R9813 */ + { 0x0000, 0x0000, 0x0000 }, /* R9814 */ + { 0x0000, 0x0000, 0x0000 }, /* R9815 */ + { 0x0000, 0x0000, 0x0000 }, /* R9816 */ + { 0x0000, 0x0000, 0x0000 }, /* R9817 */ + { 0x0000, 0x0000, 0x0000 }, /* R9818 */ + { 0x0000, 0x0000, 0x0000 }, /* R9819 */ + { 0x0000, 0x0000, 0x0000 }, /* R9820 */ + { 0x0000, 0x0000, 0x0000 }, /* R9821 */ + { 0x0000, 0x0000, 0x0000 }, /* R9822 */ + { 0x0000, 0x0000, 0x0000 }, /* R9823 */ + { 0x0000, 0x0000, 0x0000 }, /* R9824 */ + { 0x0000, 0x0000, 0x0000 }, /* R9825 */ + { 0x0000, 0x0000, 0x0000 }, /* R9826 */ + { 0x0000, 0x0000, 0x0000 }, /* R9827 */ + { 0x0000, 0x0000, 0x0000 }, /* R9828 */ + { 0x0000, 0x0000, 0x0000 }, /* R9829 */ + { 0x0000, 0x0000, 0x0000 }, /* R9830 */ + { 0x0000, 0x0000, 0x0000 }, /* R9831 */ + { 0x0000, 0x0000, 0x0000 }, /* R9832 */ + { 0x0000, 0x0000, 0x0000 }, /* R9833 */ + { 0x0000, 0x0000, 0x0000 }, /* R9834 */ + { 0x0000, 0x0000, 0x0000 }, /* R9835 */ + { 0x0000, 0x0000, 0x0000 }, /* R9836 */ + { 0x0000, 0x0000, 0x0000 }, /* R9837 */ + { 0x0000, 0x0000, 0x0000 }, /* R9838 */ + { 0x0000, 0x0000, 0x0000 }, /* R9839 */ + { 0x0000, 0x0000, 0x0000 }, /* R9840 */ + { 0x0000, 0x0000, 0x0000 }, /* R9841 */ + { 0x0000, 0x0000, 0x0000 }, /* R9842 */ + { 0x0000, 0x0000, 0x0000 }, /* R9843 */ + { 0x0000, 0x0000, 0x0000 }, /* R9844 */ + { 0x0000, 0x0000, 0x0000 }, /* R9845 */ + { 0x0000, 0x0000, 0x0000 }, /* R9846 */ + { 0x0000, 0x0000, 0x0000 }, /* R9847 */ + { 0x0000, 0x0000, 0x0000 }, /* R9848 */ + { 0x0000, 0x0000, 0x0000 }, /* R9849 */ + { 0x0000, 0x0000, 0x0000 }, /* R9850 */ + { 0x0000, 0x0000, 0x0000 }, /* R9851 */ + { 0x0000, 0x0000, 0x0000 }, /* R9852 */ + { 0x0000, 0x0000, 0x0000 }, /* R9853 */ + { 0x0000, 0x0000, 0x0000 }, /* R9854 */ + { 0x0000, 0x0000, 0x0000 }, /* R9855 */ + { 0x0000, 0x0000, 0x0000 }, /* R9856 */ + { 0x0000, 0x0000, 0x0000 }, /* R9857 */ + { 0x0000, 0x0000, 0x0000 }, /* R9858 */ + { 0x0000, 0x0000, 0x0000 }, /* R9859 */ + { 0x0000, 0x0000, 0x0000 }, /* R9860 */ + { 0x0000, 0x0000, 0x0000 }, /* R9861 */ + { 0x0000, 0x0000, 0x0000 }, /* R9862 */ + { 0x0000, 0x0000, 0x0000 }, /* R9863 */ + { 0x0000, 0x0000, 0x0000 }, /* R9864 */ + { 0x0000, 0x0000, 0x0000 }, /* R9865 */ + { 0x0000, 0x0000, 0x0000 }, /* R9866 */ + { 0x0000, 0x0000, 0x0000 }, /* R9867 */ + { 0x0000, 0x0000, 0x0000 }, /* R9868 */ + { 0x0000, 0x0000, 0x0000 }, /* R9869 */ + { 0x0000, 0x0000, 0x0000 }, /* R9870 */ + { 0x0000, 0x0000, 0x0000 }, /* R9871 */ + { 0x0000, 0x0000, 0x0000 }, /* R9872 */ + { 0x0000, 0x0000, 0x0000 }, /* R9873 */ + { 0x0000, 0x0000, 0x0000 }, /* R9874 */ + { 0x0000, 0x0000, 0x0000 }, /* R9875 */ + { 0x0000, 0x0000, 0x0000 }, /* R9876 */ + { 0x0000, 0x0000, 0x0000 }, /* R9877 */ + { 0x0000, 0x0000, 0x0000 }, /* R9878 */ + { 0x0000, 0x0000, 0x0000 }, /* R9879 */ + { 0x0000, 0x0000, 0x0000 }, /* R9880 */ + { 0x0000, 0x0000, 0x0000 }, /* R9881 */ + { 0x0000, 0x0000, 0x0000 }, /* R9882 */ + { 0x0000, 0x0000, 0x0000 }, /* R9883 */ + { 0x0000, 0x0000, 0x0000 }, /* R9884 */ + { 0x0000, 0x0000, 0x0000 }, /* R9885 */ + { 0x0000, 0x0000, 0x0000 }, /* R9886 */ + { 0x0000, 0x0000, 0x0000 }, /* R9887 */ + { 0x0000, 0x0000, 0x0000 }, /* R9888 */ + { 0x0000, 0x0000, 0x0000 }, /* R9889 */ + { 0x0000, 0x0000, 0x0000 }, /* R9890 */ + { 0x0000, 0x0000, 0x0000 }, /* R9891 */ + { 0x0000, 0x0000, 0x0000 }, /* R9892 */ + { 0x0000, 0x0000, 0x0000 }, /* R9893 */ + { 0x0000, 0x0000, 0x0000 }, /* R9894 */ + { 0x0000, 0x0000, 0x0000 }, /* R9895 */ + { 0x0000, 0x0000, 0x0000 }, /* R9896 */ + { 0x0000, 0x0000, 0x0000 }, /* R9897 */ + { 0x0000, 0x0000, 0x0000 }, /* R9898 */ + { 0x0000, 0x0000, 0x0000 }, /* R9899 */ + { 0x0000, 0x0000, 0x0000 }, /* R9900 */ + { 0x0000, 0x0000, 0x0000 }, /* R9901 */ + { 0x0000, 0x0000, 0x0000 }, /* R9902 */ + { 0x0000, 0x0000, 0x0000 }, /* R9903 */ + { 0x0000, 0x0000, 0x0000 }, /* R9904 */ + { 0x0000, 0x0000, 0x0000 }, /* R9905 */ + { 0x0000, 0x0000, 0x0000 }, /* R9906 */ + { 0x0000, 0x0000, 0x0000 }, /* R9907 */ + { 0x0000, 0x0000, 0x0000 }, /* R9908 */ + { 0x0000, 0x0000, 0x0000 }, /* R9909 */ + { 0x0000, 0x0000, 0x0000 }, /* R9910 */ + { 0x0000, 0x0000, 0x0000 }, /* R9911 */ + { 0x0000, 0x0000, 0x0000 }, /* R9912 */ + { 0x0000, 0x0000, 0x0000 }, /* R9913 */ + { 0x0000, 0x0000, 0x0000 }, /* R9914 */ + { 0x0000, 0x0000, 0x0000 }, /* R9915 */ + { 0x0000, 0x0000, 0x0000 }, /* R9916 */ + { 0x0000, 0x0000, 0x0000 }, /* R9917 */ + { 0x0000, 0x0000, 0x0000 }, /* R9918 */ + { 0x0000, 0x0000, 0x0000 }, /* R9919 */ + { 0x0000, 0x0000, 0x0000 }, /* R9920 */ + { 0x0000, 0x0000, 0x0000 }, /* R9921 */ + { 0x0000, 0x0000, 0x0000 }, /* R9922 */ + { 0x0000, 0x0000, 0x0000 }, /* R9923 */ + { 0x0000, 0x0000, 0x0000 }, /* R9924 */ + { 0x0000, 0x0000, 0x0000 }, /* R9925 */ + { 0x0000, 0x0000, 0x0000 }, /* R9926 */ + { 0x0000, 0x0000, 0x0000 }, /* R9927 */ + { 0x0000, 0x0000, 0x0000 }, /* R9928 */ + { 0x0000, 0x0000, 0x0000 }, /* R9929 */ + { 0x0000, 0x0000, 0x0000 }, /* R9930 */ + { 0x0000, 0x0000, 0x0000 }, /* R9931 */ + { 0x0000, 0x0000, 0x0000 }, /* R9932 */ + { 0x0000, 0x0000, 0x0000 }, /* R9933 */ + { 0x0000, 0x0000, 0x0000 }, /* R9934 */ + { 0x0000, 0x0000, 0x0000 }, /* R9935 */ + { 0x0000, 0x0000, 0x0000 }, /* R9936 */ + { 0x0000, 0x0000, 0x0000 }, /* R9937 */ + { 0x0000, 0x0000, 0x0000 }, /* R9938 */ + { 0x0000, 0x0000, 0x0000 }, /* R9939 */ + { 0x0000, 0x0000, 0x0000 }, /* R9940 */ + { 0x0000, 0x0000, 0x0000 }, /* R9941 */ + { 0x0000, 0x0000, 0x0000 }, /* R9942 */ + { 0x0000, 0x0000, 0x0000 }, /* R9943 */ + { 0x0000, 0x0000, 0x0000 }, /* R9944 */ + { 0x0000, 0x0000, 0x0000 }, /* R9945 */ + { 0x0000, 0x0000, 0x0000 }, /* R9946 */ + { 0x0000, 0x0000, 0x0000 }, /* R9947 */ + { 0x0000, 0x0000, 0x0000 }, /* R9948 */ + { 0x0000, 0x0000, 0x0000 }, /* R9949 */ + { 0x0000, 0x0000, 0x0000 }, /* R9950 */ + { 0x0000, 0x0000, 0x0000 }, /* R9951 */ + { 0x0000, 0x0000, 0x0000 }, /* R9952 */ + { 0x0000, 0x0000, 0x0000 }, /* R9953 */ + { 0x0000, 0x0000, 0x0000 }, /* R9954 */ + { 0x0000, 0x0000, 0x0000 }, /* R9955 */ + { 0x0000, 0x0000, 0x0000 }, /* R9956 */ + { 0x0000, 0x0000, 0x0000 }, /* R9957 */ + { 0x0000, 0x0000, 0x0000 }, /* R9958 */ + { 0x0000, 0x0000, 0x0000 }, /* R9959 */ + { 0x0000, 0x0000, 0x0000 }, /* R9960 */ + { 0x0000, 0x0000, 0x0000 }, /* R9961 */ + { 0x0000, 0x0000, 0x0000 }, /* R9962 */ + { 0x0000, 0x0000, 0x0000 }, /* R9963 */ + { 0x0000, 0x0000, 0x0000 }, /* R9964 */ + { 0x0000, 0x0000, 0x0000 }, /* R9965 */ + { 0x0000, 0x0000, 0x0000 }, /* R9966 */ + { 0x0000, 0x0000, 0x0000 }, /* R9967 */ + { 0x0000, 0x0000, 0x0000 }, /* R9968 */ + { 0x0000, 0x0000, 0x0000 }, /* R9969 */ + { 0x0000, 0x0000, 0x0000 }, /* R9970 */ + { 0x0000, 0x0000, 0x0000 }, /* R9971 */ + { 0x0000, 0x0000, 0x0000 }, /* R9972 */ + { 0x0000, 0x0000, 0x0000 }, /* R9973 */ + { 0x0000, 0x0000, 0x0000 }, /* R9974 */ + { 0x0000, 0x0000, 0x0000 }, /* R9975 */ + { 0x0000, 0x0000, 0x0000 }, /* R9976 */ + { 0x0000, 0x0000, 0x0000 }, /* R9977 */ + { 0x0000, 0x0000, 0x0000 }, /* R9978 */ + { 0x0000, 0x0000, 0x0000 }, /* R9979 */ + { 0x0000, 0x0000, 0x0000 }, /* R9980 */ + { 0x0000, 0x0000, 0x0000 }, /* R9981 */ + { 0x0000, 0x0000, 0x0000 }, /* R9982 */ + { 0x0000, 0x0000, 0x0000 }, /* R9983 */ + { 0x0000, 0x0000, 0x0000 }, /* R9984 */ + { 0x0000, 0x0000, 0x0000 }, /* R9985 */ + { 0x0000, 0x0000, 0x0000 }, /* R9986 */ + { 0x0000, 0x0000, 0x0000 }, /* R9987 */ + { 0x0000, 0x0000, 0x0000 }, /* R9988 */ + { 0x0000, 0x0000, 0x0000 }, /* R9989 */ + { 0x0000, 0x0000, 0x0000 }, /* R9990 */ + { 0x0000, 0x0000, 0x0000 }, /* R9991 */ + { 0x0000, 0x0000, 0x0000 }, /* R9992 */ + { 0x0000, 0x0000, 0x0000 }, /* R9993 */ + { 0x0000, 0x0000, 0x0000 }, /* R9994 */ + { 0x0000, 0x0000, 0x0000 }, /* R9995 */ + { 0x0000, 0x0000, 0x0000 }, /* R9996 */ + { 0x0000, 0x0000, 0x0000 }, /* R9997 */ + { 0x0000, 0x0000, 0x0000 }, /* R9998 */ + { 0x0000, 0x0000, 0x0000 }, /* R9999 */ + { 0x0000, 0x0000, 0x0000 }, /* R10000 */ + { 0x0000, 0x0000, 0x0000 }, /* R10001 */ + { 0x0000, 0x0000, 0x0000 }, /* R10002 */ + { 0x0000, 0x0000, 0x0000 }, /* R10003 */ + { 0x0000, 0x0000, 0x0000 }, /* R10004 */ + { 0x0000, 0x0000, 0x0000 }, /* R10005 */ + { 0x0000, 0x0000, 0x0000 }, /* R10006 */ + { 0x0000, 0x0000, 0x0000 }, /* R10007 */ + { 0x0000, 0x0000, 0x0000 }, /* R10008 */ + { 0x0000, 0x0000, 0x0000 }, /* R10009 */ + { 0x0000, 0x0000, 0x0000 }, /* R10010 */ + { 0x0000, 0x0000, 0x0000 }, /* R10011 */ + { 0x0000, 0x0000, 0x0000 }, /* R10012 */ + { 0x0000, 0x0000, 0x0000 }, /* R10013 */ + { 0x0000, 0x0000, 0x0000 }, /* R10014 */ + { 0x0000, 0x0000, 0x0000 }, /* R10015 */ + { 0x0000, 0x0000, 0x0000 }, /* R10016 */ + { 0x0000, 0x0000, 0x0000 }, /* R10017 */ + { 0x0000, 0x0000, 0x0000 }, /* R10018 */ + { 0x0000, 0x0000, 0x0000 }, /* R10019 */ + { 0x0000, 0x0000, 0x0000 }, /* R10020 */ + { 0x0000, 0x0000, 0x0000 }, /* R10021 */ + { 0x0000, 0x0000, 0x0000 }, /* R10022 */ + { 0x0000, 0x0000, 0x0000 }, /* R10023 */ + { 0x0000, 0x0000, 0x0000 }, /* R10024 */ + { 0x0000, 0x0000, 0x0000 }, /* R10025 */ + { 0x0000, 0x0000, 0x0000 }, /* R10026 */ + { 0x0000, 0x0000, 0x0000 }, /* R10027 */ + { 0x0000, 0x0000, 0x0000 }, /* R10028 */ + { 0x0000, 0x0000, 0x0000 }, /* R10029 */ + { 0x0000, 0x0000, 0x0000 }, /* R10030 */ + { 0x0000, 0x0000, 0x0000 }, /* R10031 */ + { 0x0000, 0x0000, 0x0000 }, /* R10032 */ + { 0x0000, 0x0000, 0x0000 }, /* R10033 */ + { 0x0000, 0x0000, 0x0000 }, /* R10034 */ + { 0x0000, 0x0000, 0x0000 }, /* R10035 */ + { 0x0000, 0x0000, 0x0000 }, /* R10036 */ + { 0x0000, 0x0000, 0x0000 }, /* R10037 */ + { 0x0000, 0x0000, 0x0000 }, /* R10038 */ + { 0x0000, 0x0000, 0x0000 }, /* R10039 */ + { 0x0000, 0x0000, 0x0000 }, /* R10040 */ + { 0x0000, 0x0000, 0x0000 }, /* R10041 */ + { 0x0000, 0x0000, 0x0000 }, /* R10042 */ + { 0x0000, 0x0000, 0x0000 }, /* R10043 */ + { 0x0000, 0x0000, 0x0000 }, /* R10044 */ + { 0x0000, 0x0000, 0x0000 }, /* R10045 */ + { 0x0000, 0x0000, 0x0000 }, /* R10046 */ + { 0x0000, 0x0000, 0x0000 }, /* R10047 */ + { 0x0000, 0x0000, 0x0000 }, /* R10048 */ + { 0x0000, 0x0000, 0x0000 }, /* R10049 */ + { 0x0000, 0x0000, 0x0000 }, /* R10050 */ + { 0x0000, 0x0000, 0x0000 }, /* R10051 */ + { 0x0000, 0x0000, 0x0000 }, /* R10052 */ + { 0x0000, 0x0000, 0x0000 }, /* R10053 */ + { 0x0000, 0x0000, 0x0000 }, /* R10054 */ + { 0x0000, 0x0000, 0x0000 }, /* R10055 */ + { 0x0000, 0x0000, 0x0000 }, /* R10056 */ + { 0x0000, 0x0000, 0x0000 }, /* R10057 */ + { 0x0000, 0x0000, 0x0000 }, /* R10058 */ + { 0x0000, 0x0000, 0x0000 }, /* R10059 */ + { 0x0000, 0x0000, 0x0000 }, /* R10060 */ + { 0x0000, 0x0000, 0x0000 }, /* R10061 */ + { 0x0000, 0x0000, 0x0000 }, /* R10062 */ + { 0x0000, 0x0000, 0x0000 }, /* R10063 */ + { 0x0000, 0x0000, 0x0000 }, /* R10064 */ + { 0x0000, 0x0000, 0x0000 }, /* R10065 */ + { 0x0000, 0x0000, 0x0000 }, /* R10066 */ + { 0x0000, 0x0000, 0x0000 }, /* R10067 */ + { 0x0000, 0x0000, 0x0000 }, /* R10068 */ + { 0x0000, 0x0000, 0x0000 }, /* R10069 */ + { 0x0000, 0x0000, 0x0000 }, /* R10070 */ + { 0x0000, 0x0000, 0x0000 }, /* R10071 */ + { 0x0000, 0x0000, 0x0000 }, /* R10072 */ + { 0x0000, 0x0000, 0x0000 }, /* R10073 */ + { 0x0000, 0x0000, 0x0000 }, /* R10074 */ + { 0x0000, 0x0000, 0x0000 }, /* R10075 */ + { 0x0000, 0x0000, 0x0000 }, /* R10076 */ + { 0x0000, 0x0000, 0x0000 }, /* R10077 */ + { 0x0000, 0x0000, 0x0000 }, /* R10078 */ + { 0x0000, 0x0000, 0x0000 }, /* R10079 */ + { 0x0000, 0x0000, 0x0000 }, /* R10080 */ + { 0x0000, 0x0000, 0x0000 }, /* R10081 */ + { 0x0000, 0x0000, 0x0000 }, /* R10082 */ + { 0x0000, 0x0000, 0x0000 }, /* R10083 */ + { 0x0000, 0x0000, 0x0000 }, /* R10084 */ + { 0x0000, 0x0000, 0x0000 }, /* R10085 */ + { 0x0000, 0x0000, 0x0000 }, /* R10086 */ + { 0x0000, 0x0000, 0x0000 }, /* R10087 */ + { 0x0000, 0x0000, 0x0000 }, /* R10088 */ + { 0x0000, 0x0000, 0x0000 }, /* R10089 */ + { 0x0000, 0x0000, 0x0000 }, /* R10090 */ + { 0x0000, 0x0000, 0x0000 }, /* R10091 */ + { 0x0000, 0x0000, 0x0000 }, /* R10092 */ + { 0x0000, 0x0000, 0x0000 }, /* R10093 */ + { 0x0000, 0x0000, 0x0000 }, /* R10094 */ + { 0x0000, 0x0000, 0x0000 }, /* R10095 */ + { 0x0000, 0x0000, 0x0000 }, /* R10096 */ + { 0x0000, 0x0000, 0x0000 }, /* R10097 */ + { 0x0000, 0x0000, 0x0000 }, /* R10098 */ + { 0x0000, 0x0000, 0x0000 }, /* R10099 */ + { 0x0000, 0x0000, 0x0000 }, /* R10100 */ + { 0x0000, 0x0000, 0x0000 }, /* R10101 */ + { 0x0000, 0x0000, 0x0000 }, /* R10102 */ + { 0x0000, 0x0000, 0x0000 }, /* R10103 */ + { 0x0000, 0x0000, 0x0000 }, /* R10104 */ + { 0x0000, 0x0000, 0x0000 }, /* R10105 */ + { 0x0000, 0x0000, 0x0000 }, /* R10106 */ + { 0x0000, 0x0000, 0x0000 }, /* R10107 */ + { 0x0000, 0x0000, 0x0000 }, /* R10108 */ + { 0x0000, 0x0000, 0x0000 }, /* R10109 */ + { 0x0000, 0x0000, 0x0000 }, /* R10110 */ + { 0x0000, 0x0000, 0x0000 }, /* R10111 */ + { 0x0000, 0x0000, 0x0000 }, /* R10112 */ + { 0x0000, 0x0000, 0x0000 }, /* R10113 */ + { 0x0000, 0x0000, 0x0000 }, /* R10114 */ + { 0x0000, 0x0000, 0x0000 }, /* R10115 */ + { 0x0000, 0x0000, 0x0000 }, /* R10116 */ + { 0x0000, 0x0000, 0x0000 }, /* R10117 */ + { 0x0000, 0x0000, 0x0000 }, /* R10118 */ + { 0x0000, 0x0000, 0x0000 }, /* R10119 */ + { 0x0000, 0x0000, 0x0000 }, /* R10120 */ + { 0x0000, 0x0000, 0x0000 }, /* R10121 */ + { 0x0000, 0x0000, 0x0000 }, /* R10122 */ + { 0x0000, 0x0000, 0x0000 }, /* R10123 */ + { 0x0000, 0x0000, 0x0000 }, /* R10124 */ + { 0x0000, 0x0000, 0x0000 }, /* R10125 */ + { 0x0000, 0x0000, 0x0000 }, /* R10126 */ + { 0x0000, 0x0000, 0x0000 }, /* R10127 */ + { 0x0000, 0x0000, 0x0000 }, /* R10128 */ + { 0x0000, 0x0000, 0x0000 }, /* R10129 */ + { 0x0000, 0x0000, 0x0000 }, /* R10130 */ + { 0x0000, 0x0000, 0x0000 }, /* R10131 */ + { 0x0000, 0x0000, 0x0000 }, /* R10132 */ + { 0x0000, 0x0000, 0x0000 }, /* R10133 */ + { 0x0000, 0x0000, 0x0000 }, /* R10134 */ + { 0x0000, 0x0000, 0x0000 }, /* R10135 */ + { 0x0000, 0x0000, 0x0000 }, /* R10136 */ + { 0x0000, 0x0000, 0x0000 }, /* R10137 */ + { 0x0000, 0x0000, 0x0000 }, /* R10138 */ + { 0x0000, 0x0000, 0x0000 }, /* R10139 */ + { 0x0000, 0x0000, 0x0000 }, /* R10140 */ + { 0x0000, 0x0000, 0x0000 }, /* R10141 */ + { 0x0000, 0x0000, 0x0000 }, /* R10142 */ + { 0x0000, 0x0000, 0x0000 }, /* R10143 */ + { 0x0000, 0x0000, 0x0000 }, /* R10144 */ + { 0x0000, 0x0000, 0x0000 }, /* R10145 */ + { 0x0000, 0x0000, 0x0000 }, /* R10146 */ + { 0x0000, 0x0000, 0x0000 }, /* R10147 */ + { 0x0000, 0x0000, 0x0000 }, /* R10148 */ + { 0x0000, 0x0000, 0x0000 }, /* R10149 */ + { 0x0000, 0x0000, 0x0000 }, /* R10150 */ + { 0x0000, 0x0000, 0x0000 }, /* R10151 */ + { 0x0000, 0x0000, 0x0000 }, /* R10152 */ + { 0x0000, 0x0000, 0x0000 }, /* R10153 */ + { 0x0000, 0x0000, 0x0000 }, /* R10154 */ + { 0x0000, 0x0000, 0x0000 }, /* R10155 */ + { 0x0000, 0x0000, 0x0000 }, /* R10156 */ + { 0x0000, 0x0000, 0x0000 }, /* R10157 */ + { 0x0000, 0x0000, 0x0000 }, /* R10158 */ + { 0x0000, 0x0000, 0x0000 }, /* R10159 */ + { 0x0000, 0x0000, 0x0000 }, /* R10160 */ + { 0x0000, 0x0000, 0x0000 }, /* R10161 */ + { 0x0000, 0x0000, 0x0000 }, /* R10162 */ + { 0x0000, 0x0000, 0x0000 }, /* R10163 */ + { 0x0000, 0x0000, 0x0000 }, /* R10164 */ + { 0x0000, 0x0000, 0x0000 }, /* R10165 */ + { 0x0000, 0x0000, 0x0000 }, /* R10166 */ + { 0x0000, 0x0000, 0x0000 }, /* R10167 */ + { 0x0000, 0x0000, 0x0000 }, /* R10168 */ + { 0x0000, 0x0000, 0x0000 }, /* R10169 */ + { 0x0000, 0x0000, 0x0000 }, /* R10170 */ + { 0x0000, 0x0000, 0x0000 }, /* R10171 */ + { 0x0000, 0x0000, 0x0000 }, /* R10172 */ + { 0x0000, 0x0000, 0x0000 }, /* R10173 */ + { 0x0000, 0x0000, 0x0000 }, /* R10174 */ + { 0x0000, 0x0000, 0x0000 }, /* R10175 */ + { 0x0000, 0x0000, 0x0000 }, /* R10176 */ + { 0x0000, 0x0000, 0x0000 }, /* R10177 */ + { 0x0000, 0x0000, 0x0000 }, /* R10178 */ + { 0x0000, 0x0000, 0x0000 }, /* R10179 */ + { 0x0000, 0x0000, 0x0000 }, /* R10180 */ + { 0x0000, 0x0000, 0x0000 }, /* R10181 */ + { 0x0000, 0x0000, 0x0000 }, /* R10182 */ + { 0x0000, 0x0000, 0x0000 }, /* R10183 */ + { 0x0000, 0x0000, 0x0000 }, /* R10184 */ + { 0x0000, 0x0000, 0x0000 }, /* R10185 */ + { 0x0000, 0x0000, 0x0000 }, /* R10186 */ + { 0x0000, 0x0000, 0x0000 }, /* R10187 */ + { 0x0000, 0x0000, 0x0000 }, /* R10188 */ + { 0x0000, 0x0000, 0x0000 }, /* R10189 */ + { 0x0000, 0x0000, 0x0000 }, /* R10190 */ + { 0x0000, 0x0000, 0x0000 }, /* R10191 */ + { 0x0000, 0x0000, 0x0000 }, /* R10192 */ + { 0x0000, 0x0000, 0x0000 }, /* R10193 */ + { 0x0000, 0x0000, 0x0000 }, /* R10194 */ + { 0x0000, 0x0000, 0x0000 }, /* R10195 */ + { 0x0000, 0x0000, 0x0000 }, /* R10196 */ + { 0x0000, 0x0000, 0x0000 }, /* R10197 */ + { 0x0000, 0x0000, 0x0000 }, /* R10198 */ + { 0x0000, 0x0000, 0x0000 }, /* R10199 */ + { 0x0000, 0x0000, 0x0000 }, /* R10200 */ + { 0x0000, 0x0000, 0x0000 }, /* R10201 */ + { 0x0000, 0x0000, 0x0000 }, /* R10202 */ + { 0x0000, 0x0000, 0x0000 }, /* R10203 */ + { 0x0000, 0x0000, 0x0000 }, /* R10204 */ + { 0x0000, 0x0000, 0x0000 }, /* R10205 */ + { 0x0000, 0x0000, 0x0000 }, /* R10206 */ + { 0x0000, 0x0000, 0x0000 }, /* R10207 */ + { 0x0000, 0x0000, 0x0000 }, /* R10208 */ + { 0x0000, 0x0000, 0x0000 }, /* R10209 */ + { 0x0000, 0x0000, 0x0000 }, /* R10210 */ + { 0x0000, 0x0000, 0x0000 }, /* R10211 */ + { 0x0000, 0x0000, 0x0000 }, /* R10212 */ + { 0x0000, 0x0000, 0x0000 }, /* R10213 */ + { 0x0000, 0x0000, 0x0000 }, /* R10214 */ + { 0x0000, 0x0000, 0x0000 }, /* R10215 */ + { 0x0000, 0x0000, 0x0000 }, /* R10216 */ + { 0x0000, 0x0000, 0x0000 }, /* R10217 */ + { 0x0000, 0x0000, 0x0000 }, /* R10218 */ + { 0x0000, 0x0000, 0x0000 }, /* R10219 */ + { 0x0000, 0x0000, 0x0000 }, /* R10220 */ + { 0x0000, 0x0000, 0x0000 }, /* R10221 */ + { 0x0000, 0x0000, 0x0000 }, /* R10222 */ + { 0x0000, 0x0000, 0x0000 }, /* R10223 */ + { 0x0000, 0x0000, 0x0000 }, /* R10224 */ + { 0x0000, 0x0000, 0x0000 }, /* R10225 */ + { 0x0000, 0x0000, 0x0000 }, /* R10226 */ + { 0x0000, 0x0000, 0x0000 }, /* R10227 */ + { 0x0000, 0x0000, 0x0000 }, /* R10228 */ + { 0x0000, 0x0000, 0x0000 }, /* R10229 */ + { 0x0000, 0x0000, 0x0000 }, /* R10230 */ + { 0x0000, 0x0000, 0x0000 }, /* R10231 */ + { 0x0000, 0x0000, 0x0000 }, /* R10232 */ + { 0x0000, 0x0000, 0x0000 }, /* R10233 */ + { 0x0000, 0x0000, 0x0000 }, /* R10234 */ + { 0x0000, 0x0000, 0x0000 }, /* R10235 */ + { 0x0000, 0x0000, 0x0000 }, /* R10236 */ + { 0x0000, 0x0000, 0x0000 }, /* R10237 */ + { 0x0000, 0x0000, 0x0000 }, /* R10238 */ + { 0x0000, 0x0000, 0x0000 }, /* R10239 */ + { 0x0000, 0x0000, 0x0000 }, /* R10240 */ + { 0x0000, 0x0000, 0x0000 }, /* R10241 */ + { 0x0000, 0x0000, 0x0000 }, /* R10242 */ + { 0x0000, 0x0000, 0x0000 }, /* R10243 */ + { 0x0000, 0x0000, 0x0000 }, /* R10244 */ + { 0x0000, 0x0000, 0x0000 }, /* R10245 */ + { 0x0000, 0x0000, 0x0000 }, /* R10246 */ + { 0x0000, 0x0000, 0x0000 }, /* R10247 */ + { 0x0000, 0x0000, 0x0000 }, /* R10248 */ + { 0x0000, 0x0000, 0x0000 }, /* R10249 */ + { 0x0000, 0x0000, 0x0000 }, /* R10250 */ + { 0x0000, 0x0000, 0x0000 }, /* R10251 */ + { 0x0000, 0x0000, 0x0000 }, /* R10252 */ + { 0x0000, 0x0000, 0x0000 }, /* R10253 */ + { 0x0000, 0x0000, 0x0000 }, /* R10254 */ + { 0x0000, 0x0000, 0x0000 }, /* R10255 */ + { 0x0000, 0x0000, 0x0000 }, /* R10256 */ + { 0x0000, 0x0000, 0x0000 }, /* R10257 */ + { 0x0000, 0x0000, 0x0000 }, /* R10258 */ + { 0x0000, 0x0000, 0x0000 }, /* R10259 */ + { 0x0000, 0x0000, 0x0000 }, /* R10260 */ + { 0x0000, 0x0000, 0x0000 }, /* R10261 */ + { 0x0000, 0x0000, 0x0000 }, /* R10262 */ + { 0x0000, 0x0000, 0x0000 }, /* R10263 */ + { 0x0000, 0x0000, 0x0000 }, /* R10264 */ + { 0x0000, 0x0000, 0x0000 }, /* R10265 */ + { 0x0000, 0x0000, 0x0000 }, /* R10266 */ + { 0x0000, 0x0000, 0x0000 }, /* R10267 */ + { 0x0000, 0x0000, 0x0000 }, /* R10268 */ + { 0x0000, 0x0000, 0x0000 }, /* R10269 */ + { 0x0000, 0x0000, 0x0000 }, /* R10270 */ + { 0x0000, 0x0000, 0x0000 }, /* R10271 */ + { 0x0000, 0x0000, 0x0000 }, /* R10272 */ + { 0x0000, 0x0000, 0x0000 }, /* R10273 */ + { 0x0000, 0x0000, 0x0000 }, /* R10274 */ + { 0x0000, 0x0000, 0x0000 }, /* R10275 */ + { 0x0000, 0x0000, 0x0000 }, /* R10276 */ + { 0x0000, 0x0000, 0x0000 }, /* R10277 */ + { 0x0000, 0x0000, 0x0000 }, /* R10278 */ + { 0x0000, 0x0000, 0x0000 }, /* R10279 */ + { 0x0000, 0x0000, 0x0000 }, /* R10280 */ + { 0x0000, 0x0000, 0x0000 }, /* R10281 */ + { 0x0000, 0x0000, 0x0000 }, /* R10282 */ + { 0x0000, 0x0000, 0x0000 }, /* R10283 */ + { 0x0000, 0x0000, 0x0000 }, /* R10284 */ + { 0x0000, 0x0000, 0x0000 }, /* R10285 */ + { 0x0000, 0x0000, 0x0000 }, /* R10286 */ + { 0x0000, 0x0000, 0x0000 }, /* R10287 */ + { 0x0000, 0x0000, 0x0000 }, /* R10288 */ + { 0x0000, 0x0000, 0x0000 }, /* R10289 */ + { 0x0000, 0x0000, 0x0000 }, /* R10290 */ + { 0x0000, 0x0000, 0x0000 }, /* R10291 */ + { 0x0000, 0x0000, 0x0000 }, /* R10292 */ + { 0x0000, 0x0000, 0x0000 }, /* R10293 */ + { 0x0000, 0x0000, 0x0000 }, /* R10294 */ + { 0x0000, 0x0000, 0x0000 }, /* R10295 */ + { 0x0000, 0x0000, 0x0000 }, /* R10296 */ + { 0x0000, 0x0000, 0x0000 }, /* R10297 */ + { 0x0000, 0x0000, 0x0000 }, /* R10298 */ + { 0x0000, 0x0000, 0x0000 }, /* R10299 */ + { 0x0000, 0x0000, 0x0000 }, /* R10300 */ + { 0x0000, 0x0000, 0x0000 }, /* R10301 */ + { 0x0000, 0x0000, 0x0000 }, /* R10302 */ + { 0x0000, 0x0000, 0x0000 }, /* R10303 */ + { 0x0000, 0x0000, 0x0000 }, /* R10304 */ + { 0x0000, 0x0000, 0x0000 }, /* R10305 */ + { 0x0000, 0x0000, 0x0000 }, /* R10306 */ + { 0x0000, 0x0000, 0x0000 }, /* R10307 */ + { 0x0000, 0x0000, 0x0000 }, /* R10308 */ + { 0x0000, 0x0000, 0x0000 }, /* R10309 */ + { 0x0000, 0x0000, 0x0000 }, /* R10310 */ + { 0x0000, 0x0000, 0x0000 }, /* R10311 */ + { 0x0000, 0x0000, 0x0000 }, /* R10312 */ + { 0x0000, 0x0000, 0x0000 }, /* R10313 */ + { 0x0000, 0x0000, 0x0000 }, /* R10314 */ + { 0x0000, 0x0000, 0x0000 }, /* R10315 */ + { 0x0000, 0x0000, 0x0000 }, /* R10316 */ + { 0x0000, 0x0000, 0x0000 }, /* R10317 */ + { 0x0000, 0x0000, 0x0000 }, /* R10318 */ + { 0x0000, 0x0000, 0x0000 }, /* R10319 */ + { 0x0000, 0x0000, 0x0000 }, /* R10320 */ + { 0x0000, 0x0000, 0x0000 }, /* R10321 */ + { 0x0000, 0x0000, 0x0000 }, /* R10322 */ + { 0x0000, 0x0000, 0x0000 }, /* R10323 */ + { 0x0000, 0x0000, 0x0000 }, /* R10324 */ + { 0x0000, 0x0000, 0x0000 }, /* R10325 */ + { 0x0000, 0x0000, 0x0000 }, /* R10326 */ + { 0x0000, 0x0000, 0x0000 }, /* R10327 */ + { 0x0000, 0x0000, 0x0000 }, /* R10328 */ + { 0x0000, 0x0000, 0x0000 }, /* R10329 */ + { 0x0000, 0x0000, 0x0000 }, /* R10330 */ + { 0x0000, 0x0000, 0x0000 }, /* R10331 */ + { 0x0000, 0x0000, 0x0000 }, /* R10332 */ + { 0x0000, 0x0000, 0x0000 }, /* R10333 */ + { 0x0000, 0x0000, 0x0000 }, /* R10334 */ + { 0x0000, 0x0000, 0x0000 }, /* R10335 */ + { 0x0000, 0x0000, 0x0000 }, /* R10336 */ + { 0x0000, 0x0000, 0x0000 }, /* R10337 */ + { 0x0000, 0x0000, 0x0000 }, /* R10338 */ + { 0x0000, 0x0000, 0x0000 }, /* R10339 */ + { 0x0000, 0x0000, 0x0000 }, /* R10340 */ + { 0x0000, 0x0000, 0x0000 }, /* R10341 */ + { 0x0000, 0x0000, 0x0000 }, /* R10342 */ + { 0x0000, 0x0000, 0x0000 }, /* R10343 */ + { 0x0000, 0x0000, 0x0000 }, /* R10344 */ + { 0x0000, 0x0000, 0x0000 }, /* R10345 */ + { 0x0000, 0x0000, 0x0000 }, /* R10346 */ + { 0x0000, 0x0000, 0x0000 }, /* R10347 */ + { 0x0000, 0x0000, 0x0000 }, /* R10348 */ + { 0x0000, 0x0000, 0x0000 }, /* R10349 */ + { 0x0000, 0x0000, 0x0000 }, /* R10350 */ + { 0x0000, 0x0000, 0x0000 }, /* R10351 */ + { 0x0000, 0x0000, 0x0000 }, /* R10352 */ + { 0x0000, 0x0000, 0x0000 }, /* R10353 */ + { 0x0000, 0x0000, 0x0000 }, /* R10354 */ + { 0x0000, 0x0000, 0x0000 }, /* R10355 */ + { 0x0000, 0x0000, 0x0000 }, /* R10356 */ + { 0x0000, 0x0000, 0x0000 }, /* R10357 */ + { 0x0000, 0x0000, 0x0000 }, /* R10358 */ + { 0x0000, 0x0000, 0x0000 }, /* R10359 */ + { 0x0000, 0x0000, 0x0000 }, /* R10360 */ + { 0x0000, 0x0000, 0x0000 }, /* R10361 */ + { 0x0000, 0x0000, 0x0000 }, /* R10362 */ + { 0x0000, 0x0000, 0x0000 }, /* R10363 */ + { 0x0000, 0x0000, 0x0000 }, /* R10364 */ + { 0x0000, 0x0000, 0x0000 }, /* R10365 */ + { 0x0000, 0x0000, 0x0000 }, /* R10366 */ + { 0x0000, 0x0000, 0x0000 }, /* R10367 */ + { 0x0000, 0x0000, 0x0000 }, /* R10368 */ + { 0x0000, 0x0000, 0x0000 }, /* R10369 */ + { 0x0000, 0x0000, 0x0000 }, /* R10370 */ + { 0x0000, 0x0000, 0x0000 }, /* R10371 */ + { 0x0000, 0x0000, 0x0000 }, /* R10372 */ + { 0x0000, 0x0000, 0x0000 }, /* R10373 */ + { 0x0000, 0x0000, 0x0000 }, /* R10374 */ + { 0x0000, 0x0000, 0x0000 }, /* R10375 */ + { 0x0000, 0x0000, 0x0000 }, /* R10376 */ + { 0x0000, 0x0000, 0x0000 }, /* R10377 */ + { 0x0000, 0x0000, 0x0000 }, /* R10378 */ + { 0x0000, 0x0000, 0x0000 }, /* R10379 */ + { 0x0000, 0x0000, 0x0000 }, /* R10380 */ + { 0x0000, 0x0000, 0x0000 }, /* R10381 */ + { 0x0000, 0x0000, 0x0000 }, /* R10382 */ + { 0x0000, 0x0000, 0x0000 }, /* R10383 */ + { 0x0000, 0x0000, 0x0000 }, /* R10384 */ + { 0x0000, 0x0000, 0x0000 }, /* R10385 */ + { 0x0000, 0x0000, 0x0000 }, /* R10386 */ + { 0x0000, 0x0000, 0x0000 }, /* R10387 */ + { 0x0000, 0x0000, 0x0000 }, /* R10388 */ + { 0x0000, 0x0000, 0x0000 }, /* R10389 */ + { 0x0000, 0x0000, 0x0000 }, /* R10390 */ + { 0x0000, 0x0000, 0x0000 }, /* R10391 */ + { 0x0000, 0x0000, 0x0000 }, /* R10392 */ + { 0x0000, 0x0000, 0x0000 }, /* R10393 */ + { 0x0000, 0x0000, 0x0000 }, /* R10394 */ + { 0x0000, 0x0000, 0x0000 }, /* R10395 */ + { 0x0000, 0x0000, 0x0000 }, /* R10396 */ + { 0x0000, 0x0000, 0x0000 }, /* R10397 */ + { 0x0000, 0x0000, 0x0000 }, /* R10398 */ + { 0x0000, 0x0000, 0x0000 }, /* R10399 */ + { 0x0000, 0x0000, 0x0000 }, /* R10400 */ + { 0x0000, 0x0000, 0x0000 }, /* R10401 */ + { 0x0000, 0x0000, 0x0000 }, /* R10402 */ + { 0x0000, 0x0000, 0x0000 }, /* R10403 */ + { 0x0000, 0x0000, 0x0000 }, /* R10404 */ + { 0x0000, 0x0000, 0x0000 }, /* R10405 */ + { 0x0000, 0x0000, 0x0000 }, /* R10406 */ + { 0x0000, 0x0000, 0x0000 }, /* R10407 */ + { 0x0000, 0x0000, 0x0000 }, /* R10408 */ + { 0x0000, 0x0000, 0x0000 }, /* R10409 */ + { 0x0000, 0x0000, 0x0000 }, /* R10410 */ + { 0x0000, 0x0000, 0x0000 }, /* R10411 */ + { 0x0000, 0x0000, 0x0000 }, /* R10412 */ + { 0x0000, 0x0000, 0x0000 }, /* R10413 */ + { 0x0000, 0x0000, 0x0000 }, /* R10414 */ + { 0x0000, 0x0000, 0x0000 }, /* R10415 */ + { 0x0000, 0x0000, 0x0000 }, /* R10416 */ + { 0x0000, 0x0000, 0x0000 }, /* R10417 */ + { 0x0000, 0x0000, 0x0000 }, /* R10418 */ + { 0x0000, 0x0000, 0x0000 }, /* R10419 */ + { 0x0000, 0x0000, 0x0000 }, /* R10420 */ + { 0x0000, 0x0000, 0x0000 }, /* R10421 */ + { 0x0000, 0x0000, 0x0000 }, /* R10422 */ + { 0x0000, 0x0000, 0x0000 }, /* R10423 */ + { 0x0000, 0x0000, 0x0000 }, /* R10424 */ + { 0x0000, 0x0000, 0x0000 }, /* R10425 */ + { 0x0000, 0x0000, 0x0000 }, /* R10426 */ + { 0x0000, 0x0000, 0x0000 }, /* R10427 */ + { 0x0000, 0x0000, 0x0000 }, /* R10428 */ + { 0x0000, 0x0000, 0x0000 }, /* R10429 */ + { 0x0000, 0x0000, 0x0000 }, /* R10430 */ + { 0x0000, 0x0000, 0x0000 }, /* R10431 */ + { 0x0000, 0x0000, 0x0000 }, /* R10432 */ + { 0x0000, 0x0000, 0x0000 }, /* R10433 */ + { 0x0000, 0x0000, 0x0000 }, /* R10434 */ + { 0x0000, 0x0000, 0x0000 }, /* R10435 */ + { 0x0000, 0x0000, 0x0000 }, /* R10436 */ + { 0x0000, 0x0000, 0x0000 }, /* R10437 */ + { 0x0000, 0x0000, 0x0000 }, /* R10438 */ + { 0x0000, 0x0000, 0x0000 }, /* R10439 */ + { 0x0000, 0x0000, 0x0000 }, /* R10440 */ + { 0x0000, 0x0000, 0x0000 }, /* R10441 */ + { 0x0000, 0x0000, 0x0000 }, /* R10442 */ + { 0x0000, 0x0000, 0x0000 }, /* R10443 */ + { 0x0000, 0x0000, 0x0000 }, /* R10444 */ + { 0x0000, 0x0000, 0x0000 }, /* R10445 */ + { 0x0000, 0x0000, 0x0000 }, /* R10446 */ + { 0x0000, 0x0000, 0x0000 }, /* R10447 */ + { 0x0000, 0x0000, 0x0000 }, /* R10448 */ + { 0x0000, 0x0000, 0x0000 }, /* R10449 */ + { 0x0000, 0x0000, 0x0000 }, /* R10450 */ + { 0x0000, 0x0000, 0x0000 }, /* R10451 */ + { 0x0000, 0x0000, 0x0000 }, /* R10452 */ + { 0x0000, 0x0000, 0x0000 }, /* R10453 */ + { 0x0000, 0x0000, 0x0000 }, /* R10454 */ + { 0x0000, 0x0000, 0x0000 }, /* R10455 */ + { 0x0000, 0x0000, 0x0000 }, /* R10456 */ + { 0x0000, 0x0000, 0x0000 }, /* R10457 */ + { 0x0000, 0x0000, 0x0000 }, /* R10458 */ + { 0x0000, 0x0000, 0x0000 }, /* R10459 */ + { 0x0000, 0x0000, 0x0000 }, /* R10460 */ + { 0x0000, 0x0000, 0x0000 }, /* R10461 */ + { 0x0000, 0x0000, 0x0000 }, /* R10462 */ + { 0x0000, 0x0000, 0x0000 }, /* R10463 */ + { 0x0000, 0x0000, 0x0000 }, /* R10464 */ + { 0x0000, 0x0000, 0x0000 }, /* R10465 */ + { 0x0000, 0x0000, 0x0000 }, /* R10466 */ + { 0x0000, 0x0000, 0x0000 }, /* R10467 */ + { 0x0000, 0x0000, 0x0000 }, /* R10468 */ + { 0x0000, 0x0000, 0x0000 }, /* R10469 */ + { 0x0000, 0x0000, 0x0000 }, /* R10470 */ + { 0x0000, 0x0000, 0x0000 }, /* R10471 */ + { 0x0000, 0x0000, 0x0000 }, /* R10472 */ + { 0x0000, 0x0000, 0x0000 }, /* R10473 */ + { 0x0000, 0x0000, 0x0000 }, /* R10474 */ + { 0x0000, 0x0000, 0x0000 }, /* R10475 */ + { 0x0000, 0x0000, 0x0000 }, /* R10476 */ + { 0x0000, 0x0000, 0x0000 }, /* R10477 */ + { 0x0000, 0x0000, 0x0000 }, /* R10478 */ + { 0x0000, 0x0000, 0x0000 }, /* R10479 */ + { 0x0000, 0x0000, 0x0000 }, /* R10480 */ + { 0x0000, 0x0000, 0x0000 }, /* R10481 */ + { 0x0000, 0x0000, 0x0000 }, /* R10482 */ + { 0x0000, 0x0000, 0x0000 }, /* R10483 */ + { 0x0000, 0x0000, 0x0000 }, /* R10484 */ + { 0x0000, 0x0000, 0x0000 }, /* R10485 */ + { 0x0000, 0x0000, 0x0000 }, /* R10486 */ + { 0x0000, 0x0000, 0x0000 }, /* R10487 */ + { 0x0000, 0x0000, 0x0000 }, /* R10488 */ + { 0x0000, 0x0000, 0x0000 }, /* R10489 */ + { 0x0000, 0x0000, 0x0000 }, /* R10490 */ + { 0x0000, 0x0000, 0x0000 }, /* R10491 */ + { 0x0000, 0x0000, 0x0000 }, /* R10492 */ + { 0x0000, 0x0000, 0x0000 }, /* R10493 */ + { 0x0000, 0x0000, 0x0000 }, /* R10494 */ + { 0x0000, 0x0000, 0x0000 }, /* R10495 */ + { 0x0000, 0x0000, 0x0000 }, /* R10496 */ + { 0x0000, 0x0000, 0x0000 }, /* R10497 */ + { 0x0000, 0x0000, 0x0000 }, /* R10498 */ + { 0x0000, 0x0000, 0x0000 }, /* R10499 */ + { 0x0000, 0x0000, 0x0000 }, /* R10500 */ + { 0x0000, 0x0000, 0x0000 }, /* R10501 */ + { 0x0000, 0x0000, 0x0000 }, /* R10502 */ + { 0x0000, 0x0000, 0x0000 }, /* R10503 */ + { 0x0000, 0x0000, 0x0000 }, /* R10504 */ + { 0x0000, 0x0000, 0x0000 }, /* R10505 */ + { 0x0000, 0x0000, 0x0000 }, /* R10506 */ + { 0x0000, 0x0000, 0x0000 }, /* R10507 */ + { 0x0000, 0x0000, 0x0000 }, /* R10508 */ + { 0x0000, 0x0000, 0x0000 }, /* R10509 */ + { 0x0000, 0x0000, 0x0000 }, /* R10510 */ + { 0x0000, 0x0000, 0x0000 }, /* R10511 */ + { 0x0000, 0x0000, 0x0000 }, /* R10512 */ + { 0x0000, 0x0000, 0x0000 }, /* R10513 */ + { 0x0000, 0x0000, 0x0000 }, /* R10514 */ + { 0x0000, 0x0000, 0x0000 }, /* R10515 */ + { 0x0000, 0x0000, 0x0000 }, /* R10516 */ + { 0x0000, 0x0000, 0x0000 }, /* R10517 */ + { 0x0000, 0x0000, 0x0000 }, /* R10518 */ + { 0x0000, 0x0000, 0x0000 }, /* R10519 */ + { 0x0000, 0x0000, 0x0000 }, /* R10520 */ + { 0x0000, 0x0000, 0x0000 }, /* R10521 */ + { 0x0000, 0x0000, 0x0000 }, /* R10522 */ + { 0x0000, 0x0000, 0x0000 }, /* R10523 */ + { 0x0000, 0x0000, 0x0000 }, /* R10524 */ + { 0x0000, 0x0000, 0x0000 }, /* R10525 */ + { 0x0000, 0x0000, 0x0000 }, /* R10526 */ + { 0x0000, 0x0000, 0x0000 }, /* R10527 */ + { 0x0000, 0x0000, 0x0000 }, /* R10528 */ + { 0x0000, 0x0000, 0x0000 }, /* R10529 */ + { 0x0000, 0x0000, 0x0000 }, /* R10530 */ + { 0x0000, 0x0000, 0x0000 }, /* R10531 */ + { 0x0000, 0x0000, 0x0000 }, /* R10532 */ + { 0x0000, 0x0000, 0x0000 }, /* R10533 */ + { 0x0000, 0x0000, 0x0000 }, /* R10534 */ + { 0x0000, 0x0000, 0x0000 }, /* R10535 */ + { 0x0000, 0x0000, 0x0000 }, /* R10536 */ + { 0x0000, 0x0000, 0x0000 }, /* R10537 */ + { 0x0000, 0x0000, 0x0000 }, /* R10538 */ + { 0x0000, 0x0000, 0x0000 }, /* R10539 */ + { 0x0000, 0x0000, 0x0000 }, /* R10540 */ + { 0x0000, 0x0000, 0x0000 }, /* R10541 */ + { 0x0000, 0x0000, 0x0000 }, /* R10542 */ + { 0x0000, 0x0000, 0x0000 }, /* R10543 */ + { 0x0000, 0x0000, 0x0000 }, /* R10544 */ + { 0x0000, 0x0000, 0x0000 }, /* R10545 */ + { 0x0000, 0x0000, 0x0000 }, /* R10546 */ + { 0x0000, 0x0000, 0x0000 }, /* R10547 */ + { 0x0000, 0x0000, 0x0000 }, /* R10548 */ + { 0x0000, 0x0000, 0x0000 }, /* R10549 */ + { 0x0000, 0x0000, 0x0000 }, /* R10550 */ + { 0x0000, 0x0000, 0x0000 }, /* R10551 */ + { 0x0000, 0x0000, 0x0000 }, /* R10552 */ + { 0x0000, 0x0000, 0x0000 }, /* R10553 */ + { 0x0000, 0x0000, 0x0000 }, /* R10554 */ + { 0x0000, 0x0000, 0x0000 }, /* R10555 */ + { 0x0000, 0x0000, 0x0000 }, /* R10556 */ + { 0x0000, 0x0000, 0x0000 }, /* R10557 */ + { 0x0000, 0x0000, 0x0000 }, /* R10558 */ + { 0x0000, 0x0000, 0x0000 }, /* R10559 */ + { 0x0000, 0x0000, 0x0000 }, /* R10560 */ + { 0x0000, 0x0000, 0x0000 }, /* R10561 */ + { 0x0000, 0x0000, 0x0000 }, /* R10562 */ + { 0x0000, 0x0000, 0x0000 }, /* R10563 */ + { 0x0000, 0x0000, 0x0000 }, /* R10564 */ + { 0x0000, 0x0000, 0x0000 }, /* R10565 */ + { 0x0000, 0x0000, 0x0000 }, /* R10566 */ + { 0x0000, 0x0000, 0x0000 }, /* R10567 */ + { 0x0000, 0x0000, 0x0000 }, /* R10568 */ + { 0x0000, 0x0000, 0x0000 }, /* R10569 */ + { 0x0000, 0x0000, 0x0000 }, /* R10570 */ + { 0x0000, 0x0000, 0x0000 }, /* R10571 */ + { 0x0000, 0x0000, 0x0000 }, /* R10572 */ + { 0x0000, 0x0000, 0x0000 }, /* R10573 */ + { 0x0000, 0x0000, 0x0000 }, /* R10574 */ + { 0x0000, 0x0000, 0x0000 }, /* R10575 */ + { 0x0000, 0x0000, 0x0000 }, /* R10576 */ + { 0x0000, 0x0000, 0x0000 }, /* R10577 */ + { 0x0000, 0x0000, 0x0000 }, /* R10578 */ + { 0x0000, 0x0000, 0x0000 }, /* R10579 */ + { 0x0000, 0x0000, 0x0000 }, /* R10580 */ + { 0x0000, 0x0000, 0x0000 }, /* R10581 */ + { 0x0000, 0x0000, 0x0000 }, /* R10582 */ + { 0x0000, 0x0000, 0x0000 }, /* R10583 */ + { 0x0000, 0x0000, 0x0000 }, /* R10584 */ + { 0x0000, 0x0000, 0x0000 }, /* R10585 */ + { 0x0000, 0x0000, 0x0000 }, /* R10586 */ + { 0x0000, 0x0000, 0x0000 }, /* R10587 */ + { 0x0000, 0x0000, 0x0000 }, /* R10588 */ + { 0x0000, 0x0000, 0x0000 }, /* R10589 */ + { 0x0000, 0x0000, 0x0000 }, /* R10590 */ + { 0x0000, 0x0000, 0x0000 }, /* R10591 */ + { 0x0000, 0x0000, 0x0000 }, /* R10592 */ + { 0x0000, 0x0000, 0x0000 }, /* R10593 */ + { 0x0000, 0x0000, 0x0000 }, /* R10594 */ + { 0x0000, 0x0000, 0x0000 }, /* R10595 */ + { 0x0000, 0x0000, 0x0000 }, /* R10596 */ + { 0x0000, 0x0000, 0x0000 }, /* R10597 */ + { 0x0000, 0x0000, 0x0000 }, /* R10598 */ + { 0x0000, 0x0000, 0x0000 }, /* R10599 */ + { 0x0000, 0x0000, 0x0000 }, /* R10600 */ + { 0x0000, 0x0000, 0x0000 }, /* R10601 */ + { 0x0000, 0x0000, 0x0000 }, /* R10602 */ + { 0x0000, 0x0000, 0x0000 }, /* R10603 */ + { 0x0000, 0x0000, 0x0000 }, /* R10604 */ + { 0x0000, 0x0000, 0x0000 }, /* R10605 */ + { 0x0000, 0x0000, 0x0000 }, /* R10606 */ + { 0x0000, 0x0000, 0x0000 }, /* R10607 */ + { 0x0000, 0x0000, 0x0000 }, /* R10608 */ + { 0x0000, 0x0000, 0x0000 }, /* R10609 */ + { 0x0000, 0x0000, 0x0000 }, /* R10610 */ + { 0x0000, 0x0000, 0x0000 }, /* R10611 */ + { 0x0000, 0x0000, 0x0000 }, /* R10612 */ + { 0x0000, 0x0000, 0x0000 }, /* R10613 */ + { 0x0000, 0x0000, 0x0000 }, /* R10614 */ + { 0x0000, 0x0000, 0x0000 }, /* R10615 */ + { 0x0000, 0x0000, 0x0000 }, /* R10616 */ + { 0x0000, 0x0000, 0x0000 }, /* R10617 */ + { 0x0000, 0x0000, 0x0000 }, /* R10618 */ + { 0x0000, 0x0000, 0x0000 }, /* R10619 */ + { 0x0000, 0x0000, 0x0000 }, /* R10620 */ + { 0x0000, 0x0000, 0x0000 }, /* R10621 */ + { 0x0000, 0x0000, 0x0000 }, /* R10622 */ + { 0x0000, 0x0000, 0x0000 }, /* R10623 */ + { 0x0000, 0x0000, 0x0000 }, /* R10624 */ + { 0x0000, 0x0000, 0x0000 }, /* R10625 */ + { 0x0000, 0x0000, 0x0000 }, /* R10626 */ + { 0x0000, 0x0000, 0x0000 }, /* R10627 */ + { 0x0000, 0x0000, 0x0000 }, /* R10628 */ + { 0x0000, 0x0000, 0x0000 }, /* R10629 */ + { 0x0000, 0x0000, 0x0000 }, /* R10630 */ + { 0x0000, 0x0000, 0x0000 }, /* R10631 */ + { 0x0000, 0x0000, 0x0000 }, /* R10632 */ + { 0x0000, 0x0000, 0x0000 }, /* R10633 */ + { 0x0000, 0x0000, 0x0000 }, /* R10634 */ + { 0x0000, 0x0000, 0x0000 }, /* R10635 */ + { 0x0000, 0x0000, 0x0000 }, /* R10636 */ + { 0x0000, 0x0000, 0x0000 }, /* R10637 */ + { 0x0000, 0x0000, 0x0000 }, /* R10638 */ + { 0x0000, 0x0000, 0x0000 }, /* R10639 */ + { 0x0000, 0x0000, 0x0000 }, /* R10640 */ + { 0x0000, 0x0000, 0x0000 }, /* R10641 */ + { 0x0000, 0x0000, 0x0000 }, /* R10642 */ + { 0x0000, 0x0000, 0x0000 }, /* R10643 */ + { 0x0000, 0x0000, 0x0000 }, /* R10644 */ + { 0x0000, 0x0000, 0x0000 }, /* R10645 */ + { 0x0000, 0x0000, 0x0000 }, /* R10646 */ + { 0x0000, 0x0000, 0x0000 }, /* R10647 */ + { 0x0000, 0x0000, 0x0000 }, /* R10648 */ + { 0x0000, 0x0000, 0x0000 }, /* R10649 */ + { 0x0000, 0x0000, 0x0000 }, /* R10650 */ + { 0x0000, 0x0000, 0x0000 }, /* R10651 */ + { 0x0000, 0x0000, 0x0000 }, /* R10652 */ + { 0x0000, 0x0000, 0x0000 }, /* R10653 */ + { 0x0000, 0x0000, 0x0000 }, /* R10654 */ + { 0x0000, 0x0000, 0x0000 }, /* R10655 */ + { 0x0000, 0x0000, 0x0000 }, /* R10656 */ + { 0x0000, 0x0000, 0x0000 }, /* R10657 */ + { 0x0000, 0x0000, 0x0000 }, /* R10658 */ + { 0x0000, 0x0000, 0x0000 }, /* R10659 */ + { 0x0000, 0x0000, 0x0000 }, /* R10660 */ + { 0x0000, 0x0000, 0x0000 }, /* R10661 */ + { 0x0000, 0x0000, 0x0000 }, /* R10662 */ + { 0x0000, 0x0000, 0x0000 }, /* R10663 */ + { 0x0000, 0x0000, 0x0000 }, /* R10664 */ + { 0x0000, 0x0000, 0x0000 }, /* R10665 */ + { 0x0000, 0x0000, 0x0000 }, /* R10666 */ + { 0x0000, 0x0000, 0x0000 }, /* R10667 */ + { 0x0000, 0x0000, 0x0000 }, /* R10668 */ + { 0x0000, 0x0000, 0x0000 }, /* R10669 */ + { 0x0000, 0x0000, 0x0000 }, /* R10670 */ + { 0x0000, 0x0000, 0x0000 }, /* R10671 */ + { 0x0000, 0x0000, 0x0000 }, /* R10672 */ + { 0x0000, 0x0000, 0x0000 }, /* R10673 */ + { 0x0000, 0x0000, 0x0000 }, /* R10674 */ + { 0x0000, 0x0000, 0x0000 }, /* R10675 */ + { 0x0000, 0x0000, 0x0000 }, /* R10676 */ + { 0x0000, 0x0000, 0x0000 }, /* R10677 */ + { 0x0000, 0x0000, 0x0000 }, /* R10678 */ + { 0x0000, 0x0000, 0x0000 }, /* R10679 */ + { 0x0000, 0x0000, 0x0000 }, /* R10680 */ + { 0x0000, 0x0000, 0x0000 }, /* R10681 */ + { 0x0000, 0x0000, 0x0000 }, /* R10682 */ + { 0x0000, 0x0000, 0x0000 }, /* R10683 */ + { 0x0000, 0x0000, 0x0000 }, /* R10684 */ + { 0x0000, 0x0000, 0x0000 }, /* R10685 */ + { 0x0000, 0x0000, 0x0000 }, /* R10686 */ + { 0x0000, 0x0000, 0x0000 }, /* R10687 */ + { 0x0000, 0x0000, 0x0000 }, /* R10688 */ + { 0x0000, 0x0000, 0x0000 }, /* R10689 */ + { 0x0000, 0x0000, 0x0000 }, /* R10690 */ + { 0x0000, 0x0000, 0x0000 }, /* R10691 */ + { 0x0000, 0x0000, 0x0000 }, /* R10692 */ + { 0x0000, 0x0000, 0x0000 }, /* R10693 */ + { 0x0000, 0x0000, 0x0000 }, /* R10694 */ + { 0x0000, 0x0000, 0x0000 }, /* R10695 */ + { 0x0000, 0x0000, 0x0000 }, /* R10696 */ + { 0x0000, 0x0000, 0x0000 }, /* R10697 */ + { 0x0000, 0x0000, 0x0000 }, /* R10698 */ + { 0x0000, 0x0000, 0x0000 }, /* R10699 */ + { 0x0000, 0x0000, 0x0000 }, /* R10700 */ + { 0x0000, 0x0000, 0x0000 }, /* R10701 */ + { 0x0000, 0x0000, 0x0000 }, /* R10702 */ + { 0x0000, 0x0000, 0x0000 }, /* R10703 */ + { 0x0000, 0x0000, 0x0000 }, /* R10704 */ + { 0x0000, 0x0000, 0x0000 }, /* R10705 */ + { 0x0000, 0x0000, 0x0000 }, /* R10706 */ + { 0x0000, 0x0000, 0x0000 }, /* R10707 */ + { 0x0000, 0x0000, 0x0000 }, /* R10708 */ + { 0x0000, 0x0000, 0x0000 }, /* R10709 */ + { 0x0000, 0x0000, 0x0000 }, /* R10710 */ + { 0x0000, 0x0000, 0x0000 }, /* R10711 */ + { 0x0000, 0x0000, 0x0000 }, /* R10712 */ + { 0x0000, 0x0000, 0x0000 }, /* R10713 */ + { 0x0000, 0x0000, 0x0000 }, /* R10714 */ + { 0x0000, 0x0000, 0x0000 }, /* R10715 */ + { 0x0000, 0x0000, 0x0000 }, /* R10716 */ + { 0x0000, 0x0000, 0x0000 }, /* R10717 */ + { 0x0000, 0x0000, 0x0000 }, /* R10718 */ + { 0x0000, 0x0000, 0x0000 }, /* R10719 */ + { 0x0000, 0x0000, 0x0000 }, /* R10720 */ + { 0x0000, 0x0000, 0x0000 }, /* R10721 */ + { 0x0000, 0x0000, 0x0000 }, /* R10722 */ + { 0x0000, 0x0000, 0x0000 }, /* R10723 */ + { 0x0000, 0x0000, 0x0000 }, /* R10724 */ + { 0x0000, 0x0000, 0x0000 }, /* R10725 */ + { 0x0000, 0x0000, 0x0000 }, /* R10726 */ + { 0x0000, 0x0000, 0x0000 }, /* R10727 */ + { 0x0000, 0x0000, 0x0000 }, /* R10728 */ + { 0x0000, 0x0000, 0x0000 }, /* R10729 */ + { 0x0000, 0x0000, 0x0000 }, /* R10730 */ + { 0x0000, 0x0000, 0x0000 }, /* R10731 */ + { 0x0000, 0x0000, 0x0000 }, /* R10732 */ + { 0x0000, 0x0000, 0x0000 }, /* R10733 */ + { 0x0000, 0x0000, 0x0000 }, /* R10734 */ + { 0x0000, 0x0000, 0x0000 }, /* R10735 */ + { 0x0000, 0x0000, 0x0000 }, /* R10736 */ + { 0x0000, 0x0000, 0x0000 }, /* R10737 */ + { 0x0000, 0x0000, 0x0000 }, /* R10738 */ + { 0x0000, 0x0000, 0x0000 }, /* R10739 */ + { 0x0000, 0x0000, 0x0000 }, /* R10740 */ + { 0x0000, 0x0000, 0x0000 }, /* R10741 */ + { 0x0000, 0x0000, 0x0000 }, /* R10742 */ + { 0x0000, 0x0000, 0x0000 }, /* R10743 */ + { 0x0000, 0x0000, 0x0000 }, /* R10744 */ + { 0x0000, 0x0000, 0x0000 }, /* R10745 */ + { 0x0000, 0x0000, 0x0000 }, /* R10746 */ + { 0x0000, 0x0000, 0x0000 }, /* R10747 */ + { 0x0000, 0x0000, 0x0000 }, /* R10748 */ + { 0x0000, 0x0000, 0x0000 }, /* R10749 */ + { 0x0000, 0x0000, 0x0000 }, /* R10750 */ + { 0x0000, 0x0000, 0x0000 }, /* R10751 */ + { 0x0000, 0x0000, 0x0000 }, /* R10752 */ + { 0x0000, 0x0000, 0x0000 }, /* R10753 */ + { 0x0000, 0x0000, 0x0000 }, /* R10754 */ + { 0x0000, 0x0000, 0x0000 }, /* R10755 */ + { 0x0000, 0x0000, 0x0000 }, /* R10756 */ + { 0x0000, 0x0000, 0x0000 }, /* R10757 */ + { 0x0000, 0x0000, 0x0000 }, /* R10758 */ + { 0x0000, 0x0000, 0x0000 }, /* R10759 */ + { 0x0000, 0x0000, 0x0000 }, /* R10760 */ + { 0x0000, 0x0000, 0x0000 }, /* R10761 */ + { 0x0000, 0x0000, 0x0000 }, /* R10762 */ + { 0x0000, 0x0000, 0x0000 }, /* R10763 */ + { 0x0000, 0x0000, 0x0000 }, /* R10764 */ + { 0x0000, 0x0000, 0x0000 }, /* R10765 */ + { 0x0000, 0x0000, 0x0000 }, /* R10766 */ + { 0x0000, 0x0000, 0x0000 }, /* R10767 */ + { 0x0000, 0x0000, 0x0000 }, /* R10768 */ + { 0x0000, 0x0000, 0x0000 }, /* R10769 */ + { 0x0000, 0x0000, 0x0000 }, /* R10770 */ + { 0x0000, 0x0000, 0x0000 }, /* R10771 */ + { 0x0000, 0x0000, 0x0000 }, /* R10772 */ + { 0x0000, 0x0000, 0x0000 }, /* R10773 */ + { 0x0000, 0x0000, 0x0000 }, /* R10774 */ + { 0x0000, 0x0000, 0x0000 }, /* R10775 */ + { 0x0000, 0x0000, 0x0000 }, /* R10776 */ + { 0x0000, 0x0000, 0x0000 }, /* R10777 */ + { 0x0000, 0x0000, 0x0000 }, /* R10778 */ + { 0x0000, 0x0000, 0x0000 }, /* R10779 */ + { 0x0000, 0x0000, 0x0000 }, /* R10780 */ + { 0x0000, 0x0000, 0x0000 }, /* R10781 */ + { 0x0000, 0x0000, 0x0000 }, /* R10782 */ + { 0x0000, 0x0000, 0x0000 }, /* R10783 */ + { 0x0000, 0x0000, 0x0000 }, /* R10784 */ + { 0x0000, 0x0000, 0x0000 }, /* R10785 */ + { 0x0000, 0x0000, 0x0000 }, /* R10786 */ + { 0x0000, 0x0000, 0x0000 }, /* R10787 */ + { 0x0000, 0x0000, 0x0000 }, /* R10788 */ + { 0x0000, 0x0000, 0x0000 }, /* R10789 */ + { 0x0000, 0x0000, 0x0000 }, /* R10790 */ + { 0x0000, 0x0000, 0x0000 }, /* R10791 */ + { 0x0000, 0x0000, 0x0000 }, /* R10792 */ + { 0x0000, 0x0000, 0x0000 }, /* R10793 */ + { 0x0000, 0x0000, 0x0000 }, /* R10794 */ + { 0x0000, 0x0000, 0x0000 }, /* R10795 */ + { 0x0000, 0x0000, 0x0000 }, /* R10796 */ + { 0x0000, 0x0000, 0x0000 }, /* R10797 */ + { 0x0000, 0x0000, 0x0000 }, /* R10798 */ + { 0x0000, 0x0000, 0x0000 }, /* R10799 */ + { 0x0000, 0x0000, 0x0000 }, /* R10800 */ + { 0x0000, 0x0000, 0x0000 }, /* R10801 */ + { 0x0000, 0x0000, 0x0000 }, /* R10802 */ + { 0x0000, 0x0000, 0x0000 }, /* R10803 */ + { 0x0000, 0x0000, 0x0000 }, /* R10804 */ + { 0x0000, 0x0000, 0x0000 }, /* R10805 */ + { 0x0000, 0x0000, 0x0000 }, /* R10806 */ + { 0x0000, 0x0000, 0x0000 }, /* R10807 */ + { 0x0000, 0x0000, 0x0000 }, /* R10808 */ + { 0x0000, 0x0000, 0x0000 }, /* R10809 */ + { 0x0000, 0x0000, 0x0000 }, /* R10810 */ + { 0x0000, 0x0000, 0x0000 }, /* R10811 */ + { 0x0000, 0x0000, 0x0000 }, /* R10812 */ + { 0x0000, 0x0000, 0x0000 }, /* R10813 */ + { 0x0000, 0x0000, 0x0000 }, /* R10814 */ + { 0x0000, 0x0000, 0x0000 }, /* R10815 */ + { 0x0000, 0x0000, 0x0000 }, /* R10816 */ + { 0x0000, 0x0000, 0x0000 }, /* R10817 */ + { 0x0000, 0x0000, 0x0000 }, /* R10818 */ + { 0x0000, 0x0000, 0x0000 }, /* R10819 */ + { 0x0000, 0x0000, 0x0000 }, /* R10820 */ + { 0x0000, 0x0000, 0x0000 }, /* R10821 */ + { 0x0000, 0x0000, 0x0000 }, /* R10822 */ + { 0x0000, 0x0000, 0x0000 }, /* R10823 */ + { 0x0000, 0x0000, 0x0000 }, /* R10824 */ + { 0x0000, 0x0000, 0x0000 }, /* R10825 */ + { 0x0000, 0x0000, 0x0000 }, /* R10826 */ + { 0x0000, 0x0000, 0x0000 }, /* R10827 */ + { 0x0000, 0x0000, 0x0000 }, /* R10828 */ + { 0x0000, 0x0000, 0x0000 }, /* R10829 */ + { 0x0000, 0x0000, 0x0000 }, /* R10830 */ + { 0x0000, 0x0000, 0x0000 }, /* R10831 */ + { 0x0000, 0x0000, 0x0000 }, /* R10832 */ + { 0x0000, 0x0000, 0x0000 }, /* R10833 */ + { 0x0000, 0x0000, 0x0000 }, /* R10834 */ + { 0x0000, 0x0000, 0x0000 }, /* R10835 */ + { 0x0000, 0x0000, 0x0000 }, /* R10836 */ + { 0x0000, 0x0000, 0x0000 }, /* R10837 */ + { 0x0000, 0x0000, 0x0000 }, /* R10838 */ + { 0x0000, 0x0000, 0x0000 }, /* R10839 */ + { 0x0000, 0x0000, 0x0000 }, /* R10840 */ + { 0x0000, 0x0000, 0x0000 }, /* R10841 */ + { 0x0000, 0x0000, 0x0000 }, /* R10842 */ + { 0x0000, 0x0000, 0x0000 }, /* R10843 */ + { 0x0000, 0x0000, 0x0000 }, /* R10844 */ + { 0x0000, 0x0000, 0x0000 }, /* R10845 */ + { 0x0000, 0x0000, 0x0000 }, /* R10846 */ + { 0x0000, 0x0000, 0x0000 }, /* R10847 */ + { 0x0000, 0x0000, 0x0000 }, /* R10848 */ + { 0x0000, 0x0000, 0x0000 }, /* R10849 */ + { 0x0000, 0x0000, 0x0000 }, /* R10850 */ + { 0x0000, 0x0000, 0x0000 }, /* R10851 */ + { 0x0000, 0x0000, 0x0000 }, /* R10852 */ + { 0x0000, 0x0000, 0x0000 }, /* R10853 */ + { 0x0000, 0x0000, 0x0000 }, /* R10854 */ + { 0x0000, 0x0000, 0x0000 }, /* R10855 */ + { 0x0000, 0x0000, 0x0000 }, /* R10856 */ + { 0x0000, 0x0000, 0x0000 }, /* R10857 */ + { 0x0000, 0x0000, 0x0000 }, /* R10858 */ + { 0x0000, 0x0000, 0x0000 }, /* R10859 */ + { 0x0000, 0x0000, 0x0000 }, /* R10860 */ + { 0x0000, 0x0000, 0x0000 }, /* R10861 */ + { 0x0000, 0x0000, 0x0000 }, /* R10862 */ + { 0x0000, 0x0000, 0x0000 }, /* R10863 */ + { 0x0000, 0x0000, 0x0000 }, /* R10864 */ + { 0x0000, 0x0000, 0x0000 }, /* R10865 */ + { 0x0000, 0x0000, 0x0000 }, /* R10866 */ + { 0x0000, 0x0000, 0x0000 }, /* R10867 */ + { 0x0000, 0x0000, 0x0000 }, /* R10868 */ + { 0x0000, 0x0000, 0x0000 }, /* R10869 */ + { 0x0000, 0x0000, 0x0000 }, /* R10870 */ + { 0x0000, 0x0000, 0x0000 }, /* R10871 */ + { 0x0000, 0x0000, 0x0000 }, /* R10872 */ + { 0x0000, 0x0000, 0x0000 }, /* R10873 */ + { 0x0000, 0x0000, 0x0000 }, /* R10874 */ + { 0x0000, 0x0000, 0x0000 }, /* R10875 */ + { 0x0000, 0x0000, 0x0000 }, /* R10876 */ + { 0x0000, 0x0000, 0x0000 }, /* R10877 */ + { 0x0000, 0x0000, 0x0000 }, /* R10878 */ + { 0x0000, 0x0000, 0x0000 }, /* R10879 */ + { 0x0000, 0x0000, 0x0000 }, /* R10880 */ + { 0x0000, 0x0000, 0x0000 }, /* R10881 */ + { 0x0000, 0x0000, 0x0000 }, /* R10882 */ + { 0x0000, 0x0000, 0x0000 }, /* R10883 */ + { 0x0000, 0x0000, 0x0000 }, /* R10884 */ + { 0x0000, 0x0000, 0x0000 }, /* R10885 */ + { 0x0000, 0x0000, 0x0000 }, /* R10886 */ + { 0x0000, 0x0000, 0x0000 }, /* R10887 */ + { 0x0000, 0x0000, 0x0000 }, /* R10888 */ + { 0x0000, 0x0000, 0x0000 }, /* R10889 */ + { 0x0000, 0x0000, 0x0000 }, /* R10890 */ + { 0x0000, 0x0000, 0x0000 }, /* R10891 */ + { 0x0000, 0x0000, 0x0000 }, /* R10892 */ + { 0x0000, 0x0000, 0x0000 }, /* R10893 */ + { 0x0000, 0x0000, 0x0000 }, /* R10894 */ + { 0x0000, 0x0000, 0x0000 }, /* R10895 */ + { 0x0000, 0x0000, 0x0000 }, /* R10896 */ + { 0x0000, 0x0000, 0x0000 }, /* R10897 */ + { 0x0000, 0x0000, 0x0000 }, /* R10898 */ + { 0x0000, 0x0000, 0x0000 }, /* R10899 */ + { 0x0000, 0x0000, 0x0000 }, /* R10900 */ + { 0x0000, 0x0000, 0x0000 }, /* R10901 */ + { 0x0000, 0x0000, 0x0000 }, /* R10902 */ + { 0x0000, 0x0000, 0x0000 }, /* R10903 */ + { 0x0000, 0x0000, 0x0000 }, /* R10904 */ + { 0x0000, 0x0000, 0x0000 }, /* R10905 */ + { 0x0000, 0x0000, 0x0000 }, /* R10906 */ + { 0x0000, 0x0000, 0x0000 }, /* R10907 */ + { 0x0000, 0x0000, 0x0000 }, /* R10908 */ + { 0x0000, 0x0000, 0x0000 }, /* R10909 */ + { 0x0000, 0x0000, 0x0000 }, /* R10910 */ + { 0x0000, 0x0000, 0x0000 }, /* R10911 */ + { 0x0000, 0x0000, 0x0000 }, /* R10912 */ + { 0x0000, 0x0000, 0x0000 }, /* R10913 */ + { 0x0000, 0x0000, 0x0000 }, /* R10914 */ + { 0x0000, 0x0000, 0x0000 }, /* R10915 */ + { 0x0000, 0x0000, 0x0000 }, /* R10916 */ + { 0x0000, 0x0000, 0x0000 }, /* R10917 */ + { 0x0000, 0x0000, 0x0000 }, /* R10918 */ + { 0x0000, 0x0000, 0x0000 }, /* R10919 */ + { 0x0000, 0x0000, 0x0000 }, /* R10920 */ + { 0x0000, 0x0000, 0x0000 }, /* R10921 */ + { 0x0000, 0x0000, 0x0000 }, /* R10922 */ + { 0x0000, 0x0000, 0x0000 }, /* R10923 */ + { 0x0000, 0x0000, 0x0000 }, /* R10924 */ + { 0x0000, 0x0000, 0x0000 }, /* R10925 */ + { 0x0000, 0x0000, 0x0000 }, /* R10926 */ + { 0x0000, 0x0000, 0x0000 }, /* R10927 */ + { 0x0000, 0x0000, 0x0000 }, /* R10928 */ + { 0x0000, 0x0000, 0x0000 }, /* R10929 */ + { 0x0000, 0x0000, 0x0000 }, /* R10930 */ + { 0x0000, 0x0000, 0x0000 }, /* R10931 */ + { 0x0000, 0x0000, 0x0000 }, /* R10932 */ + { 0x0000, 0x0000, 0x0000 }, /* R10933 */ + { 0x0000, 0x0000, 0x0000 }, /* R10934 */ + { 0x0000, 0x0000, 0x0000 }, /* R10935 */ + { 0x0000, 0x0000, 0x0000 }, /* R10936 */ + { 0x0000, 0x0000, 0x0000 }, /* R10937 */ + { 0x0000, 0x0000, 0x0000 }, /* R10938 */ + { 0x0000, 0x0000, 0x0000 }, /* R10939 */ + { 0x0000, 0x0000, 0x0000 }, /* R10940 */ + { 0x0000, 0x0000, 0x0000 }, /* R10941 */ + { 0x0000, 0x0000, 0x0000 }, /* R10942 */ + { 0x0000, 0x0000, 0x0000 }, /* R10943 */ + { 0x0000, 0x0000, 0x0000 }, /* R10944 */ + { 0x0000, 0x0000, 0x0000 }, /* R10945 */ + { 0x0000, 0x0000, 0x0000 }, /* R10946 */ + { 0x0000, 0x0000, 0x0000 }, /* R10947 */ + { 0x0000, 0x0000, 0x0000 }, /* R10948 */ + { 0x0000, 0x0000, 0x0000 }, /* R10949 */ + { 0x0000, 0x0000, 0x0000 }, /* R10950 */ + { 0x0000, 0x0000, 0x0000 }, /* R10951 */ + { 0x0000, 0x0000, 0x0000 }, /* R10952 */ + { 0x0000, 0x0000, 0x0000 }, /* R10953 */ + { 0x0000, 0x0000, 0x0000 }, /* R10954 */ + { 0x0000, 0x0000, 0x0000 }, /* R10955 */ + { 0x0000, 0x0000, 0x0000 }, /* R10956 */ + { 0x0000, 0x0000, 0x0000 }, /* R10957 */ + { 0x0000, 0x0000, 0x0000 }, /* R10958 */ + { 0x0000, 0x0000, 0x0000 }, /* R10959 */ + { 0x0000, 0x0000, 0x0000 }, /* R10960 */ + { 0x0000, 0x0000, 0x0000 }, /* R10961 */ + { 0x0000, 0x0000, 0x0000 }, /* R10962 */ + { 0x0000, 0x0000, 0x0000 }, /* R10963 */ + { 0x0000, 0x0000, 0x0000 }, /* R10964 */ + { 0x0000, 0x0000, 0x0000 }, /* R10965 */ + { 0x0000, 0x0000, 0x0000 }, /* R10966 */ + { 0x0000, 0x0000, 0x0000 }, /* R10967 */ + { 0x0000, 0x0000, 0x0000 }, /* R10968 */ + { 0x0000, 0x0000, 0x0000 }, /* R10969 */ + { 0x0000, 0x0000, 0x0000 }, /* R10970 */ + { 0x0000, 0x0000, 0x0000 }, /* R10971 */ + { 0x0000, 0x0000, 0x0000 }, /* R10972 */ + { 0x0000, 0x0000, 0x0000 }, /* R10973 */ + { 0x0000, 0x0000, 0x0000 }, /* R10974 */ + { 0x0000, 0x0000, 0x0000 }, /* R10975 */ + { 0x0000, 0x0000, 0x0000 }, /* R10976 */ + { 0x0000, 0x0000, 0x0000 }, /* R10977 */ + { 0x0000, 0x0000, 0x0000 }, /* R10978 */ + { 0x0000, 0x0000, 0x0000 }, /* R10979 */ + { 0x0000, 0x0000, 0x0000 }, /* R10980 */ + { 0x0000, 0x0000, 0x0000 }, /* R10981 */ + { 0x0000, 0x0000, 0x0000 }, /* R10982 */ + { 0x0000, 0x0000, 0x0000 }, /* R10983 */ + { 0x0000, 0x0000, 0x0000 }, /* R10984 */ + { 0x0000, 0x0000, 0x0000 }, /* R10985 */ + { 0x0000, 0x0000, 0x0000 }, /* R10986 */ + { 0x0000, 0x0000, 0x0000 }, /* R10987 */ + { 0x0000, 0x0000, 0x0000 }, /* R10988 */ + { 0x0000, 0x0000, 0x0000 }, /* R10989 */ + { 0x0000, 0x0000, 0x0000 }, /* R10990 */ + { 0x0000, 0x0000, 0x0000 }, /* R10991 */ + { 0x0000, 0x0000, 0x0000 }, /* R10992 */ + { 0x0000, 0x0000, 0x0000 }, /* R10993 */ + { 0x0000, 0x0000, 0x0000 }, /* R10994 */ + { 0x0000, 0x0000, 0x0000 }, /* R10995 */ + { 0x0000, 0x0000, 0x0000 }, /* R10996 */ + { 0x0000, 0x0000, 0x0000 }, /* R10997 */ + { 0x0000, 0x0000, 0x0000 }, /* R10998 */ + { 0x0000, 0x0000, 0x0000 }, /* R10999 */ + { 0x0000, 0x0000, 0x0000 }, /* R11000 */ + { 0x0000, 0x0000, 0x0000 }, /* R11001 */ + { 0x0000, 0x0000, 0x0000 }, /* R11002 */ + { 0x0000, 0x0000, 0x0000 }, /* R11003 */ + { 0x0000, 0x0000, 0x0000 }, /* R11004 */ + { 0x0000, 0x0000, 0x0000 }, /* R11005 */ + { 0x0000, 0x0000, 0x0000 }, /* R11006 */ + { 0x0000, 0x0000, 0x0000 }, /* R11007 */ + { 0x0000, 0x0000, 0x0000 }, /* R11008 */ + { 0x0000, 0x0000, 0x0000 }, /* R11009 */ + { 0x0000, 0x0000, 0x0000 }, /* R11010 */ + { 0x0000, 0x0000, 0x0000 }, /* R11011 */ + { 0x0000, 0x0000, 0x0000 }, /* R11012 */ + { 0x0000, 0x0000, 0x0000 }, /* R11013 */ + { 0x0000, 0x0000, 0x0000 }, /* R11014 */ + { 0x0000, 0x0000, 0x0000 }, /* R11015 */ + { 0x0000, 0x0000, 0x0000 }, /* R11016 */ + { 0x0000, 0x0000, 0x0000 }, /* R11017 */ + { 0x0000, 0x0000, 0x0000 }, /* R11018 */ + { 0x0000, 0x0000, 0x0000 }, /* R11019 */ + { 0x0000, 0x0000, 0x0000 }, /* R11020 */ + { 0x0000, 0x0000, 0x0000 }, /* R11021 */ + { 0x0000, 0x0000, 0x0000 }, /* R11022 */ + { 0x0000, 0x0000, 0x0000 }, /* R11023 */ + { 0x0000, 0x0000, 0x0000 }, /* R11024 */ + { 0x0000, 0x0000, 0x0000 }, /* R11025 */ + { 0x0000, 0x0000, 0x0000 }, /* R11026 */ + { 0x0000, 0x0000, 0x0000 }, /* R11027 */ + { 0x0000, 0x0000, 0x0000 }, /* R11028 */ + { 0x0000, 0x0000, 0x0000 }, /* R11029 */ + { 0x0000, 0x0000, 0x0000 }, /* R11030 */ + { 0x0000, 0x0000, 0x0000 }, /* R11031 */ + { 0x0000, 0x0000, 0x0000 }, /* R11032 */ + { 0x0000, 0x0000, 0x0000 }, /* R11033 */ + { 0x0000, 0x0000, 0x0000 }, /* R11034 */ + { 0x0000, 0x0000, 0x0000 }, /* R11035 */ + { 0x0000, 0x0000, 0x0000 }, /* R11036 */ + { 0x0000, 0x0000, 0x0000 }, /* R11037 */ + { 0x0000, 0x0000, 0x0000 }, /* R11038 */ + { 0x0000, 0x0000, 0x0000 }, /* R11039 */ + { 0x0000, 0x0000, 0x0000 }, /* R11040 */ + { 0x0000, 0x0000, 0x0000 }, /* R11041 */ + { 0x0000, 0x0000, 0x0000 }, /* R11042 */ + { 0x0000, 0x0000, 0x0000 }, /* R11043 */ + { 0x0000, 0x0000, 0x0000 }, /* R11044 */ + { 0x0000, 0x0000, 0x0000 }, /* R11045 */ + { 0x0000, 0x0000, 0x0000 }, /* R11046 */ + { 0x0000, 0x0000, 0x0000 }, /* R11047 */ + { 0x0000, 0x0000, 0x0000 }, /* R11048 */ + { 0x0000, 0x0000, 0x0000 }, /* R11049 */ + { 0x0000, 0x0000, 0x0000 }, /* R11050 */ + { 0x0000, 0x0000, 0x0000 }, /* R11051 */ + { 0x0000, 0x0000, 0x0000 }, /* R11052 */ + { 0x0000, 0x0000, 0x0000 }, /* R11053 */ + { 0x0000, 0x0000, 0x0000 }, /* R11054 */ + { 0x0000, 0x0000, 0x0000 }, /* R11055 */ + { 0x0000, 0x0000, 0x0000 }, /* R11056 */ + { 0x0000, 0x0000, 0x0000 }, /* R11057 */ + { 0x0000, 0x0000, 0x0000 }, /* R11058 */ + { 0x0000, 0x0000, 0x0000 }, /* R11059 */ + { 0x0000, 0x0000, 0x0000 }, /* R11060 */ + { 0x0000, 0x0000, 0x0000 }, /* R11061 */ + { 0x0000, 0x0000, 0x0000 }, /* R11062 */ + { 0x0000, 0x0000, 0x0000 }, /* R11063 */ + { 0x0000, 0x0000, 0x0000 }, /* R11064 */ + { 0x0000, 0x0000, 0x0000 }, /* R11065 */ + { 0x0000, 0x0000, 0x0000 }, /* R11066 */ + { 0x0000, 0x0000, 0x0000 }, /* R11067 */ + { 0x0000, 0x0000, 0x0000 }, /* R11068 */ + { 0x0000, 0x0000, 0x0000 }, /* R11069 */ + { 0x0000, 0x0000, 0x0000 }, /* R11070 */ + { 0x0000, 0x0000, 0x0000 }, /* R11071 */ + { 0x0000, 0x0000, 0x0000 }, /* R11072 */ + { 0x0000, 0x0000, 0x0000 }, /* R11073 */ + { 0x0000, 0x0000, 0x0000 }, /* R11074 */ + { 0x0000, 0x0000, 0x0000 }, /* R11075 */ + { 0x0000, 0x0000, 0x0000 }, /* R11076 */ + { 0x0000, 0x0000, 0x0000 }, /* R11077 */ + { 0x0000, 0x0000, 0x0000 }, /* R11078 */ + { 0x0000, 0x0000, 0x0000 }, /* R11079 */ + { 0x0000, 0x0000, 0x0000 }, /* R11080 */ + { 0x0000, 0x0000, 0x0000 }, /* R11081 */ + { 0x0000, 0x0000, 0x0000 }, /* R11082 */ + { 0x0000, 0x0000, 0x0000 }, /* R11083 */ + { 0x0000, 0x0000, 0x0000 }, /* R11084 */ + { 0x0000, 0x0000, 0x0000 }, /* R11085 */ + { 0x0000, 0x0000, 0x0000 }, /* R11086 */ + { 0x0000, 0x0000, 0x0000 }, /* R11087 */ + { 0x0000, 0x0000, 0x0000 }, /* R11088 */ + { 0x0000, 0x0000, 0x0000 }, /* R11089 */ + { 0x0000, 0x0000, 0x0000 }, /* R11090 */ + { 0x0000, 0x0000, 0x0000 }, /* R11091 */ + { 0x0000, 0x0000, 0x0000 }, /* R11092 */ + { 0x0000, 0x0000, 0x0000 }, /* R11093 */ + { 0x0000, 0x0000, 0x0000 }, /* R11094 */ + { 0x0000, 0x0000, 0x0000 }, /* R11095 */ + { 0x0000, 0x0000, 0x0000 }, /* R11096 */ + { 0x0000, 0x0000, 0x0000 }, /* R11097 */ + { 0x0000, 0x0000, 0x0000 }, /* R11098 */ + { 0x0000, 0x0000, 0x0000 }, /* R11099 */ + { 0x0000, 0x0000, 0x0000 }, /* R11100 */ + { 0x0000, 0x0000, 0x0000 }, /* R11101 */ + { 0x0000, 0x0000, 0x0000 }, /* R11102 */ + { 0x0000, 0x0000, 0x0000 }, /* R11103 */ + { 0x0000, 0x0000, 0x0000 }, /* R11104 */ + { 0x0000, 0x0000, 0x0000 }, /* R11105 */ + { 0x0000, 0x0000, 0x0000 }, /* R11106 */ + { 0x0000, 0x0000, 0x0000 }, /* R11107 */ + { 0x0000, 0x0000, 0x0000 }, /* R11108 */ + { 0x0000, 0x0000, 0x0000 }, /* R11109 */ + { 0x0000, 0x0000, 0x0000 }, /* R11110 */ + { 0x0000, 0x0000, 0x0000 }, /* R11111 */ + { 0x0000, 0x0000, 0x0000 }, /* R11112 */ + { 0x0000, 0x0000, 0x0000 }, /* R11113 */ + { 0x0000, 0x0000, 0x0000 }, /* R11114 */ + { 0x0000, 0x0000, 0x0000 }, /* R11115 */ + { 0x0000, 0x0000, 0x0000 }, /* R11116 */ + { 0x0000, 0x0000, 0x0000 }, /* R11117 */ + { 0x0000, 0x0000, 0x0000 }, /* R11118 */ + { 0x0000, 0x0000, 0x0000 }, /* R11119 */ + { 0x0000, 0x0000, 0x0000 }, /* R11120 */ + { 0x0000, 0x0000, 0x0000 }, /* R11121 */ + { 0x0000, 0x0000, 0x0000 }, /* R11122 */ + { 0x0000, 0x0000, 0x0000 }, /* R11123 */ + { 0x0000, 0x0000, 0x0000 }, /* R11124 */ + { 0x0000, 0x0000, 0x0000 }, /* R11125 */ + { 0x0000, 0x0000, 0x0000 }, /* R11126 */ + { 0x0000, 0x0000, 0x0000 }, /* R11127 */ + { 0x0000, 0x0000, 0x0000 }, /* R11128 */ + { 0x0000, 0x0000, 0x0000 }, /* R11129 */ + { 0x0000, 0x0000, 0x0000 }, /* R11130 */ + { 0x0000, 0x0000, 0x0000 }, /* R11131 */ + { 0x0000, 0x0000, 0x0000 }, /* R11132 */ + { 0x0000, 0x0000, 0x0000 }, /* R11133 */ + { 0x0000, 0x0000, 0x0000 }, /* R11134 */ + { 0x0000, 0x0000, 0x0000 }, /* R11135 */ + { 0x0000, 0x0000, 0x0000 }, /* R11136 */ + { 0x0000, 0x0000, 0x0000 }, /* R11137 */ + { 0x0000, 0x0000, 0x0000 }, /* R11138 */ + { 0x0000, 0x0000, 0x0000 }, /* R11139 */ + { 0x0000, 0x0000, 0x0000 }, /* R11140 */ + { 0x0000, 0x0000, 0x0000 }, /* R11141 */ + { 0x0000, 0x0000, 0x0000 }, /* R11142 */ + { 0x0000, 0x0000, 0x0000 }, /* R11143 */ + { 0x0000, 0x0000, 0x0000 }, /* R11144 */ + { 0x0000, 0x0000, 0x0000 }, /* R11145 */ + { 0x0000, 0x0000, 0x0000 }, /* R11146 */ + { 0x0000, 0x0000, 0x0000 }, /* R11147 */ + { 0x0000, 0x0000, 0x0000 }, /* R11148 */ + { 0x0000, 0x0000, 0x0000 }, /* R11149 */ + { 0x0000, 0x0000, 0x0000 }, /* R11150 */ + { 0x0000, 0x0000, 0x0000 }, /* R11151 */ + { 0x0000, 0x0000, 0x0000 }, /* R11152 */ + { 0x0000, 0x0000, 0x0000 }, /* R11153 */ + { 0x0000, 0x0000, 0x0000 }, /* R11154 */ + { 0x0000, 0x0000, 0x0000 }, /* R11155 */ + { 0x0000, 0x0000, 0x0000 }, /* R11156 */ + { 0x0000, 0x0000, 0x0000 }, /* R11157 */ + { 0x0000, 0x0000, 0x0000 }, /* R11158 */ + { 0x0000, 0x0000, 0x0000 }, /* R11159 */ + { 0x0000, 0x0000, 0x0000 }, /* R11160 */ + { 0x0000, 0x0000, 0x0000 }, /* R11161 */ + { 0x0000, 0x0000, 0x0000 }, /* R11162 */ + { 0x0000, 0x0000, 0x0000 }, /* R11163 */ + { 0x0000, 0x0000, 0x0000 }, /* R11164 */ + { 0x0000, 0x0000, 0x0000 }, /* R11165 */ + { 0x0000, 0x0000, 0x0000 }, /* R11166 */ + { 0x0000, 0x0000, 0x0000 }, /* R11167 */ + { 0x0000, 0x0000, 0x0000 }, /* R11168 */ + { 0x0000, 0x0000, 0x0000 }, /* R11169 */ + { 0x0000, 0x0000, 0x0000 }, /* R11170 */ + { 0x0000, 0x0000, 0x0000 }, /* R11171 */ + { 0x0000, 0x0000, 0x0000 }, /* R11172 */ + { 0x0000, 0x0000, 0x0000 }, /* R11173 */ + { 0x0000, 0x0000, 0x0000 }, /* R11174 */ + { 0x0000, 0x0000, 0x0000 }, /* R11175 */ + { 0x0000, 0x0000, 0x0000 }, /* R11176 */ + { 0x0000, 0x0000, 0x0000 }, /* R11177 */ + { 0x0000, 0x0000, 0x0000 }, /* R11178 */ + { 0x0000, 0x0000, 0x0000 }, /* R11179 */ + { 0x0000, 0x0000, 0x0000 }, /* R11180 */ + { 0x0000, 0x0000, 0x0000 }, /* R11181 */ + { 0x0000, 0x0000, 0x0000 }, /* R11182 */ + { 0x0000, 0x0000, 0x0000 }, /* R11183 */ + { 0x0000, 0x0000, 0x0000 }, /* R11184 */ + { 0x0000, 0x0000, 0x0000 }, /* R11185 */ + { 0x0000, 0x0000, 0x0000 }, /* R11186 */ + { 0x0000, 0x0000, 0x0000 }, /* R11187 */ + { 0x0000, 0x0000, 0x0000 }, /* R11188 */ + { 0x0000, 0x0000, 0x0000 }, /* R11189 */ + { 0x0000, 0x0000, 0x0000 }, /* R11190 */ + { 0x0000, 0x0000, 0x0000 }, /* R11191 */ + { 0x0000, 0x0000, 0x0000 }, /* R11192 */ + { 0x0000, 0x0000, 0x0000 }, /* R11193 */ + { 0x0000, 0x0000, 0x0000 }, /* R11194 */ + { 0x0000, 0x0000, 0x0000 }, /* R11195 */ + { 0x0000, 0x0000, 0x0000 }, /* R11196 */ + { 0x0000, 0x0000, 0x0000 }, /* R11197 */ + { 0x0000, 0x0000, 0x0000 }, /* R11198 */ + { 0x0000, 0x0000, 0x0000 }, /* R11199 */ + { 0x0000, 0x0000, 0x0000 }, /* R11200 */ + { 0x0000, 0x0000, 0x0000 }, /* R11201 */ + { 0x0000, 0x0000, 0x0000 }, /* R11202 */ + { 0x0000, 0x0000, 0x0000 }, /* R11203 */ + { 0x0000, 0x0000, 0x0000 }, /* R11204 */ + { 0x0000, 0x0000, 0x0000 }, /* R11205 */ + { 0x0000, 0x0000, 0x0000 }, /* R11206 */ + { 0x0000, 0x0000, 0x0000 }, /* R11207 */ + { 0x0000, 0x0000, 0x0000 }, /* R11208 */ + { 0x0000, 0x0000, 0x0000 }, /* R11209 */ + { 0x0000, 0x0000, 0x0000 }, /* R11210 */ + { 0x0000, 0x0000, 0x0000 }, /* R11211 */ + { 0x0000, 0x0000, 0x0000 }, /* R11212 */ + { 0x0000, 0x0000, 0x0000 }, /* R11213 */ + { 0x0000, 0x0000, 0x0000 }, /* R11214 */ + { 0x0000, 0x0000, 0x0000 }, /* R11215 */ + { 0x0000, 0x0000, 0x0000 }, /* R11216 */ + { 0x0000, 0x0000, 0x0000 }, /* R11217 */ + { 0x0000, 0x0000, 0x0000 }, /* R11218 */ + { 0x0000, 0x0000, 0x0000 }, /* R11219 */ + { 0x0000, 0x0000, 0x0000 }, /* R11220 */ + { 0x0000, 0x0000, 0x0000 }, /* R11221 */ + { 0x0000, 0x0000, 0x0000 }, /* R11222 */ + { 0x0000, 0x0000, 0x0000 }, /* R11223 */ + { 0x0000, 0x0000, 0x0000 }, /* R11224 */ + { 0x0000, 0x0000, 0x0000 }, /* R11225 */ + { 0x0000, 0x0000, 0x0000 }, /* R11226 */ + { 0x0000, 0x0000, 0x0000 }, /* R11227 */ + { 0x0000, 0x0000, 0x0000 }, /* R11228 */ + { 0x0000, 0x0000, 0x0000 }, /* R11229 */ + { 0x0000, 0x0000, 0x0000 }, /* R11230 */ + { 0x0000, 0x0000, 0x0000 }, /* R11231 */ + { 0x0000, 0x0000, 0x0000 }, /* R11232 */ + { 0x0000, 0x0000, 0x0000 }, /* R11233 */ + { 0x0000, 0x0000, 0x0000 }, /* R11234 */ + { 0x0000, 0x0000, 0x0000 }, /* R11235 */ + { 0x0000, 0x0000, 0x0000 }, /* R11236 */ + { 0x0000, 0x0000, 0x0000 }, /* R11237 */ + { 0x0000, 0x0000, 0x0000 }, /* R11238 */ + { 0x0000, 0x0000, 0x0000 }, /* R11239 */ + { 0x0000, 0x0000, 0x0000 }, /* R11240 */ + { 0x0000, 0x0000, 0x0000 }, /* R11241 */ + { 0x0000, 0x0000, 0x0000 }, /* R11242 */ + { 0x0000, 0x0000, 0x0000 }, /* R11243 */ + { 0x0000, 0x0000, 0x0000 }, /* R11244 */ + { 0x0000, 0x0000, 0x0000 }, /* R11245 */ + { 0x0000, 0x0000, 0x0000 }, /* R11246 */ + { 0x0000, 0x0000, 0x0000 }, /* R11247 */ + { 0x0000, 0x0000, 0x0000 }, /* R11248 */ + { 0x0000, 0x0000, 0x0000 }, /* R11249 */ + { 0x0000, 0x0000, 0x0000 }, /* R11250 */ + { 0x0000, 0x0000, 0x0000 }, /* R11251 */ + { 0x0000, 0x0000, 0x0000 }, /* R11252 */ + { 0x0000, 0x0000, 0x0000 }, /* R11253 */ + { 0x0000, 0x0000, 0x0000 }, /* R11254 */ + { 0x0000, 0x0000, 0x0000 }, /* R11255 */ + { 0x0000, 0x0000, 0x0000 }, /* R11256 */ + { 0x0000, 0x0000, 0x0000 }, /* R11257 */ + { 0x0000, 0x0000, 0x0000 }, /* R11258 */ + { 0x0000, 0x0000, 0x0000 }, /* R11259 */ + { 0x0000, 0x0000, 0x0000 }, /* R11260 */ + { 0x0000, 0x0000, 0x0000 }, /* R11261 */ + { 0x0000, 0x0000, 0x0000 }, /* R11262 */ + { 0x0000, 0x0000, 0x0000 }, /* R11263 */ + { 0x0000, 0x0000, 0x0000 }, /* R11264 */ + { 0x0000, 0x0000, 0x0000 }, /* R11265 */ + { 0x0000, 0x0000, 0x0000 }, /* R11266 */ + { 0x0000, 0x0000, 0x0000 }, /* R11267 */ + { 0x0000, 0x0000, 0x0000 }, /* R11268 */ + { 0x0000, 0x0000, 0x0000 }, /* R11269 */ + { 0x0000, 0x0000, 0x0000 }, /* R11270 */ + { 0x0000, 0x0000, 0x0000 }, /* R11271 */ + { 0x0000, 0x0000, 0x0000 }, /* R11272 */ + { 0x0000, 0x0000, 0x0000 }, /* R11273 */ + { 0x0000, 0x0000, 0x0000 }, /* R11274 */ + { 0x0000, 0x0000, 0x0000 }, /* R11275 */ + { 0x0000, 0x0000, 0x0000 }, /* R11276 */ + { 0x0000, 0x0000, 0x0000 }, /* R11277 */ + { 0x0000, 0x0000, 0x0000 }, /* R11278 */ + { 0x0000, 0x0000, 0x0000 }, /* R11279 */ + { 0x0000, 0x0000, 0x0000 }, /* R11280 */ + { 0x0000, 0x0000, 0x0000 }, /* R11281 */ + { 0x0000, 0x0000, 0x0000 }, /* R11282 */ + { 0x0000, 0x0000, 0x0000 }, /* R11283 */ + { 0x0000, 0x0000, 0x0000 }, /* R11284 */ + { 0x0000, 0x0000, 0x0000 }, /* R11285 */ + { 0x0000, 0x0000, 0x0000 }, /* R11286 */ + { 0x0000, 0x0000, 0x0000 }, /* R11287 */ + { 0x0000, 0x0000, 0x0000 }, /* R11288 */ + { 0x0000, 0x0000, 0x0000 }, /* R11289 */ + { 0x0000, 0x0000, 0x0000 }, /* R11290 */ + { 0x0000, 0x0000, 0x0000 }, /* R11291 */ + { 0x0000, 0x0000, 0x0000 }, /* R11292 */ + { 0x0000, 0x0000, 0x0000 }, /* R11293 */ + { 0x0000, 0x0000, 0x0000 }, /* R11294 */ + { 0x0000, 0x0000, 0x0000 }, /* R11295 */ + { 0x0000, 0x0000, 0x0000 }, /* R11296 */ + { 0x0000, 0x0000, 0x0000 }, /* R11297 */ + { 0x0000, 0x0000, 0x0000 }, /* R11298 */ + { 0x0000, 0x0000, 0x0000 }, /* R11299 */ + { 0x0000, 0x0000, 0x0000 }, /* R11300 */ + { 0x0000, 0x0000, 0x0000 }, /* R11301 */ + { 0x0000, 0x0000, 0x0000 }, /* R11302 */ + { 0x0000, 0x0000, 0x0000 }, /* R11303 */ + { 0x0000, 0x0000, 0x0000 }, /* R11304 */ + { 0x0000, 0x0000, 0x0000 }, /* R11305 */ + { 0x0000, 0x0000, 0x0000 }, /* R11306 */ + { 0x0000, 0x0000, 0x0000 }, /* R11307 */ + { 0x0000, 0x0000, 0x0000 }, /* R11308 */ + { 0x0000, 0x0000, 0x0000 }, /* R11309 */ + { 0x0000, 0x0000, 0x0000 }, /* R11310 */ + { 0x0000, 0x0000, 0x0000 }, /* R11311 */ + { 0x0000, 0x0000, 0x0000 }, /* R11312 */ + { 0x0000, 0x0000, 0x0000 }, /* R11313 */ + { 0x0000, 0x0000, 0x0000 }, /* R11314 */ + { 0x0000, 0x0000, 0x0000 }, /* R11315 */ + { 0x0000, 0x0000, 0x0000 }, /* R11316 */ + { 0x0000, 0x0000, 0x0000 }, /* R11317 */ + { 0x0000, 0x0000, 0x0000 }, /* R11318 */ + { 0x0000, 0x0000, 0x0000 }, /* R11319 */ + { 0x0000, 0x0000, 0x0000 }, /* R11320 */ + { 0x0000, 0x0000, 0x0000 }, /* R11321 */ + { 0x0000, 0x0000, 0x0000 }, /* R11322 */ + { 0x0000, 0x0000, 0x0000 }, /* R11323 */ + { 0x0000, 0x0000, 0x0000 }, /* R11324 */ + { 0x0000, 0x0000, 0x0000 }, /* R11325 */ + { 0x0000, 0x0000, 0x0000 }, /* R11326 */ + { 0x0000, 0x0000, 0x0000 }, /* R11327 */ + { 0x0000, 0x0000, 0x0000 }, /* R11328 */ + { 0x0000, 0x0000, 0x0000 }, /* R11329 */ + { 0x0000, 0x0000, 0x0000 }, /* R11330 */ + { 0x0000, 0x0000, 0x0000 }, /* R11331 */ + { 0x0000, 0x0000, 0x0000 }, /* R11332 */ + { 0x0000, 0x0000, 0x0000 }, /* R11333 */ + { 0x0000, 0x0000, 0x0000 }, /* R11334 */ + { 0x0000, 0x0000, 0x0000 }, /* R11335 */ + { 0x0000, 0x0000, 0x0000 }, /* R11336 */ + { 0x0000, 0x0000, 0x0000 }, /* R11337 */ + { 0x0000, 0x0000, 0x0000 }, /* R11338 */ + { 0x0000, 0x0000, 0x0000 }, /* R11339 */ + { 0x0000, 0x0000, 0x0000 }, /* R11340 */ + { 0x0000, 0x0000, 0x0000 }, /* R11341 */ + { 0x0000, 0x0000, 0x0000 }, /* R11342 */ + { 0x0000, 0x0000, 0x0000 }, /* R11343 */ + { 0x0000, 0x0000, 0x0000 }, /* R11344 */ + { 0x0000, 0x0000, 0x0000 }, /* R11345 */ + { 0x0000, 0x0000, 0x0000 }, /* R11346 */ + { 0x0000, 0x0000, 0x0000 }, /* R11347 */ + { 0x0000, 0x0000, 0x0000 }, /* R11348 */ + { 0x0000, 0x0000, 0x0000 }, /* R11349 */ + { 0x0000, 0x0000, 0x0000 }, /* R11350 */ + { 0x0000, 0x0000, 0x0000 }, /* R11351 */ + { 0x0000, 0x0000, 0x0000 }, /* R11352 */ + { 0x0000, 0x0000, 0x0000 }, /* R11353 */ + { 0x0000, 0x0000, 0x0000 }, /* R11354 */ + { 0x0000, 0x0000, 0x0000 }, /* R11355 */ + { 0x0000, 0x0000, 0x0000 }, /* R11356 */ + { 0x0000, 0x0000, 0x0000 }, /* R11357 */ + { 0x0000, 0x0000, 0x0000 }, /* R11358 */ + { 0x0000, 0x0000, 0x0000 }, /* R11359 */ + { 0x0000, 0x0000, 0x0000 }, /* R11360 */ + { 0x0000, 0x0000, 0x0000 }, /* R11361 */ + { 0x0000, 0x0000, 0x0000 }, /* R11362 */ + { 0x0000, 0x0000, 0x0000 }, /* R11363 */ + { 0x0000, 0x0000, 0x0000 }, /* R11364 */ + { 0x0000, 0x0000, 0x0000 }, /* R11365 */ + { 0x0000, 0x0000, 0x0000 }, /* R11366 */ + { 0x0000, 0x0000, 0x0000 }, /* R11367 */ + { 0x0000, 0x0000, 0x0000 }, /* R11368 */ + { 0x0000, 0x0000, 0x0000 }, /* R11369 */ + { 0x0000, 0x0000, 0x0000 }, /* R11370 */ + { 0x0000, 0x0000, 0x0000 }, /* R11371 */ + { 0x0000, 0x0000, 0x0000 }, /* R11372 */ + { 0x0000, 0x0000, 0x0000 }, /* R11373 */ + { 0x0000, 0x0000, 0x0000 }, /* R11374 */ + { 0x0000, 0x0000, 0x0000 }, /* R11375 */ + { 0x0000, 0x0000, 0x0000 }, /* R11376 */ + { 0x0000, 0x0000, 0x0000 }, /* R11377 */ + { 0x0000, 0x0000, 0x0000 }, /* R11378 */ + { 0x0000, 0x0000, 0x0000 }, /* R11379 */ + { 0x0000, 0x0000, 0x0000 }, /* R11380 */ + { 0x0000, 0x0000, 0x0000 }, /* R11381 */ + { 0x0000, 0x0000, 0x0000 }, /* R11382 */ + { 0x0000, 0x0000, 0x0000 }, /* R11383 */ + { 0x0000, 0x0000, 0x0000 }, /* R11384 */ + { 0x0000, 0x0000, 0x0000 }, /* R11385 */ + { 0x0000, 0x0000, 0x0000 }, /* R11386 */ + { 0x0000, 0x0000, 0x0000 }, /* R11387 */ + { 0x0000, 0x0000, 0x0000 }, /* R11388 */ + { 0x0000, 0x0000, 0x0000 }, /* R11389 */ + { 0x0000, 0x0000, 0x0000 }, /* R11390 */ + { 0x0000, 0x0000, 0x0000 }, /* R11391 */ + { 0x0000, 0x0000, 0x0000 }, /* R11392 */ + { 0x0000, 0x0000, 0x0000 }, /* R11393 */ + { 0x0000, 0x0000, 0x0000 }, /* R11394 */ + { 0x0000, 0x0000, 0x0000 }, /* R11395 */ + { 0x0000, 0x0000, 0x0000 }, /* R11396 */ + { 0x0000, 0x0000, 0x0000 }, /* R11397 */ + { 0x0000, 0x0000, 0x0000 }, /* R11398 */ + { 0x0000, 0x0000, 0x0000 }, /* R11399 */ + { 0x0000, 0x0000, 0x0000 }, /* R11400 */ + { 0x0000, 0x0000, 0x0000 }, /* R11401 */ + { 0x0000, 0x0000, 0x0000 }, /* R11402 */ + { 0x0000, 0x0000, 0x0000 }, /* R11403 */ + { 0x0000, 0x0000, 0x0000 }, /* R11404 */ + { 0x0000, 0x0000, 0x0000 }, /* R11405 */ + { 0x0000, 0x0000, 0x0000 }, /* R11406 */ + { 0x0000, 0x0000, 0x0000 }, /* R11407 */ + { 0x0000, 0x0000, 0x0000 }, /* R11408 */ + { 0x0000, 0x0000, 0x0000 }, /* R11409 */ + { 0x0000, 0x0000, 0x0000 }, /* R11410 */ + { 0x0000, 0x0000, 0x0000 }, /* R11411 */ + { 0x0000, 0x0000, 0x0000 }, /* R11412 */ + { 0x0000, 0x0000, 0x0000 }, /* R11413 */ + { 0x0000, 0x0000, 0x0000 }, /* R11414 */ + { 0x0000, 0x0000, 0x0000 }, /* R11415 */ + { 0x0000, 0x0000, 0x0000 }, /* R11416 */ + { 0x0000, 0x0000, 0x0000 }, /* R11417 */ + { 0x0000, 0x0000, 0x0000 }, /* R11418 */ + { 0x0000, 0x0000, 0x0000 }, /* R11419 */ + { 0x0000, 0x0000, 0x0000 }, /* R11420 */ + { 0x0000, 0x0000, 0x0000 }, /* R11421 */ + { 0x0000, 0x0000, 0x0000 }, /* R11422 */ + { 0x0000, 0x0000, 0x0000 }, /* R11423 */ + { 0x0000, 0x0000, 0x0000 }, /* R11424 */ + { 0x0000, 0x0000, 0x0000 }, /* R11425 */ + { 0x0000, 0x0000, 0x0000 }, /* R11426 */ + { 0x0000, 0x0000, 0x0000 }, /* R11427 */ + { 0x0000, 0x0000, 0x0000 }, /* R11428 */ + { 0x0000, 0x0000, 0x0000 }, /* R11429 */ + { 0x0000, 0x0000, 0x0000 }, /* R11430 */ + { 0x0000, 0x0000, 0x0000 }, /* R11431 */ + { 0x0000, 0x0000, 0x0000 }, /* R11432 */ + { 0x0000, 0x0000, 0x0000 }, /* R11433 */ + { 0x0000, 0x0000, 0x0000 }, /* R11434 */ + { 0x0000, 0x0000, 0x0000 }, /* R11435 */ + { 0x0000, 0x0000, 0x0000 }, /* R11436 */ + { 0x0000, 0x0000, 0x0000 }, /* R11437 */ + { 0x0000, 0x0000, 0x0000 }, /* R11438 */ + { 0x0000, 0x0000, 0x0000 }, /* R11439 */ + { 0x0000, 0x0000, 0x0000 }, /* R11440 */ + { 0x0000, 0x0000, 0x0000 }, /* R11441 */ + { 0x0000, 0x0000, 0x0000 }, /* R11442 */ + { 0x0000, 0x0000, 0x0000 }, /* R11443 */ + { 0x0000, 0x0000, 0x0000 }, /* R11444 */ + { 0x0000, 0x0000, 0x0000 }, /* R11445 */ + { 0x0000, 0x0000, 0x0000 }, /* R11446 */ + { 0x0000, 0x0000, 0x0000 }, /* R11447 */ + { 0x0000, 0x0000, 0x0000 }, /* R11448 */ + { 0x0000, 0x0000, 0x0000 }, /* R11449 */ + { 0x0000, 0x0000, 0x0000 }, /* R11450 */ + { 0x0000, 0x0000, 0x0000 }, /* R11451 */ + { 0x0000, 0x0000, 0x0000 }, /* R11452 */ + { 0x0000, 0x0000, 0x0000 }, /* R11453 */ + { 0x0000, 0x0000, 0x0000 }, /* R11454 */ + { 0x0000, 0x0000, 0x0000 }, /* R11455 */ + { 0x0000, 0x0000, 0x0000 }, /* R11456 */ + { 0x0000, 0x0000, 0x0000 }, /* R11457 */ + { 0x0000, 0x0000, 0x0000 }, /* R11458 */ + { 0x0000, 0x0000, 0x0000 }, /* R11459 */ + { 0x0000, 0x0000, 0x0000 }, /* R11460 */ + { 0x0000, 0x0000, 0x0000 }, /* R11461 */ + { 0x0000, 0x0000, 0x0000 }, /* R11462 */ + { 0x0000, 0x0000, 0x0000 }, /* R11463 */ + { 0x0000, 0x0000, 0x0000 }, /* R11464 */ + { 0x0000, 0x0000, 0x0000 }, /* R11465 */ + { 0x0000, 0x0000, 0x0000 }, /* R11466 */ + { 0x0000, 0x0000, 0x0000 }, /* R11467 */ + { 0x0000, 0x0000, 0x0000 }, /* R11468 */ + { 0x0000, 0x0000, 0x0000 }, /* R11469 */ + { 0x0000, 0x0000, 0x0000 }, /* R11470 */ + { 0x0000, 0x0000, 0x0000 }, /* R11471 */ + { 0x0000, 0x0000, 0x0000 }, /* R11472 */ + { 0x0000, 0x0000, 0x0000 }, /* R11473 */ + { 0x0000, 0x0000, 0x0000 }, /* R11474 */ + { 0x0000, 0x0000, 0x0000 }, /* R11475 */ + { 0x0000, 0x0000, 0x0000 }, /* R11476 */ + { 0x0000, 0x0000, 0x0000 }, /* R11477 */ + { 0x0000, 0x0000, 0x0000 }, /* R11478 */ + { 0x0000, 0x0000, 0x0000 }, /* R11479 */ + { 0x0000, 0x0000, 0x0000 }, /* R11480 */ + { 0x0000, 0x0000, 0x0000 }, /* R11481 */ + { 0x0000, 0x0000, 0x0000 }, /* R11482 */ + { 0x0000, 0x0000, 0x0000 }, /* R11483 */ + { 0x0000, 0x0000, 0x0000 }, /* R11484 */ + { 0x0000, 0x0000, 0x0000 }, /* R11485 */ + { 0x0000, 0x0000, 0x0000 }, /* R11486 */ + { 0x0000, 0x0000, 0x0000 }, /* R11487 */ + { 0x0000, 0x0000, 0x0000 }, /* R11488 */ + { 0x0000, 0x0000, 0x0000 }, /* R11489 */ + { 0x0000, 0x0000, 0x0000 }, /* R11490 */ + { 0x0000, 0x0000, 0x0000 }, /* R11491 */ + { 0x0000, 0x0000, 0x0000 }, /* R11492 */ + { 0x0000, 0x0000, 0x0000 }, /* R11493 */ + { 0x0000, 0x0000, 0x0000 }, /* R11494 */ + { 0x0000, 0x0000, 0x0000 }, /* R11495 */ + { 0x0000, 0x0000, 0x0000 }, /* R11496 */ + { 0x0000, 0x0000, 0x0000 }, /* R11497 */ + { 0x0000, 0x0000, 0x0000 }, /* R11498 */ + { 0x0000, 0x0000, 0x0000 }, /* R11499 */ + { 0x0000, 0x0000, 0x0000 }, /* R11500 */ + { 0x0000, 0x0000, 0x0000 }, /* R11501 */ + { 0x0000, 0x0000, 0x0000 }, /* R11502 */ + { 0x0000, 0x0000, 0x0000 }, /* R11503 */ + { 0x0000, 0x0000, 0x0000 }, /* R11504 */ + { 0x0000, 0x0000, 0x0000 }, /* R11505 */ + { 0x0000, 0x0000, 0x0000 }, /* R11506 */ + { 0x0000, 0x0000, 0x0000 }, /* R11507 */ + { 0x0000, 0x0000, 0x0000 }, /* R11508 */ + { 0x0000, 0x0000, 0x0000 }, /* R11509 */ + { 0x0000, 0x0000, 0x0000 }, /* R11510 */ + { 0x0000, 0x0000, 0x0000 }, /* R11511 */ + { 0x0000, 0x0000, 0x0000 }, /* R11512 */ + { 0x0000, 0x0000, 0x0000 }, /* R11513 */ + { 0x0000, 0x0000, 0x0000 }, /* R11514 */ + { 0x0000, 0x0000, 0x0000 }, /* R11515 */ + { 0x0000, 0x0000, 0x0000 }, /* R11516 */ + { 0x0000, 0x0000, 0x0000 }, /* R11517 */ + { 0x0000, 0x0000, 0x0000 }, /* R11518 */ + { 0x0000, 0x0000, 0x0000 }, /* R11519 */ + { 0x0000, 0x0000, 0x0000 }, /* R11520 */ + { 0x0000, 0x0000, 0x0000 }, /* R11521 */ + { 0x0000, 0x0000, 0x0000 }, /* R11522 */ + { 0x0000, 0x0000, 0x0000 }, /* R11523 */ + { 0x0000, 0x0000, 0x0000 }, /* R11524 */ + { 0x0000, 0x0000, 0x0000 }, /* R11525 */ + { 0x0000, 0x0000, 0x0000 }, /* R11526 */ + { 0x0000, 0x0000, 0x0000 }, /* R11527 */ + { 0x0000, 0x0000, 0x0000 }, /* R11528 */ + { 0x0000, 0x0000, 0x0000 }, /* R11529 */ + { 0x0000, 0x0000, 0x0000 }, /* R11530 */ + { 0x0000, 0x0000, 0x0000 }, /* R11531 */ + { 0x0000, 0x0000, 0x0000 }, /* R11532 */ + { 0x0000, 0x0000, 0x0000 }, /* R11533 */ + { 0x0000, 0x0000, 0x0000 }, /* R11534 */ + { 0x0000, 0x0000, 0x0000 }, /* R11535 */ + { 0x0000, 0x0000, 0x0000 }, /* R11536 */ + { 0x0000, 0x0000, 0x0000 }, /* R11537 */ + { 0x0000, 0x0000, 0x0000 }, /* R11538 */ + { 0x0000, 0x0000, 0x0000 }, /* R11539 */ + { 0x0000, 0x0000, 0x0000 }, /* R11540 */ + { 0x0000, 0x0000, 0x0000 }, /* R11541 */ + { 0x0000, 0x0000, 0x0000 }, /* R11542 */ + { 0x0000, 0x0000, 0x0000 }, /* R11543 */ + { 0x0000, 0x0000, 0x0000 }, /* R11544 */ + { 0x0000, 0x0000, 0x0000 }, /* R11545 */ + { 0x0000, 0x0000, 0x0000 }, /* R11546 */ + { 0x0000, 0x0000, 0x0000 }, /* R11547 */ + { 0x0000, 0x0000, 0x0000 }, /* R11548 */ + { 0x0000, 0x0000, 0x0000 }, /* R11549 */ + { 0x0000, 0x0000, 0x0000 }, /* R11550 */ + { 0x0000, 0x0000, 0x0000 }, /* R11551 */ + { 0x0000, 0x0000, 0x0000 }, /* R11552 */ + { 0x0000, 0x0000, 0x0000 }, /* R11553 */ + { 0x0000, 0x0000, 0x0000 }, /* R11554 */ + { 0x0000, 0x0000, 0x0000 }, /* R11555 */ + { 0x0000, 0x0000, 0x0000 }, /* R11556 */ + { 0x0000, 0x0000, 0x0000 }, /* R11557 */ + { 0x0000, 0x0000, 0x0000 }, /* R11558 */ + { 0x0000, 0x0000, 0x0000 }, /* R11559 */ + { 0x0000, 0x0000, 0x0000 }, /* R11560 */ + { 0x0000, 0x0000, 0x0000 }, /* R11561 */ + { 0x0000, 0x0000, 0x0000 }, /* R11562 */ + { 0x0000, 0x0000, 0x0000 }, /* R11563 */ + { 0x0000, 0x0000, 0x0000 }, /* R11564 */ + { 0x0000, 0x0000, 0x0000 }, /* R11565 */ + { 0x0000, 0x0000, 0x0000 }, /* R11566 */ + { 0x0000, 0x0000, 0x0000 }, /* R11567 */ + { 0x0000, 0x0000, 0x0000 }, /* R11568 */ + { 0x0000, 0x0000, 0x0000 }, /* R11569 */ + { 0x0000, 0x0000, 0x0000 }, /* R11570 */ + { 0x0000, 0x0000, 0x0000 }, /* R11571 */ + { 0x0000, 0x0000, 0x0000 }, /* R11572 */ + { 0x0000, 0x0000, 0x0000 }, /* R11573 */ + { 0x0000, 0x0000, 0x0000 }, /* R11574 */ + { 0x0000, 0x0000, 0x0000 }, /* R11575 */ + { 0x0000, 0x0000, 0x0000 }, /* R11576 */ + { 0x0000, 0x0000, 0x0000 }, /* R11577 */ + { 0x0000, 0x0000, 0x0000 }, /* R11578 */ + { 0x0000, 0x0000, 0x0000 }, /* R11579 */ + { 0x0000, 0x0000, 0x0000 }, /* R11580 */ + { 0x0000, 0x0000, 0x0000 }, /* R11581 */ + { 0x0000, 0x0000, 0x0000 }, /* R11582 */ + { 0x0000, 0x0000, 0x0000 }, /* R11583 */ + { 0x0000, 0x0000, 0x0000 }, /* R11584 */ + { 0x0000, 0x0000, 0x0000 }, /* R11585 */ + { 0x0000, 0x0000, 0x0000 }, /* R11586 */ + { 0x0000, 0x0000, 0x0000 }, /* R11587 */ + { 0x0000, 0x0000, 0x0000 }, /* R11588 */ + { 0x0000, 0x0000, 0x0000 }, /* R11589 */ + { 0x0000, 0x0000, 0x0000 }, /* R11590 */ + { 0x0000, 0x0000, 0x0000 }, /* R11591 */ + { 0x0000, 0x0000, 0x0000 }, /* R11592 */ + { 0x0000, 0x0000, 0x0000 }, /* R11593 */ + { 0x0000, 0x0000, 0x0000 }, /* R11594 */ + { 0x0000, 0x0000, 0x0000 }, /* R11595 */ + { 0x0000, 0x0000, 0x0000 }, /* R11596 */ + { 0x0000, 0x0000, 0x0000 }, /* R11597 */ + { 0x0000, 0x0000, 0x0000 }, /* R11598 */ + { 0x0000, 0x0000, 0x0000 }, /* R11599 */ + { 0x0000, 0x0000, 0x0000 }, /* R11600 */ + { 0x0000, 0x0000, 0x0000 }, /* R11601 */ + { 0x0000, 0x0000, 0x0000 }, /* R11602 */ + { 0x0000, 0x0000, 0x0000 }, /* R11603 */ + { 0x0000, 0x0000, 0x0000 }, /* R11604 */ + { 0x0000, 0x0000, 0x0000 }, /* R11605 */ + { 0x0000, 0x0000, 0x0000 }, /* R11606 */ + { 0x0000, 0x0000, 0x0000 }, /* R11607 */ + { 0x0000, 0x0000, 0x0000 }, /* R11608 */ + { 0x0000, 0x0000, 0x0000 }, /* R11609 */ + { 0x0000, 0x0000, 0x0000 }, /* R11610 */ + { 0x0000, 0x0000, 0x0000 }, /* R11611 */ + { 0x0000, 0x0000, 0x0000 }, /* R11612 */ + { 0x0000, 0x0000, 0x0000 }, /* R11613 */ + { 0x0000, 0x0000, 0x0000 }, /* R11614 */ + { 0x0000, 0x0000, 0x0000 }, /* R11615 */ + { 0x0000, 0x0000, 0x0000 }, /* R11616 */ + { 0x0000, 0x0000, 0x0000 }, /* R11617 */ + { 0x0000, 0x0000, 0x0000 }, /* R11618 */ + { 0x0000, 0x0000, 0x0000 }, /* R11619 */ + { 0x0000, 0x0000, 0x0000 }, /* R11620 */ + { 0x0000, 0x0000, 0x0000 }, /* R11621 */ + { 0x0000, 0x0000, 0x0000 }, /* R11622 */ + { 0x0000, 0x0000, 0x0000 }, /* R11623 */ + { 0x0000, 0x0000, 0x0000 }, /* R11624 */ + { 0x0000, 0x0000, 0x0000 }, /* R11625 */ + { 0x0000, 0x0000, 0x0000 }, /* R11626 */ + { 0x0000, 0x0000, 0x0000 }, /* R11627 */ + { 0x0000, 0x0000, 0x0000 }, /* R11628 */ + { 0x0000, 0x0000, 0x0000 }, /* R11629 */ + { 0x0000, 0x0000, 0x0000 }, /* R11630 */ + { 0x0000, 0x0000, 0x0000 }, /* R11631 */ + { 0x0000, 0x0000, 0x0000 }, /* R11632 */ + { 0x0000, 0x0000, 0x0000 }, /* R11633 */ + { 0x0000, 0x0000, 0x0000 }, /* R11634 */ + { 0x0000, 0x0000, 0x0000 }, /* R11635 */ + { 0x0000, 0x0000, 0x0000 }, /* R11636 */ + { 0x0000, 0x0000, 0x0000 }, /* R11637 */ + { 0x0000, 0x0000, 0x0000 }, /* R11638 */ + { 0x0000, 0x0000, 0x0000 }, /* R11639 */ + { 0x0000, 0x0000, 0x0000 }, /* R11640 */ + { 0x0000, 0x0000, 0x0000 }, /* R11641 */ + { 0x0000, 0x0000, 0x0000 }, /* R11642 */ + { 0x0000, 0x0000, 0x0000 }, /* R11643 */ + { 0x0000, 0x0000, 0x0000 }, /* R11644 */ + { 0x0000, 0x0000, 0x0000 }, /* R11645 */ + { 0x0000, 0x0000, 0x0000 }, /* R11646 */ + { 0x0000, 0x0000, 0x0000 }, /* R11647 */ + { 0x0000, 0x0000, 0x0000 }, /* R11648 */ + { 0x0000, 0x0000, 0x0000 }, /* R11649 */ + { 0x0000, 0x0000, 0x0000 }, /* R11650 */ + { 0x0000, 0x0000, 0x0000 }, /* R11651 */ + { 0x0000, 0x0000, 0x0000 }, /* R11652 */ + { 0x0000, 0x0000, 0x0000 }, /* R11653 */ + { 0x0000, 0x0000, 0x0000 }, /* R11654 */ + { 0x0000, 0x0000, 0x0000 }, /* R11655 */ + { 0x0000, 0x0000, 0x0000 }, /* R11656 */ + { 0x0000, 0x0000, 0x0000 }, /* R11657 */ + { 0x0000, 0x0000, 0x0000 }, /* R11658 */ + { 0x0000, 0x0000, 0x0000 }, /* R11659 */ + { 0x0000, 0x0000, 0x0000 }, /* R11660 */ + { 0x0000, 0x0000, 0x0000 }, /* R11661 */ + { 0x0000, 0x0000, 0x0000 }, /* R11662 */ + { 0x0000, 0x0000, 0x0000 }, /* R11663 */ + { 0x0000, 0x0000, 0x0000 }, /* R11664 */ + { 0x0000, 0x0000, 0x0000 }, /* R11665 */ + { 0x0000, 0x0000, 0x0000 }, /* R11666 */ + { 0x0000, 0x0000, 0x0000 }, /* R11667 */ + { 0x0000, 0x0000, 0x0000 }, /* R11668 */ + { 0x0000, 0x0000, 0x0000 }, /* R11669 */ + { 0x0000, 0x0000, 0x0000 }, /* R11670 */ + { 0x0000, 0x0000, 0x0000 }, /* R11671 */ + { 0x0000, 0x0000, 0x0000 }, /* R11672 */ + { 0x0000, 0x0000, 0x0000 }, /* R11673 */ + { 0x0000, 0x0000, 0x0000 }, /* R11674 */ + { 0x0000, 0x0000, 0x0000 }, /* R11675 */ + { 0x0000, 0x0000, 0x0000 }, /* R11676 */ + { 0x0000, 0x0000, 0x0000 }, /* R11677 */ + { 0x0000, 0x0000, 0x0000 }, /* R11678 */ + { 0x0000, 0x0000, 0x0000 }, /* R11679 */ + { 0x0000, 0x0000, 0x0000 }, /* R11680 */ + { 0x0000, 0x0000, 0x0000 }, /* R11681 */ + { 0x0000, 0x0000, 0x0000 }, /* R11682 */ + { 0x0000, 0x0000, 0x0000 }, /* R11683 */ + { 0x0000, 0x0000, 0x0000 }, /* R11684 */ + { 0x0000, 0x0000, 0x0000 }, /* R11685 */ + { 0x0000, 0x0000, 0x0000 }, /* R11686 */ + { 0x0000, 0x0000, 0x0000 }, /* R11687 */ + { 0x0000, 0x0000, 0x0000 }, /* R11688 */ + { 0x0000, 0x0000, 0x0000 }, /* R11689 */ + { 0x0000, 0x0000, 0x0000 }, /* R11690 */ + { 0x0000, 0x0000, 0x0000 }, /* R11691 */ + { 0x0000, 0x0000, 0x0000 }, /* R11692 */ + { 0x0000, 0x0000, 0x0000 }, /* R11693 */ + { 0x0000, 0x0000, 0x0000 }, /* R11694 */ + { 0x0000, 0x0000, 0x0000 }, /* R11695 */ + { 0x0000, 0x0000, 0x0000 }, /* R11696 */ + { 0x0000, 0x0000, 0x0000 }, /* R11697 */ + { 0x0000, 0x0000, 0x0000 }, /* R11698 */ + { 0x0000, 0x0000, 0x0000 }, /* R11699 */ + { 0x0000, 0x0000, 0x0000 }, /* R11700 */ + { 0x0000, 0x0000, 0x0000 }, /* R11701 */ + { 0x0000, 0x0000, 0x0000 }, /* R11702 */ + { 0x0000, 0x0000, 0x0000 }, /* R11703 */ + { 0x0000, 0x0000, 0x0000 }, /* R11704 */ + { 0x0000, 0x0000, 0x0000 }, /* R11705 */ + { 0x0000, 0x0000, 0x0000 }, /* R11706 */ + { 0x0000, 0x0000, 0x0000 }, /* R11707 */ + { 0x0000, 0x0000, 0x0000 }, /* R11708 */ + { 0x0000, 0x0000, 0x0000 }, /* R11709 */ + { 0x0000, 0x0000, 0x0000 }, /* R11710 */ + { 0x0000, 0x0000, 0x0000 }, /* R11711 */ + { 0x0000, 0x0000, 0x0000 }, /* R11712 */ + { 0x0000, 0x0000, 0x0000 }, /* R11713 */ + { 0x0000, 0x0000, 0x0000 }, /* R11714 */ + { 0x0000, 0x0000, 0x0000 }, /* R11715 */ + { 0x0000, 0x0000, 0x0000 }, /* R11716 */ + { 0x0000, 0x0000, 0x0000 }, /* R11717 */ + { 0x0000, 0x0000, 0x0000 }, /* R11718 */ + { 0x0000, 0x0000, 0x0000 }, /* R11719 */ + { 0x0000, 0x0000, 0x0000 }, /* R11720 */ + { 0x0000, 0x0000, 0x0000 }, /* R11721 */ + { 0x0000, 0x0000, 0x0000 }, /* R11722 */ + { 0x0000, 0x0000, 0x0000 }, /* R11723 */ + { 0x0000, 0x0000, 0x0000 }, /* R11724 */ + { 0x0000, 0x0000, 0x0000 }, /* R11725 */ + { 0x0000, 0x0000, 0x0000 }, /* R11726 */ + { 0x0000, 0x0000, 0x0000 }, /* R11727 */ + { 0x0000, 0x0000, 0x0000 }, /* R11728 */ + { 0x0000, 0x0000, 0x0000 }, /* R11729 */ + { 0x0000, 0x0000, 0x0000 }, /* R11730 */ + { 0x0000, 0x0000, 0x0000 }, /* R11731 */ + { 0x0000, 0x0000, 0x0000 }, /* R11732 */ + { 0x0000, 0x0000, 0x0000 }, /* R11733 */ + { 0x0000, 0x0000, 0x0000 }, /* R11734 */ + { 0x0000, 0x0000, 0x0000 }, /* R11735 */ + { 0x0000, 0x0000, 0x0000 }, /* R11736 */ + { 0x0000, 0x0000, 0x0000 }, /* R11737 */ + { 0x0000, 0x0000, 0x0000 }, /* R11738 */ + { 0x0000, 0x0000, 0x0000 }, /* R11739 */ + { 0x0000, 0x0000, 0x0000 }, /* R11740 */ + { 0x0000, 0x0000, 0x0000 }, /* R11741 */ + { 0x0000, 0x0000, 0x0000 }, /* R11742 */ + { 0x0000, 0x0000, 0x0000 }, /* R11743 */ + { 0x0000, 0x0000, 0x0000 }, /* R11744 */ + { 0x0000, 0x0000, 0x0000 }, /* R11745 */ + { 0x0000, 0x0000, 0x0000 }, /* R11746 */ + { 0x0000, 0x0000, 0x0000 }, /* R11747 */ + { 0x0000, 0x0000, 0x0000 }, /* R11748 */ + { 0x0000, 0x0000, 0x0000 }, /* R11749 */ + { 0x0000, 0x0000, 0x0000 }, /* R11750 */ + { 0x0000, 0x0000, 0x0000 }, /* R11751 */ + { 0x0000, 0x0000, 0x0000 }, /* R11752 */ + { 0x0000, 0x0000, 0x0000 }, /* R11753 */ + { 0x0000, 0x0000, 0x0000 }, /* R11754 */ + { 0x0000, 0x0000, 0x0000 }, /* R11755 */ + { 0x0000, 0x0000, 0x0000 }, /* R11756 */ + { 0x0000, 0x0000, 0x0000 }, /* R11757 */ + { 0x0000, 0x0000, 0x0000 }, /* R11758 */ + { 0x0000, 0x0000, 0x0000 }, /* R11759 */ + { 0x0000, 0x0000, 0x0000 }, /* R11760 */ + { 0x0000, 0x0000, 0x0000 }, /* R11761 */ + { 0x0000, 0x0000, 0x0000 }, /* R11762 */ + { 0x0000, 0x0000, 0x0000 }, /* R11763 */ + { 0x0000, 0x0000, 0x0000 }, /* R11764 */ + { 0x0000, 0x0000, 0x0000 }, /* R11765 */ + { 0x0000, 0x0000, 0x0000 }, /* R11766 */ + { 0x0000, 0x0000, 0x0000 }, /* R11767 */ + { 0x0000, 0x0000, 0x0000 }, /* R11768 */ + { 0x0000, 0x0000, 0x0000 }, /* R11769 */ + { 0x0000, 0x0000, 0x0000 }, /* R11770 */ + { 0x0000, 0x0000, 0x0000 }, /* R11771 */ + { 0x0000, 0x0000, 0x0000 }, /* R11772 */ + { 0x0000, 0x0000, 0x0000 }, /* R11773 */ + { 0x0000, 0x0000, 0x0000 }, /* R11774 */ + { 0x0000, 0x0000, 0x0000 }, /* R11775 */ + { 0x0000, 0x0000, 0x0000 }, /* R11776 */ + { 0x0000, 0x0000, 0x0000 }, /* R11777 */ + { 0x0000, 0x0000, 0x0000 }, /* R11778 */ + { 0x0000, 0x0000, 0x0000 }, /* R11779 */ + { 0x0000, 0x0000, 0x0000 }, /* R11780 */ + { 0x0000, 0x0000, 0x0000 }, /* R11781 */ + { 0x0000, 0x0000, 0x0000 }, /* R11782 */ + { 0x0000, 0x0000, 0x0000 }, /* R11783 */ + { 0x0000, 0x0000, 0x0000 }, /* R11784 */ + { 0x0000, 0x0000, 0x0000 }, /* R11785 */ + { 0x0000, 0x0000, 0x0000 }, /* R11786 */ + { 0x0000, 0x0000, 0x0000 }, /* R11787 */ + { 0x0000, 0x0000, 0x0000 }, /* R11788 */ + { 0x0000, 0x0000, 0x0000 }, /* R11789 */ + { 0x0000, 0x0000, 0x0000 }, /* R11790 */ + { 0x0000, 0x0000, 0x0000 }, /* R11791 */ + { 0x0000, 0x0000, 0x0000 }, /* R11792 */ + { 0x0000, 0x0000, 0x0000 }, /* R11793 */ + { 0x0000, 0x0000, 0x0000 }, /* R11794 */ + { 0x0000, 0x0000, 0x0000 }, /* R11795 */ + { 0x0000, 0x0000, 0x0000 }, /* R11796 */ + { 0x0000, 0x0000, 0x0000 }, /* R11797 */ + { 0x0000, 0x0000, 0x0000 }, /* R11798 */ + { 0x0000, 0x0000, 0x0000 }, /* R11799 */ + { 0x0000, 0x0000, 0x0000 }, /* R11800 */ + { 0x0000, 0x0000, 0x0000 }, /* R11801 */ + { 0x0000, 0x0000, 0x0000 }, /* R11802 */ + { 0x0000, 0x0000, 0x0000 }, /* R11803 */ + { 0x0000, 0x0000, 0x0000 }, /* R11804 */ + { 0x0000, 0x0000, 0x0000 }, /* R11805 */ + { 0x0000, 0x0000, 0x0000 }, /* R11806 */ + { 0x0000, 0x0000, 0x0000 }, /* R11807 */ + { 0x0000, 0x0000, 0x0000 }, /* R11808 */ + { 0x0000, 0x0000, 0x0000 }, /* R11809 */ + { 0x0000, 0x0000, 0x0000 }, /* R11810 */ + { 0x0000, 0x0000, 0x0000 }, /* R11811 */ + { 0x0000, 0x0000, 0x0000 }, /* R11812 */ + { 0x0000, 0x0000, 0x0000 }, /* R11813 */ + { 0x0000, 0x0000, 0x0000 }, /* R11814 */ + { 0x0000, 0x0000, 0x0000 }, /* R11815 */ + { 0x0000, 0x0000, 0x0000 }, /* R11816 */ + { 0x0000, 0x0000, 0x0000 }, /* R11817 */ + { 0x0000, 0x0000, 0x0000 }, /* R11818 */ + { 0x0000, 0x0000, 0x0000 }, /* R11819 */ + { 0x0000, 0x0000, 0x0000 }, /* R11820 */ + { 0x0000, 0x0000, 0x0000 }, /* R11821 */ + { 0x0000, 0x0000, 0x0000 }, /* R11822 */ + { 0x0000, 0x0000, 0x0000 }, /* R11823 */ + { 0x0000, 0x0000, 0x0000 }, /* R11824 */ + { 0x0000, 0x0000, 0x0000 }, /* R11825 */ + { 0x0000, 0x0000, 0x0000 }, /* R11826 */ + { 0x0000, 0x0000, 0x0000 }, /* R11827 */ + { 0x0000, 0x0000, 0x0000 }, /* R11828 */ + { 0x0000, 0x0000, 0x0000 }, /* R11829 */ + { 0x0000, 0x0000, 0x0000 }, /* R11830 */ + { 0x0000, 0x0000, 0x0000 }, /* R11831 */ + { 0x0000, 0x0000, 0x0000 }, /* R11832 */ + { 0x0000, 0x0000, 0x0000 }, /* R11833 */ + { 0x0000, 0x0000, 0x0000 }, /* R11834 */ + { 0x0000, 0x0000, 0x0000 }, /* R11835 */ + { 0x0000, 0x0000, 0x0000 }, /* R11836 */ + { 0x0000, 0x0000, 0x0000 }, /* R11837 */ + { 0x0000, 0x0000, 0x0000 }, /* R11838 */ + { 0x0000, 0x0000, 0x0000 }, /* R11839 */ + { 0x0000, 0x0000, 0x0000 }, /* R11840 */ + { 0x0000, 0x0000, 0x0000 }, /* R11841 */ + { 0x0000, 0x0000, 0x0000 }, /* R11842 */ + { 0x0000, 0x0000, 0x0000 }, /* R11843 */ + { 0x0000, 0x0000, 0x0000 }, /* R11844 */ + { 0x0000, 0x0000, 0x0000 }, /* R11845 */ + { 0x0000, 0x0000, 0x0000 }, /* R11846 */ + { 0x0000, 0x0000, 0x0000 }, /* R11847 */ + { 0x0000, 0x0000, 0x0000 }, /* R11848 */ + { 0x0000, 0x0000, 0x0000 }, /* R11849 */ + { 0x0000, 0x0000, 0x0000 }, /* R11850 */ + { 0x0000, 0x0000, 0x0000 }, /* R11851 */ + { 0x0000, 0x0000, 0x0000 }, /* R11852 */ + { 0x0000, 0x0000, 0x0000 }, /* R11853 */ + { 0x0000, 0x0000, 0x0000 }, /* R11854 */ + { 0x0000, 0x0000, 0x0000 }, /* R11855 */ + { 0x0000, 0x0000, 0x0000 }, /* R11856 */ + { 0x0000, 0x0000, 0x0000 }, /* R11857 */ + { 0x0000, 0x0000, 0x0000 }, /* R11858 */ + { 0x0000, 0x0000, 0x0000 }, /* R11859 */ + { 0x0000, 0x0000, 0x0000 }, /* R11860 */ + { 0x0000, 0x0000, 0x0000 }, /* R11861 */ + { 0x0000, 0x0000, 0x0000 }, /* R11862 */ + { 0x0000, 0x0000, 0x0000 }, /* R11863 */ + { 0x0000, 0x0000, 0x0000 }, /* R11864 */ + { 0x0000, 0x0000, 0x0000 }, /* R11865 */ + { 0x0000, 0x0000, 0x0000 }, /* R11866 */ + { 0x0000, 0x0000, 0x0000 }, /* R11867 */ + { 0x0000, 0x0000, 0x0000 }, /* R11868 */ + { 0x0000, 0x0000, 0x0000 }, /* R11869 */ + { 0x0000, 0x0000, 0x0000 }, /* R11870 */ + { 0x0000, 0x0000, 0x0000 }, /* R11871 */ + { 0x0000, 0x0000, 0x0000 }, /* R11872 */ + { 0x0000, 0x0000, 0x0000 }, /* R11873 */ + { 0x0000, 0x0000, 0x0000 }, /* R11874 */ + { 0x0000, 0x0000, 0x0000 }, /* R11875 */ + { 0x0000, 0x0000, 0x0000 }, /* R11876 */ + { 0x0000, 0x0000, 0x0000 }, /* R11877 */ + { 0x0000, 0x0000, 0x0000 }, /* R11878 */ + { 0x0000, 0x0000, 0x0000 }, /* R11879 */ + { 0x0000, 0x0000, 0x0000 }, /* R11880 */ + { 0x0000, 0x0000, 0x0000 }, /* R11881 */ + { 0x0000, 0x0000, 0x0000 }, /* R11882 */ + { 0x0000, 0x0000, 0x0000 }, /* R11883 */ + { 0x0000, 0x0000, 0x0000 }, /* R11884 */ + { 0x0000, 0x0000, 0x0000 }, /* R11885 */ + { 0x0000, 0x0000, 0x0000 }, /* R11886 */ + { 0x0000, 0x0000, 0x0000 }, /* R11887 */ + { 0x0000, 0x0000, 0x0000 }, /* R11888 */ + { 0x0000, 0x0000, 0x0000 }, /* R11889 */ + { 0x0000, 0x0000, 0x0000 }, /* R11890 */ + { 0x0000, 0x0000, 0x0000 }, /* R11891 */ + { 0x0000, 0x0000, 0x0000 }, /* R11892 */ + { 0x0000, 0x0000, 0x0000 }, /* R11893 */ + { 0x0000, 0x0000, 0x0000 }, /* R11894 */ + { 0x0000, 0x0000, 0x0000 }, /* R11895 */ + { 0x0000, 0x0000, 0x0000 }, /* R11896 */ + { 0x0000, 0x0000, 0x0000 }, /* R11897 */ + { 0x0000, 0x0000, 0x0000 }, /* R11898 */ + { 0x0000, 0x0000, 0x0000 }, /* R11899 */ + { 0x0000, 0x0000, 0x0000 }, /* R11900 */ + { 0x0000, 0x0000, 0x0000 }, /* R11901 */ + { 0x0000, 0x0000, 0x0000 }, /* R11902 */ + { 0x0000, 0x0000, 0x0000 }, /* R11903 */ + { 0x0000, 0x0000, 0x0000 }, /* R11904 */ + { 0x0000, 0x0000, 0x0000 }, /* R11905 */ + { 0x0000, 0x0000, 0x0000 }, /* R11906 */ + { 0x0000, 0x0000, 0x0000 }, /* R11907 */ + { 0x0000, 0x0000, 0x0000 }, /* R11908 */ + { 0x0000, 0x0000, 0x0000 }, /* R11909 */ + { 0x0000, 0x0000, 0x0000 }, /* R11910 */ + { 0x0000, 0x0000, 0x0000 }, /* R11911 */ + { 0x0000, 0x0000, 0x0000 }, /* R11912 */ + { 0x0000, 0x0000, 0x0000 }, /* R11913 */ + { 0x0000, 0x0000, 0x0000 }, /* R11914 */ + { 0x0000, 0x0000, 0x0000 }, /* R11915 */ + { 0x0000, 0x0000, 0x0000 }, /* R11916 */ + { 0x0000, 0x0000, 0x0000 }, /* R11917 */ + { 0x0000, 0x0000, 0x0000 }, /* R11918 */ + { 0x0000, 0x0000, 0x0000 }, /* R11919 */ + { 0x0000, 0x0000, 0x0000 }, /* R11920 */ + { 0x0000, 0x0000, 0x0000 }, /* R11921 */ + { 0x0000, 0x0000, 0x0000 }, /* R11922 */ + { 0x0000, 0x0000, 0x0000 }, /* R11923 */ + { 0x0000, 0x0000, 0x0000 }, /* R11924 */ + { 0x0000, 0x0000, 0x0000 }, /* R11925 */ + { 0x0000, 0x0000, 0x0000 }, /* R11926 */ + { 0x0000, 0x0000, 0x0000 }, /* R11927 */ + { 0x0000, 0x0000, 0x0000 }, /* R11928 */ + { 0x0000, 0x0000, 0x0000 }, /* R11929 */ + { 0x0000, 0x0000, 0x0000 }, /* R11930 */ + { 0x0000, 0x0000, 0x0000 }, /* R11931 */ + { 0x0000, 0x0000, 0x0000 }, /* R11932 */ + { 0x0000, 0x0000, 0x0000 }, /* R11933 */ + { 0x0000, 0x0000, 0x0000 }, /* R11934 */ + { 0x0000, 0x0000, 0x0000 }, /* R11935 */ + { 0x0000, 0x0000, 0x0000 }, /* R11936 */ + { 0x0000, 0x0000, 0x0000 }, /* R11937 */ + { 0x0000, 0x0000, 0x0000 }, /* R11938 */ + { 0x0000, 0x0000, 0x0000 }, /* R11939 */ + { 0x0000, 0x0000, 0x0000 }, /* R11940 */ + { 0x0000, 0x0000, 0x0000 }, /* R11941 */ + { 0x0000, 0x0000, 0x0000 }, /* R11942 */ + { 0x0000, 0x0000, 0x0000 }, /* R11943 */ + { 0x0000, 0x0000, 0x0000 }, /* R11944 */ + { 0x0000, 0x0000, 0x0000 }, /* R11945 */ + { 0x0000, 0x0000, 0x0000 }, /* R11946 */ + { 0x0000, 0x0000, 0x0000 }, /* R11947 */ + { 0x0000, 0x0000, 0x0000 }, /* R11948 */ + { 0x0000, 0x0000, 0x0000 }, /* R11949 */ + { 0x0000, 0x0000, 0x0000 }, /* R11950 */ + { 0x0000, 0x0000, 0x0000 }, /* R11951 */ + { 0x0000, 0x0000, 0x0000 }, /* R11952 */ + { 0x0000, 0x0000, 0x0000 }, /* R11953 */ + { 0x0000, 0x0000, 0x0000 }, /* R11954 */ + { 0x0000, 0x0000, 0x0000 }, /* R11955 */ + { 0x0000, 0x0000, 0x0000 }, /* R11956 */ + { 0x0000, 0x0000, 0x0000 }, /* R11957 */ + { 0x0000, 0x0000, 0x0000 }, /* R11958 */ + { 0x0000, 0x0000, 0x0000 }, /* R11959 */ + { 0x0000, 0x0000, 0x0000 }, /* R11960 */ + { 0x0000, 0x0000, 0x0000 }, /* R11961 */ + { 0x0000, 0x0000, 0x0000 }, /* R11962 */ + { 0x0000, 0x0000, 0x0000 }, /* R11963 */ + { 0x0000, 0x0000, 0x0000 }, /* R11964 */ + { 0x0000, 0x0000, 0x0000 }, /* R11965 */ + { 0x0000, 0x0000, 0x0000 }, /* R11966 */ + { 0x0000, 0x0000, 0x0000 }, /* R11967 */ + { 0x0000, 0x0000, 0x0000 }, /* R11968 */ + { 0x0000, 0x0000, 0x0000 }, /* R11969 */ + { 0x0000, 0x0000, 0x0000 }, /* R11970 */ + { 0x0000, 0x0000, 0x0000 }, /* R11971 */ + { 0x0000, 0x0000, 0x0000 }, /* R11972 */ + { 0x0000, 0x0000, 0x0000 }, /* R11973 */ + { 0x0000, 0x0000, 0x0000 }, /* R11974 */ + { 0x0000, 0x0000, 0x0000 }, /* R11975 */ + { 0x0000, 0x0000, 0x0000 }, /* R11976 */ + { 0x0000, 0x0000, 0x0000 }, /* R11977 */ + { 0x0000, 0x0000, 0x0000 }, /* R11978 */ + { 0x0000, 0x0000, 0x0000 }, /* R11979 */ + { 0x0000, 0x0000, 0x0000 }, /* R11980 */ + { 0x0000, 0x0000, 0x0000 }, /* R11981 */ + { 0x0000, 0x0000, 0x0000 }, /* R11982 */ + { 0x0000, 0x0000, 0x0000 }, /* R11983 */ + { 0x0000, 0x0000, 0x0000 }, /* R11984 */ + { 0x0000, 0x0000, 0x0000 }, /* R11985 */ + { 0x0000, 0x0000, 0x0000 }, /* R11986 */ + { 0x0000, 0x0000, 0x0000 }, /* R11987 */ + { 0x0000, 0x0000, 0x0000 }, /* R11988 */ + { 0x0000, 0x0000, 0x0000 }, /* R11989 */ + { 0x0000, 0x0000, 0x0000 }, /* R11990 */ + { 0x0000, 0x0000, 0x0000 }, /* R11991 */ + { 0x0000, 0x0000, 0x0000 }, /* R11992 */ + { 0x0000, 0x0000, 0x0000 }, /* R11993 */ + { 0x0000, 0x0000, 0x0000 }, /* R11994 */ + { 0x0000, 0x0000, 0x0000 }, /* R11995 */ + { 0x0000, 0x0000, 0x0000 }, /* R11996 */ + { 0x0000, 0x0000, 0x0000 }, /* R11997 */ + { 0x0000, 0x0000, 0x0000 }, /* R11998 */ + { 0x0000, 0x0000, 0x0000 }, /* R11999 */ + { 0x0000, 0x0000, 0x0000 }, /* R12000 */ + { 0x0000, 0x0000, 0x0000 }, /* R12001 */ + { 0x0000, 0x0000, 0x0000 }, /* R12002 */ + { 0x0000, 0x0000, 0x0000 }, /* R12003 */ + { 0x0000, 0x0000, 0x0000 }, /* R12004 */ + { 0x0000, 0x0000, 0x0000 }, /* R12005 */ + { 0x0000, 0x0000, 0x0000 }, /* R12006 */ + { 0x0000, 0x0000, 0x0000 }, /* R12007 */ + { 0x0000, 0x0000, 0x0000 }, /* R12008 */ + { 0x0000, 0x0000, 0x0000 }, /* R12009 */ + { 0x0000, 0x0000, 0x0000 }, /* R12010 */ + { 0x0000, 0x0000, 0x0000 }, /* R12011 */ + { 0x0000, 0x0000, 0x0000 }, /* R12012 */ + { 0x0000, 0x0000, 0x0000 }, /* R12013 */ + { 0x0000, 0x0000, 0x0000 }, /* R12014 */ + { 0x0000, 0x0000, 0x0000 }, /* R12015 */ + { 0x0000, 0x0000, 0x0000 }, /* R12016 */ + { 0x0000, 0x0000, 0x0000 }, /* R12017 */ + { 0x0000, 0x0000, 0x0000 }, /* R12018 */ + { 0x0000, 0x0000, 0x0000 }, /* R12019 */ + { 0x0000, 0x0000, 0x0000 }, /* R12020 */ + { 0x0000, 0x0000, 0x0000 }, /* R12021 */ + { 0x0000, 0x0000, 0x0000 }, /* R12022 */ + { 0x0000, 0x0000, 0x0000 }, /* R12023 */ + { 0x0000, 0x0000, 0x0000 }, /* R12024 */ + { 0x0000, 0x0000, 0x0000 }, /* R12025 */ + { 0x0000, 0x0000, 0x0000 }, /* R12026 */ + { 0x0000, 0x0000, 0x0000 }, /* R12027 */ + { 0x0000, 0x0000, 0x0000 }, /* R12028 */ + { 0x0000, 0x0000, 0x0000 }, /* R12029 */ + { 0x0000, 0x0000, 0x0000 }, /* R12030 */ + { 0x0000, 0x0000, 0x0000 }, /* R12031 */ + { 0x0000, 0x0000, 0x0000 }, /* R12032 */ + { 0x0000, 0x0000, 0x0000 }, /* R12033 */ + { 0x0000, 0x0000, 0x0000 }, /* R12034 */ + { 0x0000, 0x0000, 0x0000 }, /* R12035 */ + { 0x0000, 0x0000, 0x0000 }, /* R12036 */ + { 0x0000, 0x0000, 0x0000 }, /* R12037 */ + { 0x0000, 0x0000, 0x0000 }, /* R12038 */ + { 0x0000, 0x0000, 0x0000 }, /* R12039 */ + { 0x0000, 0x0000, 0x0000 }, /* R12040 */ + { 0x0000, 0x0000, 0x0000 }, /* R12041 */ + { 0x0000, 0x0000, 0x0000 }, /* R12042 */ + { 0x0000, 0x0000, 0x0000 }, /* R12043 */ + { 0x0000, 0x0000, 0x0000 }, /* R12044 */ + { 0x0000, 0x0000, 0x0000 }, /* R12045 */ + { 0x0000, 0x0000, 0x0000 }, /* R12046 */ + { 0x0000, 0x0000, 0x0000 }, /* R12047 */ + { 0x0000, 0x0000, 0x0000 }, /* R12048 */ + { 0x0000, 0x0000, 0x0000 }, /* R12049 */ + { 0x0000, 0x0000, 0x0000 }, /* R12050 */ + { 0x0000, 0x0000, 0x0000 }, /* R12051 */ + { 0x0000, 0x0000, 0x0000 }, /* R12052 */ + { 0x0000, 0x0000, 0x0000 }, /* R12053 */ + { 0x0000, 0x0000, 0x0000 }, /* R12054 */ + { 0x0000, 0x0000, 0x0000 }, /* R12055 */ + { 0x0000, 0x0000, 0x0000 }, /* R12056 */ + { 0x0000, 0x0000, 0x0000 }, /* R12057 */ + { 0x0000, 0x0000, 0x0000 }, /* R12058 */ + { 0x0000, 0x0000, 0x0000 }, /* R12059 */ + { 0x0000, 0x0000, 0x0000 }, /* R12060 */ + { 0x0000, 0x0000, 0x0000 }, /* R12061 */ + { 0x0000, 0x0000, 0x0000 }, /* R12062 */ + { 0x0000, 0x0000, 0x0000 }, /* R12063 */ + { 0x0000, 0x0000, 0x0000 }, /* R12064 */ + { 0x0000, 0x0000, 0x0000 }, /* R12065 */ + { 0x0000, 0x0000, 0x0000 }, /* R12066 */ + { 0x0000, 0x0000, 0x0000 }, /* R12067 */ + { 0x0000, 0x0000, 0x0000 }, /* R12068 */ + { 0x0000, 0x0000, 0x0000 }, /* R12069 */ + { 0x0000, 0x0000, 0x0000 }, /* R12070 */ + { 0x0000, 0x0000, 0x0000 }, /* R12071 */ + { 0x0000, 0x0000, 0x0000 }, /* R12072 */ + { 0x0000, 0x0000, 0x0000 }, /* R12073 */ + { 0x0000, 0x0000, 0x0000 }, /* R12074 */ + { 0x0000, 0x0000, 0x0000 }, /* R12075 */ + { 0x0000, 0x0000, 0x0000 }, /* R12076 */ + { 0x0000, 0x0000, 0x0000 }, /* R12077 */ + { 0x0000, 0x0000, 0x0000 }, /* R12078 */ + { 0x0000, 0x0000, 0x0000 }, /* R12079 */ + { 0x0000, 0x0000, 0x0000 }, /* R12080 */ + { 0x0000, 0x0000, 0x0000 }, /* R12081 */ + { 0x0000, 0x0000, 0x0000 }, /* R12082 */ + { 0x0000, 0x0000, 0x0000 }, /* R12083 */ + { 0x0000, 0x0000, 0x0000 }, /* R12084 */ + { 0x0000, 0x0000, 0x0000 }, /* R12085 */ + { 0x0000, 0x0000, 0x0000 }, /* R12086 */ + { 0x0000, 0x0000, 0x0000 }, /* R12087 */ + { 0x0000, 0x0000, 0x0000 }, /* R12088 */ + { 0x0000, 0x0000, 0x0000 }, /* R12089 */ + { 0x0000, 0x0000, 0x0000 }, /* R12090 */ + { 0x0000, 0x0000, 0x0000 }, /* R12091 */ + { 0x0000, 0x0000, 0x0000 }, /* R12092 */ + { 0x0000, 0x0000, 0x0000 }, /* R12093 */ + { 0x0000, 0x0000, 0x0000 }, /* R12094 */ + { 0x0000, 0x0000, 0x0000 }, /* R12095 */ + { 0x0000, 0x0000, 0x0000 }, /* R12096 */ + { 0x0000, 0x0000, 0x0000 }, /* R12097 */ + { 0x0000, 0x0000, 0x0000 }, /* R12098 */ + { 0x0000, 0x0000, 0x0000 }, /* R12099 */ + { 0x0000, 0x0000, 0x0000 }, /* R12100 */ + { 0x0000, 0x0000, 0x0000 }, /* R12101 */ + { 0x0000, 0x0000, 0x0000 }, /* R12102 */ + { 0x0000, 0x0000, 0x0000 }, /* R12103 */ + { 0x0000, 0x0000, 0x0000 }, /* R12104 */ + { 0x0000, 0x0000, 0x0000 }, /* R12105 */ + { 0x0000, 0x0000, 0x0000 }, /* R12106 */ + { 0x0000, 0x0000, 0x0000 }, /* R12107 */ + { 0x0000, 0x0000, 0x0000 }, /* R12108 */ + { 0x0000, 0x0000, 0x0000 }, /* R12109 */ + { 0x0000, 0x0000, 0x0000 }, /* R12110 */ + { 0x0000, 0x0000, 0x0000 }, /* R12111 */ + { 0x0000, 0x0000, 0x0000 }, /* R12112 */ + { 0x0000, 0x0000, 0x0000 }, /* R12113 */ + { 0x0000, 0x0000, 0x0000 }, /* R12114 */ + { 0x0000, 0x0000, 0x0000 }, /* R12115 */ + { 0x0000, 0x0000, 0x0000 }, /* R12116 */ + { 0x0000, 0x0000, 0x0000 }, /* R12117 */ + { 0x0000, 0x0000, 0x0000 }, /* R12118 */ + { 0x0000, 0x0000, 0x0000 }, /* R12119 */ + { 0x0000, 0x0000, 0x0000 }, /* R12120 */ + { 0x0000, 0x0000, 0x0000 }, /* R12121 */ + { 0x0000, 0x0000, 0x0000 }, /* R12122 */ + { 0x0000, 0x0000, 0x0000 }, /* R12123 */ + { 0x0000, 0x0000, 0x0000 }, /* R12124 */ + { 0x0000, 0x0000, 0x0000 }, /* R12125 */ + { 0x0000, 0x0000, 0x0000 }, /* R12126 */ + { 0x0000, 0x0000, 0x0000 }, /* R12127 */ + { 0x0000, 0x0000, 0x0000 }, /* R12128 */ + { 0x0000, 0x0000, 0x0000 }, /* R12129 */ + { 0x0000, 0x0000, 0x0000 }, /* R12130 */ + { 0x0000, 0x0000, 0x0000 }, /* R12131 */ + { 0x0000, 0x0000, 0x0000 }, /* R12132 */ + { 0x0000, 0x0000, 0x0000 }, /* R12133 */ + { 0x0000, 0x0000, 0x0000 }, /* R12134 */ + { 0x0000, 0x0000, 0x0000 }, /* R12135 */ + { 0x0000, 0x0000, 0x0000 }, /* R12136 */ + { 0x0000, 0x0000, 0x0000 }, /* R12137 */ + { 0x0000, 0x0000, 0x0000 }, /* R12138 */ + { 0x0000, 0x0000, 0x0000 }, /* R12139 */ + { 0x0000, 0x0000, 0x0000 }, /* R12140 */ + { 0x0000, 0x0000, 0x0000 }, /* R12141 */ + { 0x0000, 0x0000, 0x0000 }, /* R12142 */ + { 0x0000, 0x0000, 0x0000 }, /* R12143 */ + { 0x0000, 0x0000, 0x0000 }, /* R12144 */ + { 0x0000, 0x0000, 0x0000 }, /* R12145 */ + { 0x0000, 0x0000, 0x0000 }, /* R12146 */ + { 0x0000, 0x0000, 0x0000 }, /* R12147 */ + { 0x0000, 0x0000, 0x0000 }, /* R12148 */ + { 0x0000, 0x0000, 0x0000 }, /* R12149 */ + { 0x0000, 0x0000, 0x0000 }, /* R12150 */ + { 0x0000, 0x0000, 0x0000 }, /* R12151 */ + { 0x0000, 0x0000, 0x0000 }, /* R12152 */ + { 0x0000, 0x0000, 0x0000 }, /* R12153 */ + { 0x0000, 0x0000, 0x0000 }, /* R12154 */ + { 0x0000, 0x0000, 0x0000 }, /* R12155 */ + { 0x0000, 0x0000, 0x0000 }, /* R12156 */ + { 0x0000, 0x0000, 0x0000 }, /* R12157 */ + { 0x0000, 0x0000, 0x0000 }, /* R12158 */ + { 0x0000, 0x0000, 0x0000 }, /* R12159 */ + { 0x0000, 0x0000, 0x0000 }, /* R12160 */ + { 0x0000, 0x0000, 0x0000 }, /* R12161 */ + { 0x0000, 0x0000, 0x0000 }, /* R12162 */ + { 0x0000, 0x0000, 0x0000 }, /* R12163 */ + { 0x0000, 0x0000, 0x0000 }, /* R12164 */ + { 0x0000, 0x0000, 0x0000 }, /* R12165 */ + { 0x0000, 0x0000, 0x0000 }, /* R12166 */ + { 0x0000, 0x0000, 0x0000 }, /* R12167 */ + { 0x0000, 0x0000, 0x0000 }, /* R12168 */ + { 0x0000, 0x0000, 0x0000 }, /* R12169 */ + { 0x0000, 0x0000, 0x0000 }, /* R12170 */ + { 0x0000, 0x0000, 0x0000 }, /* R12171 */ + { 0x0000, 0x0000, 0x0000 }, /* R12172 */ + { 0x0000, 0x0000, 0x0000 }, /* R12173 */ + { 0x0000, 0x0000, 0x0000 }, /* R12174 */ + { 0x0000, 0x0000, 0x0000 }, /* R12175 */ + { 0x0000, 0x0000, 0x0000 }, /* R12176 */ + { 0x0000, 0x0000, 0x0000 }, /* R12177 */ + { 0x0000, 0x0000, 0x0000 }, /* R12178 */ + { 0x0000, 0x0000, 0x0000 }, /* R12179 */ + { 0x0000, 0x0000, 0x0000 }, /* R12180 */ + { 0x0000, 0x0000, 0x0000 }, /* R12181 */ + { 0x0000, 0x0000, 0x0000 }, /* R12182 */ + { 0x0000, 0x0000, 0x0000 }, /* R12183 */ + { 0x0000, 0x0000, 0x0000 }, /* R12184 */ + { 0x0000, 0x0000, 0x0000 }, /* R12185 */ + { 0x0000, 0x0000, 0x0000 }, /* R12186 */ + { 0x0000, 0x0000, 0x0000 }, /* R12187 */ + { 0x0000, 0x0000, 0x0000 }, /* R12188 */ + { 0x0000, 0x0000, 0x0000 }, /* R12189 */ + { 0x0000, 0x0000, 0x0000 }, /* R12190 */ + { 0x0000, 0x0000, 0x0000 }, /* R12191 */ + { 0x0000, 0x0000, 0x0000 }, /* R12192 */ + { 0x0000, 0x0000, 0x0000 }, /* R12193 */ + { 0x0000, 0x0000, 0x0000 }, /* R12194 */ + { 0x0000, 0x0000, 0x0000 }, /* R12195 */ + { 0x0000, 0x0000, 0x0000 }, /* R12196 */ + { 0x0000, 0x0000, 0x0000 }, /* R12197 */ + { 0x0000, 0x0000, 0x0000 }, /* R12198 */ + { 0x0000, 0x0000, 0x0000 }, /* R12199 */ + { 0x0000, 0x0000, 0x0000 }, /* R12200 */ + { 0x0000, 0x0000, 0x0000 }, /* R12201 */ + { 0x0000, 0x0000, 0x0000 }, /* R12202 */ + { 0x0000, 0x0000, 0x0000 }, /* R12203 */ + { 0x0000, 0x0000, 0x0000 }, /* R12204 */ + { 0x0000, 0x0000, 0x0000 }, /* R12205 */ + { 0x0000, 0x0000, 0x0000 }, /* R12206 */ + { 0x0000, 0x0000, 0x0000 }, /* R12207 */ + { 0x0000, 0x0000, 0x0000 }, /* R12208 */ + { 0x0000, 0x0000, 0x0000 }, /* R12209 */ + { 0x0000, 0x0000, 0x0000 }, /* R12210 */ + { 0x0000, 0x0000, 0x0000 }, /* R12211 */ + { 0x0000, 0x0000, 0x0000 }, /* R12212 */ + { 0x0000, 0x0000, 0x0000 }, /* R12213 */ + { 0x0000, 0x0000, 0x0000 }, /* R12214 */ + { 0x0000, 0x0000, 0x0000 }, /* R12215 */ + { 0x0000, 0x0000, 0x0000 }, /* R12216 */ + { 0x0000, 0x0000, 0x0000 }, /* R12217 */ + { 0x0000, 0x0000, 0x0000 }, /* R12218 */ + { 0x0000, 0x0000, 0x0000 }, /* R12219 */ + { 0x0000, 0x0000, 0x0000 }, /* R12220 */ + { 0x0000, 0x0000, 0x0000 }, /* R12221 */ + { 0x0000, 0x0000, 0x0000 }, /* R12222 */ + { 0x0000, 0x0000, 0x0000 }, /* R12223 */ + { 0x0000, 0x0000, 0x0000 }, /* R12224 */ + { 0x0000, 0x0000, 0x0000 }, /* R12225 */ + { 0x0000, 0x0000, 0x0000 }, /* R12226 */ + { 0x0000, 0x0000, 0x0000 }, /* R12227 */ + { 0x0000, 0x0000, 0x0000 }, /* R12228 */ + { 0x0000, 0x0000, 0x0000 }, /* R12229 */ + { 0x0000, 0x0000, 0x0000 }, /* R12230 */ + { 0x0000, 0x0000, 0x0000 }, /* R12231 */ + { 0x0000, 0x0000, 0x0000 }, /* R12232 */ + { 0x0000, 0x0000, 0x0000 }, /* R12233 */ + { 0x0000, 0x0000, 0x0000 }, /* R12234 */ + { 0x0000, 0x0000, 0x0000 }, /* R12235 */ + { 0x0000, 0x0000, 0x0000 }, /* R12236 */ + { 0x0000, 0x0000, 0x0000 }, /* R12237 */ + { 0x0000, 0x0000, 0x0000 }, /* R12238 */ + { 0x0000, 0x0000, 0x0000 }, /* R12239 */ + { 0x0000, 0x0000, 0x0000 }, /* R12240 */ + { 0x0000, 0x0000, 0x0000 }, /* R12241 */ + { 0x0000, 0x0000, 0x0000 }, /* R12242 */ + { 0x0000, 0x0000, 0x0000 }, /* R12243 */ + { 0x0000, 0x0000, 0x0000 }, /* R12244 */ + { 0x0000, 0x0000, 0x0000 }, /* R12245 */ + { 0x0000, 0x0000, 0x0000 }, /* R12246 */ + { 0x0000, 0x0000, 0x0000 }, /* R12247 */ + { 0x0000, 0x0000, 0x0000 }, /* R12248 */ + { 0x0000, 0x0000, 0x0000 }, /* R12249 */ + { 0x0000, 0x0000, 0x0000 }, /* R12250 */ + { 0x0000, 0x0000, 0x0000 }, /* R12251 */ + { 0x0000, 0x0000, 0x0000 }, /* R12252 */ + { 0x0000, 0x0000, 0x0000 }, /* R12253 */ + { 0x0000, 0x0000, 0x0000 }, /* R12254 */ + { 0x0000, 0x0000, 0x0000 }, /* R12255 */ + { 0x0000, 0x0000, 0x0000 }, /* R12256 */ + { 0x0000, 0x0000, 0x0000 }, /* R12257 */ + { 0x0000, 0x0000, 0x0000 }, /* R12258 */ + { 0x0000, 0x0000, 0x0000 }, /* R12259 */ + { 0x0000, 0x0000, 0x0000 }, /* R12260 */ + { 0x0000, 0x0000, 0x0000 }, /* R12261 */ + { 0x0000, 0x0000, 0x0000 }, /* R12262 */ + { 0x0000, 0x0000, 0x0000 }, /* R12263 */ + { 0x0000, 0x0000, 0x0000 }, /* R12264 */ + { 0x0000, 0x0000, 0x0000 }, /* R12265 */ + { 0x0000, 0x0000, 0x0000 }, /* R12266 */ + { 0x0000, 0x0000, 0x0000 }, /* R12267 */ + { 0x0000, 0x0000, 0x0000 }, /* R12268 */ + { 0x0000, 0x0000, 0x0000 }, /* R12269 */ + { 0x0000, 0x0000, 0x0000 }, /* R12270 */ + { 0x0000, 0x0000, 0x0000 }, /* R12271 */ + { 0x0000, 0x0000, 0x0000 }, /* R12272 */ + { 0x0000, 0x0000, 0x0000 }, /* R12273 */ + { 0x0000, 0x0000, 0x0000 }, /* R12274 */ + { 0x0000, 0x0000, 0x0000 }, /* R12275 */ + { 0x0000, 0x0000, 0x0000 }, /* R12276 */ + { 0x0000, 0x0000, 0x0000 }, /* R12277 */ + { 0x0000, 0x0000, 0x0000 }, /* R12278 */ + { 0x0000, 0x0000, 0x0000 }, /* R12279 */ + { 0x0000, 0x0000, 0x0000 }, /* R12280 */ + { 0x0000, 0x0000, 0x0000 }, /* R12281 */ + { 0x0000, 0x0000, 0x0000 }, /* R12282 */ + { 0x0000, 0x0000, 0x0000 }, /* R12283 */ + { 0x0000, 0x0000, 0x0000 }, /* R12284 */ + { 0x0000, 0x0000, 0x0000 }, /* R12285 */ + { 0x0000, 0x0000, 0x0000 }, /* R12286 */ + { 0x0000, 0x0000, 0x0000 }, /* R12287 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R12288 - DSP2 Data1 RAM 1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R12289 - DSP2 Data1 RAM 0 */ + { 0x0000, 0x0000, 0x0000 }, /* R12290 */ + { 0x0000, 0x0000, 0x0000 }, /* R12291 */ + { 0x0000, 0x0000, 0x0000 }, /* R12292 */ + { 0x0000, 0x0000, 0x0000 }, /* R12293 */ + { 0x0000, 0x0000, 0x0000 }, /* R12294 */ + { 0x0000, 0x0000, 0x0000 }, /* R12295 */ + { 0x0000, 0x0000, 0x0000 }, /* R12296 */ + { 0x0000, 0x0000, 0x0000 }, /* R12297 */ + { 0x0000, 0x0000, 0x0000 }, /* R12298 */ + { 0x0000, 0x0000, 0x0000 }, /* R12299 */ + { 0x0000, 0x0000, 0x0000 }, /* R12300 */ + { 0x0000, 0x0000, 0x0000 }, /* R12301 */ + { 0x0000, 0x0000, 0x0000 }, /* R12302 */ + { 0x0000, 0x0000, 0x0000 }, /* R12303 */ + { 0x0000, 0x0000, 0x0000 }, /* R12304 */ + { 0x0000, 0x0000, 0x0000 }, /* R12305 */ + { 0x0000, 0x0000, 0x0000 }, /* R12306 */ + { 0x0000, 0x0000, 0x0000 }, /* R12307 */ + { 0x0000, 0x0000, 0x0000 }, /* R12308 */ + { 0x0000, 0x0000, 0x0000 }, /* R12309 */ + { 0x0000, 0x0000, 0x0000 }, /* R12310 */ + { 0x0000, 0x0000, 0x0000 }, /* R12311 */ + { 0x0000, 0x0000, 0x0000 }, /* R12312 */ + { 0x0000, 0x0000, 0x0000 }, /* R12313 */ + { 0x0000, 0x0000, 0x0000 }, /* R12314 */ + { 0x0000, 0x0000, 0x0000 }, /* R12315 */ + { 0x0000, 0x0000, 0x0000 }, /* R12316 */ + { 0x0000, 0x0000, 0x0000 }, /* R12317 */ + { 0x0000, 0x0000, 0x0000 }, /* R12318 */ + { 0x0000, 0x0000, 0x0000 }, /* R12319 */ + { 0x0000, 0x0000, 0x0000 }, /* R12320 */ + { 0x0000, 0x0000, 0x0000 }, /* R12321 */ + { 0x0000, 0x0000, 0x0000 }, /* R12322 */ + { 0x0000, 0x0000, 0x0000 }, /* R12323 */ + { 0x0000, 0x0000, 0x0000 }, /* R12324 */ + { 0x0000, 0x0000, 0x0000 }, /* R12325 */ + { 0x0000, 0x0000, 0x0000 }, /* R12326 */ + { 0x0000, 0x0000, 0x0000 }, /* R12327 */ + { 0x0000, 0x0000, 0x0000 }, /* R12328 */ + { 0x0000, 0x0000, 0x0000 }, /* R12329 */ + { 0x0000, 0x0000, 0x0000 }, /* R12330 */ + { 0x0000, 0x0000, 0x0000 }, /* R12331 */ + { 0x0000, 0x0000, 0x0000 }, /* R12332 */ + { 0x0000, 0x0000, 0x0000 }, /* R12333 */ + { 0x0000, 0x0000, 0x0000 }, /* R12334 */ + { 0x0000, 0x0000, 0x0000 }, /* R12335 */ + { 0x0000, 0x0000, 0x0000 }, /* R12336 */ + { 0x0000, 0x0000, 0x0000 }, /* R12337 */ + { 0x0000, 0x0000, 0x0000 }, /* R12338 */ + { 0x0000, 0x0000, 0x0000 }, /* R12339 */ + { 0x0000, 0x0000, 0x0000 }, /* R12340 */ + { 0x0000, 0x0000, 0x0000 }, /* R12341 */ + { 0x0000, 0x0000, 0x0000 }, /* R12342 */ + { 0x0000, 0x0000, 0x0000 }, /* R12343 */ + { 0x0000, 0x0000, 0x0000 }, /* R12344 */ + { 0x0000, 0x0000, 0x0000 }, /* R12345 */ + { 0x0000, 0x0000, 0x0000 }, /* R12346 */ + { 0x0000, 0x0000, 0x0000 }, /* R12347 */ + { 0x0000, 0x0000, 0x0000 }, /* R12348 */ + { 0x0000, 0x0000, 0x0000 }, /* R12349 */ + { 0x0000, 0x0000, 0x0000 }, /* R12350 */ + { 0x0000, 0x0000, 0x0000 }, /* R12351 */ + { 0x0000, 0x0000, 0x0000 }, /* R12352 */ + { 0x0000, 0x0000, 0x0000 }, /* R12353 */ + { 0x0000, 0x0000, 0x0000 }, /* R12354 */ + { 0x0000, 0x0000, 0x0000 }, /* R12355 */ + { 0x0000, 0x0000, 0x0000 }, /* R12356 */ + { 0x0000, 0x0000, 0x0000 }, /* R12357 */ + { 0x0000, 0x0000, 0x0000 }, /* R12358 */ + { 0x0000, 0x0000, 0x0000 }, /* R12359 */ + { 0x0000, 0x0000, 0x0000 }, /* R12360 */ + { 0x0000, 0x0000, 0x0000 }, /* R12361 */ + { 0x0000, 0x0000, 0x0000 }, /* R12362 */ + { 0x0000, 0x0000, 0x0000 }, /* R12363 */ + { 0x0000, 0x0000, 0x0000 }, /* R12364 */ + { 0x0000, 0x0000, 0x0000 }, /* R12365 */ + { 0x0000, 0x0000, 0x0000 }, /* R12366 */ + { 0x0000, 0x0000, 0x0000 }, /* R12367 */ + { 0x0000, 0x0000, 0x0000 }, /* R12368 */ + { 0x0000, 0x0000, 0x0000 }, /* R12369 */ + { 0x0000, 0x0000, 0x0000 }, /* R12370 */ + { 0x0000, 0x0000, 0x0000 }, /* R12371 */ + { 0x0000, 0x0000, 0x0000 }, /* R12372 */ + { 0x0000, 0x0000, 0x0000 }, /* R12373 */ + { 0x0000, 0x0000, 0x0000 }, /* R12374 */ + { 0x0000, 0x0000, 0x0000 }, /* R12375 */ + { 0x0000, 0x0000, 0x0000 }, /* R12376 */ + { 0x0000, 0x0000, 0x0000 }, /* R12377 */ + { 0x0000, 0x0000, 0x0000 }, /* R12378 */ + { 0x0000, 0x0000, 0x0000 }, /* R12379 */ + { 0x0000, 0x0000, 0x0000 }, /* R12380 */ + { 0x0000, 0x0000, 0x0000 }, /* R12381 */ + { 0x0000, 0x0000, 0x0000 }, /* R12382 */ + { 0x0000, 0x0000, 0x0000 }, /* R12383 */ + { 0x0000, 0x0000, 0x0000 }, /* R12384 */ + { 0x0000, 0x0000, 0x0000 }, /* R12385 */ + { 0x0000, 0x0000, 0x0000 }, /* R12386 */ + { 0x0000, 0x0000, 0x0000 }, /* R12387 */ + { 0x0000, 0x0000, 0x0000 }, /* R12388 */ + { 0x0000, 0x0000, 0x0000 }, /* R12389 */ + { 0x0000, 0x0000, 0x0000 }, /* R12390 */ + { 0x0000, 0x0000, 0x0000 }, /* R12391 */ + { 0x0000, 0x0000, 0x0000 }, /* R12392 */ + { 0x0000, 0x0000, 0x0000 }, /* R12393 */ + { 0x0000, 0x0000, 0x0000 }, /* R12394 */ + { 0x0000, 0x0000, 0x0000 }, /* R12395 */ + { 0x0000, 0x0000, 0x0000 }, /* R12396 */ + { 0x0000, 0x0000, 0x0000 }, /* R12397 */ + { 0x0000, 0x0000, 0x0000 }, /* R12398 */ + { 0x0000, 0x0000, 0x0000 }, /* R12399 */ + { 0x0000, 0x0000, 0x0000 }, /* R12400 */ + { 0x0000, 0x0000, 0x0000 }, /* R12401 */ + { 0x0000, 0x0000, 0x0000 }, /* R12402 */ + { 0x0000, 0x0000, 0x0000 }, /* R12403 */ + { 0x0000, 0x0000, 0x0000 }, /* R12404 */ + { 0x0000, 0x0000, 0x0000 }, /* R12405 */ + { 0x0000, 0x0000, 0x0000 }, /* R12406 */ + { 0x0000, 0x0000, 0x0000 }, /* R12407 */ + { 0x0000, 0x0000, 0x0000 }, /* R12408 */ + { 0x0000, 0x0000, 0x0000 }, /* R12409 */ + { 0x0000, 0x0000, 0x0000 }, /* R12410 */ + { 0x0000, 0x0000, 0x0000 }, /* R12411 */ + { 0x0000, 0x0000, 0x0000 }, /* R12412 */ + { 0x0000, 0x0000, 0x0000 }, /* R12413 */ + { 0x0000, 0x0000, 0x0000 }, /* R12414 */ + { 0x0000, 0x0000, 0x0000 }, /* R12415 */ + { 0x0000, 0x0000, 0x0000 }, /* R12416 */ + { 0x0000, 0x0000, 0x0000 }, /* R12417 */ + { 0x0000, 0x0000, 0x0000 }, /* R12418 */ + { 0x0000, 0x0000, 0x0000 }, /* R12419 */ + { 0x0000, 0x0000, 0x0000 }, /* R12420 */ + { 0x0000, 0x0000, 0x0000 }, /* R12421 */ + { 0x0000, 0x0000, 0x0000 }, /* R12422 */ + { 0x0000, 0x0000, 0x0000 }, /* R12423 */ + { 0x0000, 0x0000, 0x0000 }, /* R12424 */ + { 0x0000, 0x0000, 0x0000 }, /* R12425 */ + { 0x0000, 0x0000, 0x0000 }, /* R12426 */ + { 0x0000, 0x0000, 0x0000 }, /* R12427 */ + { 0x0000, 0x0000, 0x0000 }, /* R12428 */ + { 0x0000, 0x0000, 0x0000 }, /* R12429 */ + { 0x0000, 0x0000, 0x0000 }, /* R12430 */ + { 0x0000, 0x0000, 0x0000 }, /* R12431 */ + { 0x0000, 0x0000, 0x0000 }, /* R12432 */ + { 0x0000, 0x0000, 0x0000 }, /* R12433 */ + { 0x0000, 0x0000, 0x0000 }, /* R12434 */ + { 0x0000, 0x0000, 0x0000 }, /* R12435 */ + { 0x0000, 0x0000, 0x0000 }, /* R12436 */ + { 0x0000, 0x0000, 0x0000 }, /* R12437 */ + { 0x0000, 0x0000, 0x0000 }, /* R12438 */ + { 0x0000, 0x0000, 0x0000 }, /* R12439 */ + { 0x0000, 0x0000, 0x0000 }, /* R12440 */ + { 0x0000, 0x0000, 0x0000 }, /* R12441 */ + { 0x0000, 0x0000, 0x0000 }, /* R12442 */ + { 0x0000, 0x0000, 0x0000 }, /* R12443 */ + { 0x0000, 0x0000, 0x0000 }, /* R12444 */ + { 0x0000, 0x0000, 0x0000 }, /* R12445 */ + { 0x0000, 0x0000, 0x0000 }, /* R12446 */ + { 0x0000, 0x0000, 0x0000 }, /* R12447 */ + { 0x0000, 0x0000, 0x0000 }, /* R12448 */ + { 0x0000, 0x0000, 0x0000 }, /* R12449 */ + { 0x0000, 0x0000, 0x0000 }, /* R12450 */ + { 0x0000, 0x0000, 0x0000 }, /* R12451 */ + { 0x0000, 0x0000, 0x0000 }, /* R12452 */ + { 0x0000, 0x0000, 0x0000 }, /* R12453 */ + { 0x0000, 0x0000, 0x0000 }, /* R12454 */ + { 0x0000, 0x0000, 0x0000 }, /* R12455 */ + { 0x0000, 0x0000, 0x0000 }, /* R12456 */ + { 0x0000, 0x0000, 0x0000 }, /* R12457 */ + { 0x0000, 0x0000, 0x0000 }, /* R12458 */ + { 0x0000, 0x0000, 0x0000 }, /* R12459 */ + { 0x0000, 0x0000, 0x0000 }, /* R12460 */ + { 0x0000, 0x0000, 0x0000 }, /* R12461 */ + { 0x0000, 0x0000, 0x0000 }, /* R12462 */ + { 0x0000, 0x0000, 0x0000 }, /* R12463 */ + { 0x0000, 0x0000, 0x0000 }, /* R12464 */ + { 0x0000, 0x0000, 0x0000 }, /* R12465 */ + { 0x0000, 0x0000, 0x0000 }, /* R12466 */ + { 0x0000, 0x0000, 0x0000 }, /* R12467 */ + { 0x0000, 0x0000, 0x0000 }, /* R12468 */ + { 0x0000, 0x0000, 0x0000 }, /* R12469 */ + { 0x0000, 0x0000, 0x0000 }, /* R12470 */ + { 0x0000, 0x0000, 0x0000 }, /* R12471 */ + { 0x0000, 0x0000, 0x0000 }, /* R12472 */ + { 0x0000, 0x0000, 0x0000 }, /* R12473 */ + { 0x0000, 0x0000, 0x0000 }, /* R12474 */ + { 0x0000, 0x0000, 0x0000 }, /* R12475 */ + { 0x0000, 0x0000, 0x0000 }, /* R12476 */ + { 0x0000, 0x0000, 0x0000 }, /* R12477 */ + { 0x0000, 0x0000, 0x0000 }, /* R12478 */ + { 0x0000, 0x0000, 0x0000 }, /* R12479 */ + { 0x0000, 0x0000, 0x0000 }, /* R12480 */ + { 0x0000, 0x0000, 0x0000 }, /* R12481 */ + { 0x0000, 0x0000, 0x0000 }, /* R12482 */ + { 0x0000, 0x0000, 0x0000 }, /* R12483 */ + { 0x0000, 0x0000, 0x0000 }, /* R12484 */ + { 0x0000, 0x0000, 0x0000 }, /* R12485 */ + { 0x0000, 0x0000, 0x0000 }, /* R12486 */ + { 0x0000, 0x0000, 0x0000 }, /* R12487 */ + { 0x0000, 0x0000, 0x0000 }, /* R12488 */ + { 0x0000, 0x0000, 0x0000 }, /* R12489 */ + { 0x0000, 0x0000, 0x0000 }, /* R12490 */ + { 0x0000, 0x0000, 0x0000 }, /* R12491 */ + { 0x0000, 0x0000, 0x0000 }, /* R12492 */ + { 0x0000, 0x0000, 0x0000 }, /* R12493 */ + { 0x0000, 0x0000, 0x0000 }, /* R12494 */ + { 0x0000, 0x0000, 0x0000 }, /* R12495 */ + { 0x0000, 0x0000, 0x0000 }, /* R12496 */ + { 0x0000, 0x0000, 0x0000 }, /* R12497 */ + { 0x0000, 0x0000, 0x0000 }, /* R12498 */ + { 0x0000, 0x0000, 0x0000 }, /* R12499 */ + { 0x0000, 0x0000, 0x0000 }, /* R12500 */ + { 0x0000, 0x0000, 0x0000 }, /* R12501 */ + { 0x0000, 0x0000, 0x0000 }, /* R12502 */ + { 0x0000, 0x0000, 0x0000 }, /* R12503 */ + { 0x0000, 0x0000, 0x0000 }, /* R12504 */ + { 0x0000, 0x0000, 0x0000 }, /* R12505 */ + { 0x0000, 0x0000, 0x0000 }, /* R12506 */ + { 0x0000, 0x0000, 0x0000 }, /* R12507 */ + { 0x0000, 0x0000, 0x0000 }, /* R12508 */ + { 0x0000, 0x0000, 0x0000 }, /* R12509 */ + { 0x0000, 0x0000, 0x0000 }, /* R12510 */ + { 0x0000, 0x0000, 0x0000 }, /* R12511 */ + { 0x0000, 0x0000, 0x0000 }, /* R12512 */ + { 0x0000, 0x0000, 0x0000 }, /* R12513 */ + { 0x0000, 0x0000, 0x0000 }, /* R12514 */ + { 0x0000, 0x0000, 0x0000 }, /* R12515 */ + { 0x0000, 0x0000, 0x0000 }, /* R12516 */ + { 0x0000, 0x0000, 0x0000 }, /* R12517 */ + { 0x0000, 0x0000, 0x0000 }, /* R12518 */ + { 0x0000, 0x0000, 0x0000 }, /* R12519 */ + { 0x0000, 0x0000, 0x0000 }, /* R12520 */ + { 0x0000, 0x0000, 0x0000 }, /* R12521 */ + { 0x0000, 0x0000, 0x0000 }, /* R12522 */ + { 0x0000, 0x0000, 0x0000 }, /* R12523 */ + { 0x0000, 0x0000, 0x0000 }, /* R12524 */ + { 0x0000, 0x0000, 0x0000 }, /* R12525 */ + { 0x0000, 0x0000, 0x0000 }, /* R12526 */ + { 0x0000, 0x0000, 0x0000 }, /* R12527 */ + { 0x0000, 0x0000, 0x0000 }, /* R12528 */ + { 0x0000, 0x0000, 0x0000 }, /* R12529 */ + { 0x0000, 0x0000, 0x0000 }, /* R12530 */ + { 0x0000, 0x0000, 0x0000 }, /* R12531 */ + { 0x0000, 0x0000, 0x0000 }, /* R12532 */ + { 0x0000, 0x0000, 0x0000 }, /* R12533 */ + { 0x0000, 0x0000, 0x0000 }, /* R12534 */ + { 0x0000, 0x0000, 0x0000 }, /* R12535 */ + { 0x0000, 0x0000, 0x0000 }, /* R12536 */ + { 0x0000, 0x0000, 0x0000 }, /* R12537 */ + { 0x0000, 0x0000, 0x0000 }, /* R12538 */ + { 0x0000, 0x0000, 0x0000 }, /* R12539 */ + { 0x0000, 0x0000, 0x0000 }, /* R12540 */ + { 0x0000, 0x0000, 0x0000 }, /* R12541 */ + { 0x0000, 0x0000, 0x0000 }, /* R12542 */ + { 0x0000, 0x0000, 0x0000 }, /* R12543 */ + { 0x0000, 0x0000, 0x0000 }, /* R12544 */ + { 0x0000, 0x0000, 0x0000 }, /* R12545 */ + { 0x0000, 0x0000, 0x0000 }, /* R12546 */ + { 0x0000, 0x0000, 0x0000 }, /* R12547 */ + { 0x0000, 0x0000, 0x0000 }, /* R12548 */ + { 0x0000, 0x0000, 0x0000 }, /* R12549 */ + { 0x0000, 0x0000, 0x0000 }, /* R12550 */ + { 0x0000, 0x0000, 0x0000 }, /* R12551 */ + { 0x0000, 0x0000, 0x0000 }, /* R12552 */ + { 0x0000, 0x0000, 0x0000 }, /* R12553 */ + { 0x0000, 0x0000, 0x0000 }, /* R12554 */ + { 0x0000, 0x0000, 0x0000 }, /* R12555 */ + { 0x0000, 0x0000, 0x0000 }, /* R12556 */ + { 0x0000, 0x0000, 0x0000 }, /* R12557 */ + { 0x0000, 0x0000, 0x0000 }, /* R12558 */ + { 0x0000, 0x0000, 0x0000 }, /* R12559 */ + { 0x0000, 0x0000, 0x0000 }, /* R12560 */ + { 0x0000, 0x0000, 0x0000 }, /* R12561 */ + { 0x0000, 0x0000, 0x0000 }, /* R12562 */ + { 0x0000, 0x0000, 0x0000 }, /* R12563 */ + { 0x0000, 0x0000, 0x0000 }, /* R12564 */ + { 0x0000, 0x0000, 0x0000 }, /* R12565 */ + { 0x0000, 0x0000, 0x0000 }, /* R12566 */ + { 0x0000, 0x0000, 0x0000 }, /* R12567 */ + { 0x0000, 0x0000, 0x0000 }, /* R12568 */ + { 0x0000, 0x0000, 0x0000 }, /* R12569 */ + { 0x0000, 0x0000, 0x0000 }, /* R12570 */ + { 0x0000, 0x0000, 0x0000 }, /* R12571 */ + { 0x0000, 0x0000, 0x0000 }, /* R12572 */ + { 0x0000, 0x0000, 0x0000 }, /* R12573 */ + { 0x0000, 0x0000, 0x0000 }, /* R12574 */ + { 0x0000, 0x0000, 0x0000 }, /* R12575 */ + { 0x0000, 0x0000, 0x0000 }, /* R12576 */ + { 0x0000, 0x0000, 0x0000 }, /* R12577 */ + { 0x0000, 0x0000, 0x0000 }, /* R12578 */ + { 0x0000, 0x0000, 0x0000 }, /* R12579 */ + { 0x0000, 0x0000, 0x0000 }, /* R12580 */ + { 0x0000, 0x0000, 0x0000 }, /* R12581 */ + { 0x0000, 0x0000, 0x0000 }, /* R12582 */ + { 0x0000, 0x0000, 0x0000 }, /* R12583 */ + { 0x0000, 0x0000, 0x0000 }, /* R12584 */ + { 0x0000, 0x0000, 0x0000 }, /* R12585 */ + { 0x0000, 0x0000, 0x0000 }, /* R12586 */ + { 0x0000, 0x0000, 0x0000 }, /* R12587 */ + { 0x0000, 0x0000, 0x0000 }, /* R12588 */ + { 0x0000, 0x0000, 0x0000 }, /* R12589 */ + { 0x0000, 0x0000, 0x0000 }, /* R12590 */ + { 0x0000, 0x0000, 0x0000 }, /* R12591 */ + { 0x0000, 0x0000, 0x0000 }, /* R12592 */ + { 0x0000, 0x0000, 0x0000 }, /* R12593 */ + { 0x0000, 0x0000, 0x0000 }, /* R12594 */ + { 0x0000, 0x0000, 0x0000 }, /* R12595 */ + { 0x0000, 0x0000, 0x0000 }, /* R12596 */ + { 0x0000, 0x0000, 0x0000 }, /* R12597 */ + { 0x0000, 0x0000, 0x0000 }, /* R12598 */ + { 0x0000, 0x0000, 0x0000 }, /* R12599 */ + { 0x0000, 0x0000, 0x0000 }, /* R12600 */ + { 0x0000, 0x0000, 0x0000 }, /* R12601 */ + { 0x0000, 0x0000, 0x0000 }, /* R12602 */ + { 0x0000, 0x0000, 0x0000 }, /* R12603 */ + { 0x0000, 0x0000, 0x0000 }, /* R12604 */ + { 0x0000, 0x0000, 0x0000 }, /* R12605 */ + { 0x0000, 0x0000, 0x0000 }, /* R12606 */ + { 0x0000, 0x0000, 0x0000 }, /* R12607 */ + { 0x0000, 0x0000, 0x0000 }, /* R12608 */ + { 0x0000, 0x0000, 0x0000 }, /* R12609 */ + { 0x0000, 0x0000, 0x0000 }, /* R12610 */ + { 0x0000, 0x0000, 0x0000 }, /* R12611 */ + { 0x0000, 0x0000, 0x0000 }, /* R12612 */ + { 0x0000, 0x0000, 0x0000 }, /* R12613 */ + { 0x0000, 0x0000, 0x0000 }, /* R12614 */ + { 0x0000, 0x0000, 0x0000 }, /* R12615 */ + { 0x0000, 0x0000, 0x0000 }, /* R12616 */ + { 0x0000, 0x0000, 0x0000 }, /* R12617 */ + { 0x0000, 0x0000, 0x0000 }, /* R12618 */ + { 0x0000, 0x0000, 0x0000 }, /* R12619 */ + { 0x0000, 0x0000, 0x0000 }, /* R12620 */ + { 0x0000, 0x0000, 0x0000 }, /* R12621 */ + { 0x0000, 0x0000, 0x0000 }, /* R12622 */ + { 0x0000, 0x0000, 0x0000 }, /* R12623 */ + { 0x0000, 0x0000, 0x0000 }, /* R12624 */ + { 0x0000, 0x0000, 0x0000 }, /* R12625 */ + { 0x0000, 0x0000, 0x0000 }, /* R12626 */ + { 0x0000, 0x0000, 0x0000 }, /* R12627 */ + { 0x0000, 0x0000, 0x0000 }, /* R12628 */ + { 0x0000, 0x0000, 0x0000 }, /* R12629 */ + { 0x0000, 0x0000, 0x0000 }, /* R12630 */ + { 0x0000, 0x0000, 0x0000 }, /* R12631 */ + { 0x0000, 0x0000, 0x0000 }, /* R12632 */ + { 0x0000, 0x0000, 0x0000 }, /* R12633 */ + { 0x0000, 0x0000, 0x0000 }, /* R12634 */ + { 0x0000, 0x0000, 0x0000 }, /* R12635 */ + { 0x0000, 0x0000, 0x0000 }, /* R12636 */ + { 0x0000, 0x0000, 0x0000 }, /* R12637 */ + { 0x0000, 0x0000, 0x0000 }, /* R12638 */ + { 0x0000, 0x0000, 0x0000 }, /* R12639 */ + { 0x0000, 0x0000, 0x0000 }, /* R12640 */ + { 0x0000, 0x0000, 0x0000 }, /* R12641 */ + { 0x0000, 0x0000, 0x0000 }, /* R12642 */ + { 0x0000, 0x0000, 0x0000 }, /* R12643 */ + { 0x0000, 0x0000, 0x0000 }, /* R12644 */ + { 0x0000, 0x0000, 0x0000 }, /* R12645 */ + { 0x0000, 0x0000, 0x0000 }, /* R12646 */ + { 0x0000, 0x0000, 0x0000 }, /* R12647 */ + { 0x0000, 0x0000, 0x0000 }, /* R12648 */ + { 0x0000, 0x0000, 0x0000 }, /* R12649 */ + { 0x0000, 0x0000, 0x0000 }, /* R12650 */ + { 0x0000, 0x0000, 0x0000 }, /* R12651 */ + { 0x0000, 0x0000, 0x0000 }, /* R12652 */ + { 0x0000, 0x0000, 0x0000 }, /* R12653 */ + { 0x0000, 0x0000, 0x0000 }, /* R12654 */ + { 0x0000, 0x0000, 0x0000 }, /* R12655 */ + { 0x0000, 0x0000, 0x0000 }, /* R12656 */ + { 0x0000, 0x0000, 0x0000 }, /* R12657 */ + { 0x0000, 0x0000, 0x0000 }, /* R12658 */ + { 0x0000, 0x0000, 0x0000 }, /* R12659 */ + { 0x0000, 0x0000, 0x0000 }, /* R12660 */ + { 0x0000, 0x0000, 0x0000 }, /* R12661 */ + { 0x0000, 0x0000, 0x0000 }, /* R12662 */ + { 0x0000, 0x0000, 0x0000 }, /* R12663 */ + { 0x0000, 0x0000, 0x0000 }, /* R12664 */ + { 0x0000, 0x0000, 0x0000 }, /* R12665 */ + { 0x0000, 0x0000, 0x0000 }, /* R12666 */ + { 0x0000, 0x0000, 0x0000 }, /* R12667 */ + { 0x0000, 0x0000, 0x0000 }, /* R12668 */ + { 0x0000, 0x0000, 0x0000 }, /* R12669 */ + { 0x0000, 0x0000, 0x0000 }, /* R12670 */ + { 0x0000, 0x0000, 0x0000 }, /* R12671 */ + { 0x0000, 0x0000, 0x0000 }, /* R12672 */ + { 0x0000, 0x0000, 0x0000 }, /* R12673 */ + { 0x0000, 0x0000, 0x0000 }, /* R12674 */ + { 0x0000, 0x0000, 0x0000 }, /* R12675 */ + { 0x0000, 0x0000, 0x0000 }, /* R12676 */ + { 0x0000, 0x0000, 0x0000 }, /* R12677 */ + { 0x0000, 0x0000, 0x0000 }, /* R12678 */ + { 0x0000, 0x0000, 0x0000 }, /* R12679 */ + { 0x0000, 0x0000, 0x0000 }, /* R12680 */ + { 0x0000, 0x0000, 0x0000 }, /* R12681 */ + { 0x0000, 0x0000, 0x0000 }, /* R12682 */ + { 0x0000, 0x0000, 0x0000 }, /* R12683 */ + { 0x0000, 0x0000, 0x0000 }, /* R12684 */ + { 0x0000, 0x0000, 0x0000 }, /* R12685 */ + { 0x0000, 0x0000, 0x0000 }, /* R12686 */ + { 0x0000, 0x0000, 0x0000 }, /* R12687 */ + { 0x0000, 0x0000, 0x0000 }, /* R12688 */ + { 0x0000, 0x0000, 0x0000 }, /* R12689 */ + { 0x0000, 0x0000, 0x0000 }, /* R12690 */ + { 0x0000, 0x0000, 0x0000 }, /* R12691 */ + { 0x0000, 0x0000, 0x0000 }, /* R12692 */ + { 0x0000, 0x0000, 0x0000 }, /* R12693 */ + { 0x0000, 0x0000, 0x0000 }, /* R12694 */ + { 0x0000, 0x0000, 0x0000 }, /* R12695 */ + { 0x0000, 0x0000, 0x0000 }, /* R12696 */ + { 0x0000, 0x0000, 0x0000 }, /* R12697 */ + { 0x0000, 0x0000, 0x0000 }, /* R12698 */ + { 0x0000, 0x0000, 0x0000 }, /* R12699 */ + { 0x0000, 0x0000, 0x0000 }, /* R12700 */ + { 0x0000, 0x0000, 0x0000 }, /* R12701 */ + { 0x0000, 0x0000, 0x0000 }, /* R12702 */ + { 0x0000, 0x0000, 0x0000 }, /* R12703 */ + { 0x0000, 0x0000, 0x0000 }, /* R12704 */ + { 0x0000, 0x0000, 0x0000 }, /* R12705 */ + { 0x0000, 0x0000, 0x0000 }, /* R12706 */ + { 0x0000, 0x0000, 0x0000 }, /* R12707 */ + { 0x0000, 0x0000, 0x0000 }, /* R12708 */ + { 0x0000, 0x0000, 0x0000 }, /* R12709 */ + { 0x0000, 0x0000, 0x0000 }, /* R12710 */ + { 0x0000, 0x0000, 0x0000 }, /* R12711 */ + { 0x0000, 0x0000, 0x0000 }, /* R12712 */ + { 0x0000, 0x0000, 0x0000 }, /* R12713 */ + { 0x0000, 0x0000, 0x0000 }, /* R12714 */ + { 0x0000, 0x0000, 0x0000 }, /* R12715 */ + { 0x0000, 0x0000, 0x0000 }, /* R12716 */ + { 0x0000, 0x0000, 0x0000 }, /* R12717 */ + { 0x0000, 0x0000, 0x0000 }, /* R12718 */ + { 0x0000, 0x0000, 0x0000 }, /* R12719 */ + { 0x0000, 0x0000, 0x0000 }, /* R12720 */ + { 0x0000, 0x0000, 0x0000 }, /* R12721 */ + { 0x0000, 0x0000, 0x0000 }, /* R12722 */ + { 0x0000, 0x0000, 0x0000 }, /* R12723 */ + { 0x0000, 0x0000, 0x0000 }, /* R12724 */ + { 0x0000, 0x0000, 0x0000 }, /* R12725 */ + { 0x0000, 0x0000, 0x0000 }, /* R12726 */ + { 0x0000, 0x0000, 0x0000 }, /* R12727 */ + { 0x0000, 0x0000, 0x0000 }, /* R12728 */ + { 0x0000, 0x0000, 0x0000 }, /* R12729 */ + { 0x0000, 0x0000, 0x0000 }, /* R12730 */ + { 0x0000, 0x0000, 0x0000 }, /* R12731 */ + { 0x0000, 0x0000, 0x0000 }, /* R12732 */ + { 0x0000, 0x0000, 0x0000 }, /* R12733 */ + { 0x0000, 0x0000, 0x0000 }, /* R12734 */ + { 0x0000, 0x0000, 0x0000 }, /* R12735 */ + { 0x0000, 0x0000, 0x0000 }, /* R12736 */ + { 0x0000, 0x0000, 0x0000 }, /* R12737 */ + { 0x0000, 0x0000, 0x0000 }, /* R12738 */ + { 0x0000, 0x0000, 0x0000 }, /* R12739 */ + { 0x0000, 0x0000, 0x0000 }, /* R12740 */ + { 0x0000, 0x0000, 0x0000 }, /* R12741 */ + { 0x0000, 0x0000, 0x0000 }, /* R12742 */ + { 0x0000, 0x0000, 0x0000 }, /* R12743 */ + { 0x0000, 0x0000, 0x0000 }, /* R12744 */ + { 0x0000, 0x0000, 0x0000 }, /* R12745 */ + { 0x0000, 0x0000, 0x0000 }, /* R12746 */ + { 0x0000, 0x0000, 0x0000 }, /* R12747 */ + { 0x0000, 0x0000, 0x0000 }, /* R12748 */ + { 0x0000, 0x0000, 0x0000 }, /* R12749 */ + { 0x0000, 0x0000, 0x0000 }, /* R12750 */ + { 0x0000, 0x0000, 0x0000 }, /* R12751 */ + { 0x0000, 0x0000, 0x0000 }, /* R12752 */ + { 0x0000, 0x0000, 0x0000 }, /* R12753 */ + { 0x0000, 0x0000, 0x0000 }, /* R12754 */ + { 0x0000, 0x0000, 0x0000 }, /* R12755 */ + { 0x0000, 0x0000, 0x0000 }, /* R12756 */ + { 0x0000, 0x0000, 0x0000 }, /* R12757 */ + { 0x0000, 0x0000, 0x0000 }, /* R12758 */ + { 0x0000, 0x0000, 0x0000 }, /* R12759 */ + { 0x0000, 0x0000, 0x0000 }, /* R12760 */ + { 0x0000, 0x0000, 0x0000 }, /* R12761 */ + { 0x0000, 0x0000, 0x0000 }, /* R12762 */ + { 0x0000, 0x0000, 0x0000 }, /* R12763 */ + { 0x0000, 0x0000, 0x0000 }, /* R12764 */ + { 0x0000, 0x0000, 0x0000 }, /* R12765 */ + { 0x0000, 0x0000, 0x0000 }, /* R12766 */ + { 0x0000, 0x0000, 0x0000 }, /* R12767 */ + { 0x0000, 0x0000, 0x0000 }, /* R12768 */ + { 0x0000, 0x0000, 0x0000 }, /* R12769 */ + { 0x0000, 0x0000, 0x0000 }, /* R12770 */ + { 0x0000, 0x0000, 0x0000 }, /* R12771 */ + { 0x0000, 0x0000, 0x0000 }, /* R12772 */ + { 0x0000, 0x0000, 0x0000 }, /* R12773 */ + { 0x0000, 0x0000, 0x0000 }, /* R12774 */ + { 0x0000, 0x0000, 0x0000 }, /* R12775 */ + { 0x0000, 0x0000, 0x0000 }, /* R12776 */ + { 0x0000, 0x0000, 0x0000 }, /* R12777 */ + { 0x0000, 0x0000, 0x0000 }, /* R12778 */ + { 0x0000, 0x0000, 0x0000 }, /* R12779 */ + { 0x0000, 0x0000, 0x0000 }, /* R12780 */ + { 0x0000, 0x0000, 0x0000 }, /* R12781 */ + { 0x0000, 0x0000, 0x0000 }, /* R12782 */ + { 0x0000, 0x0000, 0x0000 }, /* R12783 */ + { 0x0000, 0x0000, 0x0000 }, /* R12784 */ + { 0x0000, 0x0000, 0x0000 }, /* R12785 */ + { 0x0000, 0x0000, 0x0000 }, /* R12786 */ + { 0x0000, 0x0000, 0x0000 }, /* R12787 */ + { 0x0000, 0x0000, 0x0000 }, /* R12788 */ + { 0x0000, 0x0000, 0x0000 }, /* R12789 */ + { 0x0000, 0x0000, 0x0000 }, /* R12790 */ + { 0x0000, 0x0000, 0x0000 }, /* R12791 */ + { 0x0000, 0x0000, 0x0000 }, /* R12792 */ + { 0x0000, 0x0000, 0x0000 }, /* R12793 */ + { 0x0000, 0x0000, 0x0000 }, /* R12794 */ + { 0x0000, 0x0000, 0x0000 }, /* R12795 */ + { 0x0000, 0x0000, 0x0000 }, /* R12796 */ + { 0x0000, 0x0000, 0x0000 }, /* R12797 */ + { 0x0000, 0x0000, 0x0000 }, /* R12798 */ + { 0x0000, 0x0000, 0x0000 }, /* R12799 */ + { 0x0000, 0x0000, 0x0000 }, /* R12800 */ + { 0x0000, 0x0000, 0x0000 }, /* R12801 */ + { 0x0000, 0x0000, 0x0000 }, /* R12802 */ + { 0x0000, 0x0000, 0x0000 }, /* R12803 */ + { 0x0000, 0x0000, 0x0000 }, /* R12804 */ + { 0x0000, 0x0000, 0x0000 }, /* R12805 */ + { 0x0000, 0x0000, 0x0000 }, /* R12806 */ + { 0x0000, 0x0000, 0x0000 }, /* R12807 */ + { 0x0000, 0x0000, 0x0000 }, /* R12808 */ + { 0x0000, 0x0000, 0x0000 }, /* R12809 */ + { 0x0000, 0x0000, 0x0000 }, /* R12810 */ + { 0x0000, 0x0000, 0x0000 }, /* R12811 */ + { 0x0000, 0x0000, 0x0000 }, /* R12812 */ + { 0x0000, 0x0000, 0x0000 }, /* R12813 */ + { 0x0000, 0x0000, 0x0000 }, /* R12814 */ + { 0x0000, 0x0000, 0x0000 }, /* R12815 */ + { 0x0000, 0x0000, 0x0000 }, /* R12816 */ + { 0x0000, 0x0000, 0x0000 }, /* R12817 */ + { 0x0000, 0x0000, 0x0000 }, /* R12818 */ + { 0x0000, 0x0000, 0x0000 }, /* R12819 */ + { 0x0000, 0x0000, 0x0000 }, /* R12820 */ + { 0x0000, 0x0000, 0x0000 }, /* R12821 */ + { 0x0000, 0x0000, 0x0000 }, /* R12822 */ + { 0x0000, 0x0000, 0x0000 }, /* R12823 */ + { 0x0000, 0x0000, 0x0000 }, /* R12824 */ + { 0x0000, 0x0000, 0x0000 }, /* R12825 */ + { 0x0000, 0x0000, 0x0000 }, /* R12826 */ + { 0x0000, 0x0000, 0x0000 }, /* R12827 */ + { 0x0000, 0x0000, 0x0000 }, /* R12828 */ + { 0x0000, 0x0000, 0x0000 }, /* R12829 */ + { 0x0000, 0x0000, 0x0000 }, /* R12830 */ + { 0x0000, 0x0000, 0x0000 }, /* R12831 */ + { 0x0000, 0x0000, 0x0000 }, /* R12832 */ + { 0x0000, 0x0000, 0x0000 }, /* R12833 */ + { 0x0000, 0x0000, 0x0000 }, /* R12834 */ + { 0x0000, 0x0000, 0x0000 }, /* R12835 */ + { 0x0000, 0x0000, 0x0000 }, /* R12836 */ + { 0x0000, 0x0000, 0x0000 }, /* R12837 */ + { 0x0000, 0x0000, 0x0000 }, /* R12838 */ + { 0x0000, 0x0000, 0x0000 }, /* R12839 */ + { 0x0000, 0x0000, 0x0000 }, /* R12840 */ + { 0x0000, 0x0000, 0x0000 }, /* R12841 */ + { 0x0000, 0x0000, 0x0000 }, /* R12842 */ + { 0x0000, 0x0000, 0x0000 }, /* R12843 */ + { 0x0000, 0x0000, 0x0000 }, /* R12844 */ + { 0x0000, 0x0000, 0x0000 }, /* R12845 */ + { 0x0000, 0x0000, 0x0000 }, /* R12846 */ + { 0x0000, 0x0000, 0x0000 }, /* R12847 */ + { 0x0000, 0x0000, 0x0000 }, /* R12848 */ + { 0x0000, 0x0000, 0x0000 }, /* R12849 */ + { 0x0000, 0x0000, 0x0000 }, /* R12850 */ + { 0x0000, 0x0000, 0x0000 }, /* R12851 */ + { 0x0000, 0x0000, 0x0000 }, /* R12852 */ + { 0x0000, 0x0000, 0x0000 }, /* R12853 */ + { 0x0000, 0x0000, 0x0000 }, /* R12854 */ + { 0x0000, 0x0000, 0x0000 }, /* R12855 */ + { 0x0000, 0x0000, 0x0000 }, /* R12856 */ + { 0x0000, 0x0000, 0x0000 }, /* R12857 */ + { 0x0000, 0x0000, 0x0000 }, /* R12858 */ + { 0x0000, 0x0000, 0x0000 }, /* R12859 */ + { 0x0000, 0x0000, 0x0000 }, /* R12860 */ + { 0x0000, 0x0000, 0x0000 }, /* R12861 */ + { 0x0000, 0x0000, 0x0000 }, /* R12862 */ + { 0x0000, 0x0000, 0x0000 }, /* R12863 */ + { 0x0000, 0x0000, 0x0000 }, /* R12864 */ + { 0x0000, 0x0000, 0x0000 }, /* R12865 */ + { 0x0000, 0x0000, 0x0000 }, /* R12866 */ + { 0x0000, 0x0000, 0x0000 }, /* R12867 */ + { 0x0000, 0x0000, 0x0000 }, /* R12868 */ + { 0x0000, 0x0000, 0x0000 }, /* R12869 */ + { 0x0000, 0x0000, 0x0000 }, /* R12870 */ + { 0x0000, 0x0000, 0x0000 }, /* R12871 */ + { 0x0000, 0x0000, 0x0000 }, /* R12872 */ + { 0x0000, 0x0000, 0x0000 }, /* R12873 */ + { 0x0000, 0x0000, 0x0000 }, /* R12874 */ + { 0x0000, 0x0000, 0x0000 }, /* R12875 */ + { 0x0000, 0x0000, 0x0000 }, /* R12876 */ + { 0x0000, 0x0000, 0x0000 }, /* R12877 */ + { 0x0000, 0x0000, 0x0000 }, /* R12878 */ + { 0x0000, 0x0000, 0x0000 }, /* R12879 */ + { 0x0000, 0x0000, 0x0000 }, /* R12880 */ + { 0x0000, 0x0000, 0x0000 }, /* R12881 */ + { 0x0000, 0x0000, 0x0000 }, /* R12882 */ + { 0x0000, 0x0000, 0x0000 }, /* R12883 */ + { 0x0000, 0x0000, 0x0000 }, /* R12884 */ + { 0x0000, 0x0000, 0x0000 }, /* R12885 */ + { 0x0000, 0x0000, 0x0000 }, /* R12886 */ + { 0x0000, 0x0000, 0x0000 }, /* R12887 */ + { 0x0000, 0x0000, 0x0000 }, /* R12888 */ + { 0x0000, 0x0000, 0x0000 }, /* R12889 */ + { 0x0000, 0x0000, 0x0000 }, /* R12890 */ + { 0x0000, 0x0000, 0x0000 }, /* R12891 */ + { 0x0000, 0x0000, 0x0000 }, /* R12892 */ + { 0x0000, 0x0000, 0x0000 }, /* R12893 */ + { 0x0000, 0x0000, 0x0000 }, /* R12894 */ + { 0x0000, 0x0000, 0x0000 }, /* R12895 */ + { 0x0000, 0x0000, 0x0000 }, /* R12896 */ + { 0x0000, 0x0000, 0x0000 }, /* R12897 */ + { 0x0000, 0x0000, 0x0000 }, /* R12898 */ + { 0x0000, 0x0000, 0x0000 }, /* R12899 */ + { 0x0000, 0x0000, 0x0000 }, /* R12900 */ + { 0x0000, 0x0000, 0x0000 }, /* R12901 */ + { 0x0000, 0x0000, 0x0000 }, /* R12902 */ + { 0x0000, 0x0000, 0x0000 }, /* R12903 */ + { 0x0000, 0x0000, 0x0000 }, /* R12904 */ + { 0x0000, 0x0000, 0x0000 }, /* R12905 */ + { 0x0000, 0x0000, 0x0000 }, /* R12906 */ + { 0x0000, 0x0000, 0x0000 }, /* R12907 */ + { 0x0000, 0x0000, 0x0000 }, /* R12908 */ + { 0x0000, 0x0000, 0x0000 }, /* R12909 */ + { 0x0000, 0x0000, 0x0000 }, /* R12910 */ + { 0x0000, 0x0000, 0x0000 }, /* R12911 */ + { 0x0000, 0x0000, 0x0000 }, /* R12912 */ + { 0x0000, 0x0000, 0x0000 }, /* R12913 */ + { 0x0000, 0x0000, 0x0000 }, /* R12914 */ + { 0x0000, 0x0000, 0x0000 }, /* R12915 */ + { 0x0000, 0x0000, 0x0000 }, /* R12916 */ + { 0x0000, 0x0000, 0x0000 }, /* R12917 */ + { 0x0000, 0x0000, 0x0000 }, /* R12918 */ + { 0x0000, 0x0000, 0x0000 }, /* R12919 */ + { 0x0000, 0x0000, 0x0000 }, /* R12920 */ + { 0x0000, 0x0000, 0x0000 }, /* R12921 */ + { 0x0000, 0x0000, 0x0000 }, /* R12922 */ + { 0x0000, 0x0000, 0x0000 }, /* R12923 */ + { 0x0000, 0x0000, 0x0000 }, /* R12924 */ + { 0x0000, 0x0000, 0x0000 }, /* R12925 */ + { 0x0000, 0x0000, 0x0000 }, /* R12926 */ + { 0x0000, 0x0000, 0x0000 }, /* R12927 */ + { 0x0000, 0x0000, 0x0000 }, /* R12928 */ + { 0x0000, 0x0000, 0x0000 }, /* R12929 */ + { 0x0000, 0x0000, 0x0000 }, /* R12930 */ + { 0x0000, 0x0000, 0x0000 }, /* R12931 */ + { 0x0000, 0x0000, 0x0000 }, /* R12932 */ + { 0x0000, 0x0000, 0x0000 }, /* R12933 */ + { 0x0000, 0x0000, 0x0000 }, /* R12934 */ + { 0x0000, 0x0000, 0x0000 }, /* R12935 */ + { 0x0000, 0x0000, 0x0000 }, /* R12936 */ + { 0x0000, 0x0000, 0x0000 }, /* R12937 */ + { 0x0000, 0x0000, 0x0000 }, /* R12938 */ + { 0x0000, 0x0000, 0x0000 }, /* R12939 */ + { 0x0000, 0x0000, 0x0000 }, /* R12940 */ + { 0x0000, 0x0000, 0x0000 }, /* R12941 */ + { 0x0000, 0x0000, 0x0000 }, /* R12942 */ + { 0x0000, 0x0000, 0x0000 }, /* R12943 */ + { 0x0000, 0x0000, 0x0000 }, /* R12944 */ + { 0x0000, 0x0000, 0x0000 }, /* R12945 */ + { 0x0000, 0x0000, 0x0000 }, /* R12946 */ + { 0x0000, 0x0000, 0x0000 }, /* R12947 */ + { 0x0000, 0x0000, 0x0000 }, /* R12948 */ + { 0x0000, 0x0000, 0x0000 }, /* R12949 */ + { 0x0000, 0x0000, 0x0000 }, /* R12950 */ + { 0x0000, 0x0000, 0x0000 }, /* R12951 */ + { 0x0000, 0x0000, 0x0000 }, /* R12952 */ + { 0x0000, 0x0000, 0x0000 }, /* R12953 */ + { 0x0000, 0x0000, 0x0000 }, /* R12954 */ + { 0x0000, 0x0000, 0x0000 }, /* R12955 */ + { 0x0000, 0x0000, 0x0000 }, /* R12956 */ + { 0x0000, 0x0000, 0x0000 }, /* R12957 */ + { 0x0000, 0x0000, 0x0000 }, /* R12958 */ + { 0x0000, 0x0000, 0x0000 }, /* R12959 */ + { 0x0000, 0x0000, 0x0000 }, /* R12960 */ + { 0x0000, 0x0000, 0x0000 }, /* R12961 */ + { 0x0000, 0x0000, 0x0000 }, /* R12962 */ + { 0x0000, 0x0000, 0x0000 }, /* R12963 */ + { 0x0000, 0x0000, 0x0000 }, /* R12964 */ + { 0x0000, 0x0000, 0x0000 }, /* R12965 */ + { 0x0000, 0x0000, 0x0000 }, /* R12966 */ + { 0x0000, 0x0000, 0x0000 }, /* R12967 */ + { 0x0000, 0x0000, 0x0000 }, /* R12968 */ + { 0x0000, 0x0000, 0x0000 }, /* R12969 */ + { 0x0000, 0x0000, 0x0000 }, /* R12970 */ + { 0x0000, 0x0000, 0x0000 }, /* R12971 */ + { 0x0000, 0x0000, 0x0000 }, /* R12972 */ + { 0x0000, 0x0000, 0x0000 }, /* R12973 */ + { 0x0000, 0x0000, 0x0000 }, /* R12974 */ + { 0x0000, 0x0000, 0x0000 }, /* R12975 */ + { 0x0000, 0x0000, 0x0000 }, /* R12976 */ + { 0x0000, 0x0000, 0x0000 }, /* R12977 */ + { 0x0000, 0x0000, 0x0000 }, /* R12978 */ + { 0x0000, 0x0000, 0x0000 }, /* R12979 */ + { 0x0000, 0x0000, 0x0000 }, /* R12980 */ + { 0x0000, 0x0000, 0x0000 }, /* R12981 */ + { 0x0000, 0x0000, 0x0000 }, /* R12982 */ + { 0x0000, 0x0000, 0x0000 }, /* R12983 */ + { 0x0000, 0x0000, 0x0000 }, /* R12984 */ + { 0x0000, 0x0000, 0x0000 }, /* R12985 */ + { 0x0000, 0x0000, 0x0000 }, /* R12986 */ + { 0x0000, 0x0000, 0x0000 }, /* R12987 */ + { 0x0000, 0x0000, 0x0000 }, /* R12988 */ + { 0x0000, 0x0000, 0x0000 }, /* R12989 */ + { 0x0000, 0x0000, 0x0000 }, /* R12990 */ + { 0x0000, 0x0000, 0x0000 }, /* R12991 */ + { 0x0000, 0x0000, 0x0000 }, /* R12992 */ + { 0x0000, 0x0000, 0x0000 }, /* R12993 */ + { 0x0000, 0x0000, 0x0000 }, /* R12994 */ + { 0x0000, 0x0000, 0x0000 }, /* R12995 */ + { 0x0000, 0x0000, 0x0000 }, /* R12996 */ + { 0x0000, 0x0000, 0x0000 }, /* R12997 */ + { 0x0000, 0x0000, 0x0000 }, /* R12998 */ + { 0x0000, 0x0000, 0x0000 }, /* R12999 */ + { 0x0000, 0x0000, 0x0000 }, /* R13000 */ + { 0x0000, 0x0000, 0x0000 }, /* R13001 */ + { 0x0000, 0x0000, 0x0000 }, /* R13002 */ + { 0x0000, 0x0000, 0x0000 }, /* R13003 */ + { 0x0000, 0x0000, 0x0000 }, /* R13004 */ + { 0x0000, 0x0000, 0x0000 }, /* R13005 */ + { 0x0000, 0x0000, 0x0000 }, /* R13006 */ + { 0x0000, 0x0000, 0x0000 }, /* R13007 */ + { 0x0000, 0x0000, 0x0000 }, /* R13008 */ + { 0x0000, 0x0000, 0x0000 }, /* R13009 */ + { 0x0000, 0x0000, 0x0000 }, /* R13010 */ + { 0x0000, 0x0000, 0x0000 }, /* R13011 */ + { 0x0000, 0x0000, 0x0000 }, /* R13012 */ + { 0x0000, 0x0000, 0x0000 }, /* R13013 */ + { 0x0000, 0x0000, 0x0000 }, /* R13014 */ + { 0x0000, 0x0000, 0x0000 }, /* R13015 */ + { 0x0000, 0x0000, 0x0000 }, /* R13016 */ + { 0x0000, 0x0000, 0x0000 }, /* R13017 */ + { 0x0000, 0x0000, 0x0000 }, /* R13018 */ + { 0x0000, 0x0000, 0x0000 }, /* R13019 */ + { 0x0000, 0x0000, 0x0000 }, /* R13020 */ + { 0x0000, 0x0000, 0x0000 }, /* R13021 */ + { 0x0000, 0x0000, 0x0000 }, /* R13022 */ + { 0x0000, 0x0000, 0x0000 }, /* R13023 */ + { 0x0000, 0x0000, 0x0000 }, /* R13024 */ + { 0x0000, 0x0000, 0x0000 }, /* R13025 */ + { 0x0000, 0x0000, 0x0000 }, /* R13026 */ + { 0x0000, 0x0000, 0x0000 }, /* R13027 */ + { 0x0000, 0x0000, 0x0000 }, /* R13028 */ + { 0x0000, 0x0000, 0x0000 }, /* R13029 */ + { 0x0000, 0x0000, 0x0000 }, /* R13030 */ + { 0x0000, 0x0000, 0x0000 }, /* R13031 */ + { 0x0000, 0x0000, 0x0000 }, /* R13032 */ + { 0x0000, 0x0000, 0x0000 }, /* R13033 */ + { 0x0000, 0x0000, 0x0000 }, /* R13034 */ + { 0x0000, 0x0000, 0x0000 }, /* R13035 */ + { 0x0000, 0x0000, 0x0000 }, /* R13036 */ + { 0x0000, 0x0000, 0x0000 }, /* R13037 */ + { 0x0000, 0x0000, 0x0000 }, /* R13038 */ + { 0x0000, 0x0000, 0x0000 }, /* R13039 */ + { 0x0000, 0x0000, 0x0000 }, /* R13040 */ + { 0x0000, 0x0000, 0x0000 }, /* R13041 */ + { 0x0000, 0x0000, 0x0000 }, /* R13042 */ + { 0x0000, 0x0000, 0x0000 }, /* R13043 */ + { 0x0000, 0x0000, 0x0000 }, /* R13044 */ + { 0x0000, 0x0000, 0x0000 }, /* R13045 */ + { 0x0000, 0x0000, 0x0000 }, /* R13046 */ + { 0x0000, 0x0000, 0x0000 }, /* R13047 */ + { 0x0000, 0x0000, 0x0000 }, /* R13048 */ + { 0x0000, 0x0000, 0x0000 }, /* R13049 */ + { 0x0000, 0x0000, 0x0000 }, /* R13050 */ + { 0x0000, 0x0000, 0x0000 }, /* R13051 */ + { 0x0000, 0x0000, 0x0000 }, /* R13052 */ + { 0x0000, 0x0000, 0x0000 }, /* R13053 */ + { 0x0000, 0x0000, 0x0000 }, /* R13054 */ + { 0x0000, 0x0000, 0x0000 }, /* R13055 */ + { 0x0000, 0x0000, 0x0000 }, /* R13056 */ + { 0x0000, 0x0000, 0x0000 }, /* R13057 */ + { 0x0000, 0x0000, 0x0000 }, /* R13058 */ + { 0x0000, 0x0000, 0x0000 }, /* R13059 */ + { 0x0000, 0x0000, 0x0000 }, /* R13060 */ + { 0x0000, 0x0000, 0x0000 }, /* R13061 */ + { 0x0000, 0x0000, 0x0000 }, /* R13062 */ + { 0x0000, 0x0000, 0x0000 }, /* R13063 */ + { 0x0000, 0x0000, 0x0000 }, /* R13064 */ + { 0x0000, 0x0000, 0x0000 }, /* R13065 */ + { 0x0000, 0x0000, 0x0000 }, /* R13066 */ + { 0x0000, 0x0000, 0x0000 }, /* R13067 */ + { 0x0000, 0x0000, 0x0000 }, /* R13068 */ + { 0x0000, 0x0000, 0x0000 }, /* R13069 */ + { 0x0000, 0x0000, 0x0000 }, /* R13070 */ + { 0x0000, 0x0000, 0x0000 }, /* R13071 */ + { 0x0000, 0x0000, 0x0000 }, /* R13072 */ + { 0x0000, 0x0000, 0x0000 }, /* R13073 */ + { 0x0000, 0x0000, 0x0000 }, /* R13074 */ + { 0x0000, 0x0000, 0x0000 }, /* R13075 */ + { 0x0000, 0x0000, 0x0000 }, /* R13076 */ + { 0x0000, 0x0000, 0x0000 }, /* R13077 */ + { 0x0000, 0x0000, 0x0000 }, /* R13078 */ + { 0x0000, 0x0000, 0x0000 }, /* R13079 */ + { 0x0000, 0x0000, 0x0000 }, /* R13080 */ + { 0x0000, 0x0000, 0x0000 }, /* R13081 */ + { 0x0000, 0x0000, 0x0000 }, /* R13082 */ + { 0x0000, 0x0000, 0x0000 }, /* R13083 */ + { 0x0000, 0x0000, 0x0000 }, /* R13084 */ + { 0x0000, 0x0000, 0x0000 }, /* R13085 */ + { 0x0000, 0x0000, 0x0000 }, /* R13086 */ + { 0x0000, 0x0000, 0x0000 }, /* R13087 */ + { 0x0000, 0x0000, 0x0000 }, /* R13088 */ + { 0x0000, 0x0000, 0x0000 }, /* R13089 */ + { 0x0000, 0x0000, 0x0000 }, /* R13090 */ + { 0x0000, 0x0000, 0x0000 }, /* R13091 */ + { 0x0000, 0x0000, 0x0000 }, /* R13092 */ + { 0x0000, 0x0000, 0x0000 }, /* R13093 */ + { 0x0000, 0x0000, 0x0000 }, /* R13094 */ + { 0x0000, 0x0000, 0x0000 }, /* R13095 */ + { 0x0000, 0x0000, 0x0000 }, /* R13096 */ + { 0x0000, 0x0000, 0x0000 }, /* R13097 */ + { 0x0000, 0x0000, 0x0000 }, /* R13098 */ + { 0x0000, 0x0000, 0x0000 }, /* R13099 */ + { 0x0000, 0x0000, 0x0000 }, /* R13100 */ + { 0x0000, 0x0000, 0x0000 }, /* R13101 */ + { 0x0000, 0x0000, 0x0000 }, /* R13102 */ + { 0x0000, 0x0000, 0x0000 }, /* R13103 */ + { 0x0000, 0x0000, 0x0000 }, /* R13104 */ + { 0x0000, 0x0000, 0x0000 }, /* R13105 */ + { 0x0000, 0x0000, 0x0000 }, /* R13106 */ + { 0x0000, 0x0000, 0x0000 }, /* R13107 */ + { 0x0000, 0x0000, 0x0000 }, /* R13108 */ + { 0x0000, 0x0000, 0x0000 }, /* R13109 */ + { 0x0000, 0x0000, 0x0000 }, /* R13110 */ + { 0x0000, 0x0000, 0x0000 }, /* R13111 */ + { 0x0000, 0x0000, 0x0000 }, /* R13112 */ + { 0x0000, 0x0000, 0x0000 }, /* R13113 */ + { 0x0000, 0x0000, 0x0000 }, /* R13114 */ + { 0x0000, 0x0000, 0x0000 }, /* R13115 */ + { 0x0000, 0x0000, 0x0000 }, /* R13116 */ + { 0x0000, 0x0000, 0x0000 }, /* R13117 */ + { 0x0000, 0x0000, 0x0000 }, /* R13118 */ + { 0x0000, 0x0000, 0x0000 }, /* R13119 */ + { 0x0000, 0x0000, 0x0000 }, /* R13120 */ + { 0x0000, 0x0000, 0x0000 }, /* R13121 */ + { 0x0000, 0x0000, 0x0000 }, /* R13122 */ + { 0x0000, 0x0000, 0x0000 }, /* R13123 */ + { 0x0000, 0x0000, 0x0000 }, /* R13124 */ + { 0x0000, 0x0000, 0x0000 }, /* R13125 */ + { 0x0000, 0x0000, 0x0000 }, /* R13126 */ + { 0x0000, 0x0000, 0x0000 }, /* R13127 */ + { 0x0000, 0x0000, 0x0000 }, /* R13128 */ + { 0x0000, 0x0000, 0x0000 }, /* R13129 */ + { 0x0000, 0x0000, 0x0000 }, /* R13130 */ + { 0x0000, 0x0000, 0x0000 }, /* R13131 */ + { 0x0000, 0x0000, 0x0000 }, /* R13132 */ + { 0x0000, 0x0000, 0x0000 }, /* R13133 */ + { 0x0000, 0x0000, 0x0000 }, /* R13134 */ + { 0x0000, 0x0000, 0x0000 }, /* R13135 */ + { 0x0000, 0x0000, 0x0000 }, /* R13136 */ + { 0x0000, 0x0000, 0x0000 }, /* R13137 */ + { 0x0000, 0x0000, 0x0000 }, /* R13138 */ + { 0x0000, 0x0000, 0x0000 }, /* R13139 */ + { 0x0000, 0x0000, 0x0000 }, /* R13140 */ + { 0x0000, 0x0000, 0x0000 }, /* R13141 */ + { 0x0000, 0x0000, 0x0000 }, /* R13142 */ + { 0x0000, 0x0000, 0x0000 }, /* R13143 */ + { 0x0000, 0x0000, 0x0000 }, /* R13144 */ + { 0x0000, 0x0000, 0x0000 }, /* R13145 */ + { 0x0000, 0x0000, 0x0000 }, /* R13146 */ + { 0x0000, 0x0000, 0x0000 }, /* R13147 */ + { 0x0000, 0x0000, 0x0000 }, /* R13148 */ + { 0x0000, 0x0000, 0x0000 }, /* R13149 */ + { 0x0000, 0x0000, 0x0000 }, /* R13150 */ + { 0x0000, 0x0000, 0x0000 }, /* R13151 */ + { 0x0000, 0x0000, 0x0000 }, /* R13152 */ + { 0x0000, 0x0000, 0x0000 }, /* R13153 */ + { 0x0000, 0x0000, 0x0000 }, /* R13154 */ + { 0x0000, 0x0000, 0x0000 }, /* R13155 */ + { 0x0000, 0x0000, 0x0000 }, /* R13156 */ + { 0x0000, 0x0000, 0x0000 }, /* R13157 */ + { 0x0000, 0x0000, 0x0000 }, /* R13158 */ + { 0x0000, 0x0000, 0x0000 }, /* R13159 */ + { 0x0000, 0x0000, 0x0000 }, /* R13160 */ + { 0x0000, 0x0000, 0x0000 }, /* R13161 */ + { 0x0000, 0x0000, 0x0000 }, /* R13162 */ + { 0x0000, 0x0000, 0x0000 }, /* R13163 */ + { 0x0000, 0x0000, 0x0000 }, /* R13164 */ + { 0x0000, 0x0000, 0x0000 }, /* R13165 */ + { 0x0000, 0x0000, 0x0000 }, /* R13166 */ + { 0x0000, 0x0000, 0x0000 }, /* R13167 */ + { 0x0000, 0x0000, 0x0000 }, /* R13168 */ + { 0x0000, 0x0000, 0x0000 }, /* R13169 */ + { 0x0000, 0x0000, 0x0000 }, /* R13170 */ + { 0x0000, 0x0000, 0x0000 }, /* R13171 */ + { 0x0000, 0x0000, 0x0000 }, /* R13172 */ + { 0x0000, 0x0000, 0x0000 }, /* R13173 */ + { 0x0000, 0x0000, 0x0000 }, /* R13174 */ + { 0x0000, 0x0000, 0x0000 }, /* R13175 */ + { 0x0000, 0x0000, 0x0000 }, /* R13176 */ + { 0x0000, 0x0000, 0x0000 }, /* R13177 */ + { 0x0000, 0x0000, 0x0000 }, /* R13178 */ + { 0x0000, 0x0000, 0x0000 }, /* R13179 */ + { 0x0000, 0x0000, 0x0000 }, /* R13180 */ + { 0x0000, 0x0000, 0x0000 }, /* R13181 */ + { 0x0000, 0x0000, 0x0000 }, /* R13182 */ + { 0x0000, 0x0000, 0x0000 }, /* R13183 */ + { 0x0000, 0x0000, 0x0000 }, /* R13184 */ + { 0x0000, 0x0000, 0x0000 }, /* R13185 */ + { 0x0000, 0x0000, 0x0000 }, /* R13186 */ + { 0x0000, 0x0000, 0x0000 }, /* R13187 */ + { 0x0000, 0x0000, 0x0000 }, /* R13188 */ + { 0x0000, 0x0000, 0x0000 }, /* R13189 */ + { 0x0000, 0x0000, 0x0000 }, /* R13190 */ + { 0x0000, 0x0000, 0x0000 }, /* R13191 */ + { 0x0000, 0x0000, 0x0000 }, /* R13192 */ + { 0x0000, 0x0000, 0x0000 }, /* R13193 */ + { 0x0000, 0x0000, 0x0000 }, /* R13194 */ + { 0x0000, 0x0000, 0x0000 }, /* R13195 */ + { 0x0000, 0x0000, 0x0000 }, /* R13196 */ + { 0x0000, 0x0000, 0x0000 }, /* R13197 */ + { 0x0000, 0x0000, 0x0000 }, /* R13198 */ + { 0x0000, 0x0000, 0x0000 }, /* R13199 */ + { 0x0000, 0x0000, 0x0000 }, /* R13200 */ + { 0x0000, 0x0000, 0x0000 }, /* R13201 */ + { 0x0000, 0x0000, 0x0000 }, /* R13202 */ + { 0x0000, 0x0000, 0x0000 }, /* R13203 */ + { 0x0000, 0x0000, 0x0000 }, /* R13204 */ + { 0x0000, 0x0000, 0x0000 }, /* R13205 */ + { 0x0000, 0x0000, 0x0000 }, /* R13206 */ + { 0x0000, 0x0000, 0x0000 }, /* R13207 */ + { 0x0000, 0x0000, 0x0000 }, /* R13208 */ + { 0x0000, 0x0000, 0x0000 }, /* R13209 */ + { 0x0000, 0x0000, 0x0000 }, /* R13210 */ + { 0x0000, 0x0000, 0x0000 }, /* R13211 */ + { 0x0000, 0x0000, 0x0000 }, /* R13212 */ + { 0x0000, 0x0000, 0x0000 }, /* R13213 */ + { 0x0000, 0x0000, 0x0000 }, /* R13214 */ + { 0x0000, 0x0000, 0x0000 }, /* R13215 */ + { 0x0000, 0x0000, 0x0000 }, /* R13216 */ + { 0x0000, 0x0000, 0x0000 }, /* R13217 */ + { 0x0000, 0x0000, 0x0000 }, /* R13218 */ + { 0x0000, 0x0000, 0x0000 }, /* R13219 */ + { 0x0000, 0x0000, 0x0000 }, /* R13220 */ + { 0x0000, 0x0000, 0x0000 }, /* R13221 */ + { 0x0000, 0x0000, 0x0000 }, /* R13222 */ + { 0x0000, 0x0000, 0x0000 }, /* R13223 */ + { 0x0000, 0x0000, 0x0000 }, /* R13224 */ + { 0x0000, 0x0000, 0x0000 }, /* R13225 */ + { 0x0000, 0x0000, 0x0000 }, /* R13226 */ + { 0x0000, 0x0000, 0x0000 }, /* R13227 */ + { 0x0000, 0x0000, 0x0000 }, /* R13228 */ + { 0x0000, 0x0000, 0x0000 }, /* R13229 */ + { 0x0000, 0x0000, 0x0000 }, /* R13230 */ + { 0x0000, 0x0000, 0x0000 }, /* R13231 */ + { 0x0000, 0x0000, 0x0000 }, /* R13232 */ + { 0x0000, 0x0000, 0x0000 }, /* R13233 */ + { 0x0000, 0x0000, 0x0000 }, /* R13234 */ + { 0x0000, 0x0000, 0x0000 }, /* R13235 */ + { 0x0000, 0x0000, 0x0000 }, /* R13236 */ + { 0x0000, 0x0000, 0x0000 }, /* R13237 */ + { 0x0000, 0x0000, 0x0000 }, /* R13238 */ + { 0x0000, 0x0000, 0x0000 }, /* R13239 */ + { 0x0000, 0x0000, 0x0000 }, /* R13240 */ + { 0x0000, 0x0000, 0x0000 }, /* R13241 */ + { 0x0000, 0x0000, 0x0000 }, /* R13242 */ + { 0x0000, 0x0000, 0x0000 }, /* R13243 */ + { 0x0000, 0x0000, 0x0000 }, /* R13244 */ + { 0x0000, 0x0000, 0x0000 }, /* R13245 */ + { 0x0000, 0x0000, 0x0000 }, /* R13246 */ + { 0x0000, 0x0000, 0x0000 }, /* R13247 */ + { 0x0000, 0x0000, 0x0000 }, /* R13248 */ + { 0x0000, 0x0000, 0x0000 }, /* R13249 */ + { 0x0000, 0x0000, 0x0000 }, /* R13250 */ + { 0x0000, 0x0000, 0x0000 }, /* R13251 */ + { 0x0000, 0x0000, 0x0000 }, /* R13252 */ + { 0x0000, 0x0000, 0x0000 }, /* R13253 */ + { 0x0000, 0x0000, 0x0000 }, /* R13254 */ + { 0x0000, 0x0000, 0x0000 }, /* R13255 */ + { 0x0000, 0x0000, 0x0000 }, /* R13256 */ + { 0x0000, 0x0000, 0x0000 }, /* R13257 */ + { 0x0000, 0x0000, 0x0000 }, /* R13258 */ + { 0x0000, 0x0000, 0x0000 }, /* R13259 */ + { 0x0000, 0x0000, 0x0000 }, /* R13260 */ + { 0x0000, 0x0000, 0x0000 }, /* R13261 */ + { 0x0000, 0x0000, 0x0000 }, /* R13262 */ + { 0x0000, 0x0000, 0x0000 }, /* R13263 */ + { 0x0000, 0x0000, 0x0000 }, /* R13264 */ + { 0x0000, 0x0000, 0x0000 }, /* R13265 */ + { 0x0000, 0x0000, 0x0000 }, /* R13266 */ + { 0x0000, 0x0000, 0x0000 }, /* R13267 */ + { 0x0000, 0x0000, 0x0000 }, /* R13268 */ + { 0x0000, 0x0000, 0x0000 }, /* R13269 */ + { 0x0000, 0x0000, 0x0000 }, /* R13270 */ + { 0x0000, 0x0000, 0x0000 }, /* R13271 */ + { 0x0000, 0x0000, 0x0000 }, /* R13272 */ + { 0x0000, 0x0000, 0x0000 }, /* R13273 */ + { 0x0000, 0x0000, 0x0000 }, /* R13274 */ + { 0x0000, 0x0000, 0x0000 }, /* R13275 */ + { 0x0000, 0x0000, 0x0000 }, /* R13276 */ + { 0x0000, 0x0000, 0x0000 }, /* R13277 */ + { 0x0000, 0x0000, 0x0000 }, /* R13278 */ + { 0x0000, 0x0000, 0x0000 }, /* R13279 */ + { 0x0000, 0x0000, 0x0000 }, /* R13280 */ + { 0x0000, 0x0000, 0x0000 }, /* R13281 */ + { 0x0000, 0x0000, 0x0000 }, /* R13282 */ + { 0x0000, 0x0000, 0x0000 }, /* R13283 */ + { 0x0000, 0x0000, 0x0000 }, /* R13284 */ + { 0x0000, 0x0000, 0x0000 }, /* R13285 */ + { 0x0000, 0x0000, 0x0000 }, /* R13286 */ + { 0x0000, 0x0000, 0x0000 }, /* R13287 */ + { 0x0000, 0x0000, 0x0000 }, /* R13288 */ + { 0x0000, 0x0000, 0x0000 }, /* R13289 */ + { 0x0000, 0x0000, 0x0000 }, /* R13290 */ + { 0x0000, 0x0000, 0x0000 }, /* R13291 */ + { 0x0000, 0x0000, 0x0000 }, /* R13292 */ + { 0x0000, 0x0000, 0x0000 }, /* R13293 */ + { 0x0000, 0x0000, 0x0000 }, /* R13294 */ + { 0x0000, 0x0000, 0x0000 }, /* R13295 */ + { 0x0000, 0x0000, 0x0000 }, /* R13296 */ + { 0x0000, 0x0000, 0x0000 }, /* R13297 */ + { 0x0000, 0x0000, 0x0000 }, /* R13298 */ + { 0x0000, 0x0000, 0x0000 }, /* R13299 */ + { 0x0000, 0x0000, 0x0000 }, /* R13300 */ + { 0x0000, 0x0000, 0x0000 }, /* R13301 */ + { 0x0000, 0x0000, 0x0000 }, /* R13302 */ + { 0x0000, 0x0000, 0x0000 }, /* R13303 */ + { 0x0000, 0x0000, 0x0000 }, /* R13304 */ + { 0x0000, 0x0000, 0x0000 }, /* R13305 */ + { 0x0000, 0x0000, 0x0000 }, /* R13306 */ + { 0x0000, 0x0000, 0x0000 }, /* R13307 */ + { 0x0000, 0x0000, 0x0000 }, /* R13308 */ + { 0x0000, 0x0000, 0x0000 }, /* R13309 */ + { 0x0000, 0x0000, 0x0000 }, /* R13310 */ + { 0x0000, 0x0000, 0x0000 }, /* R13311 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R13312 - DSP2 Data2 RAM 1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R13313 - DSP2 Data2 RAM 0 */ + { 0x0000, 0x0000, 0x0000 }, /* R13314 */ + { 0x0000, 0x0000, 0x0000 }, /* R13315 */ + { 0x0000, 0x0000, 0x0000 }, /* R13316 */ + { 0x0000, 0x0000, 0x0000 }, /* R13317 */ + { 0x0000, 0x0000, 0x0000 }, /* R13318 */ + { 0x0000, 0x0000, 0x0000 }, /* R13319 */ + { 0x0000, 0x0000, 0x0000 }, /* R13320 */ + { 0x0000, 0x0000, 0x0000 }, /* R13321 */ + { 0x0000, 0x0000, 0x0000 }, /* R13322 */ + { 0x0000, 0x0000, 0x0000 }, /* R13323 */ + { 0x0000, 0x0000, 0x0000 }, /* R13324 */ + { 0x0000, 0x0000, 0x0000 }, /* R13325 */ + { 0x0000, 0x0000, 0x0000 }, /* R13326 */ + { 0x0000, 0x0000, 0x0000 }, /* R13327 */ + { 0x0000, 0x0000, 0x0000 }, /* R13328 */ + { 0x0000, 0x0000, 0x0000 }, /* R13329 */ + { 0x0000, 0x0000, 0x0000 }, /* R13330 */ + { 0x0000, 0x0000, 0x0000 }, /* R13331 */ + { 0x0000, 0x0000, 0x0000 }, /* R13332 */ + { 0x0000, 0x0000, 0x0000 }, /* R13333 */ + { 0x0000, 0x0000, 0x0000 }, /* R13334 */ + { 0x0000, 0x0000, 0x0000 }, /* R13335 */ + { 0x0000, 0x0000, 0x0000 }, /* R13336 */ + { 0x0000, 0x0000, 0x0000 }, /* R13337 */ + { 0x0000, 0x0000, 0x0000 }, /* R13338 */ + { 0x0000, 0x0000, 0x0000 }, /* R13339 */ + { 0x0000, 0x0000, 0x0000 }, /* R13340 */ + { 0x0000, 0x0000, 0x0000 }, /* R13341 */ + { 0x0000, 0x0000, 0x0000 }, /* R13342 */ + { 0x0000, 0x0000, 0x0000 }, /* R13343 */ + { 0x0000, 0x0000, 0x0000 }, /* R13344 */ + { 0x0000, 0x0000, 0x0000 }, /* R13345 */ + { 0x0000, 0x0000, 0x0000 }, /* R13346 */ + { 0x0000, 0x0000, 0x0000 }, /* R13347 */ + { 0x0000, 0x0000, 0x0000 }, /* R13348 */ + { 0x0000, 0x0000, 0x0000 }, /* R13349 */ + { 0x0000, 0x0000, 0x0000 }, /* R13350 */ + { 0x0000, 0x0000, 0x0000 }, /* R13351 */ + { 0x0000, 0x0000, 0x0000 }, /* R13352 */ + { 0x0000, 0x0000, 0x0000 }, /* R13353 */ + { 0x0000, 0x0000, 0x0000 }, /* R13354 */ + { 0x0000, 0x0000, 0x0000 }, /* R13355 */ + { 0x0000, 0x0000, 0x0000 }, /* R13356 */ + { 0x0000, 0x0000, 0x0000 }, /* R13357 */ + { 0x0000, 0x0000, 0x0000 }, /* R13358 */ + { 0x0000, 0x0000, 0x0000 }, /* R13359 */ + { 0x0000, 0x0000, 0x0000 }, /* R13360 */ + { 0x0000, 0x0000, 0x0000 }, /* R13361 */ + { 0x0000, 0x0000, 0x0000 }, /* R13362 */ + { 0x0000, 0x0000, 0x0000 }, /* R13363 */ + { 0x0000, 0x0000, 0x0000 }, /* R13364 */ + { 0x0000, 0x0000, 0x0000 }, /* R13365 */ + { 0x0000, 0x0000, 0x0000 }, /* R13366 */ + { 0x0000, 0x0000, 0x0000 }, /* R13367 */ + { 0x0000, 0x0000, 0x0000 }, /* R13368 */ + { 0x0000, 0x0000, 0x0000 }, /* R13369 */ + { 0x0000, 0x0000, 0x0000 }, /* R13370 */ + { 0x0000, 0x0000, 0x0000 }, /* R13371 */ + { 0x0000, 0x0000, 0x0000 }, /* R13372 */ + { 0x0000, 0x0000, 0x0000 }, /* R13373 */ + { 0x0000, 0x0000, 0x0000 }, /* R13374 */ + { 0x0000, 0x0000, 0x0000 }, /* R13375 */ + { 0x0000, 0x0000, 0x0000 }, /* R13376 */ + { 0x0000, 0x0000, 0x0000 }, /* R13377 */ + { 0x0000, 0x0000, 0x0000 }, /* R13378 */ + { 0x0000, 0x0000, 0x0000 }, /* R13379 */ + { 0x0000, 0x0000, 0x0000 }, /* R13380 */ + { 0x0000, 0x0000, 0x0000 }, /* R13381 */ + { 0x0000, 0x0000, 0x0000 }, /* R13382 */ + { 0x0000, 0x0000, 0x0000 }, /* R13383 */ + { 0x0000, 0x0000, 0x0000 }, /* R13384 */ + { 0x0000, 0x0000, 0x0000 }, /* R13385 */ + { 0x0000, 0x0000, 0x0000 }, /* R13386 */ + { 0x0000, 0x0000, 0x0000 }, /* R13387 */ + { 0x0000, 0x0000, 0x0000 }, /* R13388 */ + { 0x0000, 0x0000, 0x0000 }, /* R13389 */ + { 0x0000, 0x0000, 0x0000 }, /* R13390 */ + { 0x0000, 0x0000, 0x0000 }, /* R13391 */ + { 0x0000, 0x0000, 0x0000 }, /* R13392 */ + { 0x0000, 0x0000, 0x0000 }, /* R13393 */ + { 0x0000, 0x0000, 0x0000 }, /* R13394 */ + { 0x0000, 0x0000, 0x0000 }, /* R13395 */ + { 0x0000, 0x0000, 0x0000 }, /* R13396 */ + { 0x0000, 0x0000, 0x0000 }, /* R13397 */ + { 0x0000, 0x0000, 0x0000 }, /* R13398 */ + { 0x0000, 0x0000, 0x0000 }, /* R13399 */ + { 0x0000, 0x0000, 0x0000 }, /* R13400 */ + { 0x0000, 0x0000, 0x0000 }, /* R13401 */ + { 0x0000, 0x0000, 0x0000 }, /* R13402 */ + { 0x0000, 0x0000, 0x0000 }, /* R13403 */ + { 0x0000, 0x0000, 0x0000 }, /* R13404 */ + { 0x0000, 0x0000, 0x0000 }, /* R13405 */ + { 0x0000, 0x0000, 0x0000 }, /* R13406 */ + { 0x0000, 0x0000, 0x0000 }, /* R13407 */ + { 0x0000, 0x0000, 0x0000 }, /* R13408 */ + { 0x0000, 0x0000, 0x0000 }, /* R13409 */ + { 0x0000, 0x0000, 0x0000 }, /* R13410 */ + { 0x0000, 0x0000, 0x0000 }, /* R13411 */ + { 0x0000, 0x0000, 0x0000 }, /* R13412 */ + { 0x0000, 0x0000, 0x0000 }, /* R13413 */ + { 0x0000, 0x0000, 0x0000 }, /* R13414 */ + { 0x0000, 0x0000, 0x0000 }, /* R13415 */ + { 0x0000, 0x0000, 0x0000 }, /* R13416 */ + { 0x0000, 0x0000, 0x0000 }, /* R13417 */ + { 0x0000, 0x0000, 0x0000 }, /* R13418 */ + { 0x0000, 0x0000, 0x0000 }, /* R13419 */ + { 0x0000, 0x0000, 0x0000 }, /* R13420 */ + { 0x0000, 0x0000, 0x0000 }, /* R13421 */ + { 0x0000, 0x0000, 0x0000 }, /* R13422 */ + { 0x0000, 0x0000, 0x0000 }, /* R13423 */ + { 0x0000, 0x0000, 0x0000 }, /* R13424 */ + { 0x0000, 0x0000, 0x0000 }, /* R13425 */ + { 0x0000, 0x0000, 0x0000 }, /* R13426 */ + { 0x0000, 0x0000, 0x0000 }, /* R13427 */ + { 0x0000, 0x0000, 0x0000 }, /* R13428 */ + { 0x0000, 0x0000, 0x0000 }, /* R13429 */ + { 0x0000, 0x0000, 0x0000 }, /* R13430 */ + { 0x0000, 0x0000, 0x0000 }, /* R13431 */ + { 0x0000, 0x0000, 0x0000 }, /* R13432 */ + { 0x0000, 0x0000, 0x0000 }, /* R13433 */ + { 0x0000, 0x0000, 0x0000 }, /* R13434 */ + { 0x0000, 0x0000, 0x0000 }, /* R13435 */ + { 0x0000, 0x0000, 0x0000 }, /* R13436 */ + { 0x0000, 0x0000, 0x0000 }, /* R13437 */ + { 0x0000, 0x0000, 0x0000 }, /* R13438 */ + { 0x0000, 0x0000, 0x0000 }, /* R13439 */ + { 0x0000, 0x0000, 0x0000 }, /* R13440 */ + { 0x0000, 0x0000, 0x0000 }, /* R13441 */ + { 0x0000, 0x0000, 0x0000 }, /* R13442 */ + { 0x0000, 0x0000, 0x0000 }, /* R13443 */ + { 0x0000, 0x0000, 0x0000 }, /* R13444 */ + { 0x0000, 0x0000, 0x0000 }, /* R13445 */ + { 0x0000, 0x0000, 0x0000 }, /* R13446 */ + { 0x0000, 0x0000, 0x0000 }, /* R13447 */ + { 0x0000, 0x0000, 0x0000 }, /* R13448 */ + { 0x0000, 0x0000, 0x0000 }, /* R13449 */ + { 0x0000, 0x0000, 0x0000 }, /* R13450 */ + { 0x0000, 0x0000, 0x0000 }, /* R13451 */ + { 0x0000, 0x0000, 0x0000 }, /* R13452 */ + { 0x0000, 0x0000, 0x0000 }, /* R13453 */ + { 0x0000, 0x0000, 0x0000 }, /* R13454 */ + { 0x0000, 0x0000, 0x0000 }, /* R13455 */ + { 0x0000, 0x0000, 0x0000 }, /* R13456 */ + { 0x0000, 0x0000, 0x0000 }, /* R13457 */ + { 0x0000, 0x0000, 0x0000 }, /* R13458 */ + { 0x0000, 0x0000, 0x0000 }, /* R13459 */ + { 0x0000, 0x0000, 0x0000 }, /* R13460 */ + { 0x0000, 0x0000, 0x0000 }, /* R13461 */ + { 0x0000, 0x0000, 0x0000 }, /* R13462 */ + { 0x0000, 0x0000, 0x0000 }, /* R13463 */ + { 0x0000, 0x0000, 0x0000 }, /* R13464 */ + { 0x0000, 0x0000, 0x0000 }, /* R13465 */ + { 0x0000, 0x0000, 0x0000 }, /* R13466 */ + { 0x0000, 0x0000, 0x0000 }, /* R13467 */ + { 0x0000, 0x0000, 0x0000 }, /* R13468 */ + { 0x0000, 0x0000, 0x0000 }, /* R13469 */ + { 0x0000, 0x0000, 0x0000 }, /* R13470 */ + { 0x0000, 0x0000, 0x0000 }, /* R13471 */ + { 0x0000, 0x0000, 0x0000 }, /* R13472 */ + { 0x0000, 0x0000, 0x0000 }, /* R13473 */ + { 0x0000, 0x0000, 0x0000 }, /* R13474 */ + { 0x0000, 0x0000, 0x0000 }, /* R13475 */ + { 0x0000, 0x0000, 0x0000 }, /* R13476 */ + { 0x0000, 0x0000, 0x0000 }, /* R13477 */ + { 0x0000, 0x0000, 0x0000 }, /* R13478 */ + { 0x0000, 0x0000, 0x0000 }, /* R13479 */ + { 0x0000, 0x0000, 0x0000 }, /* R13480 */ + { 0x0000, 0x0000, 0x0000 }, /* R13481 */ + { 0x0000, 0x0000, 0x0000 }, /* R13482 */ + { 0x0000, 0x0000, 0x0000 }, /* R13483 */ + { 0x0000, 0x0000, 0x0000 }, /* R13484 */ + { 0x0000, 0x0000, 0x0000 }, /* R13485 */ + { 0x0000, 0x0000, 0x0000 }, /* R13486 */ + { 0x0000, 0x0000, 0x0000 }, /* R13487 */ + { 0x0000, 0x0000, 0x0000 }, /* R13488 */ + { 0x0000, 0x0000, 0x0000 }, /* R13489 */ + { 0x0000, 0x0000, 0x0000 }, /* R13490 */ + { 0x0000, 0x0000, 0x0000 }, /* R13491 */ + { 0x0000, 0x0000, 0x0000 }, /* R13492 */ + { 0x0000, 0x0000, 0x0000 }, /* R13493 */ + { 0x0000, 0x0000, 0x0000 }, /* R13494 */ + { 0x0000, 0x0000, 0x0000 }, /* R13495 */ + { 0x0000, 0x0000, 0x0000 }, /* R13496 */ + { 0x0000, 0x0000, 0x0000 }, /* R13497 */ + { 0x0000, 0x0000, 0x0000 }, /* R13498 */ + { 0x0000, 0x0000, 0x0000 }, /* R13499 */ + { 0x0000, 0x0000, 0x0000 }, /* R13500 */ + { 0x0000, 0x0000, 0x0000 }, /* R13501 */ + { 0x0000, 0x0000, 0x0000 }, /* R13502 */ + { 0x0000, 0x0000, 0x0000 }, /* R13503 */ + { 0x0000, 0x0000, 0x0000 }, /* R13504 */ + { 0x0000, 0x0000, 0x0000 }, /* R13505 */ + { 0x0000, 0x0000, 0x0000 }, /* R13506 */ + { 0x0000, 0x0000, 0x0000 }, /* R13507 */ + { 0x0000, 0x0000, 0x0000 }, /* R13508 */ + { 0x0000, 0x0000, 0x0000 }, /* R13509 */ + { 0x0000, 0x0000, 0x0000 }, /* R13510 */ + { 0x0000, 0x0000, 0x0000 }, /* R13511 */ + { 0x0000, 0x0000, 0x0000 }, /* R13512 */ + { 0x0000, 0x0000, 0x0000 }, /* R13513 */ + { 0x0000, 0x0000, 0x0000 }, /* R13514 */ + { 0x0000, 0x0000, 0x0000 }, /* R13515 */ + { 0x0000, 0x0000, 0x0000 }, /* R13516 */ + { 0x0000, 0x0000, 0x0000 }, /* R13517 */ + { 0x0000, 0x0000, 0x0000 }, /* R13518 */ + { 0x0000, 0x0000, 0x0000 }, /* R13519 */ + { 0x0000, 0x0000, 0x0000 }, /* R13520 */ + { 0x0000, 0x0000, 0x0000 }, /* R13521 */ + { 0x0000, 0x0000, 0x0000 }, /* R13522 */ + { 0x0000, 0x0000, 0x0000 }, /* R13523 */ + { 0x0000, 0x0000, 0x0000 }, /* R13524 */ + { 0x0000, 0x0000, 0x0000 }, /* R13525 */ + { 0x0000, 0x0000, 0x0000 }, /* R13526 */ + { 0x0000, 0x0000, 0x0000 }, /* R13527 */ + { 0x0000, 0x0000, 0x0000 }, /* R13528 */ + { 0x0000, 0x0000, 0x0000 }, /* R13529 */ + { 0x0000, 0x0000, 0x0000 }, /* R13530 */ + { 0x0000, 0x0000, 0x0000 }, /* R13531 */ + { 0x0000, 0x0000, 0x0000 }, /* R13532 */ + { 0x0000, 0x0000, 0x0000 }, /* R13533 */ + { 0x0000, 0x0000, 0x0000 }, /* R13534 */ + { 0x0000, 0x0000, 0x0000 }, /* R13535 */ + { 0x0000, 0x0000, 0x0000 }, /* R13536 */ + { 0x0000, 0x0000, 0x0000 }, /* R13537 */ + { 0x0000, 0x0000, 0x0000 }, /* R13538 */ + { 0x0000, 0x0000, 0x0000 }, /* R13539 */ + { 0x0000, 0x0000, 0x0000 }, /* R13540 */ + { 0x0000, 0x0000, 0x0000 }, /* R13541 */ + { 0x0000, 0x0000, 0x0000 }, /* R13542 */ + { 0x0000, 0x0000, 0x0000 }, /* R13543 */ + { 0x0000, 0x0000, 0x0000 }, /* R13544 */ + { 0x0000, 0x0000, 0x0000 }, /* R13545 */ + { 0x0000, 0x0000, 0x0000 }, /* R13546 */ + { 0x0000, 0x0000, 0x0000 }, /* R13547 */ + { 0x0000, 0x0000, 0x0000 }, /* R13548 */ + { 0x0000, 0x0000, 0x0000 }, /* R13549 */ + { 0x0000, 0x0000, 0x0000 }, /* R13550 */ + { 0x0000, 0x0000, 0x0000 }, /* R13551 */ + { 0x0000, 0x0000, 0x0000 }, /* R13552 */ + { 0x0000, 0x0000, 0x0000 }, /* R13553 */ + { 0x0000, 0x0000, 0x0000 }, /* R13554 */ + { 0x0000, 0x0000, 0x0000 }, /* R13555 */ + { 0x0000, 0x0000, 0x0000 }, /* R13556 */ + { 0x0000, 0x0000, 0x0000 }, /* R13557 */ + { 0x0000, 0x0000, 0x0000 }, /* R13558 */ + { 0x0000, 0x0000, 0x0000 }, /* R13559 */ + { 0x0000, 0x0000, 0x0000 }, /* R13560 */ + { 0x0000, 0x0000, 0x0000 }, /* R13561 */ + { 0x0000, 0x0000, 0x0000 }, /* R13562 */ + { 0x0000, 0x0000, 0x0000 }, /* R13563 */ + { 0x0000, 0x0000, 0x0000 }, /* R13564 */ + { 0x0000, 0x0000, 0x0000 }, /* R13565 */ + { 0x0000, 0x0000, 0x0000 }, /* R13566 */ + { 0x0000, 0x0000, 0x0000 }, /* R13567 */ + { 0x0000, 0x0000, 0x0000 }, /* R13568 */ + { 0x0000, 0x0000, 0x0000 }, /* R13569 */ + { 0x0000, 0x0000, 0x0000 }, /* R13570 */ + { 0x0000, 0x0000, 0x0000 }, /* R13571 */ + { 0x0000, 0x0000, 0x0000 }, /* R13572 */ + { 0x0000, 0x0000, 0x0000 }, /* R13573 */ + { 0x0000, 0x0000, 0x0000 }, /* R13574 */ + { 0x0000, 0x0000, 0x0000 }, /* R13575 */ + { 0x0000, 0x0000, 0x0000 }, /* R13576 */ + { 0x0000, 0x0000, 0x0000 }, /* R13577 */ + { 0x0000, 0x0000, 0x0000 }, /* R13578 */ + { 0x0000, 0x0000, 0x0000 }, /* R13579 */ + { 0x0000, 0x0000, 0x0000 }, /* R13580 */ + { 0x0000, 0x0000, 0x0000 }, /* R13581 */ + { 0x0000, 0x0000, 0x0000 }, /* R13582 */ + { 0x0000, 0x0000, 0x0000 }, /* R13583 */ + { 0x0000, 0x0000, 0x0000 }, /* R13584 */ + { 0x0000, 0x0000, 0x0000 }, /* R13585 */ + { 0x0000, 0x0000, 0x0000 }, /* R13586 */ + { 0x0000, 0x0000, 0x0000 }, /* R13587 */ + { 0x0000, 0x0000, 0x0000 }, /* R13588 */ + { 0x0000, 0x0000, 0x0000 }, /* R13589 */ + { 0x0000, 0x0000, 0x0000 }, /* R13590 */ + { 0x0000, 0x0000, 0x0000 }, /* R13591 */ + { 0x0000, 0x0000, 0x0000 }, /* R13592 */ + { 0x0000, 0x0000, 0x0000 }, /* R13593 */ + { 0x0000, 0x0000, 0x0000 }, /* R13594 */ + { 0x0000, 0x0000, 0x0000 }, /* R13595 */ + { 0x0000, 0x0000, 0x0000 }, /* R13596 */ + { 0x0000, 0x0000, 0x0000 }, /* R13597 */ + { 0x0000, 0x0000, 0x0000 }, /* R13598 */ + { 0x0000, 0x0000, 0x0000 }, /* R13599 */ + { 0x0000, 0x0000, 0x0000 }, /* R13600 */ + { 0x0000, 0x0000, 0x0000 }, /* R13601 */ + { 0x0000, 0x0000, 0x0000 }, /* R13602 */ + { 0x0000, 0x0000, 0x0000 }, /* R13603 */ + { 0x0000, 0x0000, 0x0000 }, /* R13604 */ + { 0x0000, 0x0000, 0x0000 }, /* R13605 */ + { 0x0000, 0x0000, 0x0000 }, /* R13606 */ + { 0x0000, 0x0000, 0x0000 }, /* R13607 */ + { 0x0000, 0x0000, 0x0000 }, /* R13608 */ + { 0x0000, 0x0000, 0x0000 }, /* R13609 */ + { 0x0000, 0x0000, 0x0000 }, /* R13610 */ + { 0x0000, 0x0000, 0x0000 }, /* R13611 */ + { 0x0000, 0x0000, 0x0000 }, /* R13612 */ + { 0x0000, 0x0000, 0x0000 }, /* R13613 */ + { 0x0000, 0x0000, 0x0000 }, /* R13614 */ + { 0x0000, 0x0000, 0x0000 }, /* R13615 */ + { 0x0000, 0x0000, 0x0000 }, /* R13616 */ + { 0x0000, 0x0000, 0x0000 }, /* R13617 */ + { 0x0000, 0x0000, 0x0000 }, /* R13618 */ + { 0x0000, 0x0000, 0x0000 }, /* R13619 */ + { 0x0000, 0x0000, 0x0000 }, /* R13620 */ + { 0x0000, 0x0000, 0x0000 }, /* R13621 */ + { 0x0000, 0x0000, 0x0000 }, /* R13622 */ + { 0x0000, 0x0000, 0x0000 }, /* R13623 */ + { 0x0000, 0x0000, 0x0000 }, /* R13624 */ + { 0x0000, 0x0000, 0x0000 }, /* R13625 */ + { 0x0000, 0x0000, 0x0000 }, /* R13626 */ + { 0x0000, 0x0000, 0x0000 }, /* R13627 */ + { 0x0000, 0x0000, 0x0000 }, /* R13628 */ + { 0x0000, 0x0000, 0x0000 }, /* R13629 */ + { 0x0000, 0x0000, 0x0000 }, /* R13630 */ + { 0x0000, 0x0000, 0x0000 }, /* R13631 */ + { 0x0000, 0x0000, 0x0000 }, /* R13632 */ + { 0x0000, 0x0000, 0x0000 }, /* R13633 */ + { 0x0000, 0x0000, 0x0000 }, /* R13634 */ + { 0x0000, 0x0000, 0x0000 }, /* R13635 */ + { 0x0000, 0x0000, 0x0000 }, /* R13636 */ + { 0x0000, 0x0000, 0x0000 }, /* R13637 */ + { 0x0000, 0x0000, 0x0000 }, /* R13638 */ + { 0x0000, 0x0000, 0x0000 }, /* R13639 */ + { 0x0000, 0x0000, 0x0000 }, /* R13640 */ + { 0x0000, 0x0000, 0x0000 }, /* R13641 */ + { 0x0000, 0x0000, 0x0000 }, /* R13642 */ + { 0x0000, 0x0000, 0x0000 }, /* R13643 */ + { 0x0000, 0x0000, 0x0000 }, /* R13644 */ + { 0x0000, 0x0000, 0x0000 }, /* R13645 */ + { 0x0000, 0x0000, 0x0000 }, /* R13646 */ + { 0x0000, 0x0000, 0x0000 }, /* R13647 */ + { 0x0000, 0x0000, 0x0000 }, /* R13648 */ + { 0x0000, 0x0000, 0x0000 }, /* R13649 */ + { 0x0000, 0x0000, 0x0000 }, /* R13650 */ + { 0x0000, 0x0000, 0x0000 }, /* R13651 */ + { 0x0000, 0x0000, 0x0000 }, /* R13652 */ + { 0x0000, 0x0000, 0x0000 }, /* R13653 */ + { 0x0000, 0x0000, 0x0000 }, /* R13654 */ + { 0x0000, 0x0000, 0x0000 }, /* R13655 */ + { 0x0000, 0x0000, 0x0000 }, /* R13656 */ + { 0x0000, 0x0000, 0x0000 }, /* R13657 */ + { 0x0000, 0x0000, 0x0000 }, /* R13658 */ + { 0x0000, 0x0000, 0x0000 }, /* R13659 */ + { 0x0000, 0x0000, 0x0000 }, /* R13660 */ + { 0x0000, 0x0000, 0x0000 }, /* R13661 */ + { 0x0000, 0x0000, 0x0000 }, /* R13662 */ + { 0x0000, 0x0000, 0x0000 }, /* R13663 */ + { 0x0000, 0x0000, 0x0000 }, /* R13664 */ + { 0x0000, 0x0000, 0x0000 }, /* R13665 */ + { 0x0000, 0x0000, 0x0000 }, /* R13666 */ + { 0x0000, 0x0000, 0x0000 }, /* R13667 */ + { 0x0000, 0x0000, 0x0000 }, /* R13668 */ + { 0x0000, 0x0000, 0x0000 }, /* R13669 */ + { 0x0000, 0x0000, 0x0000 }, /* R13670 */ + { 0x0000, 0x0000, 0x0000 }, /* R13671 */ + { 0x0000, 0x0000, 0x0000 }, /* R13672 */ + { 0x0000, 0x0000, 0x0000 }, /* R13673 */ + { 0x0000, 0x0000, 0x0000 }, /* R13674 */ + { 0x0000, 0x0000, 0x0000 }, /* R13675 */ + { 0x0000, 0x0000, 0x0000 }, /* R13676 */ + { 0x0000, 0x0000, 0x0000 }, /* R13677 */ + { 0x0000, 0x0000, 0x0000 }, /* R13678 */ + { 0x0000, 0x0000, 0x0000 }, /* R13679 */ + { 0x0000, 0x0000, 0x0000 }, /* R13680 */ + { 0x0000, 0x0000, 0x0000 }, /* R13681 */ + { 0x0000, 0x0000, 0x0000 }, /* R13682 */ + { 0x0000, 0x0000, 0x0000 }, /* R13683 */ + { 0x0000, 0x0000, 0x0000 }, /* R13684 */ + { 0x0000, 0x0000, 0x0000 }, /* R13685 */ + { 0x0000, 0x0000, 0x0000 }, /* R13686 */ + { 0x0000, 0x0000, 0x0000 }, /* R13687 */ + { 0x0000, 0x0000, 0x0000 }, /* R13688 */ + { 0x0000, 0x0000, 0x0000 }, /* R13689 */ + { 0x0000, 0x0000, 0x0000 }, /* R13690 */ + { 0x0000, 0x0000, 0x0000 }, /* R13691 */ + { 0x0000, 0x0000, 0x0000 }, /* R13692 */ + { 0x0000, 0x0000, 0x0000 }, /* R13693 */ + { 0x0000, 0x0000, 0x0000 }, /* R13694 */ + { 0x0000, 0x0000, 0x0000 }, /* R13695 */ + { 0x0000, 0x0000, 0x0000 }, /* R13696 */ + { 0x0000, 0x0000, 0x0000 }, /* R13697 */ + { 0x0000, 0x0000, 0x0000 }, /* R13698 */ + { 0x0000, 0x0000, 0x0000 }, /* R13699 */ + { 0x0000, 0x0000, 0x0000 }, /* R13700 */ + { 0x0000, 0x0000, 0x0000 }, /* R13701 */ + { 0x0000, 0x0000, 0x0000 }, /* R13702 */ + { 0x0000, 0x0000, 0x0000 }, /* R13703 */ + { 0x0000, 0x0000, 0x0000 }, /* R13704 */ + { 0x0000, 0x0000, 0x0000 }, /* R13705 */ + { 0x0000, 0x0000, 0x0000 }, /* R13706 */ + { 0x0000, 0x0000, 0x0000 }, /* R13707 */ + { 0x0000, 0x0000, 0x0000 }, /* R13708 */ + { 0x0000, 0x0000, 0x0000 }, /* R13709 */ + { 0x0000, 0x0000, 0x0000 }, /* R13710 */ + { 0x0000, 0x0000, 0x0000 }, /* R13711 */ + { 0x0000, 0x0000, 0x0000 }, /* R13712 */ + { 0x0000, 0x0000, 0x0000 }, /* R13713 */ + { 0x0000, 0x0000, 0x0000 }, /* R13714 */ + { 0x0000, 0x0000, 0x0000 }, /* R13715 */ + { 0x0000, 0x0000, 0x0000 }, /* R13716 */ + { 0x0000, 0x0000, 0x0000 }, /* R13717 */ + { 0x0000, 0x0000, 0x0000 }, /* R13718 */ + { 0x0000, 0x0000, 0x0000 }, /* R13719 */ + { 0x0000, 0x0000, 0x0000 }, /* R13720 */ + { 0x0000, 0x0000, 0x0000 }, /* R13721 */ + { 0x0000, 0x0000, 0x0000 }, /* R13722 */ + { 0x0000, 0x0000, 0x0000 }, /* R13723 */ + { 0x0000, 0x0000, 0x0000 }, /* R13724 */ + { 0x0000, 0x0000, 0x0000 }, /* R13725 */ + { 0x0000, 0x0000, 0x0000 }, /* R13726 */ + { 0x0000, 0x0000, 0x0000 }, /* R13727 */ + { 0x0000, 0x0000, 0x0000 }, /* R13728 */ + { 0x0000, 0x0000, 0x0000 }, /* R13729 */ + { 0x0000, 0x0000, 0x0000 }, /* R13730 */ + { 0x0000, 0x0000, 0x0000 }, /* R13731 */ + { 0x0000, 0x0000, 0x0000 }, /* R13732 */ + { 0x0000, 0x0000, 0x0000 }, /* R13733 */ + { 0x0000, 0x0000, 0x0000 }, /* R13734 */ + { 0x0000, 0x0000, 0x0000 }, /* R13735 */ + { 0x0000, 0x0000, 0x0000 }, /* R13736 */ + { 0x0000, 0x0000, 0x0000 }, /* R13737 */ + { 0x0000, 0x0000, 0x0000 }, /* R13738 */ + { 0x0000, 0x0000, 0x0000 }, /* R13739 */ + { 0x0000, 0x0000, 0x0000 }, /* R13740 */ + { 0x0000, 0x0000, 0x0000 }, /* R13741 */ + { 0x0000, 0x0000, 0x0000 }, /* R13742 */ + { 0x0000, 0x0000, 0x0000 }, /* R13743 */ + { 0x0000, 0x0000, 0x0000 }, /* R13744 */ + { 0x0000, 0x0000, 0x0000 }, /* R13745 */ + { 0x0000, 0x0000, 0x0000 }, /* R13746 */ + { 0x0000, 0x0000, 0x0000 }, /* R13747 */ + { 0x0000, 0x0000, 0x0000 }, /* R13748 */ + { 0x0000, 0x0000, 0x0000 }, /* R13749 */ + { 0x0000, 0x0000, 0x0000 }, /* R13750 */ + { 0x0000, 0x0000, 0x0000 }, /* R13751 */ + { 0x0000, 0x0000, 0x0000 }, /* R13752 */ + { 0x0000, 0x0000, 0x0000 }, /* R13753 */ + { 0x0000, 0x0000, 0x0000 }, /* R13754 */ + { 0x0000, 0x0000, 0x0000 }, /* R13755 */ + { 0x0000, 0x0000, 0x0000 }, /* R13756 */ + { 0x0000, 0x0000, 0x0000 }, /* R13757 */ + { 0x0000, 0x0000, 0x0000 }, /* R13758 */ + { 0x0000, 0x0000, 0x0000 }, /* R13759 */ + { 0x0000, 0x0000, 0x0000 }, /* R13760 */ + { 0x0000, 0x0000, 0x0000 }, /* R13761 */ + { 0x0000, 0x0000, 0x0000 }, /* R13762 */ + { 0x0000, 0x0000, 0x0000 }, /* R13763 */ + { 0x0000, 0x0000, 0x0000 }, /* R13764 */ + { 0x0000, 0x0000, 0x0000 }, /* R13765 */ + { 0x0000, 0x0000, 0x0000 }, /* R13766 */ + { 0x0000, 0x0000, 0x0000 }, /* R13767 */ + { 0x0000, 0x0000, 0x0000 }, /* R13768 */ + { 0x0000, 0x0000, 0x0000 }, /* R13769 */ + { 0x0000, 0x0000, 0x0000 }, /* R13770 */ + { 0x0000, 0x0000, 0x0000 }, /* R13771 */ + { 0x0000, 0x0000, 0x0000 }, /* R13772 */ + { 0x0000, 0x0000, 0x0000 }, /* R13773 */ + { 0x0000, 0x0000, 0x0000 }, /* R13774 */ + { 0x0000, 0x0000, 0x0000 }, /* R13775 */ + { 0x0000, 0x0000, 0x0000 }, /* R13776 */ + { 0x0000, 0x0000, 0x0000 }, /* R13777 */ + { 0x0000, 0x0000, 0x0000 }, /* R13778 */ + { 0x0000, 0x0000, 0x0000 }, /* R13779 */ + { 0x0000, 0x0000, 0x0000 }, /* R13780 */ + { 0x0000, 0x0000, 0x0000 }, /* R13781 */ + { 0x0000, 0x0000, 0x0000 }, /* R13782 */ + { 0x0000, 0x0000, 0x0000 }, /* R13783 */ + { 0x0000, 0x0000, 0x0000 }, /* R13784 */ + { 0x0000, 0x0000, 0x0000 }, /* R13785 */ + { 0x0000, 0x0000, 0x0000 }, /* R13786 */ + { 0x0000, 0x0000, 0x0000 }, /* R13787 */ + { 0x0000, 0x0000, 0x0000 }, /* R13788 */ + { 0x0000, 0x0000, 0x0000 }, /* R13789 */ + { 0x0000, 0x0000, 0x0000 }, /* R13790 */ + { 0x0000, 0x0000, 0x0000 }, /* R13791 */ + { 0x0000, 0x0000, 0x0000 }, /* R13792 */ + { 0x0000, 0x0000, 0x0000 }, /* R13793 */ + { 0x0000, 0x0000, 0x0000 }, /* R13794 */ + { 0x0000, 0x0000, 0x0000 }, /* R13795 */ + { 0x0000, 0x0000, 0x0000 }, /* R13796 */ + { 0x0000, 0x0000, 0x0000 }, /* R13797 */ + { 0x0000, 0x0000, 0x0000 }, /* R13798 */ + { 0x0000, 0x0000, 0x0000 }, /* R13799 */ + { 0x0000, 0x0000, 0x0000 }, /* R13800 */ + { 0x0000, 0x0000, 0x0000 }, /* R13801 */ + { 0x0000, 0x0000, 0x0000 }, /* R13802 */ + { 0x0000, 0x0000, 0x0000 }, /* R13803 */ + { 0x0000, 0x0000, 0x0000 }, /* R13804 */ + { 0x0000, 0x0000, 0x0000 }, /* R13805 */ + { 0x0000, 0x0000, 0x0000 }, /* R13806 */ + { 0x0000, 0x0000, 0x0000 }, /* R13807 */ + { 0x0000, 0x0000, 0x0000 }, /* R13808 */ + { 0x0000, 0x0000, 0x0000 }, /* R13809 */ + { 0x0000, 0x0000, 0x0000 }, /* R13810 */ + { 0x0000, 0x0000, 0x0000 }, /* R13811 */ + { 0x0000, 0x0000, 0x0000 }, /* R13812 */ + { 0x0000, 0x0000, 0x0000 }, /* R13813 */ + { 0x0000, 0x0000, 0x0000 }, /* R13814 */ + { 0x0000, 0x0000, 0x0000 }, /* R13815 */ + { 0x0000, 0x0000, 0x0000 }, /* R13816 */ + { 0x0000, 0x0000, 0x0000 }, /* R13817 */ + { 0x0000, 0x0000, 0x0000 }, /* R13818 */ + { 0x0000, 0x0000, 0x0000 }, /* R13819 */ + { 0x0000, 0x0000, 0x0000 }, /* R13820 */ + { 0x0000, 0x0000, 0x0000 }, /* R13821 */ + { 0x0000, 0x0000, 0x0000 }, /* R13822 */ + { 0x0000, 0x0000, 0x0000 }, /* R13823 */ + { 0x0000, 0x0000, 0x0000 }, /* R13824 */ + { 0x0000, 0x0000, 0x0000 }, /* R13825 */ + { 0x0000, 0x0000, 0x0000 }, /* R13826 */ + { 0x0000, 0x0000, 0x0000 }, /* R13827 */ + { 0x0000, 0x0000, 0x0000 }, /* R13828 */ + { 0x0000, 0x0000, 0x0000 }, /* R13829 */ + { 0x0000, 0x0000, 0x0000 }, /* R13830 */ + { 0x0000, 0x0000, 0x0000 }, /* R13831 */ + { 0x0000, 0x0000, 0x0000 }, /* R13832 */ + { 0x0000, 0x0000, 0x0000 }, /* R13833 */ + { 0x0000, 0x0000, 0x0000 }, /* R13834 */ + { 0x0000, 0x0000, 0x0000 }, /* R13835 */ + { 0x0000, 0x0000, 0x0000 }, /* R13836 */ + { 0x0000, 0x0000, 0x0000 }, /* R13837 */ + { 0x0000, 0x0000, 0x0000 }, /* R13838 */ + { 0x0000, 0x0000, 0x0000 }, /* R13839 */ + { 0x0000, 0x0000, 0x0000 }, /* R13840 */ + { 0x0000, 0x0000, 0x0000 }, /* R13841 */ + { 0x0000, 0x0000, 0x0000 }, /* R13842 */ + { 0x0000, 0x0000, 0x0000 }, /* R13843 */ + { 0x0000, 0x0000, 0x0000 }, /* R13844 */ + { 0x0000, 0x0000, 0x0000 }, /* R13845 */ + { 0x0000, 0x0000, 0x0000 }, /* R13846 */ + { 0x0000, 0x0000, 0x0000 }, /* R13847 */ + { 0x0000, 0x0000, 0x0000 }, /* R13848 */ + { 0x0000, 0x0000, 0x0000 }, /* R13849 */ + { 0x0000, 0x0000, 0x0000 }, /* R13850 */ + { 0x0000, 0x0000, 0x0000 }, /* R13851 */ + { 0x0000, 0x0000, 0x0000 }, /* R13852 */ + { 0x0000, 0x0000, 0x0000 }, /* R13853 */ + { 0x0000, 0x0000, 0x0000 }, /* R13854 */ + { 0x0000, 0x0000, 0x0000 }, /* R13855 */ + { 0x0000, 0x0000, 0x0000 }, /* R13856 */ + { 0x0000, 0x0000, 0x0000 }, /* R13857 */ + { 0x0000, 0x0000, 0x0000 }, /* R13858 */ + { 0x0000, 0x0000, 0x0000 }, /* R13859 */ + { 0x0000, 0x0000, 0x0000 }, /* R13860 */ + { 0x0000, 0x0000, 0x0000 }, /* R13861 */ + { 0x0000, 0x0000, 0x0000 }, /* R13862 */ + { 0x0000, 0x0000, 0x0000 }, /* R13863 */ + { 0x0000, 0x0000, 0x0000 }, /* R13864 */ + { 0x0000, 0x0000, 0x0000 }, /* R13865 */ + { 0x0000, 0x0000, 0x0000 }, /* R13866 */ + { 0x0000, 0x0000, 0x0000 }, /* R13867 */ + { 0x0000, 0x0000, 0x0000 }, /* R13868 */ + { 0x0000, 0x0000, 0x0000 }, /* R13869 */ + { 0x0000, 0x0000, 0x0000 }, /* R13870 */ + { 0x0000, 0x0000, 0x0000 }, /* R13871 */ + { 0x0000, 0x0000, 0x0000 }, /* R13872 */ + { 0x0000, 0x0000, 0x0000 }, /* R13873 */ + { 0x0000, 0x0000, 0x0000 }, /* R13874 */ + { 0x0000, 0x0000, 0x0000 }, /* R13875 */ + { 0x0000, 0x0000, 0x0000 }, /* R13876 */ + { 0x0000, 0x0000, 0x0000 }, /* R13877 */ + { 0x0000, 0x0000, 0x0000 }, /* R13878 */ + { 0x0000, 0x0000, 0x0000 }, /* R13879 */ + { 0x0000, 0x0000, 0x0000 }, /* R13880 */ + { 0x0000, 0x0000, 0x0000 }, /* R13881 */ + { 0x0000, 0x0000, 0x0000 }, /* R13882 */ + { 0x0000, 0x0000, 0x0000 }, /* R13883 */ + { 0x0000, 0x0000, 0x0000 }, /* R13884 */ + { 0x0000, 0x0000, 0x0000 }, /* R13885 */ + { 0x0000, 0x0000, 0x0000 }, /* R13886 */ + { 0x0000, 0x0000, 0x0000 }, /* R13887 */ + { 0x0000, 0x0000, 0x0000 }, /* R13888 */ + { 0x0000, 0x0000, 0x0000 }, /* R13889 */ + { 0x0000, 0x0000, 0x0000 }, /* R13890 */ + { 0x0000, 0x0000, 0x0000 }, /* R13891 */ + { 0x0000, 0x0000, 0x0000 }, /* R13892 */ + { 0x0000, 0x0000, 0x0000 }, /* R13893 */ + { 0x0000, 0x0000, 0x0000 }, /* R13894 */ + { 0x0000, 0x0000, 0x0000 }, /* R13895 */ + { 0x0000, 0x0000, 0x0000 }, /* R13896 */ + { 0x0000, 0x0000, 0x0000 }, /* R13897 */ + { 0x0000, 0x0000, 0x0000 }, /* R13898 */ + { 0x0000, 0x0000, 0x0000 }, /* R13899 */ + { 0x0000, 0x0000, 0x0000 }, /* R13900 */ + { 0x0000, 0x0000, 0x0000 }, /* R13901 */ + { 0x0000, 0x0000, 0x0000 }, /* R13902 */ + { 0x0000, 0x0000, 0x0000 }, /* R13903 */ + { 0x0000, 0x0000, 0x0000 }, /* R13904 */ + { 0x0000, 0x0000, 0x0000 }, /* R13905 */ + { 0x0000, 0x0000, 0x0000 }, /* R13906 */ + { 0x0000, 0x0000, 0x0000 }, /* R13907 */ + { 0x0000, 0x0000, 0x0000 }, /* R13908 */ + { 0x0000, 0x0000, 0x0000 }, /* R13909 */ + { 0x0000, 0x0000, 0x0000 }, /* R13910 */ + { 0x0000, 0x0000, 0x0000 }, /* R13911 */ + { 0x0000, 0x0000, 0x0000 }, /* R13912 */ + { 0x0000, 0x0000, 0x0000 }, /* R13913 */ + { 0x0000, 0x0000, 0x0000 }, /* R13914 */ + { 0x0000, 0x0000, 0x0000 }, /* R13915 */ + { 0x0000, 0x0000, 0x0000 }, /* R13916 */ + { 0x0000, 0x0000, 0x0000 }, /* R13917 */ + { 0x0000, 0x0000, 0x0000 }, /* R13918 */ + { 0x0000, 0x0000, 0x0000 }, /* R13919 */ + { 0x0000, 0x0000, 0x0000 }, /* R13920 */ + { 0x0000, 0x0000, 0x0000 }, /* R13921 */ + { 0x0000, 0x0000, 0x0000 }, /* R13922 */ + { 0x0000, 0x0000, 0x0000 }, /* R13923 */ + { 0x0000, 0x0000, 0x0000 }, /* R13924 */ + { 0x0000, 0x0000, 0x0000 }, /* R13925 */ + { 0x0000, 0x0000, 0x0000 }, /* R13926 */ + { 0x0000, 0x0000, 0x0000 }, /* R13927 */ + { 0x0000, 0x0000, 0x0000 }, /* R13928 */ + { 0x0000, 0x0000, 0x0000 }, /* R13929 */ + { 0x0000, 0x0000, 0x0000 }, /* R13930 */ + { 0x0000, 0x0000, 0x0000 }, /* R13931 */ + { 0x0000, 0x0000, 0x0000 }, /* R13932 */ + { 0x0000, 0x0000, 0x0000 }, /* R13933 */ + { 0x0000, 0x0000, 0x0000 }, /* R13934 */ + { 0x0000, 0x0000, 0x0000 }, /* R13935 */ + { 0x0000, 0x0000, 0x0000 }, /* R13936 */ + { 0x0000, 0x0000, 0x0000 }, /* R13937 */ + { 0x0000, 0x0000, 0x0000 }, /* R13938 */ + { 0x0000, 0x0000, 0x0000 }, /* R13939 */ + { 0x0000, 0x0000, 0x0000 }, /* R13940 */ + { 0x0000, 0x0000, 0x0000 }, /* R13941 */ + { 0x0000, 0x0000, 0x0000 }, /* R13942 */ + { 0x0000, 0x0000, 0x0000 }, /* R13943 */ + { 0x0000, 0x0000, 0x0000 }, /* R13944 */ + { 0x0000, 0x0000, 0x0000 }, /* R13945 */ + { 0x0000, 0x0000, 0x0000 }, /* R13946 */ + { 0x0000, 0x0000, 0x0000 }, /* R13947 */ + { 0x0000, 0x0000, 0x0000 }, /* R13948 */ + { 0x0000, 0x0000, 0x0000 }, /* R13949 */ + { 0x0000, 0x0000, 0x0000 }, /* R13950 */ + { 0x0000, 0x0000, 0x0000 }, /* R13951 */ + { 0x0000, 0x0000, 0x0000 }, /* R13952 */ + { 0x0000, 0x0000, 0x0000 }, /* R13953 */ + { 0x0000, 0x0000, 0x0000 }, /* R13954 */ + { 0x0000, 0x0000, 0x0000 }, /* R13955 */ + { 0x0000, 0x0000, 0x0000 }, /* R13956 */ + { 0x0000, 0x0000, 0x0000 }, /* R13957 */ + { 0x0000, 0x0000, 0x0000 }, /* R13958 */ + { 0x0000, 0x0000, 0x0000 }, /* R13959 */ + { 0x0000, 0x0000, 0x0000 }, /* R13960 */ + { 0x0000, 0x0000, 0x0000 }, /* R13961 */ + { 0x0000, 0x0000, 0x0000 }, /* R13962 */ + { 0x0000, 0x0000, 0x0000 }, /* R13963 */ + { 0x0000, 0x0000, 0x0000 }, /* R13964 */ + { 0x0000, 0x0000, 0x0000 }, /* R13965 */ + { 0x0000, 0x0000, 0x0000 }, /* R13966 */ + { 0x0000, 0x0000, 0x0000 }, /* R13967 */ + { 0x0000, 0x0000, 0x0000 }, /* R13968 */ + { 0x0000, 0x0000, 0x0000 }, /* R13969 */ + { 0x0000, 0x0000, 0x0000 }, /* R13970 */ + { 0x0000, 0x0000, 0x0000 }, /* R13971 */ + { 0x0000, 0x0000, 0x0000 }, /* R13972 */ + { 0x0000, 0x0000, 0x0000 }, /* R13973 */ + { 0x0000, 0x0000, 0x0000 }, /* R13974 */ + { 0x0000, 0x0000, 0x0000 }, /* R13975 */ + { 0x0000, 0x0000, 0x0000 }, /* R13976 */ + { 0x0000, 0x0000, 0x0000 }, /* R13977 */ + { 0x0000, 0x0000, 0x0000 }, /* R13978 */ + { 0x0000, 0x0000, 0x0000 }, /* R13979 */ + { 0x0000, 0x0000, 0x0000 }, /* R13980 */ + { 0x0000, 0x0000, 0x0000 }, /* R13981 */ + { 0x0000, 0x0000, 0x0000 }, /* R13982 */ + { 0x0000, 0x0000, 0x0000 }, /* R13983 */ + { 0x0000, 0x0000, 0x0000 }, /* R13984 */ + { 0x0000, 0x0000, 0x0000 }, /* R13985 */ + { 0x0000, 0x0000, 0x0000 }, /* R13986 */ + { 0x0000, 0x0000, 0x0000 }, /* R13987 */ + { 0x0000, 0x0000, 0x0000 }, /* R13988 */ + { 0x0000, 0x0000, 0x0000 }, /* R13989 */ + { 0x0000, 0x0000, 0x0000 }, /* R13990 */ + { 0x0000, 0x0000, 0x0000 }, /* R13991 */ + { 0x0000, 0x0000, 0x0000 }, /* R13992 */ + { 0x0000, 0x0000, 0x0000 }, /* R13993 */ + { 0x0000, 0x0000, 0x0000 }, /* R13994 */ + { 0x0000, 0x0000, 0x0000 }, /* R13995 */ + { 0x0000, 0x0000, 0x0000 }, /* R13996 */ + { 0x0000, 0x0000, 0x0000 }, /* R13997 */ + { 0x0000, 0x0000, 0x0000 }, /* R13998 */ + { 0x0000, 0x0000, 0x0000 }, /* R13999 */ + { 0x0000, 0x0000, 0x0000 }, /* R14000 */ + { 0x0000, 0x0000, 0x0000 }, /* R14001 */ + { 0x0000, 0x0000, 0x0000 }, /* R14002 */ + { 0x0000, 0x0000, 0x0000 }, /* R14003 */ + { 0x0000, 0x0000, 0x0000 }, /* R14004 */ + { 0x0000, 0x0000, 0x0000 }, /* R14005 */ + { 0x0000, 0x0000, 0x0000 }, /* R14006 */ + { 0x0000, 0x0000, 0x0000 }, /* R14007 */ + { 0x0000, 0x0000, 0x0000 }, /* R14008 */ + { 0x0000, 0x0000, 0x0000 }, /* R14009 */ + { 0x0000, 0x0000, 0x0000 }, /* R14010 */ + { 0x0000, 0x0000, 0x0000 }, /* R14011 */ + { 0x0000, 0x0000, 0x0000 }, /* R14012 */ + { 0x0000, 0x0000, 0x0000 }, /* R14013 */ + { 0x0000, 0x0000, 0x0000 }, /* R14014 */ + { 0x0000, 0x0000, 0x0000 }, /* R14015 */ + { 0x0000, 0x0000, 0x0000 }, /* R14016 */ + { 0x0000, 0x0000, 0x0000 }, /* R14017 */ + { 0x0000, 0x0000, 0x0000 }, /* R14018 */ + { 0x0000, 0x0000, 0x0000 }, /* R14019 */ + { 0x0000, 0x0000, 0x0000 }, /* R14020 */ + { 0x0000, 0x0000, 0x0000 }, /* R14021 */ + { 0x0000, 0x0000, 0x0000 }, /* R14022 */ + { 0x0000, 0x0000, 0x0000 }, /* R14023 */ + { 0x0000, 0x0000, 0x0000 }, /* R14024 */ + { 0x0000, 0x0000, 0x0000 }, /* R14025 */ + { 0x0000, 0x0000, 0x0000 }, /* R14026 */ + { 0x0000, 0x0000, 0x0000 }, /* R14027 */ + { 0x0000, 0x0000, 0x0000 }, /* R14028 */ + { 0x0000, 0x0000, 0x0000 }, /* R14029 */ + { 0x0000, 0x0000, 0x0000 }, /* R14030 */ + { 0x0000, 0x0000, 0x0000 }, /* R14031 */ + { 0x0000, 0x0000, 0x0000 }, /* R14032 */ + { 0x0000, 0x0000, 0x0000 }, /* R14033 */ + { 0x0000, 0x0000, 0x0000 }, /* R14034 */ + { 0x0000, 0x0000, 0x0000 }, /* R14035 */ + { 0x0000, 0x0000, 0x0000 }, /* R14036 */ + { 0x0000, 0x0000, 0x0000 }, /* R14037 */ + { 0x0000, 0x0000, 0x0000 }, /* R14038 */ + { 0x0000, 0x0000, 0x0000 }, /* R14039 */ + { 0x0000, 0x0000, 0x0000 }, /* R14040 */ + { 0x0000, 0x0000, 0x0000 }, /* R14041 */ + { 0x0000, 0x0000, 0x0000 }, /* R14042 */ + { 0x0000, 0x0000, 0x0000 }, /* R14043 */ + { 0x0000, 0x0000, 0x0000 }, /* R14044 */ + { 0x0000, 0x0000, 0x0000 }, /* R14045 */ + { 0x0000, 0x0000, 0x0000 }, /* R14046 */ + { 0x0000, 0x0000, 0x0000 }, /* R14047 */ + { 0x0000, 0x0000, 0x0000 }, /* R14048 */ + { 0x0000, 0x0000, 0x0000 }, /* R14049 */ + { 0x0000, 0x0000, 0x0000 }, /* R14050 */ + { 0x0000, 0x0000, 0x0000 }, /* R14051 */ + { 0x0000, 0x0000, 0x0000 }, /* R14052 */ + { 0x0000, 0x0000, 0x0000 }, /* R14053 */ + { 0x0000, 0x0000, 0x0000 }, /* R14054 */ + { 0x0000, 0x0000, 0x0000 }, /* R14055 */ + { 0x0000, 0x0000, 0x0000 }, /* R14056 */ + { 0x0000, 0x0000, 0x0000 }, /* R14057 */ + { 0x0000, 0x0000, 0x0000 }, /* R14058 */ + { 0x0000, 0x0000, 0x0000 }, /* R14059 */ + { 0x0000, 0x0000, 0x0000 }, /* R14060 */ + { 0x0000, 0x0000, 0x0000 }, /* R14061 */ + { 0x0000, 0x0000, 0x0000 }, /* R14062 */ + { 0x0000, 0x0000, 0x0000 }, /* R14063 */ + { 0x0000, 0x0000, 0x0000 }, /* R14064 */ + { 0x0000, 0x0000, 0x0000 }, /* R14065 */ + { 0x0000, 0x0000, 0x0000 }, /* R14066 */ + { 0x0000, 0x0000, 0x0000 }, /* R14067 */ + { 0x0000, 0x0000, 0x0000 }, /* R14068 */ + { 0x0000, 0x0000, 0x0000 }, /* R14069 */ + { 0x0000, 0x0000, 0x0000 }, /* R14070 */ + { 0x0000, 0x0000, 0x0000 }, /* R14071 */ + { 0x0000, 0x0000, 0x0000 }, /* R14072 */ + { 0x0000, 0x0000, 0x0000 }, /* R14073 */ + { 0x0000, 0x0000, 0x0000 }, /* R14074 */ + { 0x0000, 0x0000, 0x0000 }, /* R14075 */ + { 0x0000, 0x0000, 0x0000 }, /* R14076 */ + { 0x0000, 0x0000, 0x0000 }, /* R14077 */ + { 0x0000, 0x0000, 0x0000 }, /* R14078 */ + { 0x0000, 0x0000, 0x0000 }, /* R14079 */ + { 0x0000, 0x0000, 0x0000 }, /* R14080 */ + { 0x0000, 0x0000, 0x0000 }, /* R14081 */ + { 0x0000, 0x0000, 0x0000 }, /* R14082 */ + { 0x0000, 0x0000, 0x0000 }, /* R14083 */ + { 0x0000, 0x0000, 0x0000 }, /* R14084 */ + { 0x0000, 0x0000, 0x0000 }, /* R14085 */ + { 0x0000, 0x0000, 0x0000 }, /* R14086 */ + { 0x0000, 0x0000, 0x0000 }, /* R14087 */ + { 0x0000, 0x0000, 0x0000 }, /* R14088 */ + { 0x0000, 0x0000, 0x0000 }, /* R14089 */ + { 0x0000, 0x0000, 0x0000 }, /* R14090 */ + { 0x0000, 0x0000, 0x0000 }, /* R14091 */ + { 0x0000, 0x0000, 0x0000 }, /* R14092 */ + { 0x0000, 0x0000, 0x0000 }, /* R14093 */ + { 0x0000, 0x0000, 0x0000 }, /* R14094 */ + { 0x0000, 0x0000, 0x0000 }, /* R14095 */ + { 0x0000, 0x0000, 0x0000 }, /* R14096 */ + { 0x0000, 0x0000, 0x0000 }, /* R14097 */ + { 0x0000, 0x0000, 0x0000 }, /* R14098 */ + { 0x0000, 0x0000, 0x0000 }, /* R14099 */ + { 0x0000, 0x0000, 0x0000 }, /* R14100 */ + { 0x0000, 0x0000, 0x0000 }, /* R14101 */ + { 0x0000, 0x0000, 0x0000 }, /* R14102 */ + { 0x0000, 0x0000, 0x0000 }, /* R14103 */ + { 0x0000, 0x0000, 0x0000 }, /* R14104 */ + { 0x0000, 0x0000, 0x0000 }, /* R14105 */ + { 0x0000, 0x0000, 0x0000 }, /* R14106 */ + { 0x0000, 0x0000, 0x0000 }, /* R14107 */ + { 0x0000, 0x0000, 0x0000 }, /* R14108 */ + { 0x0000, 0x0000, 0x0000 }, /* R14109 */ + { 0x0000, 0x0000, 0x0000 }, /* R14110 */ + { 0x0000, 0x0000, 0x0000 }, /* R14111 */ + { 0x0000, 0x0000, 0x0000 }, /* R14112 */ + { 0x0000, 0x0000, 0x0000 }, /* R14113 */ + { 0x0000, 0x0000, 0x0000 }, /* R14114 */ + { 0x0000, 0x0000, 0x0000 }, /* R14115 */ + { 0x0000, 0x0000, 0x0000 }, /* R14116 */ + { 0x0000, 0x0000, 0x0000 }, /* R14117 */ + { 0x0000, 0x0000, 0x0000 }, /* R14118 */ + { 0x0000, 0x0000, 0x0000 }, /* R14119 */ + { 0x0000, 0x0000, 0x0000 }, /* R14120 */ + { 0x0000, 0x0000, 0x0000 }, /* R14121 */ + { 0x0000, 0x0000, 0x0000 }, /* R14122 */ + { 0x0000, 0x0000, 0x0000 }, /* R14123 */ + { 0x0000, 0x0000, 0x0000 }, /* R14124 */ + { 0x0000, 0x0000, 0x0000 }, /* R14125 */ + { 0x0000, 0x0000, 0x0000 }, /* R14126 */ + { 0x0000, 0x0000, 0x0000 }, /* R14127 */ + { 0x0000, 0x0000, 0x0000 }, /* R14128 */ + { 0x0000, 0x0000, 0x0000 }, /* R14129 */ + { 0x0000, 0x0000, 0x0000 }, /* R14130 */ + { 0x0000, 0x0000, 0x0000 }, /* R14131 */ + { 0x0000, 0x0000, 0x0000 }, /* R14132 */ + { 0x0000, 0x0000, 0x0000 }, /* R14133 */ + { 0x0000, 0x0000, 0x0000 }, /* R14134 */ + { 0x0000, 0x0000, 0x0000 }, /* R14135 */ + { 0x0000, 0x0000, 0x0000 }, /* R14136 */ + { 0x0000, 0x0000, 0x0000 }, /* R14137 */ + { 0x0000, 0x0000, 0x0000 }, /* R14138 */ + { 0x0000, 0x0000, 0x0000 }, /* R14139 */ + { 0x0000, 0x0000, 0x0000 }, /* R14140 */ + { 0x0000, 0x0000, 0x0000 }, /* R14141 */ + { 0x0000, 0x0000, 0x0000 }, /* R14142 */ + { 0x0000, 0x0000, 0x0000 }, /* R14143 */ + { 0x0000, 0x0000, 0x0000 }, /* R14144 */ + { 0x0000, 0x0000, 0x0000 }, /* R14145 */ + { 0x0000, 0x0000, 0x0000 }, /* R14146 */ + { 0x0000, 0x0000, 0x0000 }, /* R14147 */ + { 0x0000, 0x0000, 0x0000 }, /* R14148 */ + { 0x0000, 0x0000, 0x0000 }, /* R14149 */ + { 0x0000, 0x0000, 0x0000 }, /* R14150 */ + { 0x0000, 0x0000, 0x0000 }, /* R14151 */ + { 0x0000, 0x0000, 0x0000 }, /* R14152 */ + { 0x0000, 0x0000, 0x0000 }, /* R14153 */ + { 0x0000, 0x0000, 0x0000 }, /* R14154 */ + { 0x0000, 0x0000, 0x0000 }, /* R14155 */ + { 0x0000, 0x0000, 0x0000 }, /* R14156 */ + { 0x0000, 0x0000, 0x0000 }, /* R14157 */ + { 0x0000, 0x0000, 0x0000 }, /* R14158 */ + { 0x0000, 0x0000, 0x0000 }, /* R14159 */ + { 0x0000, 0x0000, 0x0000 }, /* R14160 */ + { 0x0000, 0x0000, 0x0000 }, /* R14161 */ + { 0x0000, 0x0000, 0x0000 }, /* R14162 */ + { 0x0000, 0x0000, 0x0000 }, /* R14163 */ + { 0x0000, 0x0000, 0x0000 }, /* R14164 */ + { 0x0000, 0x0000, 0x0000 }, /* R14165 */ + { 0x0000, 0x0000, 0x0000 }, /* R14166 */ + { 0x0000, 0x0000, 0x0000 }, /* R14167 */ + { 0x0000, 0x0000, 0x0000 }, /* R14168 */ + { 0x0000, 0x0000, 0x0000 }, /* R14169 */ + { 0x0000, 0x0000, 0x0000 }, /* R14170 */ + { 0x0000, 0x0000, 0x0000 }, /* R14171 */ + { 0x0000, 0x0000, 0x0000 }, /* R14172 */ + { 0x0000, 0x0000, 0x0000 }, /* R14173 */ + { 0x0000, 0x0000, 0x0000 }, /* R14174 */ + { 0x0000, 0x0000, 0x0000 }, /* R14175 */ + { 0x0000, 0x0000, 0x0000 }, /* R14176 */ + { 0x0000, 0x0000, 0x0000 }, /* R14177 */ + { 0x0000, 0x0000, 0x0000 }, /* R14178 */ + { 0x0000, 0x0000, 0x0000 }, /* R14179 */ + { 0x0000, 0x0000, 0x0000 }, /* R14180 */ + { 0x0000, 0x0000, 0x0000 }, /* R14181 */ + { 0x0000, 0x0000, 0x0000 }, /* R14182 */ + { 0x0000, 0x0000, 0x0000 }, /* R14183 */ + { 0x0000, 0x0000, 0x0000 }, /* R14184 */ + { 0x0000, 0x0000, 0x0000 }, /* R14185 */ + { 0x0000, 0x0000, 0x0000 }, /* R14186 */ + { 0x0000, 0x0000, 0x0000 }, /* R14187 */ + { 0x0000, 0x0000, 0x0000 }, /* R14188 */ + { 0x0000, 0x0000, 0x0000 }, /* R14189 */ + { 0x0000, 0x0000, 0x0000 }, /* R14190 */ + { 0x0000, 0x0000, 0x0000 }, /* R14191 */ + { 0x0000, 0x0000, 0x0000 }, /* R14192 */ + { 0x0000, 0x0000, 0x0000 }, /* R14193 */ + { 0x0000, 0x0000, 0x0000 }, /* R14194 */ + { 0x0000, 0x0000, 0x0000 }, /* R14195 */ + { 0x0000, 0x0000, 0x0000 }, /* R14196 */ + { 0x0000, 0x0000, 0x0000 }, /* R14197 */ + { 0x0000, 0x0000, 0x0000 }, /* R14198 */ + { 0x0000, 0x0000, 0x0000 }, /* R14199 */ + { 0x0000, 0x0000, 0x0000 }, /* R14200 */ + { 0x0000, 0x0000, 0x0000 }, /* R14201 */ + { 0x0000, 0x0000, 0x0000 }, /* R14202 */ + { 0x0000, 0x0000, 0x0000 }, /* R14203 */ + { 0x0000, 0x0000, 0x0000 }, /* R14204 */ + { 0x0000, 0x0000, 0x0000 }, /* R14205 */ + { 0x0000, 0x0000, 0x0000 }, /* R14206 */ + { 0x0000, 0x0000, 0x0000 }, /* R14207 */ + { 0x0000, 0x0000, 0x0000 }, /* R14208 */ + { 0x0000, 0x0000, 0x0000 }, /* R14209 */ + { 0x0000, 0x0000, 0x0000 }, /* R14210 */ + { 0x0000, 0x0000, 0x0000 }, /* R14211 */ + { 0x0000, 0x0000, 0x0000 }, /* R14212 */ + { 0x0000, 0x0000, 0x0000 }, /* R14213 */ + { 0x0000, 0x0000, 0x0000 }, /* R14214 */ + { 0x0000, 0x0000, 0x0000 }, /* R14215 */ + { 0x0000, 0x0000, 0x0000 }, /* R14216 */ + { 0x0000, 0x0000, 0x0000 }, /* R14217 */ + { 0x0000, 0x0000, 0x0000 }, /* R14218 */ + { 0x0000, 0x0000, 0x0000 }, /* R14219 */ + { 0x0000, 0x0000, 0x0000 }, /* R14220 */ + { 0x0000, 0x0000, 0x0000 }, /* R14221 */ + { 0x0000, 0x0000, 0x0000 }, /* R14222 */ + { 0x0000, 0x0000, 0x0000 }, /* R14223 */ + { 0x0000, 0x0000, 0x0000 }, /* R14224 */ + { 0x0000, 0x0000, 0x0000 }, /* R14225 */ + { 0x0000, 0x0000, 0x0000 }, /* R14226 */ + { 0x0000, 0x0000, 0x0000 }, /* R14227 */ + { 0x0000, 0x0000, 0x0000 }, /* R14228 */ + { 0x0000, 0x0000, 0x0000 }, /* R14229 */ + { 0x0000, 0x0000, 0x0000 }, /* R14230 */ + { 0x0000, 0x0000, 0x0000 }, /* R14231 */ + { 0x0000, 0x0000, 0x0000 }, /* R14232 */ + { 0x0000, 0x0000, 0x0000 }, /* R14233 */ + { 0x0000, 0x0000, 0x0000 }, /* R14234 */ + { 0x0000, 0x0000, 0x0000 }, /* R14235 */ + { 0x0000, 0x0000, 0x0000 }, /* R14236 */ + { 0x0000, 0x0000, 0x0000 }, /* R14237 */ + { 0x0000, 0x0000, 0x0000 }, /* R14238 */ + { 0x0000, 0x0000, 0x0000 }, /* R14239 */ + { 0x0000, 0x0000, 0x0000 }, /* R14240 */ + { 0x0000, 0x0000, 0x0000 }, /* R14241 */ + { 0x0000, 0x0000, 0x0000 }, /* R14242 */ + { 0x0000, 0x0000, 0x0000 }, /* R14243 */ + { 0x0000, 0x0000, 0x0000 }, /* R14244 */ + { 0x0000, 0x0000, 0x0000 }, /* R14245 */ + { 0x0000, 0x0000, 0x0000 }, /* R14246 */ + { 0x0000, 0x0000, 0x0000 }, /* R14247 */ + { 0x0000, 0x0000, 0x0000 }, /* R14248 */ + { 0x0000, 0x0000, 0x0000 }, /* R14249 */ + { 0x0000, 0x0000, 0x0000 }, /* R14250 */ + { 0x0000, 0x0000, 0x0000 }, /* R14251 */ + { 0x0000, 0x0000, 0x0000 }, /* R14252 */ + { 0x0000, 0x0000, 0x0000 }, /* R14253 */ + { 0x0000, 0x0000, 0x0000 }, /* R14254 */ + { 0x0000, 0x0000, 0x0000 }, /* R14255 */ + { 0x0000, 0x0000, 0x0000 }, /* R14256 */ + { 0x0000, 0x0000, 0x0000 }, /* R14257 */ + { 0x0000, 0x0000, 0x0000 }, /* R14258 */ + { 0x0000, 0x0000, 0x0000 }, /* R14259 */ + { 0x0000, 0x0000, 0x0000 }, /* R14260 */ + { 0x0000, 0x0000, 0x0000 }, /* R14261 */ + { 0x0000, 0x0000, 0x0000 }, /* R14262 */ + { 0x0000, 0x0000, 0x0000 }, /* R14263 */ + { 0x0000, 0x0000, 0x0000 }, /* R14264 */ + { 0x0000, 0x0000, 0x0000 }, /* R14265 */ + { 0x0000, 0x0000, 0x0000 }, /* R14266 */ + { 0x0000, 0x0000, 0x0000 }, /* R14267 */ + { 0x0000, 0x0000, 0x0000 }, /* R14268 */ + { 0x0000, 0x0000, 0x0000 }, /* R14269 */ + { 0x0000, 0x0000, 0x0000 }, /* R14270 */ + { 0x0000, 0x0000, 0x0000 }, /* R14271 */ + { 0x0000, 0x0000, 0x0000 }, /* R14272 */ + { 0x0000, 0x0000, 0x0000 }, /* R14273 */ + { 0x0000, 0x0000, 0x0000 }, /* R14274 */ + { 0x0000, 0x0000, 0x0000 }, /* R14275 */ + { 0x0000, 0x0000, 0x0000 }, /* R14276 */ + { 0x0000, 0x0000, 0x0000 }, /* R14277 */ + { 0x0000, 0x0000, 0x0000 }, /* R14278 */ + { 0x0000, 0x0000, 0x0000 }, /* R14279 */ + { 0x0000, 0x0000, 0x0000 }, /* R14280 */ + { 0x0000, 0x0000, 0x0000 }, /* R14281 */ + { 0x0000, 0x0000, 0x0000 }, /* R14282 */ + { 0x0000, 0x0000, 0x0000 }, /* R14283 */ + { 0x0000, 0x0000, 0x0000 }, /* R14284 */ + { 0x0000, 0x0000, 0x0000 }, /* R14285 */ + { 0x0000, 0x0000, 0x0000 }, /* R14286 */ + { 0x0000, 0x0000, 0x0000 }, /* R14287 */ + { 0x0000, 0x0000, 0x0000 }, /* R14288 */ + { 0x0000, 0x0000, 0x0000 }, /* R14289 */ + { 0x0000, 0x0000, 0x0000 }, /* R14290 */ + { 0x0000, 0x0000, 0x0000 }, /* R14291 */ + { 0x0000, 0x0000, 0x0000 }, /* R14292 */ + { 0x0000, 0x0000, 0x0000 }, /* R14293 */ + { 0x0000, 0x0000, 0x0000 }, /* R14294 */ + { 0x0000, 0x0000, 0x0000 }, /* R14295 */ + { 0x0000, 0x0000, 0x0000 }, /* R14296 */ + { 0x0000, 0x0000, 0x0000 }, /* R14297 */ + { 0x0000, 0x0000, 0x0000 }, /* R14298 */ + { 0x0000, 0x0000, 0x0000 }, /* R14299 */ + { 0x0000, 0x0000, 0x0000 }, /* R14300 */ + { 0x0000, 0x0000, 0x0000 }, /* R14301 */ + { 0x0000, 0x0000, 0x0000 }, /* R14302 */ + { 0x0000, 0x0000, 0x0000 }, /* R14303 */ + { 0x0000, 0x0000, 0x0000 }, /* R14304 */ + { 0x0000, 0x0000, 0x0000 }, /* R14305 */ + { 0x0000, 0x0000, 0x0000 }, /* R14306 */ + { 0x0000, 0x0000, 0x0000 }, /* R14307 */ + { 0x0000, 0x0000, 0x0000 }, /* R14308 */ + { 0x0000, 0x0000, 0x0000 }, /* R14309 */ + { 0x0000, 0x0000, 0x0000 }, /* R14310 */ + { 0x0000, 0x0000, 0x0000 }, /* R14311 */ + { 0x0000, 0x0000, 0x0000 }, /* R14312 */ + { 0x0000, 0x0000, 0x0000 }, /* R14313 */ + { 0x0000, 0x0000, 0x0000 }, /* R14314 */ + { 0x0000, 0x0000, 0x0000 }, /* R14315 */ + { 0x0000, 0x0000, 0x0000 }, /* R14316 */ + { 0x0000, 0x0000, 0x0000 }, /* R14317 */ + { 0x0000, 0x0000, 0x0000 }, /* R14318 */ + { 0x0000, 0x0000, 0x0000 }, /* R14319 */ + { 0x0000, 0x0000, 0x0000 }, /* R14320 */ + { 0x0000, 0x0000, 0x0000 }, /* R14321 */ + { 0x0000, 0x0000, 0x0000 }, /* R14322 */ + { 0x0000, 0x0000, 0x0000 }, /* R14323 */ + { 0x0000, 0x0000, 0x0000 }, /* R14324 */ + { 0x0000, 0x0000, 0x0000 }, /* R14325 */ + { 0x0000, 0x0000, 0x0000 }, /* R14326 */ + { 0x0000, 0x0000, 0x0000 }, /* R14327 */ + { 0x0000, 0x0000, 0x0000 }, /* R14328 */ + { 0x0000, 0x0000, 0x0000 }, /* R14329 */ + { 0x0000, 0x0000, 0x0000 }, /* R14330 */ + { 0x0000, 0x0000, 0x0000 }, /* R14331 */ + { 0x0000, 0x0000, 0x0000 }, /* R14332 */ + { 0x0000, 0x0000, 0x0000 }, /* R14333 */ + { 0x0000, 0x0000, 0x0000 }, /* R14334 */ + { 0x0000, 0x0000, 0x0000 }, /* R14335 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R14336 - DSP2 Data3 RAM 1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R14337 - DSP2 Data3 RAM 0 */ + { 0x0000, 0x0000, 0x0000 }, /* R14338 */ + { 0x0000, 0x0000, 0x0000 }, /* R14339 */ + { 0x0000, 0x0000, 0x0000 }, /* R14340 */ + { 0x0000, 0x0000, 0x0000 }, /* R14341 */ + { 0x0000, 0x0000, 0x0000 }, /* R14342 */ + { 0x0000, 0x0000, 0x0000 }, /* R14343 */ + { 0x0000, 0x0000, 0x0000 }, /* R14344 */ + { 0x0000, 0x0000, 0x0000 }, /* R14345 */ + { 0x0000, 0x0000, 0x0000 }, /* R14346 */ + { 0x0000, 0x0000, 0x0000 }, /* R14347 */ + { 0x0000, 0x0000, 0x0000 }, /* R14348 */ + { 0x0000, 0x0000, 0x0000 }, /* R14349 */ + { 0x0000, 0x0000, 0x0000 }, /* R14350 */ + { 0x0000, 0x0000, 0x0000 }, /* R14351 */ + { 0x0000, 0x0000, 0x0000 }, /* R14352 */ + { 0x0000, 0x0000, 0x0000 }, /* R14353 */ + { 0x0000, 0x0000, 0x0000 }, /* R14354 */ + { 0x0000, 0x0000, 0x0000 }, /* R14355 */ + { 0x0000, 0x0000, 0x0000 }, /* R14356 */ + { 0x0000, 0x0000, 0x0000 }, /* R14357 */ + { 0x0000, 0x0000, 0x0000 }, /* R14358 */ + { 0x0000, 0x0000, 0x0000 }, /* R14359 */ + { 0x0000, 0x0000, 0x0000 }, /* R14360 */ + { 0x0000, 0x0000, 0x0000 }, /* R14361 */ + { 0x0000, 0x0000, 0x0000 }, /* R14362 */ + { 0x0000, 0x0000, 0x0000 }, /* R14363 */ + { 0x0000, 0x0000, 0x0000 }, /* R14364 */ + { 0x0000, 0x0000, 0x0000 }, /* R14365 */ + { 0x0000, 0x0000, 0x0000 }, /* R14366 */ + { 0x0000, 0x0000, 0x0000 }, /* R14367 */ + { 0x0000, 0x0000, 0x0000 }, /* R14368 */ + { 0x0000, 0x0000, 0x0000 }, /* R14369 */ + { 0x0000, 0x0000, 0x0000 }, /* R14370 */ + { 0x0000, 0x0000, 0x0000 }, /* R14371 */ + { 0x0000, 0x0000, 0x0000 }, /* R14372 */ + { 0x0000, 0x0000, 0x0000 }, /* R14373 */ + { 0x0000, 0x0000, 0x0000 }, /* R14374 */ + { 0x0000, 0x0000, 0x0000 }, /* R14375 */ + { 0x0000, 0x0000, 0x0000 }, /* R14376 */ + { 0x0000, 0x0000, 0x0000 }, /* R14377 */ + { 0x0000, 0x0000, 0x0000 }, /* R14378 */ + { 0x0000, 0x0000, 0x0000 }, /* R14379 */ + { 0x0000, 0x0000, 0x0000 }, /* R14380 */ + { 0x0000, 0x0000, 0x0000 }, /* R14381 */ + { 0x0000, 0x0000, 0x0000 }, /* R14382 */ + { 0x0000, 0x0000, 0x0000 }, /* R14383 */ + { 0x0000, 0x0000, 0x0000 }, /* R14384 */ + { 0x0000, 0x0000, 0x0000 }, /* R14385 */ + { 0x0000, 0x0000, 0x0000 }, /* R14386 */ + { 0x0000, 0x0000, 0x0000 }, /* R14387 */ + { 0x0000, 0x0000, 0x0000 }, /* R14388 */ + { 0x0000, 0x0000, 0x0000 }, /* R14389 */ + { 0x0000, 0x0000, 0x0000 }, /* R14390 */ + { 0x0000, 0x0000, 0x0000 }, /* R14391 */ + { 0x0000, 0x0000, 0x0000 }, /* R14392 */ + { 0x0000, 0x0000, 0x0000 }, /* R14393 */ + { 0x0000, 0x0000, 0x0000 }, /* R14394 */ + { 0x0000, 0x0000, 0x0000 }, /* R14395 */ + { 0x0000, 0x0000, 0x0000 }, /* R14396 */ + { 0x0000, 0x0000, 0x0000 }, /* R14397 */ + { 0x0000, 0x0000, 0x0000 }, /* R14398 */ + { 0x0000, 0x0000, 0x0000 }, /* R14399 */ + { 0x0000, 0x0000, 0x0000 }, /* R14400 */ + { 0x0000, 0x0000, 0x0000 }, /* R14401 */ + { 0x0000, 0x0000, 0x0000 }, /* R14402 */ + { 0x0000, 0x0000, 0x0000 }, /* R14403 */ + { 0x0000, 0x0000, 0x0000 }, /* R14404 */ + { 0x0000, 0x0000, 0x0000 }, /* R14405 */ + { 0x0000, 0x0000, 0x0000 }, /* R14406 */ + { 0x0000, 0x0000, 0x0000 }, /* R14407 */ + { 0x0000, 0x0000, 0x0000 }, /* R14408 */ + { 0x0000, 0x0000, 0x0000 }, /* R14409 */ + { 0x0000, 0x0000, 0x0000 }, /* R14410 */ + { 0x0000, 0x0000, 0x0000 }, /* R14411 */ + { 0x0000, 0x0000, 0x0000 }, /* R14412 */ + { 0x0000, 0x0000, 0x0000 }, /* R14413 */ + { 0x0000, 0x0000, 0x0000 }, /* R14414 */ + { 0x0000, 0x0000, 0x0000 }, /* R14415 */ + { 0x0000, 0x0000, 0x0000 }, /* R14416 */ + { 0x0000, 0x0000, 0x0000 }, /* R14417 */ + { 0x0000, 0x0000, 0x0000 }, /* R14418 */ + { 0x0000, 0x0000, 0x0000 }, /* R14419 */ + { 0x0000, 0x0000, 0x0000 }, /* R14420 */ + { 0x0000, 0x0000, 0x0000 }, /* R14421 */ + { 0x0000, 0x0000, 0x0000 }, /* R14422 */ + { 0x0000, 0x0000, 0x0000 }, /* R14423 */ + { 0x0000, 0x0000, 0x0000 }, /* R14424 */ + { 0x0000, 0x0000, 0x0000 }, /* R14425 */ + { 0x0000, 0x0000, 0x0000 }, /* R14426 */ + { 0x0000, 0x0000, 0x0000 }, /* R14427 */ + { 0x0000, 0x0000, 0x0000 }, /* R14428 */ + { 0x0000, 0x0000, 0x0000 }, /* R14429 */ + { 0x0000, 0x0000, 0x0000 }, /* R14430 */ + { 0x0000, 0x0000, 0x0000 }, /* R14431 */ + { 0x0000, 0x0000, 0x0000 }, /* R14432 */ + { 0x0000, 0x0000, 0x0000 }, /* R14433 */ + { 0x0000, 0x0000, 0x0000 }, /* R14434 */ + { 0x0000, 0x0000, 0x0000 }, /* R14435 */ + { 0x0000, 0x0000, 0x0000 }, /* R14436 */ + { 0x0000, 0x0000, 0x0000 }, /* R14437 */ + { 0x0000, 0x0000, 0x0000 }, /* R14438 */ + { 0x0000, 0x0000, 0x0000 }, /* R14439 */ + { 0x0000, 0x0000, 0x0000 }, /* R14440 */ + { 0x0000, 0x0000, 0x0000 }, /* R14441 */ + { 0x0000, 0x0000, 0x0000 }, /* R14442 */ + { 0x0000, 0x0000, 0x0000 }, /* R14443 */ + { 0x0000, 0x0000, 0x0000 }, /* R14444 */ + { 0x0000, 0x0000, 0x0000 }, /* R14445 */ + { 0x0000, 0x0000, 0x0000 }, /* R14446 */ + { 0x0000, 0x0000, 0x0000 }, /* R14447 */ + { 0x0000, 0x0000, 0x0000 }, /* R14448 */ + { 0x0000, 0x0000, 0x0000 }, /* R14449 */ + { 0x0000, 0x0000, 0x0000 }, /* R14450 */ + { 0x0000, 0x0000, 0x0000 }, /* R14451 */ + { 0x0000, 0x0000, 0x0000 }, /* R14452 */ + { 0x0000, 0x0000, 0x0000 }, /* R14453 */ + { 0x0000, 0x0000, 0x0000 }, /* R14454 */ + { 0x0000, 0x0000, 0x0000 }, /* R14455 */ + { 0x0000, 0x0000, 0x0000 }, /* R14456 */ + { 0x0000, 0x0000, 0x0000 }, /* R14457 */ + { 0x0000, 0x0000, 0x0000 }, /* R14458 */ + { 0x0000, 0x0000, 0x0000 }, /* R14459 */ + { 0x0000, 0x0000, 0x0000 }, /* R14460 */ + { 0x0000, 0x0000, 0x0000 }, /* R14461 */ + { 0x0000, 0x0000, 0x0000 }, /* R14462 */ + { 0x0000, 0x0000, 0x0000 }, /* R14463 */ + { 0x0000, 0x0000, 0x0000 }, /* R14464 */ + { 0x0000, 0x0000, 0x0000 }, /* R14465 */ + { 0x0000, 0x0000, 0x0000 }, /* R14466 */ + { 0x0000, 0x0000, 0x0000 }, /* R14467 */ + { 0x0000, 0x0000, 0x0000 }, /* R14468 */ + { 0x0000, 0x0000, 0x0000 }, /* R14469 */ + { 0x0000, 0x0000, 0x0000 }, /* R14470 */ + { 0x0000, 0x0000, 0x0000 }, /* R14471 */ + { 0x0000, 0x0000, 0x0000 }, /* R14472 */ + { 0x0000, 0x0000, 0x0000 }, /* R14473 */ + { 0x0000, 0x0000, 0x0000 }, /* R14474 */ + { 0x0000, 0x0000, 0x0000 }, /* R14475 */ + { 0x0000, 0x0000, 0x0000 }, /* R14476 */ + { 0x0000, 0x0000, 0x0000 }, /* R14477 */ + { 0x0000, 0x0000, 0x0000 }, /* R14478 */ + { 0x0000, 0x0000, 0x0000 }, /* R14479 */ + { 0x0000, 0x0000, 0x0000 }, /* R14480 */ + { 0x0000, 0x0000, 0x0000 }, /* R14481 */ + { 0x0000, 0x0000, 0x0000 }, /* R14482 */ + { 0x0000, 0x0000, 0x0000 }, /* R14483 */ + { 0x0000, 0x0000, 0x0000 }, /* R14484 */ + { 0x0000, 0x0000, 0x0000 }, /* R14485 */ + { 0x0000, 0x0000, 0x0000 }, /* R14486 */ + { 0x0000, 0x0000, 0x0000 }, /* R14487 */ + { 0x0000, 0x0000, 0x0000 }, /* R14488 */ + { 0x0000, 0x0000, 0x0000 }, /* R14489 */ + { 0x0000, 0x0000, 0x0000 }, /* R14490 */ + { 0x0000, 0x0000, 0x0000 }, /* R14491 */ + { 0x0000, 0x0000, 0x0000 }, /* R14492 */ + { 0x0000, 0x0000, 0x0000 }, /* R14493 */ + { 0x0000, 0x0000, 0x0000 }, /* R14494 */ + { 0x0000, 0x0000, 0x0000 }, /* R14495 */ + { 0x0000, 0x0000, 0x0000 }, /* R14496 */ + { 0x0000, 0x0000, 0x0000 }, /* R14497 */ + { 0x0000, 0x0000, 0x0000 }, /* R14498 */ + { 0x0000, 0x0000, 0x0000 }, /* R14499 */ + { 0x0000, 0x0000, 0x0000 }, /* R14500 */ + { 0x0000, 0x0000, 0x0000 }, /* R14501 */ + { 0x0000, 0x0000, 0x0000 }, /* R14502 */ + { 0x0000, 0x0000, 0x0000 }, /* R14503 */ + { 0x0000, 0x0000, 0x0000 }, /* R14504 */ + { 0x0000, 0x0000, 0x0000 }, /* R14505 */ + { 0x0000, 0x0000, 0x0000 }, /* R14506 */ + { 0x0000, 0x0000, 0x0000 }, /* R14507 */ + { 0x0000, 0x0000, 0x0000 }, /* R14508 */ + { 0x0000, 0x0000, 0x0000 }, /* R14509 */ + { 0x0000, 0x0000, 0x0000 }, /* R14510 */ + { 0x0000, 0x0000, 0x0000 }, /* R14511 */ + { 0x0000, 0x0000, 0x0000 }, /* R14512 */ + { 0x0000, 0x0000, 0x0000 }, /* R14513 */ + { 0x0000, 0x0000, 0x0000 }, /* R14514 */ + { 0x0000, 0x0000, 0x0000 }, /* R14515 */ + { 0x0000, 0x0000, 0x0000 }, /* R14516 */ + { 0x0000, 0x0000, 0x0000 }, /* R14517 */ + { 0x0000, 0x0000, 0x0000 }, /* R14518 */ + { 0x0000, 0x0000, 0x0000 }, /* R14519 */ + { 0x0000, 0x0000, 0x0000 }, /* R14520 */ + { 0x0000, 0x0000, 0x0000 }, /* R14521 */ + { 0x0000, 0x0000, 0x0000 }, /* R14522 */ + { 0x0000, 0x0000, 0x0000 }, /* R14523 */ + { 0x0000, 0x0000, 0x0000 }, /* R14524 */ + { 0x0000, 0x0000, 0x0000 }, /* R14525 */ + { 0x0000, 0x0000, 0x0000 }, /* R14526 */ + { 0x0000, 0x0000, 0x0000 }, /* R14527 */ + { 0x0000, 0x0000, 0x0000 }, /* R14528 */ + { 0x0000, 0x0000, 0x0000 }, /* R14529 */ + { 0x0000, 0x0000, 0x0000 }, /* R14530 */ + { 0x0000, 0x0000, 0x0000 }, /* R14531 */ + { 0x0000, 0x0000, 0x0000 }, /* R14532 */ + { 0x0000, 0x0000, 0x0000 }, /* R14533 */ + { 0x0000, 0x0000, 0x0000 }, /* R14534 */ + { 0x0000, 0x0000, 0x0000 }, /* R14535 */ + { 0x0000, 0x0000, 0x0000 }, /* R14536 */ + { 0x0000, 0x0000, 0x0000 }, /* R14537 */ + { 0x0000, 0x0000, 0x0000 }, /* R14538 */ + { 0x0000, 0x0000, 0x0000 }, /* R14539 */ + { 0x0000, 0x0000, 0x0000 }, /* R14540 */ + { 0x0000, 0x0000, 0x0000 }, /* R14541 */ + { 0x0000, 0x0000, 0x0000 }, /* R14542 */ + { 0x0000, 0x0000, 0x0000 }, /* R14543 */ + { 0x0000, 0x0000, 0x0000 }, /* R14544 */ + { 0x0000, 0x0000, 0x0000 }, /* R14545 */ + { 0x0000, 0x0000, 0x0000 }, /* R14546 */ + { 0x0000, 0x0000, 0x0000 }, /* R14547 */ + { 0x0000, 0x0000, 0x0000 }, /* R14548 */ + { 0x0000, 0x0000, 0x0000 }, /* R14549 */ + { 0x0000, 0x0000, 0x0000 }, /* R14550 */ + { 0x0000, 0x0000, 0x0000 }, /* R14551 */ + { 0x0000, 0x0000, 0x0000 }, /* R14552 */ + { 0x0000, 0x0000, 0x0000 }, /* R14553 */ + { 0x0000, 0x0000, 0x0000 }, /* R14554 */ + { 0x0000, 0x0000, 0x0000 }, /* R14555 */ + { 0x0000, 0x0000, 0x0000 }, /* R14556 */ + { 0x0000, 0x0000, 0x0000 }, /* R14557 */ + { 0x0000, 0x0000, 0x0000 }, /* R14558 */ + { 0x0000, 0x0000, 0x0000 }, /* R14559 */ + { 0x0000, 0x0000, 0x0000 }, /* R14560 */ + { 0x0000, 0x0000, 0x0000 }, /* R14561 */ + { 0x0000, 0x0000, 0x0000 }, /* R14562 */ + { 0x0000, 0x0000, 0x0000 }, /* R14563 */ + { 0x0000, 0x0000, 0x0000 }, /* R14564 */ + { 0x0000, 0x0000, 0x0000 }, /* R14565 */ + { 0x0000, 0x0000, 0x0000 }, /* R14566 */ + { 0x0000, 0x0000, 0x0000 }, /* R14567 */ + { 0x0000, 0x0000, 0x0000 }, /* R14568 */ + { 0x0000, 0x0000, 0x0000 }, /* R14569 */ + { 0x0000, 0x0000, 0x0000 }, /* R14570 */ + { 0x0000, 0x0000, 0x0000 }, /* R14571 */ + { 0x0000, 0x0000, 0x0000 }, /* R14572 */ + { 0x0000, 0x0000, 0x0000 }, /* R14573 */ + { 0x0000, 0x0000, 0x0000 }, /* R14574 */ + { 0x0000, 0x0000, 0x0000 }, /* R14575 */ + { 0x0000, 0x0000, 0x0000 }, /* R14576 */ + { 0x0000, 0x0000, 0x0000 }, /* R14577 */ + { 0x0000, 0x0000, 0x0000 }, /* R14578 */ + { 0x0000, 0x0000, 0x0000 }, /* R14579 */ + { 0x0000, 0x0000, 0x0000 }, /* R14580 */ + { 0x0000, 0x0000, 0x0000 }, /* R14581 */ + { 0x0000, 0x0000, 0x0000 }, /* R14582 */ + { 0x0000, 0x0000, 0x0000 }, /* R14583 */ + { 0x0000, 0x0000, 0x0000 }, /* R14584 */ + { 0x0000, 0x0000, 0x0000 }, /* R14585 */ + { 0x0000, 0x0000, 0x0000 }, /* R14586 */ + { 0x0000, 0x0000, 0x0000 }, /* R14587 */ + { 0x0000, 0x0000, 0x0000 }, /* R14588 */ + { 0x0000, 0x0000, 0x0000 }, /* R14589 */ + { 0x0000, 0x0000, 0x0000 }, /* R14590 */ + { 0x0000, 0x0000, 0x0000 }, /* R14591 */ + { 0x0000, 0x0000, 0x0000 }, /* R14592 */ + { 0x0000, 0x0000, 0x0000 }, /* R14593 */ + { 0x0000, 0x0000, 0x0000 }, /* R14594 */ + { 0x0000, 0x0000, 0x0000 }, /* R14595 */ + { 0x0000, 0x0000, 0x0000 }, /* R14596 */ + { 0x0000, 0x0000, 0x0000 }, /* R14597 */ + { 0x0000, 0x0000, 0x0000 }, /* R14598 */ + { 0x0000, 0x0000, 0x0000 }, /* R14599 */ + { 0x0000, 0x0000, 0x0000 }, /* R14600 */ + { 0x0000, 0x0000, 0x0000 }, /* R14601 */ + { 0x0000, 0x0000, 0x0000 }, /* R14602 */ + { 0x0000, 0x0000, 0x0000 }, /* R14603 */ + { 0x0000, 0x0000, 0x0000 }, /* R14604 */ + { 0x0000, 0x0000, 0x0000 }, /* R14605 */ + { 0x0000, 0x0000, 0x0000 }, /* R14606 */ + { 0x0000, 0x0000, 0x0000 }, /* R14607 */ + { 0x0000, 0x0000, 0x0000 }, /* R14608 */ + { 0x0000, 0x0000, 0x0000 }, /* R14609 */ + { 0x0000, 0x0000, 0x0000 }, /* R14610 */ + { 0x0000, 0x0000, 0x0000 }, /* R14611 */ + { 0x0000, 0x0000, 0x0000 }, /* R14612 */ + { 0x0000, 0x0000, 0x0000 }, /* R14613 */ + { 0x0000, 0x0000, 0x0000 }, /* R14614 */ + { 0x0000, 0x0000, 0x0000 }, /* R14615 */ + { 0x0000, 0x0000, 0x0000 }, /* R14616 */ + { 0x0000, 0x0000, 0x0000 }, /* R14617 */ + { 0x0000, 0x0000, 0x0000 }, /* R14618 */ + { 0x0000, 0x0000, 0x0000 }, /* R14619 */ + { 0x0000, 0x0000, 0x0000 }, /* R14620 */ + { 0x0000, 0x0000, 0x0000 }, /* R14621 */ + { 0x0000, 0x0000, 0x0000 }, /* R14622 */ + { 0x0000, 0x0000, 0x0000 }, /* R14623 */ + { 0x0000, 0x0000, 0x0000 }, /* R14624 */ + { 0x0000, 0x0000, 0x0000 }, /* R14625 */ + { 0x0000, 0x0000, 0x0000 }, /* R14626 */ + { 0x0000, 0x0000, 0x0000 }, /* R14627 */ + { 0x0000, 0x0000, 0x0000 }, /* R14628 */ + { 0x0000, 0x0000, 0x0000 }, /* R14629 */ + { 0x0000, 0x0000, 0x0000 }, /* R14630 */ + { 0x0000, 0x0000, 0x0000 }, /* R14631 */ + { 0x0000, 0x0000, 0x0000 }, /* R14632 */ + { 0x0000, 0x0000, 0x0000 }, /* R14633 */ + { 0x0000, 0x0000, 0x0000 }, /* R14634 */ + { 0x0000, 0x0000, 0x0000 }, /* R14635 */ + { 0x0000, 0x0000, 0x0000 }, /* R14636 */ + { 0x0000, 0x0000, 0x0000 }, /* R14637 */ + { 0x0000, 0x0000, 0x0000 }, /* R14638 */ + { 0x0000, 0x0000, 0x0000 }, /* R14639 */ + { 0x0000, 0x0000, 0x0000 }, /* R14640 */ + { 0x0000, 0x0000, 0x0000 }, /* R14641 */ + { 0x0000, 0x0000, 0x0000 }, /* R14642 */ + { 0x0000, 0x0000, 0x0000 }, /* R14643 */ + { 0x0000, 0x0000, 0x0000 }, /* R14644 */ + { 0x0000, 0x0000, 0x0000 }, /* R14645 */ + { 0x0000, 0x0000, 0x0000 }, /* R14646 */ + { 0x0000, 0x0000, 0x0000 }, /* R14647 */ + { 0x0000, 0x0000, 0x0000 }, /* R14648 */ + { 0x0000, 0x0000, 0x0000 }, /* R14649 */ + { 0x0000, 0x0000, 0x0000 }, /* R14650 */ + { 0x0000, 0x0000, 0x0000 }, /* R14651 */ + { 0x0000, 0x0000, 0x0000 }, /* R14652 */ + { 0x0000, 0x0000, 0x0000 }, /* R14653 */ + { 0x0000, 0x0000, 0x0000 }, /* R14654 */ + { 0x0000, 0x0000, 0x0000 }, /* R14655 */ + { 0x0000, 0x0000, 0x0000 }, /* R14656 */ + { 0x0000, 0x0000, 0x0000 }, /* R14657 */ + { 0x0000, 0x0000, 0x0000 }, /* R14658 */ + { 0x0000, 0x0000, 0x0000 }, /* R14659 */ + { 0x0000, 0x0000, 0x0000 }, /* R14660 */ + { 0x0000, 0x0000, 0x0000 }, /* R14661 */ + { 0x0000, 0x0000, 0x0000 }, /* R14662 */ + { 0x0000, 0x0000, 0x0000 }, /* R14663 */ + { 0x0000, 0x0000, 0x0000 }, /* R14664 */ + { 0x0000, 0x0000, 0x0000 }, /* R14665 */ + { 0x0000, 0x0000, 0x0000 }, /* R14666 */ + { 0x0000, 0x0000, 0x0000 }, /* R14667 */ + { 0x0000, 0x0000, 0x0000 }, /* R14668 */ + { 0x0000, 0x0000, 0x0000 }, /* R14669 */ + { 0x0000, 0x0000, 0x0000 }, /* R14670 */ + { 0x0000, 0x0000, 0x0000 }, /* R14671 */ + { 0x0000, 0x0000, 0x0000 }, /* R14672 */ + { 0x0000, 0x0000, 0x0000 }, /* R14673 */ + { 0x0000, 0x0000, 0x0000 }, /* R14674 */ + { 0x0000, 0x0000, 0x0000 }, /* R14675 */ + { 0x0000, 0x0000, 0x0000 }, /* R14676 */ + { 0x0000, 0x0000, 0x0000 }, /* R14677 */ + { 0x0000, 0x0000, 0x0000 }, /* R14678 */ + { 0x0000, 0x0000, 0x0000 }, /* R14679 */ + { 0x0000, 0x0000, 0x0000 }, /* R14680 */ + { 0x0000, 0x0000, 0x0000 }, /* R14681 */ + { 0x0000, 0x0000, 0x0000 }, /* R14682 */ + { 0x0000, 0x0000, 0x0000 }, /* R14683 */ + { 0x0000, 0x0000, 0x0000 }, /* R14684 */ + { 0x0000, 0x0000, 0x0000 }, /* R14685 */ + { 0x0000, 0x0000, 0x0000 }, /* R14686 */ + { 0x0000, 0x0000, 0x0000 }, /* R14687 */ + { 0x0000, 0x0000, 0x0000 }, /* R14688 */ + { 0x0000, 0x0000, 0x0000 }, /* R14689 */ + { 0x0000, 0x0000, 0x0000 }, /* R14690 */ + { 0x0000, 0x0000, 0x0000 }, /* R14691 */ + { 0x0000, 0x0000, 0x0000 }, /* R14692 */ + { 0x0000, 0x0000, 0x0000 }, /* R14693 */ + { 0x0000, 0x0000, 0x0000 }, /* R14694 */ + { 0x0000, 0x0000, 0x0000 }, /* R14695 */ + { 0x0000, 0x0000, 0x0000 }, /* R14696 */ + { 0x0000, 0x0000, 0x0000 }, /* R14697 */ + { 0x0000, 0x0000, 0x0000 }, /* R14698 */ + { 0x0000, 0x0000, 0x0000 }, /* R14699 */ + { 0x0000, 0x0000, 0x0000 }, /* R14700 */ + { 0x0000, 0x0000, 0x0000 }, /* R14701 */ + { 0x0000, 0x0000, 0x0000 }, /* R14702 */ + { 0x0000, 0x0000, 0x0000 }, /* R14703 */ + { 0x0000, 0x0000, 0x0000 }, /* R14704 */ + { 0x0000, 0x0000, 0x0000 }, /* R14705 */ + { 0x0000, 0x0000, 0x0000 }, /* R14706 */ + { 0x0000, 0x0000, 0x0000 }, /* R14707 */ + { 0x0000, 0x0000, 0x0000 }, /* R14708 */ + { 0x0000, 0x0000, 0x0000 }, /* R14709 */ + { 0x0000, 0x0000, 0x0000 }, /* R14710 */ + { 0x0000, 0x0000, 0x0000 }, /* R14711 */ + { 0x0000, 0x0000, 0x0000 }, /* R14712 */ + { 0x0000, 0x0000, 0x0000 }, /* R14713 */ + { 0x0000, 0x0000, 0x0000 }, /* R14714 */ + { 0x0000, 0x0000, 0x0000 }, /* R14715 */ + { 0x0000, 0x0000, 0x0000 }, /* R14716 */ + { 0x0000, 0x0000, 0x0000 }, /* R14717 */ + { 0x0000, 0x0000, 0x0000 }, /* R14718 */ + { 0x0000, 0x0000, 0x0000 }, /* R14719 */ + { 0x0000, 0x0000, 0x0000 }, /* R14720 */ + { 0x0000, 0x0000, 0x0000 }, /* R14721 */ + { 0x0000, 0x0000, 0x0000 }, /* R14722 */ + { 0x0000, 0x0000, 0x0000 }, /* R14723 */ + { 0x0000, 0x0000, 0x0000 }, /* R14724 */ + { 0x0000, 0x0000, 0x0000 }, /* R14725 */ + { 0x0000, 0x0000, 0x0000 }, /* R14726 */ + { 0x0000, 0x0000, 0x0000 }, /* R14727 */ + { 0x0000, 0x0000, 0x0000 }, /* R14728 */ + { 0x0000, 0x0000, 0x0000 }, /* R14729 */ + { 0x0000, 0x0000, 0x0000 }, /* R14730 */ + { 0x0000, 0x0000, 0x0000 }, /* R14731 */ + { 0x0000, 0x0000, 0x0000 }, /* R14732 */ + { 0x0000, 0x0000, 0x0000 }, /* R14733 */ + { 0x0000, 0x0000, 0x0000 }, /* R14734 */ + { 0x0000, 0x0000, 0x0000 }, /* R14735 */ + { 0x0000, 0x0000, 0x0000 }, /* R14736 */ + { 0x0000, 0x0000, 0x0000 }, /* R14737 */ + { 0x0000, 0x0000, 0x0000 }, /* R14738 */ + { 0x0000, 0x0000, 0x0000 }, /* R14739 */ + { 0x0000, 0x0000, 0x0000 }, /* R14740 */ + { 0x0000, 0x0000, 0x0000 }, /* R14741 */ + { 0x0000, 0x0000, 0x0000 }, /* R14742 */ + { 0x0000, 0x0000, 0x0000 }, /* R14743 */ + { 0x0000, 0x0000, 0x0000 }, /* R14744 */ + { 0x0000, 0x0000, 0x0000 }, /* R14745 */ + { 0x0000, 0x0000, 0x0000 }, /* R14746 */ + { 0x0000, 0x0000, 0x0000 }, /* R14747 */ + { 0x0000, 0x0000, 0x0000 }, /* R14748 */ + { 0x0000, 0x0000, 0x0000 }, /* R14749 */ + { 0x0000, 0x0000, 0x0000 }, /* R14750 */ + { 0x0000, 0x0000, 0x0000 }, /* R14751 */ + { 0x0000, 0x0000, 0x0000 }, /* R14752 */ + { 0x0000, 0x0000, 0x0000 }, /* R14753 */ + { 0x0000, 0x0000, 0x0000 }, /* R14754 */ + { 0x0000, 0x0000, 0x0000 }, /* R14755 */ + { 0x0000, 0x0000, 0x0000 }, /* R14756 */ + { 0x0000, 0x0000, 0x0000 }, /* R14757 */ + { 0x0000, 0x0000, 0x0000 }, /* R14758 */ + { 0x0000, 0x0000, 0x0000 }, /* R14759 */ + { 0x0000, 0x0000, 0x0000 }, /* R14760 */ + { 0x0000, 0x0000, 0x0000 }, /* R14761 */ + { 0x0000, 0x0000, 0x0000 }, /* R14762 */ + { 0x0000, 0x0000, 0x0000 }, /* R14763 */ + { 0x0000, 0x0000, 0x0000 }, /* R14764 */ + { 0x0000, 0x0000, 0x0000 }, /* R14765 */ + { 0x0000, 0x0000, 0x0000 }, /* R14766 */ + { 0x0000, 0x0000, 0x0000 }, /* R14767 */ + { 0x0000, 0x0000, 0x0000 }, /* R14768 */ + { 0x0000, 0x0000, 0x0000 }, /* R14769 */ + { 0x0000, 0x0000, 0x0000 }, /* R14770 */ + { 0x0000, 0x0000, 0x0000 }, /* R14771 */ + { 0x0000, 0x0000, 0x0000 }, /* R14772 */ + { 0x0000, 0x0000, 0x0000 }, /* R14773 */ + { 0x0000, 0x0000, 0x0000 }, /* R14774 */ + { 0x0000, 0x0000, 0x0000 }, /* R14775 */ + { 0x0000, 0x0000, 0x0000 }, /* R14776 */ + { 0x0000, 0x0000, 0x0000 }, /* R14777 */ + { 0x0000, 0x0000, 0x0000 }, /* R14778 */ + { 0x0000, 0x0000, 0x0000 }, /* R14779 */ + { 0x0000, 0x0000, 0x0000 }, /* R14780 */ + { 0x0000, 0x0000, 0x0000 }, /* R14781 */ + { 0x0000, 0x0000, 0x0000 }, /* R14782 */ + { 0x0000, 0x0000, 0x0000 }, /* R14783 */ + { 0x0000, 0x0000, 0x0000 }, /* R14784 */ + { 0x0000, 0x0000, 0x0000 }, /* R14785 */ + { 0x0000, 0x0000, 0x0000 }, /* R14786 */ + { 0x0000, 0x0000, 0x0000 }, /* R14787 */ + { 0x0000, 0x0000, 0x0000 }, /* R14788 */ + { 0x0000, 0x0000, 0x0000 }, /* R14789 */ + { 0x0000, 0x0000, 0x0000 }, /* R14790 */ + { 0x0000, 0x0000, 0x0000 }, /* R14791 */ + { 0x0000, 0x0000, 0x0000 }, /* R14792 */ + { 0x0000, 0x0000, 0x0000 }, /* R14793 */ + { 0x0000, 0x0000, 0x0000 }, /* R14794 */ + { 0x0000, 0x0000, 0x0000 }, /* R14795 */ + { 0x0000, 0x0000, 0x0000 }, /* R14796 */ + { 0x0000, 0x0000, 0x0000 }, /* R14797 */ + { 0x0000, 0x0000, 0x0000 }, /* R14798 */ + { 0x0000, 0x0000, 0x0000 }, /* R14799 */ + { 0x0000, 0x0000, 0x0000 }, /* R14800 */ + { 0x0000, 0x0000, 0x0000 }, /* R14801 */ + { 0x0000, 0x0000, 0x0000 }, /* R14802 */ + { 0x0000, 0x0000, 0x0000 }, /* R14803 */ + { 0x0000, 0x0000, 0x0000 }, /* R14804 */ + { 0x0000, 0x0000, 0x0000 }, /* R14805 */ + { 0x0000, 0x0000, 0x0000 }, /* R14806 */ + { 0x0000, 0x0000, 0x0000 }, /* R14807 */ + { 0x0000, 0x0000, 0x0000 }, /* R14808 */ + { 0x0000, 0x0000, 0x0000 }, /* R14809 */ + { 0x0000, 0x0000, 0x0000 }, /* R14810 */ + { 0x0000, 0x0000, 0x0000 }, /* R14811 */ + { 0x0000, 0x0000, 0x0000 }, /* R14812 */ + { 0x0000, 0x0000, 0x0000 }, /* R14813 */ + { 0x0000, 0x0000, 0x0000 }, /* R14814 */ + { 0x0000, 0x0000, 0x0000 }, /* R14815 */ + { 0x0000, 0x0000, 0x0000 }, /* R14816 */ + { 0x0000, 0x0000, 0x0000 }, /* R14817 */ + { 0x0000, 0x0000, 0x0000 }, /* R14818 */ + { 0x0000, 0x0000, 0x0000 }, /* R14819 */ + { 0x0000, 0x0000, 0x0000 }, /* R14820 */ + { 0x0000, 0x0000, 0x0000 }, /* R14821 */ + { 0x0000, 0x0000, 0x0000 }, /* R14822 */ + { 0x0000, 0x0000, 0x0000 }, /* R14823 */ + { 0x0000, 0x0000, 0x0000 }, /* R14824 */ + { 0x0000, 0x0000, 0x0000 }, /* R14825 */ + { 0x0000, 0x0000, 0x0000 }, /* R14826 */ + { 0x0000, 0x0000, 0x0000 }, /* R14827 */ + { 0x0000, 0x0000, 0x0000 }, /* R14828 */ + { 0x0000, 0x0000, 0x0000 }, /* R14829 */ + { 0x0000, 0x0000, 0x0000 }, /* R14830 */ + { 0x0000, 0x0000, 0x0000 }, /* R14831 */ + { 0x0000, 0x0000, 0x0000 }, /* R14832 */ + { 0x0000, 0x0000, 0x0000 }, /* R14833 */ + { 0x0000, 0x0000, 0x0000 }, /* R14834 */ + { 0x0000, 0x0000, 0x0000 }, /* R14835 */ + { 0x0000, 0x0000, 0x0000 }, /* R14836 */ + { 0x0000, 0x0000, 0x0000 }, /* R14837 */ + { 0x0000, 0x0000, 0x0000 }, /* R14838 */ + { 0x0000, 0x0000, 0x0000 }, /* R14839 */ + { 0x0000, 0x0000, 0x0000 }, /* R14840 */ + { 0x0000, 0x0000, 0x0000 }, /* R14841 */ + { 0x0000, 0x0000, 0x0000 }, /* R14842 */ + { 0x0000, 0x0000, 0x0000 }, /* R14843 */ + { 0x0000, 0x0000, 0x0000 }, /* R14844 */ + { 0x0000, 0x0000, 0x0000 }, /* R14845 */ + { 0x0000, 0x0000, 0x0000 }, /* R14846 */ + { 0x0000, 0x0000, 0x0000 }, /* R14847 */ + { 0x0000, 0x0000, 0x0000 }, /* R14848 */ + { 0x0000, 0x0000, 0x0000 }, /* R14849 */ + { 0x0000, 0x0000, 0x0000 }, /* R14850 */ + { 0x0000, 0x0000, 0x0000 }, /* R14851 */ + { 0x0000, 0x0000, 0x0000 }, /* R14852 */ + { 0x0000, 0x0000, 0x0000 }, /* R14853 */ + { 0x0000, 0x0000, 0x0000 }, /* R14854 */ + { 0x0000, 0x0000, 0x0000 }, /* R14855 */ + { 0x0000, 0x0000, 0x0000 }, /* R14856 */ + { 0x0000, 0x0000, 0x0000 }, /* R14857 */ + { 0x0000, 0x0000, 0x0000 }, /* R14858 */ + { 0x0000, 0x0000, 0x0000 }, /* R14859 */ + { 0x0000, 0x0000, 0x0000 }, /* R14860 */ + { 0x0000, 0x0000, 0x0000 }, /* R14861 */ + { 0x0000, 0x0000, 0x0000 }, /* R14862 */ + { 0x0000, 0x0000, 0x0000 }, /* R14863 */ + { 0x0000, 0x0000, 0x0000 }, /* R14864 */ + { 0x0000, 0x0000, 0x0000 }, /* R14865 */ + { 0x0000, 0x0000, 0x0000 }, /* R14866 */ + { 0x0000, 0x0000, 0x0000 }, /* R14867 */ + { 0x0000, 0x0000, 0x0000 }, /* R14868 */ + { 0x0000, 0x0000, 0x0000 }, /* R14869 */ + { 0x0000, 0x0000, 0x0000 }, /* R14870 */ + { 0x0000, 0x0000, 0x0000 }, /* R14871 */ + { 0x0000, 0x0000, 0x0000 }, /* R14872 */ + { 0x0000, 0x0000, 0x0000 }, /* R14873 */ + { 0x0000, 0x0000, 0x0000 }, /* R14874 */ + { 0x0000, 0x0000, 0x0000 }, /* R14875 */ + { 0x0000, 0x0000, 0x0000 }, /* R14876 */ + { 0x0000, 0x0000, 0x0000 }, /* R14877 */ + { 0x0000, 0x0000, 0x0000 }, /* R14878 */ + { 0x0000, 0x0000, 0x0000 }, /* R14879 */ + { 0x0000, 0x0000, 0x0000 }, /* R14880 */ + { 0x0000, 0x0000, 0x0000 }, /* R14881 */ + { 0x0000, 0x0000, 0x0000 }, /* R14882 */ + { 0x0000, 0x0000, 0x0000 }, /* R14883 */ + { 0x0000, 0x0000, 0x0000 }, /* R14884 */ + { 0x0000, 0x0000, 0x0000 }, /* R14885 */ + { 0x0000, 0x0000, 0x0000 }, /* R14886 */ + { 0x0000, 0x0000, 0x0000 }, /* R14887 */ + { 0x0000, 0x0000, 0x0000 }, /* R14888 */ + { 0x0000, 0x0000, 0x0000 }, /* R14889 */ + { 0x0000, 0x0000, 0x0000 }, /* R14890 */ + { 0x0000, 0x0000, 0x0000 }, /* R14891 */ + { 0x0000, 0x0000, 0x0000 }, /* R14892 */ + { 0x0000, 0x0000, 0x0000 }, /* R14893 */ + { 0x0000, 0x0000, 0x0000 }, /* R14894 */ + { 0x0000, 0x0000, 0x0000 }, /* R14895 */ + { 0x0000, 0x0000, 0x0000 }, /* R14896 */ + { 0x0000, 0x0000, 0x0000 }, /* R14897 */ + { 0x0000, 0x0000, 0x0000 }, /* R14898 */ + { 0x0000, 0x0000, 0x0000 }, /* R14899 */ + { 0x0000, 0x0000, 0x0000 }, /* R14900 */ + { 0x0000, 0x0000, 0x0000 }, /* R14901 */ + { 0x0000, 0x0000, 0x0000 }, /* R14902 */ + { 0x0000, 0x0000, 0x0000 }, /* R14903 */ + { 0x0000, 0x0000, 0x0000 }, /* R14904 */ + { 0x0000, 0x0000, 0x0000 }, /* R14905 */ + { 0x0000, 0x0000, 0x0000 }, /* R14906 */ + { 0x0000, 0x0000, 0x0000 }, /* R14907 */ + { 0x0000, 0x0000, 0x0000 }, /* R14908 */ + { 0x0000, 0x0000, 0x0000 }, /* R14909 */ + { 0x0000, 0x0000, 0x0000 }, /* R14910 */ + { 0x0000, 0x0000, 0x0000 }, /* R14911 */ + { 0x0000, 0x0000, 0x0000 }, /* R14912 */ + { 0x0000, 0x0000, 0x0000 }, /* R14913 */ + { 0x0000, 0x0000, 0x0000 }, /* R14914 */ + { 0x0000, 0x0000, 0x0000 }, /* R14915 */ + { 0x0000, 0x0000, 0x0000 }, /* R14916 */ + { 0x0000, 0x0000, 0x0000 }, /* R14917 */ + { 0x0000, 0x0000, 0x0000 }, /* R14918 */ + { 0x0000, 0x0000, 0x0000 }, /* R14919 */ + { 0x0000, 0x0000, 0x0000 }, /* R14920 */ + { 0x0000, 0x0000, 0x0000 }, /* R14921 */ + { 0x0000, 0x0000, 0x0000 }, /* R14922 */ + { 0x0000, 0x0000, 0x0000 }, /* R14923 */ + { 0x0000, 0x0000, 0x0000 }, /* R14924 */ + { 0x0000, 0x0000, 0x0000 }, /* R14925 */ + { 0x0000, 0x0000, 0x0000 }, /* R14926 */ + { 0x0000, 0x0000, 0x0000 }, /* R14927 */ + { 0x0000, 0x0000, 0x0000 }, /* R14928 */ + { 0x0000, 0x0000, 0x0000 }, /* R14929 */ + { 0x0000, 0x0000, 0x0000 }, /* R14930 */ + { 0x0000, 0x0000, 0x0000 }, /* R14931 */ + { 0x0000, 0x0000, 0x0000 }, /* R14932 */ + { 0x0000, 0x0000, 0x0000 }, /* R14933 */ + { 0x0000, 0x0000, 0x0000 }, /* R14934 */ + { 0x0000, 0x0000, 0x0000 }, /* R14935 */ + { 0x0000, 0x0000, 0x0000 }, /* R14936 */ + { 0x0000, 0x0000, 0x0000 }, /* R14937 */ + { 0x0000, 0x0000, 0x0000 }, /* R14938 */ + { 0x0000, 0x0000, 0x0000 }, /* R14939 */ + { 0x0000, 0x0000, 0x0000 }, /* R14940 */ + { 0x0000, 0x0000, 0x0000 }, /* R14941 */ + { 0x0000, 0x0000, 0x0000 }, /* R14942 */ + { 0x0000, 0x0000, 0x0000 }, /* R14943 */ + { 0x0000, 0x0000, 0x0000 }, /* R14944 */ + { 0x0000, 0x0000, 0x0000 }, /* R14945 */ + { 0x0000, 0x0000, 0x0000 }, /* R14946 */ + { 0x0000, 0x0000, 0x0000 }, /* R14947 */ + { 0x0000, 0x0000, 0x0000 }, /* R14948 */ + { 0x0000, 0x0000, 0x0000 }, /* R14949 */ + { 0x0000, 0x0000, 0x0000 }, /* R14950 */ + { 0x0000, 0x0000, 0x0000 }, /* R14951 */ + { 0x0000, 0x0000, 0x0000 }, /* R14952 */ + { 0x0000, 0x0000, 0x0000 }, /* R14953 */ + { 0x0000, 0x0000, 0x0000 }, /* R14954 */ + { 0x0000, 0x0000, 0x0000 }, /* R14955 */ + { 0x0000, 0x0000, 0x0000 }, /* R14956 */ + { 0x0000, 0x0000, 0x0000 }, /* R14957 */ + { 0x0000, 0x0000, 0x0000 }, /* R14958 */ + { 0x0000, 0x0000, 0x0000 }, /* R14959 */ + { 0x0000, 0x0000, 0x0000 }, /* R14960 */ + { 0x0000, 0x0000, 0x0000 }, /* R14961 */ + { 0x0000, 0x0000, 0x0000 }, /* R14962 */ + { 0x0000, 0x0000, 0x0000 }, /* R14963 */ + { 0x0000, 0x0000, 0x0000 }, /* R14964 */ + { 0x0000, 0x0000, 0x0000 }, /* R14965 */ + { 0x0000, 0x0000, 0x0000 }, /* R14966 */ + { 0x0000, 0x0000, 0x0000 }, /* R14967 */ + { 0x0000, 0x0000, 0x0000 }, /* R14968 */ + { 0x0000, 0x0000, 0x0000 }, /* R14969 */ + { 0x0000, 0x0000, 0x0000 }, /* R14970 */ + { 0x0000, 0x0000, 0x0000 }, /* R14971 */ + { 0x0000, 0x0000, 0x0000 }, /* R14972 */ + { 0x0000, 0x0000, 0x0000 }, /* R14973 */ + { 0x0000, 0x0000, 0x0000 }, /* R14974 */ + { 0x0000, 0x0000, 0x0000 }, /* R14975 */ + { 0x0000, 0x0000, 0x0000 }, /* R14976 */ + { 0x0000, 0x0000, 0x0000 }, /* R14977 */ + { 0x0000, 0x0000, 0x0000 }, /* R14978 */ + { 0x0000, 0x0000, 0x0000 }, /* R14979 */ + { 0x0000, 0x0000, 0x0000 }, /* R14980 */ + { 0x0000, 0x0000, 0x0000 }, /* R14981 */ + { 0x0000, 0x0000, 0x0000 }, /* R14982 */ + { 0x0000, 0x0000, 0x0000 }, /* R14983 */ + { 0x0000, 0x0000, 0x0000 }, /* R14984 */ + { 0x0000, 0x0000, 0x0000 }, /* R14985 */ + { 0x0000, 0x0000, 0x0000 }, /* R14986 */ + { 0x0000, 0x0000, 0x0000 }, /* R14987 */ + { 0x0000, 0x0000, 0x0000 }, /* R14988 */ + { 0x0000, 0x0000, 0x0000 }, /* R14989 */ + { 0x0000, 0x0000, 0x0000 }, /* R14990 */ + { 0x0000, 0x0000, 0x0000 }, /* R14991 */ + { 0x0000, 0x0000, 0x0000 }, /* R14992 */ + { 0x0000, 0x0000, 0x0000 }, /* R14993 */ + { 0x0000, 0x0000, 0x0000 }, /* R14994 */ + { 0x0000, 0x0000, 0x0000 }, /* R14995 */ + { 0x0000, 0x0000, 0x0000 }, /* R14996 */ + { 0x0000, 0x0000, 0x0000 }, /* R14997 */ + { 0x0000, 0x0000, 0x0000 }, /* R14998 */ + { 0x0000, 0x0000, 0x0000 }, /* R14999 */ + { 0x0000, 0x0000, 0x0000 }, /* R15000 */ + { 0x0000, 0x0000, 0x0000 }, /* R15001 */ + { 0x0000, 0x0000, 0x0000 }, /* R15002 */ + { 0x0000, 0x0000, 0x0000 }, /* R15003 */ + { 0x0000, 0x0000, 0x0000 }, /* R15004 */ + { 0x0000, 0x0000, 0x0000 }, /* R15005 */ + { 0x0000, 0x0000, 0x0000 }, /* R15006 */ + { 0x0000, 0x0000, 0x0000 }, /* R15007 */ + { 0x0000, 0x0000, 0x0000 }, /* R15008 */ + { 0x0000, 0x0000, 0x0000 }, /* R15009 */ + { 0x0000, 0x0000, 0x0000 }, /* R15010 */ + { 0x0000, 0x0000, 0x0000 }, /* R15011 */ + { 0x0000, 0x0000, 0x0000 }, /* R15012 */ + { 0x0000, 0x0000, 0x0000 }, /* R15013 */ + { 0x0000, 0x0000, 0x0000 }, /* R15014 */ + { 0x0000, 0x0000, 0x0000 }, /* R15015 */ + { 0x0000, 0x0000, 0x0000 }, /* R15016 */ + { 0x0000, 0x0000, 0x0000 }, /* R15017 */ + { 0x0000, 0x0000, 0x0000 }, /* R15018 */ + { 0x0000, 0x0000, 0x0000 }, /* R15019 */ + { 0x0000, 0x0000, 0x0000 }, /* R15020 */ + { 0x0000, 0x0000, 0x0000 }, /* R15021 */ + { 0x0000, 0x0000, 0x0000 }, /* R15022 */ + { 0x0000, 0x0000, 0x0000 }, /* R15023 */ + { 0x0000, 0x0000, 0x0000 }, /* R15024 */ + { 0x0000, 0x0000, 0x0000 }, /* R15025 */ + { 0x0000, 0x0000, 0x0000 }, /* R15026 */ + { 0x0000, 0x0000, 0x0000 }, /* R15027 */ + { 0x0000, 0x0000, 0x0000 }, /* R15028 */ + { 0x0000, 0x0000, 0x0000 }, /* R15029 */ + { 0x0000, 0x0000, 0x0000 }, /* R15030 */ + { 0x0000, 0x0000, 0x0000 }, /* R15031 */ + { 0x0000, 0x0000, 0x0000 }, /* R15032 */ + { 0x0000, 0x0000, 0x0000 }, /* R15033 */ + { 0x0000, 0x0000, 0x0000 }, /* R15034 */ + { 0x0000, 0x0000, 0x0000 }, /* R15035 */ + { 0x0000, 0x0000, 0x0000 }, /* R15036 */ + { 0x0000, 0x0000, 0x0000 }, /* R15037 */ + { 0x0000, 0x0000, 0x0000 }, /* R15038 */ + { 0x0000, 0x0000, 0x0000 }, /* R15039 */ + { 0x0000, 0x0000, 0x0000 }, /* R15040 */ + { 0x0000, 0x0000, 0x0000 }, /* R15041 */ + { 0x0000, 0x0000, 0x0000 }, /* R15042 */ + { 0x0000, 0x0000, 0x0000 }, /* R15043 */ + { 0x0000, 0x0000, 0x0000 }, /* R15044 */ + { 0x0000, 0x0000, 0x0000 }, /* R15045 */ + { 0x0000, 0x0000, 0x0000 }, /* R15046 */ + { 0x0000, 0x0000, 0x0000 }, /* R15047 */ + { 0x0000, 0x0000, 0x0000 }, /* R15048 */ + { 0x0000, 0x0000, 0x0000 }, /* R15049 */ + { 0x0000, 0x0000, 0x0000 }, /* R15050 */ + { 0x0000, 0x0000, 0x0000 }, /* R15051 */ + { 0x0000, 0x0000, 0x0000 }, /* R15052 */ + { 0x0000, 0x0000, 0x0000 }, /* R15053 */ + { 0x0000, 0x0000, 0x0000 }, /* R15054 */ + { 0x0000, 0x0000, 0x0000 }, /* R15055 */ + { 0x0000, 0x0000, 0x0000 }, /* R15056 */ + { 0x0000, 0x0000, 0x0000 }, /* R15057 */ + { 0x0000, 0x0000, 0x0000 }, /* R15058 */ + { 0x0000, 0x0000, 0x0000 }, /* R15059 */ + { 0x0000, 0x0000, 0x0000 }, /* R15060 */ + { 0x0000, 0x0000, 0x0000 }, /* R15061 */ + { 0x0000, 0x0000, 0x0000 }, /* R15062 */ + { 0x0000, 0x0000, 0x0000 }, /* R15063 */ + { 0x0000, 0x0000, 0x0000 }, /* R15064 */ + { 0x0000, 0x0000, 0x0000 }, /* R15065 */ + { 0x0000, 0x0000, 0x0000 }, /* R15066 */ + { 0x0000, 0x0000, 0x0000 }, /* R15067 */ + { 0x0000, 0x0000, 0x0000 }, /* R15068 */ + { 0x0000, 0x0000, 0x0000 }, /* R15069 */ + { 0x0000, 0x0000, 0x0000 }, /* R15070 */ + { 0x0000, 0x0000, 0x0000 }, /* R15071 */ + { 0x0000, 0x0000, 0x0000 }, /* R15072 */ + { 0x0000, 0x0000, 0x0000 }, /* R15073 */ + { 0x0000, 0x0000, 0x0000 }, /* R15074 */ + { 0x0000, 0x0000, 0x0000 }, /* R15075 */ + { 0x0000, 0x0000, 0x0000 }, /* R15076 */ + { 0x0000, 0x0000, 0x0000 }, /* R15077 */ + { 0x0000, 0x0000, 0x0000 }, /* R15078 */ + { 0x0000, 0x0000, 0x0000 }, /* R15079 */ + { 0x0000, 0x0000, 0x0000 }, /* R15080 */ + { 0x0000, 0x0000, 0x0000 }, /* R15081 */ + { 0x0000, 0x0000, 0x0000 }, /* R15082 */ + { 0x0000, 0x0000, 0x0000 }, /* R15083 */ + { 0x0000, 0x0000, 0x0000 }, /* R15084 */ + { 0x0000, 0x0000, 0x0000 }, /* R15085 */ + { 0x0000, 0x0000, 0x0000 }, /* R15086 */ + { 0x0000, 0x0000, 0x0000 }, /* R15087 */ + { 0x0000, 0x0000, 0x0000 }, /* R15088 */ + { 0x0000, 0x0000, 0x0000 }, /* R15089 */ + { 0x0000, 0x0000, 0x0000 }, /* R15090 */ + { 0x0000, 0x0000, 0x0000 }, /* R15091 */ + { 0x0000, 0x0000, 0x0000 }, /* R15092 */ + { 0x0000, 0x0000, 0x0000 }, /* R15093 */ + { 0x0000, 0x0000, 0x0000 }, /* R15094 */ + { 0x0000, 0x0000, 0x0000 }, /* R15095 */ + { 0x0000, 0x0000, 0x0000 }, /* R15096 */ + { 0x0000, 0x0000, 0x0000 }, /* R15097 */ + { 0x0000, 0x0000, 0x0000 }, /* R15098 */ + { 0x0000, 0x0000, 0x0000 }, /* R15099 */ + { 0x0000, 0x0000, 0x0000 }, /* R15100 */ + { 0x0000, 0x0000, 0x0000 }, /* R15101 */ + { 0x0000, 0x0000, 0x0000 }, /* R15102 */ + { 0x0000, 0x0000, 0x0000 }, /* R15103 */ + { 0x0000, 0x0000, 0x0000 }, /* R15104 */ + { 0x0000, 0x0000, 0x0000 }, /* R15105 */ + { 0x0000, 0x0000, 0x0000 }, /* R15106 */ + { 0x0000, 0x0000, 0x0000 }, /* R15107 */ + { 0x0000, 0x0000, 0x0000 }, /* R15108 */ + { 0x0000, 0x0000, 0x0000 }, /* R15109 */ + { 0x0000, 0x0000, 0x0000 }, /* R15110 */ + { 0x0000, 0x0000, 0x0000 }, /* R15111 */ + { 0x0000, 0x0000, 0x0000 }, /* R15112 */ + { 0x0000, 0x0000, 0x0000 }, /* R15113 */ + { 0x0000, 0x0000, 0x0000 }, /* R15114 */ + { 0x0000, 0x0000, 0x0000 }, /* R15115 */ + { 0x0000, 0x0000, 0x0000 }, /* R15116 */ + { 0x0000, 0x0000, 0x0000 }, /* R15117 */ + { 0x0000, 0x0000, 0x0000 }, /* R15118 */ + { 0x0000, 0x0000, 0x0000 }, /* R15119 */ + { 0x0000, 0x0000, 0x0000 }, /* R15120 */ + { 0x0000, 0x0000, 0x0000 }, /* R15121 */ + { 0x0000, 0x0000, 0x0000 }, /* R15122 */ + { 0x0000, 0x0000, 0x0000 }, /* R15123 */ + { 0x0000, 0x0000, 0x0000 }, /* R15124 */ + { 0x0000, 0x0000, 0x0000 }, /* R15125 */ + { 0x0000, 0x0000, 0x0000 }, /* R15126 */ + { 0x0000, 0x0000, 0x0000 }, /* R15127 */ + { 0x0000, 0x0000, 0x0000 }, /* R15128 */ + { 0x0000, 0x0000, 0x0000 }, /* R15129 */ + { 0x0000, 0x0000, 0x0000 }, /* R15130 */ + { 0x0000, 0x0000, 0x0000 }, /* R15131 */ + { 0x0000, 0x0000, 0x0000 }, /* R15132 */ + { 0x0000, 0x0000, 0x0000 }, /* R15133 */ + { 0x0000, 0x0000, 0x0000 }, /* R15134 */ + { 0x0000, 0x0000, 0x0000 }, /* R15135 */ + { 0x0000, 0x0000, 0x0000 }, /* R15136 */ + { 0x0000, 0x0000, 0x0000 }, /* R15137 */ + { 0x0000, 0x0000, 0x0000 }, /* R15138 */ + { 0x0000, 0x0000, 0x0000 }, /* R15139 */ + { 0x0000, 0x0000, 0x0000 }, /* R15140 */ + { 0x0000, 0x0000, 0x0000 }, /* R15141 */ + { 0x0000, 0x0000, 0x0000 }, /* R15142 */ + { 0x0000, 0x0000, 0x0000 }, /* R15143 */ + { 0x0000, 0x0000, 0x0000 }, /* R15144 */ + { 0x0000, 0x0000, 0x0000 }, /* R15145 */ + { 0x0000, 0x0000, 0x0000 }, /* R15146 */ + { 0x0000, 0x0000, 0x0000 }, /* R15147 */ + { 0x0000, 0x0000, 0x0000 }, /* R15148 */ + { 0x0000, 0x0000, 0x0000 }, /* R15149 */ + { 0x0000, 0x0000, 0x0000 }, /* R15150 */ + { 0x0000, 0x0000, 0x0000 }, /* R15151 */ + { 0x0000, 0x0000, 0x0000 }, /* R15152 */ + { 0x0000, 0x0000, 0x0000 }, /* R15153 */ + { 0x0000, 0x0000, 0x0000 }, /* R15154 */ + { 0x0000, 0x0000, 0x0000 }, /* R15155 */ + { 0x0000, 0x0000, 0x0000 }, /* R15156 */ + { 0x0000, 0x0000, 0x0000 }, /* R15157 */ + { 0x0000, 0x0000, 0x0000 }, /* R15158 */ + { 0x0000, 0x0000, 0x0000 }, /* R15159 */ + { 0x0000, 0x0000, 0x0000 }, /* R15160 */ + { 0x0000, 0x0000, 0x0000 }, /* R15161 */ + { 0x0000, 0x0000, 0x0000 }, /* R15162 */ + { 0x0000, 0x0000, 0x0000 }, /* R15163 */ + { 0x0000, 0x0000, 0x0000 }, /* R15164 */ + { 0x0000, 0x0000, 0x0000 }, /* R15165 */ + { 0x0000, 0x0000, 0x0000 }, /* R15166 */ + { 0x0000, 0x0000, 0x0000 }, /* R15167 */ + { 0x0000, 0x0000, 0x0000 }, /* R15168 */ + { 0x0000, 0x0000, 0x0000 }, /* R15169 */ + { 0x0000, 0x0000, 0x0000 }, /* R15170 */ + { 0x0000, 0x0000, 0x0000 }, /* R15171 */ + { 0x0000, 0x0000, 0x0000 }, /* R15172 */ + { 0x0000, 0x0000, 0x0000 }, /* R15173 */ + { 0x0000, 0x0000, 0x0000 }, /* R15174 */ + { 0x0000, 0x0000, 0x0000 }, /* R15175 */ + { 0x0000, 0x0000, 0x0000 }, /* R15176 */ + { 0x0000, 0x0000, 0x0000 }, /* R15177 */ + { 0x0000, 0x0000, 0x0000 }, /* R15178 */ + { 0x0000, 0x0000, 0x0000 }, /* R15179 */ + { 0x0000, 0x0000, 0x0000 }, /* R15180 */ + { 0x0000, 0x0000, 0x0000 }, /* R15181 */ + { 0x0000, 0x0000, 0x0000 }, /* R15182 */ + { 0x0000, 0x0000, 0x0000 }, /* R15183 */ + { 0x0000, 0x0000, 0x0000 }, /* R15184 */ + { 0x0000, 0x0000, 0x0000 }, /* R15185 */ + { 0x0000, 0x0000, 0x0000 }, /* R15186 */ + { 0x0000, 0x0000, 0x0000 }, /* R15187 */ + { 0x0000, 0x0000, 0x0000 }, /* R15188 */ + { 0x0000, 0x0000, 0x0000 }, /* R15189 */ + { 0x0000, 0x0000, 0x0000 }, /* R15190 */ + { 0x0000, 0x0000, 0x0000 }, /* R15191 */ + { 0x0000, 0x0000, 0x0000 }, /* R15192 */ + { 0x0000, 0x0000, 0x0000 }, /* R15193 */ + { 0x0000, 0x0000, 0x0000 }, /* R15194 */ + { 0x0000, 0x0000, 0x0000 }, /* R15195 */ + { 0x0000, 0x0000, 0x0000 }, /* R15196 */ + { 0x0000, 0x0000, 0x0000 }, /* R15197 */ + { 0x0000, 0x0000, 0x0000 }, /* R15198 */ + { 0x0000, 0x0000, 0x0000 }, /* R15199 */ + { 0x0000, 0x0000, 0x0000 }, /* R15200 */ + { 0x0000, 0x0000, 0x0000 }, /* R15201 */ + { 0x0000, 0x0000, 0x0000 }, /* R15202 */ + { 0x0000, 0x0000, 0x0000 }, /* R15203 */ + { 0x0000, 0x0000, 0x0000 }, /* R15204 */ + { 0x0000, 0x0000, 0x0000 }, /* R15205 */ + { 0x0000, 0x0000, 0x0000 }, /* R15206 */ + { 0x0000, 0x0000, 0x0000 }, /* R15207 */ + { 0x0000, 0x0000, 0x0000 }, /* R15208 */ + { 0x0000, 0x0000, 0x0000 }, /* R15209 */ + { 0x0000, 0x0000, 0x0000 }, /* R15210 */ + { 0x0000, 0x0000, 0x0000 }, /* R15211 */ + { 0x0000, 0x0000, 0x0000 }, /* R15212 */ + { 0x0000, 0x0000, 0x0000 }, /* R15213 */ + { 0x0000, 0x0000, 0x0000 }, /* R15214 */ + { 0x0000, 0x0000, 0x0000 }, /* R15215 */ + { 0x0000, 0x0000, 0x0000 }, /* R15216 */ + { 0x0000, 0x0000, 0x0000 }, /* R15217 */ + { 0x0000, 0x0000, 0x0000 }, /* R15218 */ + { 0x0000, 0x0000, 0x0000 }, /* R15219 */ + { 0x0000, 0x0000, 0x0000 }, /* R15220 */ + { 0x0000, 0x0000, 0x0000 }, /* R15221 */ + { 0x0000, 0x0000, 0x0000 }, /* R15222 */ + { 0x0000, 0x0000, 0x0000 }, /* R15223 */ + { 0x0000, 0x0000, 0x0000 }, /* R15224 */ + { 0x0000, 0x0000, 0x0000 }, /* R15225 */ + { 0x0000, 0x0000, 0x0000 }, /* R15226 */ + { 0x0000, 0x0000, 0x0000 }, /* R15227 */ + { 0x0000, 0x0000, 0x0000 }, /* R15228 */ + { 0x0000, 0x0000, 0x0000 }, /* R15229 */ + { 0x0000, 0x0000, 0x0000 }, /* R15230 */ + { 0x0000, 0x0000, 0x0000 }, /* R15231 */ + { 0x0000, 0x0000, 0x0000 }, /* R15232 */ + { 0x0000, 0x0000, 0x0000 }, /* R15233 */ + { 0x0000, 0x0000, 0x0000 }, /* R15234 */ + { 0x0000, 0x0000, 0x0000 }, /* R15235 */ + { 0x0000, 0x0000, 0x0000 }, /* R15236 */ + { 0x0000, 0x0000, 0x0000 }, /* R15237 */ + { 0x0000, 0x0000, 0x0000 }, /* R15238 */ + { 0x0000, 0x0000, 0x0000 }, /* R15239 */ + { 0x0000, 0x0000, 0x0000 }, /* R15240 */ + { 0x0000, 0x0000, 0x0000 }, /* R15241 */ + { 0x0000, 0x0000, 0x0000 }, /* R15242 */ + { 0x0000, 0x0000, 0x0000 }, /* R15243 */ + { 0x0000, 0x0000, 0x0000 }, /* R15244 */ + { 0x0000, 0x0000, 0x0000 }, /* R15245 */ + { 0x0000, 0x0000, 0x0000 }, /* R15246 */ + { 0x0000, 0x0000, 0x0000 }, /* R15247 */ + { 0x0000, 0x0000, 0x0000 }, /* R15248 */ + { 0x0000, 0x0000, 0x0000 }, /* R15249 */ + { 0x0000, 0x0000, 0x0000 }, /* R15250 */ + { 0x0000, 0x0000, 0x0000 }, /* R15251 */ + { 0x0000, 0x0000, 0x0000 }, /* R15252 */ + { 0x0000, 0x0000, 0x0000 }, /* R15253 */ + { 0x0000, 0x0000, 0x0000 }, /* R15254 */ + { 0x0000, 0x0000, 0x0000 }, /* R15255 */ + { 0x0000, 0x0000, 0x0000 }, /* R15256 */ + { 0x0000, 0x0000, 0x0000 }, /* R15257 */ + { 0x0000, 0x0000, 0x0000 }, /* R15258 */ + { 0x0000, 0x0000, 0x0000 }, /* R15259 */ + { 0x0000, 0x0000, 0x0000 }, /* R15260 */ + { 0x0000, 0x0000, 0x0000 }, /* R15261 */ + { 0x0000, 0x0000, 0x0000 }, /* R15262 */ + { 0x0000, 0x0000, 0x0000 }, /* R15263 */ + { 0x0000, 0x0000, 0x0000 }, /* R15264 */ + { 0x0000, 0x0000, 0x0000 }, /* R15265 */ + { 0x0000, 0x0000, 0x0000 }, /* R15266 */ + { 0x0000, 0x0000, 0x0000 }, /* R15267 */ + { 0x0000, 0x0000, 0x0000 }, /* R15268 */ + { 0x0000, 0x0000, 0x0000 }, /* R15269 */ + { 0x0000, 0x0000, 0x0000 }, /* R15270 */ + { 0x0000, 0x0000, 0x0000 }, /* R15271 */ + { 0x0000, 0x0000, 0x0000 }, /* R15272 */ + { 0x0000, 0x0000, 0x0000 }, /* R15273 */ + { 0x0000, 0x0000, 0x0000 }, /* R15274 */ + { 0x0000, 0x0000, 0x0000 }, /* R15275 */ + { 0x0000, 0x0000, 0x0000 }, /* R15276 */ + { 0x0000, 0x0000, 0x0000 }, /* R15277 */ + { 0x0000, 0x0000, 0x0000 }, /* R15278 */ + { 0x0000, 0x0000, 0x0000 }, /* R15279 */ + { 0x0000, 0x0000, 0x0000 }, /* R15280 */ + { 0x0000, 0x0000, 0x0000 }, /* R15281 */ + { 0x0000, 0x0000, 0x0000 }, /* R15282 */ + { 0x0000, 0x0000, 0x0000 }, /* R15283 */ + { 0x0000, 0x0000, 0x0000 }, /* R15284 */ + { 0x0000, 0x0000, 0x0000 }, /* R15285 */ + { 0x0000, 0x0000, 0x0000 }, /* R15286 */ + { 0x0000, 0x0000, 0x0000 }, /* R15287 */ + { 0x0000, 0x0000, 0x0000 }, /* R15288 */ + { 0x0000, 0x0000, 0x0000 }, /* R15289 */ + { 0x0000, 0x0000, 0x0000 }, /* R15290 */ + { 0x0000, 0x0000, 0x0000 }, /* R15291 */ + { 0x0000, 0x0000, 0x0000 }, /* R15292 */ + { 0x0000, 0x0000, 0x0000 }, /* R15293 */ + { 0x0000, 0x0000, 0x0000 }, /* R15294 */ + { 0x0000, 0x0000, 0x0000 }, /* R15295 */ + { 0x0000, 0x0000, 0x0000 }, /* R15296 */ + { 0x0000, 0x0000, 0x0000 }, /* R15297 */ + { 0x0000, 0x0000, 0x0000 }, /* R15298 */ + { 0x0000, 0x0000, 0x0000 }, /* R15299 */ + { 0x0000, 0x0000, 0x0000 }, /* R15300 */ + { 0x0000, 0x0000, 0x0000 }, /* R15301 */ + { 0x0000, 0x0000, 0x0000 }, /* R15302 */ + { 0x0000, 0x0000, 0x0000 }, /* R15303 */ + { 0x0000, 0x0000, 0x0000 }, /* R15304 */ + { 0x0000, 0x0000, 0x0000 }, /* R15305 */ + { 0x0000, 0x0000, 0x0000 }, /* R15306 */ + { 0x0000, 0x0000, 0x0000 }, /* R15307 */ + { 0x0000, 0x0000, 0x0000 }, /* R15308 */ + { 0x0000, 0x0000, 0x0000 }, /* R15309 */ + { 0x0000, 0x0000, 0x0000 }, /* R15310 */ + { 0x0000, 0x0000, 0x0000 }, /* R15311 */ + { 0x0000, 0x0000, 0x0000 }, /* R15312 */ + { 0x0000, 0x0000, 0x0000 }, /* R15313 */ + { 0x0000, 0x0000, 0x0000 }, /* R15314 */ + { 0x0000, 0x0000, 0x0000 }, /* R15315 */ + { 0x0000, 0x0000, 0x0000 }, /* R15316 */ + { 0x0000, 0x0000, 0x0000 }, /* R15317 */ + { 0x0000, 0x0000, 0x0000 }, /* R15318 */ + { 0x0000, 0x0000, 0x0000 }, /* R15319 */ + { 0x0000, 0x0000, 0x0000 }, /* R15320 */ + { 0x0000, 0x0000, 0x0000 }, /* R15321 */ + { 0x0000, 0x0000, 0x0000 }, /* R15322 */ + { 0x0000, 0x0000, 0x0000 }, /* R15323 */ + { 0x0000, 0x0000, 0x0000 }, /* R15324 */ + { 0x0000, 0x0000, 0x0000 }, /* R15325 */ + { 0x0000, 0x0000, 0x0000 }, /* R15326 */ + { 0x0000, 0x0000, 0x0000 }, /* R15327 */ + { 0x0000, 0x0000, 0x0000 }, /* R15328 */ + { 0x0000, 0x0000, 0x0000 }, /* R15329 */ + { 0x0000, 0x0000, 0x0000 }, /* R15330 */ + { 0x0000, 0x0000, 0x0000 }, /* R15331 */ + { 0x0000, 0x0000, 0x0000 }, /* R15332 */ + { 0x0000, 0x0000, 0x0000 }, /* R15333 */ + { 0x0000, 0x0000, 0x0000 }, /* R15334 */ + { 0x0000, 0x0000, 0x0000 }, /* R15335 */ + { 0x0000, 0x0000, 0x0000 }, /* R15336 */ + { 0x0000, 0x0000, 0x0000 }, /* R15337 */ + { 0x0000, 0x0000, 0x0000 }, /* R15338 */ + { 0x0000, 0x0000, 0x0000 }, /* R15339 */ + { 0x0000, 0x0000, 0x0000 }, /* R15340 */ + { 0x0000, 0x0000, 0x0000 }, /* R15341 */ + { 0x0000, 0x0000, 0x0000 }, /* R15342 */ + { 0x0000, 0x0000, 0x0000 }, /* R15343 */ + { 0x0000, 0x0000, 0x0000 }, /* R15344 */ + { 0x0000, 0x0000, 0x0000 }, /* R15345 */ + { 0x0000, 0x0000, 0x0000 }, /* R15346 */ + { 0x0000, 0x0000, 0x0000 }, /* R15347 */ + { 0x0000, 0x0000, 0x0000 }, /* R15348 */ + { 0x0000, 0x0000, 0x0000 }, /* R15349 */ + { 0x0000, 0x0000, 0x0000 }, /* R15350 */ + { 0x0000, 0x0000, 0x0000 }, /* R15351 */ + { 0x0000, 0x0000, 0x0000 }, /* R15352 */ + { 0x0000, 0x0000, 0x0000 }, /* R15353 */ + { 0x0000, 0x0000, 0x0000 }, /* R15354 */ + { 0x0000, 0x0000, 0x0000 }, /* R15355 */ + { 0x0000, 0x0000, 0x0000 }, /* R15356 */ + { 0x0000, 0x0000, 0x0000 }, /* R15357 */ + { 0x0000, 0x0000, 0x0000 }, /* R15358 */ + { 0x0000, 0x0000, 0x0000 }, /* R15359 */ + { 0x07FF, 0x07FF, 0x0000 }, /* R15360 - DSP2 Coeff RAM 0 */ + { 0x0000, 0x0000, 0x0000 }, /* R15361 */ + { 0x0000, 0x0000, 0x0000 }, /* R15362 */ + { 0x0000, 0x0000, 0x0000 }, /* R15363 */ + { 0x0000, 0x0000, 0x0000 }, /* R15364 */ + { 0x0000, 0x0000, 0x0000 }, /* R15365 */ + { 0x0000, 0x0000, 0x0000 }, /* R15366 */ + { 0x0000, 0x0000, 0x0000 }, /* R15367 */ + { 0x0000, 0x0000, 0x0000 }, /* R15368 */ + { 0x0000, 0x0000, 0x0000 }, /* R15369 */ + { 0x0000, 0x0000, 0x0000 }, /* R15370 */ + { 0x0000, 0x0000, 0x0000 }, /* R15371 */ + { 0x0000, 0x0000, 0x0000 }, /* R15372 */ + { 0x0000, 0x0000, 0x0000 }, /* R15373 */ + { 0x0000, 0x0000, 0x0000 }, /* R15374 */ + { 0x0000, 0x0000, 0x0000 }, /* R15375 */ + { 0x0000, 0x0000, 0x0000 }, /* R15376 */ + { 0x0000, 0x0000, 0x0000 }, /* R15377 */ + { 0x0000, 0x0000, 0x0000 }, /* R15378 */ + { 0x0000, 0x0000, 0x0000 }, /* R15379 */ + { 0x0000, 0x0000, 0x0000 }, /* R15380 */ + { 0x0000, 0x0000, 0x0000 }, /* R15381 */ + { 0x0000, 0x0000, 0x0000 }, /* R15382 */ + { 0x0000, 0x0000, 0x0000 }, /* R15383 */ + { 0x0000, 0x0000, 0x0000 }, /* R15384 */ + { 0x0000, 0x0000, 0x0000 }, /* R15385 */ + { 0x0000, 0x0000, 0x0000 }, /* R15386 */ + { 0x0000, 0x0000, 0x0000 }, /* R15387 */ + { 0x0000, 0x0000, 0x0000 }, /* R15388 */ + { 0x0000, 0x0000, 0x0000 }, /* R15389 */ + { 0x0000, 0x0000, 0x0000 }, /* R15390 */ + { 0x0000, 0x0000, 0x0000 }, /* R15391 */ + { 0x0000, 0x0000, 0x0000 }, /* R15392 */ + { 0x0000, 0x0000, 0x0000 }, /* R15393 */ + { 0x0000, 0x0000, 0x0000 }, /* R15394 */ + { 0x0000, 0x0000, 0x0000 }, /* R15395 */ + { 0x0000, 0x0000, 0x0000 }, /* R15396 */ + { 0x0000, 0x0000, 0x0000 }, /* R15397 */ + { 0x0000, 0x0000, 0x0000 }, /* R15398 */ + { 0x0000, 0x0000, 0x0000 }, /* R15399 */ + { 0x0000, 0x0000, 0x0000 }, /* R15400 */ + { 0x0000, 0x0000, 0x0000 }, /* R15401 */ + { 0x0000, 0x0000, 0x0000 }, /* R15402 */ + { 0x0000, 0x0000, 0x0000 }, /* R15403 */ + { 0x0000, 0x0000, 0x0000 }, /* R15404 */ + { 0x0000, 0x0000, 0x0000 }, /* R15405 */ + { 0x0000, 0x0000, 0x0000 }, /* R15406 */ + { 0x0000, 0x0000, 0x0000 }, /* R15407 */ + { 0x0000, 0x0000, 0x0000 }, /* R15408 */ + { 0x0000, 0x0000, 0x0000 }, /* R15409 */ + { 0x0000, 0x0000, 0x0000 }, /* R15410 */ + { 0x0000, 0x0000, 0x0000 }, /* R15411 */ + { 0x0000, 0x0000, 0x0000 }, /* R15412 */ + { 0x0000, 0x0000, 0x0000 }, /* R15413 */ + { 0x0000, 0x0000, 0x0000 }, /* R15414 */ + { 0x0000, 0x0000, 0x0000 }, /* R15415 */ + { 0x0000, 0x0000, 0x0000 }, /* R15416 */ + { 0x0000, 0x0000, 0x0000 }, /* R15417 */ + { 0x0000, 0x0000, 0x0000 }, /* R15418 */ + { 0x0000, 0x0000, 0x0000 }, /* R15419 */ + { 0x0000, 0x0000, 0x0000 }, /* R15420 */ + { 0x0000, 0x0000, 0x0000 }, /* R15421 */ + { 0x0000, 0x0000, 0x0000 }, /* R15422 */ + { 0x0000, 0x0000, 0x0000 }, /* R15423 */ + { 0x0000, 0x0000, 0x0000 }, /* R15424 */ + { 0x0000, 0x0000, 0x0000 }, /* R15425 */ + { 0x0000, 0x0000, 0x0000 }, /* R15426 */ + { 0x0000, 0x0000, 0x0000 }, /* R15427 */ + { 0x0000, 0x0000, 0x0000 }, /* R15428 */ + { 0x0000, 0x0000, 0x0000 }, /* R15429 */ + { 0x0000, 0x0000, 0x0000 }, /* R15430 */ + { 0x0000, 0x0000, 0x0000 }, /* R15431 */ + { 0x0000, 0x0000, 0x0000 }, /* R15432 */ + { 0x0000, 0x0000, 0x0000 }, /* R15433 */ + { 0x0000, 0x0000, 0x0000 }, /* R15434 */ + { 0x0000, 0x0000, 0x0000 }, /* R15435 */ + { 0x0000, 0x0000, 0x0000 }, /* R15436 */ + { 0x0000, 0x0000, 0x0000 }, /* R15437 */ + { 0x0000, 0x0000, 0x0000 }, /* R15438 */ + { 0x0000, 0x0000, 0x0000 }, /* R15439 */ + { 0x0000, 0x0000, 0x0000 }, /* R15440 */ + { 0x0000, 0x0000, 0x0000 }, /* R15441 */ + { 0x0000, 0x0000, 0x0000 }, /* R15442 */ + { 0x0000, 0x0000, 0x0000 }, /* R15443 */ + { 0x0000, 0x0000, 0x0000 }, /* R15444 */ + { 0x0000, 0x0000, 0x0000 }, /* R15445 */ + { 0x0000, 0x0000, 0x0000 }, /* R15446 */ + { 0x0000, 0x0000, 0x0000 }, /* R15447 */ + { 0x0000, 0x0000, 0x0000 }, /* R15448 */ + { 0x0000, 0x0000, 0x0000 }, /* R15449 */ + { 0x0000, 0x0000, 0x0000 }, /* R15450 */ + { 0x0000, 0x0000, 0x0000 }, /* R15451 */ + { 0x0000, 0x0000, 0x0000 }, /* R15452 */ + { 0x0000, 0x0000, 0x0000 }, /* R15453 */ + { 0x0000, 0x0000, 0x0000 }, /* R15454 */ + { 0x0000, 0x0000, 0x0000 }, /* R15455 */ + { 0x0000, 0x0000, 0x0000 }, /* R15456 */ + { 0x0000, 0x0000, 0x0000 }, /* R15457 */ + { 0x0000, 0x0000, 0x0000 }, /* R15458 */ + { 0x0000, 0x0000, 0x0000 }, /* R15459 */ + { 0x0000, 0x0000, 0x0000 }, /* R15460 */ + { 0x0000, 0x0000, 0x0000 }, /* R15461 */ + { 0x0000, 0x0000, 0x0000 }, /* R15462 */ + { 0x0000, 0x0000, 0x0000 }, /* R15463 */ + { 0x0000, 0x0000, 0x0000 }, /* R15464 */ + { 0x0000, 0x0000, 0x0000 }, /* R15465 */ + { 0x0000, 0x0000, 0x0000 }, /* R15466 */ + { 0x0000, 0x0000, 0x0000 }, /* R15467 */ + { 0x0000, 0x0000, 0x0000 }, /* R15468 */ + { 0x0000, 0x0000, 0x0000 }, /* R15469 */ + { 0x0000, 0x0000, 0x0000 }, /* R15470 */ + { 0x0000, 0x0000, 0x0000 }, /* R15471 */ + { 0x0000, 0x0000, 0x0000 }, /* R15472 */ + { 0x0000, 0x0000, 0x0000 }, /* R15473 */ + { 0x0000, 0x0000, 0x0000 }, /* R15474 */ + { 0x0000, 0x0000, 0x0000 }, /* R15475 */ + { 0x0000, 0x0000, 0x0000 }, /* R15476 */ + { 0x0000, 0x0000, 0x0000 }, /* R15477 */ + { 0x0000, 0x0000, 0x0000 }, /* R15478 */ + { 0x0000, 0x0000, 0x0000 }, /* R15479 */ + { 0x0000, 0x0000, 0x0000 }, /* R15480 */ + { 0x0000, 0x0000, 0x0000 }, /* R15481 */ + { 0x0000, 0x0000, 0x0000 }, /* R15482 */ + { 0x0000, 0x0000, 0x0000 }, /* R15483 */ + { 0x0000, 0x0000, 0x0000 }, /* R15484 */ + { 0x0000, 0x0000, 0x0000 }, /* R15485 */ + { 0x0000, 0x0000, 0x0000 }, /* R15486 */ + { 0x0000, 0x0000, 0x0000 }, /* R15487 */ + { 0x0000, 0x0000, 0x0000 }, /* R15488 */ + { 0x0000, 0x0000, 0x0000 }, /* R15489 */ + { 0x0000, 0x0000, 0x0000 }, /* R15490 */ + { 0x0000, 0x0000, 0x0000 }, /* R15491 */ + { 0x0000, 0x0000, 0x0000 }, /* R15492 */ + { 0x0000, 0x0000, 0x0000 }, /* R15493 */ + { 0x0000, 0x0000, 0x0000 }, /* R15494 */ + { 0x0000, 0x0000, 0x0000 }, /* R15495 */ + { 0x0000, 0x0000, 0x0000 }, /* R15496 */ + { 0x0000, 0x0000, 0x0000 }, /* R15497 */ + { 0x0000, 0x0000, 0x0000 }, /* R15498 */ + { 0x0000, 0x0000, 0x0000 }, /* R15499 */ + { 0x0000, 0x0000, 0x0000 }, /* R15500 */ + { 0x0000, 0x0000, 0x0000 }, /* R15501 */ + { 0x0000, 0x0000, 0x0000 }, /* R15502 */ + { 0x0000, 0x0000, 0x0000 }, /* R15503 */ + { 0x0000, 0x0000, 0x0000 }, /* R15504 */ + { 0x0000, 0x0000, 0x0000 }, /* R15505 */ + { 0x0000, 0x0000, 0x0000 }, /* R15506 */ + { 0x0000, 0x0000, 0x0000 }, /* R15507 */ + { 0x0000, 0x0000, 0x0000 }, /* R15508 */ + { 0x0000, 0x0000, 0x0000 }, /* R15509 */ + { 0x0000, 0x0000, 0x0000 }, /* R15510 */ + { 0x0000, 0x0000, 0x0000 }, /* R15511 */ + { 0x0000, 0x0000, 0x0000 }, /* R15512 */ + { 0x0000, 0x0000, 0x0000 }, /* R15513 */ + { 0x0000, 0x0000, 0x0000 }, /* R15514 */ + { 0x0000, 0x0000, 0x0000 }, /* R15515 */ + { 0x0000, 0x0000, 0x0000 }, /* R15516 */ + { 0x0000, 0x0000, 0x0000 }, /* R15517 */ + { 0x0000, 0x0000, 0x0000 }, /* R15518 */ + { 0x0000, 0x0000, 0x0000 }, /* R15519 */ + { 0x0000, 0x0000, 0x0000 }, /* R15520 */ + { 0x0000, 0x0000, 0x0000 }, /* R15521 */ + { 0x0000, 0x0000, 0x0000 }, /* R15522 */ + { 0x0000, 0x0000, 0x0000 }, /* R15523 */ + { 0x0000, 0x0000, 0x0000 }, /* R15524 */ + { 0x0000, 0x0000, 0x0000 }, /* R15525 */ + { 0x0000, 0x0000, 0x0000 }, /* R15526 */ + { 0x0000, 0x0000, 0x0000 }, /* R15527 */ + { 0x0000, 0x0000, 0x0000 }, /* R15528 */ + { 0x0000, 0x0000, 0x0000 }, /* R15529 */ + { 0x0000, 0x0000, 0x0000 }, /* R15530 */ + { 0x0000, 0x0000, 0x0000 }, /* R15531 */ + { 0x0000, 0x0000, 0x0000 }, /* R15532 */ + { 0x0000, 0x0000, 0x0000 }, /* R15533 */ + { 0x0000, 0x0000, 0x0000 }, /* R15534 */ + { 0x0000, 0x0000, 0x0000 }, /* R15535 */ + { 0x0000, 0x0000, 0x0000 }, /* R15536 */ + { 0x0000, 0x0000, 0x0000 }, /* R15537 */ + { 0x0000, 0x0000, 0x0000 }, /* R15538 */ + { 0x0000, 0x0000, 0x0000 }, /* R15539 */ + { 0x0000, 0x0000, 0x0000 }, /* R15540 */ + { 0x0000, 0x0000, 0x0000 }, /* R15541 */ + { 0x0000, 0x0000, 0x0000 }, /* R15542 */ + { 0x0000, 0x0000, 0x0000 }, /* R15543 */ + { 0x0000, 0x0000, 0x0000 }, /* R15544 */ + { 0x0000, 0x0000, 0x0000 }, /* R15545 */ + { 0x0000, 0x0000, 0x0000 }, /* R15546 */ + { 0x0000, 0x0000, 0x0000 }, /* R15547 */ + { 0x0000, 0x0000, 0x0000 }, /* R15548 */ + { 0x0000, 0x0000, 0x0000 }, /* R15549 */ + { 0x0000, 0x0000, 0x0000 }, /* R15550 */ + { 0x0000, 0x0000, 0x0000 }, /* R15551 */ + { 0x0000, 0x0000, 0x0000 }, /* R15552 */ + { 0x0000, 0x0000, 0x0000 }, /* R15553 */ + { 0x0000, 0x0000, 0x0000 }, /* R15554 */ + { 0x0000, 0x0000, 0x0000 }, /* R15555 */ + { 0x0000, 0x0000, 0x0000 }, /* R15556 */ + { 0x0000, 0x0000, 0x0000 }, /* R15557 */ + { 0x0000, 0x0000, 0x0000 }, /* R15558 */ + { 0x0000, 0x0000, 0x0000 }, /* R15559 */ + { 0x0000, 0x0000, 0x0000 }, /* R15560 */ + { 0x0000, 0x0000, 0x0000 }, /* R15561 */ + { 0x0000, 0x0000, 0x0000 }, /* R15562 */ + { 0x0000, 0x0000, 0x0000 }, /* R15563 */ + { 0x0000, 0x0000, 0x0000 }, /* R15564 */ + { 0x0000, 0x0000, 0x0000 }, /* R15565 */ + { 0x0000, 0x0000, 0x0000 }, /* R15566 */ + { 0x0000, 0x0000, 0x0000 }, /* R15567 */ + { 0x0000, 0x0000, 0x0000 }, /* R15568 */ + { 0x0000, 0x0000, 0x0000 }, /* R15569 */ + { 0x0000, 0x0000, 0x0000 }, /* R15570 */ + { 0x0000, 0x0000, 0x0000 }, /* R15571 */ + { 0x0000, 0x0000, 0x0000 }, /* R15572 */ + { 0x0000, 0x0000, 0x0000 }, /* R15573 */ + { 0x0000, 0x0000, 0x0000 }, /* R15574 */ + { 0x0000, 0x0000, 0x0000 }, /* R15575 */ + { 0x0000, 0x0000, 0x0000 }, /* R15576 */ + { 0x0000, 0x0000, 0x0000 }, /* R15577 */ + { 0x0000, 0x0000, 0x0000 }, /* R15578 */ + { 0x0000, 0x0000, 0x0000 }, /* R15579 */ + { 0x0000, 0x0000, 0x0000 }, /* R15580 */ + { 0x0000, 0x0000, 0x0000 }, /* R15581 */ + { 0x0000, 0x0000, 0x0000 }, /* R15582 */ + { 0x0000, 0x0000, 0x0000 }, /* R15583 */ + { 0x0000, 0x0000, 0x0000 }, /* R15584 */ + { 0x0000, 0x0000, 0x0000 }, /* R15585 */ + { 0x0000, 0x0000, 0x0000 }, /* R15586 */ + { 0x0000, 0x0000, 0x0000 }, /* R15587 */ + { 0x0000, 0x0000, 0x0000 }, /* R15588 */ + { 0x0000, 0x0000, 0x0000 }, /* R15589 */ + { 0x0000, 0x0000, 0x0000 }, /* R15590 */ + { 0x0000, 0x0000, 0x0000 }, /* R15591 */ + { 0x0000, 0x0000, 0x0000 }, /* R15592 */ + { 0x0000, 0x0000, 0x0000 }, /* R15593 */ + { 0x0000, 0x0000, 0x0000 }, /* R15594 */ + { 0x0000, 0x0000, 0x0000 }, /* R15595 */ + { 0x0000, 0x0000, 0x0000 }, /* R15596 */ + { 0x0000, 0x0000, 0x0000 }, /* R15597 */ + { 0x0000, 0x0000, 0x0000 }, /* R15598 */ + { 0x0000, 0x0000, 0x0000 }, /* R15599 */ + { 0x0000, 0x0000, 0x0000 }, /* R15600 */ + { 0x0000, 0x0000, 0x0000 }, /* R15601 */ + { 0x0000, 0x0000, 0x0000 }, /* R15602 */ + { 0x0000, 0x0000, 0x0000 }, /* R15603 */ + { 0x0000, 0x0000, 0x0000 }, /* R15604 */ + { 0x0000, 0x0000, 0x0000 }, /* R15605 */ + { 0x0000, 0x0000, 0x0000 }, /* R15606 */ + { 0x0000, 0x0000, 0x0000 }, /* R15607 */ + { 0x0000, 0x0000, 0x0000 }, /* R15608 */ + { 0x0000, 0x0000, 0x0000 }, /* R15609 */ + { 0x0000, 0x0000, 0x0000 }, /* R15610 */ + { 0x0000, 0x0000, 0x0000 }, /* R15611 */ + { 0x0000, 0x0000, 0x0000 }, /* R15612 */ + { 0x0000, 0x0000, 0x0000 }, /* R15613 */ + { 0x0000, 0x0000, 0x0000 }, /* R15614 */ + { 0x0000, 0x0000, 0x0000 }, /* R15615 */ + { 0x0000, 0x0000, 0x0000 }, /* R15616 */ + { 0x0000, 0x0000, 0x0000 }, /* R15617 */ + { 0x0000, 0x0000, 0x0000 }, /* R15618 */ + { 0x0000, 0x0000, 0x0000 }, /* R15619 */ + { 0x0000, 0x0000, 0x0000 }, /* R15620 */ + { 0x0000, 0x0000, 0x0000 }, /* R15621 */ + { 0x0000, 0x0000, 0x0000 }, /* R15622 */ + { 0x0000, 0x0000, 0x0000 }, /* R15623 */ + { 0x0000, 0x0000, 0x0000 }, /* R15624 */ + { 0x0000, 0x0000, 0x0000 }, /* R15625 */ + { 0x0000, 0x0000, 0x0000 }, /* R15626 */ + { 0x0000, 0x0000, 0x0000 }, /* R15627 */ + { 0x0000, 0x0000, 0x0000 }, /* R15628 */ + { 0x0000, 0x0000, 0x0000 }, /* R15629 */ + { 0x0000, 0x0000, 0x0000 }, /* R15630 */ + { 0x0000, 0x0000, 0x0000 }, /* R15631 */ + { 0x0000, 0x0000, 0x0000 }, /* R15632 */ + { 0x0000, 0x0000, 0x0000 }, /* R15633 */ + { 0x0000, 0x0000, 0x0000 }, /* R15634 */ + { 0x0000, 0x0000, 0x0000 }, /* R15635 */ + { 0x0000, 0x0000, 0x0000 }, /* R15636 */ + { 0x0000, 0x0000, 0x0000 }, /* R15637 */ + { 0x0000, 0x0000, 0x0000 }, /* R15638 */ + { 0x0000, 0x0000, 0x0000 }, /* R15639 */ + { 0x0000, 0x0000, 0x0000 }, /* R15640 */ + { 0x0000, 0x0000, 0x0000 }, /* R15641 */ + { 0x0000, 0x0000, 0x0000 }, /* R15642 */ + { 0x0000, 0x0000, 0x0000 }, /* R15643 */ + { 0x0000, 0x0000, 0x0000 }, /* R15644 */ + { 0x0000, 0x0000, 0x0000 }, /* R15645 */ + { 0x0000, 0x0000, 0x0000 }, /* R15646 */ + { 0x0000, 0x0000, 0x0000 }, /* R15647 */ + { 0x0000, 0x0000, 0x0000 }, /* R15648 */ + { 0x0000, 0x0000, 0x0000 }, /* R15649 */ + { 0x0000, 0x0000, 0x0000 }, /* R15650 */ + { 0x0000, 0x0000, 0x0000 }, /* R15651 */ + { 0x0000, 0x0000, 0x0000 }, /* R15652 */ + { 0x0000, 0x0000, 0x0000 }, /* R15653 */ + { 0x0000, 0x0000, 0x0000 }, /* R15654 */ + { 0x0000, 0x0000, 0x0000 }, /* R15655 */ + { 0x0000, 0x0000, 0x0000 }, /* R15656 */ + { 0x0000, 0x0000, 0x0000 }, /* R15657 */ + { 0x0000, 0x0000, 0x0000 }, /* R15658 */ + { 0x0000, 0x0000, 0x0000 }, /* R15659 */ + { 0x0000, 0x0000, 0x0000 }, /* R15660 */ + { 0x0000, 0x0000, 0x0000 }, /* R15661 */ + { 0x0000, 0x0000, 0x0000 }, /* R15662 */ + { 0x0000, 0x0000, 0x0000 }, /* R15663 */ + { 0x0000, 0x0000, 0x0000 }, /* R15664 */ + { 0x0000, 0x0000, 0x0000 }, /* R15665 */ + { 0x0000, 0x0000, 0x0000 }, /* R15666 */ + { 0x0000, 0x0000, 0x0000 }, /* R15667 */ + { 0x0000, 0x0000, 0x0000 }, /* R15668 */ + { 0x0000, 0x0000, 0x0000 }, /* R15669 */ + { 0x0000, 0x0000, 0x0000 }, /* R15670 */ + { 0x0000, 0x0000, 0x0000 }, /* R15671 */ + { 0x0000, 0x0000, 0x0000 }, /* R15672 */ + { 0x0000, 0x0000, 0x0000 }, /* R15673 */ + { 0x0000, 0x0000, 0x0000 }, /* R15674 */ + { 0x0000, 0x0000, 0x0000 }, /* R15675 */ + { 0x0000, 0x0000, 0x0000 }, /* R15676 */ + { 0x0000, 0x0000, 0x0000 }, /* R15677 */ + { 0x0000, 0x0000, 0x0000 }, /* R15678 */ + { 0x0000, 0x0000, 0x0000 }, /* R15679 */ + { 0x0000, 0x0000, 0x0000 }, /* R15680 */ + { 0x0000, 0x0000, 0x0000 }, /* R15681 */ + { 0x0000, 0x0000, 0x0000 }, /* R15682 */ + { 0x0000, 0x0000, 0x0000 }, /* R15683 */ + { 0x0000, 0x0000, 0x0000 }, /* R15684 */ + { 0x0000, 0x0000, 0x0000 }, /* R15685 */ + { 0x0000, 0x0000, 0x0000 }, /* R15686 */ + { 0x0000, 0x0000, 0x0000 }, /* R15687 */ + { 0x0000, 0x0000, 0x0000 }, /* R15688 */ + { 0x0000, 0x0000, 0x0000 }, /* R15689 */ + { 0x0000, 0x0000, 0x0000 }, /* R15690 */ + { 0x0000, 0x0000, 0x0000 }, /* R15691 */ + { 0x0000, 0x0000, 0x0000 }, /* R15692 */ + { 0x0000, 0x0000, 0x0000 }, /* R15693 */ + { 0x0000, 0x0000, 0x0000 }, /* R15694 */ + { 0x0000, 0x0000, 0x0000 }, /* R15695 */ + { 0x0000, 0x0000, 0x0000 }, /* R15696 */ + { 0x0000, 0x0000, 0x0000 }, /* R15697 */ + { 0x0000, 0x0000, 0x0000 }, /* R15698 */ + { 0x0000, 0x0000, 0x0000 }, /* R15699 */ + { 0x0000, 0x0000, 0x0000 }, /* R15700 */ + { 0x0000, 0x0000, 0x0000 }, /* R15701 */ + { 0x0000, 0x0000, 0x0000 }, /* R15702 */ + { 0x0000, 0x0000, 0x0000 }, /* R15703 */ + { 0x0000, 0x0000, 0x0000 }, /* R15704 */ + { 0x0000, 0x0000, 0x0000 }, /* R15705 */ + { 0x0000, 0x0000, 0x0000 }, /* R15706 */ + { 0x0000, 0x0000, 0x0000 }, /* R15707 */ + { 0x0000, 0x0000, 0x0000 }, /* R15708 */ + { 0x0000, 0x0000, 0x0000 }, /* R15709 */ + { 0x0000, 0x0000, 0x0000 }, /* R15710 */ + { 0x0000, 0x0000, 0x0000 }, /* R15711 */ + { 0x0000, 0x0000, 0x0000 }, /* R15712 */ + { 0x0000, 0x0000, 0x0000 }, /* R15713 */ + { 0x0000, 0x0000, 0x0000 }, /* R15714 */ + { 0x0000, 0x0000, 0x0000 }, /* R15715 */ + { 0x0000, 0x0000, 0x0000 }, /* R15716 */ + { 0x0000, 0x0000, 0x0000 }, /* R15717 */ + { 0x0000, 0x0000, 0x0000 }, /* R15718 */ + { 0x0000, 0x0000, 0x0000 }, /* R15719 */ + { 0x0000, 0x0000, 0x0000 }, /* R15720 */ + { 0x0000, 0x0000, 0x0000 }, /* R15721 */ + { 0x0000, 0x0000, 0x0000 }, /* R15722 */ + { 0x0000, 0x0000, 0x0000 }, /* R15723 */ + { 0x0000, 0x0000, 0x0000 }, /* R15724 */ + { 0x0000, 0x0000, 0x0000 }, /* R15725 */ + { 0x0000, 0x0000, 0x0000 }, /* R15726 */ + { 0x0000, 0x0000, 0x0000 }, /* R15727 */ + { 0x0000, 0x0000, 0x0000 }, /* R15728 */ + { 0x0000, 0x0000, 0x0000 }, /* R15729 */ + { 0x0000, 0x0000, 0x0000 }, /* R15730 */ + { 0x0000, 0x0000, 0x0000 }, /* R15731 */ + { 0x0000, 0x0000, 0x0000 }, /* R15732 */ + { 0x0000, 0x0000, 0x0000 }, /* R15733 */ + { 0x0000, 0x0000, 0x0000 }, /* R15734 */ + { 0x0000, 0x0000, 0x0000 }, /* R15735 */ + { 0x0000, 0x0000, 0x0000 }, /* R15736 */ + { 0x0000, 0x0000, 0x0000 }, /* R15737 */ + { 0x0000, 0x0000, 0x0000 }, /* R15738 */ + { 0x0000, 0x0000, 0x0000 }, /* R15739 */ + { 0x0000, 0x0000, 0x0000 }, /* R15740 */ + { 0x0000, 0x0000, 0x0000 }, /* R15741 */ + { 0x0000, 0x0000, 0x0000 }, /* R15742 */ + { 0x0000, 0x0000, 0x0000 }, /* R15743 */ + { 0x0000, 0x0000, 0x0000 }, /* R15744 */ + { 0x0000, 0x0000, 0x0000 }, /* R15745 */ + { 0x0000, 0x0000, 0x0000 }, /* R15746 */ + { 0x0000, 0x0000, 0x0000 }, /* R15747 */ + { 0x0000, 0x0000, 0x0000 }, /* R15748 */ + { 0x0000, 0x0000, 0x0000 }, /* R15749 */ + { 0x0000, 0x0000, 0x0000 }, /* R15750 */ + { 0x0000, 0x0000, 0x0000 }, /* R15751 */ + { 0x0000, 0x0000, 0x0000 }, /* R15752 */ + { 0x0000, 0x0000, 0x0000 }, /* R15753 */ + { 0x0000, 0x0000, 0x0000 }, /* R15754 */ + { 0x0000, 0x0000, 0x0000 }, /* R15755 */ + { 0x0000, 0x0000, 0x0000 }, /* R15756 */ + { 0x0000, 0x0000, 0x0000 }, /* R15757 */ + { 0x0000, 0x0000, 0x0000 }, /* R15758 */ + { 0x0000, 0x0000, 0x0000 }, /* R15759 */ + { 0x0000, 0x0000, 0x0000 }, /* R15760 */ + { 0x0000, 0x0000, 0x0000 }, /* R15761 */ + { 0x0000, 0x0000, 0x0000 }, /* R15762 */ + { 0x0000, 0x0000, 0x0000 }, /* R15763 */ + { 0x0000, 0x0000, 0x0000 }, /* R15764 */ + { 0x0000, 0x0000, 0x0000 }, /* R15765 */ + { 0x0000, 0x0000, 0x0000 }, /* R15766 */ + { 0x0000, 0x0000, 0x0000 }, /* R15767 */ + { 0x0000, 0x0000, 0x0000 }, /* R15768 */ + { 0x0000, 0x0000, 0x0000 }, /* R15769 */ + { 0x0000, 0x0000, 0x0000 }, /* R15770 */ + { 0x0000, 0x0000, 0x0000 }, /* R15771 */ + { 0x0000, 0x0000, 0x0000 }, /* R15772 */ + { 0x0000, 0x0000, 0x0000 }, /* R15773 */ + { 0x0000, 0x0000, 0x0000 }, /* R15774 */ + { 0x0000, 0x0000, 0x0000 }, /* R15775 */ + { 0x0000, 0x0000, 0x0000 }, /* R15776 */ + { 0x0000, 0x0000, 0x0000 }, /* R15777 */ + { 0x0000, 0x0000, 0x0000 }, /* R15778 */ + { 0x0000, 0x0000, 0x0000 }, /* R15779 */ + { 0x0000, 0x0000, 0x0000 }, /* R15780 */ + { 0x0000, 0x0000, 0x0000 }, /* R15781 */ + { 0x0000, 0x0000, 0x0000 }, /* R15782 */ + { 0x0000, 0x0000, 0x0000 }, /* R15783 */ + { 0x0000, 0x0000, 0x0000 }, /* R15784 */ + { 0x0000, 0x0000, 0x0000 }, /* R15785 */ + { 0x0000, 0x0000, 0x0000 }, /* R15786 */ + { 0x0000, 0x0000, 0x0000 }, /* R15787 */ + { 0x0000, 0x0000, 0x0000 }, /* R15788 */ + { 0x0000, 0x0000, 0x0000 }, /* R15789 */ + { 0x0000, 0x0000, 0x0000 }, /* R15790 */ + { 0x0000, 0x0000, 0x0000 }, /* R15791 */ + { 0x0000, 0x0000, 0x0000 }, /* R15792 */ + { 0x0000, 0x0000, 0x0000 }, /* R15793 */ + { 0x0000, 0x0000, 0x0000 }, /* R15794 */ + { 0x0000, 0x0000, 0x0000 }, /* R15795 */ + { 0x0000, 0x0000, 0x0000 }, /* R15796 */ + { 0x0000, 0x0000, 0x0000 }, /* R15797 */ + { 0x0000, 0x0000, 0x0000 }, /* R15798 */ + { 0x0000, 0x0000, 0x0000 }, /* R15799 */ + { 0x0000, 0x0000, 0x0000 }, /* R15800 */ + { 0x0000, 0x0000, 0x0000 }, /* R15801 */ + { 0x0000, 0x0000, 0x0000 }, /* R15802 */ + { 0x0000, 0x0000, 0x0000 }, /* R15803 */ + { 0x0000, 0x0000, 0x0000 }, /* R15804 */ + { 0x0000, 0x0000, 0x0000 }, /* R15805 */ + { 0x0000, 0x0000, 0x0000 }, /* R15806 */ + { 0x0000, 0x0000, 0x0000 }, /* R15807 */ + { 0x0000, 0x0000, 0x0000 }, /* R15808 */ + { 0x0000, 0x0000, 0x0000 }, /* R15809 */ + { 0x0000, 0x0000, 0x0000 }, /* R15810 */ + { 0x0000, 0x0000, 0x0000 }, /* R15811 */ + { 0x0000, 0x0000, 0x0000 }, /* R15812 */ + { 0x0000, 0x0000, 0x0000 }, /* R15813 */ + { 0x0000, 0x0000, 0x0000 }, /* R15814 */ + { 0x0000, 0x0000, 0x0000 }, /* R15815 */ + { 0x0000, 0x0000, 0x0000 }, /* R15816 */ + { 0x0000, 0x0000, 0x0000 }, /* R15817 */ + { 0x0000, 0x0000, 0x0000 }, /* R15818 */ + { 0x0000, 0x0000, 0x0000 }, /* R15819 */ + { 0x0000, 0x0000, 0x0000 }, /* R15820 */ + { 0x0000, 0x0000, 0x0000 }, /* R15821 */ + { 0x0000, 0x0000, 0x0000 }, /* R15822 */ + { 0x0000, 0x0000, 0x0000 }, /* R15823 */ + { 0x0000, 0x0000, 0x0000 }, /* R15824 */ + { 0x0000, 0x0000, 0x0000 }, /* R15825 */ + { 0x0000, 0x0000, 0x0000 }, /* R15826 */ + { 0x0000, 0x0000, 0x0000 }, /* R15827 */ + { 0x0000, 0x0000, 0x0000 }, /* R15828 */ + { 0x0000, 0x0000, 0x0000 }, /* R15829 */ + { 0x0000, 0x0000, 0x0000 }, /* R15830 */ + { 0x0000, 0x0000, 0x0000 }, /* R15831 */ + { 0x0000, 0x0000, 0x0000 }, /* R15832 */ + { 0x0000, 0x0000, 0x0000 }, /* R15833 */ + { 0x0000, 0x0000, 0x0000 }, /* R15834 */ + { 0x0000, 0x0000, 0x0000 }, /* R15835 */ + { 0x0000, 0x0000, 0x0000 }, /* R15836 */ + { 0x0000, 0x0000, 0x0000 }, /* R15837 */ + { 0x0000, 0x0000, 0x0000 }, /* R15838 */ + { 0x0000, 0x0000, 0x0000 }, /* R15839 */ + { 0x0000, 0x0000, 0x0000 }, /* R15840 */ + { 0x0000, 0x0000, 0x0000 }, /* R15841 */ + { 0x0000, 0x0000, 0x0000 }, /* R15842 */ + { 0x0000, 0x0000, 0x0000 }, /* R15843 */ + { 0x0000, 0x0000, 0x0000 }, /* R15844 */ + { 0x0000, 0x0000, 0x0000 }, /* R15845 */ + { 0x0000, 0x0000, 0x0000 }, /* R15846 */ + { 0x0000, 0x0000, 0x0000 }, /* R15847 */ + { 0x0000, 0x0000, 0x0000 }, /* R15848 */ + { 0x0000, 0x0000, 0x0000 }, /* R15849 */ + { 0x0000, 0x0000, 0x0000 }, /* R15850 */ + { 0x0000, 0x0000, 0x0000 }, /* R15851 */ + { 0x0000, 0x0000, 0x0000 }, /* R15852 */ + { 0x0000, 0x0000, 0x0000 }, /* R15853 */ + { 0x0000, 0x0000, 0x0000 }, /* R15854 */ + { 0x0000, 0x0000, 0x0000 }, /* R15855 */ + { 0x0000, 0x0000, 0x0000 }, /* R15856 */ + { 0x0000, 0x0000, 0x0000 }, /* R15857 */ + { 0x0000, 0x0000, 0x0000 }, /* R15858 */ + { 0x0000, 0x0000, 0x0000 }, /* R15859 */ + { 0x0000, 0x0000, 0x0000 }, /* R15860 */ + { 0x0000, 0x0000, 0x0000 }, /* R15861 */ + { 0x0000, 0x0000, 0x0000 }, /* R15862 */ + { 0x0000, 0x0000, 0x0000 }, /* R15863 */ + { 0x0000, 0x0000, 0x0000 }, /* R15864 */ + { 0x0000, 0x0000, 0x0000 }, /* R15865 */ + { 0x0000, 0x0000, 0x0000 }, /* R15866 */ + { 0x0000, 0x0000, 0x0000 }, /* R15867 */ + { 0x0000, 0x0000, 0x0000 }, /* R15868 */ + { 0x0000, 0x0000, 0x0000 }, /* R15869 */ + { 0x0000, 0x0000, 0x0000 }, /* R15870 */ + { 0x0000, 0x0000, 0x0000 }, /* R15871 */ + { 0x0000, 0x0000, 0x0000 }, /* R15872 */ + { 0x0000, 0x0000, 0x0000 }, /* R15873 */ + { 0x0000, 0x0000, 0x0000 }, /* R15874 */ + { 0x0000, 0x0000, 0x0000 }, /* R15875 */ + { 0x0000, 0x0000, 0x0000 }, /* R15876 */ + { 0x0000, 0x0000, 0x0000 }, /* R15877 */ + { 0x0000, 0x0000, 0x0000 }, /* R15878 */ + { 0x0000, 0x0000, 0x0000 }, /* R15879 */ + { 0x0000, 0x0000, 0x0000 }, /* R15880 */ + { 0x0000, 0x0000, 0x0000 }, /* R15881 */ + { 0x0000, 0x0000, 0x0000 }, /* R15882 */ + { 0x0000, 0x0000, 0x0000 }, /* R15883 */ + { 0x0000, 0x0000, 0x0000 }, /* R15884 */ + { 0x0000, 0x0000, 0x0000 }, /* R15885 */ + { 0x0000, 0x0000, 0x0000 }, /* R15886 */ + { 0x0000, 0x0000, 0x0000 }, /* R15887 */ + { 0x0000, 0x0000, 0x0000 }, /* R15888 */ + { 0x0000, 0x0000, 0x0000 }, /* R15889 */ + { 0x0000, 0x0000, 0x0000 }, /* R15890 */ + { 0x0000, 0x0000, 0x0000 }, /* R15891 */ + { 0x0000, 0x0000, 0x0000 }, /* R15892 */ + { 0x0000, 0x0000, 0x0000 }, /* R15893 */ + { 0x0000, 0x0000, 0x0000 }, /* R15894 */ + { 0x0000, 0x0000, 0x0000 }, /* R15895 */ + { 0x0000, 0x0000, 0x0000 }, /* R15896 */ + { 0x0000, 0x0000, 0x0000 }, /* R15897 */ + { 0x0000, 0x0000, 0x0000 }, /* R15898 */ + { 0x0000, 0x0000, 0x0000 }, /* R15899 */ + { 0x0000, 0x0000, 0x0000 }, /* R15900 */ + { 0x0000, 0x0000, 0x0000 }, /* R15901 */ + { 0x0000, 0x0000, 0x0000 }, /* R15902 */ + { 0x0000, 0x0000, 0x0000 }, /* R15903 */ + { 0x0000, 0x0000, 0x0000 }, /* R15904 */ + { 0x0000, 0x0000, 0x0000 }, /* R15905 */ + { 0x0000, 0x0000, 0x0000 }, /* R15906 */ + { 0x0000, 0x0000, 0x0000 }, /* R15907 */ + { 0x0000, 0x0000, 0x0000 }, /* R15908 */ + { 0x0000, 0x0000, 0x0000 }, /* R15909 */ + { 0x0000, 0x0000, 0x0000 }, /* R15910 */ + { 0x0000, 0x0000, 0x0000 }, /* R15911 */ + { 0x0000, 0x0000, 0x0000 }, /* R15912 */ + { 0x0000, 0x0000, 0x0000 }, /* R15913 */ + { 0x0000, 0x0000, 0x0000 }, /* R15914 */ + { 0x0000, 0x0000, 0x0000 }, /* R15915 */ + { 0x0000, 0x0000, 0x0000 }, /* R15916 */ + { 0x0000, 0x0000, 0x0000 }, /* R15917 */ + { 0x0000, 0x0000, 0x0000 }, /* R15918 */ + { 0x0000, 0x0000, 0x0000 }, /* R15919 */ + { 0x0000, 0x0000, 0x0000 }, /* R15920 */ + { 0x0000, 0x0000, 0x0000 }, /* R15921 */ + { 0x0000, 0x0000, 0x0000 }, /* R15922 */ + { 0x0000, 0x0000, 0x0000 }, /* R15923 */ + { 0x0000, 0x0000, 0x0000 }, /* R15924 */ + { 0x0000, 0x0000, 0x0000 }, /* R15925 */ + { 0x0000, 0x0000, 0x0000 }, /* R15926 */ + { 0x0000, 0x0000, 0x0000 }, /* R15927 */ + { 0x0000, 0x0000, 0x0000 }, /* R15928 */ + { 0x0000, 0x0000, 0x0000 }, /* R15929 */ + { 0x0000, 0x0000, 0x0000 }, /* R15930 */ + { 0x0000, 0x0000, 0x0000 }, /* R15931 */ + { 0x0000, 0x0000, 0x0000 }, /* R15932 */ + { 0x0000, 0x0000, 0x0000 }, /* R15933 */ + { 0x0000, 0x0000, 0x0000 }, /* R15934 */ + { 0x0000, 0x0000, 0x0000 }, /* R15935 */ + { 0x0000, 0x0000, 0x0000 }, /* R15936 */ + { 0x0000, 0x0000, 0x0000 }, /* R15937 */ + { 0x0000, 0x0000, 0x0000 }, /* R15938 */ + { 0x0000, 0x0000, 0x0000 }, /* R15939 */ + { 0x0000, 0x0000, 0x0000 }, /* R15940 */ + { 0x0000, 0x0000, 0x0000 }, /* R15941 */ + { 0x0000, 0x0000, 0x0000 }, /* R15942 */ + { 0x0000, 0x0000, 0x0000 }, /* R15943 */ + { 0x0000, 0x0000, 0x0000 }, /* R15944 */ + { 0x0000, 0x0000, 0x0000 }, /* R15945 */ + { 0x0000, 0x0000, 0x0000 }, /* R15946 */ + { 0x0000, 0x0000, 0x0000 }, /* R15947 */ + { 0x0000, 0x0000, 0x0000 }, /* R15948 */ + { 0x0000, 0x0000, 0x0000 }, /* R15949 */ + { 0x0000, 0x0000, 0x0000 }, /* R15950 */ + { 0x0000, 0x0000, 0x0000 }, /* R15951 */ + { 0x0000, 0x0000, 0x0000 }, /* R15952 */ + { 0x0000, 0x0000, 0x0000 }, /* R15953 */ + { 0x0000, 0x0000, 0x0000 }, /* R15954 */ + { 0x0000, 0x0000, 0x0000 }, /* R15955 */ + { 0x0000, 0x0000, 0x0000 }, /* R15956 */ + { 0x0000, 0x0000, 0x0000 }, /* R15957 */ + { 0x0000, 0x0000, 0x0000 }, /* R15958 */ + { 0x0000, 0x0000, 0x0000 }, /* R15959 */ + { 0x0000, 0x0000, 0x0000 }, /* R15960 */ + { 0x0000, 0x0000, 0x0000 }, /* R15961 */ + { 0x0000, 0x0000, 0x0000 }, /* R15962 */ + { 0x0000, 0x0000, 0x0000 }, /* R15963 */ + { 0x0000, 0x0000, 0x0000 }, /* R15964 */ + { 0x0000, 0x0000, 0x0000 }, /* R15965 */ + { 0x0000, 0x0000, 0x0000 }, /* R15966 */ + { 0x0000, 0x0000, 0x0000 }, /* R15967 */ + { 0x0000, 0x0000, 0x0000 }, /* R15968 */ + { 0x0000, 0x0000, 0x0000 }, /* R15969 */ + { 0x0000, 0x0000, 0x0000 }, /* R15970 */ + { 0x0000, 0x0000, 0x0000 }, /* R15971 */ + { 0x0000, 0x0000, 0x0000 }, /* R15972 */ + { 0x0000, 0x0000, 0x0000 }, /* R15973 */ + { 0x0000, 0x0000, 0x0000 }, /* R15974 */ + { 0x0000, 0x0000, 0x0000 }, /* R15975 */ + { 0x0000, 0x0000, 0x0000 }, /* R15976 */ + { 0x0000, 0x0000, 0x0000 }, /* R15977 */ + { 0x0000, 0x0000, 0x0000 }, /* R15978 */ + { 0x0000, 0x0000, 0x0000 }, /* R15979 */ + { 0x0000, 0x0000, 0x0000 }, /* R15980 */ + { 0x0000, 0x0000, 0x0000 }, /* R15981 */ + { 0x0000, 0x0000, 0x0000 }, /* R15982 */ + { 0x0000, 0x0000, 0x0000 }, /* R15983 */ + { 0x0000, 0x0000, 0x0000 }, /* R15984 */ + { 0x0000, 0x0000, 0x0000 }, /* R15985 */ + { 0x0000, 0x0000, 0x0000 }, /* R15986 */ + { 0x0000, 0x0000, 0x0000 }, /* R15987 */ + { 0x0000, 0x0000, 0x0000 }, /* R15988 */ + { 0x0000, 0x0000, 0x0000 }, /* R15989 */ + { 0x0000, 0x0000, 0x0000 }, /* R15990 */ + { 0x0000, 0x0000, 0x0000 }, /* R15991 */ + { 0x0000, 0x0000, 0x0000 }, /* R15992 */ + { 0x0000, 0x0000, 0x0000 }, /* R15993 */ + { 0x0000, 0x0000, 0x0000 }, /* R15994 */ + { 0x0000, 0x0000, 0x0000 }, /* R15995 */ + { 0x0000, 0x0000, 0x0000 }, /* R15996 */ + { 0x0000, 0x0000, 0x0000 }, /* R15997 */ + { 0x0000, 0x0000, 0x0000 }, /* R15998 */ + { 0x0000, 0x0000, 0x0000 }, /* R15999 */ + { 0x0000, 0x0000, 0x0000 }, /* R16000 */ + { 0x0000, 0x0000, 0x0000 }, /* R16001 */ + { 0x0000, 0x0000, 0x0000 }, /* R16002 */ + { 0x0000, 0x0000, 0x0000 }, /* R16003 */ + { 0x0000, 0x0000, 0x0000 }, /* R16004 */ + { 0x0000, 0x0000, 0x0000 }, /* R16005 */ + { 0x0000, 0x0000, 0x0000 }, /* R16006 */ + { 0x0000, 0x0000, 0x0000 }, /* R16007 */ + { 0x0000, 0x0000, 0x0000 }, /* R16008 */ + { 0x0000, 0x0000, 0x0000 }, /* R16009 */ + { 0x0000, 0x0000, 0x0000 }, /* R16010 */ + { 0x0000, 0x0000, 0x0000 }, /* R16011 */ + { 0x0000, 0x0000, 0x0000 }, /* R16012 */ + { 0x0000, 0x0000, 0x0000 }, /* R16013 */ + { 0x0000, 0x0000, 0x0000 }, /* R16014 */ + { 0x0000, 0x0000, 0x0000 }, /* R16015 */ + { 0x0000, 0x0000, 0x0000 }, /* R16016 */ + { 0x0000, 0x0000, 0x0000 }, /* R16017 */ + { 0x0000, 0x0000, 0x0000 }, /* R16018 */ + { 0x0000, 0x0000, 0x0000 }, /* R16019 */ + { 0x0000, 0x0000, 0x0000 }, /* R16020 */ + { 0x0000, 0x0000, 0x0000 }, /* R16021 */ + { 0x0000, 0x0000, 0x0000 }, /* R16022 */ + { 0x0000, 0x0000, 0x0000 }, /* R16023 */ + { 0x0000, 0x0000, 0x0000 }, /* R16024 */ + { 0x0000, 0x0000, 0x0000 }, /* R16025 */ + { 0x0000, 0x0000, 0x0000 }, /* R16026 */ + { 0x0000, 0x0000, 0x0000 }, /* R16027 */ + { 0x0000, 0x0000, 0x0000 }, /* R16028 */ + { 0x0000, 0x0000, 0x0000 }, /* R16029 */ + { 0x0000, 0x0000, 0x0000 }, /* R16030 */ + { 0x0000, 0x0000, 0x0000 }, /* R16031 */ + { 0x0000, 0x0000, 0x0000 }, /* R16032 */ + { 0x0000, 0x0000, 0x0000 }, /* R16033 */ + { 0x0000, 0x0000, 0x0000 }, /* R16034 */ + { 0x0000, 0x0000, 0x0000 }, /* R16035 */ + { 0x0000, 0x0000, 0x0000 }, /* R16036 */ + { 0x0000, 0x0000, 0x0000 }, /* R16037 */ + { 0x0000, 0x0000, 0x0000 }, /* R16038 */ + { 0x0000, 0x0000, 0x0000 }, /* R16039 */ + { 0x0000, 0x0000, 0x0000 }, /* R16040 */ + { 0x0000, 0x0000, 0x0000 }, /* R16041 */ + { 0x0000, 0x0000, 0x0000 }, /* R16042 */ + { 0x0000, 0x0000, 0x0000 }, /* R16043 */ + { 0x0000, 0x0000, 0x0000 }, /* R16044 */ + { 0x0000, 0x0000, 0x0000 }, /* R16045 */ + { 0x0000, 0x0000, 0x0000 }, /* R16046 */ + { 0x0000, 0x0000, 0x0000 }, /* R16047 */ + { 0x0000, 0x0000, 0x0000 }, /* R16048 */ + { 0x0000, 0x0000, 0x0000 }, /* R16049 */ + { 0x0000, 0x0000, 0x0000 }, /* R16050 */ + { 0x0000, 0x0000, 0x0000 }, /* R16051 */ + { 0x0000, 0x0000, 0x0000 }, /* R16052 */ + { 0x0000, 0x0000, 0x0000 }, /* R16053 */ + { 0x0000, 0x0000, 0x0000 }, /* R16054 */ + { 0x0000, 0x0000, 0x0000 }, /* R16055 */ + { 0x0000, 0x0000, 0x0000 }, /* R16056 */ + { 0x0000, 0x0000, 0x0000 }, /* R16057 */ + { 0x0000, 0x0000, 0x0000 }, /* R16058 */ + { 0x0000, 0x0000, 0x0000 }, /* R16059 */ + { 0x0000, 0x0000, 0x0000 }, /* R16060 */ + { 0x0000, 0x0000, 0x0000 }, /* R16061 */ + { 0x0000, 0x0000, 0x0000 }, /* R16062 */ + { 0x0000, 0x0000, 0x0000 }, /* R16063 */ + { 0x0000, 0x0000, 0x0000 }, /* R16064 */ + { 0x0000, 0x0000, 0x0000 }, /* R16065 */ + { 0x0000, 0x0000, 0x0000 }, /* R16066 */ + { 0x0000, 0x0000, 0x0000 }, /* R16067 */ + { 0x0000, 0x0000, 0x0000 }, /* R16068 */ + { 0x0000, 0x0000, 0x0000 }, /* R16069 */ + { 0x0000, 0x0000, 0x0000 }, /* R16070 */ + { 0x0000, 0x0000, 0x0000 }, /* R16071 */ + { 0x0000, 0x0000, 0x0000 }, /* R16072 */ + { 0x0000, 0x0000, 0x0000 }, /* R16073 */ + { 0x0000, 0x0000, 0x0000 }, /* R16074 */ + { 0x0000, 0x0000, 0x0000 }, /* R16075 */ + { 0x0000, 0x0000, 0x0000 }, /* R16076 */ + { 0x0000, 0x0000, 0x0000 }, /* R16077 */ + { 0x0000, 0x0000, 0x0000 }, /* R16078 */ + { 0x0000, 0x0000, 0x0000 }, /* R16079 */ + { 0x0000, 0x0000, 0x0000 }, /* R16080 */ + { 0x0000, 0x0000, 0x0000 }, /* R16081 */ + { 0x0000, 0x0000, 0x0000 }, /* R16082 */ + { 0x0000, 0x0000, 0x0000 }, /* R16083 */ + { 0x0000, 0x0000, 0x0000 }, /* R16084 */ + { 0x0000, 0x0000, 0x0000 }, /* R16085 */ + { 0x0000, 0x0000, 0x0000 }, /* R16086 */ + { 0x0000, 0x0000, 0x0000 }, /* R16087 */ + { 0x0000, 0x0000, 0x0000 }, /* R16088 */ + { 0x0000, 0x0000, 0x0000 }, /* R16089 */ + { 0x0000, 0x0000, 0x0000 }, /* R16090 */ + { 0x0000, 0x0000, 0x0000 }, /* R16091 */ + { 0x0000, 0x0000, 0x0000 }, /* R16092 */ + { 0x0000, 0x0000, 0x0000 }, /* R16093 */ + { 0x0000, 0x0000, 0x0000 }, /* R16094 */ + { 0x0000, 0x0000, 0x0000 }, /* R16095 */ + { 0x0000, 0x0000, 0x0000 }, /* R16096 */ + { 0x0000, 0x0000, 0x0000 }, /* R16097 */ + { 0x0000, 0x0000, 0x0000 }, /* R16098 */ + { 0x0000, 0x0000, 0x0000 }, /* R16099 */ + { 0x0000, 0x0000, 0x0000 }, /* R16100 */ + { 0x0000, 0x0000, 0x0000 }, /* R16101 */ + { 0x0000, 0x0000, 0x0000 }, /* R16102 */ + { 0x0000, 0x0000, 0x0000 }, /* R16103 */ + { 0x0000, 0x0000, 0x0000 }, /* R16104 */ + { 0x0000, 0x0000, 0x0000 }, /* R16105 */ + { 0x0000, 0x0000, 0x0000 }, /* R16106 */ + { 0x0000, 0x0000, 0x0000 }, /* R16107 */ + { 0x0000, 0x0000, 0x0000 }, /* R16108 */ + { 0x0000, 0x0000, 0x0000 }, /* R16109 */ + { 0x0000, 0x0000, 0x0000 }, /* R16110 */ + { 0x0000, 0x0000, 0x0000 }, /* R16111 */ + { 0x0000, 0x0000, 0x0000 }, /* R16112 */ + { 0x0000, 0x0000, 0x0000 }, /* R16113 */ + { 0x0000, 0x0000, 0x0000 }, /* R16114 */ + { 0x0000, 0x0000, 0x0000 }, /* R16115 */ + { 0x0000, 0x0000, 0x0000 }, /* R16116 */ + { 0x0000, 0x0000, 0x0000 }, /* R16117 */ + { 0x0000, 0x0000, 0x0000 }, /* R16118 */ + { 0x0000, 0x0000, 0x0000 }, /* R16119 */ + { 0x0000, 0x0000, 0x0000 }, /* R16120 */ + { 0x0000, 0x0000, 0x0000 }, /* R16121 */ + { 0x0000, 0x0000, 0x0000 }, /* R16122 */ + { 0x0000, 0x0000, 0x0000 }, /* R16123 */ + { 0x0000, 0x0000, 0x0000 }, /* R16124 */ + { 0x0000, 0x0000, 0x0000 }, /* R16125 */ + { 0x0000, 0x0000, 0x0000 }, /* R16126 */ + { 0x0000, 0x0000, 0x0000 }, /* R16127 */ + { 0x0000, 0x0000, 0x0000 }, /* R16128 */ + { 0x0000, 0x0000, 0x0000 }, /* R16129 */ + { 0x0000, 0x0000, 0x0000 }, /* R16130 */ + { 0x0000, 0x0000, 0x0000 }, /* R16131 */ + { 0x0000, 0x0000, 0x0000 }, /* R16132 */ + { 0x0000, 0x0000, 0x0000 }, /* R16133 */ + { 0x0000, 0x0000, 0x0000 }, /* R16134 */ + { 0x0000, 0x0000, 0x0000 }, /* R16135 */ + { 0x0000, 0x0000, 0x0000 }, /* R16136 */ + { 0x0000, 0x0000, 0x0000 }, /* R16137 */ + { 0x0000, 0x0000, 0x0000 }, /* R16138 */ + { 0x0000, 0x0000, 0x0000 }, /* R16139 */ + { 0x0000, 0x0000, 0x0000 }, /* R16140 */ + { 0x0000, 0x0000, 0x0000 }, /* R16141 */ + { 0x0000, 0x0000, 0x0000 }, /* R16142 */ + { 0x0000, 0x0000, 0x0000 }, /* R16143 */ + { 0x0000, 0x0000, 0x0000 }, /* R16144 */ + { 0x0000, 0x0000, 0x0000 }, /* R16145 */ + { 0x0000, 0x0000, 0x0000 }, /* R16146 */ + { 0x0000, 0x0000, 0x0000 }, /* R16147 */ + { 0x0000, 0x0000, 0x0000 }, /* R16148 */ + { 0x0000, 0x0000, 0x0000 }, /* R16149 */ + { 0x0000, 0x0000, 0x0000 }, /* R16150 */ + { 0x0000, 0x0000, 0x0000 }, /* R16151 */ + { 0x0000, 0x0000, 0x0000 }, /* R16152 */ + { 0x0000, 0x0000, 0x0000 }, /* R16153 */ + { 0x0000, 0x0000, 0x0000 }, /* R16154 */ + { 0x0000, 0x0000, 0x0000 }, /* R16155 */ + { 0x0000, 0x0000, 0x0000 }, /* R16156 */ + { 0x0000, 0x0000, 0x0000 }, /* R16157 */ + { 0x0000, 0x0000, 0x0000 }, /* R16158 */ + { 0x0000, 0x0000, 0x0000 }, /* R16159 */ + { 0x0000, 0x0000, 0x0000 }, /* R16160 */ + { 0x0000, 0x0000, 0x0000 }, /* R16161 */ + { 0x0000, 0x0000, 0x0000 }, /* R16162 */ + { 0x0000, 0x0000, 0x0000 }, /* R16163 */ + { 0x0000, 0x0000, 0x0000 }, /* R16164 */ + { 0x0000, 0x0000, 0x0000 }, /* R16165 */ + { 0x0000, 0x0000, 0x0000 }, /* R16166 */ + { 0x0000, 0x0000, 0x0000 }, /* R16167 */ + { 0x0000, 0x0000, 0x0000 }, /* R16168 */ + { 0x0000, 0x0000, 0x0000 }, /* R16169 */ + { 0x0000, 0x0000, 0x0000 }, /* R16170 */ + { 0x0000, 0x0000, 0x0000 }, /* R16171 */ + { 0x0000, 0x0000, 0x0000 }, /* R16172 */ + { 0x0000, 0x0000, 0x0000 }, /* R16173 */ + { 0x0000, 0x0000, 0x0000 }, /* R16174 */ + { 0x0000, 0x0000, 0x0000 }, /* R16175 */ + { 0x0000, 0x0000, 0x0000 }, /* R16176 */ + { 0x0000, 0x0000, 0x0000 }, /* R16177 */ + { 0x0000, 0x0000, 0x0000 }, /* R16178 */ + { 0x0000, 0x0000, 0x0000 }, /* R16179 */ + { 0x0000, 0x0000, 0x0000 }, /* R16180 */ + { 0x0000, 0x0000, 0x0000 }, /* R16181 */ + { 0x0000, 0x0000, 0x0000 }, /* R16182 */ + { 0x0000, 0x0000, 0x0000 }, /* R16183 */ + { 0x0000, 0x0000, 0x0000 }, /* R16184 */ + { 0x0000, 0x0000, 0x0000 }, /* R16185 */ + { 0x0000, 0x0000, 0x0000 }, /* R16186 */ + { 0x0000, 0x0000, 0x0000 }, /* R16187 */ + { 0x0000, 0x0000, 0x0000 }, /* R16188 */ + { 0x0000, 0x0000, 0x0000 }, /* R16189 */ + { 0x0000, 0x0000, 0x0000 }, /* R16190 */ + { 0x0000, 0x0000, 0x0000 }, /* R16191 */ + { 0x0000, 0x0000, 0x0000 }, /* R16192 */ + { 0x0000, 0x0000, 0x0000 }, /* R16193 */ + { 0x0000, 0x0000, 0x0000 }, /* R16194 */ + { 0x0000, 0x0000, 0x0000 }, /* R16195 */ + { 0x0000, 0x0000, 0x0000 }, /* R16196 */ + { 0x0000, 0x0000, 0x0000 }, /* R16197 */ + { 0x0000, 0x0000, 0x0000 }, /* R16198 */ + { 0x0000, 0x0000, 0x0000 }, /* R16199 */ + { 0x0000, 0x0000, 0x0000 }, /* R16200 */ + { 0x0000, 0x0000, 0x0000 }, /* R16201 */ + { 0x0000, 0x0000, 0x0000 }, /* R16202 */ + { 0x0000, 0x0000, 0x0000 }, /* R16203 */ + { 0x0000, 0x0000, 0x0000 }, /* R16204 */ + { 0x0000, 0x0000, 0x0000 }, /* R16205 */ + { 0x0000, 0x0000, 0x0000 }, /* R16206 */ + { 0x0000, 0x0000, 0x0000 }, /* R16207 */ + { 0x0000, 0x0000, 0x0000 }, /* R16208 */ + { 0x0000, 0x0000, 0x0000 }, /* R16209 */ + { 0x0000, 0x0000, 0x0000 }, /* R16210 */ + { 0x0000, 0x0000, 0x0000 }, /* R16211 */ + { 0x0000, 0x0000, 0x0000 }, /* R16212 */ + { 0x0000, 0x0000, 0x0000 }, /* R16213 */ + { 0x0000, 0x0000, 0x0000 }, /* R16214 */ + { 0x0000, 0x0000, 0x0000 }, /* R16215 */ + { 0x0000, 0x0000, 0x0000 }, /* R16216 */ + { 0x0000, 0x0000, 0x0000 }, /* R16217 */ + { 0x0000, 0x0000, 0x0000 }, /* R16218 */ + { 0x0000, 0x0000, 0x0000 }, /* R16219 */ + { 0x0000, 0x0000, 0x0000 }, /* R16220 */ + { 0x0000, 0x0000, 0x0000 }, /* R16221 */ + { 0x0000, 0x0000, 0x0000 }, /* R16222 */ + { 0x0000, 0x0000, 0x0000 }, /* R16223 */ + { 0x0000, 0x0000, 0x0000 }, /* R16224 */ + { 0x0000, 0x0000, 0x0000 }, /* R16225 */ + { 0x0000, 0x0000, 0x0000 }, /* R16226 */ + { 0x0000, 0x0000, 0x0000 }, /* R16227 */ + { 0x0000, 0x0000, 0x0000 }, /* R16228 */ + { 0x0000, 0x0000, 0x0000 }, /* R16229 */ + { 0x0000, 0x0000, 0x0000 }, /* R16230 */ + { 0x0000, 0x0000, 0x0000 }, /* R16231 */ + { 0x0000, 0x0000, 0x0000 }, /* R16232 */ + { 0x0000, 0x0000, 0x0000 }, /* R16233 */ + { 0x0000, 0x0000, 0x0000 }, /* R16234 */ + { 0x0000, 0x0000, 0x0000 }, /* R16235 */ + { 0x0000, 0x0000, 0x0000 }, /* R16236 */ + { 0x0000, 0x0000, 0x0000 }, /* R16237 */ + { 0x0000, 0x0000, 0x0000 }, /* R16238 */ + { 0x0000, 0x0000, 0x0000 }, /* R16239 */ + { 0x0000, 0x0000, 0x0000 }, /* R16240 */ + { 0x0000, 0x0000, 0x0000 }, /* R16241 */ + { 0x0000, 0x0000, 0x0000 }, /* R16242 */ + { 0x0000, 0x0000, 0x0000 }, /* R16243 */ + { 0x0000, 0x0000, 0x0000 }, /* R16244 */ + { 0x0000, 0x0000, 0x0000 }, /* R16245 */ + { 0x0000, 0x0000, 0x0000 }, /* R16246 */ + { 0x0000, 0x0000, 0x0000 }, /* R16247 */ + { 0x0000, 0x0000, 0x0000 }, /* R16248 */ + { 0x0000, 0x0000, 0x0000 }, /* R16249 */ + { 0x0000, 0x0000, 0x0000 }, /* R16250 */ + { 0x0000, 0x0000, 0x0000 }, /* R16251 */ + { 0x0000, 0x0000, 0x0000 }, /* R16252 */ + { 0x0000, 0x0000, 0x0000 }, /* R16253 */ + { 0x0000, 0x0000, 0x0000 }, /* R16254 */ + { 0x0000, 0x0000, 0x0000 }, /* R16255 */ + { 0x0000, 0x0000, 0x0000 }, /* R16256 */ + { 0x0000, 0x0000, 0x0000 }, /* R16257 */ + { 0x0000, 0x0000, 0x0000 }, /* R16258 */ + { 0x0000, 0x0000, 0x0000 }, /* R16259 */ + { 0x0000, 0x0000, 0x0000 }, /* R16260 */ + { 0x0000, 0x0000, 0x0000 }, /* R16261 */ + { 0x0000, 0x0000, 0x0000 }, /* R16262 */ + { 0x0000, 0x0000, 0x0000 }, /* R16263 */ + { 0x0000, 0x0000, 0x0000 }, /* R16264 */ + { 0x0000, 0x0000, 0x0000 }, /* R16265 */ + { 0x0000, 0x0000, 0x0000 }, /* R16266 */ + { 0x0000, 0x0000, 0x0000 }, /* R16267 */ + { 0x0000, 0x0000, 0x0000 }, /* R16268 */ + { 0x0000, 0x0000, 0x0000 }, /* R16269 */ + { 0x0000, 0x0000, 0x0000 }, /* R16270 */ + { 0x0000, 0x0000, 0x0000 }, /* R16271 */ + { 0x0000, 0x0000, 0x0000 }, /* R16272 */ + { 0x0000, 0x0000, 0x0000 }, /* R16273 */ + { 0x0000, 0x0000, 0x0000 }, /* R16274 */ + { 0x0000, 0x0000, 0x0000 }, /* R16275 */ + { 0x0000, 0x0000, 0x0000 }, /* R16276 */ + { 0x0000, 0x0000, 0x0000 }, /* R16277 */ + { 0x0000, 0x0000, 0x0000 }, /* R16278 */ + { 0x0000, 0x0000, 0x0000 }, /* R16279 */ + { 0x0000, 0x0000, 0x0000 }, /* R16280 */ + { 0x0000, 0x0000, 0x0000 }, /* R16281 */ + { 0x0000, 0x0000, 0x0000 }, /* R16282 */ + { 0x0000, 0x0000, 0x0000 }, /* R16283 */ + { 0x0000, 0x0000, 0x0000 }, /* R16284 */ + { 0x0000, 0x0000, 0x0000 }, /* R16285 */ + { 0x0000, 0x0000, 0x0000 }, /* R16286 */ + { 0x0000, 0x0000, 0x0000 }, /* R16287 */ + { 0x0000, 0x0000, 0x0000 }, /* R16288 */ + { 0x0000, 0x0000, 0x0000 }, /* R16289 */ + { 0x0000, 0x0000, 0x0000 }, /* R16290 */ + { 0x0000, 0x0000, 0x0000 }, /* R16291 */ + { 0x0000, 0x0000, 0x0000 }, /* R16292 */ + { 0x0000, 0x0000, 0x0000 }, /* R16293 */ + { 0x0000, 0x0000, 0x0000 }, /* R16294 */ + { 0x0000, 0x0000, 0x0000 }, /* R16295 */ + { 0x0000, 0x0000, 0x0000 }, /* R16296 */ + { 0x0000, 0x0000, 0x0000 }, /* R16297 */ + { 0x0000, 0x0000, 0x0000 }, /* R16298 */ + { 0x0000, 0x0000, 0x0000 }, /* R16299 */ + { 0x0000, 0x0000, 0x0000 }, /* R16300 */ + { 0x0000, 0x0000, 0x0000 }, /* R16301 */ + { 0x0000, 0x0000, 0x0000 }, /* R16302 */ + { 0x0000, 0x0000, 0x0000 }, /* R16303 */ + { 0x0000, 0x0000, 0x0000 }, /* R16304 */ + { 0x0000, 0x0000, 0x0000 }, /* R16305 */ + { 0x0000, 0x0000, 0x0000 }, /* R16306 */ + { 0x0000, 0x0000, 0x0000 }, /* R16307 */ + { 0x0000, 0x0000, 0x0000 }, /* R16308 */ + { 0x0000, 0x0000, 0x0000 }, /* R16309 */ + { 0x0000, 0x0000, 0x0000 }, /* R16310 */ + { 0x0000, 0x0000, 0x0000 }, /* R16311 */ + { 0x0000, 0x0000, 0x0000 }, /* R16312 */ + { 0x0000, 0x0000, 0x0000 }, /* R16313 */ + { 0x0000, 0x0000, 0x0000 }, /* R16314 */ + { 0x0000, 0x0000, 0x0000 }, /* R16315 */ + { 0x0000, 0x0000, 0x0000 }, /* R16316 */ + { 0x0000, 0x0000, 0x0000 }, /* R16317 */ + { 0x0000, 0x0000, 0x0000 }, /* R16318 */ + { 0x0000, 0x0000, 0x0000 }, /* R16319 */ + { 0x0000, 0x0000, 0x0000 }, /* R16320 */ + { 0x0000, 0x0000, 0x0000 }, /* R16321 */ + { 0x0000, 0x0000, 0x0000 }, /* R16322 */ + { 0x0000, 0x0000, 0x0000 }, /* R16323 */ + { 0x0000, 0x0000, 0x0000 }, /* R16324 */ + { 0x0000, 0x0000, 0x0000 }, /* R16325 */ + { 0x0000, 0x0000, 0x0000 }, /* R16326 */ + { 0x0000, 0x0000, 0x0000 }, /* R16327 */ + { 0x0000, 0x0000, 0x0000 }, /* R16328 */ + { 0x0000, 0x0000, 0x0000 }, /* R16329 */ + { 0x0000, 0x0000, 0x0000 }, /* R16330 */ + { 0x0000, 0x0000, 0x0000 }, /* R16331 */ + { 0x0000, 0x0000, 0x0000 }, /* R16332 */ + { 0x0000, 0x0000, 0x0000 }, /* R16333 */ + { 0x0000, 0x0000, 0x0000 }, /* R16334 */ + { 0x0000, 0x0000, 0x0000 }, /* R16335 */ + { 0x0000, 0x0000, 0x0000 }, /* R16336 */ + { 0x0000, 0x0000, 0x0000 }, /* R16337 */ + { 0x0000, 0x0000, 0x0000 }, /* R16338 */ + { 0x0000, 0x0000, 0x0000 }, /* R16339 */ + { 0x0000, 0x0000, 0x0000 }, /* R16340 */ + { 0x0000, 0x0000, 0x0000 }, /* R16341 */ + { 0x0000, 0x0000, 0x0000 }, /* R16342 */ + { 0x0000, 0x0000, 0x0000 }, /* R16343 */ + { 0x0000, 0x0000, 0x0000 }, /* R16344 */ + { 0x0000, 0x0000, 0x0000 }, /* R16345 */ + { 0x0000, 0x0000, 0x0000 }, /* R16346 */ + { 0x0000, 0x0000, 0x0000 }, /* R16347 */ + { 0x0000, 0x0000, 0x0000 }, /* R16348 */ + { 0x0000, 0x0000, 0x0000 }, /* R16349 */ + { 0x0000, 0x0000, 0x0000 }, /* R16350 */ + { 0x0000, 0x0000, 0x0000 }, /* R16351 */ + { 0x0000, 0x0000, 0x0000 }, /* R16352 */ + { 0x0000, 0x0000, 0x0000 }, /* R16353 */ + { 0x0000, 0x0000, 0x0000 }, /* R16354 */ + { 0x0000, 0x0000, 0x0000 }, /* R16355 */ + { 0x0000, 0x0000, 0x0000 }, /* R16356 */ + { 0x0000, 0x0000, 0x0000 }, /* R16357 */ + { 0x0000, 0x0000, 0x0000 }, /* R16358 */ + { 0x0000, 0x0000, 0x0000 }, /* R16359 */ + { 0x0000, 0x0000, 0x0000 }, /* R16360 */ + { 0x0000, 0x0000, 0x0000 }, /* R16361 */ + { 0x0000, 0x0000, 0x0000 }, /* R16362 */ + { 0x0000, 0x0000, 0x0000 }, /* R16363 */ + { 0x0000, 0x0000, 0x0000 }, /* R16364 */ + { 0x0000, 0x0000, 0x0000 }, /* R16365 */ + { 0x0000, 0x0000, 0x0000 }, /* R16366 */ + { 0x0000, 0x0000, 0x0000 }, /* R16367 */ + { 0x0000, 0x0000, 0x0000 }, /* R16368 */ + { 0x0000, 0x0000, 0x0000 }, /* R16369 */ + { 0x0000, 0x0000, 0x0000 }, /* R16370 */ + { 0x0000, 0x0000, 0x0000 }, /* R16371 */ + { 0x0000, 0x0000, 0x0000 }, /* R16372 */ + { 0x0000, 0x0000, 0x0000 }, /* R16373 */ + { 0x0000, 0x0000, 0x0000 }, /* R16374 */ + { 0x0000, 0x0000, 0x0000 }, /* R16375 */ + { 0x0000, 0x0000, 0x0000 }, /* R16376 */ + { 0x0000, 0x0000, 0x0000 }, /* R16377 */ + { 0x0000, 0x0000, 0x0000 }, /* R16378 */ + { 0x0000, 0x0000, 0x0000 }, /* R16379 */ + { 0x0000, 0x0000, 0x0000 }, /* R16380 */ + { 0x0000, 0x0000, 0x0000 }, /* R16381 */ + { 0x0000, 0x0000, 0x0000 }, /* R16382 */ + { 0x0000, 0x0000, 0x0000 }, /* R16383 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16384 - RETUNEADC_SHARED_COEFF_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16385 - RETUNEADC_SHARED_COEFF_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16388 - SOUNDSTAGE_ENABLES_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16389 - SOUNDSTAGE_ENABLES_0 */ + { 0x0000, 0x0000, 0x0000 }, /* R16390 */ + { 0x0000, 0x0000, 0x0000 }, /* R16391 */ + { 0x0000, 0x0000, 0x0000 }, /* R16392 */ + { 0x0000, 0x0000, 0x0000 }, /* R16393 */ + { 0x0000, 0x0000, 0x0000 }, /* R16394 */ + { 0x0000, 0x0000, 0x0000 }, /* R16395 */ + { 0x0000, 0x0000, 0x0000 }, /* R16396 */ + { 0x0000, 0x0000, 0x0000 }, /* R16397 */ + { 0x0000, 0x0000, 0x0000 }, /* R16398 */ + { 0x0000, 0x0000, 0x0000 }, /* R16399 */ + { 0x0000, 0x0000, 0x0000 }, /* R16400 */ + { 0x0000, 0x0000, 0x0000 }, /* R16401 */ + { 0x0000, 0x0000, 0x0000 }, /* R16402 */ + { 0x0000, 0x0000, 0x0000 }, /* R16403 */ + { 0x0000, 0x0000, 0x0000 }, /* R16404 */ + { 0x0000, 0x0000, 0x0000 }, /* R16405 */ + { 0x0000, 0x0000, 0x0000 }, /* R16406 */ + { 0x0000, 0x0000, 0x0000 }, /* R16407 */ + { 0x0000, 0x0000, 0x0000 }, /* R16408 */ + { 0x0000, 0x0000, 0x0000 }, /* R16409 */ + { 0x0000, 0x0000, 0x0000 }, /* R16410 */ + { 0x0000, 0x0000, 0x0000 }, /* R16411 */ + { 0x0000, 0x0000, 0x0000 }, /* R16412 */ + { 0x0000, 0x0000, 0x0000 }, /* R16413 */ + { 0x0000, 0x0000, 0x0000 }, /* R16414 */ + { 0x0000, 0x0000, 0x0000 }, /* R16415 */ + { 0x0000, 0x0000, 0x0000 }, /* R16416 */ + { 0x0000, 0x0000, 0x0000 }, /* R16417 */ + { 0x0000, 0x0000, 0x0000 }, /* R16418 */ + { 0x0000, 0x0000, 0x0000 }, /* R16419 */ + { 0x0000, 0x0000, 0x0000 }, /* R16420 */ + { 0x0000, 0x0000, 0x0000 }, /* R16421 */ + { 0x0000, 0x0000, 0x0000 }, /* R16422 */ + { 0x0000, 0x0000, 0x0000 }, /* R16423 */ + { 0x0000, 0x0000, 0x0000 }, /* R16424 */ + { 0x0000, 0x0000, 0x0000 }, /* R16425 */ + { 0x0000, 0x0000, 0x0000 }, /* R16426 */ + { 0x0000, 0x0000, 0x0000 }, /* R16427 */ + { 0x0000, 0x0000, 0x0000 }, /* R16428 */ + { 0x0000, 0x0000, 0x0000 }, /* R16429 */ + { 0x0000, 0x0000, 0x0000 }, /* R16430 */ + { 0x0000, 0x0000, 0x0000 }, /* R16431 */ + { 0x0000, 0x0000, 0x0000 }, /* R16432 */ + { 0x0000, 0x0000, 0x0000 }, /* R16433 */ + { 0x0000, 0x0000, 0x0000 }, /* R16434 */ + { 0x0000, 0x0000, 0x0000 }, /* R16435 */ + { 0x0000, 0x0000, 0x0000 }, /* R16436 */ + { 0x0000, 0x0000, 0x0000 }, /* R16437 */ + { 0x0000, 0x0000, 0x0000 }, /* R16438 */ + { 0x0000, 0x0000, 0x0000 }, /* R16439 */ + { 0x0000, 0x0000, 0x0000 }, /* R16440 */ + { 0x0000, 0x0000, 0x0000 }, /* R16441 */ + { 0x0000, 0x0000, 0x0000 }, /* R16442 */ + { 0x0000, 0x0000, 0x0000 }, /* R16443 */ + { 0x0000, 0x0000, 0x0000 }, /* R16444 */ + { 0x0000, 0x0000, 0x0000 }, /* R16445 */ + { 0x0000, 0x0000, 0x0000 }, /* R16446 */ + { 0x0000, 0x0000, 0x0000 }, /* R16447 */ + { 0x0000, 0x0000, 0x0000 }, /* R16448 */ + { 0x0000, 0x0000, 0x0000 }, /* R16449 */ + { 0x0000, 0x0000, 0x0000 }, /* R16450 */ + { 0x0000, 0x0000, 0x0000 }, /* R16451 */ + { 0x0000, 0x0000, 0x0000 }, /* R16452 */ + { 0x0000, 0x0000, 0x0000 }, /* R16453 */ + { 0x0000, 0x0000, 0x0000 }, /* R16454 */ + { 0x0000, 0x0000, 0x0000 }, /* R16455 */ + { 0x0000, 0x0000, 0x0000 }, /* R16456 */ + { 0x0000, 0x0000, 0x0000 }, /* R16457 */ + { 0x0000, 0x0000, 0x0000 }, /* R16458 */ + { 0x0000, 0x0000, 0x0000 }, /* R16459 */ + { 0x0000, 0x0000, 0x0000 }, /* R16460 */ + { 0x0000, 0x0000, 0x0000 }, /* R16461 */ + { 0x0000, 0x0000, 0x0000 }, /* R16462 */ + { 0x0000, 0x0000, 0x0000 }, /* R16463 */ + { 0x0000, 0x0000, 0x0000 }, /* R16464 */ + { 0x0000, 0x0000, 0x0000 }, /* R16465 */ + { 0x0000, 0x0000, 0x0000 }, /* R16466 */ + { 0x0000, 0x0000, 0x0000 }, /* R16467 */ + { 0x0000, 0x0000, 0x0000 }, /* R16468 */ + { 0x0000, 0x0000, 0x0000 }, /* R16469 */ + { 0x0000, 0x0000, 0x0000 }, /* R16470 */ + { 0x0000, 0x0000, 0x0000 }, /* R16471 */ + { 0x0000, 0x0000, 0x0000 }, /* R16472 */ + { 0x0000, 0x0000, 0x0000 }, /* R16473 */ + { 0x0000, 0x0000, 0x0000 }, /* R16474 */ + { 0x0000, 0x0000, 0x0000 }, /* R16475 */ + { 0x0000, 0x0000, 0x0000 }, /* R16476 */ + { 0x0000, 0x0000, 0x0000 }, /* R16477 */ + { 0x0000, 0x0000, 0x0000 }, /* R16478 */ + { 0x0000, 0x0000, 0x0000 }, /* R16479 */ + { 0x0000, 0x0000, 0x0000 }, /* R16480 */ + { 0x0000, 0x0000, 0x0000 }, /* R16481 */ + { 0x0000, 0x0000, 0x0000 }, /* R16482 */ + { 0x0000, 0x0000, 0x0000 }, /* R16483 */ + { 0x0000, 0x0000, 0x0000 }, /* R16484 */ + { 0x0000, 0x0000, 0x0000 }, /* R16485 */ + { 0x0000, 0x0000, 0x0000 }, /* R16486 */ + { 0x0000, 0x0000, 0x0000 }, /* R16487 */ + { 0x0000, 0x0000, 0x0000 }, /* R16488 */ + { 0x0000, 0x0000, 0x0000 }, /* R16489 */ + { 0x0000, 0x0000, 0x0000 }, /* R16490 */ + { 0x0000, 0x0000, 0x0000 }, /* R16491 */ + { 0x0000, 0x0000, 0x0000 }, /* R16492 */ + { 0x0000, 0x0000, 0x0000 }, /* R16493 */ + { 0x0000, 0x0000, 0x0000 }, /* R16494 */ + { 0x0000, 0x0000, 0x0000 }, /* R16495 */ + { 0x0000, 0x0000, 0x0000 }, /* R16496 */ + { 0x0000, 0x0000, 0x0000 }, /* R16497 */ + { 0x0000, 0x0000, 0x0000 }, /* R16498 */ + { 0x0000, 0x0000, 0x0000 }, /* R16499 */ + { 0x0000, 0x0000, 0x0000 }, /* R16500 */ + { 0x0000, 0x0000, 0x0000 }, /* R16501 */ + { 0x0000, 0x0000, 0x0000 }, /* R16502 */ + { 0x0000, 0x0000, 0x0000 }, /* R16503 */ + { 0x0000, 0x0000, 0x0000 }, /* R16504 */ + { 0x0000, 0x0000, 0x0000 }, /* R16505 */ + { 0x0000, 0x0000, 0x0000 }, /* R16506 */ + { 0x0000, 0x0000, 0x0000 }, /* R16507 */ + { 0x0000, 0x0000, 0x0000 }, /* R16508 */ + { 0x0000, 0x0000, 0x0000 }, /* R16509 */ + { 0x0000, 0x0000, 0x0000 }, /* R16510 */ + { 0x0000, 0x0000, 0x0000 }, /* R16511 */ + { 0x0000, 0x0000, 0x0000 }, /* R16512 */ + { 0x0000, 0x0000, 0x0000 }, /* R16513 */ + { 0x0000, 0x0000, 0x0000 }, /* R16514 */ + { 0x0000, 0x0000, 0x0000 }, /* R16515 */ + { 0x0000, 0x0000, 0x0000 }, /* R16516 */ + { 0x0000, 0x0000, 0x0000 }, /* R16517 */ + { 0x0000, 0x0000, 0x0000 }, /* R16518 */ + { 0x0000, 0x0000, 0x0000 }, /* R16519 */ + { 0x0000, 0x0000, 0x0000 }, /* R16520 */ + { 0x0000, 0x0000, 0x0000 }, /* R16521 */ + { 0x0000, 0x0000, 0x0000 }, /* R16522 */ + { 0x0000, 0x0000, 0x0000 }, /* R16523 */ + { 0x0000, 0x0000, 0x0000 }, /* R16524 */ + { 0x0000, 0x0000, 0x0000 }, /* R16525 */ + { 0x0000, 0x0000, 0x0000 }, /* R16526 */ + { 0x0000, 0x0000, 0x0000 }, /* R16527 */ + { 0x0000, 0x0000, 0x0000 }, /* R16528 */ + { 0x0000, 0x0000, 0x0000 }, /* R16529 */ + { 0x0000, 0x0000, 0x0000 }, /* R16530 */ + { 0x0000, 0x0000, 0x0000 }, /* R16531 */ + { 0x0000, 0x0000, 0x0000 }, /* R16532 */ + { 0x0000, 0x0000, 0x0000 }, /* R16533 */ + { 0x0000, 0x0000, 0x0000 }, /* R16534 */ + { 0x0000, 0x0000, 0x0000 }, /* R16535 */ + { 0x0000, 0x0000, 0x0000 }, /* R16536 */ + { 0x0000, 0x0000, 0x0000 }, /* R16537 */ + { 0x0000, 0x0000, 0x0000 }, /* R16538 */ + { 0x0000, 0x0000, 0x0000 }, /* R16539 */ + { 0x0000, 0x0000, 0x0000 }, /* R16540 */ + { 0x0000, 0x0000, 0x0000 }, /* R16541 */ + { 0x0000, 0x0000, 0x0000 }, /* R16542 */ + { 0x0000, 0x0000, 0x0000 }, /* R16543 */ + { 0x0000, 0x0000, 0x0000 }, /* R16544 */ + { 0x0000, 0x0000, 0x0000 }, /* R16545 */ + { 0x0000, 0x0000, 0x0000 }, /* R16546 */ + { 0x0000, 0x0000, 0x0000 }, /* R16547 */ + { 0x0000, 0x0000, 0x0000 }, /* R16548 */ + { 0x0000, 0x0000, 0x0000 }, /* R16549 */ + { 0x0000, 0x0000, 0x0000 }, /* R16550 */ + { 0x0000, 0x0000, 0x0000 }, /* R16551 */ + { 0x0000, 0x0000, 0x0000 }, /* R16552 */ + { 0x0000, 0x0000, 0x0000 }, /* R16553 */ + { 0x0000, 0x0000, 0x0000 }, /* R16554 */ + { 0x0000, 0x0000, 0x0000 }, /* R16555 */ + { 0x0000, 0x0000, 0x0000 }, /* R16556 */ + { 0x0000, 0x0000, 0x0000 }, /* R16557 */ + { 0x0000, 0x0000, 0x0000 }, /* R16558 */ + { 0x0000, 0x0000, 0x0000 }, /* R16559 */ + { 0x0000, 0x0000, 0x0000 }, /* R16560 */ + { 0x0000, 0x0000, 0x0000 }, /* R16561 */ + { 0x0000, 0x0000, 0x0000 }, /* R16562 */ + { 0x0000, 0x0000, 0x0000 }, /* R16563 */ + { 0x0000, 0x0000, 0x0000 }, /* R16564 */ + { 0x0000, 0x0000, 0x0000 }, /* R16565 */ + { 0x0000, 0x0000, 0x0000 }, /* R16566 */ + { 0x0000, 0x0000, 0x0000 }, /* R16567 */ + { 0x0000, 0x0000, 0x0000 }, /* R16568 */ + { 0x0000, 0x0000, 0x0000 }, /* R16569 */ + { 0x0000, 0x0000, 0x0000 }, /* R16570 */ + { 0x0000, 0x0000, 0x0000 }, /* R16571 */ + { 0x0000, 0x0000, 0x0000 }, /* R16572 */ + { 0x0000, 0x0000, 0x0000 }, /* R16573 */ + { 0x0000, 0x0000, 0x0000 }, /* R16574 */ + { 0x0000, 0x0000, 0x0000 }, /* R16575 */ + { 0x0000, 0x0000, 0x0000 }, /* R16576 */ + { 0x0000, 0x0000, 0x0000 }, /* R16577 */ + { 0x0000, 0x0000, 0x0000 }, /* R16578 */ + { 0x0000, 0x0000, 0x0000 }, /* R16579 */ + { 0x0000, 0x0000, 0x0000 }, /* R16580 */ + { 0x0000, 0x0000, 0x0000 }, /* R16581 */ + { 0x0000, 0x0000, 0x0000 }, /* R16582 */ + { 0x0000, 0x0000, 0x0000 }, /* R16583 */ + { 0x0000, 0x0000, 0x0000 }, /* R16584 */ + { 0x0000, 0x0000, 0x0000 }, /* R16585 */ + { 0x0000, 0x0000, 0x0000 }, /* R16586 */ + { 0x0000, 0x0000, 0x0000 }, /* R16587 */ + { 0x0000, 0x0000, 0x0000 }, /* R16588 */ + { 0x0000, 0x0000, 0x0000 }, /* R16589 */ + { 0x0000, 0x0000, 0x0000 }, /* R16590 */ + { 0x0000, 0x0000, 0x0000 }, /* R16591 */ + { 0x0000, 0x0000, 0x0000 }, /* R16592 */ + { 0x0000, 0x0000, 0x0000 }, /* R16593 */ + { 0x0000, 0x0000, 0x0000 }, /* R16594 */ + { 0x0000, 0x0000, 0x0000 }, /* R16595 */ + { 0x0000, 0x0000, 0x0000 }, /* R16596 */ + { 0x0000, 0x0000, 0x0000 }, /* R16597 */ + { 0x0000, 0x0000, 0x0000 }, /* R16598 */ + { 0x0000, 0x0000, 0x0000 }, /* R16599 */ + { 0x0000, 0x0000, 0x0000 }, /* R16600 */ + { 0x0000, 0x0000, 0x0000 }, /* R16601 */ + { 0x0000, 0x0000, 0x0000 }, /* R16602 */ + { 0x0000, 0x0000, 0x0000 }, /* R16603 */ + { 0x0000, 0x0000, 0x0000 }, /* R16604 */ + { 0x0000, 0x0000, 0x0000 }, /* R16605 */ + { 0x0000, 0x0000, 0x0000 }, /* R16606 */ + { 0x0000, 0x0000, 0x0000 }, /* R16607 */ + { 0x0000, 0x0000, 0x0000 }, /* R16608 */ + { 0x0000, 0x0000, 0x0000 }, /* R16609 */ + { 0x0000, 0x0000, 0x0000 }, /* R16610 */ + { 0x0000, 0x0000, 0x0000 }, /* R16611 */ + { 0x0000, 0x0000, 0x0000 }, /* R16612 */ + { 0x0000, 0x0000, 0x0000 }, /* R16613 */ + { 0x0000, 0x0000, 0x0000 }, /* R16614 */ + { 0x0000, 0x0000, 0x0000 }, /* R16615 */ + { 0x0000, 0x0000, 0x0000 }, /* R16616 */ + { 0x0000, 0x0000, 0x0000 }, /* R16617 */ + { 0x0000, 0x0000, 0x0000 }, /* R16618 */ + { 0x0000, 0x0000, 0x0000 }, /* R16619 */ + { 0x0000, 0x0000, 0x0000 }, /* R16620 */ + { 0x0000, 0x0000, 0x0000 }, /* R16621 */ + { 0x0000, 0x0000, 0x0000 }, /* R16622 */ + { 0x0000, 0x0000, 0x0000 }, /* R16623 */ + { 0x0000, 0x0000, 0x0000 }, /* R16624 */ + { 0x0000, 0x0000, 0x0000 }, /* R16625 */ + { 0x0000, 0x0000, 0x0000 }, /* R16626 */ + { 0x0000, 0x0000, 0x0000 }, /* R16627 */ + { 0x0000, 0x0000, 0x0000 }, /* R16628 */ + { 0x0000, 0x0000, 0x0000 }, /* R16629 */ + { 0x0000, 0x0000, 0x0000 }, /* R16630 */ + { 0x0000, 0x0000, 0x0000 }, /* R16631 */ + { 0x0000, 0x0000, 0x0000 }, /* R16632 */ + { 0x0000, 0x0000, 0x0000 }, /* R16633 */ + { 0x0000, 0x0000, 0x0000 }, /* R16634 */ + { 0x0000, 0x0000, 0x0000 }, /* R16635 */ + { 0x0000, 0x0000, 0x0000 }, /* R16636 */ + { 0x0000, 0x0000, 0x0000 }, /* R16637 */ + { 0x0000, 0x0000, 0x0000 }, /* R16638 */ + { 0x0000, 0x0000, 0x0000 }, /* R16639 */ + { 0x0000, 0x0000, 0x0000 }, /* R16640 */ + { 0x0000, 0x0000, 0x0000 }, /* R16641 */ + { 0x0000, 0x0000, 0x0000 }, /* R16642 */ + { 0x0000, 0x0000, 0x0000 }, /* R16643 */ + { 0x0000, 0x0000, 0x0000 }, /* R16644 */ + { 0x0000, 0x0000, 0x0000 }, /* R16645 */ + { 0x0000, 0x0000, 0x0000 }, /* R16646 */ + { 0x0000, 0x0000, 0x0000 }, /* R16647 */ + { 0x0000, 0x0000, 0x0000 }, /* R16648 */ + { 0x0000, 0x0000, 0x0000 }, /* R16649 */ + { 0x0000, 0x0000, 0x0000 }, /* R16650 */ + { 0x0000, 0x0000, 0x0000 }, /* R16651 */ + { 0x0000, 0x0000, 0x0000 }, /* R16652 */ + { 0x0000, 0x0000, 0x0000 }, /* R16653 */ + { 0x0000, 0x0000, 0x0000 }, /* R16654 */ + { 0x0000, 0x0000, 0x0000 }, /* R16655 */ + { 0x0000, 0x0000, 0x0000 }, /* R16656 */ + { 0x0000, 0x0000, 0x0000 }, /* R16657 */ + { 0x0000, 0x0000, 0x0000 }, /* R16658 */ + { 0x0000, 0x0000, 0x0000 }, /* R16659 */ + { 0x0000, 0x0000, 0x0000 }, /* R16660 */ + { 0x0000, 0x0000, 0x0000 }, /* R16661 */ + { 0x0000, 0x0000, 0x0000 }, /* R16662 */ + { 0x0000, 0x0000, 0x0000 }, /* R16663 */ + { 0x0000, 0x0000, 0x0000 }, /* R16664 */ + { 0x0000, 0x0000, 0x0000 }, /* R16665 */ + { 0x0000, 0x0000, 0x0000 }, /* R16666 */ + { 0x0000, 0x0000, 0x0000 }, /* R16667 */ + { 0x0000, 0x0000, 0x0000 }, /* R16668 */ + { 0x0000, 0x0000, 0x0000 }, /* R16669 */ + { 0x0000, 0x0000, 0x0000 }, /* R16670 */ + { 0x0000, 0x0000, 0x0000 }, /* R16671 */ + { 0x0000, 0x0000, 0x0000 }, /* R16672 */ + { 0x0000, 0x0000, 0x0000 }, /* R16673 */ + { 0x0000, 0x0000, 0x0000 }, /* R16674 */ + { 0x0000, 0x0000, 0x0000 }, /* R16675 */ + { 0x0000, 0x0000, 0x0000 }, /* R16676 */ + { 0x0000, 0x0000, 0x0000 }, /* R16677 */ + { 0x0000, 0x0000, 0x0000 }, /* R16678 */ + { 0x0000, 0x0000, 0x0000 }, /* R16679 */ + { 0x0000, 0x0000, 0x0000 }, /* R16680 */ + { 0x0000, 0x0000, 0x0000 }, /* R16681 */ + { 0x0000, 0x0000, 0x0000 }, /* R16682 */ + { 0x0000, 0x0000, 0x0000 }, /* R16683 */ + { 0x0000, 0x0000, 0x0000 }, /* R16684 */ + { 0x0000, 0x0000, 0x0000 }, /* R16685 */ + { 0x0000, 0x0000, 0x0000 }, /* R16686 */ + { 0x0000, 0x0000, 0x0000 }, /* R16687 */ + { 0x0000, 0x0000, 0x0000 }, /* R16688 */ + { 0x0000, 0x0000, 0x0000 }, /* R16689 */ + { 0x0000, 0x0000, 0x0000 }, /* R16690 */ + { 0x0000, 0x0000, 0x0000 }, /* R16691 */ + { 0x0000, 0x0000, 0x0000 }, /* R16692 */ + { 0x0000, 0x0000, 0x0000 }, /* R16693 */ + { 0x0000, 0x0000, 0x0000 }, /* R16694 */ + { 0x0000, 0x0000, 0x0000 }, /* R16695 */ + { 0x0000, 0x0000, 0x0000 }, /* R16696 */ + { 0x0000, 0x0000, 0x0000 }, /* R16697 */ + { 0x0000, 0x0000, 0x0000 }, /* R16698 */ + { 0x0000, 0x0000, 0x0000 }, /* R16699 */ + { 0x0000, 0x0000, 0x0000 }, /* R16700 */ + { 0x0000, 0x0000, 0x0000 }, /* R16701 */ + { 0x0000, 0x0000, 0x0000 }, /* R16702 */ + { 0x0000, 0x0000, 0x0000 }, /* R16703 */ + { 0x0000, 0x0000, 0x0000 }, /* R16704 */ + { 0x0000, 0x0000, 0x0000 }, /* R16705 */ + { 0x0000, 0x0000, 0x0000 }, /* R16706 */ + { 0x0000, 0x0000, 0x0000 }, /* R16707 */ + { 0x0000, 0x0000, 0x0000 }, /* R16708 */ + { 0x0000, 0x0000, 0x0000 }, /* R16709 */ + { 0x0000, 0x0000, 0x0000 }, /* R16710 */ + { 0x0000, 0x0000, 0x0000 }, /* R16711 */ + { 0x0000, 0x0000, 0x0000 }, /* R16712 */ + { 0x0000, 0x0000, 0x0000 }, /* R16713 */ + { 0x0000, 0x0000, 0x0000 }, /* R16714 */ + { 0x0000, 0x0000, 0x0000 }, /* R16715 */ + { 0x0000, 0x0000, 0x0000 }, /* R16716 */ + { 0x0000, 0x0000, 0x0000 }, /* R16717 */ + { 0x0000, 0x0000, 0x0000 }, /* R16718 */ + { 0x0000, 0x0000, 0x0000 }, /* R16719 */ + { 0x0000, 0x0000, 0x0000 }, /* R16720 */ + { 0x0000, 0x0000, 0x0000 }, /* R16721 */ + { 0x0000, 0x0000, 0x0000 }, /* R16722 */ + { 0x0000, 0x0000, 0x0000 }, /* R16723 */ + { 0x0000, 0x0000, 0x0000 }, /* R16724 */ + { 0x0000, 0x0000, 0x0000 }, /* R16725 */ + { 0x0000, 0x0000, 0x0000 }, /* R16726 */ + { 0x0000, 0x0000, 0x0000 }, /* R16727 */ + { 0x0000, 0x0000, 0x0000 }, /* R16728 */ + { 0x0000, 0x0000, 0x0000 }, /* R16729 */ + { 0x0000, 0x0000, 0x0000 }, /* R16730 */ + { 0x0000, 0x0000, 0x0000 }, /* R16731 */ + { 0x0000, 0x0000, 0x0000 }, /* R16732 */ + { 0x0000, 0x0000, 0x0000 }, /* R16733 */ + { 0x0000, 0x0000, 0x0000 }, /* R16734 */ + { 0x0000, 0x0000, 0x0000 }, /* R16735 */ + { 0x0000, 0x0000, 0x0000 }, /* R16736 */ + { 0x0000, 0x0000, 0x0000 }, /* R16737 */ + { 0x0000, 0x0000, 0x0000 }, /* R16738 */ + { 0x0000, 0x0000, 0x0000 }, /* R16739 */ + { 0x0000, 0x0000, 0x0000 }, /* R16740 */ + { 0x0000, 0x0000, 0x0000 }, /* R16741 */ + { 0x0000, 0x0000, 0x0000 }, /* R16742 */ + { 0x0000, 0x0000, 0x0000 }, /* R16743 */ + { 0x0000, 0x0000, 0x0000 }, /* R16744 */ + { 0x0000, 0x0000, 0x0000 }, /* R16745 */ + { 0x0000, 0x0000, 0x0000 }, /* R16746 */ + { 0x0000, 0x0000, 0x0000 }, /* R16747 */ + { 0x0000, 0x0000, 0x0000 }, /* R16748 */ + { 0x0000, 0x0000, 0x0000 }, /* R16749 */ + { 0x0000, 0x0000, 0x0000 }, /* R16750 */ + { 0x0000, 0x0000, 0x0000 }, /* R16751 */ + { 0x0000, 0x0000, 0x0000 }, /* R16752 */ + { 0x0000, 0x0000, 0x0000 }, /* R16753 */ + { 0x0000, 0x0000, 0x0000 }, /* R16754 */ + { 0x0000, 0x0000, 0x0000 }, /* R16755 */ + { 0x0000, 0x0000, 0x0000 }, /* R16756 */ + { 0x0000, 0x0000, 0x0000 }, /* R16757 */ + { 0x0000, 0x0000, 0x0000 }, /* R16758 */ + { 0x0000, 0x0000, 0x0000 }, /* R16759 */ + { 0x0000, 0x0000, 0x0000 }, /* R16760 */ + { 0x0000, 0x0000, 0x0000 }, /* R16761 */ + { 0x0000, 0x0000, 0x0000 }, /* R16762 */ + { 0x0000, 0x0000, 0x0000 }, /* R16763 */ + { 0x0000, 0x0000, 0x0000 }, /* R16764 */ + { 0x0000, 0x0000, 0x0000 }, /* R16765 */ + { 0x0000, 0x0000, 0x0000 }, /* R16766 */ + { 0x0000, 0x0000, 0x0000 }, /* R16767 */ + { 0x0000, 0x0000, 0x0000 }, /* R16768 */ + { 0x0000, 0x0000, 0x0000 }, /* R16769 */ + { 0x0000, 0x0000, 0x0000 }, /* R16770 */ + { 0x0000, 0x0000, 0x0000 }, /* R16771 */ + { 0x0000, 0x0000, 0x0000 }, /* R16772 */ + { 0x0000, 0x0000, 0x0000 }, /* R16773 */ + { 0x0000, 0x0000, 0x0000 }, /* R16774 */ + { 0x0000, 0x0000, 0x0000 }, /* R16775 */ + { 0x0000, 0x0000, 0x0000 }, /* R16776 */ + { 0x0000, 0x0000, 0x0000 }, /* R16777 */ + { 0x0000, 0x0000, 0x0000 }, /* R16778 */ + { 0x0000, 0x0000, 0x0000 }, /* R16779 */ + { 0x0000, 0x0000, 0x0000 }, /* R16780 */ + { 0x0000, 0x0000, 0x0000 }, /* R16781 */ + { 0x0000, 0x0000, 0x0000 }, /* R16782 */ + { 0x0000, 0x0000, 0x0000 }, /* R16783 */ + { 0x0000, 0x0000, 0x0000 }, /* R16784 */ + { 0x0000, 0x0000, 0x0000 }, /* R16785 */ + { 0x0000, 0x0000, 0x0000 }, /* R16786 */ + { 0x0000, 0x0000, 0x0000 }, /* R16787 */ + { 0x0000, 0x0000, 0x0000 }, /* R16788 */ + { 0x0000, 0x0000, 0x0000 }, /* R16789 */ + { 0x0000, 0x0000, 0x0000 }, /* R16790 */ + { 0x0000, 0x0000, 0x0000 }, /* R16791 */ + { 0x0000, 0x0000, 0x0000 }, /* R16792 */ + { 0x0000, 0x0000, 0x0000 }, /* R16793 */ + { 0x0000, 0x0000, 0x0000 }, /* R16794 */ + { 0x0000, 0x0000, 0x0000 }, /* R16795 */ + { 0x0000, 0x0000, 0x0000 }, /* R16796 */ + { 0x0000, 0x0000, 0x0000 }, /* R16797 */ + { 0x0000, 0x0000, 0x0000 }, /* R16798 */ + { 0x0000, 0x0000, 0x0000 }, /* R16799 */ + { 0x0000, 0x0000, 0x0000 }, /* R16800 */ + { 0x0000, 0x0000, 0x0000 }, /* R16801 */ + { 0x0000, 0x0000, 0x0000 }, /* R16802 */ + { 0x0000, 0x0000, 0x0000 }, /* R16803 */ + { 0x0000, 0x0000, 0x0000 }, /* R16804 */ + { 0x0000, 0x0000, 0x0000 }, /* R16805 */ + { 0x0000, 0x0000, 0x0000 }, /* R16806 */ + { 0x0000, 0x0000, 0x0000 }, /* R16807 */ + { 0x0000, 0x0000, 0x0000 }, /* R16808 */ + { 0x0000, 0x0000, 0x0000 }, /* R16809 */ + { 0x0000, 0x0000, 0x0000 }, /* R16810 */ + { 0x0000, 0x0000, 0x0000 }, /* R16811 */ + { 0x0000, 0x0000, 0x0000 }, /* R16812 */ + { 0x0000, 0x0000, 0x0000 }, /* R16813 */ + { 0x0000, 0x0000, 0x0000 }, /* R16814 */ + { 0x0000, 0x0000, 0x0000 }, /* R16815 */ + { 0x0000, 0x0000, 0x0000 }, /* R16816 */ + { 0x0000, 0x0000, 0x0000 }, /* R16817 */ + { 0x0000, 0x0000, 0x0000 }, /* R16818 */ + { 0x0000, 0x0000, 0x0000 }, /* R16819 */ + { 0x0000, 0x0000, 0x0000 }, /* R16820 */ + { 0x0000, 0x0000, 0x0000 }, /* R16821 */ + { 0x0000, 0x0000, 0x0000 }, /* R16822 */ + { 0x0000, 0x0000, 0x0000 }, /* R16823 */ + { 0x0000, 0x0000, 0x0000 }, /* R16824 */ + { 0x0000, 0x0000, 0x0000 }, /* R16825 */ + { 0x0000, 0x0000, 0x0000 }, /* R16826 */ + { 0x0000, 0x0000, 0x0000 }, /* R16827 */ + { 0x0000, 0x0000, 0x0000 }, /* R16828 */ + { 0x0000, 0x0000, 0x0000 }, /* R16829 */ + { 0x0000, 0x0000, 0x0000 }, /* R16830 */ + { 0x0000, 0x0000, 0x0000 }, /* R16831 */ + { 0x0000, 0x0000, 0x0000 }, /* R16832 */ + { 0x0000, 0x0000, 0x0000 }, /* R16833 */ + { 0x0000, 0x0000, 0x0000 }, /* R16834 */ + { 0x0000, 0x0000, 0x0000 }, /* R16835 */ + { 0x0000, 0x0000, 0x0000 }, /* R16836 */ + { 0x0000, 0x0000, 0x0000 }, /* R16837 */ + { 0x0000, 0x0000, 0x0000 }, /* R16838 */ + { 0x0000, 0x0000, 0x0000 }, /* R16839 */ + { 0x0000, 0x0000, 0x0000 }, /* R16840 */ + { 0x0000, 0x0000, 0x0000 }, /* R16841 */ + { 0x0000, 0x0000, 0x0000 }, /* R16842 */ + { 0x0000, 0x0000, 0x0000 }, /* R16843 */ + { 0x0000, 0x0000, 0x0000 }, /* R16844 */ + { 0x0000, 0x0000, 0x0000 }, /* R16845 */ + { 0x0000, 0x0000, 0x0000 }, /* R16846 */ + { 0x0000, 0x0000, 0x0000 }, /* R16847 */ + { 0x0000, 0x0000, 0x0000 }, /* R16848 */ + { 0x0000, 0x0000, 0x0000 }, /* R16849 */ + { 0x0000, 0x0000, 0x0000 }, /* R16850 */ + { 0x0000, 0x0000, 0x0000 }, /* R16851 */ + { 0x0000, 0x0000, 0x0000 }, /* R16852 */ + { 0x0000, 0x0000, 0x0000 }, /* R16853 */ + { 0x0000, 0x0000, 0x0000 }, /* R16854 */ + { 0x0000, 0x0000, 0x0000 }, /* R16855 */ + { 0x0000, 0x0000, 0x0000 }, /* R16856 */ + { 0x0000, 0x0000, 0x0000 }, /* R16857 */ + { 0x0000, 0x0000, 0x0000 }, /* R16858 */ + { 0x0000, 0x0000, 0x0000 }, /* R16859 */ + { 0x0000, 0x0000, 0x0000 }, /* R16860 */ + { 0x0000, 0x0000, 0x0000 }, /* R16861 */ + { 0x0000, 0x0000, 0x0000 }, /* R16862 */ + { 0x0000, 0x0000, 0x0000 }, /* R16863 */ + { 0x0000, 0x0000, 0x0000 }, /* R16864 */ + { 0x0000, 0x0000, 0x0000 }, /* R16865 */ + { 0x0000, 0x0000, 0x0000 }, /* R16866 */ + { 0x0000, 0x0000, 0x0000 }, /* R16867 */ + { 0x0000, 0x0000, 0x0000 }, /* R16868 */ + { 0x0000, 0x0000, 0x0000 }, /* R16869 */ + { 0x0000, 0x0000, 0x0000 }, /* R16870 */ + { 0x0000, 0x0000, 0x0000 }, /* R16871 */ + { 0x0000, 0x0000, 0x0000 }, /* R16872 */ + { 0x0000, 0x0000, 0x0000 }, /* R16873 */ + { 0x0000, 0x0000, 0x0000 }, /* R16874 */ + { 0x0000, 0x0000, 0x0000 }, /* R16875 */ + { 0x0000, 0x0000, 0x0000 }, /* R16876 */ + { 0x0000, 0x0000, 0x0000 }, /* R16877 */ + { 0x0000, 0x0000, 0x0000 }, /* R16878 */ + { 0x0000, 0x0000, 0x0000 }, /* R16879 */ + { 0x0000, 0x0000, 0x0000 }, /* R16880 */ + { 0x0000, 0x0000, 0x0000 }, /* R16881 */ + { 0x0000, 0x0000, 0x0000 }, /* R16882 */ + { 0x0000, 0x0000, 0x0000 }, /* R16883 */ + { 0x0000, 0x0000, 0x0000 }, /* R16884 */ + { 0x0000, 0x0000, 0x0000 }, /* R16885 */ + { 0x0000, 0x0000, 0x0000 }, /* R16886 */ + { 0x0000, 0x0000, 0x0000 }, /* R16887 */ + { 0x0000, 0x0000, 0x0000 }, /* R16888 */ + { 0x0000, 0x0000, 0x0000 }, /* R16889 */ + { 0x0000, 0x0000, 0x0000 }, /* R16890 */ + { 0x0000, 0x0000, 0x0000 }, /* R16891 */ + { 0x0000, 0x0000, 0x0000 }, /* R16892 */ + { 0x0000, 0x0000, 0x0000 }, /* R16893 */ + { 0x0000, 0x0000, 0x0000 }, /* R16894 */ + { 0x0000, 0x0000, 0x0000 }, /* R16895 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16896 - HDBASS_AI_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16897 - HDBASS_AI_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16898 - HDBASS_AR_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16899 - HDBASS_AR_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16900 - HDBASS_B_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16901 - HDBASS_B_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16902 - HDBASS_K_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16903 - HDBASS_K_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16904 - HDBASS_N1_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16905 - HDBASS_N1_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16906 - HDBASS_N2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16907 - HDBASS_N2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16908 - HDBASS_N3_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16909 - HDBASS_N3_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16910 - HDBASS_N4_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16911 - HDBASS_N4_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16912 - HDBASS_N5_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16913 - HDBASS_N5_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16914 - HDBASS_X1_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16915 - HDBASS_X1_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16916 - HDBASS_X2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16917 - HDBASS_X2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16918 - HDBASS_X3_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16919 - HDBASS_X3_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16920 - HDBASS_ATK_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16921 - HDBASS_ATK_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16922 - HDBASS_DCY_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16923 - HDBASS_DCY_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R16924 - HDBASS_PG_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R16925 - HDBASS_PG_0 */ + { 0x0000, 0x0000, 0x0000 }, /* R16926 */ + { 0x0000, 0x0000, 0x0000 }, /* R16927 */ + { 0x0000, 0x0000, 0x0000 }, /* R16928 */ + { 0x0000, 0x0000, 0x0000 }, /* R16929 */ + { 0x0000, 0x0000, 0x0000 }, /* R16930 */ + { 0x0000, 0x0000, 0x0000 }, /* R16931 */ + { 0x0000, 0x0000, 0x0000 }, /* R16932 */ + { 0x0000, 0x0000, 0x0000 }, /* R16933 */ + { 0x0000, 0x0000, 0x0000 }, /* R16934 */ + { 0x0000, 0x0000, 0x0000 }, /* R16935 */ + { 0x0000, 0x0000, 0x0000 }, /* R16936 */ + { 0x0000, 0x0000, 0x0000 }, /* R16937 */ + { 0x0000, 0x0000, 0x0000 }, /* R16938 */ + { 0x0000, 0x0000, 0x0000 }, /* R16939 */ + { 0x0000, 0x0000, 0x0000 }, /* R16940 */ + { 0x0000, 0x0000, 0x0000 }, /* R16941 */ + { 0x0000, 0x0000, 0x0000 }, /* R16942 */ + { 0x0000, 0x0000, 0x0000 }, /* R16943 */ + { 0x0000, 0x0000, 0x0000 }, /* R16944 */ + { 0x0000, 0x0000, 0x0000 }, /* R16945 */ + { 0x0000, 0x0000, 0x0000 }, /* R16946 */ + { 0x0000, 0x0000, 0x0000 }, /* R16947 */ + { 0x0000, 0x0000, 0x0000 }, /* R16948 */ + { 0x0000, 0x0000, 0x0000 }, /* R16949 */ + { 0x0000, 0x0000, 0x0000 }, /* R16950 */ + { 0x0000, 0x0000, 0x0000 }, /* R16951 */ + { 0x0000, 0x0000, 0x0000 }, /* R16952 */ + { 0x0000, 0x0000, 0x0000 }, /* R16953 */ + { 0x0000, 0x0000, 0x0000 }, /* R16954 */ + { 0x0000, 0x0000, 0x0000 }, /* R16955 */ + { 0x0000, 0x0000, 0x0000 }, /* R16956 */ + { 0x0000, 0x0000, 0x0000 }, /* R16957 */ + { 0x0000, 0x0000, 0x0000 }, /* R16958 */ + { 0x0000, 0x0000, 0x0000 }, /* R16959 */ + { 0x0000, 0x0000, 0x0000 }, /* R16960 */ + { 0x0000, 0x0000, 0x0000 }, /* R16961 */ + { 0x0000, 0x0000, 0x0000 }, /* R16962 */ + { 0x0000, 0x0000, 0x0000 }, /* R16963 */ + { 0x0000, 0x0000, 0x0000 }, /* R16964 */ + { 0x0000, 0x0000, 0x0000 }, /* R16965 */ + { 0x0000, 0x0000, 0x0000 }, /* R16966 */ + { 0x0000, 0x0000, 0x0000 }, /* R16967 */ + { 0x0000, 0x0000, 0x0000 }, /* R16968 */ + { 0x0000, 0x0000, 0x0000 }, /* R16969 */ + { 0x0000, 0x0000, 0x0000 }, /* R16970 */ + { 0x0000, 0x0000, 0x0000 }, /* R16971 */ + { 0x0000, 0x0000, 0x0000 }, /* R16972 */ + { 0x0000, 0x0000, 0x0000 }, /* R16973 */ + { 0x0000, 0x0000, 0x0000 }, /* R16974 */ + { 0x0000, 0x0000, 0x0000 }, /* R16975 */ + { 0x0000, 0x0000, 0x0000 }, /* R16976 */ + { 0x0000, 0x0000, 0x0000 }, /* R16977 */ + { 0x0000, 0x0000, 0x0000 }, /* R16978 */ + { 0x0000, 0x0000, 0x0000 }, /* R16979 */ + { 0x0000, 0x0000, 0x0000 }, /* R16980 */ + { 0x0000, 0x0000, 0x0000 }, /* R16981 */ + { 0x0000, 0x0000, 0x0000 }, /* R16982 */ + { 0x0000, 0x0000, 0x0000 }, /* R16983 */ + { 0x0000, 0x0000, 0x0000 }, /* R16984 */ + { 0x0000, 0x0000, 0x0000 }, /* R16985 */ + { 0x0000, 0x0000, 0x0000 }, /* R16986 */ + { 0x0000, 0x0000, 0x0000 }, /* R16987 */ + { 0x0000, 0x0000, 0x0000 }, /* R16988 */ + { 0x0000, 0x0000, 0x0000 }, /* R16989 */ + { 0x0000, 0x0000, 0x0000 }, /* R16990 */ + { 0x0000, 0x0000, 0x0000 }, /* R16991 */ + { 0x0000, 0x0000, 0x0000 }, /* R16992 */ + { 0x0000, 0x0000, 0x0000 }, /* R16993 */ + { 0x0000, 0x0000, 0x0000 }, /* R16994 */ + { 0x0000, 0x0000, 0x0000 }, /* R16995 */ + { 0x0000, 0x0000, 0x0000 }, /* R16996 */ + { 0x0000, 0x0000, 0x0000 }, /* R16997 */ + { 0x0000, 0x0000, 0x0000 }, /* R16998 */ + { 0x0000, 0x0000, 0x0000 }, /* R16999 */ + { 0x0000, 0x0000, 0x0000 }, /* R17000 */ + { 0x0000, 0x0000, 0x0000 }, /* R17001 */ + { 0x0000, 0x0000, 0x0000 }, /* R17002 */ + { 0x0000, 0x0000, 0x0000 }, /* R17003 */ + { 0x0000, 0x0000, 0x0000 }, /* R17004 */ + { 0x0000, 0x0000, 0x0000 }, /* R17005 */ + { 0x0000, 0x0000, 0x0000 }, /* R17006 */ + { 0x0000, 0x0000, 0x0000 }, /* R17007 */ + { 0x0000, 0x0000, 0x0000 }, /* R17008 */ + { 0x0000, 0x0000, 0x0000 }, /* R17009 */ + { 0x0000, 0x0000, 0x0000 }, /* R17010 */ + { 0x0000, 0x0000, 0x0000 }, /* R17011 */ + { 0x0000, 0x0000, 0x0000 }, /* R17012 */ + { 0x0000, 0x0000, 0x0000 }, /* R17013 */ + { 0x0000, 0x0000, 0x0000 }, /* R17014 */ + { 0x0000, 0x0000, 0x0000 }, /* R17015 */ + { 0x0000, 0x0000, 0x0000 }, /* R17016 */ + { 0x0000, 0x0000, 0x0000 }, /* R17017 */ + { 0x0000, 0x0000, 0x0000 }, /* R17018 */ + { 0x0000, 0x0000, 0x0000 }, /* R17019 */ + { 0x0000, 0x0000, 0x0000 }, /* R17020 */ + { 0x0000, 0x0000, 0x0000 }, /* R17021 */ + { 0x0000, 0x0000, 0x0000 }, /* R17022 */ + { 0x0000, 0x0000, 0x0000 }, /* R17023 */ + { 0x0000, 0x0000, 0x0000 }, /* R17024 */ + { 0x0000, 0x0000, 0x0000 }, /* R17025 */ + { 0x0000, 0x0000, 0x0000 }, /* R17026 */ + { 0x0000, 0x0000, 0x0000 }, /* R17027 */ + { 0x0000, 0x0000, 0x0000 }, /* R17028 */ + { 0x0000, 0x0000, 0x0000 }, /* R17029 */ + { 0x0000, 0x0000, 0x0000 }, /* R17030 */ + { 0x0000, 0x0000, 0x0000 }, /* R17031 */ + { 0x0000, 0x0000, 0x0000 }, /* R17032 */ + { 0x0000, 0x0000, 0x0000 }, /* R17033 */ + { 0x0000, 0x0000, 0x0000 }, /* R17034 */ + { 0x0000, 0x0000, 0x0000 }, /* R17035 */ + { 0x0000, 0x0000, 0x0000 }, /* R17036 */ + { 0x0000, 0x0000, 0x0000 }, /* R17037 */ + { 0x0000, 0x0000, 0x0000 }, /* R17038 */ + { 0x0000, 0x0000, 0x0000 }, /* R17039 */ + { 0x0000, 0x0000, 0x0000 }, /* R17040 */ + { 0x0000, 0x0000, 0x0000 }, /* R17041 */ + { 0x0000, 0x0000, 0x0000 }, /* R17042 */ + { 0x0000, 0x0000, 0x0000 }, /* R17043 */ + { 0x0000, 0x0000, 0x0000 }, /* R17044 */ + { 0x0000, 0x0000, 0x0000 }, /* R17045 */ + { 0x0000, 0x0000, 0x0000 }, /* R17046 */ + { 0x0000, 0x0000, 0x0000 }, /* R17047 */ + { 0x0000, 0x0000, 0x0000 }, /* R17048 */ + { 0x0000, 0x0000, 0x0000 }, /* R17049 */ + { 0x0000, 0x0000, 0x0000 }, /* R17050 */ + { 0x0000, 0x0000, 0x0000 }, /* R17051 */ + { 0x0000, 0x0000, 0x0000 }, /* R17052 */ + { 0x0000, 0x0000, 0x0000 }, /* R17053 */ + { 0x0000, 0x0000, 0x0000 }, /* R17054 */ + { 0x0000, 0x0000, 0x0000 }, /* R17055 */ + { 0x0000, 0x0000, 0x0000 }, /* R17056 */ + { 0x0000, 0x0000, 0x0000 }, /* R17057 */ + { 0x0000, 0x0000, 0x0000 }, /* R17058 */ + { 0x0000, 0x0000, 0x0000 }, /* R17059 */ + { 0x0000, 0x0000, 0x0000 }, /* R17060 */ + { 0x0000, 0x0000, 0x0000 }, /* R17061 */ + { 0x0000, 0x0000, 0x0000 }, /* R17062 */ + { 0x0000, 0x0000, 0x0000 }, /* R17063 */ + { 0x0000, 0x0000, 0x0000 }, /* R17064 */ + { 0x0000, 0x0000, 0x0000 }, /* R17065 */ + { 0x0000, 0x0000, 0x0000 }, /* R17066 */ + { 0x0000, 0x0000, 0x0000 }, /* R17067 */ + { 0x0000, 0x0000, 0x0000 }, /* R17068 */ + { 0x0000, 0x0000, 0x0000 }, /* R17069 */ + { 0x0000, 0x0000, 0x0000 }, /* R17070 */ + { 0x0000, 0x0000, 0x0000 }, /* R17071 */ + { 0x0000, 0x0000, 0x0000 }, /* R17072 */ + { 0x0000, 0x0000, 0x0000 }, /* R17073 */ + { 0x0000, 0x0000, 0x0000 }, /* R17074 */ + { 0x0000, 0x0000, 0x0000 }, /* R17075 */ + { 0x0000, 0x0000, 0x0000 }, /* R17076 */ + { 0x0000, 0x0000, 0x0000 }, /* R17077 */ + { 0x0000, 0x0000, 0x0000 }, /* R17078 */ + { 0x0000, 0x0000, 0x0000 }, /* R17079 */ + { 0x0000, 0x0000, 0x0000 }, /* R17080 */ + { 0x0000, 0x0000, 0x0000 }, /* R17081 */ + { 0x0000, 0x0000, 0x0000 }, /* R17082 */ + { 0x0000, 0x0000, 0x0000 }, /* R17083 */ + { 0x0000, 0x0000, 0x0000 }, /* R17084 */ + { 0x0000, 0x0000, 0x0000 }, /* R17085 */ + { 0x0000, 0x0000, 0x0000 }, /* R17086 */ + { 0x0000, 0x0000, 0x0000 }, /* R17087 */ + { 0x0000, 0x0000, 0x0000 }, /* R17088 */ + { 0x0000, 0x0000, 0x0000 }, /* R17089 */ + { 0x0000, 0x0000, 0x0000 }, /* R17090 */ + { 0x0000, 0x0000, 0x0000 }, /* R17091 */ + { 0x0000, 0x0000, 0x0000 }, /* R17092 */ + { 0x0000, 0x0000, 0x0000 }, /* R17093 */ + { 0x0000, 0x0000, 0x0000 }, /* R17094 */ + { 0x0000, 0x0000, 0x0000 }, /* R17095 */ + { 0x0000, 0x0000, 0x0000 }, /* R17096 */ + { 0x0000, 0x0000, 0x0000 }, /* R17097 */ + { 0x0000, 0x0000, 0x0000 }, /* R17098 */ + { 0x0000, 0x0000, 0x0000 }, /* R17099 */ + { 0x0000, 0x0000, 0x0000 }, /* R17100 */ + { 0x0000, 0x0000, 0x0000 }, /* R17101 */ + { 0x0000, 0x0000, 0x0000 }, /* R17102 */ + { 0x0000, 0x0000, 0x0000 }, /* R17103 */ + { 0x0000, 0x0000, 0x0000 }, /* R17104 */ + { 0x0000, 0x0000, 0x0000 }, /* R17105 */ + { 0x0000, 0x0000, 0x0000 }, /* R17106 */ + { 0x0000, 0x0000, 0x0000 }, /* R17107 */ + { 0x0000, 0x0000, 0x0000 }, /* R17108 */ + { 0x0000, 0x0000, 0x0000 }, /* R17109 */ + { 0x0000, 0x0000, 0x0000 }, /* R17110 */ + { 0x0000, 0x0000, 0x0000 }, /* R17111 */ + { 0x0000, 0x0000, 0x0000 }, /* R17112 */ + { 0x0000, 0x0000, 0x0000 }, /* R17113 */ + { 0x0000, 0x0000, 0x0000 }, /* R17114 */ + { 0x0000, 0x0000, 0x0000 }, /* R17115 */ + { 0x0000, 0x0000, 0x0000 }, /* R17116 */ + { 0x0000, 0x0000, 0x0000 }, /* R17117 */ + { 0x0000, 0x0000, 0x0000 }, /* R17118 */ + { 0x0000, 0x0000, 0x0000 }, /* R17119 */ + { 0x0000, 0x0000, 0x0000 }, /* R17120 */ + { 0x0000, 0x0000, 0x0000 }, /* R17121 */ + { 0x0000, 0x0000, 0x0000 }, /* R17122 */ + { 0x0000, 0x0000, 0x0000 }, /* R17123 */ + { 0x0000, 0x0000, 0x0000 }, /* R17124 */ + { 0x0000, 0x0000, 0x0000 }, /* R17125 */ + { 0x0000, 0x0000, 0x0000 }, /* R17126 */ + { 0x0000, 0x0000, 0x0000 }, /* R17127 */ + { 0x0000, 0x0000, 0x0000 }, /* R17128 */ + { 0x0000, 0x0000, 0x0000 }, /* R17129 */ + { 0x0000, 0x0000, 0x0000 }, /* R17130 */ + { 0x0000, 0x0000, 0x0000 }, /* R17131 */ + { 0x0000, 0x0000, 0x0000 }, /* R17132 */ + { 0x0000, 0x0000, 0x0000 }, /* R17133 */ + { 0x0000, 0x0000, 0x0000 }, /* R17134 */ + { 0x0000, 0x0000, 0x0000 }, /* R17135 */ + { 0x0000, 0x0000, 0x0000 }, /* R17136 */ + { 0x0000, 0x0000, 0x0000 }, /* R17137 */ + { 0x0000, 0x0000, 0x0000 }, /* R17138 */ + { 0x0000, 0x0000, 0x0000 }, /* R17139 */ + { 0x0000, 0x0000, 0x0000 }, /* R17140 */ + { 0x0000, 0x0000, 0x0000 }, /* R17141 */ + { 0x0000, 0x0000, 0x0000 }, /* R17142 */ + { 0x0000, 0x0000, 0x0000 }, /* R17143 */ + { 0x0000, 0x0000, 0x0000 }, /* R17144 */ + { 0x0000, 0x0000, 0x0000 }, /* R17145 */ + { 0x0000, 0x0000, 0x0000 }, /* R17146 */ + { 0x0000, 0x0000, 0x0000 }, /* R17147 */ + { 0x0000, 0x0000, 0x0000 }, /* R17148 */ + { 0x0000, 0x0000, 0x0000 }, /* R17149 */ + { 0x0000, 0x0000, 0x0000 }, /* R17150 */ + { 0x0000, 0x0000, 0x0000 }, /* R17151 */ + { 0x0000, 0x0000, 0x0000 }, /* R17152 */ + { 0x0000, 0x0000, 0x0000 }, /* R17153 */ + { 0x0000, 0x0000, 0x0000 }, /* R17154 */ + { 0x0000, 0x0000, 0x0000 }, /* R17155 */ + { 0x0000, 0x0000, 0x0000 }, /* R17156 */ + { 0x0000, 0x0000, 0x0000 }, /* R17157 */ + { 0x0000, 0x0000, 0x0000 }, /* R17158 */ + { 0x0000, 0x0000, 0x0000 }, /* R17159 */ + { 0x0000, 0x0000, 0x0000 }, /* R17160 */ + { 0x0000, 0x0000, 0x0000 }, /* R17161 */ + { 0x0000, 0x0000, 0x0000 }, /* R17162 */ + { 0x0000, 0x0000, 0x0000 }, /* R17163 */ + { 0x0000, 0x0000, 0x0000 }, /* R17164 */ + { 0x0000, 0x0000, 0x0000 }, /* R17165 */ + { 0x0000, 0x0000, 0x0000 }, /* R17166 */ + { 0x0000, 0x0000, 0x0000 }, /* R17167 */ + { 0x0000, 0x0000, 0x0000 }, /* R17168 */ + { 0x0000, 0x0000, 0x0000 }, /* R17169 */ + { 0x0000, 0x0000, 0x0000 }, /* R17170 */ + { 0x0000, 0x0000, 0x0000 }, /* R17171 */ + { 0x0000, 0x0000, 0x0000 }, /* R17172 */ + { 0x0000, 0x0000, 0x0000 }, /* R17173 */ + { 0x0000, 0x0000, 0x0000 }, /* R17174 */ + { 0x0000, 0x0000, 0x0000 }, /* R17175 */ + { 0x0000, 0x0000, 0x0000 }, /* R17176 */ + { 0x0000, 0x0000, 0x0000 }, /* R17177 */ + { 0x0000, 0x0000, 0x0000 }, /* R17178 */ + { 0x0000, 0x0000, 0x0000 }, /* R17179 */ + { 0x0000, 0x0000, 0x0000 }, /* R17180 */ + { 0x0000, 0x0000, 0x0000 }, /* R17181 */ + { 0x0000, 0x0000, 0x0000 }, /* R17182 */ + { 0x0000, 0x0000, 0x0000 }, /* R17183 */ + { 0x0000, 0x0000, 0x0000 }, /* R17184 */ + { 0x0000, 0x0000, 0x0000 }, /* R17185 */ + { 0x0000, 0x0000, 0x0000 }, /* R17186 */ + { 0x0000, 0x0000, 0x0000 }, /* R17187 */ + { 0x0000, 0x0000, 0x0000 }, /* R17188 */ + { 0x0000, 0x0000, 0x0000 }, /* R17189 */ + { 0x0000, 0x0000, 0x0000 }, /* R17190 */ + { 0x0000, 0x0000, 0x0000 }, /* R17191 */ + { 0x0000, 0x0000, 0x0000 }, /* R17192 */ + { 0x0000, 0x0000, 0x0000 }, /* R17193 */ + { 0x0000, 0x0000, 0x0000 }, /* R17194 */ + { 0x0000, 0x0000, 0x0000 }, /* R17195 */ + { 0x0000, 0x0000, 0x0000 }, /* R17196 */ + { 0x0000, 0x0000, 0x0000 }, /* R17197 */ + { 0x0000, 0x0000, 0x0000 }, /* R17198 */ + { 0x0000, 0x0000, 0x0000 }, /* R17199 */ + { 0x0000, 0x0000, 0x0000 }, /* R17200 */ + { 0x0000, 0x0000, 0x0000 }, /* R17201 */ + { 0x0000, 0x0000, 0x0000 }, /* R17202 */ + { 0x0000, 0x0000, 0x0000 }, /* R17203 */ + { 0x0000, 0x0000, 0x0000 }, /* R17204 */ + { 0x0000, 0x0000, 0x0000 }, /* R17205 */ + { 0x0000, 0x0000, 0x0000 }, /* R17206 */ + { 0x0000, 0x0000, 0x0000 }, /* R17207 */ + { 0x0000, 0x0000, 0x0000 }, /* R17208 */ + { 0x0000, 0x0000, 0x0000 }, /* R17209 */ + { 0x0000, 0x0000, 0x0000 }, /* R17210 */ + { 0x0000, 0x0000, 0x0000 }, /* R17211 */ + { 0x0000, 0x0000, 0x0000 }, /* R17212 */ + { 0x0000, 0x0000, 0x0000 }, /* R17213 */ + { 0x0000, 0x0000, 0x0000 }, /* R17214 */ + { 0x0000, 0x0000, 0x0000 }, /* R17215 */ + { 0x0000, 0x0000, 0x0000 }, /* R17216 */ + { 0x0000, 0x0000, 0x0000 }, /* R17217 */ + { 0x0000, 0x0000, 0x0000 }, /* R17218 */ + { 0x0000, 0x0000, 0x0000 }, /* R17219 */ + { 0x0000, 0x0000, 0x0000 }, /* R17220 */ + { 0x0000, 0x0000, 0x0000 }, /* R17221 */ + { 0x0000, 0x0000, 0x0000 }, /* R17222 */ + { 0x0000, 0x0000, 0x0000 }, /* R17223 */ + { 0x0000, 0x0000, 0x0000 }, /* R17224 */ + { 0x0000, 0x0000, 0x0000 }, /* R17225 */ + { 0x0000, 0x0000, 0x0000 }, /* R17226 */ + { 0x0000, 0x0000, 0x0000 }, /* R17227 */ + { 0x0000, 0x0000, 0x0000 }, /* R17228 */ + { 0x0000, 0x0000, 0x0000 }, /* R17229 */ + { 0x0000, 0x0000, 0x0000 }, /* R17230 */ + { 0x0000, 0x0000, 0x0000 }, /* R17231 */ + { 0x0000, 0x0000, 0x0000 }, /* R17232 */ + { 0x0000, 0x0000, 0x0000 }, /* R17233 */ + { 0x0000, 0x0000, 0x0000 }, /* R17234 */ + { 0x0000, 0x0000, 0x0000 }, /* R17235 */ + { 0x0000, 0x0000, 0x0000 }, /* R17236 */ + { 0x0000, 0x0000, 0x0000 }, /* R17237 */ + { 0x0000, 0x0000, 0x0000 }, /* R17238 */ + { 0x0000, 0x0000, 0x0000 }, /* R17239 */ + { 0x0000, 0x0000, 0x0000 }, /* R17240 */ + { 0x0000, 0x0000, 0x0000 }, /* R17241 */ + { 0x0000, 0x0000, 0x0000 }, /* R17242 */ + { 0x0000, 0x0000, 0x0000 }, /* R17243 */ + { 0x0000, 0x0000, 0x0000 }, /* R17244 */ + { 0x0000, 0x0000, 0x0000 }, /* R17245 */ + { 0x0000, 0x0000, 0x0000 }, /* R17246 */ + { 0x0000, 0x0000, 0x0000 }, /* R17247 */ + { 0x0000, 0x0000, 0x0000 }, /* R17248 */ + { 0x0000, 0x0000, 0x0000 }, /* R17249 */ + { 0x0000, 0x0000, 0x0000 }, /* R17250 */ + { 0x0000, 0x0000, 0x0000 }, /* R17251 */ + { 0x0000, 0x0000, 0x0000 }, /* R17252 */ + { 0x0000, 0x0000, 0x0000 }, /* R17253 */ + { 0x0000, 0x0000, 0x0000 }, /* R17254 */ + { 0x0000, 0x0000, 0x0000 }, /* R17255 */ + { 0x0000, 0x0000, 0x0000 }, /* R17256 */ + { 0x0000, 0x0000, 0x0000 }, /* R17257 */ + { 0x0000, 0x0000, 0x0000 }, /* R17258 */ + { 0x0000, 0x0000, 0x0000 }, /* R17259 */ + { 0x0000, 0x0000, 0x0000 }, /* R17260 */ + { 0x0000, 0x0000, 0x0000 }, /* R17261 */ + { 0x0000, 0x0000, 0x0000 }, /* R17262 */ + { 0x0000, 0x0000, 0x0000 }, /* R17263 */ + { 0x0000, 0x0000, 0x0000 }, /* R17264 */ + { 0x0000, 0x0000, 0x0000 }, /* R17265 */ + { 0x0000, 0x0000, 0x0000 }, /* R17266 */ + { 0x0000, 0x0000, 0x0000 }, /* R17267 */ + { 0x0000, 0x0000, 0x0000 }, /* R17268 */ + { 0x0000, 0x0000, 0x0000 }, /* R17269 */ + { 0x0000, 0x0000, 0x0000 }, /* R17270 */ + { 0x0000, 0x0000, 0x0000 }, /* R17271 */ + { 0x0000, 0x0000, 0x0000 }, /* R17272 */ + { 0x0000, 0x0000, 0x0000 }, /* R17273 */ + { 0x0000, 0x0000, 0x0000 }, /* R17274 */ + { 0x0000, 0x0000, 0x0000 }, /* R17275 */ + { 0x0000, 0x0000, 0x0000 }, /* R17276 */ + { 0x0000, 0x0000, 0x0000 }, /* R17277 */ + { 0x0000, 0x0000, 0x0000 }, /* R17278 */ + { 0x0000, 0x0000, 0x0000 }, /* R17279 */ + { 0x0000, 0x0000, 0x0000 }, /* R17280 */ + { 0x0000, 0x0000, 0x0000 }, /* R17281 */ + { 0x0000, 0x0000, 0x0000 }, /* R17282 */ + { 0x0000, 0x0000, 0x0000 }, /* R17283 */ + { 0x0000, 0x0000, 0x0000 }, /* R17284 */ + { 0x0000, 0x0000, 0x0000 }, /* R17285 */ + { 0x0000, 0x0000, 0x0000 }, /* R17286 */ + { 0x0000, 0x0000, 0x0000 }, /* R17287 */ + { 0x0000, 0x0000, 0x0000 }, /* R17288 */ + { 0x0000, 0x0000, 0x0000 }, /* R17289 */ + { 0x0000, 0x0000, 0x0000 }, /* R17290 */ + { 0x0000, 0x0000, 0x0000 }, /* R17291 */ + { 0x0000, 0x0000, 0x0000 }, /* R17292 */ + { 0x0000, 0x0000, 0x0000 }, /* R17293 */ + { 0x0000, 0x0000, 0x0000 }, /* R17294 */ + { 0x0000, 0x0000, 0x0000 }, /* R17295 */ + { 0x0000, 0x0000, 0x0000 }, /* R17296 */ + { 0x0000, 0x0000, 0x0000 }, /* R17297 */ + { 0x0000, 0x0000, 0x0000 }, /* R17298 */ + { 0x0000, 0x0000, 0x0000 }, /* R17299 */ + { 0x0000, 0x0000, 0x0000 }, /* R17300 */ + { 0x0000, 0x0000, 0x0000 }, /* R17301 */ + { 0x0000, 0x0000, 0x0000 }, /* R17302 */ + { 0x0000, 0x0000, 0x0000 }, /* R17303 */ + { 0x0000, 0x0000, 0x0000 }, /* R17304 */ + { 0x0000, 0x0000, 0x0000 }, /* R17305 */ + { 0x0000, 0x0000, 0x0000 }, /* R17306 */ + { 0x0000, 0x0000, 0x0000 }, /* R17307 */ + { 0x0000, 0x0000, 0x0000 }, /* R17308 */ + { 0x0000, 0x0000, 0x0000 }, /* R17309 */ + { 0x0000, 0x0000, 0x0000 }, /* R17310 */ + { 0x0000, 0x0000, 0x0000 }, /* R17311 */ + { 0x0000, 0x0000, 0x0000 }, /* R17312 */ + { 0x0000, 0x0000, 0x0000 }, /* R17313 */ + { 0x0000, 0x0000, 0x0000 }, /* R17314 */ + { 0x0000, 0x0000, 0x0000 }, /* R17315 */ + { 0x0000, 0x0000, 0x0000 }, /* R17316 */ + { 0x0000, 0x0000, 0x0000 }, /* R17317 */ + { 0x0000, 0x0000, 0x0000 }, /* R17318 */ + { 0x0000, 0x0000, 0x0000 }, /* R17319 */ + { 0x0000, 0x0000, 0x0000 }, /* R17320 */ + { 0x0000, 0x0000, 0x0000 }, /* R17321 */ + { 0x0000, 0x0000, 0x0000 }, /* R17322 */ + { 0x0000, 0x0000, 0x0000 }, /* R17323 */ + { 0x0000, 0x0000, 0x0000 }, /* R17324 */ + { 0x0000, 0x0000, 0x0000 }, /* R17325 */ + { 0x0000, 0x0000, 0x0000 }, /* R17326 */ + { 0x0000, 0x0000, 0x0000 }, /* R17327 */ + { 0x0000, 0x0000, 0x0000 }, /* R17328 */ + { 0x0000, 0x0000, 0x0000 }, /* R17329 */ + { 0x0000, 0x0000, 0x0000 }, /* R17330 */ + { 0x0000, 0x0000, 0x0000 }, /* R17331 */ + { 0x0000, 0x0000, 0x0000 }, /* R17332 */ + { 0x0000, 0x0000, 0x0000 }, /* R17333 */ + { 0x0000, 0x0000, 0x0000 }, /* R17334 */ + { 0x0000, 0x0000, 0x0000 }, /* R17335 */ + { 0x0000, 0x0000, 0x0000 }, /* R17336 */ + { 0x0000, 0x0000, 0x0000 }, /* R17337 */ + { 0x0000, 0x0000, 0x0000 }, /* R17338 */ + { 0x0000, 0x0000, 0x0000 }, /* R17339 */ + { 0x0000, 0x0000, 0x0000 }, /* R17340 */ + { 0x0000, 0x0000, 0x0000 }, /* R17341 */ + { 0x0000, 0x0000, 0x0000 }, /* R17342 */ + { 0x0000, 0x0000, 0x0000 }, /* R17343 */ + { 0x0000, 0x0000, 0x0000 }, /* R17344 */ + { 0x0000, 0x0000, 0x0000 }, /* R17345 */ + { 0x0000, 0x0000, 0x0000 }, /* R17346 */ + { 0x0000, 0x0000, 0x0000 }, /* R17347 */ + { 0x0000, 0x0000, 0x0000 }, /* R17348 */ + { 0x0000, 0x0000, 0x0000 }, /* R17349 */ + { 0x0000, 0x0000, 0x0000 }, /* R17350 */ + { 0x0000, 0x0000, 0x0000 }, /* R17351 */ + { 0x0000, 0x0000, 0x0000 }, /* R17352 */ + { 0x0000, 0x0000, 0x0000 }, /* R17353 */ + { 0x0000, 0x0000, 0x0000 }, /* R17354 */ + { 0x0000, 0x0000, 0x0000 }, /* R17355 */ + { 0x0000, 0x0000, 0x0000 }, /* R17356 */ + { 0x0000, 0x0000, 0x0000 }, /* R17357 */ + { 0x0000, 0x0000, 0x0000 }, /* R17358 */ + { 0x0000, 0x0000, 0x0000 }, /* R17359 */ + { 0x0000, 0x0000, 0x0000 }, /* R17360 */ + { 0x0000, 0x0000, 0x0000 }, /* R17361 */ + { 0x0000, 0x0000, 0x0000 }, /* R17362 */ + { 0x0000, 0x0000, 0x0000 }, /* R17363 */ + { 0x0000, 0x0000, 0x0000 }, /* R17364 */ + { 0x0000, 0x0000, 0x0000 }, /* R17365 */ + { 0x0000, 0x0000, 0x0000 }, /* R17366 */ + { 0x0000, 0x0000, 0x0000 }, /* R17367 */ + { 0x0000, 0x0000, 0x0000 }, /* R17368 */ + { 0x0000, 0x0000, 0x0000 }, /* R17369 */ + { 0x0000, 0x0000, 0x0000 }, /* R17370 */ + { 0x0000, 0x0000, 0x0000 }, /* R17371 */ + { 0x0000, 0x0000, 0x0000 }, /* R17372 */ + { 0x0000, 0x0000, 0x0000 }, /* R17373 */ + { 0x0000, 0x0000, 0x0000 }, /* R17374 */ + { 0x0000, 0x0000, 0x0000 }, /* R17375 */ + { 0x0000, 0x0000, 0x0000 }, /* R17376 */ + { 0x0000, 0x0000, 0x0000 }, /* R17377 */ + { 0x0000, 0x0000, 0x0000 }, /* R17378 */ + { 0x0000, 0x0000, 0x0000 }, /* R17379 */ + { 0x0000, 0x0000, 0x0000 }, /* R17380 */ + { 0x0000, 0x0000, 0x0000 }, /* R17381 */ + { 0x0000, 0x0000, 0x0000 }, /* R17382 */ + { 0x0000, 0x0000, 0x0000 }, /* R17383 */ + { 0x0000, 0x0000, 0x0000 }, /* R17384 */ + { 0x0000, 0x0000, 0x0000 }, /* R17385 */ + { 0x0000, 0x0000, 0x0000 }, /* R17386 */ + { 0x0000, 0x0000, 0x0000 }, /* R17387 */ + { 0x0000, 0x0000, 0x0000 }, /* R17388 */ + { 0x0000, 0x0000, 0x0000 }, /* R17389 */ + { 0x0000, 0x0000, 0x0000 }, /* R17390 */ + { 0x0000, 0x0000, 0x0000 }, /* R17391 */ + { 0x0000, 0x0000, 0x0000 }, /* R17392 */ + { 0x0000, 0x0000, 0x0000 }, /* R17393 */ + { 0x0000, 0x0000, 0x0000 }, /* R17394 */ + { 0x0000, 0x0000, 0x0000 }, /* R17395 */ + { 0x0000, 0x0000, 0x0000 }, /* R17396 */ + { 0x0000, 0x0000, 0x0000 }, /* R17397 */ + { 0x0000, 0x0000, 0x0000 }, /* R17398 */ + { 0x0000, 0x0000, 0x0000 }, /* R17399 */ + { 0x0000, 0x0000, 0x0000 }, /* R17400 */ + { 0x0000, 0x0000, 0x0000 }, /* R17401 */ + { 0x0000, 0x0000, 0x0000 }, /* R17402 */ + { 0x0000, 0x0000, 0x0000 }, /* R17403 */ + { 0x0000, 0x0000, 0x0000 }, /* R17404 */ + { 0x0000, 0x0000, 0x0000 }, /* R17405 */ + { 0x0000, 0x0000, 0x0000 }, /* R17406 */ + { 0x0000, 0x0000, 0x0000 }, /* R17407 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17408 - HPF_C_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17409 - HPF_C_0 */ + { 0x0000, 0x0000, 0x0000 }, /* R17410 */ + { 0x0000, 0x0000, 0x0000 }, /* R17411 */ + { 0x0000, 0x0000, 0x0000 }, /* R17412 */ + { 0x0000, 0x0000, 0x0000 }, /* R17413 */ + { 0x0000, 0x0000, 0x0000 }, /* R17414 */ + { 0x0000, 0x0000, 0x0000 }, /* R17415 */ + { 0x0000, 0x0000, 0x0000 }, /* R17416 */ + { 0x0000, 0x0000, 0x0000 }, /* R17417 */ + { 0x0000, 0x0000, 0x0000 }, /* R17418 */ + { 0x0000, 0x0000, 0x0000 }, /* R17419 */ + { 0x0000, 0x0000, 0x0000 }, /* R17420 */ + { 0x0000, 0x0000, 0x0000 }, /* R17421 */ + { 0x0000, 0x0000, 0x0000 }, /* R17422 */ + { 0x0000, 0x0000, 0x0000 }, /* R17423 */ + { 0x0000, 0x0000, 0x0000 }, /* R17424 */ + { 0x0000, 0x0000, 0x0000 }, /* R17425 */ + { 0x0000, 0x0000, 0x0000 }, /* R17426 */ + { 0x0000, 0x0000, 0x0000 }, /* R17427 */ + { 0x0000, 0x0000, 0x0000 }, /* R17428 */ + { 0x0000, 0x0000, 0x0000 }, /* R17429 */ + { 0x0000, 0x0000, 0x0000 }, /* R17430 */ + { 0x0000, 0x0000, 0x0000 }, /* R17431 */ + { 0x0000, 0x0000, 0x0000 }, /* R17432 */ + { 0x0000, 0x0000, 0x0000 }, /* R17433 */ + { 0x0000, 0x0000, 0x0000 }, /* R17434 */ + { 0x0000, 0x0000, 0x0000 }, /* R17435 */ + { 0x0000, 0x0000, 0x0000 }, /* R17436 */ + { 0x0000, 0x0000, 0x0000 }, /* R17437 */ + { 0x0000, 0x0000, 0x0000 }, /* R17438 */ + { 0x0000, 0x0000, 0x0000 }, /* R17439 */ + { 0x0000, 0x0000, 0x0000 }, /* R17440 */ + { 0x0000, 0x0000, 0x0000 }, /* R17441 */ + { 0x0000, 0x0000, 0x0000 }, /* R17442 */ + { 0x0000, 0x0000, 0x0000 }, /* R17443 */ + { 0x0000, 0x0000, 0x0000 }, /* R17444 */ + { 0x0000, 0x0000, 0x0000 }, /* R17445 */ + { 0x0000, 0x0000, 0x0000 }, /* R17446 */ + { 0x0000, 0x0000, 0x0000 }, /* R17447 */ + { 0x0000, 0x0000, 0x0000 }, /* R17448 */ + { 0x0000, 0x0000, 0x0000 }, /* R17449 */ + { 0x0000, 0x0000, 0x0000 }, /* R17450 */ + { 0x0000, 0x0000, 0x0000 }, /* R17451 */ + { 0x0000, 0x0000, 0x0000 }, /* R17452 */ + { 0x0000, 0x0000, 0x0000 }, /* R17453 */ + { 0x0000, 0x0000, 0x0000 }, /* R17454 */ + { 0x0000, 0x0000, 0x0000 }, /* R17455 */ + { 0x0000, 0x0000, 0x0000 }, /* R17456 */ + { 0x0000, 0x0000, 0x0000 }, /* R17457 */ + { 0x0000, 0x0000, 0x0000 }, /* R17458 */ + { 0x0000, 0x0000, 0x0000 }, /* R17459 */ + { 0x0000, 0x0000, 0x0000 }, /* R17460 */ + { 0x0000, 0x0000, 0x0000 }, /* R17461 */ + { 0x0000, 0x0000, 0x0000 }, /* R17462 */ + { 0x0000, 0x0000, 0x0000 }, /* R17463 */ + { 0x0000, 0x0000, 0x0000 }, /* R17464 */ + { 0x0000, 0x0000, 0x0000 }, /* R17465 */ + { 0x0000, 0x0000, 0x0000 }, /* R17466 */ + { 0x0000, 0x0000, 0x0000 }, /* R17467 */ + { 0x0000, 0x0000, 0x0000 }, /* R17468 */ + { 0x0000, 0x0000, 0x0000 }, /* R17469 */ + { 0x0000, 0x0000, 0x0000 }, /* R17470 */ + { 0x0000, 0x0000, 0x0000 }, /* R17471 */ + { 0x0000, 0x0000, 0x0000 }, /* R17472 */ + { 0x0000, 0x0000, 0x0000 }, /* R17473 */ + { 0x0000, 0x0000, 0x0000 }, /* R17474 */ + { 0x0000, 0x0000, 0x0000 }, /* R17475 */ + { 0x0000, 0x0000, 0x0000 }, /* R17476 */ + { 0x0000, 0x0000, 0x0000 }, /* R17477 */ + { 0x0000, 0x0000, 0x0000 }, /* R17478 */ + { 0x0000, 0x0000, 0x0000 }, /* R17479 */ + { 0x0000, 0x0000, 0x0000 }, /* R17480 */ + { 0x0000, 0x0000, 0x0000 }, /* R17481 */ + { 0x0000, 0x0000, 0x0000 }, /* R17482 */ + { 0x0000, 0x0000, 0x0000 }, /* R17483 */ + { 0x0000, 0x0000, 0x0000 }, /* R17484 */ + { 0x0000, 0x0000, 0x0000 }, /* R17485 */ + { 0x0000, 0x0000, 0x0000 }, /* R17486 */ + { 0x0000, 0x0000, 0x0000 }, /* R17487 */ + { 0x0000, 0x0000, 0x0000 }, /* R17488 */ + { 0x0000, 0x0000, 0x0000 }, /* R17489 */ + { 0x0000, 0x0000, 0x0000 }, /* R17490 */ + { 0x0000, 0x0000, 0x0000 }, /* R17491 */ + { 0x0000, 0x0000, 0x0000 }, /* R17492 */ + { 0x0000, 0x0000, 0x0000 }, /* R17493 */ + { 0x0000, 0x0000, 0x0000 }, /* R17494 */ + { 0x0000, 0x0000, 0x0000 }, /* R17495 */ + { 0x0000, 0x0000, 0x0000 }, /* R17496 */ + { 0x0000, 0x0000, 0x0000 }, /* R17497 */ + { 0x0000, 0x0000, 0x0000 }, /* R17498 */ + { 0x0000, 0x0000, 0x0000 }, /* R17499 */ + { 0x0000, 0x0000, 0x0000 }, /* R17500 */ + { 0x0000, 0x0000, 0x0000 }, /* R17501 */ + { 0x0000, 0x0000, 0x0000 }, /* R17502 */ + { 0x0000, 0x0000, 0x0000 }, /* R17503 */ + { 0x0000, 0x0000, 0x0000 }, /* R17504 */ + { 0x0000, 0x0000, 0x0000 }, /* R17505 */ + { 0x0000, 0x0000, 0x0000 }, /* R17506 */ + { 0x0000, 0x0000, 0x0000 }, /* R17507 */ + { 0x0000, 0x0000, 0x0000 }, /* R17508 */ + { 0x0000, 0x0000, 0x0000 }, /* R17509 */ + { 0x0000, 0x0000, 0x0000 }, /* R17510 */ + { 0x0000, 0x0000, 0x0000 }, /* R17511 */ + { 0x0000, 0x0000, 0x0000 }, /* R17512 */ + { 0x0000, 0x0000, 0x0000 }, /* R17513 */ + { 0x0000, 0x0000, 0x0000 }, /* R17514 */ + { 0x0000, 0x0000, 0x0000 }, /* R17515 */ + { 0x0000, 0x0000, 0x0000 }, /* R17516 */ + { 0x0000, 0x0000, 0x0000 }, /* R17517 */ + { 0x0000, 0x0000, 0x0000 }, /* R17518 */ + { 0x0000, 0x0000, 0x0000 }, /* R17519 */ + { 0x0000, 0x0000, 0x0000 }, /* R17520 */ + { 0x0000, 0x0000, 0x0000 }, /* R17521 */ + { 0x0000, 0x0000, 0x0000 }, /* R17522 */ + { 0x0000, 0x0000, 0x0000 }, /* R17523 */ + { 0x0000, 0x0000, 0x0000 }, /* R17524 */ + { 0x0000, 0x0000, 0x0000 }, /* R17525 */ + { 0x0000, 0x0000, 0x0000 }, /* R17526 */ + { 0x0000, 0x0000, 0x0000 }, /* R17527 */ + { 0x0000, 0x0000, 0x0000 }, /* R17528 */ + { 0x0000, 0x0000, 0x0000 }, /* R17529 */ + { 0x0000, 0x0000, 0x0000 }, /* R17530 */ + { 0x0000, 0x0000, 0x0000 }, /* R17531 */ + { 0x0000, 0x0000, 0x0000 }, /* R17532 */ + { 0x0000, 0x0000, 0x0000 }, /* R17533 */ + { 0x0000, 0x0000, 0x0000 }, /* R17534 */ + { 0x0000, 0x0000, 0x0000 }, /* R17535 */ + { 0x0000, 0x0000, 0x0000 }, /* R17536 */ + { 0x0000, 0x0000, 0x0000 }, /* R17537 */ + { 0x0000, 0x0000, 0x0000 }, /* R17538 */ + { 0x0000, 0x0000, 0x0000 }, /* R17539 */ + { 0x0000, 0x0000, 0x0000 }, /* R17540 */ + { 0x0000, 0x0000, 0x0000 }, /* R17541 */ + { 0x0000, 0x0000, 0x0000 }, /* R17542 */ + { 0x0000, 0x0000, 0x0000 }, /* R17543 */ + { 0x0000, 0x0000, 0x0000 }, /* R17544 */ + { 0x0000, 0x0000, 0x0000 }, /* R17545 */ + { 0x0000, 0x0000, 0x0000 }, /* R17546 */ + { 0x0000, 0x0000, 0x0000 }, /* R17547 */ + { 0x0000, 0x0000, 0x0000 }, /* R17548 */ + { 0x0000, 0x0000, 0x0000 }, /* R17549 */ + { 0x0000, 0x0000, 0x0000 }, /* R17550 */ + { 0x0000, 0x0000, 0x0000 }, /* R17551 */ + { 0x0000, 0x0000, 0x0000 }, /* R17552 */ + { 0x0000, 0x0000, 0x0000 }, /* R17553 */ + { 0x0000, 0x0000, 0x0000 }, /* R17554 */ + { 0x0000, 0x0000, 0x0000 }, /* R17555 */ + { 0x0000, 0x0000, 0x0000 }, /* R17556 */ + { 0x0000, 0x0000, 0x0000 }, /* R17557 */ + { 0x0000, 0x0000, 0x0000 }, /* R17558 */ + { 0x0000, 0x0000, 0x0000 }, /* R17559 */ + { 0x0000, 0x0000, 0x0000 }, /* R17560 */ + { 0x0000, 0x0000, 0x0000 }, /* R17561 */ + { 0x0000, 0x0000, 0x0000 }, /* R17562 */ + { 0x0000, 0x0000, 0x0000 }, /* R17563 */ + { 0x0000, 0x0000, 0x0000 }, /* R17564 */ + { 0x0000, 0x0000, 0x0000 }, /* R17565 */ + { 0x0000, 0x0000, 0x0000 }, /* R17566 */ + { 0x0000, 0x0000, 0x0000 }, /* R17567 */ + { 0x0000, 0x0000, 0x0000 }, /* R17568 */ + { 0x0000, 0x0000, 0x0000 }, /* R17569 */ + { 0x0000, 0x0000, 0x0000 }, /* R17570 */ + { 0x0000, 0x0000, 0x0000 }, /* R17571 */ + { 0x0000, 0x0000, 0x0000 }, /* R17572 */ + { 0x0000, 0x0000, 0x0000 }, /* R17573 */ + { 0x0000, 0x0000, 0x0000 }, /* R17574 */ + { 0x0000, 0x0000, 0x0000 }, /* R17575 */ + { 0x0000, 0x0000, 0x0000 }, /* R17576 */ + { 0x0000, 0x0000, 0x0000 }, /* R17577 */ + { 0x0000, 0x0000, 0x0000 }, /* R17578 */ + { 0x0000, 0x0000, 0x0000 }, /* R17579 */ + { 0x0000, 0x0000, 0x0000 }, /* R17580 */ + { 0x0000, 0x0000, 0x0000 }, /* R17581 */ + { 0x0000, 0x0000, 0x0000 }, /* R17582 */ + { 0x0000, 0x0000, 0x0000 }, /* R17583 */ + { 0x0000, 0x0000, 0x0000 }, /* R17584 */ + { 0x0000, 0x0000, 0x0000 }, /* R17585 */ + { 0x0000, 0x0000, 0x0000 }, /* R17586 */ + { 0x0000, 0x0000, 0x0000 }, /* R17587 */ + { 0x0000, 0x0000, 0x0000 }, /* R17588 */ + { 0x0000, 0x0000, 0x0000 }, /* R17589 */ + { 0x0000, 0x0000, 0x0000 }, /* R17590 */ + { 0x0000, 0x0000, 0x0000 }, /* R17591 */ + { 0x0000, 0x0000, 0x0000 }, /* R17592 */ + { 0x0000, 0x0000, 0x0000 }, /* R17593 */ + { 0x0000, 0x0000, 0x0000 }, /* R17594 */ + { 0x0000, 0x0000, 0x0000 }, /* R17595 */ + { 0x0000, 0x0000, 0x0000 }, /* R17596 */ + { 0x0000, 0x0000, 0x0000 }, /* R17597 */ + { 0x0000, 0x0000, 0x0000 }, /* R17598 */ + { 0x0000, 0x0000, 0x0000 }, /* R17599 */ + { 0x0000, 0x0000, 0x0000 }, /* R17600 */ + { 0x0000, 0x0000, 0x0000 }, /* R17601 */ + { 0x0000, 0x0000, 0x0000 }, /* R17602 */ + { 0x0000, 0x0000, 0x0000 }, /* R17603 */ + { 0x0000, 0x0000, 0x0000 }, /* R17604 */ + { 0x0000, 0x0000, 0x0000 }, /* R17605 */ + { 0x0000, 0x0000, 0x0000 }, /* R17606 */ + { 0x0000, 0x0000, 0x0000 }, /* R17607 */ + { 0x0000, 0x0000, 0x0000 }, /* R17608 */ + { 0x0000, 0x0000, 0x0000 }, /* R17609 */ + { 0x0000, 0x0000, 0x0000 }, /* R17610 */ + { 0x0000, 0x0000, 0x0000 }, /* R17611 */ + { 0x0000, 0x0000, 0x0000 }, /* R17612 */ + { 0x0000, 0x0000, 0x0000 }, /* R17613 */ + { 0x0000, 0x0000, 0x0000 }, /* R17614 */ + { 0x0000, 0x0000, 0x0000 }, /* R17615 */ + { 0x0000, 0x0000, 0x0000 }, /* R17616 */ + { 0x0000, 0x0000, 0x0000 }, /* R17617 */ + { 0x0000, 0x0000, 0x0000 }, /* R17618 */ + { 0x0000, 0x0000, 0x0000 }, /* R17619 */ + { 0x0000, 0x0000, 0x0000 }, /* R17620 */ + { 0x0000, 0x0000, 0x0000 }, /* R17621 */ + { 0x0000, 0x0000, 0x0000 }, /* R17622 */ + { 0x0000, 0x0000, 0x0000 }, /* R17623 */ + { 0x0000, 0x0000, 0x0000 }, /* R17624 */ + { 0x0000, 0x0000, 0x0000 }, /* R17625 */ + { 0x0000, 0x0000, 0x0000 }, /* R17626 */ + { 0x0000, 0x0000, 0x0000 }, /* R17627 */ + { 0x0000, 0x0000, 0x0000 }, /* R17628 */ + { 0x0000, 0x0000, 0x0000 }, /* R17629 */ + { 0x0000, 0x0000, 0x0000 }, /* R17630 */ + { 0x0000, 0x0000, 0x0000 }, /* R17631 */ + { 0x0000, 0x0000, 0x0000 }, /* R17632 */ + { 0x0000, 0x0000, 0x0000 }, /* R17633 */ + { 0x0000, 0x0000, 0x0000 }, /* R17634 */ + { 0x0000, 0x0000, 0x0000 }, /* R17635 */ + { 0x0000, 0x0000, 0x0000 }, /* R17636 */ + { 0x0000, 0x0000, 0x0000 }, /* R17637 */ + { 0x0000, 0x0000, 0x0000 }, /* R17638 */ + { 0x0000, 0x0000, 0x0000 }, /* R17639 */ + { 0x0000, 0x0000, 0x0000 }, /* R17640 */ + { 0x0000, 0x0000, 0x0000 }, /* R17641 */ + { 0x0000, 0x0000, 0x0000 }, /* R17642 */ + { 0x0000, 0x0000, 0x0000 }, /* R17643 */ + { 0x0000, 0x0000, 0x0000 }, /* R17644 */ + { 0x0000, 0x0000, 0x0000 }, /* R17645 */ + { 0x0000, 0x0000, 0x0000 }, /* R17646 */ + { 0x0000, 0x0000, 0x0000 }, /* R17647 */ + { 0x0000, 0x0000, 0x0000 }, /* R17648 */ + { 0x0000, 0x0000, 0x0000 }, /* R17649 */ + { 0x0000, 0x0000, 0x0000 }, /* R17650 */ + { 0x0000, 0x0000, 0x0000 }, /* R17651 */ + { 0x0000, 0x0000, 0x0000 }, /* R17652 */ + { 0x0000, 0x0000, 0x0000 }, /* R17653 */ + { 0x0000, 0x0000, 0x0000 }, /* R17654 */ + { 0x0000, 0x0000, 0x0000 }, /* R17655 */ + { 0x0000, 0x0000, 0x0000 }, /* R17656 */ + { 0x0000, 0x0000, 0x0000 }, /* R17657 */ + { 0x0000, 0x0000, 0x0000 }, /* R17658 */ + { 0x0000, 0x0000, 0x0000 }, /* R17659 */ + { 0x0000, 0x0000, 0x0000 }, /* R17660 */ + { 0x0000, 0x0000, 0x0000 }, /* R17661 */ + { 0x0000, 0x0000, 0x0000 }, /* R17662 */ + { 0x0000, 0x0000, 0x0000 }, /* R17663 */ + { 0x0000, 0x0000, 0x0000 }, /* R17664 */ + { 0x0000, 0x0000, 0x0000 }, /* R17665 */ + { 0x0000, 0x0000, 0x0000 }, /* R17666 */ + { 0x0000, 0x0000, 0x0000 }, /* R17667 */ + { 0x0000, 0x0000, 0x0000 }, /* R17668 */ + { 0x0000, 0x0000, 0x0000 }, /* R17669 */ + { 0x0000, 0x0000, 0x0000 }, /* R17670 */ + { 0x0000, 0x0000, 0x0000 }, /* R17671 */ + { 0x0000, 0x0000, 0x0000 }, /* R17672 */ + { 0x0000, 0x0000, 0x0000 }, /* R17673 */ + { 0x0000, 0x0000, 0x0000 }, /* R17674 */ + { 0x0000, 0x0000, 0x0000 }, /* R17675 */ + { 0x0000, 0x0000, 0x0000 }, /* R17676 */ + { 0x0000, 0x0000, 0x0000 }, /* R17677 */ + { 0x0000, 0x0000, 0x0000 }, /* R17678 */ + { 0x0000, 0x0000, 0x0000 }, /* R17679 */ + { 0x0000, 0x0000, 0x0000 }, /* R17680 */ + { 0x0000, 0x0000, 0x0000 }, /* R17681 */ + { 0x0000, 0x0000, 0x0000 }, /* R17682 */ + { 0x0000, 0x0000, 0x0000 }, /* R17683 */ + { 0x0000, 0x0000, 0x0000 }, /* R17684 */ + { 0x0000, 0x0000, 0x0000 }, /* R17685 */ + { 0x0000, 0x0000, 0x0000 }, /* R17686 */ + { 0x0000, 0x0000, 0x0000 }, /* R17687 */ + { 0x0000, 0x0000, 0x0000 }, /* R17688 */ + { 0x0000, 0x0000, 0x0000 }, /* R17689 */ + { 0x0000, 0x0000, 0x0000 }, /* R17690 */ + { 0x0000, 0x0000, 0x0000 }, /* R17691 */ + { 0x0000, 0x0000, 0x0000 }, /* R17692 */ + { 0x0000, 0x0000, 0x0000 }, /* R17693 */ + { 0x0000, 0x0000, 0x0000 }, /* R17694 */ + { 0x0000, 0x0000, 0x0000 }, /* R17695 */ + { 0x0000, 0x0000, 0x0000 }, /* R17696 */ + { 0x0000, 0x0000, 0x0000 }, /* R17697 */ + { 0x0000, 0x0000, 0x0000 }, /* R17698 */ + { 0x0000, 0x0000, 0x0000 }, /* R17699 */ + { 0x0000, 0x0000, 0x0000 }, /* R17700 */ + { 0x0000, 0x0000, 0x0000 }, /* R17701 */ + { 0x0000, 0x0000, 0x0000 }, /* R17702 */ + { 0x0000, 0x0000, 0x0000 }, /* R17703 */ + { 0x0000, 0x0000, 0x0000 }, /* R17704 */ + { 0x0000, 0x0000, 0x0000 }, /* R17705 */ + { 0x0000, 0x0000, 0x0000 }, /* R17706 */ + { 0x0000, 0x0000, 0x0000 }, /* R17707 */ + { 0x0000, 0x0000, 0x0000 }, /* R17708 */ + { 0x0000, 0x0000, 0x0000 }, /* R17709 */ + { 0x0000, 0x0000, 0x0000 }, /* R17710 */ + { 0x0000, 0x0000, 0x0000 }, /* R17711 */ + { 0x0000, 0x0000, 0x0000 }, /* R17712 */ + { 0x0000, 0x0000, 0x0000 }, /* R17713 */ + { 0x0000, 0x0000, 0x0000 }, /* R17714 */ + { 0x0000, 0x0000, 0x0000 }, /* R17715 */ + { 0x0000, 0x0000, 0x0000 }, /* R17716 */ + { 0x0000, 0x0000, 0x0000 }, /* R17717 */ + { 0x0000, 0x0000, 0x0000 }, /* R17718 */ + { 0x0000, 0x0000, 0x0000 }, /* R17719 */ + { 0x0000, 0x0000, 0x0000 }, /* R17720 */ + { 0x0000, 0x0000, 0x0000 }, /* R17721 */ + { 0x0000, 0x0000, 0x0000 }, /* R17722 */ + { 0x0000, 0x0000, 0x0000 }, /* R17723 */ + { 0x0000, 0x0000, 0x0000 }, /* R17724 */ + { 0x0000, 0x0000, 0x0000 }, /* R17725 */ + { 0x0000, 0x0000, 0x0000 }, /* R17726 */ + { 0x0000, 0x0000, 0x0000 }, /* R17727 */ + { 0x0000, 0x0000, 0x0000 }, /* R17728 */ + { 0x0000, 0x0000, 0x0000 }, /* R17729 */ + { 0x0000, 0x0000, 0x0000 }, /* R17730 */ + { 0x0000, 0x0000, 0x0000 }, /* R17731 */ + { 0x0000, 0x0000, 0x0000 }, /* R17732 */ + { 0x0000, 0x0000, 0x0000 }, /* R17733 */ + { 0x0000, 0x0000, 0x0000 }, /* R17734 */ + { 0x0000, 0x0000, 0x0000 }, /* R17735 */ + { 0x0000, 0x0000, 0x0000 }, /* R17736 */ + { 0x0000, 0x0000, 0x0000 }, /* R17737 */ + { 0x0000, 0x0000, 0x0000 }, /* R17738 */ + { 0x0000, 0x0000, 0x0000 }, /* R17739 */ + { 0x0000, 0x0000, 0x0000 }, /* R17740 */ + { 0x0000, 0x0000, 0x0000 }, /* R17741 */ + { 0x0000, 0x0000, 0x0000 }, /* R17742 */ + { 0x0000, 0x0000, 0x0000 }, /* R17743 */ + { 0x0000, 0x0000, 0x0000 }, /* R17744 */ + { 0x0000, 0x0000, 0x0000 }, /* R17745 */ + { 0x0000, 0x0000, 0x0000 }, /* R17746 */ + { 0x0000, 0x0000, 0x0000 }, /* R17747 */ + { 0x0000, 0x0000, 0x0000 }, /* R17748 */ + { 0x0000, 0x0000, 0x0000 }, /* R17749 */ + { 0x0000, 0x0000, 0x0000 }, /* R17750 */ + { 0x0000, 0x0000, 0x0000 }, /* R17751 */ + { 0x0000, 0x0000, 0x0000 }, /* R17752 */ + { 0x0000, 0x0000, 0x0000 }, /* R17753 */ + { 0x0000, 0x0000, 0x0000 }, /* R17754 */ + { 0x0000, 0x0000, 0x0000 }, /* R17755 */ + { 0x0000, 0x0000, 0x0000 }, /* R17756 */ + { 0x0000, 0x0000, 0x0000 }, /* R17757 */ + { 0x0000, 0x0000, 0x0000 }, /* R17758 */ + { 0x0000, 0x0000, 0x0000 }, /* R17759 */ + { 0x0000, 0x0000, 0x0000 }, /* R17760 */ + { 0x0000, 0x0000, 0x0000 }, /* R17761 */ + { 0x0000, 0x0000, 0x0000 }, /* R17762 */ + { 0x0000, 0x0000, 0x0000 }, /* R17763 */ + { 0x0000, 0x0000, 0x0000 }, /* R17764 */ + { 0x0000, 0x0000, 0x0000 }, /* R17765 */ + { 0x0000, 0x0000, 0x0000 }, /* R17766 */ + { 0x0000, 0x0000, 0x0000 }, /* R17767 */ + { 0x0000, 0x0000, 0x0000 }, /* R17768 */ + { 0x0000, 0x0000, 0x0000 }, /* R17769 */ + { 0x0000, 0x0000, 0x0000 }, /* R17770 */ + { 0x0000, 0x0000, 0x0000 }, /* R17771 */ + { 0x0000, 0x0000, 0x0000 }, /* R17772 */ + { 0x0000, 0x0000, 0x0000 }, /* R17773 */ + { 0x0000, 0x0000, 0x0000 }, /* R17774 */ + { 0x0000, 0x0000, 0x0000 }, /* R17775 */ + { 0x0000, 0x0000, 0x0000 }, /* R17776 */ + { 0x0000, 0x0000, 0x0000 }, /* R17777 */ + { 0x0000, 0x0000, 0x0000 }, /* R17778 */ + { 0x0000, 0x0000, 0x0000 }, /* R17779 */ + { 0x0000, 0x0000, 0x0000 }, /* R17780 */ + { 0x0000, 0x0000, 0x0000 }, /* R17781 */ + { 0x0000, 0x0000, 0x0000 }, /* R17782 */ + { 0x0000, 0x0000, 0x0000 }, /* R17783 */ + { 0x0000, 0x0000, 0x0000 }, /* R17784 */ + { 0x0000, 0x0000, 0x0000 }, /* R17785 */ + { 0x0000, 0x0000, 0x0000 }, /* R17786 */ + { 0x0000, 0x0000, 0x0000 }, /* R17787 */ + { 0x0000, 0x0000, 0x0000 }, /* R17788 */ + { 0x0000, 0x0000, 0x0000 }, /* R17789 */ + { 0x0000, 0x0000, 0x0000 }, /* R17790 */ + { 0x0000, 0x0000, 0x0000 }, /* R17791 */ + { 0x0000, 0x0000, 0x0000 }, /* R17792 */ + { 0x0000, 0x0000, 0x0000 }, /* R17793 */ + { 0x0000, 0x0000, 0x0000 }, /* R17794 */ + { 0x0000, 0x0000, 0x0000 }, /* R17795 */ + { 0x0000, 0x0000, 0x0000 }, /* R17796 */ + { 0x0000, 0x0000, 0x0000 }, /* R17797 */ + { 0x0000, 0x0000, 0x0000 }, /* R17798 */ + { 0x0000, 0x0000, 0x0000 }, /* R17799 */ + { 0x0000, 0x0000, 0x0000 }, /* R17800 */ + { 0x0000, 0x0000, 0x0000 }, /* R17801 */ + { 0x0000, 0x0000, 0x0000 }, /* R17802 */ + { 0x0000, 0x0000, 0x0000 }, /* R17803 */ + { 0x0000, 0x0000, 0x0000 }, /* R17804 */ + { 0x0000, 0x0000, 0x0000 }, /* R17805 */ + { 0x0000, 0x0000, 0x0000 }, /* R17806 */ + { 0x0000, 0x0000, 0x0000 }, /* R17807 */ + { 0x0000, 0x0000, 0x0000 }, /* R17808 */ + { 0x0000, 0x0000, 0x0000 }, /* R17809 */ + { 0x0000, 0x0000, 0x0000 }, /* R17810 */ + { 0x0000, 0x0000, 0x0000 }, /* R17811 */ + { 0x0000, 0x0000, 0x0000 }, /* R17812 */ + { 0x0000, 0x0000, 0x0000 }, /* R17813 */ + { 0x0000, 0x0000, 0x0000 }, /* R17814 */ + { 0x0000, 0x0000, 0x0000 }, /* R17815 */ + { 0x0000, 0x0000, 0x0000 }, /* R17816 */ + { 0x0000, 0x0000, 0x0000 }, /* R17817 */ + { 0x0000, 0x0000, 0x0000 }, /* R17818 */ + { 0x0000, 0x0000, 0x0000 }, /* R17819 */ + { 0x0000, 0x0000, 0x0000 }, /* R17820 */ + { 0x0000, 0x0000, 0x0000 }, /* R17821 */ + { 0x0000, 0x0000, 0x0000 }, /* R17822 */ + { 0x0000, 0x0000, 0x0000 }, /* R17823 */ + { 0x0000, 0x0000, 0x0000 }, /* R17824 */ + { 0x0000, 0x0000, 0x0000 }, /* R17825 */ + { 0x0000, 0x0000, 0x0000 }, /* R17826 */ + { 0x0000, 0x0000, 0x0000 }, /* R17827 */ + { 0x0000, 0x0000, 0x0000 }, /* R17828 */ + { 0x0000, 0x0000, 0x0000 }, /* R17829 */ + { 0x0000, 0x0000, 0x0000 }, /* R17830 */ + { 0x0000, 0x0000, 0x0000 }, /* R17831 */ + { 0x0000, 0x0000, 0x0000 }, /* R17832 */ + { 0x0000, 0x0000, 0x0000 }, /* R17833 */ + { 0x0000, 0x0000, 0x0000 }, /* R17834 */ + { 0x0000, 0x0000, 0x0000 }, /* R17835 */ + { 0x0000, 0x0000, 0x0000 }, /* R17836 */ + { 0x0000, 0x0000, 0x0000 }, /* R17837 */ + { 0x0000, 0x0000, 0x0000 }, /* R17838 */ + { 0x0000, 0x0000, 0x0000 }, /* R17839 */ + { 0x0000, 0x0000, 0x0000 }, /* R17840 */ + { 0x0000, 0x0000, 0x0000 }, /* R17841 */ + { 0x0000, 0x0000, 0x0000 }, /* R17842 */ + { 0x0000, 0x0000, 0x0000 }, /* R17843 */ + { 0x0000, 0x0000, 0x0000 }, /* R17844 */ + { 0x0000, 0x0000, 0x0000 }, /* R17845 */ + { 0x0000, 0x0000, 0x0000 }, /* R17846 */ + { 0x0000, 0x0000, 0x0000 }, /* R17847 */ + { 0x0000, 0x0000, 0x0000 }, /* R17848 */ + { 0x0000, 0x0000, 0x0000 }, /* R17849 */ + { 0x0000, 0x0000, 0x0000 }, /* R17850 */ + { 0x0000, 0x0000, 0x0000 }, /* R17851 */ + { 0x0000, 0x0000, 0x0000 }, /* R17852 */ + { 0x0000, 0x0000, 0x0000 }, /* R17853 */ + { 0x0000, 0x0000, 0x0000 }, /* R17854 */ + { 0x0000, 0x0000, 0x0000 }, /* R17855 */ + { 0x0000, 0x0000, 0x0000 }, /* R17856 */ + { 0x0000, 0x0000, 0x0000 }, /* R17857 */ + { 0x0000, 0x0000, 0x0000 }, /* R17858 */ + { 0x0000, 0x0000, 0x0000 }, /* R17859 */ + { 0x0000, 0x0000, 0x0000 }, /* R17860 */ + { 0x0000, 0x0000, 0x0000 }, /* R17861 */ + { 0x0000, 0x0000, 0x0000 }, /* R17862 */ + { 0x0000, 0x0000, 0x0000 }, /* R17863 */ + { 0x0000, 0x0000, 0x0000 }, /* R17864 */ + { 0x0000, 0x0000, 0x0000 }, /* R17865 */ + { 0x0000, 0x0000, 0x0000 }, /* R17866 */ + { 0x0000, 0x0000, 0x0000 }, /* R17867 */ + { 0x0000, 0x0000, 0x0000 }, /* R17868 */ + { 0x0000, 0x0000, 0x0000 }, /* R17869 */ + { 0x0000, 0x0000, 0x0000 }, /* R17870 */ + { 0x0000, 0x0000, 0x0000 }, /* R17871 */ + { 0x0000, 0x0000, 0x0000 }, /* R17872 */ + { 0x0000, 0x0000, 0x0000 }, /* R17873 */ + { 0x0000, 0x0000, 0x0000 }, /* R17874 */ + { 0x0000, 0x0000, 0x0000 }, /* R17875 */ + { 0x0000, 0x0000, 0x0000 }, /* R17876 */ + { 0x0000, 0x0000, 0x0000 }, /* R17877 */ + { 0x0000, 0x0000, 0x0000 }, /* R17878 */ + { 0x0000, 0x0000, 0x0000 }, /* R17879 */ + { 0x0000, 0x0000, 0x0000 }, /* R17880 */ + { 0x0000, 0x0000, 0x0000 }, /* R17881 */ + { 0x0000, 0x0000, 0x0000 }, /* R17882 */ + { 0x0000, 0x0000, 0x0000 }, /* R17883 */ + { 0x0000, 0x0000, 0x0000 }, /* R17884 */ + { 0x0000, 0x0000, 0x0000 }, /* R17885 */ + { 0x0000, 0x0000, 0x0000 }, /* R17886 */ + { 0x0000, 0x0000, 0x0000 }, /* R17887 */ + { 0x0000, 0x0000, 0x0000 }, /* R17888 */ + { 0x0000, 0x0000, 0x0000 }, /* R17889 */ + { 0x0000, 0x0000, 0x0000 }, /* R17890 */ + { 0x0000, 0x0000, 0x0000 }, /* R17891 */ + { 0x0000, 0x0000, 0x0000 }, /* R17892 */ + { 0x0000, 0x0000, 0x0000 }, /* R17893 */ + { 0x0000, 0x0000, 0x0000 }, /* R17894 */ + { 0x0000, 0x0000, 0x0000 }, /* R17895 */ + { 0x0000, 0x0000, 0x0000 }, /* R17896 */ + { 0x0000, 0x0000, 0x0000 }, /* R17897 */ + { 0x0000, 0x0000, 0x0000 }, /* R17898 */ + { 0x0000, 0x0000, 0x0000 }, /* R17899 */ + { 0x0000, 0x0000, 0x0000 }, /* R17900 */ + { 0x0000, 0x0000, 0x0000 }, /* R17901 */ + { 0x0000, 0x0000, 0x0000 }, /* R17902 */ + { 0x0000, 0x0000, 0x0000 }, /* R17903 */ + { 0x0000, 0x0000, 0x0000 }, /* R17904 */ + { 0x0000, 0x0000, 0x0000 }, /* R17905 */ + { 0x0000, 0x0000, 0x0000 }, /* R17906 */ + { 0x0000, 0x0000, 0x0000 }, /* R17907 */ + { 0x0000, 0x0000, 0x0000 }, /* R17908 */ + { 0x0000, 0x0000, 0x0000 }, /* R17909 */ + { 0x0000, 0x0000, 0x0000 }, /* R17910 */ + { 0x0000, 0x0000, 0x0000 }, /* R17911 */ + { 0x0000, 0x0000, 0x0000 }, /* R17912 */ + { 0x0000, 0x0000, 0x0000 }, /* R17913 */ + { 0x0000, 0x0000, 0x0000 }, /* R17914 */ + { 0x0000, 0x0000, 0x0000 }, /* R17915 */ + { 0x0000, 0x0000, 0x0000 }, /* R17916 */ + { 0x0000, 0x0000, 0x0000 }, /* R17917 */ + { 0x0000, 0x0000, 0x0000 }, /* R17918 */ + { 0x0000, 0x0000, 0x0000 }, /* R17919 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17920 - ADCL_RETUNE_C1_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17921 - ADCL_RETUNE_C1_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17922 - ADCL_RETUNE_C2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17923 - ADCL_RETUNE_C2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17924 - ADCL_RETUNE_C3_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17925 - ADCL_RETUNE_C3_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17926 - ADCL_RETUNE_C4_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17927 - ADCL_RETUNE_C4_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17928 - ADCL_RETUNE_C5_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17929 - ADCL_RETUNE_C5_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17930 - ADCL_RETUNE_C6_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17931 - ADCL_RETUNE_C6_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17932 - ADCL_RETUNE_C7_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17933 - ADCL_RETUNE_C7_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17934 - ADCL_RETUNE_C8_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17935 - ADCL_RETUNE_C8_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17936 - ADCL_RETUNE_C9_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17937 - ADCL_RETUNE_C9_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17938 - ADCL_RETUNE_C10_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17939 - ADCL_RETUNE_C10_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17940 - ADCL_RETUNE_C11_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17941 - ADCL_RETUNE_C11_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17942 - ADCL_RETUNE_C12_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17943 - ADCL_RETUNE_C12_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17944 - ADCL_RETUNE_C13_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17945 - ADCL_RETUNE_C13_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17946 - ADCL_RETUNE_C14_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17947 - ADCL_RETUNE_C14_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17948 - ADCL_RETUNE_C15_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17949 - ADCL_RETUNE_C15_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17950 - ADCL_RETUNE_C16_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17951 - ADCL_RETUNE_C16_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17952 - ADCL_RETUNE_C17_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17953 - ADCL_RETUNE_C17_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17954 - ADCL_RETUNE_C18_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17955 - ADCL_RETUNE_C18_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17956 - ADCL_RETUNE_C19_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17957 - ADCL_RETUNE_C19_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17958 - ADCL_RETUNE_C20_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17959 - ADCL_RETUNE_C20_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17960 - ADCL_RETUNE_C21_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17961 - ADCL_RETUNE_C21_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17962 - ADCL_RETUNE_C22_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17963 - ADCL_RETUNE_C22_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17964 - ADCL_RETUNE_C23_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17965 - ADCL_RETUNE_C23_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17966 - ADCL_RETUNE_C24_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17967 - ADCL_RETUNE_C24_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17968 - ADCL_RETUNE_C25_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17969 - ADCL_RETUNE_C25_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17970 - ADCL_RETUNE_C26_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17971 - ADCL_RETUNE_C26_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17972 - ADCL_RETUNE_C27_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17973 - ADCL_RETUNE_C27_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17974 - ADCL_RETUNE_C28_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17975 - ADCL_RETUNE_C28_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17976 - ADCL_RETUNE_C29_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17977 - ADCL_RETUNE_C29_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17978 - ADCL_RETUNE_C30_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17979 - ADCL_RETUNE_C30_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17980 - ADCL_RETUNE_C31_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17981 - ADCL_RETUNE_C31_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R17982 - ADCL_RETUNE_C32_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R17983 - ADCL_RETUNE_C32_0 */ + { 0x0000, 0x0000, 0x0000 }, /* R17984 */ + { 0x0000, 0x0000, 0x0000 }, /* R17985 */ + { 0x0000, 0x0000, 0x0000 }, /* R17986 */ + { 0x0000, 0x0000, 0x0000 }, /* R17987 */ + { 0x0000, 0x0000, 0x0000 }, /* R17988 */ + { 0x0000, 0x0000, 0x0000 }, /* R17989 */ + { 0x0000, 0x0000, 0x0000 }, /* R17990 */ + { 0x0000, 0x0000, 0x0000 }, /* R17991 */ + { 0x0000, 0x0000, 0x0000 }, /* R17992 */ + { 0x0000, 0x0000, 0x0000 }, /* R17993 */ + { 0x0000, 0x0000, 0x0000 }, /* R17994 */ + { 0x0000, 0x0000, 0x0000 }, /* R17995 */ + { 0x0000, 0x0000, 0x0000 }, /* R17996 */ + { 0x0000, 0x0000, 0x0000 }, /* R17997 */ + { 0x0000, 0x0000, 0x0000 }, /* R17998 */ + { 0x0000, 0x0000, 0x0000 }, /* R17999 */ + { 0x0000, 0x0000, 0x0000 }, /* R18000 */ + { 0x0000, 0x0000, 0x0000 }, /* R18001 */ + { 0x0000, 0x0000, 0x0000 }, /* R18002 */ + { 0x0000, 0x0000, 0x0000 }, /* R18003 */ + { 0x0000, 0x0000, 0x0000 }, /* R18004 */ + { 0x0000, 0x0000, 0x0000 }, /* R18005 */ + { 0x0000, 0x0000, 0x0000 }, /* R18006 */ + { 0x0000, 0x0000, 0x0000 }, /* R18007 */ + { 0x0000, 0x0000, 0x0000 }, /* R18008 */ + { 0x0000, 0x0000, 0x0000 }, /* R18009 */ + { 0x0000, 0x0000, 0x0000 }, /* R18010 */ + { 0x0000, 0x0000, 0x0000 }, /* R18011 */ + { 0x0000, 0x0000, 0x0000 }, /* R18012 */ + { 0x0000, 0x0000, 0x0000 }, /* R18013 */ + { 0x0000, 0x0000, 0x0000 }, /* R18014 */ + { 0x0000, 0x0000, 0x0000 }, /* R18015 */ + { 0x0000, 0x0000, 0x0000 }, /* R18016 */ + { 0x0000, 0x0000, 0x0000 }, /* R18017 */ + { 0x0000, 0x0000, 0x0000 }, /* R18018 */ + { 0x0000, 0x0000, 0x0000 }, /* R18019 */ + { 0x0000, 0x0000, 0x0000 }, /* R18020 */ + { 0x0000, 0x0000, 0x0000 }, /* R18021 */ + { 0x0000, 0x0000, 0x0000 }, /* R18022 */ + { 0x0000, 0x0000, 0x0000 }, /* R18023 */ + { 0x0000, 0x0000, 0x0000 }, /* R18024 */ + { 0x0000, 0x0000, 0x0000 }, /* R18025 */ + { 0x0000, 0x0000, 0x0000 }, /* R18026 */ + { 0x0000, 0x0000, 0x0000 }, /* R18027 */ + { 0x0000, 0x0000, 0x0000 }, /* R18028 */ + { 0x0000, 0x0000, 0x0000 }, /* R18029 */ + { 0x0000, 0x0000, 0x0000 }, /* R18030 */ + { 0x0000, 0x0000, 0x0000 }, /* R18031 */ + { 0x0000, 0x0000, 0x0000 }, /* R18032 */ + { 0x0000, 0x0000, 0x0000 }, /* R18033 */ + { 0x0000, 0x0000, 0x0000 }, /* R18034 */ + { 0x0000, 0x0000, 0x0000 }, /* R18035 */ + { 0x0000, 0x0000, 0x0000 }, /* R18036 */ + { 0x0000, 0x0000, 0x0000 }, /* R18037 */ + { 0x0000, 0x0000, 0x0000 }, /* R18038 */ + { 0x0000, 0x0000, 0x0000 }, /* R18039 */ + { 0x0000, 0x0000, 0x0000 }, /* R18040 */ + { 0x0000, 0x0000, 0x0000 }, /* R18041 */ + { 0x0000, 0x0000, 0x0000 }, /* R18042 */ + { 0x0000, 0x0000, 0x0000 }, /* R18043 */ + { 0x0000, 0x0000, 0x0000 }, /* R18044 */ + { 0x0000, 0x0000, 0x0000 }, /* R18045 */ + { 0x0000, 0x0000, 0x0000 }, /* R18046 */ + { 0x0000, 0x0000, 0x0000 }, /* R18047 */ + { 0x0000, 0x0000, 0x0000 }, /* R18048 */ + { 0x0000, 0x0000, 0x0000 }, /* R18049 */ + { 0x0000, 0x0000, 0x0000 }, /* R18050 */ + { 0x0000, 0x0000, 0x0000 }, /* R18051 */ + { 0x0000, 0x0000, 0x0000 }, /* R18052 */ + { 0x0000, 0x0000, 0x0000 }, /* R18053 */ + { 0x0000, 0x0000, 0x0000 }, /* R18054 */ + { 0x0000, 0x0000, 0x0000 }, /* R18055 */ + { 0x0000, 0x0000, 0x0000 }, /* R18056 */ + { 0x0000, 0x0000, 0x0000 }, /* R18057 */ + { 0x0000, 0x0000, 0x0000 }, /* R18058 */ + { 0x0000, 0x0000, 0x0000 }, /* R18059 */ + { 0x0000, 0x0000, 0x0000 }, /* R18060 */ + { 0x0000, 0x0000, 0x0000 }, /* R18061 */ + { 0x0000, 0x0000, 0x0000 }, /* R18062 */ + { 0x0000, 0x0000, 0x0000 }, /* R18063 */ + { 0x0000, 0x0000, 0x0000 }, /* R18064 */ + { 0x0000, 0x0000, 0x0000 }, /* R18065 */ + { 0x0000, 0x0000, 0x0000 }, /* R18066 */ + { 0x0000, 0x0000, 0x0000 }, /* R18067 */ + { 0x0000, 0x0000, 0x0000 }, /* R18068 */ + { 0x0000, 0x0000, 0x0000 }, /* R18069 */ + { 0x0000, 0x0000, 0x0000 }, /* R18070 */ + { 0x0000, 0x0000, 0x0000 }, /* R18071 */ + { 0x0000, 0x0000, 0x0000 }, /* R18072 */ + { 0x0000, 0x0000, 0x0000 }, /* R18073 */ + { 0x0000, 0x0000, 0x0000 }, /* R18074 */ + { 0x0000, 0x0000, 0x0000 }, /* R18075 */ + { 0x0000, 0x0000, 0x0000 }, /* R18076 */ + { 0x0000, 0x0000, 0x0000 }, /* R18077 */ + { 0x0000, 0x0000, 0x0000 }, /* R18078 */ + { 0x0000, 0x0000, 0x0000 }, /* R18079 */ + { 0x0000, 0x0000, 0x0000 }, /* R18080 */ + { 0x0000, 0x0000, 0x0000 }, /* R18081 */ + { 0x0000, 0x0000, 0x0000 }, /* R18082 */ + { 0x0000, 0x0000, 0x0000 }, /* R18083 */ + { 0x0000, 0x0000, 0x0000 }, /* R18084 */ + { 0x0000, 0x0000, 0x0000 }, /* R18085 */ + { 0x0000, 0x0000, 0x0000 }, /* R18086 */ + { 0x0000, 0x0000, 0x0000 }, /* R18087 */ + { 0x0000, 0x0000, 0x0000 }, /* R18088 */ + { 0x0000, 0x0000, 0x0000 }, /* R18089 */ + { 0x0000, 0x0000, 0x0000 }, /* R18090 */ + { 0x0000, 0x0000, 0x0000 }, /* R18091 */ + { 0x0000, 0x0000, 0x0000 }, /* R18092 */ + { 0x0000, 0x0000, 0x0000 }, /* R18093 */ + { 0x0000, 0x0000, 0x0000 }, /* R18094 */ + { 0x0000, 0x0000, 0x0000 }, /* R18095 */ + { 0x0000, 0x0000, 0x0000 }, /* R18096 */ + { 0x0000, 0x0000, 0x0000 }, /* R18097 */ + { 0x0000, 0x0000, 0x0000 }, /* R18098 */ + { 0x0000, 0x0000, 0x0000 }, /* R18099 */ + { 0x0000, 0x0000, 0x0000 }, /* R18100 */ + { 0x0000, 0x0000, 0x0000 }, /* R18101 */ + { 0x0000, 0x0000, 0x0000 }, /* R18102 */ + { 0x0000, 0x0000, 0x0000 }, /* R18103 */ + { 0x0000, 0x0000, 0x0000 }, /* R18104 */ + { 0x0000, 0x0000, 0x0000 }, /* R18105 */ + { 0x0000, 0x0000, 0x0000 }, /* R18106 */ + { 0x0000, 0x0000, 0x0000 }, /* R18107 */ + { 0x0000, 0x0000, 0x0000 }, /* R18108 */ + { 0x0000, 0x0000, 0x0000 }, /* R18109 */ + { 0x0000, 0x0000, 0x0000 }, /* R18110 */ + { 0x0000, 0x0000, 0x0000 }, /* R18111 */ + { 0x0000, 0x0000, 0x0000 }, /* R18112 */ + { 0x0000, 0x0000, 0x0000 }, /* R18113 */ + { 0x0000, 0x0000, 0x0000 }, /* R18114 */ + { 0x0000, 0x0000, 0x0000 }, /* R18115 */ + { 0x0000, 0x0000, 0x0000 }, /* R18116 */ + { 0x0000, 0x0000, 0x0000 }, /* R18117 */ + { 0x0000, 0x0000, 0x0000 }, /* R18118 */ + { 0x0000, 0x0000, 0x0000 }, /* R18119 */ + { 0x0000, 0x0000, 0x0000 }, /* R18120 */ + { 0x0000, 0x0000, 0x0000 }, /* R18121 */ + { 0x0000, 0x0000, 0x0000 }, /* R18122 */ + { 0x0000, 0x0000, 0x0000 }, /* R18123 */ + { 0x0000, 0x0000, 0x0000 }, /* R18124 */ + { 0x0000, 0x0000, 0x0000 }, /* R18125 */ + { 0x0000, 0x0000, 0x0000 }, /* R18126 */ + { 0x0000, 0x0000, 0x0000 }, /* R18127 */ + { 0x0000, 0x0000, 0x0000 }, /* R18128 */ + { 0x0000, 0x0000, 0x0000 }, /* R18129 */ + { 0x0000, 0x0000, 0x0000 }, /* R18130 */ + { 0x0000, 0x0000, 0x0000 }, /* R18131 */ + { 0x0000, 0x0000, 0x0000 }, /* R18132 */ + { 0x0000, 0x0000, 0x0000 }, /* R18133 */ + { 0x0000, 0x0000, 0x0000 }, /* R18134 */ + { 0x0000, 0x0000, 0x0000 }, /* R18135 */ + { 0x0000, 0x0000, 0x0000 }, /* R18136 */ + { 0x0000, 0x0000, 0x0000 }, /* R18137 */ + { 0x0000, 0x0000, 0x0000 }, /* R18138 */ + { 0x0000, 0x0000, 0x0000 }, /* R18139 */ + { 0x0000, 0x0000, 0x0000 }, /* R18140 */ + { 0x0000, 0x0000, 0x0000 }, /* R18141 */ + { 0x0000, 0x0000, 0x0000 }, /* R18142 */ + { 0x0000, 0x0000, 0x0000 }, /* R18143 */ + { 0x0000, 0x0000, 0x0000 }, /* R18144 */ + { 0x0000, 0x0000, 0x0000 }, /* R18145 */ + { 0x0000, 0x0000, 0x0000 }, /* R18146 */ + { 0x0000, 0x0000, 0x0000 }, /* R18147 */ + { 0x0000, 0x0000, 0x0000 }, /* R18148 */ + { 0x0000, 0x0000, 0x0000 }, /* R18149 */ + { 0x0000, 0x0000, 0x0000 }, /* R18150 */ + { 0x0000, 0x0000, 0x0000 }, /* R18151 */ + { 0x0000, 0x0000, 0x0000 }, /* R18152 */ + { 0x0000, 0x0000, 0x0000 }, /* R18153 */ + { 0x0000, 0x0000, 0x0000 }, /* R18154 */ + { 0x0000, 0x0000, 0x0000 }, /* R18155 */ + { 0x0000, 0x0000, 0x0000 }, /* R18156 */ + { 0x0000, 0x0000, 0x0000 }, /* R18157 */ + { 0x0000, 0x0000, 0x0000 }, /* R18158 */ + { 0x0000, 0x0000, 0x0000 }, /* R18159 */ + { 0x0000, 0x0000, 0x0000 }, /* R18160 */ + { 0x0000, 0x0000, 0x0000 }, /* R18161 */ + { 0x0000, 0x0000, 0x0000 }, /* R18162 */ + { 0x0000, 0x0000, 0x0000 }, /* R18163 */ + { 0x0000, 0x0000, 0x0000 }, /* R18164 */ + { 0x0000, 0x0000, 0x0000 }, /* R18165 */ + { 0x0000, 0x0000, 0x0000 }, /* R18166 */ + { 0x0000, 0x0000, 0x0000 }, /* R18167 */ + { 0x0000, 0x0000, 0x0000 }, /* R18168 */ + { 0x0000, 0x0000, 0x0000 }, /* R18169 */ + { 0x0000, 0x0000, 0x0000 }, /* R18170 */ + { 0x0000, 0x0000, 0x0000 }, /* R18171 */ + { 0x0000, 0x0000, 0x0000 }, /* R18172 */ + { 0x0000, 0x0000, 0x0000 }, /* R18173 */ + { 0x0000, 0x0000, 0x0000 }, /* R18174 */ + { 0x0000, 0x0000, 0x0000 }, /* R18175 */ + { 0x0000, 0x0000, 0x0000 }, /* R18176 */ + { 0x0000, 0x0000, 0x0000 }, /* R18177 */ + { 0x0000, 0x0000, 0x0000 }, /* R18178 */ + { 0x0000, 0x0000, 0x0000 }, /* R18179 */ + { 0x0000, 0x0000, 0x0000 }, /* R18180 */ + { 0x0000, 0x0000, 0x0000 }, /* R18181 */ + { 0x0000, 0x0000, 0x0000 }, /* R18182 */ + { 0x0000, 0x0000, 0x0000 }, /* R18183 */ + { 0x0000, 0x0000, 0x0000 }, /* R18184 */ + { 0x0000, 0x0000, 0x0000 }, /* R18185 */ + { 0x0000, 0x0000, 0x0000 }, /* R18186 */ + { 0x0000, 0x0000, 0x0000 }, /* R18187 */ + { 0x0000, 0x0000, 0x0000 }, /* R18188 */ + { 0x0000, 0x0000, 0x0000 }, /* R18189 */ + { 0x0000, 0x0000, 0x0000 }, /* R18190 */ + { 0x0000, 0x0000, 0x0000 }, /* R18191 */ + { 0x0000, 0x0000, 0x0000 }, /* R18192 */ + { 0x0000, 0x0000, 0x0000 }, /* R18193 */ + { 0x0000, 0x0000, 0x0000 }, /* R18194 */ + { 0x0000, 0x0000, 0x0000 }, /* R18195 */ + { 0x0000, 0x0000, 0x0000 }, /* R18196 */ + { 0x0000, 0x0000, 0x0000 }, /* R18197 */ + { 0x0000, 0x0000, 0x0000 }, /* R18198 */ + { 0x0000, 0x0000, 0x0000 }, /* R18199 */ + { 0x0000, 0x0000, 0x0000 }, /* R18200 */ + { 0x0000, 0x0000, 0x0000 }, /* R18201 */ + { 0x0000, 0x0000, 0x0000 }, /* R18202 */ + { 0x0000, 0x0000, 0x0000 }, /* R18203 */ + { 0x0000, 0x0000, 0x0000 }, /* R18204 */ + { 0x0000, 0x0000, 0x0000 }, /* R18205 */ + { 0x0000, 0x0000, 0x0000 }, /* R18206 */ + { 0x0000, 0x0000, 0x0000 }, /* R18207 */ + { 0x0000, 0x0000, 0x0000 }, /* R18208 */ + { 0x0000, 0x0000, 0x0000 }, /* R18209 */ + { 0x0000, 0x0000, 0x0000 }, /* R18210 */ + { 0x0000, 0x0000, 0x0000 }, /* R18211 */ + { 0x0000, 0x0000, 0x0000 }, /* R18212 */ + { 0x0000, 0x0000, 0x0000 }, /* R18213 */ + { 0x0000, 0x0000, 0x0000 }, /* R18214 */ + { 0x0000, 0x0000, 0x0000 }, /* R18215 */ + { 0x0000, 0x0000, 0x0000 }, /* R18216 */ + { 0x0000, 0x0000, 0x0000 }, /* R18217 */ + { 0x0000, 0x0000, 0x0000 }, /* R18218 */ + { 0x0000, 0x0000, 0x0000 }, /* R18219 */ + { 0x0000, 0x0000, 0x0000 }, /* R18220 */ + { 0x0000, 0x0000, 0x0000 }, /* R18221 */ + { 0x0000, 0x0000, 0x0000 }, /* R18222 */ + { 0x0000, 0x0000, 0x0000 }, /* R18223 */ + { 0x0000, 0x0000, 0x0000 }, /* R18224 */ + { 0x0000, 0x0000, 0x0000 }, /* R18225 */ + { 0x0000, 0x0000, 0x0000 }, /* R18226 */ + { 0x0000, 0x0000, 0x0000 }, /* R18227 */ + { 0x0000, 0x0000, 0x0000 }, /* R18228 */ + { 0x0000, 0x0000, 0x0000 }, /* R18229 */ + { 0x0000, 0x0000, 0x0000 }, /* R18230 */ + { 0x0000, 0x0000, 0x0000 }, /* R18231 */ + { 0x0000, 0x0000, 0x0000 }, /* R18232 */ + { 0x0000, 0x0000, 0x0000 }, /* R18233 */ + { 0x0000, 0x0000, 0x0000 }, /* R18234 */ + { 0x0000, 0x0000, 0x0000 }, /* R18235 */ + { 0x0000, 0x0000, 0x0000 }, /* R18236 */ + { 0x0000, 0x0000, 0x0000 }, /* R18237 */ + { 0x0000, 0x0000, 0x0000 }, /* R18238 */ + { 0x0000, 0x0000, 0x0000 }, /* R18239 */ + { 0x0000, 0x0000, 0x0000 }, /* R18240 */ + { 0x0000, 0x0000, 0x0000 }, /* R18241 */ + { 0x0000, 0x0000, 0x0000 }, /* R18242 */ + { 0x0000, 0x0000, 0x0000 }, /* R18243 */ + { 0x0000, 0x0000, 0x0000 }, /* R18244 */ + { 0x0000, 0x0000, 0x0000 }, /* R18245 */ + { 0x0000, 0x0000, 0x0000 }, /* R18246 */ + { 0x0000, 0x0000, 0x0000 }, /* R18247 */ + { 0x0000, 0x0000, 0x0000 }, /* R18248 */ + { 0x0000, 0x0000, 0x0000 }, /* R18249 */ + { 0x0000, 0x0000, 0x0000 }, /* R18250 */ + { 0x0000, 0x0000, 0x0000 }, /* R18251 */ + { 0x0000, 0x0000, 0x0000 }, /* R18252 */ + { 0x0000, 0x0000, 0x0000 }, /* R18253 */ + { 0x0000, 0x0000, 0x0000 }, /* R18254 */ + { 0x0000, 0x0000, 0x0000 }, /* R18255 */ + { 0x0000, 0x0000, 0x0000 }, /* R18256 */ + { 0x0000, 0x0000, 0x0000 }, /* R18257 */ + { 0x0000, 0x0000, 0x0000 }, /* R18258 */ + { 0x0000, 0x0000, 0x0000 }, /* R18259 */ + { 0x0000, 0x0000, 0x0000 }, /* R18260 */ + { 0x0000, 0x0000, 0x0000 }, /* R18261 */ + { 0x0000, 0x0000, 0x0000 }, /* R18262 */ + { 0x0000, 0x0000, 0x0000 }, /* R18263 */ + { 0x0000, 0x0000, 0x0000 }, /* R18264 */ + { 0x0000, 0x0000, 0x0000 }, /* R18265 */ + { 0x0000, 0x0000, 0x0000 }, /* R18266 */ + { 0x0000, 0x0000, 0x0000 }, /* R18267 */ + { 0x0000, 0x0000, 0x0000 }, /* R18268 */ + { 0x0000, 0x0000, 0x0000 }, /* R18269 */ + { 0x0000, 0x0000, 0x0000 }, /* R18270 */ + { 0x0000, 0x0000, 0x0000 }, /* R18271 */ + { 0x0000, 0x0000, 0x0000 }, /* R18272 */ + { 0x0000, 0x0000, 0x0000 }, /* R18273 */ + { 0x0000, 0x0000, 0x0000 }, /* R18274 */ + { 0x0000, 0x0000, 0x0000 }, /* R18275 */ + { 0x0000, 0x0000, 0x0000 }, /* R18276 */ + { 0x0000, 0x0000, 0x0000 }, /* R18277 */ + { 0x0000, 0x0000, 0x0000 }, /* R18278 */ + { 0x0000, 0x0000, 0x0000 }, /* R18279 */ + { 0x0000, 0x0000, 0x0000 }, /* R18280 */ + { 0x0000, 0x0000, 0x0000 }, /* R18281 */ + { 0x0000, 0x0000, 0x0000 }, /* R18282 */ + { 0x0000, 0x0000, 0x0000 }, /* R18283 */ + { 0x0000, 0x0000, 0x0000 }, /* R18284 */ + { 0x0000, 0x0000, 0x0000 }, /* R18285 */ + { 0x0000, 0x0000, 0x0000 }, /* R18286 */ + { 0x0000, 0x0000, 0x0000 }, /* R18287 */ + { 0x0000, 0x0000, 0x0000 }, /* R18288 */ + { 0x0000, 0x0000, 0x0000 }, /* R18289 */ + { 0x0000, 0x0000, 0x0000 }, /* R18290 */ + { 0x0000, 0x0000, 0x0000 }, /* R18291 */ + { 0x0000, 0x0000, 0x0000 }, /* R18292 */ + { 0x0000, 0x0000, 0x0000 }, /* R18293 */ + { 0x0000, 0x0000, 0x0000 }, /* R18294 */ + { 0x0000, 0x0000, 0x0000 }, /* R18295 */ + { 0x0000, 0x0000, 0x0000 }, /* R18296 */ + { 0x0000, 0x0000, 0x0000 }, /* R18297 */ + { 0x0000, 0x0000, 0x0000 }, /* R18298 */ + { 0x0000, 0x0000, 0x0000 }, /* R18299 */ + { 0x0000, 0x0000, 0x0000 }, /* R18300 */ + { 0x0000, 0x0000, 0x0000 }, /* R18301 */ + { 0x0000, 0x0000, 0x0000 }, /* R18302 */ + { 0x0000, 0x0000, 0x0000 }, /* R18303 */ + { 0x0000, 0x0000, 0x0000 }, /* R18304 */ + { 0x0000, 0x0000, 0x0000 }, /* R18305 */ + { 0x0000, 0x0000, 0x0000 }, /* R18306 */ + { 0x0000, 0x0000, 0x0000 }, /* R18307 */ + { 0x0000, 0x0000, 0x0000 }, /* R18308 */ + { 0x0000, 0x0000, 0x0000 }, /* R18309 */ + { 0x0000, 0x0000, 0x0000 }, /* R18310 */ + { 0x0000, 0x0000, 0x0000 }, /* R18311 */ + { 0x0000, 0x0000, 0x0000 }, /* R18312 */ + { 0x0000, 0x0000, 0x0000 }, /* R18313 */ + { 0x0000, 0x0000, 0x0000 }, /* R18314 */ + { 0x0000, 0x0000, 0x0000 }, /* R18315 */ + { 0x0000, 0x0000, 0x0000 }, /* R18316 */ + { 0x0000, 0x0000, 0x0000 }, /* R18317 */ + { 0x0000, 0x0000, 0x0000 }, /* R18318 */ + { 0x0000, 0x0000, 0x0000 }, /* R18319 */ + { 0x0000, 0x0000, 0x0000 }, /* R18320 */ + { 0x0000, 0x0000, 0x0000 }, /* R18321 */ + { 0x0000, 0x0000, 0x0000 }, /* R18322 */ + { 0x0000, 0x0000, 0x0000 }, /* R18323 */ + { 0x0000, 0x0000, 0x0000 }, /* R18324 */ + { 0x0000, 0x0000, 0x0000 }, /* R18325 */ + { 0x0000, 0x0000, 0x0000 }, /* R18326 */ + { 0x0000, 0x0000, 0x0000 }, /* R18327 */ + { 0x0000, 0x0000, 0x0000 }, /* R18328 */ + { 0x0000, 0x0000, 0x0000 }, /* R18329 */ + { 0x0000, 0x0000, 0x0000 }, /* R18330 */ + { 0x0000, 0x0000, 0x0000 }, /* R18331 */ + { 0x0000, 0x0000, 0x0000 }, /* R18332 */ + { 0x0000, 0x0000, 0x0000 }, /* R18333 */ + { 0x0000, 0x0000, 0x0000 }, /* R18334 */ + { 0x0000, 0x0000, 0x0000 }, /* R18335 */ + { 0x0000, 0x0000, 0x0000 }, /* R18336 */ + { 0x0000, 0x0000, 0x0000 }, /* R18337 */ + { 0x0000, 0x0000, 0x0000 }, /* R18338 */ + { 0x0000, 0x0000, 0x0000 }, /* R18339 */ + { 0x0000, 0x0000, 0x0000 }, /* R18340 */ + { 0x0000, 0x0000, 0x0000 }, /* R18341 */ + { 0x0000, 0x0000, 0x0000 }, /* R18342 */ + { 0x0000, 0x0000, 0x0000 }, /* R18343 */ + { 0x0000, 0x0000, 0x0000 }, /* R18344 */ + { 0x0000, 0x0000, 0x0000 }, /* R18345 */ + { 0x0000, 0x0000, 0x0000 }, /* R18346 */ + { 0x0000, 0x0000, 0x0000 }, /* R18347 */ + { 0x0000, 0x0000, 0x0000 }, /* R18348 */ + { 0x0000, 0x0000, 0x0000 }, /* R18349 */ + { 0x0000, 0x0000, 0x0000 }, /* R18350 */ + { 0x0000, 0x0000, 0x0000 }, /* R18351 */ + { 0x0000, 0x0000, 0x0000 }, /* R18352 */ + { 0x0000, 0x0000, 0x0000 }, /* R18353 */ + { 0x0000, 0x0000, 0x0000 }, /* R18354 */ + { 0x0000, 0x0000, 0x0000 }, /* R18355 */ + { 0x0000, 0x0000, 0x0000 }, /* R18356 */ + { 0x0000, 0x0000, 0x0000 }, /* R18357 */ + { 0x0000, 0x0000, 0x0000 }, /* R18358 */ + { 0x0000, 0x0000, 0x0000 }, /* R18359 */ + { 0x0000, 0x0000, 0x0000 }, /* R18360 */ + { 0x0000, 0x0000, 0x0000 }, /* R18361 */ + { 0x0000, 0x0000, 0x0000 }, /* R18362 */ + { 0x0000, 0x0000, 0x0000 }, /* R18363 */ + { 0x0000, 0x0000, 0x0000 }, /* R18364 */ + { 0x0000, 0x0000, 0x0000 }, /* R18365 */ + { 0x0000, 0x0000, 0x0000 }, /* R18366 */ + { 0x0000, 0x0000, 0x0000 }, /* R18367 */ + { 0x0000, 0x0000, 0x0000 }, /* R18368 */ + { 0x0000, 0x0000, 0x0000 }, /* R18369 */ + { 0x0000, 0x0000, 0x0000 }, /* R18370 */ + { 0x0000, 0x0000, 0x0000 }, /* R18371 */ + { 0x0000, 0x0000, 0x0000 }, /* R18372 */ + { 0x0000, 0x0000, 0x0000 }, /* R18373 */ + { 0x0000, 0x0000, 0x0000 }, /* R18374 */ + { 0x0000, 0x0000, 0x0000 }, /* R18375 */ + { 0x0000, 0x0000, 0x0000 }, /* R18376 */ + { 0x0000, 0x0000, 0x0000 }, /* R18377 */ + { 0x0000, 0x0000, 0x0000 }, /* R18378 */ + { 0x0000, 0x0000, 0x0000 }, /* R18379 */ + { 0x0000, 0x0000, 0x0000 }, /* R18380 */ + { 0x0000, 0x0000, 0x0000 }, /* R18381 */ + { 0x0000, 0x0000, 0x0000 }, /* R18382 */ + { 0x0000, 0x0000, 0x0000 }, /* R18383 */ + { 0x0000, 0x0000, 0x0000 }, /* R18384 */ + { 0x0000, 0x0000, 0x0000 }, /* R18385 */ + { 0x0000, 0x0000, 0x0000 }, /* R18386 */ + { 0x0000, 0x0000, 0x0000 }, /* R18387 */ + { 0x0000, 0x0000, 0x0000 }, /* R18388 */ + { 0x0000, 0x0000, 0x0000 }, /* R18389 */ + { 0x0000, 0x0000, 0x0000 }, /* R18390 */ + { 0x0000, 0x0000, 0x0000 }, /* R18391 */ + { 0x0000, 0x0000, 0x0000 }, /* R18392 */ + { 0x0000, 0x0000, 0x0000 }, /* R18393 */ + { 0x0000, 0x0000, 0x0000 }, /* R18394 */ + { 0x0000, 0x0000, 0x0000 }, /* R18395 */ + { 0x0000, 0x0000, 0x0000 }, /* R18396 */ + { 0x0000, 0x0000, 0x0000 }, /* R18397 */ + { 0x0000, 0x0000, 0x0000 }, /* R18398 */ + { 0x0000, 0x0000, 0x0000 }, /* R18399 */ + { 0x0000, 0x0000, 0x0000 }, /* R18400 */ + { 0x0000, 0x0000, 0x0000 }, /* R18401 */ + { 0x0000, 0x0000, 0x0000 }, /* R18402 */ + { 0x0000, 0x0000, 0x0000 }, /* R18403 */ + { 0x0000, 0x0000, 0x0000 }, /* R18404 */ + { 0x0000, 0x0000, 0x0000 }, /* R18405 */ + { 0x0000, 0x0000, 0x0000 }, /* R18406 */ + { 0x0000, 0x0000, 0x0000 }, /* R18407 */ + { 0x0000, 0x0000, 0x0000 }, /* R18408 */ + { 0x0000, 0x0000, 0x0000 }, /* R18409 */ + { 0x0000, 0x0000, 0x0000 }, /* R18410 */ + { 0x0000, 0x0000, 0x0000 }, /* R18411 */ + { 0x0000, 0x0000, 0x0000 }, /* R18412 */ + { 0x0000, 0x0000, 0x0000 }, /* R18413 */ + { 0x0000, 0x0000, 0x0000 }, /* R18414 */ + { 0x0000, 0x0000, 0x0000 }, /* R18415 */ + { 0x0000, 0x0000, 0x0000 }, /* R18416 */ + { 0x0000, 0x0000, 0x0000 }, /* R18417 */ + { 0x0000, 0x0000, 0x0000 }, /* R18418 */ + { 0x0000, 0x0000, 0x0000 }, /* R18419 */ + { 0x0000, 0x0000, 0x0000 }, /* R18420 */ + { 0x0000, 0x0000, 0x0000 }, /* R18421 */ + { 0x0000, 0x0000, 0x0000 }, /* R18422 */ + { 0x0000, 0x0000, 0x0000 }, /* R18423 */ + { 0x0000, 0x0000, 0x0000 }, /* R18424 */ + { 0x0000, 0x0000, 0x0000 }, /* R18425 */ + { 0x0000, 0x0000, 0x0000 }, /* R18426 */ + { 0x0000, 0x0000, 0x0000 }, /* R18427 */ + { 0x0000, 0x0000, 0x0000 }, /* R18428 */ + { 0x0000, 0x0000, 0x0000 }, /* R18429 */ + { 0x0000, 0x0000, 0x0000 }, /* R18430 */ + { 0x0000, 0x0000, 0x0000 }, /* R18431 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18432 - RETUNEADC_PG2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18433 - RETUNEADC_PG2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18434 - RETUNEADC_PG_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18435 - RETUNEADC_PG_0 */ + { 0x0000, 0x0000, 0x0000 }, /* R18436 */ + { 0x0000, 0x0000, 0x0000 }, /* R18437 */ + { 0x0000, 0x0000, 0x0000 }, /* R18438 */ + { 0x0000, 0x0000, 0x0000 }, /* R18439 */ + { 0x0000, 0x0000, 0x0000 }, /* R18440 */ + { 0x0000, 0x0000, 0x0000 }, /* R18441 */ + { 0x0000, 0x0000, 0x0000 }, /* R18442 */ + { 0x0000, 0x0000, 0x0000 }, /* R18443 */ + { 0x0000, 0x0000, 0x0000 }, /* R18444 */ + { 0x0000, 0x0000, 0x0000 }, /* R18445 */ + { 0x0000, 0x0000, 0x0000 }, /* R18446 */ + { 0x0000, 0x0000, 0x0000 }, /* R18447 */ + { 0x0000, 0x0000, 0x0000 }, /* R18448 */ + { 0x0000, 0x0000, 0x0000 }, /* R18449 */ + { 0x0000, 0x0000, 0x0000 }, /* R18450 */ + { 0x0000, 0x0000, 0x0000 }, /* R18451 */ + { 0x0000, 0x0000, 0x0000 }, /* R18452 */ + { 0x0000, 0x0000, 0x0000 }, /* R18453 */ + { 0x0000, 0x0000, 0x0000 }, /* R18454 */ + { 0x0000, 0x0000, 0x0000 }, /* R18455 */ + { 0x0000, 0x0000, 0x0000 }, /* R18456 */ + { 0x0000, 0x0000, 0x0000 }, /* R18457 */ + { 0x0000, 0x0000, 0x0000 }, /* R18458 */ + { 0x0000, 0x0000, 0x0000 }, /* R18459 */ + { 0x0000, 0x0000, 0x0000 }, /* R18460 */ + { 0x0000, 0x0000, 0x0000 }, /* R18461 */ + { 0x0000, 0x0000, 0x0000 }, /* R18462 */ + { 0x0000, 0x0000, 0x0000 }, /* R18463 */ + { 0x0000, 0x0000, 0x0000 }, /* R18464 */ + { 0x0000, 0x0000, 0x0000 }, /* R18465 */ + { 0x0000, 0x0000, 0x0000 }, /* R18466 */ + { 0x0000, 0x0000, 0x0000 }, /* R18467 */ + { 0x0000, 0x0000, 0x0000 }, /* R18468 */ + { 0x0000, 0x0000, 0x0000 }, /* R18469 */ + { 0x0000, 0x0000, 0x0000 }, /* R18470 */ + { 0x0000, 0x0000, 0x0000 }, /* R18471 */ + { 0x0000, 0x0000, 0x0000 }, /* R18472 */ + { 0x0000, 0x0000, 0x0000 }, /* R18473 */ + { 0x0000, 0x0000, 0x0000 }, /* R18474 */ + { 0x0000, 0x0000, 0x0000 }, /* R18475 */ + { 0x0000, 0x0000, 0x0000 }, /* R18476 */ + { 0x0000, 0x0000, 0x0000 }, /* R18477 */ + { 0x0000, 0x0000, 0x0000 }, /* R18478 */ + { 0x0000, 0x0000, 0x0000 }, /* R18479 */ + { 0x0000, 0x0000, 0x0000 }, /* R18480 */ + { 0x0000, 0x0000, 0x0000 }, /* R18481 */ + { 0x0000, 0x0000, 0x0000 }, /* R18482 */ + { 0x0000, 0x0000, 0x0000 }, /* R18483 */ + { 0x0000, 0x0000, 0x0000 }, /* R18484 */ + { 0x0000, 0x0000, 0x0000 }, /* R18485 */ + { 0x0000, 0x0000, 0x0000 }, /* R18486 */ + { 0x0000, 0x0000, 0x0000 }, /* R18487 */ + { 0x0000, 0x0000, 0x0000 }, /* R18488 */ + { 0x0000, 0x0000, 0x0000 }, /* R18489 */ + { 0x0000, 0x0000, 0x0000 }, /* R18490 */ + { 0x0000, 0x0000, 0x0000 }, /* R18491 */ + { 0x0000, 0x0000, 0x0000 }, /* R18492 */ + { 0x0000, 0x0000, 0x0000 }, /* R18493 */ + { 0x0000, 0x0000, 0x0000 }, /* R18494 */ + { 0x0000, 0x0000, 0x0000 }, /* R18495 */ + { 0x0000, 0x0000, 0x0000 }, /* R18496 */ + { 0x0000, 0x0000, 0x0000 }, /* R18497 */ + { 0x0000, 0x0000, 0x0000 }, /* R18498 */ + { 0x0000, 0x0000, 0x0000 }, /* R18499 */ + { 0x0000, 0x0000, 0x0000 }, /* R18500 */ + { 0x0000, 0x0000, 0x0000 }, /* R18501 */ + { 0x0000, 0x0000, 0x0000 }, /* R18502 */ + { 0x0000, 0x0000, 0x0000 }, /* R18503 */ + { 0x0000, 0x0000, 0x0000 }, /* R18504 */ + { 0x0000, 0x0000, 0x0000 }, /* R18505 */ + { 0x0000, 0x0000, 0x0000 }, /* R18506 */ + { 0x0000, 0x0000, 0x0000 }, /* R18507 */ + { 0x0000, 0x0000, 0x0000 }, /* R18508 */ + { 0x0000, 0x0000, 0x0000 }, /* R18509 */ + { 0x0000, 0x0000, 0x0000 }, /* R18510 */ + { 0x0000, 0x0000, 0x0000 }, /* R18511 */ + { 0x0000, 0x0000, 0x0000 }, /* R18512 */ + { 0x0000, 0x0000, 0x0000 }, /* R18513 */ + { 0x0000, 0x0000, 0x0000 }, /* R18514 */ + { 0x0000, 0x0000, 0x0000 }, /* R18515 */ + { 0x0000, 0x0000, 0x0000 }, /* R18516 */ + { 0x0000, 0x0000, 0x0000 }, /* R18517 */ + { 0x0000, 0x0000, 0x0000 }, /* R18518 */ + { 0x0000, 0x0000, 0x0000 }, /* R18519 */ + { 0x0000, 0x0000, 0x0000 }, /* R18520 */ + { 0x0000, 0x0000, 0x0000 }, /* R18521 */ + { 0x0000, 0x0000, 0x0000 }, /* R18522 */ + { 0x0000, 0x0000, 0x0000 }, /* R18523 */ + { 0x0000, 0x0000, 0x0000 }, /* R18524 */ + { 0x0000, 0x0000, 0x0000 }, /* R18525 */ + { 0x0000, 0x0000, 0x0000 }, /* R18526 */ + { 0x0000, 0x0000, 0x0000 }, /* R18527 */ + { 0x0000, 0x0000, 0x0000 }, /* R18528 */ + { 0x0000, 0x0000, 0x0000 }, /* R18529 */ + { 0x0000, 0x0000, 0x0000 }, /* R18530 */ + { 0x0000, 0x0000, 0x0000 }, /* R18531 */ + { 0x0000, 0x0000, 0x0000 }, /* R18532 */ + { 0x0000, 0x0000, 0x0000 }, /* R18533 */ + { 0x0000, 0x0000, 0x0000 }, /* R18534 */ + { 0x0000, 0x0000, 0x0000 }, /* R18535 */ + { 0x0000, 0x0000, 0x0000 }, /* R18536 */ + { 0x0000, 0x0000, 0x0000 }, /* R18537 */ + { 0x0000, 0x0000, 0x0000 }, /* R18538 */ + { 0x0000, 0x0000, 0x0000 }, /* R18539 */ + { 0x0000, 0x0000, 0x0000 }, /* R18540 */ + { 0x0000, 0x0000, 0x0000 }, /* R18541 */ + { 0x0000, 0x0000, 0x0000 }, /* R18542 */ + { 0x0000, 0x0000, 0x0000 }, /* R18543 */ + { 0x0000, 0x0000, 0x0000 }, /* R18544 */ + { 0x0000, 0x0000, 0x0000 }, /* R18545 */ + { 0x0000, 0x0000, 0x0000 }, /* R18546 */ + { 0x0000, 0x0000, 0x0000 }, /* R18547 */ + { 0x0000, 0x0000, 0x0000 }, /* R18548 */ + { 0x0000, 0x0000, 0x0000 }, /* R18549 */ + { 0x0000, 0x0000, 0x0000 }, /* R18550 */ + { 0x0000, 0x0000, 0x0000 }, /* R18551 */ + { 0x0000, 0x0000, 0x0000 }, /* R18552 */ + { 0x0000, 0x0000, 0x0000 }, /* R18553 */ + { 0x0000, 0x0000, 0x0000 }, /* R18554 */ + { 0x0000, 0x0000, 0x0000 }, /* R18555 */ + { 0x0000, 0x0000, 0x0000 }, /* R18556 */ + { 0x0000, 0x0000, 0x0000 }, /* R18557 */ + { 0x0000, 0x0000, 0x0000 }, /* R18558 */ + { 0x0000, 0x0000, 0x0000 }, /* R18559 */ + { 0x0000, 0x0000, 0x0000 }, /* R18560 */ + { 0x0000, 0x0000, 0x0000 }, /* R18561 */ + { 0x0000, 0x0000, 0x0000 }, /* R18562 */ + { 0x0000, 0x0000, 0x0000 }, /* R18563 */ + { 0x0000, 0x0000, 0x0000 }, /* R18564 */ + { 0x0000, 0x0000, 0x0000 }, /* R18565 */ + { 0x0000, 0x0000, 0x0000 }, /* R18566 */ + { 0x0000, 0x0000, 0x0000 }, /* R18567 */ + { 0x0000, 0x0000, 0x0000 }, /* R18568 */ + { 0x0000, 0x0000, 0x0000 }, /* R18569 */ + { 0x0000, 0x0000, 0x0000 }, /* R18570 */ + { 0x0000, 0x0000, 0x0000 }, /* R18571 */ + { 0x0000, 0x0000, 0x0000 }, /* R18572 */ + { 0x0000, 0x0000, 0x0000 }, /* R18573 */ + { 0x0000, 0x0000, 0x0000 }, /* R18574 */ + { 0x0000, 0x0000, 0x0000 }, /* R18575 */ + { 0x0000, 0x0000, 0x0000 }, /* R18576 */ + { 0x0000, 0x0000, 0x0000 }, /* R18577 */ + { 0x0000, 0x0000, 0x0000 }, /* R18578 */ + { 0x0000, 0x0000, 0x0000 }, /* R18579 */ + { 0x0000, 0x0000, 0x0000 }, /* R18580 */ + { 0x0000, 0x0000, 0x0000 }, /* R18581 */ + { 0x0000, 0x0000, 0x0000 }, /* R18582 */ + { 0x0000, 0x0000, 0x0000 }, /* R18583 */ + { 0x0000, 0x0000, 0x0000 }, /* R18584 */ + { 0x0000, 0x0000, 0x0000 }, /* R18585 */ + { 0x0000, 0x0000, 0x0000 }, /* R18586 */ + { 0x0000, 0x0000, 0x0000 }, /* R18587 */ + { 0x0000, 0x0000, 0x0000 }, /* R18588 */ + { 0x0000, 0x0000, 0x0000 }, /* R18589 */ + { 0x0000, 0x0000, 0x0000 }, /* R18590 */ + { 0x0000, 0x0000, 0x0000 }, /* R18591 */ + { 0x0000, 0x0000, 0x0000 }, /* R18592 */ + { 0x0000, 0x0000, 0x0000 }, /* R18593 */ + { 0x0000, 0x0000, 0x0000 }, /* R18594 */ + { 0x0000, 0x0000, 0x0000 }, /* R18595 */ + { 0x0000, 0x0000, 0x0000 }, /* R18596 */ + { 0x0000, 0x0000, 0x0000 }, /* R18597 */ + { 0x0000, 0x0000, 0x0000 }, /* R18598 */ + { 0x0000, 0x0000, 0x0000 }, /* R18599 */ + { 0x0000, 0x0000, 0x0000 }, /* R18600 */ + { 0x0000, 0x0000, 0x0000 }, /* R18601 */ + { 0x0000, 0x0000, 0x0000 }, /* R18602 */ + { 0x0000, 0x0000, 0x0000 }, /* R18603 */ + { 0x0000, 0x0000, 0x0000 }, /* R18604 */ + { 0x0000, 0x0000, 0x0000 }, /* R18605 */ + { 0x0000, 0x0000, 0x0000 }, /* R18606 */ + { 0x0000, 0x0000, 0x0000 }, /* R18607 */ + { 0x0000, 0x0000, 0x0000 }, /* R18608 */ + { 0x0000, 0x0000, 0x0000 }, /* R18609 */ + { 0x0000, 0x0000, 0x0000 }, /* R18610 */ + { 0x0000, 0x0000, 0x0000 }, /* R18611 */ + { 0x0000, 0x0000, 0x0000 }, /* R18612 */ + { 0x0000, 0x0000, 0x0000 }, /* R18613 */ + { 0x0000, 0x0000, 0x0000 }, /* R18614 */ + { 0x0000, 0x0000, 0x0000 }, /* R18615 */ + { 0x0000, 0x0000, 0x0000 }, /* R18616 */ + { 0x0000, 0x0000, 0x0000 }, /* R18617 */ + { 0x0000, 0x0000, 0x0000 }, /* R18618 */ + { 0x0000, 0x0000, 0x0000 }, /* R18619 */ + { 0x0000, 0x0000, 0x0000 }, /* R18620 */ + { 0x0000, 0x0000, 0x0000 }, /* R18621 */ + { 0x0000, 0x0000, 0x0000 }, /* R18622 */ + { 0x0000, 0x0000, 0x0000 }, /* R18623 */ + { 0x0000, 0x0000, 0x0000 }, /* R18624 */ + { 0x0000, 0x0000, 0x0000 }, /* R18625 */ + { 0x0000, 0x0000, 0x0000 }, /* R18626 */ + { 0x0000, 0x0000, 0x0000 }, /* R18627 */ + { 0x0000, 0x0000, 0x0000 }, /* R18628 */ + { 0x0000, 0x0000, 0x0000 }, /* R18629 */ + { 0x0000, 0x0000, 0x0000 }, /* R18630 */ + { 0x0000, 0x0000, 0x0000 }, /* R18631 */ + { 0x0000, 0x0000, 0x0000 }, /* R18632 */ + { 0x0000, 0x0000, 0x0000 }, /* R18633 */ + { 0x0000, 0x0000, 0x0000 }, /* R18634 */ + { 0x0000, 0x0000, 0x0000 }, /* R18635 */ + { 0x0000, 0x0000, 0x0000 }, /* R18636 */ + { 0x0000, 0x0000, 0x0000 }, /* R18637 */ + { 0x0000, 0x0000, 0x0000 }, /* R18638 */ + { 0x0000, 0x0000, 0x0000 }, /* R18639 */ + { 0x0000, 0x0000, 0x0000 }, /* R18640 */ + { 0x0000, 0x0000, 0x0000 }, /* R18641 */ + { 0x0000, 0x0000, 0x0000 }, /* R18642 */ + { 0x0000, 0x0000, 0x0000 }, /* R18643 */ + { 0x0000, 0x0000, 0x0000 }, /* R18644 */ + { 0x0000, 0x0000, 0x0000 }, /* R18645 */ + { 0x0000, 0x0000, 0x0000 }, /* R18646 */ + { 0x0000, 0x0000, 0x0000 }, /* R18647 */ + { 0x0000, 0x0000, 0x0000 }, /* R18648 */ + { 0x0000, 0x0000, 0x0000 }, /* R18649 */ + { 0x0000, 0x0000, 0x0000 }, /* R18650 */ + { 0x0000, 0x0000, 0x0000 }, /* R18651 */ + { 0x0000, 0x0000, 0x0000 }, /* R18652 */ + { 0x0000, 0x0000, 0x0000 }, /* R18653 */ + { 0x0000, 0x0000, 0x0000 }, /* R18654 */ + { 0x0000, 0x0000, 0x0000 }, /* R18655 */ + { 0x0000, 0x0000, 0x0000 }, /* R18656 */ + { 0x0000, 0x0000, 0x0000 }, /* R18657 */ + { 0x0000, 0x0000, 0x0000 }, /* R18658 */ + { 0x0000, 0x0000, 0x0000 }, /* R18659 */ + { 0x0000, 0x0000, 0x0000 }, /* R18660 */ + { 0x0000, 0x0000, 0x0000 }, /* R18661 */ + { 0x0000, 0x0000, 0x0000 }, /* R18662 */ + { 0x0000, 0x0000, 0x0000 }, /* R18663 */ + { 0x0000, 0x0000, 0x0000 }, /* R18664 */ + { 0x0000, 0x0000, 0x0000 }, /* R18665 */ + { 0x0000, 0x0000, 0x0000 }, /* R18666 */ + { 0x0000, 0x0000, 0x0000 }, /* R18667 */ + { 0x0000, 0x0000, 0x0000 }, /* R18668 */ + { 0x0000, 0x0000, 0x0000 }, /* R18669 */ + { 0x0000, 0x0000, 0x0000 }, /* R18670 */ + { 0x0000, 0x0000, 0x0000 }, /* R18671 */ + { 0x0000, 0x0000, 0x0000 }, /* R18672 */ + { 0x0000, 0x0000, 0x0000 }, /* R18673 */ + { 0x0000, 0x0000, 0x0000 }, /* R18674 */ + { 0x0000, 0x0000, 0x0000 }, /* R18675 */ + { 0x0000, 0x0000, 0x0000 }, /* R18676 */ + { 0x0000, 0x0000, 0x0000 }, /* R18677 */ + { 0x0000, 0x0000, 0x0000 }, /* R18678 */ + { 0x0000, 0x0000, 0x0000 }, /* R18679 */ + { 0x0000, 0x0000, 0x0000 }, /* R18680 */ + { 0x0000, 0x0000, 0x0000 }, /* R18681 */ + { 0x0000, 0x0000, 0x0000 }, /* R18682 */ + { 0x0000, 0x0000, 0x0000 }, /* R18683 */ + { 0x0000, 0x0000, 0x0000 }, /* R18684 */ + { 0x0000, 0x0000, 0x0000 }, /* R18685 */ + { 0x0000, 0x0000, 0x0000 }, /* R18686 */ + { 0x0000, 0x0000, 0x0000 }, /* R18687 */ + { 0x0000, 0x0000, 0x0000 }, /* R18688 */ + { 0x0000, 0x0000, 0x0000 }, /* R18689 */ + { 0x0000, 0x0000, 0x0000 }, /* R18690 */ + { 0x0000, 0x0000, 0x0000 }, /* R18691 */ + { 0x0000, 0x0000, 0x0000 }, /* R18692 */ + { 0x0000, 0x0000, 0x0000 }, /* R18693 */ + { 0x0000, 0x0000, 0x0000 }, /* R18694 */ + { 0x0000, 0x0000, 0x0000 }, /* R18695 */ + { 0x0000, 0x0000, 0x0000 }, /* R18696 */ + { 0x0000, 0x0000, 0x0000 }, /* R18697 */ + { 0x0000, 0x0000, 0x0000 }, /* R18698 */ + { 0x0000, 0x0000, 0x0000 }, /* R18699 */ + { 0x0000, 0x0000, 0x0000 }, /* R18700 */ + { 0x0000, 0x0000, 0x0000 }, /* R18701 */ + { 0x0000, 0x0000, 0x0000 }, /* R18702 */ + { 0x0000, 0x0000, 0x0000 }, /* R18703 */ + { 0x0000, 0x0000, 0x0000 }, /* R18704 */ + { 0x0000, 0x0000, 0x0000 }, /* R18705 */ + { 0x0000, 0x0000, 0x0000 }, /* R18706 */ + { 0x0000, 0x0000, 0x0000 }, /* R18707 */ + { 0x0000, 0x0000, 0x0000 }, /* R18708 */ + { 0x0000, 0x0000, 0x0000 }, /* R18709 */ + { 0x0000, 0x0000, 0x0000 }, /* R18710 */ + { 0x0000, 0x0000, 0x0000 }, /* R18711 */ + { 0x0000, 0x0000, 0x0000 }, /* R18712 */ + { 0x0000, 0x0000, 0x0000 }, /* R18713 */ + { 0x0000, 0x0000, 0x0000 }, /* R18714 */ + { 0x0000, 0x0000, 0x0000 }, /* R18715 */ + { 0x0000, 0x0000, 0x0000 }, /* R18716 */ + { 0x0000, 0x0000, 0x0000 }, /* R18717 */ + { 0x0000, 0x0000, 0x0000 }, /* R18718 */ + { 0x0000, 0x0000, 0x0000 }, /* R18719 */ + { 0x0000, 0x0000, 0x0000 }, /* R18720 */ + { 0x0000, 0x0000, 0x0000 }, /* R18721 */ + { 0x0000, 0x0000, 0x0000 }, /* R18722 */ + { 0x0000, 0x0000, 0x0000 }, /* R18723 */ + { 0x0000, 0x0000, 0x0000 }, /* R18724 */ + { 0x0000, 0x0000, 0x0000 }, /* R18725 */ + { 0x0000, 0x0000, 0x0000 }, /* R18726 */ + { 0x0000, 0x0000, 0x0000 }, /* R18727 */ + { 0x0000, 0x0000, 0x0000 }, /* R18728 */ + { 0x0000, 0x0000, 0x0000 }, /* R18729 */ + { 0x0000, 0x0000, 0x0000 }, /* R18730 */ + { 0x0000, 0x0000, 0x0000 }, /* R18731 */ + { 0x0000, 0x0000, 0x0000 }, /* R18732 */ + { 0x0000, 0x0000, 0x0000 }, /* R18733 */ + { 0x0000, 0x0000, 0x0000 }, /* R18734 */ + { 0x0000, 0x0000, 0x0000 }, /* R18735 */ + { 0x0000, 0x0000, 0x0000 }, /* R18736 */ + { 0x0000, 0x0000, 0x0000 }, /* R18737 */ + { 0x0000, 0x0000, 0x0000 }, /* R18738 */ + { 0x0000, 0x0000, 0x0000 }, /* R18739 */ + { 0x0000, 0x0000, 0x0000 }, /* R18740 */ + { 0x0000, 0x0000, 0x0000 }, /* R18741 */ + { 0x0000, 0x0000, 0x0000 }, /* R18742 */ + { 0x0000, 0x0000, 0x0000 }, /* R18743 */ + { 0x0000, 0x0000, 0x0000 }, /* R18744 */ + { 0x0000, 0x0000, 0x0000 }, /* R18745 */ + { 0x0000, 0x0000, 0x0000 }, /* R18746 */ + { 0x0000, 0x0000, 0x0000 }, /* R18747 */ + { 0x0000, 0x0000, 0x0000 }, /* R18748 */ + { 0x0000, 0x0000, 0x0000 }, /* R18749 */ + { 0x0000, 0x0000, 0x0000 }, /* R18750 */ + { 0x0000, 0x0000, 0x0000 }, /* R18751 */ + { 0x0000, 0x0000, 0x0000 }, /* R18752 */ + { 0x0000, 0x0000, 0x0000 }, /* R18753 */ + { 0x0000, 0x0000, 0x0000 }, /* R18754 */ + { 0x0000, 0x0000, 0x0000 }, /* R18755 */ + { 0x0000, 0x0000, 0x0000 }, /* R18756 */ + { 0x0000, 0x0000, 0x0000 }, /* R18757 */ + { 0x0000, 0x0000, 0x0000 }, /* R18758 */ + { 0x0000, 0x0000, 0x0000 }, /* R18759 */ + { 0x0000, 0x0000, 0x0000 }, /* R18760 */ + { 0x0000, 0x0000, 0x0000 }, /* R18761 */ + { 0x0000, 0x0000, 0x0000 }, /* R18762 */ + { 0x0000, 0x0000, 0x0000 }, /* R18763 */ + { 0x0000, 0x0000, 0x0000 }, /* R18764 */ + { 0x0000, 0x0000, 0x0000 }, /* R18765 */ + { 0x0000, 0x0000, 0x0000 }, /* R18766 */ + { 0x0000, 0x0000, 0x0000 }, /* R18767 */ + { 0x0000, 0x0000, 0x0000 }, /* R18768 */ + { 0x0000, 0x0000, 0x0000 }, /* R18769 */ + { 0x0000, 0x0000, 0x0000 }, /* R18770 */ + { 0x0000, 0x0000, 0x0000 }, /* R18771 */ + { 0x0000, 0x0000, 0x0000 }, /* R18772 */ + { 0x0000, 0x0000, 0x0000 }, /* R18773 */ + { 0x0000, 0x0000, 0x0000 }, /* R18774 */ + { 0x0000, 0x0000, 0x0000 }, /* R18775 */ + { 0x0000, 0x0000, 0x0000 }, /* R18776 */ + { 0x0000, 0x0000, 0x0000 }, /* R18777 */ + { 0x0000, 0x0000, 0x0000 }, /* R18778 */ + { 0x0000, 0x0000, 0x0000 }, /* R18779 */ + { 0x0000, 0x0000, 0x0000 }, /* R18780 */ + { 0x0000, 0x0000, 0x0000 }, /* R18781 */ + { 0x0000, 0x0000, 0x0000 }, /* R18782 */ + { 0x0000, 0x0000, 0x0000 }, /* R18783 */ + { 0x0000, 0x0000, 0x0000 }, /* R18784 */ + { 0x0000, 0x0000, 0x0000 }, /* R18785 */ + { 0x0000, 0x0000, 0x0000 }, /* R18786 */ + { 0x0000, 0x0000, 0x0000 }, /* R18787 */ + { 0x0000, 0x0000, 0x0000 }, /* R18788 */ + { 0x0000, 0x0000, 0x0000 }, /* R18789 */ + { 0x0000, 0x0000, 0x0000 }, /* R18790 */ + { 0x0000, 0x0000, 0x0000 }, /* R18791 */ + { 0x0000, 0x0000, 0x0000 }, /* R18792 */ + { 0x0000, 0x0000, 0x0000 }, /* R18793 */ + { 0x0000, 0x0000, 0x0000 }, /* R18794 */ + { 0x0000, 0x0000, 0x0000 }, /* R18795 */ + { 0x0000, 0x0000, 0x0000 }, /* R18796 */ + { 0x0000, 0x0000, 0x0000 }, /* R18797 */ + { 0x0000, 0x0000, 0x0000 }, /* R18798 */ + { 0x0000, 0x0000, 0x0000 }, /* R18799 */ + { 0x0000, 0x0000, 0x0000 }, /* R18800 */ + { 0x0000, 0x0000, 0x0000 }, /* R18801 */ + { 0x0000, 0x0000, 0x0000 }, /* R18802 */ + { 0x0000, 0x0000, 0x0000 }, /* R18803 */ + { 0x0000, 0x0000, 0x0000 }, /* R18804 */ + { 0x0000, 0x0000, 0x0000 }, /* R18805 */ + { 0x0000, 0x0000, 0x0000 }, /* R18806 */ + { 0x0000, 0x0000, 0x0000 }, /* R18807 */ + { 0x0000, 0x0000, 0x0000 }, /* R18808 */ + { 0x0000, 0x0000, 0x0000 }, /* R18809 */ + { 0x0000, 0x0000, 0x0000 }, /* R18810 */ + { 0x0000, 0x0000, 0x0000 }, /* R18811 */ + { 0x0000, 0x0000, 0x0000 }, /* R18812 */ + { 0x0000, 0x0000, 0x0000 }, /* R18813 */ + { 0x0000, 0x0000, 0x0000 }, /* R18814 */ + { 0x0000, 0x0000, 0x0000 }, /* R18815 */ + { 0x0000, 0x0000, 0x0000 }, /* R18816 */ + { 0x0000, 0x0000, 0x0000 }, /* R18817 */ + { 0x0000, 0x0000, 0x0000 }, /* R18818 */ + { 0x0000, 0x0000, 0x0000 }, /* R18819 */ + { 0x0000, 0x0000, 0x0000 }, /* R18820 */ + { 0x0000, 0x0000, 0x0000 }, /* R18821 */ + { 0x0000, 0x0000, 0x0000 }, /* R18822 */ + { 0x0000, 0x0000, 0x0000 }, /* R18823 */ + { 0x0000, 0x0000, 0x0000 }, /* R18824 */ + { 0x0000, 0x0000, 0x0000 }, /* R18825 */ + { 0x0000, 0x0000, 0x0000 }, /* R18826 */ + { 0x0000, 0x0000, 0x0000 }, /* R18827 */ + { 0x0000, 0x0000, 0x0000 }, /* R18828 */ + { 0x0000, 0x0000, 0x0000 }, /* R18829 */ + { 0x0000, 0x0000, 0x0000 }, /* R18830 */ + { 0x0000, 0x0000, 0x0000 }, /* R18831 */ + { 0x0000, 0x0000, 0x0000 }, /* R18832 */ + { 0x0000, 0x0000, 0x0000 }, /* R18833 */ + { 0x0000, 0x0000, 0x0000 }, /* R18834 */ + { 0x0000, 0x0000, 0x0000 }, /* R18835 */ + { 0x0000, 0x0000, 0x0000 }, /* R18836 */ + { 0x0000, 0x0000, 0x0000 }, /* R18837 */ + { 0x0000, 0x0000, 0x0000 }, /* R18838 */ + { 0x0000, 0x0000, 0x0000 }, /* R18839 */ + { 0x0000, 0x0000, 0x0000 }, /* R18840 */ + { 0x0000, 0x0000, 0x0000 }, /* R18841 */ + { 0x0000, 0x0000, 0x0000 }, /* R18842 */ + { 0x0000, 0x0000, 0x0000 }, /* R18843 */ + { 0x0000, 0x0000, 0x0000 }, /* R18844 */ + { 0x0000, 0x0000, 0x0000 }, /* R18845 */ + { 0x0000, 0x0000, 0x0000 }, /* R18846 */ + { 0x0000, 0x0000, 0x0000 }, /* R18847 */ + { 0x0000, 0x0000, 0x0000 }, /* R18848 */ + { 0x0000, 0x0000, 0x0000 }, /* R18849 */ + { 0x0000, 0x0000, 0x0000 }, /* R18850 */ + { 0x0000, 0x0000, 0x0000 }, /* R18851 */ + { 0x0000, 0x0000, 0x0000 }, /* R18852 */ + { 0x0000, 0x0000, 0x0000 }, /* R18853 */ + { 0x0000, 0x0000, 0x0000 }, /* R18854 */ + { 0x0000, 0x0000, 0x0000 }, /* R18855 */ + { 0x0000, 0x0000, 0x0000 }, /* R18856 */ + { 0x0000, 0x0000, 0x0000 }, /* R18857 */ + { 0x0000, 0x0000, 0x0000 }, /* R18858 */ + { 0x0000, 0x0000, 0x0000 }, /* R18859 */ + { 0x0000, 0x0000, 0x0000 }, /* R18860 */ + { 0x0000, 0x0000, 0x0000 }, /* R18861 */ + { 0x0000, 0x0000, 0x0000 }, /* R18862 */ + { 0x0000, 0x0000, 0x0000 }, /* R18863 */ + { 0x0000, 0x0000, 0x0000 }, /* R18864 */ + { 0x0000, 0x0000, 0x0000 }, /* R18865 */ + { 0x0000, 0x0000, 0x0000 }, /* R18866 */ + { 0x0000, 0x0000, 0x0000 }, /* R18867 */ + { 0x0000, 0x0000, 0x0000 }, /* R18868 */ + { 0x0000, 0x0000, 0x0000 }, /* R18869 */ + { 0x0000, 0x0000, 0x0000 }, /* R18870 */ + { 0x0000, 0x0000, 0x0000 }, /* R18871 */ + { 0x0000, 0x0000, 0x0000 }, /* R18872 */ + { 0x0000, 0x0000, 0x0000 }, /* R18873 */ + { 0x0000, 0x0000, 0x0000 }, /* R18874 */ + { 0x0000, 0x0000, 0x0000 }, /* R18875 */ + { 0x0000, 0x0000, 0x0000 }, /* R18876 */ + { 0x0000, 0x0000, 0x0000 }, /* R18877 */ + { 0x0000, 0x0000, 0x0000 }, /* R18878 */ + { 0x0000, 0x0000, 0x0000 }, /* R18879 */ + { 0x0000, 0x0000, 0x0000 }, /* R18880 */ + { 0x0000, 0x0000, 0x0000 }, /* R18881 */ + { 0x0000, 0x0000, 0x0000 }, /* R18882 */ + { 0x0000, 0x0000, 0x0000 }, /* R18883 */ + { 0x0000, 0x0000, 0x0000 }, /* R18884 */ + { 0x0000, 0x0000, 0x0000 }, /* R18885 */ + { 0x0000, 0x0000, 0x0000 }, /* R18886 */ + { 0x0000, 0x0000, 0x0000 }, /* R18887 */ + { 0x0000, 0x0000, 0x0000 }, /* R18888 */ + { 0x0000, 0x0000, 0x0000 }, /* R18889 */ + { 0x0000, 0x0000, 0x0000 }, /* R18890 */ + { 0x0000, 0x0000, 0x0000 }, /* R18891 */ + { 0x0000, 0x0000, 0x0000 }, /* R18892 */ + { 0x0000, 0x0000, 0x0000 }, /* R18893 */ + { 0x0000, 0x0000, 0x0000 }, /* R18894 */ + { 0x0000, 0x0000, 0x0000 }, /* R18895 */ + { 0x0000, 0x0000, 0x0000 }, /* R18896 */ + { 0x0000, 0x0000, 0x0000 }, /* R18897 */ + { 0x0000, 0x0000, 0x0000 }, /* R18898 */ + { 0x0000, 0x0000, 0x0000 }, /* R18899 */ + { 0x0000, 0x0000, 0x0000 }, /* R18900 */ + { 0x0000, 0x0000, 0x0000 }, /* R18901 */ + { 0x0000, 0x0000, 0x0000 }, /* R18902 */ + { 0x0000, 0x0000, 0x0000 }, /* R18903 */ + { 0x0000, 0x0000, 0x0000 }, /* R18904 */ + { 0x0000, 0x0000, 0x0000 }, /* R18905 */ + { 0x0000, 0x0000, 0x0000 }, /* R18906 */ + { 0x0000, 0x0000, 0x0000 }, /* R18907 */ + { 0x0000, 0x0000, 0x0000 }, /* R18908 */ + { 0x0000, 0x0000, 0x0000 }, /* R18909 */ + { 0x0000, 0x0000, 0x0000 }, /* R18910 */ + { 0x0000, 0x0000, 0x0000 }, /* R18911 */ + { 0x0000, 0x0000, 0x0000 }, /* R18912 */ + { 0x0000, 0x0000, 0x0000 }, /* R18913 */ + { 0x0000, 0x0000, 0x0000 }, /* R18914 */ + { 0x0000, 0x0000, 0x0000 }, /* R18915 */ + { 0x0000, 0x0000, 0x0000 }, /* R18916 */ + { 0x0000, 0x0000, 0x0000 }, /* R18917 */ + { 0x0000, 0x0000, 0x0000 }, /* R18918 */ + { 0x0000, 0x0000, 0x0000 }, /* R18919 */ + { 0x0000, 0x0000, 0x0000 }, /* R18920 */ + { 0x0000, 0x0000, 0x0000 }, /* R18921 */ + { 0x0000, 0x0000, 0x0000 }, /* R18922 */ + { 0x0000, 0x0000, 0x0000 }, /* R18923 */ + { 0x0000, 0x0000, 0x0000 }, /* R18924 */ + { 0x0000, 0x0000, 0x0000 }, /* R18925 */ + { 0x0000, 0x0000, 0x0000 }, /* R18926 */ + { 0x0000, 0x0000, 0x0000 }, /* R18927 */ + { 0x0000, 0x0000, 0x0000 }, /* R18928 */ + { 0x0000, 0x0000, 0x0000 }, /* R18929 */ + { 0x0000, 0x0000, 0x0000 }, /* R18930 */ + { 0x0000, 0x0000, 0x0000 }, /* R18931 */ + { 0x0000, 0x0000, 0x0000 }, /* R18932 */ + { 0x0000, 0x0000, 0x0000 }, /* R18933 */ + { 0x0000, 0x0000, 0x0000 }, /* R18934 */ + { 0x0000, 0x0000, 0x0000 }, /* R18935 */ + { 0x0000, 0x0000, 0x0000 }, /* R18936 */ + { 0x0000, 0x0000, 0x0000 }, /* R18937 */ + { 0x0000, 0x0000, 0x0000 }, /* R18938 */ + { 0x0000, 0x0000, 0x0000 }, /* R18939 */ + { 0x0000, 0x0000, 0x0000 }, /* R18940 */ + { 0x0000, 0x0000, 0x0000 }, /* R18941 */ + { 0x0000, 0x0000, 0x0000 }, /* R18942 */ + { 0x0000, 0x0000, 0x0000 }, /* R18943 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18944 - ADCR_RETUNE_C1_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18945 - ADCR_RETUNE_C1_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18946 - ADCR_RETUNE_C2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18947 - ADCR_RETUNE_C2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18948 - ADCR_RETUNE_C3_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18949 - ADCR_RETUNE_C3_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18950 - ADCR_RETUNE_C4_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18951 - ADCR_RETUNE_C4_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18952 - ADCR_RETUNE_C5_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18953 - ADCR_RETUNE_C5_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18954 - ADCR_RETUNE_C6_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18955 - ADCR_RETUNE_C6_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18956 - ADCR_RETUNE_C7_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18957 - ADCR_RETUNE_C7_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18958 - ADCR_RETUNE_C8_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18959 - ADCR_RETUNE_C8_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18960 - ADCR_RETUNE_C9_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18961 - ADCR_RETUNE_C9_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18962 - ADCR_RETUNE_C10_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18963 - ADCR_RETUNE_C10_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18964 - ADCR_RETUNE_C11_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18965 - ADCR_RETUNE_C11_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18966 - ADCR_RETUNE_C12_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18967 - ADCR_RETUNE_C12_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18968 - ADCR_RETUNE_C13_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18969 - ADCR_RETUNE_C13_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18970 - ADCR_RETUNE_C14_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18971 - ADCR_RETUNE_C14_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18972 - ADCR_RETUNE_C15_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18973 - ADCR_RETUNE_C15_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18974 - ADCR_RETUNE_C16_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18975 - ADCR_RETUNE_C16_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18976 - ADCR_RETUNE_C17_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18977 - ADCR_RETUNE_C17_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18978 - ADCR_RETUNE_C18_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18979 - ADCR_RETUNE_C18_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18980 - ADCR_RETUNE_C19_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18981 - ADCR_RETUNE_C19_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18982 - ADCR_RETUNE_C20_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18983 - ADCR_RETUNE_C20_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18984 - ADCR_RETUNE_C21_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18985 - ADCR_RETUNE_C21_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18986 - ADCR_RETUNE_C22_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18987 - ADCR_RETUNE_C22_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18988 - ADCR_RETUNE_C23_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18989 - ADCR_RETUNE_C23_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18990 - ADCR_RETUNE_C24_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18991 - ADCR_RETUNE_C24_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18992 - ADCR_RETUNE_C25_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18993 - ADCR_RETUNE_C25_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18994 - ADCR_RETUNE_C26_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18995 - ADCR_RETUNE_C26_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18996 - ADCR_RETUNE_C27_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18997 - ADCR_RETUNE_C27_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R18998 - ADCR_RETUNE_C28_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R18999 - ADCR_RETUNE_C28_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19000 - ADCR_RETUNE_C29_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19001 - ADCR_RETUNE_C29_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19002 - ADCR_RETUNE_C30_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19003 - ADCR_RETUNE_C30_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19004 - ADCR_RETUNE_C31_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19005 - ADCR_RETUNE_C31_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19006 - ADCR_RETUNE_C32_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19007 - ADCR_RETUNE_C32_0 */ + { 0x0000, 0x0000, 0x0000 }, /* R19008 */ + { 0x0000, 0x0000, 0x0000 }, /* R19009 */ + { 0x0000, 0x0000, 0x0000 }, /* R19010 */ + { 0x0000, 0x0000, 0x0000 }, /* R19011 */ + { 0x0000, 0x0000, 0x0000 }, /* R19012 */ + { 0x0000, 0x0000, 0x0000 }, /* R19013 */ + { 0x0000, 0x0000, 0x0000 }, /* R19014 */ + { 0x0000, 0x0000, 0x0000 }, /* R19015 */ + { 0x0000, 0x0000, 0x0000 }, /* R19016 */ + { 0x0000, 0x0000, 0x0000 }, /* R19017 */ + { 0x0000, 0x0000, 0x0000 }, /* R19018 */ + { 0x0000, 0x0000, 0x0000 }, /* R19019 */ + { 0x0000, 0x0000, 0x0000 }, /* R19020 */ + { 0x0000, 0x0000, 0x0000 }, /* R19021 */ + { 0x0000, 0x0000, 0x0000 }, /* R19022 */ + { 0x0000, 0x0000, 0x0000 }, /* R19023 */ + { 0x0000, 0x0000, 0x0000 }, /* R19024 */ + { 0x0000, 0x0000, 0x0000 }, /* R19025 */ + { 0x0000, 0x0000, 0x0000 }, /* R19026 */ + { 0x0000, 0x0000, 0x0000 }, /* R19027 */ + { 0x0000, 0x0000, 0x0000 }, /* R19028 */ + { 0x0000, 0x0000, 0x0000 }, /* R19029 */ + { 0x0000, 0x0000, 0x0000 }, /* R19030 */ + { 0x0000, 0x0000, 0x0000 }, /* R19031 */ + { 0x0000, 0x0000, 0x0000 }, /* R19032 */ + { 0x0000, 0x0000, 0x0000 }, /* R19033 */ + { 0x0000, 0x0000, 0x0000 }, /* R19034 */ + { 0x0000, 0x0000, 0x0000 }, /* R19035 */ + { 0x0000, 0x0000, 0x0000 }, /* R19036 */ + { 0x0000, 0x0000, 0x0000 }, /* R19037 */ + { 0x0000, 0x0000, 0x0000 }, /* R19038 */ + { 0x0000, 0x0000, 0x0000 }, /* R19039 */ + { 0x0000, 0x0000, 0x0000 }, /* R19040 */ + { 0x0000, 0x0000, 0x0000 }, /* R19041 */ + { 0x0000, 0x0000, 0x0000 }, /* R19042 */ + { 0x0000, 0x0000, 0x0000 }, /* R19043 */ + { 0x0000, 0x0000, 0x0000 }, /* R19044 */ + { 0x0000, 0x0000, 0x0000 }, /* R19045 */ + { 0x0000, 0x0000, 0x0000 }, /* R19046 */ + { 0x0000, 0x0000, 0x0000 }, /* R19047 */ + { 0x0000, 0x0000, 0x0000 }, /* R19048 */ + { 0x0000, 0x0000, 0x0000 }, /* R19049 */ + { 0x0000, 0x0000, 0x0000 }, /* R19050 */ + { 0x0000, 0x0000, 0x0000 }, /* R19051 */ + { 0x0000, 0x0000, 0x0000 }, /* R19052 */ + { 0x0000, 0x0000, 0x0000 }, /* R19053 */ + { 0x0000, 0x0000, 0x0000 }, /* R19054 */ + { 0x0000, 0x0000, 0x0000 }, /* R19055 */ + { 0x0000, 0x0000, 0x0000 }, /* R19056 */ + { 0x0000, 0x0000, 0x0000 }, /* R19057 */ + { 0x0000, 0x0000, 0x0000 }, /* R19058 */ + { 0x0000, 0x0000, 0x0000 }, /* R19059 */ + { 0x0000, 0x0000, 0x0000 }, /* R19060 */ + { 0x0000, 0x0000, 0x0000 }, /* R19061 */ + { 0x0000, 0x0000, 0x0000 }, /* R19062 */ + { 0x0000, 0x0000, 0x0000 }, /* R19063 */ + { 0x0000, 0x0000, 0x0000 }, /* R19064 */ + { 0x0000, 0x0000, 0x0000 }, /* R19065 */ + { 0x0000, 0x0000, 0x0000 }, /* R19066 */ + { 0x0000, 0x0000, 0x0000 }, /* R19067 */ + { 0x0000, 0x0000, 0x0000 }, /* R19068 */ + { 0x0000, 0x0000, 0x0000 }, /* R19069 */ + { 0x0000, 0x0000, 0x0000 }, /* R19070 */ + { 0x0000, 0x0000, 0x0000 }, /* R19071 */ + { 0x0000, 0x0000, 0x0000 }, /* R19072 */ + { 0x0000, 0x0000, 0x0000 }, /* R19073 */ + { 0x0000, 0x0000, 0x0000 }, /* R19074 */ + { 0x0000, 0x0000, 0x0000 }, /* R19075 */ + { 0x0000, 0x0000, 0x0000 }, /* R19076 */ + { 0x0000, 0x0000, 0x0000 }, /* R19077 */ + { 0x0000, 0x0000, 0x0000 }, /* R19078 */ + { 0x0000, 0x0000, 0x0000 }, /* R19079 */ + { 0x0000, 0x0000, 0x0000 }, /* R19080 */ + { 0x0000, 0x0000, 0x0000 }, /* R19081 */ + { 0x0000, 0x0000, 0x0000 }, /* R19082 */ + { 0x0000, 0x0000, 0x0000 }, /* R19083 */ + { 0x0000, 0x0000, 0x0000 }, /* R19084 */ + { 0x0000, 0x0000, 0x0000 }, /* R19085 */ + { 0x0000, 0x0000, 0x0000 }, /* R19086 */ + { 0x0000, 0x0000, 0x0000 }, /* R19087 */ + { 0x0000, 0x0000, 0x0000 }, /* R19088 */ + { 0x0000, 0x0000, 0x0000 }, /* R19089 */ + { 0x0000, 0x0000, 0x0000 }, /* R19090 */ + { 0x0000, 0x0000, 0x0000 }, /* R19091 */ + { 0x0000, 0x0000, 0x0000 }, /* R19092 */ + { 0x0000, 0x0000, 0x0000 }, /* R19093 */ + { 0x0000, 0x0000, 0x0000 }, /* R19094 */ + { 0x0000, 0x0000, 0x0000 }, /* R19095 */ + { 0x0000, 0x0000, 0x0000 }, /* R19096 */ + { 0x0000, 0x0000, 0x0000 }, /* R19097 */ + { 0x0000, 0x0000, 0x0000 }, /* R19098 */ + { 0x0000, 0x0000, 0x0000 }, /* R19099 */ + { 0x0000, 0x0000, 0x0000 }, /* R19100 */ + { 0x0000, 0x0000, 0x0000 }, /* R19101 */ + { 0x0000, 0x0000, 0x0000 }, /* R19102 */ + { 0x0000, 0x0000, 0x0000 }, /* R19103 */ + { 0x0000, 0x0000, 0x0000 }, /* R19104 */ + { 0x0000, 0x0000, 0x0000 }, /* R19105 */ + { 0x0000, 0x0000, 0x0000 }, /* R19106 */ + { 0x0000, 0x0000, 0x0000 }, /* R19107 */ + { 0x0000, 0x0000, 0x0000 }, /* R19108 */ + { 0x0000, 0x0000, 0x0000 }, /* R19109 */ + { 0x0000, 0x0000, 0x0000 }, /* R19110 */ + { 0x0000, 0x0000, 0x0000 }, /* R19111 */ + { 0x0000, 0x0000, 0x0000 }, /* R19112 */ + { 0x0000, 0x0000, 0x0000 }, /* R19113 */ + { 0x0000, 0x0000, 0x0000 }, /* R19114 */ + { 0x0000, 0x0000, 0x0000 }, /* R19115 */ + { 0x0000, 0x0000, 0x0000 }, /* R19116 */ + { 0x0000, 0x0000, 0x0000 }, /* R19117 */ + { 0x0000, 0x0000, 0x0000 }, /* R19118 */ + { 0x0000, 0x0000, 0x0000 }, /* R19119 */ + { 0x0000, 0x0000, 0x0000 }, /* R19120 */ + { 0x0000, 0x0000, 0x0000 }, /* R19121 */ + { 0x0000, 0x0000, 0x0000 }, /* R19122 */ + { 0x0000, 0x0000, 0x0000 }, /* R19123 */ + { 0x0000, 0x0000, 0x0000 }, /* R19124 */ + { 0x0000, 0x0000, 0x0000 }, /* R19125 */ + { 0x0000, 0x0000, 0x0000 }, /* R19126 */ + { 0x0000, 0x0000, 0x0000 }, /* R19127 */ + { 0x0000, 0x0000, 0x0000 }, /* R19128 */ + { 0x0000, 0x0000, 0x0000 }, /* R19129 */ + { 0x0000, 0x0000, 0x0000 }, /* R19130 */ + { 0x0000, 0x0000, 0x0000 }, /* R19131 */ + { 0x0000, 0x0000, 0x0000 }, /* R19132 */ + { 0x0000, 0x0000, 0x0000 }, /* R19133 */ + { 0x0000, 0x0000, 0x0000 }, /* R19134 */ + { 0x0000, 0x0000, 0x0000 }, /* R19135 */ + { 0x0000, 0x0000, 0x0000 }, /* R19136 */ + { 0x0000, 0x0000, 0x0000 }, /* R19137 */ + { 0x0000, 0x0000, 0x0000 }, /* R19138 */ + { 0x0000, 0x0000, 0x0000 }, /* R19139 */ + { 0x0000, 0x0000, 0x0000 }, /* R19140 */ + { 0x0000, 0x0000, 0x0000 }, /* R19141 */ + { 0x0000, 0x0000, 0x0000 }, /* R19142 */ + { 0x0000, 0x0000, 0x0000 }, /* R19143 */ + { 0x0000, 0x0000, 0x0000 }, /* R19144 */ + { 0x0000, 0x0000, 0x0000 }, /* R19145 */ + { 0x0000, 0x0000, 0x0000 }, /* R19146 */ + { 0x0000, 0x0000, 0x0000 }, /* R19147 */ + { 0x0000, 0x0000, 0x0000 }, /* R19148 */ + { 0x0000, 0x0000, 0x0000 }, /* R19149 */ + { 0x0000, 0x0000, 0x0000 }, /* R19150 */ + { 0x0000, 0x0000, 0x0000 }, /* R19151 */ + { 0x0000, 0x0000, 0x0000 }, /* R19152 */ + { 0x0000, 0x0000, 0x0000 }, /* R19153 */ + { 0x0000, 0x0000, 0x0000 }, /* R19154 */ + { 0x0000, 0x0000, 0x0000 }, /* R19155 */ + { 0x0000, 0x0000, 0x0000 }, /* R19156 */ + { 0x0000, 0x0000, 0x0000 }, /* R19157 */ + { 0x0000, 0x0000, 0x0000 }, /* R19158 */ + { 0x0000, 0x0000, 0x0000 }, /* R19159 */ + { 0x0000, 0x0000, 0x0000 }, /* R19160 */ + { 0x0000, 0x0000, 0x0000 }, /* R19161 */ + { 0x0000, 0x0000, 0x0000 }, /* R19162 */ + { 0x0000, 0x0000, 0x0000 }, /* R19163 */ + { 0x0000, 0x0000, 0x0000 }, /* R19164 */ + { 0x0000, 0x0000, 0x0000 }, /* R19165 */ + { 0x0000, 0x0000, 0x0000 }, /* R19166 */ + { 0x0000, 0x0000, 0x0000 }, /* R19167 */ + { 0x0000, 0x0000, 0x0000 }, /* R19168 */ + { 0x0000, 0x0000, 0x0000 }, /* R19169 */ + { 0x0000, 0x0000, 0x0000 }, /* R19170 */ + { 0x0000, 0x0000, 0x0000 }, /* R19171 */ + { 0x0000, 0x0000, 0x0000 }, /* R19172 */ + { 0x0000, 0x0000, 0x0000 }, /* R19173 */ + { 0x0000, 0x0000, 0x0000 }, /* R19174 */ + { 0x0000, 0x0000, 0x0000 }, /* R19175 */ + { 0x0000, 0x0000, 0x0000 }, /* R19176 */ + { 0x0000, 0x0000, 0x0000 }, /* R19177 */ + { 0x0000, 0x0000, 0x0000 }, /* R19178 */ + { 0x0000, 0x0000, 0x0000 }, /* R19179 */ + { 0x0000, 0x0000, 0x0000 }, /* R19180 */ + { 0x0000, 0x0000, 0x0000 }, /* R19181 */ + { 0x0000, 0x0000, 0x0000 }, /* R19182 */ + { 0x0000, 0x0000, 0x0000 }, /* R19183 */ + { 0x0000, 0x0000, 0x0000 }, /* R19184 */ + { 0x0000, 0x0000, 0x0000 }, /* R19185 */ + { 0x0000, 0x0000, 0x0000 }, /* R19186 */ + { 0x0000, 0x0000, 0x0000 }, /* R19187 */ + { 0x0000, 0x0000, 0x0000 }, /* R19188 */ + { 0x0000, 0x0000, 0x0000 }, /* R19189 */ + { 0x0000, 0x0000, 0x0000 }, /* R19190 */ + { 0x0000, 0x0000, 0x0000 }, /* R19191 */ + { 0x0000, 0x0000, 0x0000 }, /* R19192 */ + { 0x0000, 0x0000, 0x0000 }, /* R19193 */ + { 0x0000, 0x0000, 0x0000 }, /* R19194 */ + { 0x0000, 0x0000, 0x0000 }, /* R19195 */ + { 0x0000, 0x0000, 0x0000 }, /* R19196 */ + { 0x0000, 0x0000, 0x0000 }, /* R19197 */ + { 0x0000, 0x0000, 0x0000 }, /* R19198 */ + { 0x0000, 0x0000, 0x0000 }, /* R19199 */ + { 0x0000, 0x0000, 0x0000 }, /* R19200 */ + { 0x0000, 0x0000, 0x0000 }, /* R19201 */ + { 0x0000, 0x0000, 0x0000 }, /* R19202 */ + { 0x0000, 0x0000, 0x0000 }, /* R19203 */ + { 0x0000, 0x0000, 0x0000 }, /* R19204 */ + { 0x0000, 0x0000, 0x0000 }, /* R19205 */ + { 0x0000, 0x0000, 0x0000 }, /* R19206 */ + { 0x0000, 0x0000, 0x0000 }, /* R19207 */ + { 0x0000, 0x0000, 0x0000 }, /* R19208 */ + { 0x0000, 0x0000, 0x0000 }, /* R19209 */ + { 0x0000, 0x0000, 0x0000 }, /* R19210 */ + { 0x0000, 0x0000, 0x0000 }, /* R19211 */ + { 0x0000, 0x0000, 0x0000 }, /* R19212 */ + { 0x0000, 0x0000, 0x0000 }, /* R19213 */ + { 0x0000, 0x0000, 0x0000 }, /* R19214 */ + { 0x0000, 0x0000, 0x0000 }, /* R19215 */ + { 0x0000, 0x0000, 0x0000 }, /* R19216 */ + { 0x0000, 0x0000, 0x0000 }, /* R19217 */ + { 0x0000, 0x0000, 0x0000 }, /* R19218 */ + { 0x0000, 0x0000, 0x0000 }, /* R19219 */ + { 0x0000, 0x0000, 0x0000 }, /* R19220 */ + { 0x0000, 0x0000, 0x0000 }, /* R19221 */ + { 0x0000, 0x0000, 0x0000 }, /* R19222 */ + { 0x0000, 0x0000, 0x0000 }, /* R19223 */ + { 0x0000, 0x0000, 0x0000 }, /* R19224 */ + { 0x0000, 0x0000, 0x0000 }, /* R19225 */ + { 0x0000, 0x0000, 0x0000 }, /* R19226 */ + { 0x0000, 0x0000, 0x0000 }, /* R19227 */ + { 0x0000, 0x0000, 0x0000 }, /* R19228 */ + { 0x0000, 0x0000, 0x0000 }, /* R19229 */ + { 0x0000, 0x0000, 0x0000 }, /* R19230 */ + { 0x0000, 0x0000, 0x0000 }, /* R19231 */ + { 0x0000, 0x0000, 0x0000 }, /* R19232 */ + { 0x0000, 0x0000, 0x0000 }, /* R19233 */ + { 0x0000, 0x0000, 0x0000 }, /* R19234 */ + { 0x0000, 0x0000, 0x0000 }, /* R19235 */ + { 0x0000, 0x0000, 0x0000 }, /* R19236 */ + { 0x0000, 0x0000, 0x0000 }, /* R19237 */ + { 0x0000, 0x0000, 0x0000 }, /* R19238 */ + { 0x0000, 0x0000, 0x0000 }, /* R19239 */ + { 0x0000, 0x0000, 0x0000 }, /* R19240 */ + { 0x0000, 0x0000, 0x0000 }, /* R19241 */ + { 0x0000, 0x0000, 0x0000 }, /* R19242 */ + { 0x0000, 0x0000, 0x0000 }, /* R19243 */ + { 0x0000, 0x0000, 0x0000 }, /* R19244 */ + { 0x0000, 0x0000, 0x0000 }, /* R19245 */ + { 0x0000, 0x0000, 0x0000 }, /* R19246 */ + { 0x0000, 0x0000, 0x0000 }, /* R19247 */ + { 0x0000, 0x0000, 0x0000 }, /* R19248 */ + { 0x0000, 0x0000, 0x0000 }, /* R19249 */ + { 0x0000, 0x0000, 0x0000 }, /* R19250 */ + { 0x0000, 0x0000, 0x0000 }, /* R19251 */ + { 0x0000, 0x0000, 0x0000 }, /* R19252 */ + { 0x0000, 0x0000, 0x0000 }, /* R19253 */ + { 0x0000, 0x0000, 0x0000 }, /* R19254 */ + { 0x0000, 0x0000, 0x0000 }, /* R19255 */ + { 0x0000, 0x0000, 0x0000 }, /* R19256 */ + { 0x0000, 0x0000, 0x0000 }, /* R19257 */ + { 0x0000, 0x0000, 0x0000 }, /* R19258 */ + { 0x0000, 0x0000, 0x0000 }, /* R19259 */ + { 0x0000, 0x0000, 0x0000 }, /* R19260 */ + { 0x0000, 0x0000, 0x0000 }, /* R19261 */ + { 0x0000, 0x0000, 0x0000 }, /* R19262 */ + { 0x0000, 0x0000, 0x0000 }, /* R19263 */ + { 0x0000, 0x0000, 0x0000 }, /* R19264 */ + { 0x0000, 0x0000, 0x0000 }, /* R19265 */ + { 0x0000, 0x0000, 0x0000 }, /* R19266 */ + { 0x0000, 0x0000, 0x0000 }, /* R19267 */ + { 0x0000, 0x0000, 0x0000 }, /* R19268 */ + { 0x0000, 0x0000, 0x0000 }, /* R19269 */ + { 0x0000, 0x0000, 0x0000 }, /* R19270 */ + { 0x0000, 0x0000, 0x0000 }, /* R19271 */ + { 0x0000, 0x0000, 0x0000 }, /* R19272 */ + { 0x0000, 0x0000, 0x0000 }, /* R19273 */ + { 0x0000, 0x0000, 0x0000 }, /* R19274 */ + { 0x0000, 0x0000, 0x0000 }, /* R19275 */ + { 0x0000, 0x0000, 0x0000 }, /* R19276 */ + { 0x0000, 0x0000, 0x0000 }, /* R19277 */ + { 0x0000, 0x0000, 0x0000 }, /* R19278 */ + { 0x0000, 0x0000, 0x0000 }, /* R19279 */ + { 0x0000, 0x0000, 0x0000 }, /* R19280 */ + { 0x0000, 0x0000, 0x0000 }, /* R19281 */ + { 0x0000, 0x0000, 0x0000 }, /* R19282 */ + { 0x0000, 0x0000, 0x0000 }, /* R19283 */ + { 0x0000, 0x0000, 0x0000 }, /* R19284 */ + { 0x0000, 0x0000, 0x0000 }, /* R19285 */ + { 0x0000, 0x0000, 0x0000 }, /* R19286 */ + { 0x0000, 0x0000, 0x0000 }, /* R19287 */ + { 0x0000, 0x0000, 0x0000 }, /* R19288 */ + { 0x0000, 0x0000, 0x0000 }, /* R19289 */ + { 0x0000, 0x0000, 0x0000 }, /* R19290 */ + { 0x0000, 0x0000, 0x0000 }, /* R19291 */ + { 0x0000, 0x0000, 0x0000 }, /* R19292 */ + { 0x0000, 0x0000, 0x0000 }, /* R19293 */ + { 0x0000, 0x0000, 0x0000 }, /* R19294 */ + { 0x0000, 0x0000, 0x0000 }, /* R19295 */ + { 0x0000, 0x0000, 0x0000 }, /* R19296 */ + { 0x0000, 0x0000, 0x0000 }, /* R19297 */ + { 0x0000, 0x0000, 0x0000 }, /* R19298 */ + { 0x0000, 0x0000, 0x0000 }, /* R19299 */ + { 0x0000, 0x0000, 0x0000 }, /* R19300 */ + { 0x0000, 0x0000, 0x0000 }, /* R19301 */ + { 0x0000, 0x0000, 0x0000 }, /* R19302 */ + { 0x0000, 0x0000, 0x0000 }, /* R19303 */ + { 0x0000, 0x0000, 0x0000 }, /* R19304 */ + { 0x0000, 0x0000, 0x0000 }, /* R19305 */ + { 0x0000, 0x0000, 0x0000 }, /* R19306 */ + { 0x0000, 0x0000, 0x0000 }, /* R19307 */ + { 0x0000, 0x0000, 0x0000 }, /* R19308 */ + { 0x0000, 0x0000, 0x0000 }, /* R19309 */ + { 0x0000, 0x0000, 0x0000 }, /* R19310 */ + { 0x0000, 0x0000, 0x0000 }, /* R19311 */ + { 0x0000, 0x0000, 0x0000 }, /* R19312 */ + { 0x0000, 0x0000, 0x0000 }, /* R19313 */ + { 0x0000, 0x0000, 0x0000 }, /* R19314 */ + { 0x0000, 0x0000, 0x0000 }, /* R19315 */ + { 0x0000, 0x0000, 0x0000 }, /* R19316 */ + { 0x0000, 0x0000, 0x0000 }, /* R19317 */ + { 0x0000, 0x0000, 0x0000 }, /* R19318 */ + { 0x0000, 0x0000, 0x0000 }, /* R19319 */ + { 0x0000, 0x0000, 0x0000 }, /* R19320 */ + { 0x0000, 0x0000, 0x0000 }, /* R19321 */ + { 0x0000, 0x0000, 0x0000 }, /* R19322 */ + { 0x0000, 0x0000, 0x0000 }, /* R19323 */ + { 0x0000, 0x0000, 0x0000 }, /* R19324 */ + { 0x0000, 0x0000, 0x0000 }, /* R19325 */ + { 0x0000, 0x0000, 0x0000 }, /* R19326 */ + { 0x0000, 0x0000, 0x0000 }, /* R19327 */ + { 0x0000, 0x0000, 0x0000 }, /* R19328 */ + { 0x0000, 0x0000, 0x0000 }, /* R19329 */ + { 0x0000, 0x0000, 0x0000 }, /* R19330 */ + { 0x0000, 0x0000, 0x0000 }, /* R19331 */ + { 0x0000, 0x0000, 0x0000 }, /* R19332 */ + { 0x0000, 0x0000, 0x0000 }, /* R19333 */ + { 0x0000, 0x0000, 0x0000 }, /* R19334 */ + { 0x0000, 0x0000, 0x0000 }, /* R19335 */ + { 0x0000, 0x0000, 0x0000 }, /* R19336 */ + { 0x0000, 0x0000, 0x0000 }, /* R19337 */ + { 0x0000, 0x0000, 0x0000 }, /* R19338 */ + { 0x0000, 0x0000, 0x0000 }, /* R19339 */ + { 0x0000, 0x0000, 0x0000 }, /* R19340 */ + { 0x0000, 0x0000, 0x0000 }, /* R19341 */ + { 0x0000, 0x0000, 0x0000 }, /* R19342 */ + { 0x0000, 0x0000, 0x0000 }, /* R19343 */ + { 0x0000, 0x0000, 0x0000 }, /* R19344 */ + { 0x0000, 0x0000, 0x0000 }, /* R19345 */ + { 0x0000, 0x0000, 0x0000 }, /* R19346 */ + { 0x0000, 0x0000, 0x0000 }, /* R19347 */ + { 0x0000, 0x0000, 0x0000 }, /* R19348 */ + { 0x0000, 0x0000, 0x0000 }, /* R19349 */ + { 0x0000, 0x0000, 0x0000 }, /* R19350 */ + { 0x0000, 0x0000, 0x0000 }, /* R19351 */ + { 0x0000, 0x0000, 0x0000 }, /* R19352 */ + { 0x0000, 0x0000, 0x0000 }, /* R19353 */ + { 0x0000, 0x0000, 0x0000 }, /* R19354 */ + { 0x0000, 0x0000, 0x0000 }, /* R19355 */ + { 0x0000, 0x0000, 0x0000 }, /* R19356 */ + { 0x0000, 0x0000, 0x0000 }, /* R19357 */ + { 0x0000, 0x0000, 0x0000 }, /* R19358 */ + { 0x0000, 0x0000, 0x0000 }, /* R19359 */ + { 0x0000, 0x0000, 0x0000 }, /* R19360 */ + { 0x0000, 0x0000, 0x0000 }, /* R19361 */ + { 0x0000, 0x0000, 0x0000 }, /* R19362 */ + { 0x0000, 0x0000, 0x0000 }, /* R19363 */ + { 0x0000, 0x0000, 0x0000 }, /* R19364 */ + { 0x0000, 0x0000, 0x0000 }, /* R19365 */ + { 0x0000, 0x0000, 0x0000 }, /* R19366 */ + { 0x0000, 0x0000, 0x0000 }, /* R19367 */ + { 0x0000, 0x0000, 0x0000 }, /* R19368 */ + { 0x0000, 0x0000, 0x0000 }, /* R19369 */ + { 0x0000, 0x0000, 0x0000 }, /* R19370 */ + { 0x0000, 0x0000, 0x0000 }, /* R19371 */ + { 0x0000, 0x0000, 0x0000 }, /* R19372 */ + { 0x0000, 0x0000, 0x0000 }, /* R19373 */ + { 0x0000, 0x0000, 0x0000 }, /* R19374 */ + { 0x0000, 0x0000, 0x0000 }, /* R19375 */ + { 0x0000, 0x0000, 0x0000 }, /* R19376 */ + { 0x0000, 0x0000, 0x0000 }, /* R19377 */ + { 0x0000, 0x0000, 0x0000 }, /* R19378 */ + { 0x0000, 0x0000, 0x0000 }, /* R19379 */ + { 0x0000, 0x0000, 0x0000 }, /* R19380 */ + { 0x0000, 0x0000, 0x0000 }, /* R19381 */ + { 0x0000, 0x0000, 0x0000 }, /* R19382 */ + { 0x0000, 0x0000, 0x0000 }, /* R19383 */ + { 0x0000, 0x0000, 0x0000 }, /* R19384 */ + { 0x0000, 0x0000, 0x0000 }, /* R19385 */ + { 0x0000, 0x0000, 0x0000 }, /* R19386 */ + { 0x0000, 0x0000, 0x0000 }, /* R19387 */ + { 0x0000, 0x0000, 0x0000 }, /* R19388 */ + { 0x0000, 0x0000, 0x0000 }, /* R19389 */ + { 0x0000, 0x0000, 0x0000 }, /* R19390 */ + { 0x0000, 0x0000, 0x0000 }, /* R19391 */ + { 0x0000, 0x0000, 0x0000 }, /* R19392 */ + { 0x0000, 0x0000, 0x0000 }, /* R19393 */ + { 0x0000, 0x0000, 0x0000 }, /* R19394 */ + { 0x0000, 0x0000, 0x0000 }, /* R19395 */ + { 0x0000, 0x0000, 0x0000 }, /* R19396 */ + { 0x0000, 0x0000, 0x0000 }, /* R19397 */ + { 0x0000, 0x0000, 0x0000 }, /* R19398 */ + { 0x0000, 0x0000, 0x0000 }, /* R19399 */ + { 0x0000, 0x0000, 0x0000 }, /* R19400 */ + { 0x0000, 0x0000, 0x0000 }, /* R19401 */ + { 0x0000, 0x0000, 0x0000 }, /* R19402 */ + { 0x0000, 0x0000, 0x0000 }, /* R19403 */ + { 0x0000, 0x0000, 0x0000 }, /* R19404 */ + { 0x0000, 0x0000, 0x0000 }, /* R19405 */ + { 0x0000, 0x0000, 0x0000 }, /* R19406 */ + { 0x0000, 0x0000, 0x0000 }, /* R19407 */ + { 0x0000, 0x0000, 0x0000 }, /* R19408 */ + { 0x0000, 0x0000, 0x0000 }, /* R19409 */ + { 0x0000, 0x0000, 0x0000 }, /* R19410 */ + { 0x0000, 0x0000, 0x0000 }, /* R19411 */ + { 0x0000, 0x0000, 0x0000 }, /* R19412 */ + { 0x0000, 0x0000, 0x0000 }, /* R19413 */ + { 0x0000, 0x0000, 0x0000 }, /* R19414 */ + { 0x0000, 0x0000, 0x0000 }, /* R19415 */ + { 0x0000, 0x0000, 0x0000 }, /* R19416 */ + { 0x0000, 0x0000, 0x0000 }, /* R19417 */ + { 0x0000, 0x0000, 0x0000 }, /* R19418 */ + { 0x0000, 0x0000, 0x0000 }, /* R19419 */ + { 0x0000, 0x0000, 0x0000 }, /* R19420 */ + { 0x0000, 0x0000, 0x0000 }, /* R19421 */ + { 0x0000, 0x0000, 0x0000 }, /* R19422 */ + { 0x0000, 0x0000, 0x0000 }, /* R19423 */ + { 0x0000, 0x0000, 0x0000 }, /* R19424 */ + { 0x0000, 0x0000, 0x0000 }, /* R19425 */ + { 0x0000, 0x0000, 0x0000 }, /* R19426 */ + { 0x0000, 0x0000, 0x0000 }, /* R19427 */ + { 0x0000, 0x0000, 0x0000 }, /* R19428 */ + { 0x0000, 0x0000, 0x0000 }, /* R19429 */ + { 0x0000, 0x0000, 0x0000 }, /* R19430 */ + { 0x0000, 0x0000, 0x0000 }, /* R19431 */ + { 0x0000, 0x0000, 0x0000 }, /* R19432 */ + { 0x0000, 0x0000, 0x0000 }, /* R19433 */ + { 0x0000, 0x0000, 0x0000 }, /* R19434 */ + { 0x0000, 0x0000, 0x0000 }, /* R19435 */ + { 0x0000, 0x0000, 0x0000 }, /* R19436 */ + { 0x0000, 0x0000, 0x0000 }, /* R19437 */ + { 0x0000, 0x0000, 0x0000 }, /* R19438 */ + { 0x0000, 0x0000, 0x0000 }, /* R19439 */ + { 0x0000, 0x0000, 0x0000 }, /* R19440 */ + { 0x0000, 0x0000, 0x0000 }, /* R19441 */ + { 0x0000, 0x0000, 0x0000 }, /* R19442 */ + { 0x0000, 0x0000, 0x0000 }, /* R19443 */ + { 0x0000, 0x0000, 0x0000 }, /* R19444 */ + { 0x0000, 0x0000, 0x0000 }, /* R19445 */ + { 0x0000, 0x0000, 0x0000 }, /* R19446 */ + { 0x0000, 0x0000, 0x0000 }, /* R19447 */ + { 0x0000, 0x0000, 0x0000 }, /* R19448 */ + { 0x0000, 0x0000, 0x0000 }, /* R19449 */ + { 0x0000, 0x0000, 0x0000 }, /* R19450 */ + { 0x0000, 0x0000, 0x0000 }, /* R19451 */ + { 0x0000, 0x0000, 0x0000 }, /* R19452 */ + { 0x0000, 0x0000, 0x0000 }, /* R19453 */ + { 0x0000, 0x0000, 0x0000 }, /* R19454 */ + { 0x0000, 0x0000, 0x0000 }, /* R19455 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19456 - DACL_RETUNE_C1_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19457 - DACL_RETUNE_C1_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19458 - DACL_RETUNE_C2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19459 - DACL_RETUNE_C2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19460 - DACL_RETUNE_C3_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19461 - DACL_RETUNE_C3_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19462 - DACL_RETUNE_C4_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19463 - DACL_RETUNE_C4_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19464 - DACL_RETUNE_C5_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19465 - DACL_RETUNE_C5_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19466 - DACL_RETUNE_C6_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19467 - DACL_RETUNE_C6_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19468 - DACL_RETUNE_C7_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19469 - DACL_RETUNE_C7_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19470 - DACL_RETUNE_C8_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19471 - DACL_RETUNE_C8_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19472 - DACL_RETUNE_C9_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19473 - DACL_RETUNE_C9_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19474 - DACL_RETUNE_C10_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19475 - DACL_RETUNE_C10_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19476 - DACL_RETUNE_C11_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19477 - DACL_RETUNE_C11_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19478 - DACL_RETUNE_C12_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19479 - DACL_RETUNE_C12_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19480 - DACL_RETUNE_C13_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19481 - DACL_RETUNE_C13_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19482 - DACL_RETUNE_C14_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19483 - DACL_RETUNE_C14_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19484 - DACL_RETUNE_C15_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19485 - DACL_RETUNE_C15_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19486 - DACL_RETUNE_C16_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19487 - DACL_RETUNE_C16_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19488 - DACL_RETUNE_C17_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19489 - DACL_RETUNE_C17_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19490 - DACL_RETUNE_C18_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19491 - DACL_RETUNE_C18_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19492 - DACL_RETUNE_C19_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19493 - DACL_RETUNE_C19_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19494 - DACL_RETUNE_C20_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19495 - DACL_RETUNE_C20_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19496 - DACL_RETUNE_C21_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19497 - DACL_RETUNE_C21_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19498 - DACL_RETUNE_C22_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19499 - DACL_RETUNE_C22_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19500 - DACL_RETUNE_C23_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19501 - DACL_RETUNE_C23_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19502 - DACL_RETUNE_C24_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19503 - DACL_RETUNE_C24_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19504 - DACL_RETUNE_C25_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19505 - DACL_RETUNE_C25_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19506 - DACL_RETUNE_C26_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19507 - DACL_RETUNE_C26_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19508 - DACL_RETUNE_C27_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19509 - DACL_RETUNE_C27_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19510 - DACL_RETUNE_C28_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19511 - DACL_RETUNE_C28_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19512 - DACL_RETUNE_C29_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19513 - DACL_RETUNE_C29_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19514 - DACL_RETUNE_C30_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19515 - DACL_RETUNE_C30_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19516 - DACL_RETUNE_C31_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19517 - DACL_RETUNE_C31_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19518 - DACL_RETUNE_C32_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19519 - DACL_RETUNE_C32_0 */ + { 0x0000, 0x0000, 0x0000 }, /* R19520 */ + { 0x0000, 0x0000, 0x0000 }, /* R19521 */ + { 0x0000, 0x0000, 0x0000 }, /* R19522 */ + { 0x0000, 0x0000, 0x0000 }, /* R19523 */ + { 0x0000, 0x0000, 0x0000 }, /* R19524 */ + { 0x0000, 0x0000, 0x0000 }, /* R19525 */ + { 0x0000, 0x0000, 0x0000 }, /* R19526 */ + { 0x0000, 0x0000, 0x0000 }, /* R19527 */ + { 0x0000, 0x0000, 0x0000 }, /* R19528 */ + { 0x0000, 0x0000, 0x0000 }, /* R19529 */ + { 0x0000, 0x0000, 0x0000 }, /* R19530 */ + { 0x0000, 0x0000, 0x0000 }, /* R19531 */ + { 0x0000, 0x0000, 0x0000 }, /* R19532 */ + { 0x0000, 0x0000, 0x0000 }, /* R19533 */ + { 0x0000, 0x0000, 0x0000 }, /* R19534 */ + { 0x0000, 0x0000, 0x0000 }, /* R19535 */ + { 0x0000, 0x0000, 0x0000 }, /* R19536 */ + { 0x0000, 0x0000, 0x0000 }, /* R19537 */ + { 0x0000, 0x0000, 0x0000 }, /* R19538 */ + { 0x0000, 0x0000, 0x0000 }, /* R19539 */ + { 0x0000, 0x0000, 0x0000 }, /* R19540 */ + { 0x0000, 0x0000, 0x0000 }, /* R19541 */ + { 0x0000, 0x0000, 0x0000 }, /* R19542 */ + { 0x0000, 0x0000, 0x0000 }, /* R19543 */ + { 0x0000, 0x0000, 0x0000 }, /* R19544 */ + { 0x0000, 0x0000, 0x0000 }, /* R19545 */ + { 0x0000, 0x0000, 0x0000 }, /* R19546 */ + { 0x0000, 0x0000, 0x0000 }, /* R19547 */ + { 0x0000, 0x0000, 0x0000 }, /* R19548 */ + { 0x0000, 0x0000, 0x0000 }, /* R19549 */ + { 0x0000, 0x0000, 0x0000 }, /* R19550 */ + { 0x0000, 0x0000, 0x0000 }, /* R19551 */ + { 0x0000, 0x0000, 0x0000 }, /* R19552 */ + { 0x0000, 0x0000, 0x0000 }, /* R19553 */ + { 0x0000, 0x0000, 0x0000 }, /* R19554 */ + { 0x0000, 0x0000, 0x0000 }, /* R19555 */ + { 0x0000, 0x0000, 0x0000 }, /* R19556 */ + { 0x0000, 0x0000, 0x0000 }, /* R19557 */ + { 0x0000, 0x0000, 0x0000 }, /* R19558 */ + { 0x0000, 0x0000, 0x0000 }, /* R19559 */ + { 0x0000, 0x0000, 0x0000 }, /* R19560 */ + { 0x0000, 0x0000, 0x0000 }, /* R19561 */ + { 0x0000, 0x0000, 0x0000 }, /* R19562 */ + { 0x0000, 0x0000, 0x0000 }, /* R19563 */ + { 0x0000, 0x0000, 0x0000 }, /* R19564 */ + { 0x0000, 0x0000, 0x0000 }, /* R19565 */ + { 0x0000, 0x0000, 0x0000 }, /* R19566 */ + { 0x0000, 0x0000, 0x0000 }, /* R19567 */ + { 0x0000, 0x0000, 0x0000 }, /* R19568 */ + { 0x0000, 0x0000, 0x0000 }, /* R19569 */ + { 0x0000, 0x0000, 0x0000 }, /* R19570 */ + { 0x0000, 0x0000, 0x0000 }, /* R19571 */ + { 0x0000, 0x0000, 0x0000 }, /* R19572 */ + { 0x0000, 0x0000, 0x0000 }, /* R19573 */ + { 0x0000, 0x0000, 0x0000 }, /* R19574 */ + { 0x0000, 0x0000, 0x0000 }, /* R19575 */ + { 0x0000, 0x0000, 0x0000 }, /* R19576 */ + { 0x0000, 0x0000, 0x0000 }, /* R19577 */ + { 0x0000, 0x0000, 0x0000 }, /* R19578 */ + { 0x0000, 0x0000, 0x0000 }, /* R19579 */ + { 0x0000, 0x0000, 0x0000 }, /* R19580 */ + { 0x0000, 0x0000, 0x0000 }, /* R19581 */ + { 0x0000, 0x0000, 0x0000 }, /* R19582 */ + { 0x0000, 0x0000, 0x0000 }, /* R19583 */ + { 0x0000, 0x0000, 0x0000 }, /* R19584 */ + { 0x0000, 0x0000, 0x0000 }, /* R19585 */ + { 0x0000, 0x0000, 0x0000 }, /* R19586 */ + { 0x0000, 0x0000, 0x0000 }, /* R19587 */ + { 0x0000, 0x0000, 0x0000 }, /* R19588 */ + { 0x0000, 0x0000, 0x0000 }, /* R19589 */ + { 0x0000, 0x0000, 0x0000 }, /* R19590 */ + { 0x0000, 0x0000, 0x0000 }, /* R19591 */ + { 0x0000, 0x0000, 0x0000 }, /* R19592 */ + { 0x0000, 0x0000, 0x0000 }, /* R19593 */ + { 0x0000, 0x0000, 0x0000 }, /* R19594 */ + { 0x0000, 0x0000, 0x0000 }, /* R19595 */ + { 0x0000, 0x0000, 0x0000 }, /* R19596 */ + { 0x0000, 0x0000, 0x0000 }, /* R19597 */ + { 0x0000, 0x0000, 0x0000 }, /* R19598 */ + { 0x0000, 0x0000, 0x0000 }, /* R19599 */ + { 0x0000, 0x0000, 0x0000 }, /* R19600 */ + { 0x0000, 0x0000, 0x0000 }, /* R19601 */ + { 0x0000, 0x0000, 0x0000 }, /* R19602 */ + { 0x0000, 0x0000, 0x0000 }, /* R19603 */ + { 0x0000, 0x0000, 0x0000 }, /* R19604 */ + { 0x0000, 0x0000, 0x0000 }, /* R19605 */ + { 0x0000, 0x0000, 0x0000 }, /* R19606 */ + { 0x0000, 0x0000, 0x0000 }, /* R19607 */ + { 0x0000, 0x0000, 0x0000 }, /* R19608 */ + { 0x0000, 0x0000, 0x0000 }, /* R19609 */ + { 0x0000, 0x0000, 0x0000 }, /* R19610 */ + { 0x0000, 0x0000, 0x0000 }, /* R19611 */ + { 0x0000, 0x0000, 0x0000 }, /* R19612 */ + { 0x0000, 0x0000, 0x0000 }, /* R19613 */ + { 0x0000, 0x0000, 0x0000 }, /* R19614 */ + { 0x0000, 0x0000, 0x0000 }, /* R19615 */ + { 0x0000, 0x0000, 0x0000 }, /* R19616 */ + { 0x0000, 0x0000, 0x0000 }, /* R19617 */ + { 0x0000, 0x0000, 0x0000 }, /* R19618 */ + { 0x0000, 0x0000, 0x0000 }, /* R19619 */ + { 0x0000, 0x0000, 0x0000 }, /* R19620 */ + { 0x0000, 0x0000, 0x0000 }, /* R19621 */ + { 0x0000, 0x0000, 0x0000 }, /* R19622 */ + { 0x0000, 0x0000, 0x0000 }, /* R19623 */ + { 0x0000, 0x0000, 0x0000 }, /* R19624 */ + { 0x0000, 0x0000, 0x0000 }, /* R19625 */ + { 0x0000, 0x0000, 0x0000 }, /* R19626 */ + { 0x0000, 0x0000, 0x0000 }, /* R19627 */ + { 0x0000, 0x0000, 0x0000 }, /* R19628 */ + { 0x0000, 0x0000, 0x0000 }, /* R19629 */ + { 0x0000, 0x0000, 0x0000 }, /* R19630 */ + { 0x0000, 0x0000, 0x0000 }, /* R19631 */ + { 0x0000, 0x0000, 0x0000 }, /* R19632 */ + { 0x0000, 0x0000, 0x0000 }, /* R19633 */ + { 0x0000, 0x0000, 0x0000 }, /* R19634 */ + { 0x0000, 0x0000, 0x0000 }, /* R19635 */ + { 0x0000, 0x0000, 0x0000 }, /* R19636 */ + { 0x0000, 0x0000, 0x0000 }, /* R19637 */ + { 0x0000, 0x0000, 0x0000 }, /* R19638 */ + { 0x0000, 0x0000, 0x0000 }, /* R19639 */ + { 0x0000, 0x0000, 0x0000 }, /* R19640 */ + { 0x0000, 0x0000, 0x0000 }, /* R19641 */ + { 0x0000, 0x0000, 0x0000 }, /* R19642 */ + { 0x0000, 0x0000, 0x0000 }, /* R19643 */ + { 0x0000, 0x0000, 0x0000 }, /* R19644 */ + { 0x0000, 0x0000, 0x0000 }, /* R19645 */ + { 0x0000, 0x0000, 0x0000 }, /* R19646 */ + { 0x0000, 0x0000, 0x0000 }, /* R19647 */ + { 0x0000, 0x0000, 0x0000 }, /* R19648 */ + { 0x0000, 0x0000, 0x0000 }, /* R19649 */ + { 0x0000, 0x0000, 0x0000 }, /* R19650 */ + { 0x0000, 0x0000, 0x0000 }, /* R19651 */ + { 0x0000, 0x0000, 0x0000 }, /* R19652 */ + { 0x0000, 0x0000, 0x0000 }, /* R19653 */ + { 0x0000, 0x0000, 0x0000 }, /* R19654 */ + { 0x0000, 0x0000, 0x0000 }, /* R19655 */ + { 0x0000, 0x0000, 0x0000 }, /* R19656 */ + { 0x0000, 0x0000, 0x0000 }, /* R19657 */ + { 0x0000, 0x0000, 0x0000 }, /* R19658 */ + { 0x0000, 0x0000, 0x0000 }, /* R19659 */ + { 0x0000, 0x0000, 0x0000 }, /* R19660 */ + { 0x0000, 0x0000, 0x0000 }, /* R19661 */ + { 0x0000, 0x0000, 0x0000 }, /* R19662 */ + { 0x0000, 0x0000, 0x0000 }, /* R19663 */ + { 0x0000, 0x0000, 0x0000 }, /* R19664 */ + { 0x0000, 0x0000, 0x0000 }, /* R19665 */ + { 0x0000, 0x0000, 0x0000 }, /* R19666 */ + { 0x0000, 0x0000, 0x0000 }, /* R19667 */ + { 0x0000, 0x0000, 0x0000 }, /* R19668 */ + { 0x0000, 0x0000, 0x0000 }, /* R19669 */ + { 0x0000, 0x0000, 0x0000 }, /* R19670 */ + { 0x0000, 0x0000, 0x0000 }, /* R19671 */ + { 0x0000, 0x0000, 0x0000 }, /* R19672 */ + { 0x0000, 0x0000, 0x0000 }, /* R19673 */ + { 0x0000, 0x0000, 0x0000 }, /* R19674 */ + { 0x0000, 0x0000, 0x0000 }, /* R19675 */ + { 0x0000, 0x0000, 0x0000 }, /* R19676 */ + { 0x0000, 0x0000, 0x0000 }, /* R19677 */ + { 0x0000, 0x0000, 0x0000 }, /* R19678 */ + { 0x0000, 0x0000, 0x0000 }, /* R19679 */ + { 0x0000, 0x0000, 0x0000 }, /* R19680 */ + { 0x0000, 0x0000, 0x0000 }, /* R19681 */ + { 0x0000, 0x0000, 0x0000 }, /* R19682 */ + { 0x0000, 0x0000, 0x0000 }, /* R19683 */ + { 0x0000, 0x0000, 0x0000 }, /* R19684 */ + { 0x0000, 0x0000, 0x0000 }, /* R19685 */ + { 0x0000, 0x0000, 0x0000 }, /* R19686 */ + { 0x0000, 0x0000, 0x0000 }, /* R19687 */ + { 0x0000, 0x0000, 0x0000 }, /* R19688 */ + { 0x0000, 0x0000, 0x0000 }, /* R19689 */ + { 0x0000, 0x0000, 0x0000 }, /* R19690 */ + { 0x0000, 0x0000, 0x0000 }, /* R19691 */ + { 0x0000, 0x0000, 0x0000 }, /* R19692 */ + { 0x0000, 0x0000, 0x0000 }, /* R19693 */ + { 0x0000, 0x0000, 0x0000 }, /* R19694 */ + { 0x0000, 0x0000, 0x0000 }, /* R19695 */ + { 0x0000, 0x0000, 0x0000 }, /* R19696 */ + { 0x0000, 0x0000, 0x0000 }, /* R19697 */ + { 0x0000, 0x0000, 0x0000 }, /* R19698 */ + { 0x0000, 0x0000, 0x0000 }, /* R19699 */ + { 0x0000, 0x0000, 0x0000 }, /* R19700 */ + { 0x0000, 0x0000, 0x0000 }, /* R19701 */ + { 0x0000, 0x0000, 0x0000 }, /* R19702 */ + { 0x0000, 0x0000, 0x0000 }, /* R19703 */ + { 0x0000, 0x0000, 0x0000 }, /* R19704 */ + { 0x0000, 0x0000, 0x0000 }, /* R19705 */ + { 0x0000, 0x0000, 0x0000 }, /* R19706 */ + { 0x0000, 0x0000, 0x0000 }, /* R19707 */ + { 0x0000, 0x0000, 0x0000 }, /* R19708 */ + { 0x0000, 0x0000, 0x0000 }, /* R19709 */ + { 0x0000, 0x0000, 0x0000 }, /* R19710 */ + { 0x0000, 0x0000, 0x0000 }, /* R19711 */ + { 0x0000, 0x0000, 0x0000 }, /* R19712 */ + { 0x0000, 0x0000, 0x0000 }, /* R19713 */ + { 0x0000, 0x0000, 0x0000 }, /* R19714 */ + { 0x0000, 0x0000, 0x0000 }, /* R19715 */ + { 0x0000, 0x0000, 0x0000 }, /* R19716 */ + { 0x0000, 0x0000, 0x0000 }, /* R19717 */ + { 0x0000, 0x0000, 0x0000 }, /* R19718 */ + { 0x0000, 0x0000, 0x0000 }, /* R19719 */ + { 0x0000, 0x0000, 0x0000 }, /* R19720 */ + { 0x0000, 0x0000, 0x0000 }, /* R19721 */ + { 0x0000, 0x0000, 0x0000 }, /* R19722 */ + { 0x0000, 0x0000, 0x0000 }, /* R19723 */ + { 0x0000, 0x0000, 0x0000 }, /* R19724 */ + { 0x0000, 0x0000, 0x0000 }, /* R19725 */ + { 0x0000, 0x0000, 0x0000 }, /* R19726 */ + { 0x0000, 0x0000, 0x0000 }, /* R19727 */ + { 0x0000, 0x0000, 0x0000 }, /* R19728 */ + { 0x0000, 0x0000, 0x0000 }, /* R19729 */ + { 0x0000, 0x0000, 0x0000 }, /* R19730 */ + { 0x0000, 0x0000, 0x0000 }, /* R19731 */ + { 0x0000, 0x0000, 0x0000 }, /* R19732 */ + { 0x0000, 0x0000, 0x0000 }, /* R19733 */ + { 0x0000, 0x0000, 0x0000 }, /* R19734 */ + { 0x0000, 0x0000, 0x0000 }, /* R19735 */ + { 0x0000, 0x0000, 0x0000 }, /* R19736 */ + { 0x0000, 0x0000, 0x0000 }, /* R19737 */ + { 0x0000, 0x0000, 0x0000 }, /* R19738 */ + { 0x0000, 0x0000, 0x0000 }, /* R19739 */ + { 0x0000, 0x0000, 0x0000 }, /* R19740 */ + { 0x0000, 0x0000, 0x0000 }, /* R19741 */ + { 0x0000, 0x0000, 0x0000 }, /* R19742 */ + { 0x0000, 0x0000, 0x0000 }, /* R19743 */ + { 0x0000, 0x0000, 0x0000 }, /* R19744 */ + { 0x0000, 0x0000, 0x0000 }, /* R19745 */ + { 0x0000, 0x0000, 0x0000 }, /* R19746 */ + { 0x0000, 0x0000, 0x0000 }, /* R19747 */ + { 0x0000, 0x0000, 0x0000 }, /* R19748 */ + { 0x0000, 0x0000, 0x0000 }, /* R19749 */ + { 0x0000, 0x0000, 0x0000 }, /* R19750 */ + { 0x0000, 0x0000, 0x0000 }, /* R19751 */ + { 0x0000, 0x0000, 0x0000 }, /* R19752 */ + { 0x0000, 0x0000, 0x0000 }, /* R19753 */ + { 0x0000, 0x0000, 0x0000 }, /* R19754 */ + { 0x0000, 0x0000, 0x0000 }, /* R19755 */ + { 0x0000, 0x0000, 0x0000 }, /* R19756 */ + { 0x0000, 0x0000, 0x0000 }, /* R19757 */ + { 0x0000, 0x0000, 0x0000 }, /* R19758 */ + { 0x0000, 0x0000, 0x0000 }, /* R19759 */ + { 0x0000, 0x0000, 0x0000 }, /* R19760 */ + { 0x0000, 0x0000, 0x0000 }, /* R19761 */ + { 0x0000, 0x0000, 0x0000 }, /* R19762 */ + { 0x0000, 0x0000, 0x0000 }, /* R19763 */ + { 0x0000, 0x0000, 0x0000 }, /* R19764 */ + { 0x0000, 0x0000, 0x0000 }, /* R19765 */ + { 0x0000, 0x0000, 0x0000 }, /* R19766 */ + { 0x0000, 0x0000, 0x0000 }, /* R19767 */ + { 0x0000, 0x0000, 0x0000 }, /* R19768 */ + { 0x0000, 0x0000, 0x0000 }, /* R19769 */ + { 0x0000, 0x0000, 0x0000 }, /* R19770 */ + { 0x0000, 0x0000, 0x0000 }, /* R19771 */ + { 0x0000, 0x0000, 0x0000 }, /* R19772 */ + { 0x0000, 0x0000, 0x0000 }, /* R19773 */ + { 0x0000, 0x0000, 0x0000 }, /* R19774 */ + { 0x0000, 0x0000, 0x0000 }, /* R19775 */ + { 0x0000, 0x0000, 0x0000 }, /* R19776 */ + { 0x0000, 0x0000, 0x0000 }, /* R19777 */ + { 0x0000, 0x0000, 0x0000 }, /* R19778 */ + { 0x0000, 0x0000, 0x0000 }, /* R19779 */ + { 0x0000, 0x0000, 0x0000 }, /* R19780 */ + { 0x0000, 0x0000, 0x0000 }, /* R19781 */ + { 0x0000, 0x0000, 0x0000 }, /* R19782 */ + { 0x0000, 0x0000, 0x0000 }, /* R19783 */ + { 0x0000, 0x0000, 0x0000 }, /* R19784 */ + { 0x0000, 0x0000, 0x0000 }, /* R19785 */ + { 0x0000, 0x0000, 0x0000 }, /* R19786 */ + { 0x0000, 0x0000, 0x0000 }, /* R19787 */ + { 0x0000, 0x0000, 0x0000 }, /* R19788 */ + { 0x0000, 0x0000, 0x0000 }, /* R19789 */ + { 0x0000, 0x0000, 0x0000 }, /* R19790 */ + { 0x0000, 0x0000, 0x0000 }, /* R19791 */ + { 0x0000, 0x0000, 0x0000 }, /* R19792 */ + { 0x0000, 0x0000, 0x0000 }, /* R19793 */ + { 0x0000, 0x0000, 0x0000 }, /* R19794 */ + { 0x0000, 0x0000, 0x0000 }, /* R19795 */ + { 0x0000, 0x0000, 0x0000 }, /* R19796 */ + { 0x0000, 0x0000, 0x0000 }, /* R19797 */ + { 0x0000, 0x0000, 0x0000 }, /* R19798 */ + { 0x0000, 0x0000, 0x0000 }, /* R19799 */ + { 0x0000, 0x0000, 0x0000 }, /* R19800 */ + { 0x0000, 0x0000, 0x0000 }, /* R19801 */ + { 0x0000, 0x0000, 0x0000 }, /* R19802 */ + { 0x0000, 0x0000, 0x0000 }, /* R19803 */ + { 0x0000, 0x0000, 0x0000 }, /* R19804 */ + { 0x0000, 0x0000, 0x0000 }, /* R19805 */ + { 0x0000, 0x0000, 0x0000 }, /* R19806 */ + { 0x0000, 0x0000, 0x0000 }, /* R19807 */ + { 0x0000, 0x0000, 0x0000 }, /* R19808 */ + { 0x0000, 0x0000, 0x0000 }, /* R19809 */ + { 0x0000, 0x0000, 0x0000 }, /* R19810 */ + { 0x0000, 0x0000, 0x0000 }, /* R19811 */ + { 0x0000, 0x0000, 0x0000 }, /* R19812 */ + { 0x0000, 0x0000, 0x0000 }, /* R19813 */ + { 0x0000, 0x0000, 0x0000 }, /* R19814 */ + { 0x0000, 0x0000, 0x0000 }, /* R19815 */ + { 0x0000, 0x0000, 0x0000 }, /* R19816 */ + { 0x0000, 0x0000, 0x0000 }, /* R19817 */ + { 0x0000, 0x0000, 0x0000 }, /* R19818 */ + { 0x0000, 0x0000, 0x0000 }, /* R19819 */ + { 0x0000, 0x0000, 0x0000 }, /* R19820 */ + { 0x0000, 0x0000, 0x0000 }, /* R19821 */ + { 0x0000, 0x0000, 0x0000 }, /* R19822 */ + { 0x0000, 0x0000, 0x0000 }, /* R19823 */ + { 0x0000, 0x0000, 0x0000 }, /* R19824 */ + { 0x0000, 0x0000, 0x0000 }, /* R19825 */ + { 0x0000, 0x0000, 0x0000 }, /* R19826 */ + { 0x0000, 0x0000, 0x0000 }, /* R19827 */ + { 0x0000, 0x0000, 0x0000 }, /* R19828 */ + { 0x0000, 0x0000, 0x0000 }, /* R19829 */ + { 0x0000, 0x0000, 0x0000 }, /* R19830 */ + { 0x0000, 0x0000, 0x0000 }, /* R19831 */ + { 0x0000, 0x0000, 0x0000 }, /* R19832 */ + { 0x0000, 0x0000, 0x0000 }, /* R19833 */ + { 0x0000, 0x0000, 0x0000 }, /* R19834 */ + { 0x0000, 0x0000, 0x0000 }, /* R19835 */ + { 0x0000, 0x0000, 0x0000 }, /* R19836 */ + { 0x0000, 0x0000, 0x0000 }, /* R19837 */ + { 0x0000, 0x0000, 0x0000 }, /* R19838 */ + { 0x0000, 0x0000, 0x0000 }, /* R19839 */ + { 0x0000, 0x0000, 0x0000 }, /* R19840 */ + { 0x0000, 0x0000, 0x0000 }, /* R19841 */ + { 0x0000, 0x0000, 0x0000 }, /* R19842 */ + { 0x0000, 0x0000, 0x0000 }, /* R19843 */ + { 0x0000, 0x0000, 0x0000 }, /* R19844 */ + { 0x0000, 0x0000, 0x0000 }, /* R19845 */ + { 0x0000, 0x0000, 0x0000 }, /* R19846 */ + { 0x0000, 0x0000, 0x0000 }, /* R19847 */ + { 0x0000, 0x0000, 0x0000 }, /* R19848 */ + { 0x0000, 0x0000, 0x0000 }, /* R19849 */ + { 0x0000, 0x0000, 0x0000 }, /* R19850 */ + { 0x0000, 0x0000, 0x0000 }, /* R19851 */ + { 0x0000, 0x0000, 0x0000 }, /* R19852 */ + { 0x0000, 0x0000, 0x0000 }, /* R19853 */ + { 0x0000, 0x0000, 0x0000 }, /* R19854 */ + { 0x0000, 0x0000, 0x0000 }, /* R19855 */ + { 0x0000, 0x0000, 0x0000 }, /* R19856 */ + { 0x0000, 0x0000, 0x0000 }, /* R19857 */ + { 0x0000, 0x0000, 0x0000 }, /* R19858 */ + { 0x0000, 0x0000, 0x0000 }, /* R19859 */ + { 0x0000, 0x0000, 0x0000 }, /* R19860 */ + { 0x0000, 0x0000, 0x0000 }, /* R19861 */ + { 0x0000, 0x0000, 0x0000 }, /* R19862 */ + { 0x0000, 0x0000, 0x0000 }, /* R19863 */ + { 0x0000, 0x0000, 0x0000 }, /* R19864 */ + { 0x0000, 0x0000, 0x0000 }, /* R19865 */ + { 0x0000, 0x0000, 0x0000 }, /* R19866 */ + { 0x0000, 0x0000, 0x0000 }, /* R19867 */ + { 0x0000, 0x0000, 0x0000 }, /* R19868 */ + { 0x0000, 0x0000, 0x0000 }, /* R19869 */ + { 0x0000, 0x0000, 0x0000 }, /* R19870 */ + { 0x0000, 0x0000, 0x0000 }, /* R19871 */ + { 0x0000, 0x0000, 0x0000 }, /* R19872 */ + { 0x0000, 0x0000, 0x0000 }, /* R19873 */ + { 0x0000, 0x0000, 0x0000 }, /* R19874 */ + { 0x0000, 0x0000, 0x0000 }, /* R19875 */ + { 0x0000, 0x0000, 0x0000 }, /* R19876 */ + { 0x0000, 0x0000, 0x0000 }, /* R19877 */ + { 0x0000, 0x0000, 0x0000 }, /* R19878 */ + { 0x0000, 0x0000, 0x0000 }, /* R19879 */ + { 0x0000, 0x0000, 0x0000 }, /* R19880 */ + { 0x0000, 0x0000, 0x0000 }, /* R19881 */ + { 0x0000, 0x0000, 0x0000 }, /* R19882 */ + { 0x0000, 0x0000, 0x0000 }, /* R19883 */ + { 0x0000, 0x0000, 0x0000 }, /* R19884 */ + { 0x0000, 0x0000, 0x0000 }, /* R19885 */ + { 0x0000, 0x0000, 0x0000 }, /* R19886 */ + { 0x0000, 0x0000, 0x0000 }, /* R19887 */ + { 0x0000, 0x0000, 0x0000 }, /* R19888 */ + { 0x0000, 0x0000, 0x0000 }, /* R19889 */ + { 0x0000, 0x0000, 0x0000 }, /* R19890 */ + { 0x0000, 0x0000, 0x0000 }, /* R19891 */ + { 0x0000, 0x0000, 0x0000 }, /* R19892 */ + { 0x0000, 0x0000, 0x0000 }, /* R19893 */ + { 0x0000, 0x0000, 0x0000 }, /* R19894 */ + { 0x0000, 0x0000, 0x0000 }, /* R19895 */ + { 0x0000, 0x0000, 0x0000 }, /* R19896 */ + { 0x0000, 0x0000, 0x0000 }, /* R19897 */ + { 0x0000, 0x0000, 0x0000 }, /* R19898 */ + { 0x0000, 0x0000, 0x0000 }, /* R19899 */ + { 0x0000, 0x0000, 0x0000 }, /* R19900 */ + { 0x0000, 0x0000, 0x0000 }, /* R19901 */ + { 0x0000, 0x0000, 0x0000 }, /* R19902 */ + { 0x0000, 0x0000, 0x0000 }, /* R19903 */ + { 0x0000, 0x0000, 0x0000 }, /* R19904 */ + { 0x0000, 0x0000, 0x0000 }, /* R19905 */ + { 0x0000, 0x0000, 0x0000 }, /* R19906 */ + { 0x0000, 0x0000, 0x0000 }, /* R19907 */ + { 0x0000, 0x0000, 0x0000 }, /* R19908 */ + { 0x0000, 0x0000, 0x0000 }, /* R19909 */ + { 0x0000, 0x0000, 0x0000 }, /* R19910 */ + { 0x0000, 0x0000, 0x0000 }, /* R19911 */ + { 0x0000, 0x0000, 0x0000 }, /* R19912 */ + { 0x0000, 0x0000, 0x0000 }, /* R19913 */ + { 0x0000, 0x0000, 0x0000 }, /* R19914 */ + { 0x0000, 0x0000, 0x0000 }, /* R19915 */ + { 0x0000, 0x0000, 0x0000 }, /* R19916 */ + { 0x0000, 0x0000, 0x0000 }, /* R19917 */ + { 0x0000, 0x0000, 0x0000 }, /* R19918 */ + { 0x0000, 0x0000, 0x0000 }, /* R19919 */ + { 0x0000, 0x0000, 0x0000 }, /* R19920 */ + { 0x0000, 0x0000, 0x0000 }, /* R19921 */ + { 0x0000, 0x0000, 0x0000 }, /* R19922 */ + { 0x0000, 0x0000, 0x0000 }, /* R19923 */ + { 0x0000, 0x0000, 0x0000 }, /* R19924 */ + { 0x0000, 0x0000, 0x0000 }, /* R19925 */ + { 0x0000, 0x0000, 0x0000 }, /* R19926 */ + { 0x0000, 0x0000, 0x0000 }, /* R19927 */ + { 0x0000, 0x0000, 0x0000 }, /* R19928 */ + { 0x0000, 0x0000, 0x0000 }, /* R19929 */ + { 0x0000, 0x0000, 0x0000 }, /* R19930 */ + { 0x0000, 0x0000, 0x0000 }, /* R19931 */ + { 0x0000, 0x0000, 0x0000 }, /* R19932 */ + { 0x0000, 0x0000, 0x0000 }, /* R19933 */ + { 0x0000, 0x0000, 0x0000 }, /* R19934 */ + { 0x0000, 0x0000, 0x0000 }, /* R19935 */ + { 0x0000, 0x0000, 0x0000 }, /* R19936 */ + { 0x0000, 0x0000, 0x0000 }, /* R19937 */ + { 0x0000, 0x0000, 0x0000 }, /* R19938 */ + { 0x0000, 0x0000, 0x0000 }, /* R19939 */ + { 0x0000, 0x0000, 0x0000 }, /* R19940 */ + { 0x0000, 0x0000, 0x0000 }, /* R19941 */ + { 0x0000, 0x0000, 0x0000 }, /* R19942 */ + { 0x0000, 0x0000, 0x0000 }, /* R19943 */ + { 0x0000, 0x0000, 0x0000 }, /* R19944 */ + { 0x0000, 0x0000, 0x0000 }, /* R19945 */ + { 0x0000, 0x0000, 0x0000 }, /* R19946 */ + { 0x0000, 0x0000, 0x0000 }, /* R19947 */ + { 0x0000, 0x0000, 0x0000 }, /* R19948 */ + { 0x0000, 0x0000, 0x0000 }, /* R19949 */ + { 0x0000, 0x0000, 0x0000 }, /* R19950 */ + { 0x0000, 0x0000, 0x0000 }, /* R19951 */ + { 0x0000, 0x0000, 0x0000 }, /* R19952 */ + { 0x0000, 0x0000, 0x0000 }, /* R19953 */ + { 0x0000, 0x0000, 0x0000 }, /* R19954 */ + { 0x0000, 0x0000, 0x0000 }, /* R19955 */ + { 0x0000, 0x0000, 0x0000 }, /* R19956 */ + { 0x0000, 0x0000, 0x0000 }, /* R19957 */ + { 0x0000, 0x0000, 0x0000 }, /* R19958 */ + { 0x0000, 0x0000, 0x0000 }, /* R19959 */ + { 0x0000, 0x0000, 0x0000 }, /* R19960 */ + { 0x0000, 0x0000, 0x0000 }, /* R19961 */ + { 0x0000, 0x0000, 0x0000 }, /* R19962 */ + { 0x0000, 0x0000, 0x0000 }, /* R19963 */ + { 0x0000, 0x0000, 0x0000 }, /* R19964 */ + { 0x0000, 0x0000, 0x0000 }, /* R19965 */ + { 0x0000, 0x0000, 0x0000 }, /* R19966 */ + { 0x0000, 0x0000, 0x0000 }, /* R19967 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19968 - RETUNEDAC_PG2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19969 - RETUNEDAC_PG2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R19970 - RETUNEDAC_PG_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R19971 - RETUNEDAC_PG_0 */ + { 0x0000, 0x0000, 0x0000 }, /* R19972 */ + { 0x0000, 0x0000, 0x0000 }, /* R19973 */ + { 0x0000, 0x0000, 0x0000 }, /* R19974 */ + { 0x0000, 0x0000, 0x0000 }, /* R19975 */ + { 0x0000, 0x0000, 0x0000 }, /* R19976 */ + { 0x0000, 0x0000, 0x0000 }, /* R19977 */ + { 0x0000, 0x0000, 0x0000 }, /* R19978 */ + { 0x0000, 0x0000, 0x0000 }, /* R19979 */ + { 0x0000, 0x0000, 0x0000 }, /* R19980 */ + { 0x0000, 0x0000, 0x0000 }, /* R19981 */ + { 0x0000, 0x0000, 0x0000 }, /* R19982 */ + { 0x0000, 0x0000, 0x0000 }, /* R19983 */ + { 0x0000, 0x0000, 0x0000 }, /* R19984 */ + { 0x0000, 0x0000, 0x0000 }, /* R19985 */ + { 0x0000, 0x0000, 0x0000 }, /* R19986 */ + { 0x0000, 0x0000, 0x0000 }, /* R19987 */ + { 0x0000, 0x0000, 0x0000 }, /* R19988 */ + { 0x0000, 0x0000, 0x0000 }, /* R19989 */ + { 0x0000, 0x0000, 0x0000 }, /* R19990 */ + { 0x0000, 0x0000, 0x0000 }, /* R19991 */ + { 0x0000, 0x0000, 0x0000 }, /* R19992 */ + { 0x0000, 0x0000, 0x0000 }, /* R19993 */ + { 0x0000, 0x0000, 0x0000 }, /* R19994 */ + { 0x0000, 0x0000, 0x0000 }, /* R19995 */ + { 0x0000, 0x0000, 0x0000 }, /* R19996 */ + { 0x0000, 0x0000, 0x0000 }, /* R19997 */ + { 0x0000, 0x0000, 0x0000 }, /* R19998 */ + { 0x0000, 0x0000, 0x0000 }, /* R19999 */ + { 0x0000, 0x0000, 0x0000 }, /* R20000 */ + { 0x0000, 0x0000, 0x0000 }, /* R20001 */ + { 0x0000, 0x0000, 0x0000 }, /* R20002 */ + { 0x0000, 0x0000, 0x0000 }, /* R20003 */ + { 0x0000, 0x0000, 0x0000 }, /* R20004 */ + { 0x0000, 0x0000, 0x0000 }, /* R20005 */ + { 0x0000, 0x0000, 0x0000 }, /* R20006 */ + { 0x0000, 0x0000, 0x0000 }, /* R20007 */ + { 0x0000, 0x0000, 0x0000 }, /* R20008 */ + { 0x0000, 0x0000, 0x0000 }, /* R20009 */ + { 0x0000, 0x0000, 0x0000 }, /* R20010 */ + { 0x0000, 0x0000, 0x0000 }, /* R20011 */ + { 0x0000, 0x0000, 0x0000 }, /* R20012 */ + { 0x0000, 0x0000, 0x0000 }, /* R20013 */ + { 0x0000, 0x0000, 0x0000 }, /* R20014 */ + { 0x0000, 0x0000, 0x0000 }, /* R20015 */ + { 0x0000, 0x0000, 0x0000 }, /* R20016 */ + { 0x0000, 0x0000, 0x0000 }, /* R20017 */ + { 0x0000, 0x0000, 0x0000 }, /* R20018 */ + { 0x0000, 0x0000, 0x0000 }, /* R20019 */ + { 0x0000, 0x0000, 0x0000 }, /* R20020 */ + { 0x0000, 0x0000, 0x0000 }, /* R20021 */ + { 0x0000, 0x0000, 0x0000 }, /* R20022 */ + { 0x0000, 0x0000, 0x0000 }, /* R20023 */ + { 0x0000, 0x0000, 0x0000 }, /* R20024 */ + { 0x0000, 0x0000, 0x0000 }, /* R20025 */ + { 0x0000, 0x0000, 0x0000 }, /* R20026 */ + { 0x0000, 0x0000, 0x0000 }, /* R20027 */ + { 0x0000, 0x0000, 0x0000 }, /* R20028 */ + { 0x0000, 0x0000, 0x0000 }, /* R20029 */ + { 0x0000, 0x0000, 0x0000 }, /* R20030 */ + { 0x0000, 0x0000, 0x0000 }, /* R20031 */ + { 0x0000, 0x0000, 0x0000 }, /* R20032 */ + { 0x0000, 0x0000, 0x0000 }, /* R20033 */ + { 0x0000, 0x0000, 0x0000 }, /* R20034 */ + { 0x0000, 0x0000, 0x0000 }, /* R20035 */ + { 0x0000, 0x0000, 0x0000 }, /* R20036 */ + { 0x0000, 0x0000, 0x0000 }, /* R20037 */ + { 0x0000, 0x0000, 0x0000 }, /* R20038 */ + { 0x0000, 0x0000, 0x0000 }, /* R20039 */ + { 0x0000, 0x0000, 0x0000 }, /* R20040 */ + { 0x0000, 0x0000, 0x0000 }, /* R20041 */ + { 0x0000, 0x0000, 0x0000 }, /* R20042 */ + { 0x0000, 0x0000, 0x0000 }, /* R20043 */ + { 0x0000, 0x0000, 0x0000 }, /* R20044 */ + { 0x0000, 0x0000, 0x0000 }, /* R20045 */ + { 0x0000, 0x0000, 0x0000 }, /* R20046 */ + { 0x0000, 0x0000, 0x0000 }, /* R20047 */ + { 0x0000, 0x0000, 0x0000 }, /* R20048 */ + { 0x0000, 0x0000, 0x0000 }, /* R20049 */ + { 0x0000, 0x0000, 0x0000 }, /* R20050 */ + { 0x0000, 0x0000, 0x0000 }, /* R20051 */ + { 0x0000, 0x0000, 0x0000 }, /* R20052 */ + { 0x0000, 0x0000, 0x0000 }, /* R20053 */ + { 0x0000, 0x0000, 0x0000 }, /* R20054 */ + { 0x0000, 0x0000, 0x0000 }, /* R20055 */ + { 0x0000, 0x0000, 0x0000 }, /* R20056 */ + { 0x0000, 0x0000, 0x0000 }, /* R20057 */ + { 0x0000, 0x0000, 0x0000 }, /* R20058 */ + { 0x0000, 0x0000, 0x0000 }, /* R20059 */ + { 0x0000, 0x0000, 0x0000 }, /* R20060 */ + { 0x0000, 0x0000, 0x0000 }, /* R20061 */ + { 0x0000, 0x0000, 0x0000 }, /* R20062 */ + { 0x0000, 0x0000, 0x0000 }, /* R20063 */ + { 0x0000, 0x0000, 0x0000 }, /* R20064 */ + { 0x0000, 0x0000, 0x0000 }, /* R20065 */ + { 0x0000, 0x0000, 0x0000 }, /* R20066 */ + { 0x0000, 0x0000, 0x0000 }, /* R20067 */ + { 0x0000, 0x0000, 0x0000 }, /* R20068 */ + { 0x0000, 0x0000, 0x0000 }, /* R20069 */ + { 0x0000, 0x0000, 0x0000 }, /* R20070 */ + { 0x0000, 0x0000, 0x0000 }, /* R20071 */ + { 0x0000, 0x0000, 0x0000 }, /* R20072 */ + { 0x0000, 0x0000, 0x0000 }, /* R20073 */ + { 0x0000, 0x0000, 0x0000 }, /* R20074 */ + { 0x0000, 0x0000, 0x0000 }, /* R20075 */ + { 0x0000, 0x0000, 0x0000 }, /* R20076 */ + { 0x0000, 0x0000, 0x0000 }, /* R20077 */ + { 0x0000, 0x0000, 0x0000 }, /* R20078 */ + { 0x0000, 0x0000, 0x0000 }, /* R20079 */ + { 0x0000, 0x0000, 0x0000 }, /* R20080 */ + { 0x0000, 0x0000, 0x0000 }, /* R20081 */ + { 0x0000, 0x0000, 0x0000 }, /* R20082 */ + { 0x0000, 0x0000, 0x0000 }, /* R20083 */ + { 0x0000, 0x0000, 0x0000 }, /* R20084 */ + { 0x0000, 0x0000, 0x0000 }, /* R20085 */ + { 0x0000, 0x0000, 0x0000 }, /* R20086 */ + { 0x0000, 0x0000, 0x0000 }, /* R20087 */ + { 0x0000, 0x0000, 0x0000 }, /* R20088 */ + { 0x0000, 0x0000, 0x0000 }, /* R20089 */ + { 0x0000, 0x0000, 0x0000 }, /* R20090 */ + { 0x0000, 0x0000, 0x0000 }, /* R20091 */ + { 0x0000, 0x0000, 0x0000 }, /* R20092 */ + { 0x0000, 0x0000, 0x0000 }, /* R20093 */ + { 0x0000, 0x0000, 0x0000 }, /* R20094 */ + { 0x0000, 0x0000, 0x0000 }, /* R20095 */ + { 0x0000, 0x0000, 0x0000 }, /* R20096 */ + { 0x0000, 0x0000, 0x0000 }, /* R20097 */ + { 0x0000, 0x0000, 0x0000 }, /* R20098 */ + { 0x0000, 0x0000, 0x0000 }, /* R20099 */ + { 0x0000, 0x0000, 0x0000 }, /* R20100 */ + { 0x0000, 0x0000, 0x0000 }, /* R20101 */ + { 0x0000, 0x0000, 0x0000 }, /* R20102 */ + { 0x0000, 0x0000, 0x0000 }, /* R20103 */ + { 0x0000, 0x0000, 0x0000 }, /* R20104 */ + { 0x0000, 0x0000, 0x0000 }, /* R20105 */ + { 0x0000, 0x0000, 0x0000 }, /* R20106 */ + { 0x0000, 0x0000, 0x0000 }, /* R20107 */ + { 0x0000, 0x0000, 0x0000 }, /* R20108 */ + { 0x0000, 0x0000, 0x0000 }, /* R20109 */ + { 0x0000, 0x0000, 0x0000 }, /* R20110 */ + { 0x0000, 0x0000, 0x0000 }, /* R20111 */ + { 0x0000, 0x0000, 0x0000 }, /* R20112 */ + { 0x0000, 0x0000, 0x0000 }, /* R20113 */ + { 0x0000, 0x0000, 0x0000 }, /* R20114 */ + { 0x0000, 0x0000, 0x0000 }, /* R20115 */ + { 0x0000, 0x0000, 0x0000 }, /* R20116 */ + { 0x0000, 0x0000, 0x0000 }, /* R20117 */ + { 0x0000, 0x0000, 0x0000 }, /* R20118 */ + { 0x0000, 0x0000, 0x0000 }, /* R20119 */ + { 0x0000, 0x0000, 0x0000 }, /* R20120 */ + { 0x0000, 0x0000, 0x0000 }, /* R20121 */ + { 0x0000, 0x0000, 0x0000 }, /* R20122 */ + { 0x0000, 0x0000, 0x0000 }, /* R20123 */ + { 0x0000, 0x0000, 0x0000 }, /* R20124 */ + { 0x0000, 0x0000, 0x0000 }, /* R20125 */ + { 0x0000, 0x0000, 0x0000 }, /* R20126 */ + { 0x0000, 0x0000, 0x0000 }, /* R20127 */ + { 0x0000, 0x0000, 0x0000 }, /* R20128 */ + { 0x0000, 0x0000, 0x0000 }, /* R20129 */ + { 0x0000, 0x0000, 0x0000 }, /* R20130 */ + { 0x0000, 0x0000, 0x0000 }, /* R20131 */ + { 0x0000, 0x0000, 0x0000 }, /* R20132 */ + { 0x0000, 0x0000, 0x0000 }, /* R20133 */ + { 0x0000, 0x0000, 0x0000 }, /* R20134 */ + { 0x0000, 0x0000, 0x0000 }, /* R20135 */ + { 0x0000, 0x0000, 0x0000 }, /* R20136 */ + { 0x0000, 0x0000, 0x0000 }, /* R20137 */ + { 0x0000, 0x0000, 0x0000 }, /* R20138 */ + { 0x0000, 0x0000, 0x0000 }, /* R20139 */ + { 0x0000, 0x0000, 0x0000 }, /* R20140 */ + { 0x0000, 0x0000, 0x0000 }, /* R20141 */ + { 0x0000, 0x0000, 0x0000 }, /* R20142 */ + { 0x0000, 0x0000, 0x0000 }, /* R20143 */ + { 0x0000, 0x0000, 0x0000 }, /* R20144 */ + { 0x0000, 0x0000, 0x0000 }, /* R20145 */ + { 0x0000, 0x0000, 0x0000 }, /* R20146 */ + { 0x0000, 0x0000, 0x0000 }, /* R20147 */ + { 0x0000, 0x0000, 0x0000 }, /* R20148 */ + { 0x0000, 0x0000, 0x0000 }, /* R20149 */ + { 0x0000, 0x0000, 0x0000 }, /* R20150 */ + { 0x0000, 0x0000, 0x0000 }, /* R20151 */ + { 0x0000, 0x0000, 0x0000 }, /* R20152 */ + { 0x0000, 0x0000, 0x0000 }, /* R20153 */ + { 0x0000, 0x0000, 0x0000 }, /* R20154 */ + { 0x0000, 0x0000, 0x0000 }, /* R20155 */ + { 0x0000, 0x0000, 0x0000 }, /* R20156 */ + { 0x0000, 0x0000, 0x0000 }, /* R20157 */ + { 0x0000, 0x0000, 0x0000 }, /* R20158 */ + { 0x0000, 0x0000, 0x0000 }, /* R20159 */ + { 0x0000, 0x0000, 0x0000 }, /* R20160 */ + { 0x0000, 0x0000, 0x0000 }, /* R20161 */ + { 0x0000, 0x0000, 0x0000 }, /* R20162 */ + { 0x0000, 0x0000, 0x0000 }, /* R20163 */ + { 0x0000, 0x0000, 0x0000 }, /* R20164 */ + { 0x0000, 0x0000, 0x0000 }, /* R20165 */ + { 0x0000, 0x0000, 0x0000 }, /* R20166 */ + { 0x0000, 0x0000, 0x0000 }, /* R20167 */ + { 0x0000, 0x0000, 0x0000 }, /* R20168 */ + { 0x0000, 0x0000, 0x0000 }, /* R20169 */ + { 0x0000, 0x0000, 0x0000 }, /* R20170 */ + { 0x0000, 0x0000, 0x0000 }, /* R20171 */ + { 0x0000, 0x0000, 0x0000 }, /* R20172 */ + { 0x0000, 0x0000, 0x0000 }, /* R20173 */ + { 0x0000, 0x0000, 0x0000 }, /* R20174 */ + { 0x0000, 0x0000, 0x0000 }, /* R20175 */ + { 0x0000, 0x0000, 0x0000 }, /* R20176 */ + { 0x0000, 0x0000, 0x0000 }, /* R20177 */ + { 0x0000, 0x0000, 0x0000 }, /* R20178 */ + { 0x0000, 0x0000, 0x0000 }, /* R20179 */ + { 0x0000, 0x0000, 0x0000 }, /* R20180 */ + { 0x0000, 0x0000, 0x0000 }, /* R20181 */ + { 0x0000, 0x0000, 0x0000 }, /* R20182 */ + { 0x0000, 0x0000, 0x0000 }, /* R20183 */ + { 0x0000, 0x0000, 0x0000 }, /* R20184 */ + { 0x0000, 0x0000, 0x0000 }, /* R20185 */ + { 0x0000, 0x0000, 0x0000 }, /* R20186 */ + { 0x0000, 0x0000, 0x0000 }, /* R20187 */ + { 0x0000, 0x0000, 0x0000 }, /* R20188 */ + { 0x0000, 0x0000, 0x0000 }, /* R20189 */ + { 0x0000, 0x0000, 0x0000 }, /* R20190 */ + { 0x0000, 0x0000, 0x0000 }, /* R20191 */ + { 0x0000, 0x0000, 0x0000 }, /* R20192 */ + { 0x0000, 0x0000, 0x0000 }, /* R20193 */ + { 0x0000, 0x0000, 0x0000 }, /* R20194 */ + { 0x0000, 0x0000, 0x0000 }, /* R20195 */ + { 0x0000, 0x0000, 0x0000 }, /* R20196 */ + { 0x0000, 0x0000, 0x0000 }, /* R20197 */ + { 0x0000, 0x0000, 0x0000 }, /* R20198 */ + { 0x0000, 0x0000, 0x0000 }, /* R20199 */ + { 0x0000, 0x0000, 0x0000 }, /* R20200 */ + { 0x0000, 0x0000, 0x0000 }, /* R20201 */ + { 0x0000, 0x0000, 0x0000 }, /* R20202 */ + { 0x0000, 0x0000, 0x0000 }, /* R20203 */ + { 0x0000, 0x0000, 0x0000 }, /* R20204 */ + { 0x0000, 0x0000, 0x0000 }, /* R20205 */ + { 0x0000, 0x0000, 0x0000 }, /* R20206 */ + { 0x0000, 0x0000, 0x0000 }, /* R20207 */ + { 0x0000, 0x0000, 0x0000 }, /* R20208 */ + { 0x0000, 0x0000, 0x0000 }, /* R20209 */ + { 0x0000, 0x0000, 0x0000 }, /* R20210 */ + { 0x0000, 0x0000, 0x0000 }, /* R20211 */ + { 0x0000, 0x0000, 0x0000 }, /* R20212 */ + { 0x0000, 0x0000, 0x0000 }, /* R20213 */ + { 0x0000, 0x0000, 0x0000 }, /* R20214 */ + { 0x0000, 0x0000, 0x0000 }, /* R20215 */ + { 0x0000, 0x0000, 0x0000 }, /* R20216 */ + { 0x0000, 0x0000, 0x0000 }, /* R20217 */ + { 0x0000, 0x0000, 0x0000 }, /* R20218 */ + { 0x0000, 0x0000, 0x0000 }, /* R20219 */ + { 0x0000, 0x0000, 0x0000 }, /* R20220 */ + { 0x0000, 0x0000, 0x0000 }, /* R20221 */ + { 0x0000, 0x0000, 0x0000 }, /* R20222 */ + { 0x0000, 0x0000, 0x0000 }, /* R20223 */ + { 0x0000, 0x0000, 0x0000 }, /* R20224 */ + { 0x0000, 0x0000, 0x0000 }, /* R20225 */ + { 0x0000, 0x0000, 0x0000 }, /* R20226 */ + { 0x0000, 0x0000, 0x0000 }, /* R20227 */ + { 0x0000, 0x0000, 0x0000 }, /* R20228 */ + { 0x0000, 0x0000, 0x0000 }, /* R20229 */ + { 0x0000, 0x0000, 0x0000 }, /* R20230 */ + { 0x0000, 0x0000, 0x0000 }, /* R20231 */ + { 0x0000, 0x0000, 0x0000 }, /* R20232 */ + { 0x0000, 0x0000, 0x0000 }, /* R20233 */ + { 0x0000, 0x0000, 0x0000 }, /* R20234 */ + { 0x0000, 0x0000, 0x0000 }, /* R20235 */ + { 0x0000, 0x0000, 0x0000 }, /* R20236 */ + { 0x0000, 0x0000, 0x0000 }, /* R20237 */ + { 0x0000, 0x0000, 0x0000 }, /* R20238 */ + { 0x0000, 0x0000, 0x0000 }, /* R20239 */ + { 0x0000, 0x0000, 0x0000 }, /* R20240 */ + { 0x0000, 0x0000, 0x0000 }, /* R20241 */ + { 0x0000, 0x0000, 0x0000 }, /* R20242 */ + { 0x0000, 0x0000, 0x0000 }, /* R20243 */ + { 0x0000, 0x0000, 0x0000 }, /* R20244 */ + { 0x0000, 0x0000, 0x0000 }, /* R20245 */ + { 0x0000, 0x0000, 0x0000 }, /* R20246 */ + { 0x0000, 0x0000, 0x0000 }, /* R20247 */ + { 0x0000, 0x0000, 0x0000 }, /* R20248 */ + { 0x0000, 0x0000, 0x0000 }, /* R20249 */ + { 0x0000, 0x0000, 0x0000 }, /* R20250 */ + { 0x0000, 0x0000, 0x0000 }, /* R20251 */ + { 0x0000, 0x0000, 0x0000 }, /* R20252 */ + { 0x0000, 0x0000, 0x0000 }, /* R20253 */ + { 0x0000, 0x0000, 0x0000 }, /* R20254 */ + { 0x0000, 0x0000, 0x0000 }, /* R20255 */ + { 0x0000, 0x0000, 0x0000 }, /* R20256 */ + { 0x0000, 0x0000, 0x0000 }, /* R20257 */ + { 0x0000, 0x0000, 0x0000 }, /* R20258 */ + { 0x0000, 0x0000, 0x0000 }, /* R20259 */ + { 0x0000, 0x0000, 0x0000 }, /* R20260 */ + { 0x0000, 0x0000, 0x0000 }, /* R20261 */ + { 0x0000, 0x0000, 0x0000 }, /* R20262 */ + { 0x0000, 0x0000, 0x0000 }, /* R20263 */ + { 0x0000, 0x0000, 0x0000 }, /* R20264 */ + { 0x0000, 0x0000, 0x0000 }, /* R20265 */ + { 0x0000, 0x0000, 0x0000 }, /* R20266 */ + { 0x0000, 0x0000, 0x0000 }, /* R20267 */ + { 0x0000, 0x0000, 0x0000 }, /* R20268 */ + { 0x0000, 0x0000, 0x0000 }, /* R20269 */ + { 0x0000, 0x0000, 0x0000 }, /* R20270 */ + { 0x0000, 0x0000, 0x0000 }, /* R20271 */ + { 0x0000, 0x0000, 0x0000 }, /* R20272 */ + { 0x0000, 0x0000, 0x0000 }, /* R20273 */ + { 0x0000, 0x0000, 0x0000 }, /* R20274 */ + { 0x0000, 0x0000, 0x0000 }, /* R20275 */ + { 0x0000, 0x0000, 0x0000 }, /* R20276 */ + { 0x0000, 0x0000, 0x0000 }, /* R20277 */ + { 0x0000, 0x0000, 0x0000 }, /* R20278 */ + { 0x0000, 0x0000, 0x0000 }, /* R20279 */ + { 0x0000, 0x0000, 0x0000 }, /* R20280 */ + { 0x0000, 0x0000, 0x0000 }, /* R20281 */ + { 0x0000, 0x0000, 0x0000 }, /* R20282 */ + { 0x0000, 0x0000, 0x0000 }, /* R20283 */ + { 0x0000, 0x0000, 0x0000 }, /* R20284 */ + { 0x0000, 0x0000, 0x0000 }, /* R20285 */ + { 0x0000, 0x0000, 0x0000 }, /* R20286 */ + { 0x0000, 0x0000, 0x0000 }, /* R20287 */ + { 0x0000, 0x0000, 0x0000 }, /* R20288 */ + { 0x0000, 0x0000, 0x0000 }, /* R20289 */ + { 0x0000, 0x0000, 0x0000 }, /* R20290 */ + { 0x0000, 0x0000, 0x0000 }, /* R20291 */ + { 0x0000, 0x0000, 0x0000 }, /* R20292 */ + { 0x0000, 0x0000, 0x0000 }, /* R20293 */ + { 0x0000, 0x0000, 0x0000 }, /* R20294 */ + { 0x0000, 0x0000, 0x0000 }, /* R20295 */ + { 0x0000, 0x0000, 0x0000 }, /* R20296 */ + { 0x0000, 0x0000, 0x0000 }, /* R20297 */ + { 0x0000, 0x0000, 0x0000 }, /* R20298 */ + { 0x0000, 0x0000, 0x0000 }, /* R20299 */ + { 0x0000, 0x0000, 0x0000 }, /* R20300 */ + { 0x0000, 0x0000, 0x0000 }, /* R20301 */ + { 0x0000, 0x0000, 0x0000 }, /* R20302 */ + { 0x0000, 0x0000, 0x0000 }, /* R20303 */ + { 0x0000, 0x0000, 0x0000 }, /* R20304 */ + { 0x0000, 0x0000, 0x0000 }, /* R20305 */ + { 0x0000, 0x0000, 0x0000 }, /* R20306 */ + { 0x0000, 0x0000, 0x0000 }, /* R20307 */ + { 0x0000, 0x0000, 0x0000 }, /* R20308 */ + { 0x0000, 0x0000, 0x0000 }, /* R20309 */ + { 0x0000, 0x0000, 0x0000 }, /* R20310 */ + { 0x0000, 0x0000, 0x0000 }, /* R20311 */ + { 0x0000, 0x0000, 0x0000 }, /* R20312 */ + { 0x0000, 0x0000, 0x0000 }, /* R20313 */ + { 0x0000, 0x0000, 0x0000 }, /* R20314 */ + { 0x0000, 0x0000, 0x0000 }, /* R20315 */ + { 0x0000, 0x0000, 0x0000 }, /* R20316 */ + { 0x0000, 0x0000, 0x0000 }, /* R20317 */ + { 0x0000, 0x0000, 0x0000 }, /* R20318 */ + { 0x0000, 0x0000, 0x0000 }, /* R20319 */ + { 0x0000, 0x0000, 0x0000 }, /* R20320 */ + { 0x0000, 0x0000, 0x0000 }, /* R20321 */ + { 0x0000, 0x0000, 0x0000 }, /* R20322 */ + { 0x0000, 0x0000, 0x0000 }, /* R20323 */ + { 0x0000, 0x0000, 0x0000 }, /* R20324 */ + { 0x0000, 0x0000, 0x0000 }, /* R20325 */ + { 0x0000, 0x0000, 0x0000 }, /* R20326 */ + { 0x0000, 0x0000, 0x0000 }, /* R20327 */ + { 0x0000, 0x0000, 0x0000 }, /* R20328 */ + { 0x0000, 0x0000, 0x0000 }, /* R20329 */ + { 0x0000, 0x0000, 0x0000 }, /* R20330 */ + { 0x0000, 0x0000, 0x0000 }, /* R20331 */ + { 0x0000, 0x0000, 0x0000 }, /* R20332 */ + { 0x0000, 0x0000, 0x0000 }, /* R20333 */ + { 0x0000, 0x0000, 0x0000 }, /* R20334 */ + { 0x0000, 0x0000, 0x0000 }, /* R20335 */ + { 0x0000, 0x0000, 0x0000 }, /* R20336 */ + { 0x0000, 0x0000, 0x0000 }, /* R20337 */ + { 0x0000, 0x0000, 0x0000 }, /* R20338 */ + { 0x0000, 0x0000, 0x0000 }, /* R20339 */ + { 0x0000, 0x0000, 0x0000 }, /* R20340 */ + { 0x0000, 0x0000, 0x0000 }, /* R20341 */ + { 0x0000, 0x0000, 0x0000 }, /* R20342 */ + { 0x0000, 0x0000, 0x0000 }, /* R20343 */ + { 0x0000, 0x0000, 0x0000 }, /* R20344 */ + { 0x0000, 0x0000, 0x0000 }, /* R20345 */ + { 0x0000, 0x0000, 0x0000 }, /* R20346 */ + { 0x0000, 0x0000, 0x0000 }, /* R20347 */ + { 0x0000, 0x0000, 0x0000 }, /* R20348 */ + { 0x0000, 0x0000, 0x0000 }, /* R20349 */ + { 0x0000, 0x0000, 0x0000 }, /* R20350 */ + { 0x0000, 0x0000, 0x0000 }, /* R20351 */ + { 0x0000, 0x0000, 0x0000 }, /* R20352 */ + { 0x0000, 0x0000, 0x0000 }, /* R20353 */ + { 0x0000, 0x0000, 0x0000 }, /* R20354 */ + { 0x0000, 0x0000, 0x0000 }, /* R20355 */ + { 0x0000, 0x0000, 0x0000 }, /* R20356 */ + { 0x0000, 0x0000, 0x0000 }, /* R20357 */ + { 0x0000, 0x0000, 0x0000 }, /* R20358 */ + { 0x0000, 0x0000, 0x0000 }, /* R20359 */ + { 0x0000, 0x0000, 0x0000 }, /* R20360 */ + { 0x0000, 0x0000, 0x0000 }, /* R20361 */ + { 0x0000, 0x0000, 0x0000 }, /* R20362 */ + { 0x0000, 0x0000, 0x0000 }, /* R20363 */ + { 0x0000, 0x0000, 0x0000 }, /* R20364 */ + { 0x0000, 0x0000, 0x0000 }, /* R20365 */ + { 0x0000, 0x0000, 0x0000 }, /* R20366 */ + { 0x0000, 0x0000, 0x0000 }, /* R20367 */ + { 0x0000, 0x0000, 0x0000 }, /* R20368 */ + { 0x0000, 0x0000, 0x0000 }, /* R20369 */ + { 0x0000, 0x0000, 0x0000 }, /* R20370 */ + { 0x0000, 0x0000, 0x0000 }, /* R20371 */ + { 0x0000, 0x0000, 0x0000 }, /* R20372 */ + { 0x0000, 0x0000, 0x0000 }, /* R20373 */ + { 0x0000, 0x0000, 0x0000 }, /* R20374 */ + { 0x0000, 0x0000, 0x0000 }, /* R20375 */ + { 0x0000, 0x0000, 0x0000 }, /* R20376 */ + { 0x0000, 0x0000, 0x0000 }, /* R20377 */ + { 0x0000, 0x0000, 0x0000 }, /* R20378 */ + { 0x0000, 0x0000, 0x0000 }, /* R20379 */ + { 0x0000, 0x0000, 0x0000 }, /* R20380 */ + { 0x0000, 0x0000, 0x0000 }, /* R20381 */ + { 0x0000, 0x0000, 0x0000 }, /* R20382 */ + { 0x0000, 0x0000, 0x0000 }, /* R20383 */ + { 0x0000, 0x0000, 0x0000 }, /* R20384 */ + { 0x0000, 0x0000, 0x0000 }, /* R20385 */ + { 0x0000, 0x0000, 0x0000 }, /* R20386 */ + { 0x0000, 0x0000, 0x0000 }, /* R20387 */ + { 0x0000, 0x0000, 0x0000 }, /* R20388 */ + { 0x0000, 0x0000, 0x0000 }, /* R20389 */ + { 0x0000, 0x0000, 0x0000 }, /* R20390 */ + { 0x0000, 0x0000, 0x0000 }, /* R20391 */ + { 0x0000, 0x0000, 0x0000 }, /* R20392 */ + { 0x0000, 0x0000, 0x0000 }, /* R20393 */ + { 0x0000, 0x0000, 0x0000 }, /* R20394 */ + { 0x0000, 0x0000, 0x0000 }, /* R20395 */ + { 0x0000, 0x0000, 0x0000 }, /* R20396 */ + { 0x0000, 0x0000, 0x0000 }, /* R20397 */ + { 0x0000, 0x0000, 0x0000 }, /* R20398 */ + { 0x0000, 0x0000, 0x0000 }, /* R20399 */ + { 0x0000, 0x0000, 0x0000 }, /* R20400 */ + { 0x0000, 0x0000, 0x0000 }, /* R20401 */ + { 0x0000, 0x0000, 0x0000 }, /* R20402 */ + { 0x0000, 0x0000, 0x0000 }, /* R20403 */ + { 0x0000, 0x0000, 0x0000 }, /* R20404 */ + { 0x0000, 0x0000, 0x0000 }, /* R20405 */ + { 0x0000, 0x0000, 0x0000 }, /* R20406 */ + { 0x0000, 0x0000, 0x0000 }, /* R20407 */ + { 0x0000, 0x0000, 0x0000 }, /* R20408 */ + { 0x0000, 0x0000, 0x0000 }, /* R20409 */ + { 0x0000, 0x0000, 0x0000 }, /* R20410 */ + { 0x0000, 0x0000, 0x0000 }, /* R20411 */ + { 0x0000, 0x0000, 0x0000 }, /* R20412 */ + { 0x0000, 0x0000, 0x0000 }, /* R20413 */ + { 0x0000, 0x0000, 0x0000 }, /* R20414 */ + { 0x0000, 0x0000, 0x0000 }, /* R20415 */ + { 0x0000, 0x0000, 0x0000 }, /* R20416 */ + { 0x0000, 0x0000, 0x0000 }, /* R20417 */ + { 0x0000, 0x0000, 0x0000 }, /* R20418 */ + { 0x0000, 0x0000, 0x0000 }, /* R20419 */ + { 0x0000, 0x0000, 0x0000 }, /* R20420 */ + { 0x0000, 0x0000, 0x0000 }, /* R20421 */ + { 0x0000, 0x0000, 0x0000 }, /* R20422 */ + { 0x0000, 0x0000, 0x0000 }, /* R20423 */ + { 0x0000, 0x0000, 0x0000 }, /* R20424 */ + { 0x0000, 0x0000, 0x0000 }, /* R20425 */ + { 0x0000, 0x0000, 0x0000 }, /* R20426 */ + { 0x0000, 0x0000, 0x0000 }, /* R20427 */ + { 0x0000, 0x0000, 0x0000 }, /* R20428 */ + { 0x0000, 0x0000, 0x0000 }, /* R20429 */ + { 0x0000, 0x0000, 0x0000 }, /* R20430 */ + { 0x0000, 0x0000, 0x0000 }, /* R20431 */ + { 0x0000, 0x0000, 0x0000 }, /* R20432 */ + { 0x0000, 0x0000, 0x0000 }, /* R20433 */ + { 0x0000, 0x0000, 0x0000 }, /* R20434 */ + { 0x0000, 0x0000, 0x0000 }, /* R20435 */ + { 0x0000, 0x0000, 0x0000 }, /* R20436 */ + { 0x0000, 0x0000, 0x0000 }, /* R20437 */ + { 0x0000, 0x0000, 0x0000 }, /* R20438 */ + { 0x0000, 0x0000, 0x0000 }, /* R20439 */ + { 0x0000, 0x0000, 0x0000 }, /* R20440 */ + { 0x0000, 0x0000, 0x0000 }, /* R20441 */ + { 0x0000, 0x0000, 0x0000 }, /* R20442 */ + { 0x0000, 0x0000, 0x0000 }, /* R20443 */ + { 0x0000, 0x0000, 0x0000 }, /* R20444 */ + { 0x0000, 0x0000, 0x0000 }, /* R20445 */ + { 0x0000, 0x0000, 0x0000 }, /* R20446 */ + { 0x0000, 0x0000, 0x0000 }, /* R20447 */ + { 0x0000, 0x0000, 0x0000 }, /* R20448 */ + { 0x0000, 0x0000, 0x0000 }, /* R20449 */ + { 0x0000, 0x0000, 0x0000 }, /* R20450 */ + { 0x0000, 0x0000, 0x0000 }, /* R20451 */ + { 0x0000, 0x0000, 0x0000 }, /* R20452 */ + { 0x0000, 0x0000, 0x0000 }, /* R20453 */ + { 0x0000, 0x0000, 0x0000 }, /* R20454 */ + { 0x0000, 0x0000, 0x0000 }, /* R20455 */ + { 0x0000, 0x0000, 0x0000 }, /* R20456 */ + { 0x0000, 0x0000, 0x0000 }, /* R20457 */ + { 0x0000, 0x0000, 0x0000 }, /* R20458 */ + { 0x0000, 0x0000, 0x0000 }, /* R20459 */ + { 0x0000, 0x0000, 0x0000 }, /* R20460 */ + { 0x0000, 0x0000, 0x0000 }, /* R20461 */ + { 0x0000, 0x0000, 0x0000 }, /* R20462 */ + { 0x0000, 0x0000, 0x0000 }, /* R20463 */ + { 0x0000, 0x0000, 0x0000 }, /* R20464 */ + { 0x0000, 0x0000, 0x0000 }, /* R20465 */ + { 0x0000, 0x0000, 0x0000 }, /* R20466 */ + { 0x0000, 0x0000, 0x0000 }, /* R20467 */ + { 0x0000, 0x0000, 0x0000 }, /* R20468 */ + { 0x0000, 0x0000, 0x0000 }, /* R20469 */ + { 0x0000, 0x0000, 0x0000 }, /* R20470 */ + { 0x0000, 0x0000, 0x0000 }, /* R20471 */ + { 0x0000, 0x0000, 0x0000 }, /* R20472 */ + { 0x0000, 0x0000, 0x0000 }, /* R20473 */ + { 0x0000, 0x0000, 0x0000 }, /* R20474 */ + { 0x0000, 0x0000, 0x0000 }, /* R20475 */ + { 0x0000, 0x0000, 0x0000 }, /* R20476 */ + { 0x0000, 0x0000, 0x0000 }, /* R20477 */ + { 0x0000, 0x0000, 0x0000 }, /* R20478 */ + { 0x0000, 0x0000, 0x0000 }, /* R20479 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20480 - DACR_RETUNE_C1_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20481 - DACR_RETUNE_C1_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20482 - DACR_RETUNE_C2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20483 - DACR_RETUNE_C2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20484 - DACR_RETUNE_C3_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20485 - DACR_RETUNE_C3_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20486 - DACR_RETUNE_C4_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20487 - DACR_RETUNE_C4_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20488 - DACR_RETUNE_C5_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20489 - DACR_RETUNE_C5_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20490 - DACR_RETUNE_C6_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20491 - DACR_RETUNE_C6_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20492 - DACR_RETUNE_C7_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20493 - DACR_RETUNE_C7_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20494 - DACR_RETUNE_C8_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20495 - DACR_RETUNE_C8_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20496 - DACR_RETUNE_C9_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20497 - DACR_RETUNE_C9_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20498 - DACR_RETUNE_C10_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20499 - DACR_RETUNE_C10_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20500 - DACR_RETUNE_C11_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20501 - DACR_RETUNE_C11_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20502 - DACR_RETUNE_C12_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20503 - DACR_RETUNE_C12_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20504 - DACR_RETUNE_C13_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20505 - DACR_RETUNE_C13_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20506 - DACR_RETUNE_C14_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20507 - DACR_RETUNE_C14_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20508 - DACR_RETUNE_C15_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20509 - DACR_RETUNE_C15_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20510 - DACR_RETUNE_C16_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20511 - DACR_RETUNE_C16_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20512 - DACR_RETUNE_C17_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20513 - DACR_RETUNE_C17_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20514 - DACR_RETUNE_C18_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20515 - DACR_RETUNE_C18_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20516 - DACR_RETUNE_C19_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20517 - DACR_RETUNE_C19_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20518 - DACR_RETUNE_C20_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20519 - DACR_RETUNE_C20_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20520 - DACR_RETUNE_C21_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20521 - DACR_RETUNE_C21_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20522 - DACR_RETUNE_C22_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20523 - DACR_RETUNE_C22_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20524 - DACR_RETUNE_C23_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20525 - DACR_RETUNE_C23_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20526 - DACR_RETUNE_C24_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20527 - DACR_RETUNE_C24_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20528 - DACR_RETUNE_C25_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20529 - DACR_RETUNE_C25_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20530 - DACR_RETUNE_C26_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20531 - DACR_RETUNE_C26_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20532 - DACR_RETUNE_C27_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20533 - DACR_RETUNE_C27_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20534 - DACR_RETUNE_C28_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20535 - DACR_RETUNE_C28_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20536 - DACR_RETUNE_C29_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20537 - DACR_RETUNE_C29_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20538 - DACR_RETUNE_C30_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20539 - DACR_RETUNE_C30_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20540 - DACR_RETUNE_C31_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20541 - DACR_RETUNE_C31_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20542 - DACR_RETUNE_C32_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20543 - DACR_RETUNE_C32_0 */ + { 0x0000, 0x0000, 0x0000 }, /* R20544 */ + { 0x0000, 0x0000, 0x0000 }, /* R20545 */ + { 0x0000, 0x0000, 0x0000 }, /* R20546 */ + { 0x0000, 0x0000, 0x0000 }, /* R20547 */ + { 0x0000, 0x0000, 0x0000 }, /* R20548 */ + { 0x0000, 0x0000, 0x0000 }, /* R20549 */ + { 0x0000, 0x0000, 0x0000 }, /* R20550 */ + { 0x0000, 0x0000, 0x0000 }, /* R20551 */ + { 0x0000, 0x0000, 0x0000 }, /* R20552 */ + { 0x0000, 0x0000, 0x0000 }, /* R20553 */ + { 0x0000, 0x0000, 0x0000 }, /* R20554 */ + { 0x0000, 0x0000, 0x0000 }, /* R20555 */ + { 0x0000, 0x0000, 0x0000 }, /* R20556 */ + { 0x0000, 0x0000, 0x0000 }, /* R20557 */ + { 0x0000, 0x0000, 0x0000 }, /* R20558 */ + { 0x0000, 0x0000, 0x0000 }, /* R20559 */ + { 0x0000, 0x0000, 0x0000 }, /* R20560 */ + { 0x0000, 0x0000, 0x0000 }, /* R20561 */ + { 0x0000, 0x0000, 0x0000 }, /* R20562 */ + { 0x0000, 0x0000, 0x0000 }, /* R20563 */ + { 0x0000, 0x0000, 0x0000 }, /* R20564 */ + { 0x0000, 0x0000, 0x0000 }, /* R20565 */ + { 0x0000, 0x0000, 0x0000 }, /* R20566 */ + { 0x0000, 0x0000, 0x0000 }, /* R20567 */ + { 0x0000, 0x0000, 0x0000 }, /* R20568 */ + { 0x0000, 0x0000, 0x0000 }, /* R20569 */ + { 0x0000, 0x0000, 0x0000 }, /* R20570 */ + { 0x0000, 0x0000, 0x0000 }, /* R20571 */ + { 0x0000, 0x0000, 0x0000 }, /* R20572 */ + { 0x0000, 0x0000, 0x0000 }, /* R20573 */ + { 0x0000, 0x0000, 0x0000 }, /* R20574 */ + { 0x0000, 0x0000, 0x0000 }, /* R20575 */ + { 0x0000, 0x0000, 0x0000 }, /* R20576 */ + { 0x0000, 0x0000, 0x0000 }, /* R20577 */ + { 0x0000, 0x0000, 0x0000 }, /* R20578 */ + { 0x0000, 0x0000, 0x0000 }, /* R20579 */ + { 0x0000, 0x0000, 0x0000 }, /* R20580 */ + { 0x0000, 0x0000, 0x0000 }, /* R20581 */ + { 0x0000, 0x0000, 0x0000 }, /* R20582 */ + { 0x0000, 0x0000, 0x0000 }, /* R20583 */ + { 0x0000, 0x0000, 0x0000 }, /* R20584 */ + { 0x0000, 0x0000, 0x0000 }, /* R20585 */ + { 0x0000, 0x0000, 0x0000 }, /* R20586 */ + { 0x0000, 0x0000, 0x0000 }, /* R20587 */ + { 0x0000, 0x0000, 0x0000 }, /* R20588 */ + { 0x0000, 0x0000, 0x0000 }, /* R20589 */ + { 0x0000, 0x0000, 0x0000 }, /* R20590 */ + { 0x0000, 0x0000, 0x0000 }, /* R20591 */ + { 0x0000, 0x0000, 0x0000 }, /* R20592 */ + { 0x0000, 0x0000, 0x0000 }, /* R20593 */ + { 0x0000, 0x0000, 0x0000 }, /* R20594 */ + { 0x0000, 0x0000, 0x0000 }, /* R20595 */ + { 0x0000, 0x0000, 0x0000 }, /* R20596 */ + { 0x0000, 0x0000, 0x0000 }, /* R20597 */ + { 0x0000, 0x0000, 0x0000 }, /* R20598 */ + { 0x0000, 0x0000, 0x0000 }, /* R20599 */ + { 0x0000, 0x0000, 0x0000 }, /* R20600 */ + { 0x0000, 0x0000, 0x0000 }, /* R20601 */ + { 0x0000, 0x0000, 0x0000 }, /* R20602 */ + { 0x0000, 0x0000, 0x0000 }, /* R20603 */ + { 0x0000, 0x0000, 0x0000 }, /* R20604 */ + { 0x0000, 0x0000, 0x0000 }, /* R20605 */ + { 0x0000, 0x0000, 0x0000 }, /* R20606 */ + { 0x0000, 0x0000, 0x0000 }, /* R20607 */ + { 0x0000, 0x0000, 0x0000 }, /* R20608 */ + { 0x0000, 0x0000, 0x0000 }, /* R20609 */ + { 0x0000, 0x0000, 0x0000 }, /* R20610 */ + { 0x0000, 0x0000, 0x0000 }, /* R20611 */ + { 0x0000, 0x0000, 0x0000 }, /* R20612 */ + { 0x0000, 0x0000, 0x0000 }, /* R20613 */ + { 0x0000, 0x0000, 0x0000 }, /* R20614 */ + { 0x0000, 0x0000, 0x0000 }, /* R20615 */ + { 0x0000, 0x0000, 0x0000 }, /* R20616 */ + { 0x0000, 0x0000, 0x0000 }, /* R20617 */ + { 0x0000, 0x0000, 0x0000 }, /* R20618 */ + { 0x0000, 0x0000, 0x0000 }, /* R20619 */ + { 0x0000, 0x0000, 0x0000 }, /* R20620 */ + { 0x0000, 0x0000, 0x0000 }, /* R20621 */ + { 0x0000, 0x0000, 0x0000 }, /* R20622 */ + { 0x0000, 0x0000, 0x0000 }, /* R20623 */ + { 0x0000, 0x0000, 0x0000 }, /* R20624 */ + { 0x0000, 0x0000, 0x0000 }, /* R20625 */ + { 0x0000, 0x0000, 0x0000 }, /* R20626 */ + { 0x0000, 0x0000, 0x0000 }, /* R20627 */ + { 0x0000, 0x0000, 0x0000 }, /* R20628 */ + { 0x0000, 0x0000, 0x0000 }, /* R20629 */ + { 0x0000, 0x0000, 0x0000 }, /* R20630 */ + { 0x0000, 0x0000, 0x0000 }, /* R20631 */ + { 0x0000, 0x0000, 0x0000 }, /* R20632 */ + { 0x0000, 0x0000, 0x0000 }, /* R20633 */ + { 0x0000, 0x0000, 0x0000 }, /* R20634 */ + { 0x0000, 0x0000, 0x0000 }, /* R20635 */ + { 0x0000, 0x0000, 0x0000 }, /* R20636 */ + { 0x0000, 0x0000, 0x0000 }, /* R20637 */ + { 0x0000, 0x0000, 0x0000 }, /* R20638 */ + { 0x0000, 0x0000, 0x0000 }, /* R20639 */ + { 0x0000, 0x0000, 0x0000 }, /* R20640 */ + { 0x0000, 0x0000, 0x0000 }, /* R20641 */ + { 0x0000, 0x0000, 0x0000 }, /* R20642 */ + { 0x0000, 0x0000, 0x0000 }, /* R20643 */ + { 0x0000, 0x0000, 0x0000 }, /* R20644 */ + { 0x0000, 0x0000, 0x0000 }, /* R20645 */ + { 0x0000, 0x0000, 0x0000 }, /* R20646 */ + { 0x0000, 0x0000, 0x0000 }, /* R20647 */ + { 0x0000, 0x0000, 0x0000 }, /* R20648 */ + { 0x0000, 0x0000, 0x0000 }, /* R20649 */ + { 0x0000, 0x0000, 0x0000 }, /* R20650 */ + { 0x0000, 0x0000, 0x0000 }, /* R20651 */ + { 0x0000, 0x0000, 0x0000 }, /* R20652 */ + { 0x0000, 0x0000, 0x0000 }, /* R20653 */ + { 0x0000, 0x0000, 0x0000 }, /* R20654 */ + { 0x0000, 0x0000, 0x0000 }, /* R20655 */ + { 0x0000, 0x0000, 0x0000 }, /* R20656 */ + { 0x0000, 0x0000, 0x0000 }, /* R20657 */ + { 0x0000, 0x0000, 0x0000 }, /* R20658 */ + { 0x0000, 0x0000, 0x0000 }, /* R20659 */ + { 0x0000, 0x0000, 0x0000 }, /* R20660 */ + { 0x0000, 0x0000, 0x0000 }, /* R20661 */ + { 0x0000, 0x0000, 0x0000 }, /* R20662 */ + { 0x0000, 0x0000, 0x0000 }, /* R20663 */ + { 0x0000, 0x0000, 0x0000 }, /* R20664 */ + { 0x0000, 0x0000, 0x0000 }, /* R20665 */ + { 0x0000, 0x0000, 0x0000 }, /* R20666 */ + { 0x0000, 0x0000, 0x0000 }, /* R20667 */ + { 0x0000, 0x0000, 0x0000 }, /* R20668 */ + { 0x0000, 0x0000, 0x0000 }, /* R20669 */ + { 0x0000, 0x0000, 0x0000 }, /* R20670 */ + { 0x0000, 0x0000, 0x0000 }, /* R20671 */ + { 0x0000, 0x0000, 0x0000 }, /* R20672 */ + { 0x0000, 0x0000, 0x0000 }, /* R20673 */ + { 0x0000, 0x0000, 0x0000 }, /* R20674 */ + { 0x0000, 0x0000, 0x0000 }, /* R20675 */ + { 0x0000, 0x0000, 0x0000 }, /* R20676 */ + { 0x0000, 0x0000, 0x0000 }, /* R20677 */ + { 0x0000, 0x0000, 0x0000 }, /* R20678 */ + { 0x0000, 0x0000, 0x0000 }, /* R20679 */ + { 0x0000, 0x0000, 0x0000 }, /* R20680 */ + { 0x0000, 0x0000, 0x0000 }, /* R20681 */ + { 0x0000, 0x0000, 0x0000 }, /* R20682 */ + { 0x0000, 0x0000, 0x0000 }, /* R20683 */ + { 0x0000, 0x0000, 0x0000 }, /* R20684 */ + { 0x0000, 0x0000, 0x0000 }, /* R20685 */ + { 0x0000, 0x0000, 0x0000 }, /* R20686 */ + { 0x0000, 0x0000, 0x0000 }, /* R20687 */ + { 0x0000, 0x0000, 0x0000 }, /* R20688 */ + { 0x0000, 0x0000, 0x0000 }, /* R20689 */ + { 0x0000, 0x0000, 0x0000 }, /* R20690 */ + { 0x0000, 0x0000, 0x0000 }, /* R20691 */ + { 0x0000, 0x0000, 0x0000 }, /* R20692 */ + { 0x0000, 0x0000, 0x0000 }, /* R20693 */ + { 0x0000, 0x0000, 0x0000 }, /* R20694 */ + { 0x0000, 0x0000, 0x0000 }, /* R20695 */ + { 0x0000, 0x0000, 0x0000 }, /* R20696 */ + { 0x0000, 0x0000, 0x0000 }, /* R20697 */ + { 0x0000, 0x0000, 0x0000 }, /* R20698 */ + { 0x0000, 0x0000, 0x0000 }, /* R20699 */ + { 0x0000, 0x0000, 0x0000 }, /* R20700 */ + { 0x0000, 0x0000, 0x0000 }, /* R20701 */ + { 0x0000, 0x0000, 0x0000 }, /* R20702 */ + { 0x0000, 0x0000, 0x0000 }, /* R20703 */ + { 0x0000, 0x0000, 0x0000 }, /* R20704 */ + { 0x0000, 0x0000, 0x0000 }, /* R20705 */ + { 0x0000, 0x0000, 0x0000 }, /* R20706 */ + { 0x0000, 0x0000, 0x0000 }, /* R20707 */ + { 0x0000, 0x0000, 0x0000 }, /* R20708 */ + { 0x0000, 0x0000, 0x0000 }, /* R20709 */ + { 0x0000, 0x0000, 0x0000 }, /* R20710 */ + { 0x0000, 0x0000, 0x0000 }, /* R20711 */ + { 0x0000, 0x0000, 0x0000 }, /* R20712 */ + { 0x0000, 0x0000, 0x0000 }, /* R20713 */ + { 0x0000, 0x0000, 0x0000 }, /* R20714 */ + { 0x0000, 0x0000, 0x0000 }, /* R20715 */ + { 0x0000, 0x0000, 0x0000 }, /* R20716 */ + { 0x0000, 0x0000, 0x0000 }, /* R20717 */ + { 0x0000, 0x0000, 0x0000 }, /* R20718 */ + { 0x0000, 0x0000, 0x0000 }, /* R20719 */ + { 0x0000, 0x0000, 0x0000 }, /* R20720 */ + { 0x0000, 0x0000, 0x0000 }, /* R20721 */ + { 0x0000, 0x0000, 0x0000 }, /* R20722 */ + { 0x0000, 0x0000, 0x0000 }, /* R20723 */ + { 0x0000, 0x0000, 0x0000 }, /* R20724 */ + { 0x0000, 0x0000, 0x0000 }, /* R20725 */ + { 0x0000, 0x0000, 0x0000 }, /* R20726 */ + { 0x0000, 0x0000, 0x0000 }, /* R20727 */ + { 0x0000, 0x0000, 0x0000 }, /* R20728 */ + { 0x0000, 0x0000, 0x0000 }, /* R20729 */ + { 0x0000, 0x0000, 0x0000 }, /* R20730 */ + { 0x0000, 0x0000, 0x0000 }, /* R20731 */ + { 0x0000, 0x0000, 0x0000 }, /* R20732 */ + { 0x0000, 0x0000, 0x0000 }, /* R20733 */ + { 0x0000, 0x0000, 0x0000 }, /* R20734 */ + { 0x0000, 0x0000, 0x0000 }, /* R20735 */ + { 0x0000, 0x0000, 0x0000 }, /* R20736 */ + { 0x0000, 0x0000, 0x0000 }, /* R20737 */ + { 0x0000, 0x0000, 0x0000 }, /* R20738 */ + { 0x0000, 0x0000, 0x0000 }, /* R20739 */ + { 0x0000, 0x0000, 0x0000 }, /* R20740 */ + { 0x0000, 0x0000, 0x0000 }, /* R20741 */ + { 0x0000, 0x0000, 0x0000 }, /* R20742 */ + { 0x0000, 0x0000, 0x0000 }, /* R20743 */ + { 0x0000, 0x0000, 0x0000 }, /* R20744 */ + { 0x0000, 0x0000, 0x0000 }, /* R20745 */ + { 0x0000, 0x0000, 0x0000 }, /* R20746 */ + { 0x0000, 0x0000, 0x0000 }, /* R20747 */ + { 0x0000, 0x0000, 0x0000 }, /* R20748 */ + { 0x0000, 0x0000, 0x0000 }, /* R20749 */ + { 0x0000, 0x0000, 0x0000 }, /* R20750 */ + { 0x0000, 0x0000, 0x0000 }, /* R20751 */ + { 0x0000, 0x0000, 0x0000 }, /* R20752 */ + { 0x0000, 0x0000, 0x0000 }, /* R20753 */ + { 0x0000, 0x0000, 0x0000 }, /* R20754 */ + { 0x0000, 0x0000, 0x0000 }, /* R20755 */ + { 0x0000, 0x0000, 0x0000 }, /* R20756 */ + { 0x0000, 0x0000, 0x0000 }, /* R20757 */ + { 0x0000, 0x0000, 0x0000 }, /* R20758 */ + { 0x0000, 0x0000, 0x0000 }, /* R20759 */ + { 0x0000, 0x0000, 0x0000 }, /* R20760 */ + { 0x0000, 0x0000, 0x0000 }, /* R20761 */ + { 0x0000, 0x0000, 0x0000 }, /* R20762 */ + { 0x0000, 0x0000, 0x0000 }, /* R20763 */ + { 0x0000, 0x0000, 0x0000 }, /* R20764 */ + { 0x0000, 0x0000, 0x0000 }, /* R20765 */ + { 0x0000, 0x0000, 0x0000 }, /* R20766 */ + { 0x0000, 0x0000, 0x0000 }, /* R20767 */ + { 0x0000, 0x0000, 0x0000 }, /* R20768 */ + { 0x0000, 0x0000, 0x0000 }, /* R20769 */ + { 0x0000, 0x0000, 0x0000 }, /* R20770 */ + { 0x0000, 0x0000, 0x0000 }, /* R20771 */ + { 0x0000, 0x0000, 0x0000 }, /* R20772 */ + { 0x0000, 0x0000, 0x0000 }, /* R20773 */ + { 0x0000, 0x0000, 0x0000 }, /* R20774 */ + { 0x0000, 0x0000, 0x0000 }, /* R20775 */ + { 0x0000, 0x0000, 0x0000 }, /* R20776 */ + { 0x0000, 0x0000, 0x0000 }, /* R20777 */ + { 0x0000, 0x0000, 0x0000 }, /* R20778 */ + { 0x0000, 0x0000, 0x0000 }, /* R20779 */ + { 0x0000, 0x0000, 0x0000 }, /* R20780 */ + { 0x0000, 0x0000, 0x0000 }, /* R20781 */ + { 0x0000, 0x0000, 0x0000 }, /* R20782 */ + { 0x0000, 0x0000, 0x0000 }, /* R20783 */ + { 0x0000, 0x0000, 0x0000 }, /* R20784 */ + { 0x0000, 0x0000, 0x0000 }, /* R20785 */ + { 0x0000, 0x0000, 0x0000 }, /* R20786 */ + { 0x0000, 0x0000, 0x0000 }, /* R20787 */ + { 0x0000, 0x0000, 0x0000 }, /* R20788 */ + { 0x0000, 0x0000, 0x0000 }, /* R20789 */ + { 0x0000, 0x0000, 0x0000 }, /* R20790 */ + { 0x0000, 0x0000, 0x0000 }, /* R20791 */ + { 0x0000, 0x0000, 0x0000 }, /* R20792 */ + { 0x0000, 0x0000, 0x0000 }, /* R20793 */ + { 0x0000, 0x0000, 0x0000 }, /* R20794 */ + { 0x0000, 0x0000, 0x0000 }, /* R20795 */ + { 0x0000, 0x0000, 0x0000 }, /* R20796 */ + { 0x0000, 0x0000, 0x0000 }, /* R20797 */ + { 0x0000, 0x0000, 0x0000 }, /* R20798 */ + { 0x0000, 0x0000, 0x0000 }, /* R20799 */ + { 0x0000, 0x0000, 0x0000 }, /* R20800 */ + { 0x0000, 0x0000, 0x0000 }, /* R20801 */ + { 0x0000, 0x0000, 0x0000 }, /* R20802 */ + { 0x0000, 0x0000, 0x0000 }, /* R20803 */ + { 0x0000, 0x0000, 0x0000 }, /* R20804 */ + { 0x0000, 0x0000, 0x0000 }, /* R20805 */ + { 0x0000, 0x0000, 0x0000 }, /* R20806 */ + { 0x0000, 0x0000, 0x0000 }, /* R20807 */ + { 0x0000, 0x0000, 0x0000 }, /* R20808 */ + { 0x0000, 0x0000, 0x0000 }, /* R20809 */ + { 0x0000, 0x0000, 0x0000 }, /* R20810 */ + { 0x0000, 0x0000, 0x0000 }, /* R20811 */ + { 0x0000, 0x0000, 0x0000 }, /* R20812 */ + { 0x0000, 0x0000, 0x0000 }, /* R20813 */ + { 0x0000, 0x0000, 0x0000 }, /* R20814 */ + { 0x0000, 0x0000, 0x0000 }, /* R20815 */ + { 0x0000, 0x0000, 0x0000 }, /* R20816 */ + { 0x0000, 0x0000, 0x0000 }, /* R20817 */ + { 0x0000, 0x0000, 0x0000 }, /* R20818 */ + { 0x0000, 0x0000, 0x0000 }, /* R20819 */ + { 0x0000, 0x0000, 0x0000 }, /* R20820 */ + { 0x0000, 0x0000, 0x0000 }, /* R20821 */ + { 0x0000, 0x0000, 0x0000 }, /* R20822 */ + { 0x0000, 0x0000, 0x0000 }, /* R20823 */ + { 0x0000, 0x0000, 0x0000 }, /* R20824 */ + { 0x0000, 0x0000, 0x0000 }, /* R20825 */ + { 0x0000, 0x0000, 0x0000 }, /* R20826 */ + { 0x0000, 0x0000, 0x0000 }, /* R20827 */ + { 0x0000, 0x0000, 0x0000 }, /* R20828 */ + { 0x0000, 0x0000, 0x0000 }, /* R20829 */ + { 0x0000, 0x0000, 0x0000 }, /* R20830 */ + { 0x0000, 0x0000, 0x0000 }, /* R20831 */ + { 0x0000, 0x0000, 0x0000 }, /* R20832 */ + { 0x0000, 0x0000, 0x0000 }, /* R20833 */ + { 0x0000, 0x0000, 0x0000 }, /* R20834 */ + { 0x0000, 0x0000, 0x0000 }, /* R20835 */ + { 0x0000, 0x0000, 0x0000 }, /* R20836 */ + { 0x0000, 0x0000, 0x0000 }, /* R20837 */ + { 0x0000, 0x0000, 0x0000 }, /* R20838 */ + { 0x0000, 0x0000, 0x0000 }, /* R20839 */ + { 0x0000, 0x0000, 0x0000 }, /* R20840 */ + { 0x0000, 0x0000, 0x0000 }, /* R20841 */ + { 0x0000, 0x0000, 0x0000 }, /* R20842 */ + { 0x0000, 0x0000, 0x0000 }, /* R20843 */ + { 0x0000, 0x0000, 0x0000 }, /* R20844 */ + { 0x0000, 0x0000, 0x0000 }, /* R20845 */ + { 0x0000, 0x0000, 0x0000 }, /* R20846 */ + { 0x0000, 0x0000, 0x0000 }, /* R20847 */ + { 0x0000, 0x0000, 0x0000 }, /* R20848 */ + { 0x0000, 0x0000, 0x0000 }, /* R20849 */ + { 0x0000, 0x0000, 0x0000 }, /* R20850 */ + { 0x0000, 0x0000, 0x0000 }, /* R20851 */ + { 0x0000, 0x0000, 0x0000 }, /* R20852 */ + { 0x0000, 0x0000, 0x0000 }, /* R20853 */ + { 0x0000, 0x0000, 0x0000 }, /* R20854 */ + { 0x0000, 0x0000, 0x0000 }, /* R20855 */ + { 0x0000, 0x0000, 0x0000 }, /* R20856 */ + { 0x0000, 0x0000, 0x0000 }, /* R20857 */ + { 0x0000, 0x0000, 0x0000 }, /* R20858 */ + { 0x0000, 0x0000, 0x0000 }, /* R20859 */ + { 0x0000, 0x0000, 0x0000 }, /* R20860 */ + { 0x0000, 0x0000, 0x0000 }, /* R20861 */ + { 0x0000, 0x0000, 0x0000 }, /* R20862 */ + { 0x0000, 0x0000, 0x0000 }, /* R20863 */ + { 0x0000, 0x0000, 0x0000 }, /* R20864 */ + { 0x0000, 0x0000, 0x0000 }, /* R20865 */ + { 0x0000, 0x0000, 0x0000 }, /* R20866 */ + { 0x0000, 0x0000, 0x0000 }, /* R20867 */ + { 0x0000, 0x0000, 0x0000 }, /* R20868 */ + { 0x0000, 0x0000, 0x0000 }, /* R20869 */ + { 0x0000, 0x0000, 0x0000 }, /* R20870 */ + { 0x0000, 0x0000, 0x0000 }, /* R20871 */ + { 0x0000, 0x0000, 0x0000 }, /* R20872 */ + { 0x0000, 0x0000, 0x0000 }, /* R20873 */ + { 0x0000, 0x0000, 0x0000 }, /* R20874 */ + { 0x0000, 0x0000, 0x0000 }, /* R20875 */ + { 0x0000, 0x0000, 0x0000 }, /* R20876 */ + { 0x0000, 0x0000, 0x0000 }, /* R20877 */ + { 0x0000, 0x0000, 0x0000 }, /* R20878 */ + { 0x0000, 0x0000, 0x0000 }, /* R20879 */ + { 0x0000, 0x0000, 0x0000 }, /* R20880 */ + { 0x0000, 0x0000, 0x0000 }, /* R20881 */ + { 0x0000, 0x0000, 0x0000 }, /* R20882 */ + { 0x0000, 0x0000, 0x0000 }, /* R20883 */ + { 0x0000, 0x0000, 0x0000 }, /* R20884 */ + { 0x0000, 0x0000, 0x0000 }, /* R20885 */ + { 0x0000, 0x0000, 0x0000 }, /* R20886 */ + { 0x0000, 0x0000, 0x0000 }, /* R20887 */ + { 0x0000, 0x0000, 0x0000 }, /* R20888 */ + { 0x0000, 0x0000, 0x0000 }, /* R20889 */ + { 0x0000, 0x0000, 0x0000 }, /* R20890 */ + { 0x0000, 0x0000, 0x0000 }, /* R20891 */ + { 0x0000, 0x0000, 0x0000 }, /* R20892 */ + { 0x0000, 0x0000, 0x0000 }, /* R20893 */ + { 0x0000, 0x0000, 0x0000 }, /* R20894 */ + { 0x0000, 0x0000, 0x0000 }, /* R20895 */ + { 0x0000, 0x0000, 0x0000 }, /* R20896 */ + { 0x0000, 0x0000, 0x0000 }, /* R20897 */ + { 0x0000, 0x0000, 0x0000 }, /* R20898 */ + { 0x0000, 0x0000, 0x0000 }, /* R20899 */ + { 0x0000, 0x0000, 0x0000 }, /* R20900 */ + { 0x0000, 0x0000, 0x0000 }, /* R20901 */ + { 0x0000, 0x0000, 0x0000 }, /* R20902 */ + { 0x0000, 0x0000, 0x0000 }, /* R20903 */ + { 0x0000, 0x0000, 0x0000 }, /* R20904 */ + { 0x0000, 0x0000, 0x0000 }, /* R20905 */ + { 0x0000, 0x0000, 0x0000 }, /* R20906 */ + { 0x0000, 0x0000, 0x0000 }, /* R20907 */ + { 0x0000, 0x0000, 0x0000 }, /* R20908 */ + { 0x0000, 0x0000, 0x0000 }, /* R20909 */ + { 0x0000, 0x0000, 0x0000 }, /* R20910 */ + { 0x0000, 0x0000, 0x0000 }, /* R20911 */ + { 0x0000, 0x0000, 0x0000 }, /* R20912 */ + { 0x0000, 0x0000, 0x0000 }, /* R20913 */ + { 0x0000, 0x0000, 0x0000 }, /* R20914 */ + { 0x0000, 0x0000, 0x0000 }, /* R20915 */ + { 0x0000, 0x0000, 0x0000 }, /* R20916 */ + { 0x0000, 0x0000, 0x0000 }, /* R20917 */ + { 0x0000, 0x0000, 0x0000 }, /* R20918 */ + { 0x0000, 0x0000, 0x0000 }, /* R20919 */ + { 0x0000, 0x0000, 0x0000 }, /* R20920 */ + { 0x0000, 0x0000, 0x0000 }, /* R20921 */ + { 0x0000, 0x0000, 0x0000 }, /* R20922 */ + { 0x0000, 0x0000, 0x0000 }, /* R20923 */ + { 0x0000, 0x0000, 0x0000 }, /* R20924 */ + { 0x0000, 0x0000, 0x0000 }, /* R20925 */ + { 0x0000, 0x0000, 0x0000 }, /* R20926 */ + { 0x0000, 0x0000, 0x0000 }, /* R20927 */ + { 0x0000, 0x0000, 0x0000 }, /* R20928 */ + { 0x0000, 0x0000, 0x0000 }, /* R20929 */ + { 0x0000, 0x0000, 0x0000 }, /* R20930 */ + { 0x0000, 0x0000, 0x0000 }, /* R20931 */ + { 0x0000, 0x0000, 0x0000 }, /* R20932 */ + { 0x0000, 0x0000, 0x0000 }, /* R20933 */ + { 0x0000, 0x0000, 0x0000 }, /* R20934 */ + { 0x0000, 0x0000, 0x0000 }, /* R20935 */ + { 0x0000, 0x0000, 0x0000 }, /* R20936 */ + { 0x0000, 0x0000, 0x0000 }, /* R20937 */ + { 0x0000, 0x0000, 0x0000 }, /* R20938 */ + { 0x0000, 0x0000, 0x0000 }, /* R20939 */ + { 0x0000, 0x0000, 0x0000 }, /* R20940 */ + { 0x0000, 0x0000, 0x0000 }, /* R20941 */ + { 0x0000, 0x0000, 0x0000 }, /* R20942 */ + { 0x0000, 0x0000, 0x0000 }, /* R20943 */ + { 0x0000, 0x0000, 0x0000 }, /* R20944 */ + { 0x0000, 0x0000, 0x0000 }, /* R20945 */ + { 0x0000, 0x0000, 0x0000 }, /* R20946 */ + { 0x0000, 0x0000, 0x0000 }, /* R20947 */ + { 0x0000, 0x0000, 0x0000 }, /* R20948 */ + { 0x0000, 0x0000, 0x0000 }, /* R20949 */ + { 0x0000, 0x0000, 0x0000 }, /* R20950 */ + { 0x0000, 0x0000, 0x0000 }, /* R20951 */ + { 0x0000, 0x0000, 0x0000 }, /* R20952 */ + { 0x0000, 0x0000, 0x0000 }, /* R20953 */ + { 0x0000, 0x0000, 0x0000 }, /* R20954 */ + { 0x0000, 0x0000, 0x0000 }, /* R20955 */ + { 0x0000, 0x0000, 0x0000 }, /* R20956 */ + { 0x0000, 0x0000, 0x0000 }, /* R20957 */ + { 0x0000, 0x0000, 0x0000 }, /* R20958 */ + { 0x0000, 0x0000, 0x0000 }, /* R20959 */ + { 0x0000, 0x0000, 0x0000 }, /* R20960 */ + { 0x0000, 0x0000, 0x0000 }, /* R20961 */ + { 0x0000, 0x0000, 0x0000 }, /* R20962 */ + { 0x0000, 0x0000, 0x0000 }, /* R20963 */ + { 0x0000, 0x0000, 0x0000 }, /* R20964 */ + { 0x0000, 0x0000, 0x0000 }, /* R20965 */ + { 0x0000, 0x0000, 0x0000 }, /* R20966 */ + { 0x0000, 0x0000, 0x0000 }, /* R20967 */ + { 0x0000, 0x0000, 0x0000 }, /* R20968 */ + { 0x0000, 0x0000, 0x0000 }, /* R20969 */ + { 0x0000, 0x0000, 0x0000 }, /* R20970 */ + { 0x0000, 0x0000, 0x0000 }, /* R20971 */ + { 0x0000, 0x0000, 0x0000 }, /* R20972 */ + { 0x0000, 0x0000, 0x0000 }, /* R20973 */ + { 0x0000, 0x0000, 0x0000 }, /* R20974 */ + { 0x0000, 0x0000, 0x0000 }, /* R20975 */ + { 0x0000, 0x0000, 0x0000 }, /* R20976 */ + { 0x0000, 0x0000, 0x0000 }, /* R20977 */ + { 0x0000, 0x0000, 0x0000 }, /* R20978 */ + { 0x0000, 0x0000, 0x0000 }, /* R20979 */ + { 0x0000, 0x0000, 0x0000 }, /* R20980 */ + { 0x0000, 0x0000, 0x0000 }, /* R20981 */ + { 0x0000, 0x0000, 0x0000 }, /* R20982 */ + { 0x0000, 0x0000, 0x0000 }, /* R20983 */ + { 0x0000, 0x0000, 0x0000 }, /* R20984 */ + { 0x0000, 0x0000, 0x0000 }, /* R20985 */ + { 0x0000, 0x0000, 0x0000 }, /* R20986 */ + { 0x0000, 0x0000, 0x0000 }, /* R20987 */ + { 0x0000, 0x0000, 0x0000 }, /* R20988 */ + { 0x0000, 0x0000, 0x0000 }, /* R20989 */ + { 0x0000, 0x0000, 0x0000 }, /* R20990 */ + { 0x0000, 0x0000, 0x0000 }, /* R20991 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20992 - VSS_XHD2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20993 - VSS_XHD2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20994 - VSS_XHD3_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20995 - VSS_XHD3_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20996 - VSS_XHN1_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20997 - VSS_XHN1_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R20998 - VSS_XHN2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R20999 - VSS_XHN2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21000 - VSS_XHN3_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21001 - VSS_XHN3_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21002 - VSS_XLA_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21003 - VSS_XLA_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21004 - VSS_XLB_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21005 - VSS_XLB_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21006 - VSS_XLG_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21007 - VSS_XLG_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21008 - VSS_PG2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21009 - VSS_PG2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21010 - VSS_PG_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21011 - VSS_PG_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21012 - VSS_XTD1_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21013 - VSS_XTD1_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21014 - VSS_XTD2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21015 - VSS_XTD2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21016 - VSS_XTD3_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21017 - VSS_XTD3_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21018 - VSS_XTD4_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21019 - VSS_XTD4_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21020 - VSS_XTD5_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21021 - VSS_XTD5_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21022 - VSS_XTD6_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21023 - VSS_XTD6_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21024 - VSS_XTD7_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21025 - VSS_XTD7_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21026 - VSS_XTD8_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21027 - VSS_XTD8_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21028 - VSS_XTD9_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21029 - VSS_XTD9_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21030 - VSS_XTD10_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21031 - VSS_XTD10_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21032 - VSS_XTD11_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21033 - VSS_XTD11_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21034 - VSS_XTD12_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21035 - VSS_XTD12_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21036 - VSS_XTD13_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21037 - VSS_XTD13_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21038 - VSS_XTD14_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21039 - VSS_XTD14_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21040 - VSS_XTD15_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21041 - VSS_XTD15_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21042 - VSS_XTD16_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21043 - VSS_XTD16_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21044 - VSS_XTD17_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21045 - VSS_XTD17_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21046 - VSS_XTD18_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21047 - VSS_XTD18_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21048 - VSS_XTD19_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21049 - VSS_XTD19_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21050 - VSS_XTD20_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21051 - VSS_XTD20_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21052 - VSS_XTD21_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21053 - VSS_XTD21_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21054 - VSS_XTD22_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21055 - VSS_XTD22_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21056 - VSS_XTD23_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21057 - VSS_XTD23_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21058 - VSS_XTD24_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21059 - VSS_XTD24_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21060 - VSS_XTD25_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21061 - VSS_XTD25_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21062 - VSS_XTD26_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21063 - VSS_XTD26_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21064 - VSS_XTD27_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21065 - VSS_XTD27_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21066 - VSS_XTD28_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21067 - VSS_XTD28_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21068 - VSS_XTD29_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21069 - VSS_XTD29_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21070 - VSS_XTD30_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21071 - VSS_XTD30_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21072 - VSS_XTD31_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21073 - VSS_XTD31_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21074 - VSS_XTD32_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21075 - VSS_XTD32_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21076 - VSS_XTS1_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21077 - VSS_XTS1_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21078 - VSS_XTS2_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21079 - VSS_XTS2_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21080 - VSS_XTS3_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21081 - VSS_XTS3_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21082 - VSS_XTS4_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21083 - VSS_XTS4_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21084 - VSS_XTS5_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21085 - VSS_XTS5_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21086 - VSS_XTS6_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21087 - VSS_XTS6_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21088 - VSS_XTS7_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21089 - VSS_XTS7_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21090 - VSS_XTS8_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21091 - VSS_XTS8_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21092 - VSS_XTS9_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21093 - VSS_XTS9_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21094 - VSS_XTS10_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21095 - VSS_XTS10_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21096 - VSS_XTS11_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21097 - VSS_XTS11_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21098 - VSS_XTS12_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21099 - VSS_XTS12_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21100 - VSS_XTS13_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21101 - VSS_XTS13_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21102 - VSS_XTS14_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21103 - VSS_XTS14_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21104 - VSS_XTS15_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21105 - VSS_XTS15_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21106 - VSS_XTS16_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21107 - VSS_XTS16_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21108 - VSS_XTS17_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21109 - VSS_XTS17_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21110 - VSS_XTS18_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21111 - VSS_XTS18_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21112 - VSS_XTS19_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21113 - VSS_XTS19_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21114 - VSS_XTS20_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21115 - VSS_XTS20_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21116 - VSS_XTS21_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21117 - VSS_XTS21_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21118 - VSS_XTS22_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21119 - VSS_XTS22_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21120 - VSS_XTS23_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21121 - VSS_XTS23_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21122 - VSS_XTS24_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21123 - VSS_XTS24_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21124 - VSS_XTS25_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21125 - VSS_XTS25_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21126 - VSS_XTS26_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21127 - VSS_XTS26_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21128 - VSS_XTS27_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21129 - VSS_XTS27_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21130 - VSS_XTS28_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21131 - VSS_XTS28_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21132 - VSS_XTS29_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21133 - VSS_XTS29_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21134 - VSS_XTS30_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21135 - VSS_XTS30_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21136 - VSS_XTS31_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21137 - VSS_XTS31_0 */ + { 0x00FF, 0x00FF, 0x0000 }, /* R21138 - VSS_XTS32_1 */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */ +}; diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c new file mode 100644 index 000000000000..ea8940e80263 --- /dev/null +++ b/sound/soc/codecs/wm8962.c @@ -0,0 +1,1933 @@ +/* + * wm8962.c -- WM8962 ALSA SoC Audio driver + * + * Copyright 2010 Wolfson Microelectronics plc + * + * Author: Mark Brown + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wm8962.h" + +static struct snd_soc_codec *wm8962_codec; +struct snd_soc_codec_device soc_codec_dev_wm8962; + +#define WM8962_NUM_SUPPLIES 8 +static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = { + "DCVDD", + "DBVDD", + "AVDD", + "CPVDD", + "MICVDD", + "PLLVDD", + "SPKVDD1", + "SPKVDD2", +}; + +/* codec private data */ +struct wm8962_priv { + struct snd_soc_codec codec; + u16 reg_cache[WM8962_MAX_REGISTER + 1]; + + int sysclk; + int sysclk_rate; + + int bclk; /* Desired BCLK */ + int lrclk; + + int fll_src; + int fll_fref; + int fll_fout; + + struct regulator_bulk_data supplies[WM8962_NUM_SUPPLIES]; + struct notifier_block disable_nb[WM8962_NUM_SUPPLIES]; + +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + struct input_dev *beep; + struct work_struct beep_work; + int beep_rate; +#endif +}; + +/* We can't use the same notifier block for more than one supply and + * there's no way I can see to get from a callback to the caller + * except container_of(). + */ +#define WM8962_REGULATOR_EVENT(n) \ +static int wm8962_regulator_event_##n(struct notifier_block *nb, \ + unsigned long event, void *data) \ +{ \ + struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \ + disable_nb[n]); \ + if (event & REGULATOR_EVENT_DISABLE) { \ + wm8962->codec.cache_sync = 1; \ + } \ + return 0; \ +} + +WM8962_REGULATOR_EVENT(0) +WM8962_REGULATOR_EVENT(1) +WM8962_REGULATOR_EVENT(2) +WM8962_REGULATOR_EVENT(3) +WM8962_REGULATOR_EVENT(4) +WM8962_REGULATOR_EVENT(5) +WM8962_REGULATOR_EVENT(6) +WM8962_REGULATOR_EVENT(7) + +static int wm8962_volatile_register(unsigned int reg) +{ + if (wm8962_reg_access[reg].vol) + return 1; + else + return 0; +} + +static int wm8962_readable(unsigned int reg) +{ + if (wm8962_reg_access[reg].read) + return 1; + else + return 0; +} + +static int wm8962_reset(struct snd_soc_codec *codec) +{ + return snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0); +} + +static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0); +static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0); +static const unsigned int mixinpga_tlv[] = { + TLV_DB_RANGE_HEAD(7), + 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0), + 2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0), + 3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0), + 5, 5, TLV_DB_SCALE_ITEM(2400, 0, 0), + 6, 7, TLV_DB_SCALE_ITEM(2700, 300, 0), +}; +static const DECLARE_TLV_DB_SCALE(beep_tlv, -9600, 600, 1); +static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); +static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); +static const DECLARE_TLV_DB_SCALE(inmix_tlv, -600, 600, 0); +static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); +static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); +static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0); +static const unsigned int classd_tlv[] = { + TLV_DB_RANGE_HEAD(7), + 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), + 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), +}; + +/* The VU bits for the headphones are in a different register to the mute + * bits and only take effect on the PGA if it is actually powered. + */ +static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + u16 *reg_cache = codec->reg_cache; + int ret; + + /* Apply the update (if any) */ + ret = snd_soc_put_volsw(kcontrol, ucontrol); + if (ret == 0) + return 0; + + /* If the left PGA is enabled hit that VU bit... */ + if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTL_PGA_ENA) + return snd_soc_write(codec, WM8962_HPOUTL_VOLUME, + reg_cache[WM8962_HPOUTL_VOLUME]); + + /* ...otherwise the right. The VU is stereo. */ + if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTR_PGA_ENA) + return snd_soc_write(codec, WM8962_HPOUTR_VOLUME, + reg_cache[WM8962_HPOUTR_VOLUME]); + + return 0; +} + +/* The VU bits for the speakers are in a different register to the mute + * bits and only take effect on the PGA if it is actually powered. + */ +static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + u16 *reg_cache = codec->reg_cache; + int ret; + + /* Apply the update (if any) */ + ret = snd_soc_put_volsw(kcontrol, ucontrol); + if (ret == 0) + return 0; + + /* If the left PGA is enabled hit that VU bit... */ + if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA) + return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME, + reg_cache[WM8962_SPKOUTL_VOLUME]); + + /* ...otherwise the right. The VU is stereo. */ + if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA) + return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME, + reg_cache[WM8962_SPKOUTR_VOLUME]); + + return 0; +} + +static const struct snd_kcontrol_new wm8962_snd_controls[] = { +SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), + +SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 6, 7, 0, + mixin_tlv), +SOC_SINGLE_TLV("MIXINL PGA Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 3, 7, 0, + mixinpga_tlv), +SOC_SINGLE_TLV("MIXINL IN3L Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 0, 7, 0, + mixin_tlv), + +SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 6, 7, 0, + mixin_tlv), +SOC_SINGLE_TLV("MIXINR PGA Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 3, 7, 0, + mixinpga_tlv), +SOC_SINGLE_TLV("MIXINR IN3R Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 0, 7, 0, + mixin_tlv), + +SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8962_LEFT_ADC_VOLUME, + WM8962_RIGHT_ADC_VOLUME, 1, 127, 0, digital_tlv), +SOC_DOUBLE_R_TLV("Capture Volume", WM8962_LEFT_INPUT_VOLUME, + WM8962_RIGHT_INPUT_VOLUME, 0, 63, 0, inpga_tlv), +SOC_DOUBLE_R("Capture Switch", WM8962_LEFT_INPUT_VOLUME, + WM8962_RIGHT_INPUT_VOLUME, 7, 1, 1), +SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME, + WM8962_RIGHT_INPUT_VOLUME, 6, 1, 1), + +SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1, + WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv), + +SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8962_LEFT_DAC_VOLUME, + WM8962_RIGHT_DAC_VOLUME, 1, 127, 0, digital_tlv), +SOC_SINGLE("DAC High Performance Switch", WM8962_ADC_DAC_CONTROL_2, 0, 1, 0), + +SOC_SINGLE("ADC High Performance Switch", WM8962_ADDITIONAL_CONTROL_1, + 5, 1, 0), + +SOC_SINGLE_TLV("Beep Volume", WM8962_BEEP_GENERATOR_1, 4, 15, 0, beep_tlv), + +SOC_DOUBLE_R_TLV("Headphone Volume", WM8962_HPOUTL_VOLUME, + WM8962_HPOUTR_VOLUME, 0, 127, 0, out_tlv), +SOC_DOUBLE_EXT("Headphone Switch", WM8962_PWR_MGMT_2, 1, 0, 1, 1, + snd_soc_get_volsw, wm8962_put_hp_sw), +SOC_DOUBLE_R("Headphone ZC Switch", WM8962_HPOUTL_VOLUME, WM8962_HPOUTR_VOLUME, + 7, 1, 0), +SOC_DOUBLE_TLV("Headphone Aux Volume", WM8962_ANALOGUE_HP_2, 3, 6, 7, 0, + hp_tlv), + +SOC_DOUBLE_R("Headphone Mixer Switch", WM8962_HEADPHONE_MIXER_3, + WM8962_HEADPHONE_MIXER_4, 8, 1, 1), + +SOC_SINGLE_TLV("HPMIXL IN4L Volume", WM8962_HEADPHONE_MIXER_3, + 3, 7, 0, bypass_tlv), +SOC_SINGLE_TLV("HPMIXL IN4R Volume", WM8962_HEADPHONE_MIXER_3, + 0, 7, 0, bypass_tlv), +SOC_SINGLE_TLV("HPMIXL MIXINL Volume", WM8962_HEADPHONE_MIXER_3, + 7, 1, 1, inmix_tlv), +SOC_SINGLE_TLV("HPMIXL MIXINR Volume", WM8962_HEADPHONE_MIXER_3, + 6, 1, 1, inmix_tlv), + +SOC_SINGLE_TLV("HPMIXR IN4L Volume", WM8962_HEADPHONE_MIXER_4, + 3, 7, 0, bypass_tlv), +SOC_SINGLE_TLV("HPMIXR IN4R Volume", WM8962_HEADPHONE_MIXER_4, + 0, 7, 0, bypass_tlv), +SOC_SINGLE_TLV("HPMIXR MIXINL Volume", WM8962_HEADPHONE_MIXER_4, + 7, 1, 1, inmix_tlv), +SOC_SINGLE_TLV("HPMIXR MIXINR Volume", WM8962_HEADPHONE_MIXER_4, + 6, 1, 1, inmix_tlv), + +SOC_SINGLE_TLV("Speaker Boost Volume", WM8962_CLASS_D_CONTROL_2, 0, 7, 0, + classd_tlv), +}; + +static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { +SOC_SINGLE_TLV("Speaker Volume", WM8962_SPKOUTL_VOLUME, 0, 127, 0, out_tlv), +SOC_SINGLE_EXT("Speaker Switch", WM8962_CLASS_D_CONTROL_1, 1, 1, 1, + snd_soc_get_volsw, wm8962_put_spk_sw), +SOC_SINGLE("Speaker ZC Switch", WM8962_SPKOUTL_VOLUME, 7, 1, 0), + +SOC_SINGLE("Speaker Mixer Switch", WM8962_SPEAKER_MIXER_3, 8, 1, 1), +SOC_SINGLE_TLV("Speaker Mixer IN4L Volume", WM8962_SPEAKER_MIXER_3, + 3, 7, 0, bypass_tlv), +SOC_SINGLE_TLV("Speaker Mixer IN4R Volume", WM8962_SPEAKER_MIXER_3, + 0, 7, 0, bypass_tlv), +SOC_SINGLE_TLV("Speaker Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_3, + 7, 1, 1, inmix_tlv), +SOC_SINGLE_TLV("Speaker Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_3, + 6, 1, 1, inmix_tlv), +SOC_SINGLE_TLV("Speaker Mixer DACL Volume", WM8962_SPEAKER_MIXER_5, + 7, 1, 0, inmix_tlv), +SOC_SINGLE_TLV("Speaker Mixer DACR Volume", WM8962_SPEAKER_MIXER_5, + 6, 1, 0, inmix_tlv), +}; + +static const struct snd_kcontrol_new wm8962_spk_stereo_controls[] = { +SOC_DOUBLE_R_TLV("Speaker Volume", WM8962_SPKOUTL_VOLUME, + WM8962_SPKOUTR_VOLUME, 0, 127, 0, out_tlv), +SOC_DOUBLE_EXT("Speaker Switch", WM8962_CLASS_D_CONTROL_1, 1, 0, 1, 1, + snd_soc_get_volsw, wm8962_put_spk_sw), +SOC_DOUBLE_R("Speaker ZC Switch", WM8962_SPKOUTL_VOLUME, WM8962_SPKOUTR_VOLUME, + 7, 1, 0), + +SOC_DOUBLE_R("Speaker Mixer Switch", WM8962_SPEAKER_MIXER_3, + WM8962_SPEAKER_MIXER_4, 8, 1, 1), + +SOC_SINGLE_TLV("SPKOUTL Mixer IN4L Volume", WM8962_SPEAKER_MIXER_3, + 3, 7, 0, bypass_tlv), +SOC_SINGLE_TLV("SPKOUTL Mixer IN4R Volume", WM8962_SPEAKER_MIXER_3, + 0, 7, 0, bypass_tlv), +SOC_SINGLE_TLV("SPKOUTL Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_3, + 7, 1, 1, inmix_tlv), +SOC_SINGLE_TLV("SPKOUTL Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_3, + 6, 1, 1, inmix_tlv), +SOC_SINGLE_TLV("SPKOUTL Mixer DACL Volume", WM8962_SPEAKER_MIXER_5, + 7, 1, 0, inmix_tlv), +SOC_SINGLE_TLV("SPKOUTL Mixer DACR Volume", WM8962_SPEAKER_MIXER_5, + 6, 1, 0, inmix_tlv), + +SOC_SINGLE_TLV("SPKOUTR Mixer IN4L Volume", WM8962_SPEAKER_MIXER_4, + 3, 7, 0, bypass_tlv), +SOC_SINGLE_TLV("SPKOUTR Mixer IN4R Volume", WM8962_SPEAKER_MIXER_4, + 0, 7, 0, bypass_tlv), +SOC_SINGLE_TLV("SPKOUTR Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_4, + 7, 1, 1, inmix_tlv), +SOC_SINGLE_TLV("SPKOUTR Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_4, + 6, 1, 1, inmix_tlv), +SOC_SINGLE_TLV("SPKOUTR Mixer DACL Volume", WM8962_SPEAKER_MIXER_5, + 5, 1, 0, inmix_tlv), +SOC_SINGLE_TLV("SPKOUTR Mixer DACR Volume", WM8962_SPEAKER_MIXER_5, + 4, 1, 0, inmix_tlv), +}; + +static int sysclk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + int src; + int fll; + + src = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_SRC_MASK; + + switch (src) { + case 0: /* MCLK */ + fll = 0; + break; + case 0x200: /* FLL */ + fll = 1; + break; + default: + dev_err(codec->dev, "Unknown SYSCLK source %x\n", src); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (fll) + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, + WM8962_FLL_ENA, WM8962_FLL_ENA); + break; + + case SND_SOC_DAPM_POST_PMD: + if (fll) + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, + WM8962_FLL_ENA, 0); + break; + + default: + BUG(); + return -EINVAL; + } + + return 0; +} + +static int cp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + switch (event) { + case SND_SOC_DAPM_POST_PMU: + msleep(5); + break; + + default: + BUG(); + return -EINVAL; + } + + return 0; +} + +static int hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + int timeout; + int reg; + int expected = (WM8962_DCS_STARTUP_DONE_HP1L | + WM8962_DCS_STARTUP_DONE_HP1R); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, + WM8962_HP1L_ENA | WM8962_HP1R_ENA, + WM8962_HP1L_ENA | WM8962_HP1R_ENA); + udelay(20); + + snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, + WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY, + WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY); + + /* Start the DC servo */ + snd_soc_update_bits(codec, WM8962_DC_SERVO_1, + WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA | + WM8962_HP1L_DCS_STARTUP | + WM8962_HP1R_DCS_STARTUP, + WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA | + WM8962_HP1L_DCS_STARTUP | + WM8962_HP1R_DCS_STARTUP); + + /* Wait for it to complete, should be well under 100ms */ + timeout = 0; + do { + msleep(1); + reg = snd_soc_read(codec, WM8962_DC_SERVO_6); + if (reg < 0) { + dev_err(codec->dev, + "Failed to read DCS status: %d\n", + reg); + continue; + } + dev_dbg(codec->dev, "DCS status: %x\n", reg); + } while (++timeout < 200 && (reg & expected) != expected); + + if ((reg & expected) != expected) + dev_err(codec->dev, "DC servo timed out\n"); + else + dev_dbg(codec->dev, "DC servo complete after %dms\n", + timeout); + + snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, + WM8962_HP1L_ENA_OUTP | + WM8962_HP1R_ENA_OUTP, + WM8962_HP1L_ENA_OUTP | + WM8962_HP1R_ENA_OUTP); + udelay(20); + + snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, + WM8962_HP1L_RMV_SHORT | + WM8962_HP1R_RMV_SHORT, + WM8962_HP1L_RMV_SHORT | + WM8962_HP1R_RMV_SHORT); + break; + + case SND_SOC_DAPM_PRE_PMD: + snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, + WM8962_HP1L_RMV_SHORT | + WM8962_HP1R_RMV_SHORT, 0); + + udelay(20); + + snd_soc_update_bits(codec, WM8962_DC_SERVO_1, + WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA | + WM8962_HP1L_DCS_STARTUP | + WM8962_HP1R_DCS_STARTUP, + 0); + + snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, + WM8962_HP1L_ENA | WM8962_HP1R_ENA | + WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY | + WM8962_HP1L_ENA_OUTP | + WM8962_HP1R_ENA_OUTP, 0); + + break; + + default: + BUG(); + return -EINVAL; + + } + + return 0; +} + +/* VU bits for the output PGAs only take effect while the PGA is powered */ +static int out_pga_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + u16 *reg_cache = codec->reg_cache; + int reg; + + switch (w->shift) { + case WM8962_HPOUTR_PGA_ENA_SHIFT: + reg = WM8962_HPOUTR_VOLUME; + break; + case WM8962_HPOUTL_PGA_ENA_SHIFT: + reg = WM8962_HPOUTL_VOLUME; + break; + case WM8962_SPKOUTR_PGA_ENA_SHIFT: + reg = WM8962_SPKOUTR_VOLUME; + break; + case WM8962_SPKOUTL_PGA_ENA_SHIFT: + reg = WM8962_SPKOUTL_VOLUME; + break; + default: + BUG(); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + return snd_soc_write(codec, reg, reg_cache[reg]); + default: + BUG(); + return -EINVAL; + } +} + +static const char *st_text[] = { "None", "Right", "Left" }; + +static const struct soc_enum str_enum = + SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text); + +static const struct snd_kcontrol_new str_mux = + SOC_DAPM_ENUM("Right Sidetone", str_enum); + +static const struct soc_enum stl_enum = + SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_2, 2, 3, st_text); + +static const struct snd_kcontrol_new stl_mux = + SOC_DAPM_ENUM("Left Sidetone", stl_enum); + +static const char *outmux_text[] = { "DAC", "Mixer" }; + +static const struct soc_enum spkoutr_enum = + SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_2, 7, 2, outmux_text); + +static const struct snd_kcontrol_new spkoutr_mux = + SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum); + +static const struct soc_enum spkoutl_enum = + SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_1, 7, 2, outmux_text); + +static const struct snd_kcontrol_new spkoutl_mux = + SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum); + +static const struct soc_enum hpoutr_enum = + SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_2, 7, 2, outmux_text); + +static const struct snd_kcontrol_new hpoutr_mux = + SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum); + +static const struct soc_enum hpoutl_enum = + SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_1, 7, 2, outmux_text); + +static const struct snd_kcontrol_new hpoutl_mux = + SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum); + +static const struct snd_kcontrol_new inpgal[] = { +SOC_DAPM_SINGLE("IN1L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 3, 1, 0), +SOC_DAPM_SINGLE("IN2L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 2, 1, 0), +SOC_DAPM_SINGLE("IN3L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 1, 1, 0), +SOC_DAPM_SINGLE("IN4L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 0, 1, 0), +}; + +static const struct snd_kcontrol_new inpgar[] = { +SOC_DAPM_SINGLE("IN1R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 3, 1, 0), +SOC_DAPM_SINGLE("IN2R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 2, 1, 0), +SOC_DAPM_SINGLE("IN3R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 1, 1, 0), +SOC_DAPM_SINGLE("IN4R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 0, 1, 0), +}; + +static const struct snd_kcontrol_new mixinl[] = { +SOC_DAPM_SINGLE("IN2L Switch", WM8962_INPUT_MIXER_CONTROL_2, 5, 1, 0), +SOC_DAPM_SINGLE("IN3L Switch", WM8962_INPUT_MIXER_CONTROL_2, 4, 1, 0), +SOC_DAPM_SINGLE("PGA Switch", WM8962_INPUT_MIXER_CONTROL_2, 3, 1, 0), +}; + +static const struct snd_kcontrol_new mixinr[] = { +SOC_DAPM_SINGLE("IN2R Switch", WM8962_INPUT_MIXER_CONTROL_2, 2, 1, 0), +SOC_DAPM_SINGLE("IN3R Switch", WM8962_INPUT_MIXER_CONTROL_2, 1, 1, 0), +SOC_DAPM_SINGLE("PGA Switch", WM8962_INPUT_MIXER_CONTROL_2, 0, 1, 0), +}; + +static const struct snd_kcontrol_new hpmixl[] = { +SOC_DAPM_SINGLE("DACL Switch", WM8962_HEADPHONE_MIXER_1, 5, 1, 0), +SOC_DAPM_SINGLE("DACR Switch", WM8962_HEADPHONE_MIXER_1, 4, 1, 0), +SOC_DAPM_SINGLE("MIXINL Switch", WM8962_HEADPHONE_MIXER_1, 3, 1, 0), +SOC_DAPM_SINGLE("MIXINR Switch", WM8962_HEADPHONE_MIXER_1, 2, 1, 0), +SOC_DAPM_SINGLE("IN4L Switch", WM8962_HEADPHONE_MIXER_1, 1, 1, 0), +SOC_DAPM_SINGLE("IN4R Switch", WM8962_HEADPHONE_MIXER_1, 0, 1, 0), +}; + +static const struct snd_kcontrol_new hpmixr[] = { +SOC_DAPM_SINGLE("DACL Switch", WM8962_HEADPHONE_MIXER_2, 5, 1, 0), +SOC_DAPM_SINGLE("DACR Switch", WM8962_HEADPHONE_MIXER_2, 4, 1, 0), +SOC_DAPM_SINGLE("MIXINL Switch", WM8962_HEADPHONE_MIXER_2, 3, 1, 0), +SOC_DAPM_SINGLE("MIXINR Switch", WM8962_HEADPHONE_MIXER_2, 2, 1, 0), +SOC_DAPM_SINGLE("IN4L Switch", WM8962_HEADPHONE_MIXER_2, 1, 1, 0), +SOC_DAPM_SINGLE("IN4R Switch", WM8962_HEADPHONE_MIXER_2, 0, 1, 0), +}; + +static const struct snd_kcontrol_new spkmixl[] = { +SOC_DAPM_SINGLE("DACL Switch", WM8962_SPEAKER_MIXER_1, 5, 1, 0), +SOC_DAPM_SINGLE("DACR Switch", WM8962_SPEAKER_MIXER_1, 4, 1, 0), +SOC_DAPM_SINGLE("MIXINL Switch", WM8962_SPEAKER_MIXER_1, 3, 1, 0), +SOC_DAPM_SINGLE("MIXINR Switch", WM8962_SPEAKER_MIXER_1, 2, 1, 0), +SOC_DAPM_SINGLE("IN4L Switch", WM8962_SPEAKER_MIXER_1, 1, 1, 0), +SOC_DAPM_SINGLE("IN4R Switch", WM8962_SPEAKER_MIXER_1, 0, 1, 0), +}; + +static const struct snd_kcontrol_new spkmixr[] = { +SOC_DAPM_SINGLE("DACL Switch", WM8962_SPEAKER_MIXER_2, 5, 1, 0), +SOC_DAPM_SINGLE("DACR Switch", WM8962_SPEAKER_MIXER_2, 4, 1, 0), +SOC_DAPM_SINGLE("MIXINL Switch", WM8962_SPEAKER_MIXER_2, 3, 1, 0), +SOC_DAPM_SINGLE("MIXINR Switch", WM8962_SPEAKER_MIXER_2, 2, 1, 0), +SOC_DAPM_SINGLE("IN4L Switch", WM8962_SPEAKER_MIXER_2, 1, 1, 0), +SOC_DAPM_SINGLE("IN4R Switch", WM8962_SPEAKER_MIXER_2, 0, 1, 0), +}; + +static const struct snd_soc_dapm_widget wm8962_dapm_widgets[] = { +SND_SOC_DAPM_INPUT("IN1L"), +SND_SOC_DAPM_INPUT("IN1R"), +SND_SOC_DAPM_INPUT("IN2L"), +SND_SOC_DAPM_INPUT("IN2R"), +SND_SOC_DAPM_INPUT("IN3L"), +SND_SOC_DAPM_INPUT("IN3R"), +SND_SOC_DAPM_INPUT("IN4L"), +SND_SOC_DAPM_INPUT("IN4R"), +SND_SOC_DAPM_INPUT("Beep"), + +SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0), +SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event, + SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0), + +SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0, + inpgal, ARRAY_SIZE(inpgal)), +SND_SOC_DAPM_MIXER("INPGAR", WM8962_RIGHT_INPUT_PGA_CONTROL, 4, 0, + inpgar, ARRAY_SIZE(inpgar)), +SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0, + mixinl, ARRAY_SIZE(mixinl)), +SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0, + mixinr, ARRAY_SIZE(mixinr)), + +SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0), +SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0), + +SND_SOC_DAPM_MUX("STL", SND_SOC_NOPM, 0, 0, &stl_mux), +SND_SOC_DAPM_MUX("STR", SND_SOC_NOPM, 0, 0, &str_mux), + +SND_SOC_DAPM_DAC("DACL", "Playback", WM8962_PWR_MGMT_2, 8, 0), +SND_SOC_DAPM_DAC("DACR", "Playback", WM8962_PWR_MGMT_2, 7, 0), + +SND_SOC_DAPM_PGA("Left Bypass", SND_SOC_NOPM, 0, 0, NULL, 0), +SND_SOC_DAPM_PGA("Right Bypass", SND_SOC_NOPM, 0, 0, NULL, 0), + +SND_SOC_DAPM_MIXER("HPMIXL", WM8962_MIXER_ENABLES, 3, 0, + hpmixl, ARRAY_SIZE(hpmixl)), +SND_SOC_DAPM_MIXER("HPMIXR", WM8962_MIXER_ENABLES, 2, 0, + hpmixr, ARRAY_SIZE(hpmixr)), + +SND_SOC_DAPM_MUX_E("HPOUTL PGA", WM8962_PWR_MGMT_2, 6, 0, &hpoutl_mux, + out_pga_event, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_MUX_E("HPOUTR PGA", WM8962_PWR_MGMT_2, 5, 0, &hpoutr_mux, + out_pga_event, SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_PGA_E("HPOUT", SND_SOC_NOPM, 0, 0, NULL, 0, hp_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + +SND_SOC_DAPM_OUTPUT("HPOUTL"), +SND_SOC_DAPM_OUTPUT("HPOUTR"), +}; + +static const struct snd_soc_dapm_widget wm8962_dapm_spk_mono_widgets[] = { +SND_SOC_DAPM_MIXER("Speaker Mixer", WM8962_MIXER_ENABLES, 1, 0, + spkmixl, ARRAY_SIZE(spkmixl)), +SND_SOC_DAPM_MUX_E("Speaker PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux, + out_pga_event, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA("Speaker Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0), +SND_SOC_DAPM_OUTPUT("SPKOUT"), +}; + +static const struct snd_soc_dapm_widget wm8962_dapm_spk_stereo_widgets[] = { +SND_SOC_DAPM_MIXER("SPKOUTL Mixer", WM8962_MIXER_ENABLES, 1, 0, + spkmixl, ARRAY_SIZE(spkmixl)), +SND_SOC_DAPM_MIXER("SPKOUTR Mixer", WM8962_MIXER_ENABLES, 0, 0, + spkmixr, ARRAY_SIZE(spkmixr)), + +SND_SOC_DAPM_MUX_E("SPKOUTL PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux, + out_pga_event, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_MUX_E("SPKOUTR PGA", WM8962_PWR_MGMT_2, 3, 0, &spkoutr_mux, + out_pga_event, SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_PGA("SPKOUTR Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0), +SND_SOC_DAPM_PGA("SPKOUTL Output", WM8962_CLASS_D_CONTROL_1, 6, 0, NULL, 0), + +SND_SOC_DAPM_OUTPUT("SPKOUTL"), +SND_SOC_DAPM_OUTPUT("SPKOUTR"), +}; + +static const struct snd_soc_dapm_route wm8962_intercon[] = { + { "INPGAL", "IN1L Switch", "IN1L" }, + { "INPGAL", "IN2L Switch", "IN2L" }, + { "INPGAL", "IN3L Switch", "IN3L" }, + { "INPGAL", "IN4L Switch", "IN4L" }, + + { "INPGAR", "IN1R Switch", "IN1R" }, + { "INPGAR", "IN2R Switch", "IN2R" }, + { "INPGAR", "IN3R Switch", "IN3R" }, + { "INPGAR", "IN4R Switch", "IN4R" }, + + { "MIXINL", "IN2L Switch", "IN2L" }, + { "MIXINL", "IN3L Switch", "IN3L" }, + { "MIXINL", "PGA Switch", "INPGAL" }, + + { "MIXINR", "IN2R Switch", "IN2R" }, + { "MIXINR", "IN3R Switch", "IN3R" }, + { "MIXINR", "PGA Switch", "INPGAR" }, + + { "ADCL", NULL, "SYSCLK" }, + { "ADCL", NULL, "TOCLK" }, + { "ADCL", NULL, "MIXINL" }, + + { "ADCR", NULL, "SYSCLK" }, + { "ADCR", NULL, "TOCLK" }, + { "ADCR", NULL, "MIXINR" }, + + { "STL", "Left", "ADCL" }, + { "STL", "Right", "ADCR" }, + + { "STR", "Left", "ADCL" }, + { "STR", "Right", "ADCR" }, + + { "DACL", NULL, "SYSCLK" }, + { "DACL", NULL, "TOCLK" }, + { "DACL", NULL, "Beep" }, + { "DACL", NULL, "STL" }, + + { "DACR", NULL, "SYSCLK" }, + { "DACR", NULL, "TOCLK" }, + { "DACR", NULL, "Beep" }, + { "DACR", NULL, "STR" }, + + { "HPMIXL", "IN4L Switch", "IN4L" }, + { "HPMIXL", "IN4R Switch", "IN4R" }, + { "HPMIXL", "DACL Switch", "DACL" }, + { "HPMIXL", "DACR Switch", "DACR" }, + { "HPMIXL", "MIXINL Switch", "MIXINL" }, + { "HPMIXL", "MIXINR Switch", "MIXINR" }, + + { "HPMIXR", "IN4L Switch", "IN4L" }, + { "HPMIXR", "IN4R Switch", "IN4R" }, + { "HPMIXR", "DACL Switch", "DACL" }, + { "HPMIXR", "DACR Switch", "DACR" }, + { "HPMIXR", "MIXINL Switch", "MIXINL" }, + { "HPMIXR", "MIXINR Switch", "MIXINR" }, + + { "Left Bypass", NULL, "HPMIXL" }, + { "Left Bypass", NULL, "Class G" }, + + { "Right Bypass", NULL, "HPMIXR" }, + { "Right Bypass", NULL, "Class G" }, + + { "HPOUTL PGA", "Mixer", "Left Bypass" }, + { "HPOUTL PGA", "DAC", "DACL" }, + + { "HPOUTR PGA", "Mixer", "Right Bypass" }, + { "HPOUTR PGA", "DAC", "DACR" }, + + { "HPOUT", NULL, "HPOUTL PGA" }, + { "HPOUT", NULL, "HPOUTR PGA" }, + { "HPOUT", NULL, "Charge Pump" }, + { "HPOUT", NULL, "SYSCLK" }, + { "HPOUT", NULL, "TOCLK" }, + + { "HPOUTL", NULL, "HPOUT" }, + { "HPOUTR", NULL, "HPOUT" }, +}; + +static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = { + { "Speaker Mixer", "IN4L Switch", "IN4L" }, + { "Speaker Mixer", "IN4R Switch", "IN4R" }, + { "Speaker Mixer", "DACL Switch", "DACL" }, + { "Speaker Mixer", "DACR Switch", "DACR" }, + { "Speaker Mixer", "MIXINL Switch", "MIXINL" }, + { "Speaker Mixer", "MIXINR Switch", "MIXINR" }, + + { "Speaker PGA", "Mixer", "Speaker Mixer" }, + { "Speaker PGA", "DAC", "DACL" }, + + { "Speaker Output", NULL, "Speaker PGA" }, + { "Speaker Output", NULL, "SYSCLK" }, + { "Speaker Output", NULL, "TOCLK" }, + + { "SPKOUT", NULL, "Speaker Output" }, +}; + +static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = { + { "SPKOUTL Mixer", "IN4L Switch", "IN4L" }, + { "SPKOUTL Mixer", "IN4R Switch", "IN4R" }, + { "SPKOUTL Mixer", "DACL Switch", "DACL" }, + { "SPKOUTL Mixer", "DACR Switch", "DACR" }, + { "SPKOUTL Mixer", "MIXINL Switch", "MIXINL" }, + { "SPKOUTL Mixer", "MIXINR Switch", "MIXINR" }, + + { "SPKOUTR Mixer", "IN4L Switch", "IN4L" }, + { "SPKOUTR Mixer", "IN4R Switch", "IN4R" }, + { "SPKOUTR Mixer", "DACL Switch", "DACL" }, + { "SPKOUTR Mixer", "DACR Switch", "DACR" }, + { "SPKOUTR Mixer", "MIXINL Switch", "MIXINL" }, + { "SPKOUTR Mixer", "MIXINR Switch", "MIXINR" }, + + { "SPKOUTL PGA", "Mixer", "SPKOUTL Mixer" }, + { "SPKOUTL PGA", "DAC", "DACL" }, + + { "SPKOUTR PGA", "Mixer", "SPKOUTR Mixer" }, + { "SPKOUTR PGA", "DAC", "DACR" }, + + { "SPKOUTL Output", NULL, "SPKOUTL PGA" }, + { "SPKOUTL Output", NULL, "SYSCLK" }, + { "SPKOUTL Output", NULL, "TOCLK" }, + + { "SPKOUTR Output", NULL, "SPKOUTR PGA" }, + { "SPKOUTR Output", NULL, "SYSCLK" }, + { "SPKOUTR Output", NULL, "TOCLK" }, + + { "SPKOUTL", NULL, "SPKOUTL Output" }, + { "SPKOUTR", NULL, "SPKOUTR Output" }, +}; + +static int wm8962_add_widgets(struct snd_soc_codec *codec) +{ + struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); + + snd_soc_add_controls(codec, wm8962_snd_controls, + ARRAY_SIZE(wm8962_snd_controls)); + if (pdata && pdata->spk_mono) + snd_soc_add_controls(codec, wm8962_spk_mono_controls, + ARRAY_SIZE(wm8962_spk_mono_controls)); + else + snd_soc_add_controls(codec, wm8962_spk_stereo_controls, + ARRAY_SIZE(wm8962_spk_stereo_controls)); + + + snd_soc_dapm_new_controls(codec, wm8962_dapm_widgets, + ARRAY_SIZE(wm8962_dapm_widgets)); + if (pdata && pdata->spk_mono) + snd_soc_dapm_new_controls(codec, wm8962_dapm_spk_mono_widgets, + ARRAY_SIZE(wm8962_dapm_spk_mono_widgets)); + else + snd_soc_dapm_new_controls(codec, wm8962_dapm_spk_stereo_widgets, + ARRAY_SIZE(wm8962_dapm_spk_stereo_widgets)); + + snd_soc_dapm_add_routes(codec, wm8962_intercon, + ARRAY_SIZE(wm8962_intercon)); + if (pdata && pdata->spk_mono) + snd_soc_dapm_add_routes(codec, wm8962_spk_mono_intercon, + ARRAY_SIZE(wm8962_spk_mono_intercon)); + else + snd_soc_dapm_add_routes(codec, wm8962_spk_stereo_intercon, + ARRAY_SIZE(wm8962_spk_stereo_intercon)); + + + snd_soc_dapm_disable_pin(codec, "Beep"); + + return 0; +} + +static void wm8962_sync_cache(struct snd_soc_codec *codec) +{ + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + int i; + + if (!codec->cache_sync) + return; + + dev_dbg(codec->dev, "Syncing cache\n"); + + codec->cache_only = 0; + + /* Sync back cached values if they're different from the + * hardware default. + */ + for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { + if (i == WM8962_SOFTWARE_RESET) + continue; + if (wm8962->reg_cache[i] == wm8962_reg[i]) + continue; + + snd_soc_write(codec, i, wm8962->reg_cache[i]); + } + + codec->cache_sync = 0; +} + +/* -1 for reserved values */ +static const int bclk_divs[] = { + 1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32 +}; + +static void wm8962_configure_bclk(struct snd_soc_codec *codec) +{ + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + int dspclk, i; + int clocking2 = 0; + int aif2 = 0; + + /* If the CODEC is powered on we can configure BCLK */ + if (codec->bias_level != SND_SOC_BIAS_OFF) { + dev_dbg(codec->dev, "Bias is off, can't configure BCLK\n"); + return; + } + + if (!wm8962->bclk) { + dev_dbg(codec->dev, "No BCLK rate configured\n"); + return; + } + + dspclk = snd_soc_read(codec, WM8962_CLOCKING1); + if (dspclk < 0) { + dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); + return; + } + + dspclk = (dspclk & WM8962_DSPCLK_DIV_MASK) >> WM8962_DSPCLK_DIV_SHIFT; + switch (dspclk) { + case 0: + dspclk = wm8962->sysclk_rate; + break; + case 1: + dspclk = wm8962->sysclk_rate / 2; + break; + case 2: + dspclk = wm8962->sysclk_rate / 4; + break; + default: + dev_warn(codec->dev, "Unknown DSPCLK divisor read back\n"); + dspclk = wm8962->sysclk; + } + + dev_dbg(codec->dev, "DSPCLK is %dHz, BCLK %d\n", dspclk, wm8962->bclk); + + /* We're expecting an exact match */ + for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { + if (bclk_divs[i] < 0) + continue; + + if (dspclk / bclk_divs[i] == wm8962->bclk) { + dev_dbg(codec->dev, "Selected BCLK_DIV %d for %dHz\n", + bclk_divs[i], wm8962->bclk); + clocking2 |= i; + break; + } + } + if (i == ARRAY_SIZE(bclk_divs)) { + dev_err(codec->dev, "Unsupported BCLK ratio %d\n", + dspclk / wm8962->bclk); + return; + } + + aif2 |= wm8962->bclk / wm8962->lrclk; + dev_dbg(codec->dev, "Selected LRCLK divisor %d for %dHz\n", + wm8962->bclk / wm8962->lrclk, wm8962->lrclk); + + snd_soc_update_bits(codec, WM8962_CLOCKING2, + WM8962_BCLK_DIV_MASK, clocking2); + snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_2, + WM8962_AIF_RATE_MASK, aif2); +} + +static int wm8962_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + int ret; + + if (level == codec->bias_level) + return 0; + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + /* VMID 2*50k */ + snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, + WM8962_VMID_SEL_MASK, 0x80); + break; + + case SND_SOC_BIAS_STANDBY: + if (codec->bias_level == SND_SOC_BIAS_OFF) { + ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies), + wm8962->supplies); + if (ret != 0) { + dev_err(codec->dev, + "Failed to enable supplies: %d\n", + ret); + return ret; + } + + wm8962_sync_cache(codec); + + snd_soc_update_bits(codec, WM8962_ANTI_POP, + WM8962_STARTUP_BIAS_ENA | + WM8962_VMID_BUF_ENA, + WM8962_STARTUP_BIAS_ENA | + WM8962_VMID_BUF_ENA); + + /* Bias enable at 2*50k for ramp */ + snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, + WM8962_VMID_SEL_MASK | + WM8962_BIAS_ENA, + WM8962_BIAS_ENA | 0x180); + + msleep(5); + + snd_soc_update_bits(codec, WM8962_CLOCKING2, + WM8962_CLKREG_OVD, + WM8962_CLKREG_OVD); + + wm8962_configure_bclk(codec); + } + + /* VMID 2*250k */ + snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, + WM8962_VMID_SEL_MASK, 0x100); + break; + + case SND_SOC_BIAS_OFF: + snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, + WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0); + + snd_soc_update_bits(codec, WM8962_ANTI_POP, + WM8962_STARTUP_BIAS_ENA | + WM8962_VMID_BUF_ENA, 0); + + regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), + wm8962->supplies); + break; + } + codec->bias_level = level; + return 0; +} + +static const struct { + int rate; + int reg; +} sr_vals[] = { + { 48000, 0 }, + { 44100, 0 }, + { 32000, 1 }, + { 22050, 2 }, + { 24000, 2 }, + { 16000, 3 }, + { 11025, 4 }, + { 12000, 4 }, + { 8000, 5 }, + { 88200, 6 }, + { 96000, 6 }, +}; + +static const int sysclk_rates[] = { + 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536, +}; + +static int wm8962_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->card->codec; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + int rate = params_rate(params); + int i; + int aif0 = 0; + int adctl3 = 0; + int clocking4 = 0; + + wm8962->bclk = snd_soc_params_to_bclk(params); + wm8962->lrclk = params_rate(params); + + for (i = 0; i < ARRAY_SIZE(sr_vals); i++) { + if (sr_vals[i].rate == rate) { + adctl3 |= sr_vals[i].reg; + break; + } + } + if (i == ARRAY_SIZE(sr_vals)) { + dev_err(codec->dev, "Unsupported rate %dHz\n", rate); + return -EINVAL; + } + + if (rate % 8000 == 0) + adctl3 |= WM8962_SAMPLE_RATE_INT_MODE; + + for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) { + if (sysclk_rates[i] == wm8962->sysclk_rate / rate) { + clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT; + break; + } + } + if (i == ARRAY_SIZE(sysclk_rates)) { + dev_err(codec->dev, "Unsupported sysclk ratio %d\n", + wm8962->sysclk_rate / rate); + return -EINVAL; + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + break; + case SNDRV_PCM_FORMAT_S20_3LE: + aif0 |= 0x40; + break; + case SNDRV_PCM_FORMAT_S24_LE: + aif0 |= 0x80; + break; + case SNDRV_PCM_FORMAT_S32_LE: + aif0 |= 0xc0; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_0, + WM8962_WL_MASK, aif0); + snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3, + WM8962_SAMPLE_RATE_INT_MODE | + WM8962_SAMPLE_RATE_MASK, adctl3); + snd_soc_update_bits(codec, WM8962_CLOCKING_4, + WM8962_SYSCLK_RATE_MASK, clocking4); + + wm8962_configure_bclk(codec); + + return 0; +} + +static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + int src; + + switch (clk_id) { + case WM8962_SYSCLK_MCLK: + wm8962->sysclk = WM8962_SYSCLK_MCLK; + src = 0; + break; + case WM8962_SYSCLK_FLL: + wm8962->sysclk = WM8962_SYSCLK_FLL; + src = 1 << WM8962_SYSCLK_SRC_SHIFT; + WARN_ON(freq != wm8962->fll_fout); + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_SRC_MASK, + src); + + wm8962->sysclk_rate = freq; + + return 0; +} + +static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = dai->codec; + int aif0 = 0; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + aif0 |= WM8962_LRCLK_INV; + case SND_SOC_DAIFMT_DSP_B: + aif0 |= 3; + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + case SND_SOC_DAIFMT_IB_NF: + break; + default: + return -EINVAL; + } + break; + + case SND_SOC_DAIFMT_RIGHT_J: + break; + case SND_SOC_DAIFMT_LEFT_J: + aif0 |= 1; + break; + case SND_SOC_DAIFMT_I2S: + aif0 |= 2; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + aif0 |= WM8962_BCLK_INV; + break; + case SND_SOC_DAIFMT_NB_IF: + aif0 |= WM8962_LRCLK_INV; + break; + case SND_SOC_DAIFMT_IB_IF: + aif0 |= WM8962_BCLK_INV | WM8962_LRCLK_INV; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + aif0 |= WM8962_MSTR; + break; + case SND_SOC_DAIFMT_CBS_CFS: + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_0, + WM8962_FMT_MASK | WM8962_BCLK_INV | WM8962_MSTR | + WM8962_LRCLK_INV, aif0); + + return 0; +} + +struct _fll_div { + u16 fll_fratio; + u16 fll_outdiv; + u16 fll_refclk_div; + u16 n; + u16 theta; + u16 lambda; +}; + +/* The size in bits of the FLL divide multiplied by 10 + * to allow rounding later */ +#define FIXED_FLL_SIZE ((1 << 16) * 10) + +static struct { + unsigned int min; + unsigned int max; + u16 fll_fratio; + int ratio; +} fll_fratios[] = { + { 0, 64000, 4, 16 }, + { 64000, 128000, 3, 8 }, + { 128000, 256000, 2, 4 }, + { 256000, 1000000, 1, 2 }, + { 1000000, 13500000, 0, 1 }, +}; + +static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, + unsigned int Fout) +{ + unsigned int target; + unsigned int div; + unsigned int fratio, gcd_fll; + int i; + + /* Fref must be <=13.5MHz */ + div = 1; + fll_div->fll_refclk_div = 0; + while ((Fref / div) > 13500000) { + div *= 2; + fll_div->fll_refclk_div++; + + if (div > 4) { + pr_err("Can't scale %dMHz input down to <=13.5MHz\n", + Fref); + return -EINVAL; + } + } + + pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout); + + /* Apply the division for our remaining calculations */ + Fref /= div; + + /* Fvco should be 90-100MHz; don't check the upper bound */ + div = 2; + while (Fout * div < 90000000) { + div++; + if (div > 64) { + pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", + Fout); + return -EINVAL; + } + } + target = Fout * div; + fll_div->fll_outdiv = div - 1; + + pr_debug("FLL Fvco=%dHz\n", target); + + /* Find an appropraite FLL_FRATIO and factor it out of the target */ + for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { + if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { + fll_div->fll_fratio = fll_fratios[i].fll_fratio; + fratio = fll_fratios[i].ratio; + break; + } + } + if (i == ARRAY_SIZE(fll_fratios)) { + pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); + return -EINVAL; + } + + fll_div->n = target / (fratio * Fref); + + if (target % Fref == 0) { + fll_div->theta = 0; + fll_div->lambda = 0; + } else { + gcd_fll = gcd(target, fratio * Fref); + + fll_div->theta = (target - (fll_div->n * fratio * Fref)) + / gcd_fll; + fll_div->lambda = (fratio * Fref) / gcd_fll; + } + + pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n", + fll_div->n, fll_div->theta, fll_div->lambda); + pr_debug("FLL_FRATIO=%x FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n", + fll_div->fll_fratio, fll_div->fll_outdiv, + fll_div->fll_refclk_div); + + return 0; +} + +static int wm8962_set_fll(struct snd_soc_dai *dai, int fll_id, int source, + unsigned int Fref, unsigned int Fout) +{ + struct snd_soc_codec *codec = dai->codec; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + struct _fll_div fll_div; + int ret; + int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1); + + /* Any change? */ + if (source == wm8962->fll_src && Fref == wm8962->fll_fref && + Fout == wm8962->fll_fout) + return 0; + + if (Fout == 0) { + dev_dbg(codec->dev, "FLL disabled\n"); + + wm8962->fll_fref = 0; + wm8962->fll_fout = 0; + + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, + WM8962_FLL_ENA, 0); + + return 0; + } + + ret = fll_factors(&fll_div, Fref, Fout); + if (ret != 0) + return ret; + + switch (fll_id) { + case WM8962_FLL_MCLK: + case WM8962_FLL_BCLK: + case WM8962_FLL_OSC: + fll1 |= (fll_id - 1) << WM8962_FLL_REFCLK_SRC_SHIFT; + break; + case WM8962_FLL_INT: + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, + WM8962_FLL_OSC_ENA, WM8962_FLL_OSC_ENA); + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_5, + WM8962_FLL_FRC_NCO, WM8962_FLL_FRC_NCO); + break; + default: + dev_err(codec->dev, "Unknown FLL source %d\n", ret); + return -EINVAL; + } + + if (fll_div.theta || fll_div.lambda) + fll1 |= WM8962_FLL_FRAC; + + /* Stop the FLL while we reconfigure */ + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0); + + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_2, + WM8962_FLL_OUTDIV_MASK | + WM8962_FLL_REFCLK_DIV_MASK, + (fll_div.fll_outdiv << WM8962_FLL_OUTDIV_SHIFT) | + (fll_div.fll_refclk_div)); + + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_3, + WM8962_FLL_FRATIO_MASK, fll_div.fll_fratio); + + snd_soc_write(codec, WM8962_FLL_CONTROL_6, fll_div.theta); + snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda); + snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n); + + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, + WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK | + WM8962_FLL_ENA, fll1); + + dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); + + wm8962->fll_fref = Fref; + wm8962->fll_fout = Fout; + wm8962->fll_src = source; + + return 0; +} + +static int wm8962_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + int val; + + if (mute) + val = WM8962_DAC_MUTE; + else + val = 0; + + return snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, + WM8962_DAC_MUTE, val); +} + +#define WM8962_RATES SNDRV_PCM_RATE_8000_96000 + +#define WM8962_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_ops wm8962_dai_ops = { + .hw_params = wm8962_hw_params, + .set_sysclk = wm8962_set_dai_sysclk, + .set_fmt = wm8962_set_dai_fmt, + .set_pll = wm8962_set_fll, + .digital_mute = wm8962_mute, +}; + +struct snd_soc_dai wm8962_dai = { + .name = "WM8962", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = WM8962_RATES, + .formats = WM8962_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = WM8962_RATES, + .formats = WM8962_FORMATS, + }, + .ops = &wm8962_dai_ops, + .symmetric_rates = 1, +}; +EXPORT_SYMBOL_GPL(wm8962_dai); + +static int wm8962_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; + int ret = 0; + + if (wm8962_codec == NULL) { + dev_err(&pdev->dev, "Codec device not registered\n"); + return -ENODEV; + } + + socdev->card->codec = wm8962_codec; + codec = wm8962_codec; + + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + dev_err(codec->dev, "failed to create pcms: %d\n", ret); + goto pcm_err; + } + + wm8962_add_widgets(codec); + + return ret; + +pcm_err: + return ret; +} + +static int wm8962_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); + + return 0; +} + +#ifdef CONFIG_PM +static int wm8962_resume(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->card->codec; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; + int i; + + /* Restore the registers */ + for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { + switch (i) { + case WM8962_SOFTWARE_RESET: + continue; + default: + break; + } + + if (reg_cache[i] != wm8962_reg[i]) + snd_soc_write(codec, i, reg_cache[i]); + } + + return 0; +} +#else +#define wm8962_resume NULL +#endif + +struct snd_soc_codec_device soc_codec_dev_wm8962 = { + .probe = wm8962_probe, + .remove = wm8962_remove, + .resume = wm8962_resume, +}; +EXPORT_SYMBOL_GPL(soc_codec_dev_wm8962); + +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) +static int beep_rates[] = { + 500, 1000, 2000, 4000, +}; + +static void wm8962_beep_work(struct work_struct *work) +{ + struct wm8962_priv *wm8962 = + container_of(work, struct wm8962_priv, beep_work); + struct snd_soc_codec *codec = &wm8962->codec; + int i; + int reg = 0; + int best = 0; + + if (wm8962->beep_rate) { + for (i = 0; i < ARRAY_SIZE(beep_rates); i++) { + if (abs(wm8962->beep_rate - beep_rates[i]) < + abs(wm8962->beep_rate - beep_rates[best])) + best = i; + } + + dev_dbg(codec->dev, "Set beep rate %dHz for requested %dHz\n", + beep_rates[best], wm8962->beep_rate); + + reg = WM8962_BEEP_ENA | (best << WM8962_BEEP_RATE_SHIFT); + + snd_soc_dapm_enable_pin(codec, "Beep"); + } else { + dev_dbg(codec->dev, "Disabling beep\n"); + snd_soc_dapm_disable_pin(codec, "Beep"); + } + + snd_soc_update_bits(codec, WM8962_BEEP_GENERATOR_1, + WM8962_BEEP_ENA | WM8962_BEEP_RATE_MASK, reg); + + snd_soc_dapm_sync(codec); +} + +/* For usability define a way of injecting beep events for the device - + * many systems will not have a keyboard. + */ +static int wm8962_beep_event(struct input_dev *dev, unsigned int type, + unsigned int code, int hz) +{ + struct snd_soc_codec *codec = input_get_drvdata(dev); + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + + dev_dbg(codec->dev, "Beep event %x %x\n", code, hz); + + switch (code) { + case SND_BELL: + if (hz) + hz = 1000; + case SND_TONE: + break; + default: + return -1; + } + + /* Kick the beep from a workqueue */ + wm8962->beep_rate = hz; + schedule_work(&wm8962->beep_work); + return 0; +} + +static ssize_t wm8962_beep_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct wm8962_priv *wm8962 = dev_get_drvdata(dev); + long int time; + + strict_strtol(buf, 10, &time); + + input_event(wm8962->beep, EV_SND, SND_TONE, time); + + return count; +} + +static DEVICE_ATTR(beep, 0200, NULL, wm8962_beep_set); + +static void wm8962_init_beep(struct snd_soc_codec *codec) +{ + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + int ret; + + wm8962->beep = input_allocate_device(); + if (!wm8962->beep) { + dev_err(codec->dev, "Failed to allocate beep device\n"); + return; + } + + INIT_WORK(&wm8962->beep_work, wm8962_beep_work); + wm8962->beep_rate = 0; + + wm8962->beep->name = "WM8962 Beep Generator"; + wm8962->beep->phys = dev_name(codec->dev); + wm8962->beep->id.bustype = BUS_I2C; + + wm8962->beep->evbit[0] = BIT_MASK(EV_SND); + wm8962->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); + wm8962->beep->event = wm8962_beep_event; + wm8962->beep->dev.parent = codec->dev; + input_set_drvdata(wm8962->beep, codec); + + ret = input_register_device(wm8962->beep); + if (ret != 0) { + input_free_device(wm8962->beep); + wm8962->beep = NULL; + dev_err(codec->dev, "Failed to register beep device\n"); + } + + ret = device_create_file(codec->dev, &dev_attr_beep); + if (ret != 0) { + dev_err(codec->dev, "Failed to create keyclick file: %d\n", + ret); + } +} + +static void wm8962_free_beep(struct snd_soc_codec *codec) +{ + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + + device_remove_file(codec->dev, &dev_attr_beep); + input_unregister_device(wm8962->beep); + cancel_work_sync(&wm8962->beep_work); + wm8962->beep = NULL; + + snd_soc_update_bits(codec, WM8962_BEEP_GENERATOR_1, WM8962_BEEP_ENA,0); +} +#else +static void wm8962_init_beep(struct snd_soc_codec *codec) +{ +} + +static void wm8962_free_beep(struct snd_soc_codec *codec) +{ +} +#endif + +static int wm8962_register(struct wm8962_priv *wm8962, + enum snd_soc_control_type control) +{ + int ret; + struct snd_soc_codec *codec = &wm8962->codec; + struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); + int i; + + if (wm8962_codec) { + dev_err(codec->dev, "Another WM8962 is registered\n"); + return -EINVAL; + } + + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + snd_soc_codec_set_drvdata(codec, wm8962); + codec->name = "WM8962"; + codec->owner = THIS_MODULE; + codec->bias_level = SND_SOC_BIAS_OFF; + codec->set_bias_level = wm8962_set_bias_level; + codec->dai = &wm8962_dai; + codec->num_dai = 1; + codec->reg_cache_size = WM8962_MAX_REGISTER; + codec->reg_cache = &wm8962->reg_cache; + codec->volatile_register = wm8962_volatile_register; + codec->cache_sync = 1; + codec->idle_bias_off = 1; + codec->readable_register = wm8962_readable; + + memcpy(codec->reg_cache, wm8962_reg, sizeof(wm8962_reg)); + + ret = snd_soc_codec_set_cache_io(codec, 16, 16, control); + if (ret != 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + goto err; + } + + for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) + wm8962->supplies[i].supply = wm8962_supply_names[i]; + + ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8962->supplies), + wm8962->supplies); + if (ret != 0) { + dev_err(codec->dev, "Failed to request supplies: %d\n", ret); + goto err; + } + + wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0; + wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1; + wm8962->disable_nb[2].notifier_call = wm8962_regulator_event_2; + wm8962->disable_nb[3].notifier_call = wm8962_regulator_event_3; + wm8962->disable_nb[4].notifier_call = wm8962_regulator_event_4; + wm8962->disable_nb[5].notifier_call = wm8962_regulator_event_5; + wm8962->disable_nb[6].notifier_call = wm8962_regulator_event_6; + wm8962->disable_nb[7].notifier_call = wm8962_regulator_event_7; + + /* This should really be moved into the regulator core */ + for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) { + ret = regulator_register_notifier(wm8962->supplies[i].consumer, + &wm8962->disable_nb[i]); + if (ret != 0) { + dev_err(codec->dev, + "Failed to register regulator notifier: %d\n", + ret); + } + } + + ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies), + wm8962->supplies); + if (ret != 0) { + dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); + goto err_get; + } + + ret = snd_soc_read(codec, WM8962_SOFTWARE_RESET); + if (ret < 0) { + dev_err(codec->dev, "Failed to read ID register\n"); + goto err_enable; + } + if (ret != wm8962_reg[WM8962_SOFTWARE_RESET]) { + dev_err(codec->dev, "Device is not a WM8962, ID %x != %x\n", + ret, wm8962_reg[WM8962_SOFTWARE_RESET]); + ret = -EINVAL; + goto err_enable; + } + + ret = snd_soc_read(codec, WM8962_RIGHT_INPUT_VOLUME); + if (ret < 0) { + dev_err(codec->dev, "Failed to read device revision: %d\n", + ret); + goto err_enable; + } + + dev_info(codec->dev, "customer id %x revision %c\n", + (ret & WM8962_CUST_ID_MASK) >> WM8962_CUST_ID_SHIFT, + ((ret & WM8962_CHIP_REV_MASK) >> WM8962_CHIP_REV_SHIFT) + + 'A'); + + ret = wm8962_reset(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to issue reset\n"); + goto err_enable; + } + + /* SYSCLK defaults to on; make sure it is off so we can safely + * write to registers if the device is declocked. + */ + snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_ENA, 0); + + regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); + + if (pdata) { + /* Apply static configuration for GPIOs */ + for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) + if (pdata->gpio_init[i]) + snd_soc_write(codec, 0x200 + i, + pdata->gpio_init[i] & 0xffff); + + /* Put the speakers into mono mode? */ + if (pdata->spk_mono) + wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2] + |= WM8962_SPK_MONO; + } + + /* Latch volume update bits */ + wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; + wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; + wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; + wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU; + wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; + wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; + wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; + wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; + wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; + wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU; + + wm8962_dai.dev = codec->dev; + + wm8962_codec = codec; + + ret = snd_soc_register_codec(codec); + if (ret != 0) { + dev_err(codec->dev, "Failed to register codec: %d\n", ret); + return ret; + } + + ret = snd_soc_register_dai(&wm8962_dai); + if (ret != 0) { + dev_err(codec->dev, "Failed to register DAI: %d\n", ret); + snd_soc_unregister_codec(codec); + return ret; + } + + wm8962_init_beep(codec); + + return 0; + +err_enable: + regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); +err_get: + regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); +err: + kfree(wm8962); + return ret; +} + +static void wm8962_unregister(struct wm8962_priv *wm8962) +{ + int i; + + wm8962_free_beep(&wm8962->codec); + wm8962_set_bias_level(&wm8962->codec, SND_SOC_BIAS_OFF); + for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) + regulator_unregister_notifier(wm8962->supplies[i].consumer, + &wm8962->disable_nb[i]); + regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); + snd_soc_unregister_dai(&wm8962_dai); + snd_soc_unregister_codec(&wm8962->codec); + kfree(wm8962); + wm8962_codec = NULL; +} + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8962_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct wm8962_priv *wm8962; + struct snd_soc_codec *codec; + + wm8962 = kzalloc(sizeof(struct wm8962_priv), GFP_KERNEL); + if (wm8962 == NULL) + return -ENOMEM; + + codec = &wm8962->codec; + codec->hw_write = (hw_write_t)i2c_master_send; + + i2c_set_clientdata(i2c, wm8962); + codec->control_data = i2c; + + codec->dev = &i2c->dev; + + return wm8962_register(wm8962, SND_SOC_I2C); +} + +static __devexit int wm8962_i2c_remove(struct i2c_client *client) +{ + struct wm8962_priv *wm8962 = i2c_get_clientdata(client); + wm8962_unregister(wm8962); + return 0; +} + +static const struct i2c_device_id wm8962_i2c_id[] = { + { "wm8962", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wm8962_i2c_id); + +static struct i2c_driver wm8962_i2c_driver = { + .driver = { + .name = "WM8962", + .owner = THIS_MODULE, + }, + .probe = wm8962_i2c_probe, + .remove = __devexit_p(wm8962_i2c_remove), + .id_table = wm8962_i2c_id, +}; +#endif + +static int __init wm8962_modinit(void) +{ + int ret; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + ret = i2c_add_driver(&wm8962_i2c_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register WM8962 I2C driver: %d\n", + ret); + } +#endif + return 0; +} +module_init(wm8962_modinit); + +static void __exit wm8962_exit(void) +{ +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_del_driver(&wm8962_i2c_driver); +#endif +} +module_exit(wm8962_exit); + +MODULE_DESCRIPTION("ASoC WM8962 driver"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wm8962.h b/sound/soc/codecs/wm8962.h new file mode 100644 index 000000000000..bc0b1876174c --- /dev/null +++ b/sound/soc/codecs/wm8962.h @@ -0,0 +1,3790 @@ +/* + * wm8962.h -- WM8962 ASoC driver + * + * Copyright 2010 Wolfson Microelectronics, plc + * + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _WM8962_H +#define _WM8962_H + +#include + +extern struct snd_soc_dai wm8962_dai; +extern struct snd_soc_codec_device soc_codec_dev_wm8962; + +#define WM8962_SYSCLK_MCLK 1 +#define WM8962_SYSCLK_FLL 2 +#define WM8962_SYSCLK_PLL3 3 + +#define WM8962_FLL 1 + +#define WM8962_FLL_MCLK 1 +#define WM8962_FLL_BCLK 2 +#define WM8962_FLL_OSC 3 +#define WM8962_FLL_INT 4 + +/* + * Register values. + */ +#define WM8962_LEFT_INPUT_VOLUME 0x00 +#define WM8962_RIGHT_INPUT_VOLUME 0x01 +#define WM8962_HPOUTL_VOLUME 0x02 +#define WM8962_HPOUTR_VOLUME 0x03 +#define WM8962_CLOCKING1 0x04 +#define WM8962_ADC_DAC_CONTROL_1 0x05 +#define WM8962_ADC_DAC_CONTROL_2 0x06 +#define WM8962_AUDIO_INTERFACE_0 0x07 +#define WM8962_CLOCKING2 0x08 +#define WM8962_AUDIO_INTERFACE_1 0x09 +#define WM8962_LEFT_DAC_VOLUME 0x0A +#define WM8962_RIGHT_DAC_VOLUME 0x0B +#define WM8962_AUDIO_INTERFACE_2 0x0E +#define WM8962_SOFTWARE_RESET 0x0F +#define WM8962_ALC1 0x11 +#define WM8962_ALC2 0x12 +#define WM8962_ALC3 0x13 +#define WM8962_NOISE_GATE 0x14 +#define WM8962_LEFT_ADC_VOLUME 0x15 +#define WM8962_RIGHT_ADC_VOLUME 0x16 +#define WM8962_ADDITIONAL_CONTROL_1 0x17 +#define WM8962_ADDITIONAL_CONTROL_2 0x18 +#define WM8962_PWR_MGMT_1 0x19 +#define WM8962_PWR_MGMT_2 0x1A +#define WM8962_ADDITIONAL_CONTROL_3 0x1B +#define WM8962_ANTI_POP 0x1C +#define WM8962_CLOCKING_3 0x1E +#define WM8962_INPUT_MIXER_CONTROL_1 0x1F +#define WM8962_LEFT_INPUT_MIXER_VOLUME 0x20 +#define WM8962_RIGHT_INPUT_MIXER_VOLUME 0x21 +#define WM8962_INPUT_MIXER_CONTROL_2 0x22 +#define WM8962_INPUT_BIAS_CONTROL 0x23 +#define WM8962_LEFT_INPUT_PGA_CONTROL 0x25 +#define WM8962_RIGHT_INPUT_PGA_CONTROL 0x26 +#define WM8962_SPKOUTL_VOLUME 0x28 +#define WM8962_SPKOUTR_VOLUME 0x29 +#define WM8962_THERMAL_SHUTDOWN_STATUS 0x2F +#define WM8962_ADDITIONAL_CONTROL_4 0x30 +#define WM8962_CLASS_D_CONTROL_1 0x31 +#define WM8962_CLASS_D_CONTROL_2 0x33 +#define WM8962_CLOCKING_4 0x38 +#define WM8962_DAC_DSP_MIXING_1 0x39 +#define WM8962_DAC_DSP_MIXING_2 0x3A +#define WM8962_DC_SERVO_0 0x3C +#define WM8962_DC_SERVO_1 0x3D +#define WM8962_DC_SERVO_4 0x40 +#define WM8962_DC_SERVO_6 0x42 +#define WM8962_ANALOGUE_PGA_BIAS 0x44 +#define WM8962_ANALOGUE_HP_0 0x45 +#define WM8962_ANALOGUE_HP_2 0x47 +#define WM8962_CHARGE_PUMP_1 0x48 +#define WM8962_CHARGE_PUMP_B 0x52 +#define WM8962_WRITE_SEQUENCER_CONTROL_1 0x57 +#define WM8962_WRITE_SEQUENCER_CONTROL_2 0x5A +#define WM8962_WRITE_SEQUENCER_CONTROL_3 0x5D +#define WM8962_CONTROL_INTERFACE 0x5E +#define WM8962_MIXER_ENABLES 0x63 +#define WM8962_HEADPHONE_MIXER_1 0x64 +#define WM8962_HEADPHONE_MIXER_2 0x65 +#define WM8962_HEADPHONE_MIXER_3 0x66 +#define WM8962_HEADPHONE_MIXER_4 0x67 +#define WM8962_SPEAKER_MIXER_1 0x69 +#define WM8962_SPEAKER_MIXER_2 0x6A +#define WM8962_SPEAKER_MIXER_3 0x6B +#define WM8962_SPEAKER_MIXER_4 0x6C +#define WM8962_SPEAKER_MIXER_5 0x6D +#define WM8962_BEEP_GENERATOR_1 0x6E +#define WM8962_OSCILLATOR_TRIM_3 0x73 +#define WM8962_OSCILLATOR_TRIM_4 0x74 +#define WM8962_OSCILLATOR_TRIM_7 0x77 +#define WM8962_ANALOGUE_CLOCKING1 0x7C +#define WM8962_ANALOGUE_CLOCKING2 0x7D +#define WM8962_ANALOGUE_CLOCKING3 0x7E +#define WM8962_PLL_SOFTWARE_RESET 0x7F +#define WM8962_PLL2 0x81 +#define WM8962_PLL_4 0x83 +#define WM8962_PLL_9 0x88 +#define WM8962_PLL_10 0x89 +#define WM8962_PLL_11 0x8A +#define WM8962_PLL_12 0x8B +#define WM8962_PLL_13 0x8C +#define WM8962_PLL_14 0x8D +#define WM8962_PLL_15 0x8E +#define WM8962_PLL_16 0x8F +#define WM8962_FLL_CONTROL_1 0x9B +#define WM8962_FLL_CONTROL_2 0x9C +#define WM8962_FLL_CONTROL_3 0x9D +#define WM8962_FLL_CONTROL_5 0x9F +#define WM8962_FLL_CONTROL_6 0xA0 +#define WM8962_FLL_CONTROL_7 0xA1 +#define WM8962_FLL_CONTROL_8 0xA2 +#define WM8962_GENERAL_TEST_1 0xFC +#define WM8962_DF1 0x100 +#define WM8962_DF2 0x101 +#define WM8962_DF3 0x102 +#define WM8962_DF4 0x103 +#define WM8962_DF5 0x104 +#define WM8962_DF6 0x105 +#define WM8962_DF7 0x106 +#define WM8962_LHPF1 0x108 +#define WM8962_LHPF2 0x109 +#define WM8962_THREED1 0x10C +#define WM8962_THREED2 0x10D +#define WM8962_THREED3 0x10E +#define WM8962_THREED4 0x10F +#define WM8962_DRC_1 0x114 +#define WM8962_DRC_2 0x115 +#define WM8962_DRC_3 0x116 +#define WM8962_DRC_4 0x117 +#define WM8962_DRC_5 0x118 +#define WM8962_TLOOPBACK 0x11D +#define WM8962_EQ1 0x14F +#define WM8962_EQ2 0x150 +#define WM8962_EQ3 0x151 +#define WM8962_EQ4 0x152 +#define WM8962_EQ5 0x153 +#define WM8962_EQ6 0x154 +#define WM8962_EQ7 0x155 +#define WM8962_EQ8 0x156 +#define WM8962_EQ9 0x157 +#define WM8962_EQ10 0x158 +#define WM8962_EQ11 0x159 +#define WM8962_EQ12 0x15A +#define WM8962_EQ13 0x15B +#define WM8962_EQ14 0x15C +#define WM8962_EQ15 0x15D +#define WM8962_EQ16 0x15E +#define WM8962_EQ17 0x15F +#define WM8962_EQ18 0x160 +#define WM8962_EQ19 0x161 +#define WM8962_EQ20 0x162 +#define WM8962_EQ21 0x163 +#define WM8962_EQ22 0x164 +#define WM8962_EQ23 0x165 +#define WM8962_EQ24 0x166 +#define WM8962_EQ25 0x167 +#define WM8962_EQ26 0x168 +#define WM8962_EQ27 0x169 +#define WM8962_EQ28 0x16A +#define WM8962_EQ29 0x16B +#define WM8962_EQ30 0x16C +#define WM8962_EQ31 0x16D +#define WM8962_EQ32 0x16E +#define WM8962_EQ33 0x16F +#define WM8962_EQ34 0x170 +#define WM8962_EQ35 0x171 +#define WM8962_EQ36 0x172 +#define WM8962_EQ37 0x173 +#define WM8962_EQ38 0x174 +#define WM8962_EQ39 0x175 +#define WM8962_EQ40 0x176 +#define WM8962_EQ41 0x177 +#define WM8962_GPIO_2 0x201 +#define WM8962_GPIO_3 0x202 +#define WM8962_GPIO_5 0x204 +#define WM8962_GPIO_6 0x205 +#define WM8962_INTERRUPT_STATUS_1 0x230 +#define WM8962_INTERRUPT_STATUS_2 0x231 +#define WM8962_INTERRUPT_STATUS_1_MASK 0x238 +#define WM8962_INTERRUPT_STATUS_2_MASK 0x239 +#define WM8962_INTERRUPT_CONTROL 0x240 +#define WM8962_IRQ_DEBOUNCE 0x248 +#define WM8962_MICINT_SOURCE_POL 0x24A +#define WM8962_DSP2_POWER_MANAGEMENT 0x300 +#define WM8962_DSP2_EXECCONTROL 0x40D +#define WM8962_WRITE_SEQUENCER_0 0x1000 +#define WM8962_WRITE_SEQUENCER_1 0x1001 +#define WM8962_WRITE_SEQUENCER_2 0x1002 +#define WM8962_WRITE_SEQUENCER_3 0x1003 +#define WM8962_WRITE_SEQUENCER_4 0x1004 +#define WM8962_WRITE_SEQUENCER_5 0x1005 +#define WM8962_WRITE_SEQUENCER_6 0x1006 +#define WM8962_WRITE_SEQUENCER_7 0x1007 +#define WM8962_WRITE_SEQUENCER_8 0x1008 +#define WM8962_WRITE_SEQUENCER_9 0x1009 +#define WM8962_WRITE_SEQUENCER_10 0x100A +#define WM8962_WRITE_SEQUENCER_11 0x100B +#define WM8962_WRITE_SEQUENCER_12 0x100C +#define WM8962_WRITE_SEQUENCER_13 0x100D +#define WM8962_WRITE_SEQUENCER_14 0x100E +#define WM8962_WRITE_SEQUENCER_15 0x100F +#define WM8962_WRITE_SEQUENCER_16 0x1010 +#define WM8962_WRITE_SEQUENCER_17 0x1011 +#define WM8962_WRITE_SEQUENCER_18 0x1012 +#define WM8962_WRITE_SEQUENCER_19 0x1013 +#define WM8962_WRITE_SEQUENCER_20 0x1014 +#define WM8962_WRITE_SEQUENCER_21 0x1015 +#define WM8962_WRITE_SEQUENCER_22 0x1016 +#define WM8962_WRITE_SEQUENCER_23 0x1017 +#define WM8962_WRITE_SEQUENCER_24 0x1018 +#define WM8962_WRITE_SEQUENCER_25 0x1019 +#define WM8962_WRITE_SEQUENCER_26 0x101A +#define WM8962_WRITE_SEQUENCER_27 0x101B +#define WM8962_WRITE_SEQUENCER_28 0x101C +#define WM8962_WRITE_SEQUENCER_29 0x101D +#define WM8962_WRITE_SEQUENCER_30 0x101E +#define WM8962_WRITE_SEQUENCER_31 0x101F +#define WM8962_WRITE_SEQUENCER_32 0x1020 +#define WM8962_WRITE_SEQUENCER_33 0x1021 +#define WM8962_WRITE_SEQUENCER_34 0x1022 +#define WM8962_WRITE_SEQUENCER_35 0x1023 +#define WM8962_WRITE_SEQUENCER_36 0x1024 +#define WM8962_WRITE_SEQUENCER_37 0x1025 +#define WM8962_WRITE_SEQUENCER_38 0x1026 +#define WM8962_WRITE_SEQUENCER_39 0x1027 +#define WM8962_WRITE_SEQUENCER_40 0x1028 +#define WM8962_WRITE_SEQUENCER_41 0x1029 +#define WM8962_WRITE_SEQUENCER_42 0x102A +#define WM8962_WRITE_SEQUENCER_43 0x102B +#define WM8962_WRITE_SEQUENCER_44 0x102C +#define WM8962_WRITE_SEQUENCER_45 0x102D +#define WM8962_WRITE_SEQUENCER_46 0x102E +#define WM8962_WRITE_SEQUENCER_47 0x102F +#define WM8962_WRITE_SEQUENCER_48 0x1030 +#define WM8962_WRITE_SEQUENCER_49 0x1031 +#define WM8962_WRITE_SEQUENCER_50 0x1032 +#define WM8962_WRITE_SEQUENCER_51 0x1033 +#define WM8962_WRITE_SEQUENCER_52 0x1034 +#define WM8962_WRITE_SEQUENCER_53 0x1035 +#define WM8962_WRITE_SEQUENCER_54 0x1036 +#define WM8962_WRITE_SEQUENCER_55 0x1037 +#define WM8962_WRITE_SEQUENCER_56 0x1038 +#define WM8962_WRITE_SEQUENCER_57 0x1039 +#define WM8962_WRITE_SEQUENCER_58 0x103A +#define WM8962_WRITE_SEQUENCER_59 0x103B +#define WM8962_WRITE_SEQUENCER_60 0x103C +#define WM8962_WRITE_SEQUENCER_61 0x103D +#define WM8962_WRITE_SEQUENCER_62 0x103E +#define WM8962_WRITE_SEQUENCER_63 0x103F +#define WM8962_WRITE_SEQUENCER_64 0x1040 +#define WM8962_WRITE_SEQUENCER_65 0x1041 +#define WM8962_WRITE_SEQUENCER_66 0x1042 +#define WM8962_WRITE_SEQUENCER_67 0x1043 +#define WM8962_WRITE_SEQUENCER_68 0x1044 +#define WM8962_WRITE_SEQUENCER_69 0x1045 +#define WM8962_WRITE_SEQUENCER_70 0x1046 +#define WM8962_WRITE_SEQUENCER_71 0x1047 +#define WM8962_WRITE_SEQUENCER_72 0x1048 +#define WM8962_WRITE_SEQUENCER_73 0x1049 +#define WM8962_WRITE_SEQUENCER_74 0x104A +#define WM8962_WRITE_SEQUENCER_75 0x104B +#define WM8962_WRITE_SEQUENCER_76 0x104C +#define WM8962_WRITE_SEQUENCER_77 0x104D +#define WM8962_WRITE_SEQUENCER_78 0x104E +#define WM8962_WRITE_SEQUENCER_79 0x104F +#define WM8962_WRITE_SEQUENCER_80 0x1050 +#define WM8962_WRITE_SEQUENCER_81 0x1051 +#define WM8962_WRITE_SEQUENCER_82 0x1052 +#define WM8962_WRITE_SEQUENCER_83 0x1053 +#define WM8962_WRITE_SEQUENCER_84 0x1054 +#define WM8962_WRITE_SEQUENCER_85 0x1055 +#define WM8962_WRITE_SEQUENCER_86 0x1056 +#define WM8962_WRITE_SEQUENCER_87 0x1057 +#define WM8962_WRITE_SEQUENCER_88 0x1058 +#define WM8962_WRITE_SEQUENCER_89 0x1059 +#define WM8962_WRITE_SEQUENCER_90 0x105A +#define WM8962_WRITE_SEQUENCER_91 0x105B +#define WM8962_WRITE_SEQUENCER_92 0x105C +#define WM8962_WRITE_SEQUENCER_93 0x105D +#define WM8962_WRITE_SEQUENCER_94 0x105E +#define WM8962_WRITE_SEQUENCER_95 0x105F +#define WM8962_WRITE_SEQUENCER_96 0x1060 +#define WM8962_WRITE_SEQUENCER_97 0x1061 +#define WM8962_WRITE_SEQUENCER_98 0x1062 +#define WM8962_WRITE_SEQUENCER_99 0x1063 +#define WM8962_WRITE_SEQUENCER_100 0x1064 +#define WM8962_WRITE_SEQUENCER_101 0x1065 +#define WM8962_WRITE_SEQUENCER_102 0x1066 +#define WM8962_WRITE_SEQUENCER_103 0x1067 +#define WM8962_WRITE_SEQUENCER_104 0x1068 +#define WM8962_WRITE_SEQUENCER_105 0x1069 +#define WM8962_WRITE_SEQUENCER_106 0x106A +#define WM8962_WRITE_SEQUENCER_107 0x106B +#define WM8962_WRITE_SEQUENCER_108 0x106C +#define WM8962_WRITE_SEQUENCER_109 0x106D +#define WM8962_WRITE_SEQUENCER_110 0x106E +#define WM8962_WRITE_SEQUENCER_111 0x106F +#define WM8962_WRITE_SEQUENCER_112 0x1070 +#define WM8962_WRITE_SEQUENCER_113 0x1071 +#define WM8962_WRITE_SEQUENCER_114 0x1072 +#define WM8962_WRITE_SEQUENCER_115 0x1073 +#define WM8962_WRITE_SEQUENCER_116 0x1074 +#define WM8962_WRITE_SEQUENCER_117 0x1075 +#define WM8962_WRITE_SEQUENCER_118 0x1076 +#define WM8962_WRITE_SEQUENCER_119 0x1077 +#define WM8962_WRITE_SEQUENCER_120 0x1078 +#define WM8962_WRITE_SEQUENCER_121 0x1079 +#define WM8962_WRITE_SEQUENCER_122 0x107A +#define WM8962_WRITE_SEQUENCER_123 0x107B +#define WM8962_WRITE_SEQUENCER_124 0x107C +#define WM8962_WRITE_SEQUENCER_125 0x107D +#define WM8962_WRITE_SEQUENCER_126 0x107E +#define WM8962_WRITE_SEQUENCER_127 0x107F +#define WM8962_WRITE_SEQUENCER_128 0x1080 +#define WM8962_WRITE_SEQUENCER_129 0x1081 +#define WM8962_WRITE_SEQUENCER_130 0x1082 +#define WM8962_WRITE_SEQUENCER_131 0x1083 +#define WM8962_WRITE_SEQUENCER_132 0x1084 +#define WM8962_WRITE_SEQUENCER_133 0x1085 +#define WM8962_WRITE_SEQUENCER_134 0x1086 +#define WM8962_WRITE_SEQUENCER_135 0x1087 +#define WM8962_WRITE_SEQUENCER_136 0x1088 +#define WM8962_WRITE_SEQUENCER_137 0x1089 +#define WM8962_WRITE_SEQUENCER_138 0x108A +#define WM8962_WRITE_SEQUENCER_139 0x108B +#define WM8962_WRITE_SEQUENCER_140 0x108C +#define WM8962_WRITE_SEQUENCER_141 0x108D +#define WM8962_WRITE_SEQUENCER_142 0x108E +#define WM8962_WRITE_SEQUENCER_143 0x108F +#define WM8962_WRITE_SEQUENCER_144 0x1090 +#define WM8962_WRITE_SEQUENCER_145 0x1091 +#define WM8962_WRITE_SEQUENCER_146 0x1092 +#define WM8962_WRITE_SEQUENCER_147 0x1093 +#define WM8962_WRITE_SEQUENCER_148 0x1094 +#define WM8962_WRITE_SEQUENCER_149 0x1095 +#define WM8962_WRITE_SEQUENCER_150 0x1096 +#define WM8962_WRITE_SEQUENCER_151 0x1097 +#define WM8962_WRITE_SEQUENCER_152 0x1098 +#define WM8962_WRITE_SEQUENCER_153 0x1099 +#define WM8962_WRITE_SEQUENCER_154 0x109A +#define WM8962_WRITE_SEQUENCER_155 0x109B +#define WM8962_WRITE_SEQUENCER_156 0x109C +#define WM8962_WRITE_SEQUENCER_157 0x109D +#define WM8962_WRITE_SEQUENCER_158 0x109E +#define WM8962_WRITE_SEQUENCER_159 0x109F +#define WM8962_WRITE_SEQUENCER_160 0x10A0 +#define WM8962_WRITE_SEQUENCER_161 0x10A1 +#define WM8962_WRITE_SEQUENCER_162 0x10A2 +#define WM8962_WRITE_SEQUENCER_163 0x10A3 +#define WM8962_WRITE_SEQUENCER_164 0x10A4 +#define WM8962_WRITE_SEQUENCER_165 0x10A5 +#define WM8962_WRITE_SEQUENCER_166 0x10A6 +#define WM8962_WRITE_SEQUENCER_167 0x10A7 +#define WM8962_WRITE_SEQUENCER_168 0x10A8 +#define WM8962_WRITE_SEQUENCER_169 0x10A9 +#define WM8962_WRITE_SEQUENCER_170 0x10AA +#define WM8962_WRITE_SEQUENCER_171 0x10AB +#define WM8962_WRITE_SEQUENCER_172 0x10AC +#define WM8962_WRITE_SEQUENCER_173 0x10AD +#define WM8962_WRITE_SEQUENCER_174 0x10AE +#define WM8962_WRITE_SEQUENCER_175 0x10AF +#define WM8962_WRITE_SEQUENCER_176 0x10B0 +#define WM8962_WRITE_SEQUENCER_177 0x10B1 +#define WM8962_WRITE_SEQUENCER_178 0x10B2 +#define WM8962_WRITE_SEQUENCER_179 0x10B3 +#define WM8962_WRITE_SEQUENCER_180 0x10B4 +#define WM8962_WRITE_SEQUENCER_181 0x10B5 +#define WM8962_WRITE_SEQUENCER_182 0x10B6 +#define WM8962_WRITE_SEQUENCER_183 0x10B7 +#define WM8962_WRITE_SEQUENCER_184 0x10B8 +#define WM8962_WRITE_SEQUENCER_185 0x10B9 +#define WM8962_WRITE_SEQUENCER_186 0x10BA +#define WM8962_WRITE_SEQUENCER_187 0x10BB +#define WM8962_WRITE_SEQUENCER_188 0x10BC +#define WM8962_WRITE_SEQUENCER_189 0x10BD +#define WM8962_WRITE_SEQUENCER_190 0x10BE +#define WM8962_WRITE_SEQUENCER_191 0x10BF +#define WM8962_WRITE_SEQUENCER_192 0x10C0 +#define WM8962_WRITE_SEQUENCER_193 0x10C1 +#define WM8962_WRITE_SEQUENCER_194 0x10C2 +#define WM8962_WRITE_SEQUENCER_195 0x10C3 +#define WM8962_WRITE_SEQUENCER_196 0x10C4 +#define WM8962_WRITE_SEQUENCER_197 0x10C5 +#define WM8962_WRITE_SEQUENCER_198 0x10C6 +#define WM8962_WRITE_SEQUENCER_199 0x10C7 +#define WM8962_WRITE_SEQUENCER_200 0x10C8 +#define WM8962_WRITE_SEQUENCER_201 0x10C9 +#define WM8962_WRITE_SEQUENCER_202 0x10CA +#define WM8962_WRITE_SEQUENCER_203 0x10CB +#define WM8962_WRITE_SEQUENCER_204 0x10CC +#define WM8962_WRITE_SEQUENCER_205 0x10CD +#define WM8962_WRITE_SEQUENCER_206 0x10CE +#define WM8962_WRITE_SEQUENCER_207 0x10CF +#define WM8962_WRITE_SEQUENCER_208 0x10D0 +#define WM8962_WRITE_SEQUENCER_209 0x10D1 +#define WM8962_WRITE_SEQUENCER_210 0x10D2 +#define WM8962_WRITE_SEQUENCER_211 0x10D3 +#define WM8962_WRITE_SEQUENCER_212 0x10D4 +#define WM8962_WRITE_SEQUENCER_213 0x10D5 +#define WM8962_WRITE_SEQUENCER_214 0x10D6 +#define WM8962_WRITE_SEQUENCER_215 0x10D7 +#define WM8962_WRITE_SEQUENCER_216 0x10D8 +#define WM8962_WRITE_SEQUENCER_217 0x10D9 +#define WM8962_WRITE_SEQUENCER_218 0x10DA +#define WM8962_WRITE_SEQUENCER_219 0x10DB +#define WM8962_WRITE_SEQUENCER_220 0x10DC +#define WM8962_WRITE_SEQUENCER_221 0x10DD +#define WM8962_WRITE_SEQUENCER_222 0x10DE +#define WM8962_WRITE_SEQUENCER_223 0x10DF +#define WM8962_WRITE_SEQUENCER_224 0x10E0 +#define WM8962_WRITE_SEQUENCER_225 0x10E1 +#define WM8962_WRITE_SEQUENCER_226 0x10E2 +#define WM8962_WRITE_SEQUENCER_227 0x10E3 +#define WM8962_WRITE_SEQUENCER_228 0x10E4 +#define WM8962_WRITE_SEQUENCER_229 0x10E5 +#define WM8962_WRITE_SEQUENCER_230 0x10E6 +#define WM8962_WRITE_SEQUENCER_231 0x10E7 +#define WM8962_WRITE_SEQUENCER_232 0x10E8 +#define WM8962_WRITE_SEQUENCER_233 0x10E9 +#define WM8962_WRITE_SEQUENCER_234 0x10EA +#define WM8962_WRITE_SEQUENCER_235 0x10EB +#define WM8962_WRITE_SEQUENCER_236 0x10EC +#define WM8962_WRITE_SEQUENCER_237 0x10ED +#define WM8962_WRITE_SEQUENCER_238 0x10EE +#define WM8962_WRITE_SEQUENCER_239 0x10EF +#define WM8962_WRITE_SEQUENCER_240 0x10F0 +#define WM8962_WRITE_SEQUENCER_241 0x10F1 +#define WM8962_WRITE_SEQUENCER_242 0x10F2 +#define WM8962_WRITE_SEQUENCER_243 0x10F3 +#define WM8962_WRITE_SEQUENCER_244 0x10F4 +#define WM8962_WRITE_SEQUENCER_245 0x10F5 +#define WM8962_WRITE_SEQUENCER_246 0x10F6 +#define WM8962_WRITE_SEQUENCER_247 0x10F7 +#define WM8962_WRITE_SEQUENCER_248 0x10F8 +#define WM8962_WRITE_SEQUENCER_249 0x10F9 +#define WM8962_WRITE_SEQUENCER_250 0x10FA +#define WM8962_WRITE_SEQUENCER_251 0x10FB +#define WM8962_WRITE_SEQUENCER_252 0x10FC +#define WM8962_WRITE_SEQUENCER_253 0x10FD +#define WM8962_WRITE_SEQUENCER_254 0x10FE +#define WM8962_WRITE_SEQUENCER_255 0x10FF +#define WM8962_WRITE_SEQUENCER_256 0x1100 +#define WM8962_WRITE_SEQUENCER_257 0x1101 +#define WM8962_WRITE_SEQUENCER_258 0x1102 +#define WM8962_WRITE_SEQUENCER_259 0x1103 +#define WM8962_WRITE_SEQUENCER_260 0x1104 +#define WM8962_WRITE_SEQUENCER_261 0x1105 +#define WM8962_WRITE_SEQUENCER_262 0x1106 +#define WM8962_WRITE_SEQUENCER_263 0x1107 +#define WM8962_WRITE_SEQUENCER_264 0x1108 +#define WM8962_WRITE_SEQUENCER_265 0x1109 +#define WM8962_WRITE_SEQUENCER_266 0x110A +#define WM8962_WRITE_SEQUENCER_267 0x110B +#define WM8962_WRITE_SEQUENCER_268 0x110C +#define WM8962_WRITE_SEQUENCER_269 0x110D +#define WM8962_WRITE_SEQUENCER_270 0x110E +#define WM8962_WRITE_SEQUENCER_271 0x110F +#define WM8962_WRITE_SEQUENCER_272 0x1110 +#define WM8962_WRITE_SEQUENCER_273 0x1111 +#define WM8962_WRITE_SEQUENCER_274 0x1112 +#define WM8962_WRITE_SEQUENCER_275 0x1113 +#define WM8962_WRITE_SEQUENCER_276 0x1114 +#define WM8962_WRITE_SEQUENCER_277 0x1115 +#define WM8962_WRITE_SEQUENCER_278 0x1116 +#define WM8962_WRITE_SEQUENCER_279 0x1117 +#define WM8962_WRITE_SEQUENCER_280 0x1118 +#define WM8962_WRITE_SEQUENCER_281 0x1119 +#define WM8962_WRITE_SEQUENCER_282 0x111A +#define WM8962_WRITE_SEQUENCER_283 0x111B +#define WM8962_WRITE_SEQUENCER_284 0x111C +#define WM8962_WRITE_SEQUENCER_285 0x111D +#define WM8962_WRITE_SEQUENCER_286 0x111E +#define WM8962_WRITE_SEQUENCER_287 0x111F +#define WM8962_WRITE_SEQUENCER_288 0x1120 +#define WM8962_WRITE_SEQUENCER_289 0x1121 +#define WM8962_WRITE_SEQUENCER_290 0x1122 +#define WM8962_WRITE_SEQUENCER_291 0x1123 +#define WM8962_WRITE_SEQUENCER_292 0x1124 +#define WM8962_WRITE_SEQUENCER_293 0x1125 +#define WM8962_WRITE_SEQUENCER_294 0x1126 +#define WM8962_WRITE_SEQUENCER_295 0x1127 +#define WM8962_WRITE_SEQUENCER_296 0x1128 +#define WM8962_WRITE_SEQUENCER_297 0x1129 +#define WM8962_WRITE_SEQUENCER_298 0x112A +#define WM8962_WRITE_SEQUENCER_299 0x112B +#define WM8962_WRITE_SEQUENCER_300 0x112C +#define WM8962_WRITE_SEQUENCER_301 0x112D +#define WM8962_WRITE_SEQUENCER_302 0x112E +#define WM8962_WRITE_SEQUENCER_303 0x112F +#define WM8962_WRITE_SEQUENCER_304 0x1130 +#define WM8962_WRITE_SEQUENCER_305 0x1131 +#define WM8962_WRITE_SEQUENCER_306 0x1132 +#define WM8962_WRITE_SEQUENCER_307 0x1133 +#define WM8962_WRITE_SEQUENCER_308 0x1134 +#define WM8962_WRITE_SEQUENCER_309 0x1135 +#define WM8962_WRITE_SEQUENCER_310 0x1136 +#define WM8962_WRITE_SEQUENCER_311 0x1137 +#define WM8962_WRITE_SEQUENCER_312 0x1138 +#define WM8962_WRITE_SEQUENCER_313 0x1139 +#define WM8962_WRITE_SEQUENCER_314 0x113A +#define WM8962_WRITE_SEQUENCER_315 0x113B +#define WM8962_WRITE_SEQUENCER_316 0x113C +#define WM8962_WRITE_SEQUENCER_317 0x113D +#define WM8962_WRITE_SEQUENCER_318 0x113E +#define WM8962_WRITE_SEQUENCER_319 0x113F +#define WM8962_WRITE_SEQUENCER_320 0x1140 +#define WM8962_WRITE_SEQUENCER_321 0x1141 +#define WM8962_WRITE_SEQUENCER_322 0x1142 +#define WM8962_WRITE_SEQUENCER_323 0x1143 +#define WM8962_WRITE_SEQUENCER_324 0x1144 +#define WM8962_WRITE_SEQUENCER_325 0x1145 +#define WM8962_WRITE_SEQUENCER_326 0x1146 +#define WM8962_WRITE_SEQUENCER_327 0x1147 +#define WM8962_WRITE_SEQUENCER_328 0x1148 +#define WM8962_WRITE_SEQUENCER_329 0x1149 +#define WM8962_WRITE_SEQUENCER_330 0x114A +#define WM8962_WRITE_SEQUENCER_331 0x114B +#define WM8962_WRITE_SEQUENCER_332 0x114C +#define WM8962_WRITE_SEQUENCER_333 0x114D +#define WM8962_WRITE_SEQUENCER_334 0x114E +#define WM8962_WRITE_SEQUENCER_335 0x114F +#define WM8962_WRITE_SEQUENCER_336 0x1150 +#define WM8962_WRITE_SEQUENCER_337 0x1151 +#define WM8962_WRITE_SEQUENCER_338 0x1152 +#define WM8962_WRITE_SEQUENCER_339 0x1153 +#define WM8962_WRITE_SEQUENCER_340 0x1154 +#define WM8962_WRITE_SEQUENCER_341 0x1155 +#define WM8962_WRITE_SEQUENCER_342 0x1156 +#define WM8962_WRITE_SEQUENCER_343 0x1157 +#define WM8962_WRITE_SEQUENCER_344 0x1158 +#define WM8962_WRITE_SEQUENCER_345 0x1159 +#define WM8962_WRITE_SEQUENCER_346 0x115A +#define WM8962_WRITE_SEQUENCER_347 0x115B +#define WM8962_WRITE_SEQUENCER_348 0x115C +#define WM8962_WRITE_SEQUENCER_349 0x115D +#define WM8962_WRITE_SEQUENCER_350 0x115E +#define WM8962_WRITE_SEQUENCER_351 0x115F +#define WM8962_WRITE_SEQUENCER_352 0x1160 +#define WM8962_WRITE_SEQUENCER_353 0x1161 +#define WM8962_WRITE_SEQUENCER_354 0x1162 +#define WM8962_WRITE_SEQUENCER_355 0x1163 +#define WM8962_WRITE_SEQUENCER_356 0x1164 +#define WM8962_WRITE_SEQUENCER_357 0x1165 +#define WM8962_WRITE_SEQUENCER_358 0x1166 +#define WM8962_WRITE_SEQUENCER_359 0x1167 +#define WM8962_WRITE_SEQUENCER_360 0x1168 +#define WM8962_WRITE_SEQUENCER_361 0x1169 +#define WM8962_WRITE_SEQUENCER_362 0x116A +#define WM8962_WRITE_SEQUENCER_363 0x116B +#define WM8962_WRITE_SEQUENCER_364 0x116C +#define WM8962_WRITE_SEQUENCER_365 0x116D +#define WM8962_WRITE_SEQUENCER_366 0x116E +#define WM8962_WRITE_SEQUENCER_367 0x116F +#define WM8962_WRITE_SEQUENCER_368 0x1170 +#define WM8962_WRITE_SEQUENCER_369 0x1171 +#define WM8962_WRITE_SEQUENCER_370 0x1172 +#define WM8962_WRITE_SEQUENCER_371 0x1173 +#define WM8962_WRITE_SEQUENCER_372 0x1174 +#define WM8962_WRITE_SEQUENCER_373 0x1175 +#define WM8962_WRITE_SEQUENCER_374 0x1176 +#define WM8962_WRITE_SEQUENCER_375 0x1177 +#define WM8962_WRITE_SEQUENCER_376 0x1178 +#define WM8962_WRITE_SEQUENCER_377 0x1179 +#define WM8962_WRITE_SEQUENCER_378 0x117A +#define WM8962_WRITE_SEQUENCER_379 0x117B +#define WM8962_WRITE_SEQUENCER_380 0x117C +#define WM8962_WRITE_SEQUENCER_381 0x117D +#define WM8962_WRITE_SEQUENCER_382 0x117E +#define WM8962_WRITE_SEQUENCER_383 0x117F +#define WM8962_WRITE_SEQUENCER_384 0x1180 +#define WM8962_WRITE_SEQUENCER_385 0x1181 +#define WM8962_WRITE_SEQUENCER_386 0x1182 +#define WM8962_WRITE_SEQUENCER_387 0x1183 +#define WM8962_WRITE_SEQUENCER_388 0x1184 +#define WM8962_WRITE_SEQUENCER_389 0x1185 +#define WM8962_WRITE_SEQUENCER_390 0x1186 +#define WM8962_WRITE_SEQUENCER_391 0x1187 +#define WM8962_WRITE_SEQUENCER_392 0x1188 +#define WM8962_WRITE_SEQUENCER_393 0x1189 +#define WM8962_WRITE_SEQUENCER_394 0x118A +#define WM8962_WRITE_SEQUENCER_395 0x118B +#define WM8962_WRITE_SEQUENCER_396 0x118C +#define WM8962_WRITE_SEQUENCER_397 0x118D +#define WM8962_WRITE_SEQUENCER_398 0x118E +#define WM8962_WRITE_SEQUENCER_399 0x118F +#define WM8962_WRITE_SEQUENCER_400 0x1190 +#define WM8962_WRITE_SEQUENCER_401 0x1191 +#define WM8962_WRITE_SEQUENCER_402 0x1192 +#define WM8962_WRITE_SEQUENCER_403 0x1193 +#define WM8962_WRITE_SEQUENCER_404 0x1194 +#define WM8962_WRITE_SEQUENCER_405 0x1195 +#define WM8962_WRITE_SEQUENCER_406 0x1196 +#define WM8962_WRITE_SEQUENCER_407 0x1197 +#define WM8962_WRITE_SEQUENCER_408 0x1198 +#define WM8962_WRITE_SEQUENCER_409 0x1199 +#define WM8962_WRITE_SEQUENCER_410 0x119A +#define WM8962_WRITE_SEQUENCER_411 0x119B +#define WM8962_WRITE_SEQUENCER_412 0x119C +#define WM8962_WRITE_SEQUENCER_413 0x119D +#define WM8962_WRITE_SEQUENCER_414 0x119E +#define WM8962_WRITE_SEQUENCER_415 0x119F +#define WM8962_WRITE_SEQUENCER_416 0x11A0 +#define WM8962_WRITE_SEQUENCER_417 0x11A1 +#define WM8962_WRITE_SEQUENCER_418 0x11A2 +#define WM8962_WRITE_SEQUENCER_419 0x11A3 +#define WM8962_WRITE_SEQUENCER_420 0x11A4 +#define WM8962_WRITE_SEQUENCER_421 0x11A5 +#define WM8962_WRITE_SEQUENCER_422 0x11A6 +#define WM8962_WRITE_SEQUENCER_423 0x11A7 +#define WM8962_WRITE_SEQUENCER_424 0x11A8 +#define WM8962_WRITE_SEQUENCER_425 0x11A9 +#define WM8962_WRITE_SEQUENCER_426 0x11AA +#define WM8962_WRITE_SEQUENCER_427 0x11AB +#define WM8962_WRITE_SEQUENCER_428 0x11AC +#define WM8962_WRITE_SEQUENCER_429 0x11AD +#define WM8962_WRITE_SEQUENCER_430 0x11AE +#define WM8962_WRITE_SEQUENCER_431 0x11AF +#define WM8962_WRITE_SEQUENCER_432 0x11B0 +#define WM8962_WRITE_SEQUENCER_433 0x11B1 +#define WM8962_WRITE_SEQUENCER_434 0x11B2 +#define WM8962_WRITE_SEQUENCER_435 0x11B3 +#define WM8962_WRITE_SEQUENCER_436 0x11B4 +#define WM8962_WRITE_SEQUENCER_437 0x11B5 +#define WM8962_WRITE_SEQUENCER_438 0x11B6 +#define WM8962_WRITE_SEQUENCER_439 0x11B7 +#define WM8962_WRITE_SEQUENCER_440 0x11B8 +#define WM8962_WRITE_SEQUENCER_441 0x11B9 +#define WM8962_WRITE_SEQUENCER_442 0x11BA +#define WM8962_WRITE_SEQUENCER_443 0x11BB +#define WM8962_WRITE_SEQUENCER_444 0x11BC +#define WM8962_WRITE_SEQUENCER_445 0x11BD +#define WM8962_WRITE_SEQUENCER_446 0x11BE +#define WM8962_WRITE_SEQUENCER_447 0x11BF +#define WM8962_WRITE_SEQUENCER_448 0x11C0 +#define WM8962_WRITE_SEQUENCER_449 0x11C1 +#define WM8962_WRITE_SEQUENCER_450 0x11C2 +#define WM8962_WRITE_SEQUENCER_451 0x11C3 +#define WM8962_WRITE_SEQUENCER_452 0x11C4 +#define WM8962_WRITE_SEQUENCER_453 0x11C5 +#define WM8962_WRITE_SEQUENCER_454 0x11C6 +#define WM8962_WRITE_SEQUENCER_455 0x11C7 +#define WM8962_WRITE_SEQUENCER_456 0x11C8 +#define WM8962_WRITE_SEQUENCER_457 0x11C9 +#define WM8962_WRITE_SEQUENCER_458 0x11CA +#define WM8962_WRITE_SEQUENCER_459 0x11CB +#define WM8962_WRITE_SEQUENCER_460 0x11CC +#define WM8962_WRITE_SEQUENCER_461 0x11CD +#define WM8962_WRITE_SEQUENCER_462 0x11CE +#define WM8962_WRITE_SEQUENCER_463 0x11CF +#define WM8962_WRITE_SEQUENCER_464 0x11D0 +#define WM8962_WRITE_SEQUENCER_465 0x11D1 +#define WM8962_WRITE_SEQUENCER_466 0x11D2 +#define WM8962_WRITE_SEQUENCER_467 0x11D3 +#define WM8962_WRITE_SEQUENCER_468 0x11D4 +#define WM8962_WRITE_SEQUENCER_469 0x11D5 +#define WM8962_WRITE_SEQUENCER_470 0x11D6 +#define WM8962_WRITE_SEQUENCER_471 0x11D7 +#define WM8962_WRITE_SEQUENCER_472 0x11D8 +#define WM8962_WRITE_SEQUENCER_473 0x11D9 +#define WM8962_WRITE_SEQUENCER_474 0x11DA +#define WM8962_WRITE_SEQUENCER_475 0x11DB +#define WM8962_WRITE_SEQUENCER_476 0x11DC +#define WM8962_WRITE_SEQUENCER_477 0x11DD +#define WM8962_WRITE_SEQUENCER_478 0x11DE +#define WM8962_WRITE_SEQUENCER_479 0x11DF +#define WM8962_WRITE_SEQUENCER_480 0x11E0 +#define WM8962_WRITE_SEQUENCER_481 0x11E1 +#define WM8962_WRITE_SEQUENCER_482 0x11E2 +#define WM8962_WRITE_SEQUENCER_483 0x11E3 +#define WM8962_WRITE_SEQUENCER_484 0x11E4 +#define WM8962_WRITE_SEQUENCER_485 0x11E5 +#define WM8962_WRITE_SEQUENCER_486 0x11E6 +#define WM8962_WRITE_SEQUENCER_487 0x11E7 +#define WM8962_WRITE_SEQUENCER_488 0x11E8 +#define WM8962_WRITE_SEQUENCER_489 0x11E9 +#define WM8962_WRITE_SEQUENCER_490 0x11EA +#define WM8962_WRITE_SEQUENCER_491 0x11EB +#define WM8962_WRITE_SEQUENCER_492 0x11EC +#define WM8962_WRITE_SEQUENCER_493 0x11ED +#define WM8962_WRITE_SEQUENCER_494 0x11EE +#define WM8962_WRITE_SEQUENCER_495 0x11EF +#define WM8962_WRITE_SEQUENCER_496 0x11F0 +#define WM8962_WRITE_SEQUENCER_497 0x11F1 +#define WM8962_WRITE_SEQUENCER_498 0x11F2 +#define WM8962_WRITE_SEQUENCER_499 0x11F3 +#define WM8962_WRITE_SEQUENCER_500 0x11F4 +#define WM8962_WRITE_SEQUENCER_501 0x11F5 +#define WM8962_WRITE_SEQUENCER_502 0x11F6 +#define WM8962_WRITE_SEQUENCER_503 0x11F7 +#define WM8962_WRITE_SEQUENCER_504 0x11F8 +#define WM8962_WRITE_SEQUENCER_505 0x11F9 +#define WM8962_WRITE_SEQUENCER_506 0x11FA +#define WM8962_WRITE_SEQUENCER_507 0x11FB +#define WM8962_WRITE_SEQUENCER_508 0x11FC +#define WM8962_WRITE_SEQUENCER_509 0x11FD +#define WM8962_WRITE_SEQUENCER_510 0x11FE +#define WM8962_WRITE_SEQUENCER_511 0x11FF +#define WM8962_DSP2_INSTRUCTION_RAM_0 0x2000 +#define WM8962_DSP2_ADDRESS_RAM_2 0x2400 +#define WM8962_DSP2_ADDRESS_RAM_1 0x2401 +#define WM8962_DSP2_ADDRESS_RAM_0 0x2402 +#define WM8962_DSP2_DATA1_RAM_1 0x3000 +#define WM8962_DSP2_DATA1_RAM_0 0x3001 +#define WM8962_DSP2_DATA2_RAM_1 0x3400 +#define WM8962_DSP2_DATA2_RAM_0 0x3401 +#define WM8962_DSP2_DATA3_RAM_1 0x3800 +#define WM8962_DSP2_DATA3_RAM_0 0x3801 +#define WM8962_DSP2_COEFF_RAM_0 0x3C00 +#define WM8962_RETUNEADC_SHARED_COEFF_1 0x4000 +#define WM8962_RETUNEADC_SHARED_COEFF_0 0x4001 +#define WM8962_RETUNEDAC_SHARED_COEFF_1 0x4002 +#define WM8962_RETUNEDAC_SHARED_COEFF_0 0x4003 +#define WM8962_SOUNDSTAGE_ENABLES_1 0x4004 +#define WM8962_SOUNDSTAGE_ENABLES_0 0x4005 +#define WM8962_HDBASS_AI_1 0x4200 +#define WM8962_HDBASS_AI_0 0x4201 +#define WM8962_HDBASS_AR_1 0x4202 +#define WM8962_HDBASS_AR_0 0x4203 +#define WM8962_HDBASS_B_1 0x4204 +#define WM8962_HDBASS_B_0 0x4205 +#define WM8962_HDBASS_K_1 0x4206 +#define WM8962_HDBASS_K_0 0x4207 +#define WM8962_HDBASS_N1_1 0x4208 +#define WM8962_HDBASS_N1_0 0x4209 +#define WM8962_HDBASS_N2_1 0x420A +#define WM8962_HDBASS_N2_0 0x420B +#define WM8962_HDBASS_N3_1 0x420C +#define WM8962_HDBASS_N3_0 0x420D +#define WM8962_HDBASS_N4_1 0x420E +#define WM8962_HDBASS_N4_0 0x420F +#define WM8962_HDBASS_N5_1 0x4210 +#define WM8962_HDBASS_N5_0 0x4211 +#define WM8962_HDBASS_X1_1 0x4212 +#define WM8962_HDBASS_X1_0 0x4213 +#define WM8962_HDBASS_X2_1 0x4214 +#define WM8962_HDBASS_X2_0 0x4215 +#define WM8962_HDBASS_X3_1 0x4216 +#define WM8962_HDBASS_X3_0 0x4217 +#define WM8962_HDBASS_ATK_1 0x4218 +#define WM8962_HDBASS_ATK_0 0x4219 +#define WM8962_HDBASS_DCY_1 0x421A +#define WM8962_HDBASS_DCY_0 0x421B +#define WM8962_HDBASS_PG_1 0x421C +#define WM8962_HDBASS_PG_0 0x421D +#define WM8962_HPF_C_1 0x4400 +#define WM8962_HPF_C_0 0x4401 +#define WM8962_ADCL_RETUNE_C1_1 0x4600 +#define WM8962_ADCL_RETUNE_C1_0 0x4601 +#define WM8962_ADCL_RETUNE_C2_1 0x4602 +#define WM8962_ADCL_RETUNE_C2_0 0x4603 +#define WM8962_ADCL_RETUNE_C3_1 0x4604 +#define WM8962_ADCL_RETUNE_C3_0 0x4605 +#define WM8962_ADCL_RETUNE_C4_1 0x4606 +#define WM8962_ADCL_RETUNE_C4_0 0x4607 +#define WM8962_ADCL_RETUNE_C5_1 0x4608 +#define WM8962_ADCL_RETUNE_C5_0 0x4609 +#define WM8962_ADCL_RETUNE_C6_1 0x460A +#define WM8962_ADCL_RETUNE_C6_0 0x460B +#define WM8962_ADCL_RETUNE_C7_1 0x460C +#define WM8962_ADCL_RETUNE_C7_0 0x460D +#define WM8962_ADCL_RETUNE_C8_1 0x460E +#define WM8962_ADCL_RETUNE_C8_0 0x460F +#define WM8962_ADCL_RETUNE_C9_1 0x4610 +#define WM8962_ADCL_RETUNE_C9_0 0x4611 +#define WM8962_ADCL_RETUNE_C10_1 0x4612 +#define WM8962_ADCL_RETUNE_C10_0 0x4613 +#define WM8962_ADCL_RETUNE_C11_1 0x4614 +#define WM8962_ADCL_RETUNE_C11_0 0x4615 +#define WM8962_ADCL_RETUNE_C12_1 0x4616 +#define WM8962_ADCL_RETUNE_C12_0 0x4617 +#define WM8962_ADCL_RETUNE_C13_1 0x4618 +#define WM8962_ADCL_RETUNE_C13_0 0x4619 +#define WM8962_ADCL_RETUNE_C14_1 0x461A +#define WM8962_ADCL_RETUNE_C14_0 0x461B +#define WM8962_ADCL_RETUNE_C15_1 0x461C +#define WM8962_ADCL_RETUNE_C15_0 0x461D +#define WM8962_ADCL_RETUNE_C16_1 0x461E +#define WM8962_ADCL_RETUNE_C16_0 0x461F +#define WM8962_ADCL_RETUNE_C17_1 0x4620 +#define WM8962_ADCL_RETUNE_C17_0 0x4621 +#define WM8962_ADCL_RETUNE_C18_1 0x4622 +#define WM8962_ADCL_RETUNE_C18_0 0x4623 +#define WM8962_ADCL_RETUNE_C19_1 0x4624 +#define WM8962_ADCL_RETUNE_C19_0 0x4625 +#define WM8962_ADCL_RETUNE_C20_1 0x4626 +#define WM8962_ADCL_RETUNE_C20_0 0x4627 +#define WM8962_ADCL_RETUNE_C21_1 0x4628 +#define WM8962_ADCL_RETUNE_C21_0 0x4629 +#define WM8962_ADCL_RETUNE_C22_1 0x462A +#define WM8962_ADCL_RETUNE_C22_0 0x462B +#define WM8962_ADCL_RETUNE_C23_1 0x462C +#define WM8962_ADCL_RETUNE_C23_0 0x462D +#define WM8962_ADCL_RETUNE_C24_1 0x462E +#define WM8962_ADCL_RETUNE_C24_0 0x462F +#define WM8962_ADCL_RETUNE_C25_1 0x4630 +#define WM8962_ADCL_RETUNE_C25_0 0x4631 +#define WM8962_ADCL_RETUNE_C26_1 0x4632 +#define WM8962_ADCL_RETUNE_C26_0 0x4633 +#define WM8962_ADCL_RETUNE_C27_1 0x4634 +#define WM8962_ADCL_RETUNE_C27_0 0x4635 +#define WM8962_ADCL_RETUNE_C28_1 0x4636 +#define WM8962_ADCL_RETUNE_C28_0 0x4637 +#define WM8962_ADCL_RETUNE_C29_1 0x4638 +#define WM8962_ADCL_RETUNE_C29_0 0x4639 +#define WM8962_ADCL_RETUNE_C30_1 0x463A +#define WM8962_ADCL_RETUNE_C30_0 0x463B +#define WM8962_ADCL_RETUNE_C31_1 0x463C +#define WM8962_ADCL_RETUNE_C31_0 0x463D +#define WM8962_ADCL_RETUNE_C32_1 0x463E +#define WM8962_ADCL_RETUNE_C32_0 0x463F +#define WM8962_RETUNEADC_PG2_1 0x4800 +#define WM8962_RETUNEADC_PG2_0 0x4801 +#define WM8962_RETUNEADC_PG_1 0x4802 +#define WM8962_RETUNEADC_PG_0 0x4803 +#define WM8962_ADCR_RETUNE_C1_1 0x4A00 +#define WM8962_ADCR_RETUNE_C1_0 0x4A01 +#define WM8962_ADCR_RETUNE_C2_1 0x4A02 +#define WM8962_ADCR_RETUNE_C2_0 0x4A03 +#define WM8962_ADCR_RETUNE_C3_1 0x4A04 +#define WM8962_ADCR_RETUNE_C3_0 0x4A05 +#define WM8962_ADCR_RETUNE_C4_1 0x4A06 +#define WM8962_ADCR_RETUNE_C4_0 0x4A07 +#define WM8962_ADCR_RETUNE_C5_1 0x4A08 +#define WM8962_ADCR_RETUNE_C5_0 0x4A09 +#define WM8962_ADCR_RETUNE_C6_1 0x4A0A +#define WM8962_ADCR_RETUNE_C6_0 0x4A0B +#define WM8962_ADCR_RETUNE_C7_1 0x4A0C +#define WM8962_ADCR_RETUNE_C7_0 0x4A0D +#define WM8962_ADCR_RETUNE_C8_1 0x4A0E +#define WM8962_ADCR_RETUNE_C8_0 0x4A0F +#define WM8962_ADCR_RETUNE_C9_1 0x4A10 +#define WM8962_ADCR_RETUNE_C9_0 0x4A11 +#define WM8962_ADCR_RETUNE_C10_1 0x4A12 +#define WM8962_ADCR_RETUNE_C10_0 0x4A13 +#define WM8962_ADCR_RETUNE_C11_1 0x4A14 +#define WM8962_ADCR_RETUNE_C11_0 0x4A15 +#define WM8962_ADCR_RETUNE_C12_1 0x4A16 +#define WM8962_ADCR_RETUNE_C12_0 0x4A17 +#define WM8962_ADCR_RETUNE_C13_1 0x4A18 +#define WM8962_ADCR_RETUNE_C13_0 0x4A19 +#define WM8962_ADCR_RETUNE_C14_1 0x4A1A +#define WM8962_ADCR_RETUNE_C14_0 0x4A1B +#define WM8962_ADCR_RETUNE_C15_1 0x4A1C +#define WM8962_ADCR_RETUNE_C15_0 0x4A1D +#define WM8962_ADCR_RETUNE_C16_1 0x4A1E +#define WM8962_ADCR_RETUNE_C16_0 0x4A1F +#define WM8962_ADCR_RETUNE_C17_1 0x4A20 +#define WM8962_ADCR_RETUNE_C17_0 0x4A21 +#define WM8962_ADCR_RETUNE_C18_1 0x4A22 +#define WM8962_ADCR_RETUNE_C18_0 0x4A23 +#define WM8962_ADCR_RETUNE_C19_1 0x4A24 +#define WM8962_ADCR_RETUNE_C19_0 0x4A25 +#define WM8962_ADCR_RETUNE_C20_1 0x4A26 +#define WM8962_ADCR_RETUNE_C20_0 0x4A27 +#define WM8962_ADCR_RETUNE_C21_1 0x4A28 +#define WM8962_ADCR_RETUNE_C21_0 0x4A29 +#define WM8962_ADCR_RETUNE_C22_1 0x4A2A +#define WM8962_ADCR_RETUNE_C22_0 0x4A2B +#define WM8962_ADCR_RETUNE_C23_1 0x4A2C +#define WM8962_ADCR_RETUNE_C23_0 0x4A2D +#define WM8962_ADCR_RETUNE_C24_1 0x4A2E +#define WM8962_ADCR_RETUNE_C24_0 0x4A2F +#define WM8962_ADCR_RETUNE_C25_1 0x4A30 +#define WM8962_ADCR_RETUNE_C25_0 0x4A31 +#define WM8962_ADCR_RETUNE_C26_1 0x4A32 +#define WM8962_ADCR_RETUNE_C26_0 0x4A33 +#define WM8962_ADCR_RETUNE_C27_1 0x4A34 +#define WM8962_ADCR_RETUNE_C27_0 0x4A35 +#define WM8962_ADCR_RETUNE_C28_1 0x4A36 +#define WM8962_ADCR_RETUNE_C28_0 0x4A37 +#define WM8962_ADCR_RETUNE_C29_1 0x4A38 +#define WM8962_ADCR_RETUNE_C29_0 0x4A39 +#define WM8962_ADCR_RETUNE_C30_1 0x4A3A +#define WM8962_ADCR_RETUNE_C30_0 0x4A3B +#define WM8962_ADCR_RETUNE_C31_1 0x4A3C +#define WM8962_ADCR_RETUNE_C31_0 0x4A3D +#define WM8962_ADCR_RETUNE_C32_1 0x4A3E +#define WM8962_ADCR_RETUNE_C32_0 0x4A3F +#define WM8962_DACL_RETUNE_C1_1 0x4C00 +#define WM8962_DACL_RETUNE_C1_0 0x4C01 +#define WM8962_DACL_RETUNE_C2_1 0x4C02 +#define WM8962_DACL_RETUNE_C2_0 0x4C03 +#define WM8962_DACL_RETUNE_C3_1 0x4C04 +#define WM8962_DACL_RETUNE_C3_0 0x4C05 +#define WM8962_DACL_RETUNE_C4_1 0x4C06 +#define WM8962_DACL_RETUNE_C4_0 0x4C07 +#define WM8962_DACL_RETUNE_C5_1 0x4C08 +#define WM8962_DACL_RETUNE_C5_0 0x4C09 +#define WM8962_DACL_RETUNE_C6_1 0x4C0A +#define WM8962_DACL_RETUNE_C6_0 0x4C0B +#define WM8962_DACL_RETUNE_C7_1 0x4C0C +#define WM8962_DACL_RETUNE_C7_0 0x4C0D +#define WM8962_DACL_RETUNE_C8_1 0x4C0E +#define WM8962_DACL_RETUNE_C8_0 0x4C0F +#define WM8962_DACL_RETUNE_C9_1 0x4C10 +#define WM8962_DACL_RETUNE_C9_0 0x4C11 +#define WM8962_DACL_RETUNE_C10_1 0x4C12 +#define WM8962_DACL_RETUNE_C10_0 0x4C13 +#define WM8962_DACL_RETUNE_C11_1 0x4C14 +#define WM8962_DACL_RETUNE_C11_0 0x4C15 +#define WM8962_DACL_RETUNE_C12_1 0x4C16 +#define WM8962_DACL_RETUNE_C12_0 0x4C17 +#define WM8962_DACL_RETUNE_C13_1 0x4C18 +#define WM8962_DACL_RETUNE_C13_0 0x4C19 +#define WM8962_DACL_RETUNE_C14_1 0x4C1A +#define WM8962_DACL_RETUNE_C14_0 0x4C1B +#define WM8962_DACL_RETUNE_C15_1 0x4C1C +#define WM8962_DACL_RETUNE_C15_0 0x4C1D +#define WM8962_DACL_RETUNE_C16_1 0x4C1E +#define WM8962_DACL_RETUNE_C16_0 0x4C1F +#define WM8962_DACL_RETUNE_C17_1 0x4C20 +#define WM8962_DACL_RETUNE_C17_0 0x4C21 +#define WM8962_DACL_RETUNE_C18_1 0x4C22 +#define WM8962_DACL_RETUNE_C18_0 0x4C23 +#define WM8962_DACL_RETUNE_C19_1 0x4C24 +#define WM8962_DACL_RETUNE_C19_0 0x4C25 +#define WM8962_DACL_RETUNE_C20_1 0x4C26 +#define WM8962_DACL_RETUNE_C20_0 0x4C27 +#define WM8962_DACL_RETUNE_C21_1 0x4C28 +#define WM8962_DACL_RETUNE_C21_0 0x4C29 +#define WM8962_DACL_RETUNE_C22_1 0x4C2A +#define WM8962_DACL_RETUNE_C22_0 0x4C2B +#define WM8962_DACL_RETUNE_C23_1 0x4C2C +#define WM8962_DACL_RETUNE_C23_0 0x4C2D +#define WM8962_DACL_RETUNE_C24_1 0x4C2E +#define WM8962_DACL_RETUNE_C24_0 0x4C2F +#define WM8962_DACL_RETUNE_C25_1 0x4C30 +#define WM8962_DACL_RETUNE_C25_0 0x4C31 +#define WM8962_DACL_RETUNE_C26_1 0x4C32 +#define WM8962_DACL_RETUNE_C26_0 0x4C33 +#define WM8962_DACL_RETUNE_C27_1 0x4C34 +#define WM8962_DACL_RETUNE_C27_0 0x4C35 +#define WM8962_DACL_RETUNE_C28_1 0x4C36 +#define WM8962_DACL_RETUNE_C28_0 0x4C37 +#define WM8962_DACL_RETUNE_C29_1 0x4C38 +#define WM8962_DACL_RETUNE_C29_0 0x4C39 +#define WM8962_DACL_RETUNE_C30_1 0x4C3A +#define WM8962_DACL_RETUNE_C30_0 0x4C3B +#define WM8962_DACL_RETUNE_C31_1 0x4C3C +#define WM8962_DACL_RETUNE_C31_0 0x4C3D +#define WM8962_DACL_RETUNE_C32_1 0x4C3E +#define WM8962_DACL_RETUNE_C32_0 0x4C3F +#define WM8962_RETUNEDAC_PG2_1 0x4E00 +#define WM8962_RETUNEDAC_PG2_0 0x4E01 +#define WM8962_RETUNEDAC_PG_1 0x4E02 +#define WM8962_RETUNEDAC_PG_0 0x4E03 +#define WM8962_DACR_RETUNE_C1_1 0x5000 +#define WM8962_DACR_RETUNE_C1_0 0x5001 +#define WM8962_DACR_RETUNE_C2_1 0x5002 +#define WM8962_DACR_RETUNE_C2_0 0x5003 +#define WM8962_DACR_RETUNE_C3_1 0x5004 +#define WM8962_DACR_RETUNE_C3_0 0x5005 +#define WM8962_DACR_RETUNE_C4_1 0x5006 +#define WM8962_DACR_RETUNE_C4_0 0x5007 +#define WM8962_DACR_RETUNE_C5_1 0x5008 +#define WM8962_DACR_RETUNE_C5_0 0x5009 +#define WM8962_DACR_RETUNE_C6_1 0x500A +#define WM8962_DACR_RETUNE_C6_0 0x500B +#define WM8962_DACR_RETUNE_C7_1 0x500C +#define WM8962_DACR_RETUNE_C7_0 0x500D +#define WM8962_DACR_RETUNE_C8_1 0x500E +#define WM8962_DACR_RETUNE_C8_0 0x500F +#define WM8962_DACR_RETUNE_C9_1 0x5010 +#define WM8962_DACR_RETUNE_C9_0 0x5011 +#define WM8962_DACR_RETUNE_C10_1 0x5012 +#define WM8962_DACR_RETUNE_C10_0 0x5013 +#define WM8962_DACR_RETUNE_C11_1 0x5014 +#define WM8962_DACR_RETUNE_C11_0 0x5015 +#define WM8962_DACR_RETUNE_C12_1 0x5016 +#define WM8962_DACR_RETUNE_C12_0 0x5017 +#define WM8962_DACR_RETUNE_C13_1 0x5018 +#define WM8962_DACR_RETUNE_C13_0 0x5019 +#define WM8962_DACR_RETUNE_C14_1 0x501A +#define WM8962_DACR_RETUNE_C14_0 0x501B +#define WM8962_DACR_RETUNE_C15_1 0x501C +#define WM8962_DACR_RETUNE_C15_0 0x501D +#define WM8962_DACR_RETUNE_C16_1 0x501E +#define WM8962_DACR_RETUNE_C16_0 0x501F +#define WM8962_DACR_RETUNE_C17_1 0x5020 +#define WM8962_DACR_RETUNE_C17_0 0x5021 +#define WM8962_DACR_RETUNE_C18_1 0x5022 +#define WM8962_DACR_RETUNE_C18_0 0x5023 +#define WM8962_DACR_RETUNE_C19_1 0x5024 +#define WM8962_DACR_RETUNE_C19_0 0x5025 +#define WM8962_DACR_RETUNE_C20_1 0x5026 +#define WM8962_DACR_RETUNE_C20_0 0x5027 +#define WM8962_DACR_RETUNE_C21_1 0x5028 +#define WM8962_DACR_RETUNE_C21_0 0x5029 +#define WM8962_DACR_RETUNE_C22_1 0x502A +#define WM8962_DACR_RETUNE_C22_0 0x502B +#define WM8962_DACR_RETUNE_C23_1 0x502C +#define WM8962_DACR_RETUNE_C23_0 0x502D +#define WM8962_DACR_RETUNE_C24_1 0x502E +#define WM8962_DACR_RETUNE_C24_0 0x502F +#define WM8962_DACR_RETUNE_C25_1 0x5030 +#define WM8962_DACR_RETUNE_C25_0 0x5031 +#define WM8962_DACR_RETUNE_C26_1 0x5032 +#define WM8962_DACR_RETUNE_C26_0 0x5033 +#define WM8962_DACR_RETUNE_C27_1 0x5034 +#define WM8962_DACR_RETUNE_C27_0 0x5035 +#define WM8962_DACR_RETUNE_C28_1 0x5036 +#define WM8962_DACR_RETUNE_C28_0 0x5037 +#define WM8962_DACR_RETUNE_C29_1 0x5038 +#define WM8962_DACR_RETUNE_C29_0 0x5039 +#define WM8962_DACR_RETUNE_C30_1 0x503A +#define WM8962_DACR_RETUNE_C30_0 0x503B +#define WM8962_DACR_RETUNE_C31_1 0x503C +#define WM8962_DACR_RETUNE_C31_0 0x503D +#define WM8962_DACR_RETUNE_C32_1 0x503E +#define WM8962_DACR_RETUNE_C32_0 0x503F +#define WM8962_VSS_XHD2_1 0x5200 +#define WM8962_VSS_XHD2_0 0x5201 +#define WM8962_VSS_XHD3_1 0x5202 +#define WM8962_VSS_XHD3_0 0x5203 +#define WM8962_VSS_XHN1_1 0x5204 +#define WM8962_VSS_XHN1_0 0x5205 +#define WM8962_VSS_XHN2_1 0x5206 +#define WM8962_VSS_XHN2_0 0x5207 +#define WM8962_VSS_XHN3_1 0x5208 +#define WM8962_VSS_XHN3_0 0x5209 +#define WM8962_VSS_XLA_1 0x520A +#define WM8962_VSS_XLA_0 0x520B +#define WM8962_VSS_XLB_1 0x520C +#define WM8962_VSS_XLB_0 0x520D +#define WM8962_VSS_XLG_1 0x520E +#define WM8962_VSS_XLG_0 0x520F +#define WM8962_VSS_PG2_1 0x5210 +#define WM8962_VSS_PG2_0 0x5211 +#define WM8962_VSS_PG_1 0x5212 +#define WM8962_VSS_PG_0 0x5213 +#define WM8962_VSS_XTD1_1 0x5214 +#define WM8962_VSS_XTD1_0 0x5215 +#define WM8962_VSS_XTD2_1 0x5216 +#define WM8962_VSS_XTD2_0 0x5217 +#define WM8962_VSS_XTD3_1 0x5218 +#define WM8962_VSS_XTD3_0 0x5219 +#define WM8962_VSS_XTD4_1 0x521A +#define WM8962_VSS_XTD4_0 0x521B +#define WM8962_VSS_XTD5_1 0x521C +#define WM8962_VSS_XTD5_0 0x521D +#define WM8962_VSS_XTD6_1 0x521E +#define WM8962_VSS_XTD6_0 0x521F +#define WM8962_VSS_XTD7_1 0x5220 +#define WM8962_VSS_XTD7_0 0x5221 +#define WM8962_VSS_XTD8_1 0x5222 +#define WM8962_VSS_XTD8_0 0x5223 +#define WM8962_VSS_XTD9_1 0x5224 +#define WM8962_VSS_XTD9_0 0x5225 +#define WM8962_VSS_XTD10_1 0x5226 +#define WM8962_VSS_XTD10_0 0x5227 +#define WM8962_VSS_XTD11_1 0x5228 +#define WM8962_VSS_XTD11_0 0x5229 +#define WM8962_VSS_XTD12_1 0x522A +#define WM8962_VSS_XTD12_0 0x522B +#define WM8962_VSS_XTD13_1 0x522C +#define WM8962_VSS_XTD13_0 0x522D +#define WM8962_VSS_XTD14_1 0x522E +#define WM8962_VSS_XTD14_0 0x522F +#define WM8962_VSS_XTD15_1 0x5230 +#define WM8962_VSS_XTD15_0 0x5231 +#define WM8962_VSS_XTD16_1 0x5232 +#define WM8962_VSS_XTD16_0 0x5233 +#define WM8962_VSS_XTD17_1 0x5234 +#define WM8962_VSS_XTD17_0 0x5235 +#define WM8962_VSS_XTD18_1 0x5236 +#define WM8962_VSS_XTD18_0 0x5237 +#define WM8962_VSS_XTD19_1 0x5238 +#define WM8962_VSS_XTD19_0 0x5239 +#define WM8962_VSS_XTD20_1 0x523A +#define WM8962_VSS_XTD20_0 0x523B +#define WM8962_VSS_XTD21_1 0x523C +#define WM8962_VSS_XTD21_0 0x523D +#define WM8962_VSS_XTD22_1 0x523E +#define WM8962_VSS_XTD22_0 0x523F +#define WM8962_VSS_XTD23_1 0x5240 +#define WM8962_VSS_XTD23_0 0x5241 +#define WM8962_VSS_XTD24_1 0x5242 +#define WM8962_VSS_XTD24_0 0x5243 +#define WM8962_VSS_XTD25_1 0x5244 +#define WM8962_VSS_XTD25_0 0x5245 +#define WM8962_VSS_XTD26_1 0x5246 +#define WM8962_VSS_XTD26_0 0x5247 +#define WM8962_VSS_XTD27_1 0x5248 +#define WM8962_VSS_XTD27_0 0x5249 +#define WM8962_VSS_XTD28_1 0x524A +#define WM8962_VSS_XTD28_0 0x524B +#define WM8962_VSS_XTD29_1 0x524C +#define WM8962_VSS_XTD29_0 0x524D +#define WM8962_VSS_XTD30_1 0x524E +#define WM8962_VSS_XTD30_0 0x524F +#define WM8962_VSS_XTD31_1 0x5250 +#define WM8962_VSS_XTD31_0 0x5251 +#define WM8962_VSS_XTD32_1 0x5252 +#define WM8962_VSS_XTD32_0 0x5253 +#define WM8962_VSS_XTS1_1 0x5254 +#define WM8962_VSS_XTS1_0 0x5255 +#define WM8962_VSS_XTS2_1 0x5256 +#define WM8962_VSS_XTS2_0 0x5257 +#define WM8962_VSS_XTS3_1 0x5258 +#define WM8962_VSS_XTS3_0 0x5259 +#define WM8962_VSS_XTS4_1 0x525A +#define WM8962_VSS_XTS4_0 0x525B +#define WM8962_VSS_XTS5_1 0x525C +#define WM8962_VSS_XTS5_0 0x525D +#define WM8962_VSS_XTS6_1 0x525E +#define WM8962_VSS_XTS6_0 0x525F +#define WM8962_VSS_XTS7_1 0x5260 +#define WM8962_VSS_XTS7_0 0x5261 +#define WM8962_VSS_XTS8_1 0x5262 +#define WM8962_VSS_XTS8_0 0x5263 +#define WM8962_VSS_XTS9_1 0x5264 +#define WM8962_VSS_XTS9_0 0x5265 +#define WM8962_VSS_XTS10_1 0x5266 +#define WM8962_VSS_XTS10_0 0x5267 +#define WM8962_VSS_XTS11_1 0x5268 +#define WM8962_VSS_XTS11_0 0x5269 +#define WM8962_VSS_XTS12_1 0x526A +#define WM8962_VSS_XTS12_0 0x526B +#define WM8962_VSS_XTS13_1 0x526C +#define WM8962_VSS_XTS13_0 0x526D +#define WM8962_VSS_XTS14_1 0x526E +#define WM8962_VSS_XTS14_0 0x526F +#define WM8962_VSS_XTS15_1 0x5270 +#define WM8962_VSS_XTS15_0 0x5271 +#define WM8962_VSS_XTS16_1 0x5272 +#define WM8962_VSS_XTS16_0 0x5273 +#define WM8962_VSS_XTS17_1 0x5274 +#define WM8962_VSS_XTS17_0 0x5275 +#define WM8962_VSS_XTS18_1 0x5276 +#define WM8962_VSS_XTS18_0 0x5277 +#define WM8962_VSS_XTS19_1 0x5278 +#define WM8962_VSS_XTS19_0 0x5279 +#define WM8962_VSS_XTS20_1 0x527A +#define WM8962_VSS_XTS20_0 0x527B +#define WM8962_VSS_XTS21_1 0x527C +#define WM8962_VSS_XTS21_0 0x527D +#define WM8962_VSS_XTS22_1 0x527E +#define WM8962_VSS_XTS22_0 0x527F +#define WM8962_VSS_XTS23_1 0x5280 +#define WM8962_VSS_XTS23_0 0x5281 +#define WM8962_VSS_XTS24_1 0x5282 +#define WM8962_VSS_XTS24_0 0x5283 +#define WM8962_VSS_XTS25_1 0x5284 +#define WM8962_VSS_XTS25_0 0x5285 +#define WM8962_VSS_XTS26_1 0x5286 +#define WM8962_VSS_XTS26_0 0x5287 +#define WM8962_VSS_XTS27_1 0x5288 +#define WM8962_VSS_XTS27_0 0x5289 +#define WM8962_VSS_XTS28_1 0x528A +#define WM8962_VSS_XTS28_0 0x528B +#define WM8962_VSS_XTS29_1 0x528C +#define WM8962_VSS_XTS29_0 0x528D +#define WM8962_VSS_XTS30_1 0x528E +#define WM8962_VSS_XTS30_0 0x528F +#define WM8962_VSS_XTS31_1 0x5290 +#define WM8962_VSS_XTS31_0 0x5291 +#define WM8962_VSS_XTS32_1 0x5292 +#define WM8962_VSS_XTS32_0 0x5293 + +#define WM8962_REGISTER_COUNT 1138 +#define WM8962_MAX_REGISTER 0x5293 + +/* + * Field Definitions. + */ + +/* + * R0 (0x00) - Left Input volume + */ +#define WM8962_IN_VU 0x0100 /* IN_VU */ +#define WM8962_IN_VU_MASK 0x0100 /* IN_VU */ +#define WM8962_IN_VU_SHIFT 8 /* IN_VU */ +#define WM8962_IN_VU_WIDTH 1 /* IN_VU */ +#define WM8962_INPGAL_MUTE 0x0080 /* INPGAL_MUTE */ +#define WM8962_INPGAL_MUTE_MASK 0x0080 /* INPGAL_MUTE */ +#define WM8962_INPGAL_MUTE_SHIFT 7 /* INPGAL_MUTE */ +#define WM8962_INPGAL_MUTE_WIDTH 1 /* INPGAL_MUTE */ +#define WM8962_INL_ZC 0x0040 /* INL_ZC */ +#define WM8962_INL_ZC_MASK 0x0040 /* INL_ZC */ +#define WM8962_INL_ZC_SHIFT 6 /* INL_ZC */ +#define WM8962_INL_ZC_WIDTH 1 /* INL_ZC */ +#define WM8962_INL_VOL_MASK 0x003F /* INL_VOL - [5:0] */ +#define WM8962_INL_VOL_SHIFT 0 /* INL_VOL - [5:0] */ +#define WM8962_INL_VOL_WIDTH 6 /* INL_VOL - [5:0] */ + +/* + * R1 (0x01) - Right Input volume + */ +#define WM8962_CUST_ID_MASK 0xF000 /* CUST_ID - [15:12] */ +#define WM8962_CUST_ID_SHIFT 12 /* CUST_ID - [15:12] */ +#define WM8962_CUST_ID_WIDTH 4 /* CUST_ID - [15:12] */ +#define WM8962_CHIP_REV_MASK 0x0E00 /* CHIP_REV - [11:9] */ +#define WM8962_CHIP_REV_SHIFT 9 /* CHIP_REV - [11:9] */ +#define WM8962_CHIP_REV_WIDTH 3 /* CHIP_REV - [11:9] */ +#define WM8962_IN_VU 0x0100 /* IN_VU */ +#define WM8962_IN_VU_MASK 0x0100 /* IN_VU */ +#define WM8962_IN_VU_SHIFT 8 /* IN_VU */ +#define WM8962_IN_VU_WIDTH 1 /* IN_VU */ +#define WM8962_INPGAR_MUTE 0x0080 /* INPGAR_MUTE */ +#define WM8962_INPGAR_MUTE_MASK 0x0080 /* INPGAR_MUTE */ +#define WM8962_INPGAR_MUTE_SHIFT 7 /* INPGAR_MUTE */ +#define WM8962_INPGAR_MUTE_WIDTH 1 /* INPGAR_MUTE */ +#define WM8962_INR_ZC 0x0040 /* INR_ZC */ +#define WM8962_INR_ZC_MASK 0x0040 /* INR_ZC */ +#define WM8962_INR_ZC_SHIFT 6 /* INR_ZC */ +#define WM8962_INR_ZC_WIDTH 1 /* INR_ZC */ +#define WM8962_INR_VOL_MASK 0x003F /* INR_VOL - [5:0] */ +#define WM8962_INR_VOL_SHIFT 0 /* INR_VOL - [5:0] */ +#define WM8962_INR_VOL_WIDTH 6 /* INR_VOL - [5:0] */ + +/* + * R2 (0x02) - HPOUTL volume + */ +#define WM8962_HPOUT_VU 0x0100 /* HPOUT_VU */ +#define WM8962_HPOUT_VU_MASK 0x0100 /* HPOUT_VU */ +#define WM8962_HPOUT_VU_SHIFT 8 /* HPOUT_VU */ +#define WM8962_HPOUT_VU_WIDTH 1 /* HPOUT_VU */ +#define WM8962_HPOUTL_ZC 0x0080 /* HPOUTL_ZC */ +#define WM8962_HPOUTL_ZC_MASK 0x0080 /* HPOUTL_ZC */ +#define WM8962_HPOUTL_ZC_SHIFT 7 /* HPOUTL_ZC */ +#define WM8962_HPOUTL_ZC_WIDTH 1 /* HPOUTL_ZC */ +#define WM8962_HPOUTL_VOL_MASK 0x007F /* HPOUTL_VOL - [6:0] */ +#define WM8962_HPOUTL_VOL_SHIFT 0 /* HPOUTL_VOL - [6:0] */ +#define WM8962_HPOUTL_VOL_WIDTH 7 /* HPOUTL_VOL - [6:0] */ + +/* + * R3 (0x03) - HPOUTR volume + */ +#define WM8962_HPOUT_VU 0x0100 /* HPOUT_VU */ +#define WM8962_HPOUT_VU_MASK 0x0100 /* HPOUT_VU */ +#define WM8962_HPOUT_VU_SHIFT 8 /* HPOUT_VU */ +#define WM8962_HPOUT_VU_WIDTH 1 /* HPOUT_VU */ +#define WM8962_HPOUTR_ZC 0x0080 /* HPOUTR_ZC */ +#define WM8962_HPOUTR_ZC_MASK 0x0080 /* HPOUTR_ZC */ +#define WM8962_HPOUTR_ZC_SHIFT 7 /* HPOUTR_ZC */ +#define WM8962_HPOUTR_ZC_WIDTH 1 /* HPOUTR_ZC */ +#define WM8962_HPOUTR_VOL_MASK 0x007F /* HPOUTR_VOL - [6:0] */ +#define WM8962_HPOUTR_VOL_SHIFT 0 /* HPOUTR_VOL - [6:0] */ +#define WM8962_HPOUTR_VOL_WIDTH 7 /* HPOUTR_VOL - [6:0] */ + +/* + * R4 (0x04) - Clocking1 + */ +#define WM8962_DSPCLK_DIV_MASK 0x0600 /* DSPCLK_DIV - [10:9] */ +#define WM8962_DSPCLK_DIV_SHIFT 9 /* DSPCLK_DIV - [10:9] */ +#define WM8962_DSPCLK_DIV_WIDTH 2 /* DSPCLK_DIV - [10:9] */ +#define WM8962_ADCSYS_CLK_DIV_MASK 0x01C0 /* ADCSYS_CLK_DIV - [8:6] */ +#define WM8962_ADCSYS_CLK_DIV_SHIFT 6 /* ADCSYS_CLK_DIV - [8:6] */ +#define WM8962_ADCSYS_CLK_DIV_WIDTH 3 /* ADCSYS_CLK_DIV - [8:6] */ +#define WM8962_DACSYS_CLK_DIV_MASK 0x0038 /* DACSYS_CLK_DIV - [5:3] */ +#define WM8962_DACSYS_CLK_DIV_SHIFT 3 /* DACSYS_CLK_DIV - [5:3] */ +#define WM8962_DACSYS_CLK_DIV_WIDTH 3 /* DACSYS_CLK_DIV - [5:3] */ +#define WM8962_MCLKDIV_MASK 0x0006 /* MCLKDIV - [2:1] */ +#define WM8962_MCLKDIV_SHIFT 1 /* MCLKDIV - [2:1] */ +#define WM8962_MCLKDIV_WIDTH 2 /* MCLKDIV - [2:1] */ + +/* + * R5 (0x05) - ADC & DAC Control 1 + */ +#define WM8962_ADCR_DAT_INV 0x0040 /* ADCR_DAT_INV */ +#define WM8962_ADCR_DAT_INV_MASK 0x0040 /* ADCR_DAT_INV */ +#define WM8962_ADCR_DAT_INV_SHIFT 6 /* ADCR_DAT_INV */ +#define WM8962_ADCR_DAT_INV_WIDTH 1 /* ADCR_DAT_INV */ +#define WM8962_ADCL_DAT_INV 0x0020 /* ADCL_DAT_INV */ +#define WM8962_ADCL_DAT_INV_MASK 0x0020 /* ADCL_DAT_INV */ +#define WM8962_ADCL_DAT_INV_SHIFT 5 /* ADCL_DAT_INV */ +#define WM8962_ADCL_DAT_INV_WIDTH 1 /* ADCL_DAT_INV */ +#define WM8962_DAC_MUTE_RAMP 0x0010 /* DAC_MUTE_RAMP */ +#define WM8962_DAC_MUTE_RAMP_MASK 0x0010 /* DAC_MUTE_RAMP */ +#define WM8962_DAC_MUTE_RAMP_SHIFT 4 /* DAC_MUTE_RAMP */ +#define WM8962_DAC_MUTE_RAMP_WIDTH 1 /* DAC_MUTE_RAMP */ +#define WM8962_DAC_MUTE 0x0008 /* DAC_MUTE */ +#define WM8962_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */ +#define WM8962_DAC_MUTE_SHIFT 3 /* DAC_MUTE */ +#define WM8962_DAC_MUTE_WIDTH 1 /* DAC_MUTE */ +#define WM8962_DAC_DEEMP_MASK 0x0006 /* DAC_DEEMP - [2:1] */ +#define WM8962_DAC_DEEMP_SHIFT 1 /* DAC_DEEMP - [2:1] */ +#define WM8962_DAC_DEEMP_WIDTH 2 /* DAC_DEEMP - [2:1] */ +#define WM8962_ADC_HPF_DIS 0x0001 /* ADC_HPF_DIS */ +#define WM8962_ADC_HPF_DIS_MASK 0x0001 /* ADC_HPF_DIS */ +#define WM8962_ADC_HPF_DIS_SHIFT 0 /* ADC_HPF_DIS */ +#define WM8962_ADC_HPF_DIS_WIDTH 1 /* ADC_HPF_DIS */ + +/* + * R6 (0x06) - ADC & DAC Control 2 + */ +#define WM8962_ADC_HPF_SR_MASK 0x3000 /* ADC_HPF_SR - [13:12] */ +#define WM8962_ADC_HPF_SR_SHIFT 12 /* ADC_HPF_SR - [13:12] */ +#define WM8962_ADC_HPF_SR_WIDTH 2 /* ADC_HPF_SR - [13:12] */ +#define WM8962_ADC_HPF_MODE 0x0400 /* ADC_HPF_MODE */ +#define WM8962_ADC_HPF_MODE_MASK 0x0400 /* ADC_HPF_MODE */ +#define WM8962_ADC_HPF_MODE_SHIFT 10 /* ADC_HPF_MODE */ +#define WM8962_ADC_HPF_MODE_WIDTH 1 /* ADC_HPF_MODE */ +#define WM8962_ADC_HPF_CUT_MASK 0x0380 /* ADC_HPF_CUT - [9:7] */ +#define WM8962_ADC_HPF_CUT_SHIFT 7 /* ADC_HPF_CUT - [9:7] */ +#define WM8962_ADC_HPF_CUT_WIDTH 3 /* ADC_HPF_CUT - [9:7] */ +#define WM8962_DACR_DAT_INV 0x0040 /* DACR_DAT_INV */ +#define WM8962_DACR_DAT_INV_MASK 0x0040 /* DACR_DAT_INV */ +#define WM8962_DACR_DAT_INV_SHIFT 6 /* DACR_DAT_INV */ +#define WM8962_DACR_DAT_INV_WIDTH 1 /* DACR_DAT_INV */ +#define WM8962_DACL_DAT_INV 0x0020 /* DACL_DAT_INV */ +#define WM8962_DACL_DAT_INV_MASK 0x0020 /* DACL_DAT_INV */ +#define WM8962_DACL_DAT_INV_SHIFT 5 /* DACL_DAT_INV */ +#define WM8962_DACL_DAT_INV_WIDTH 1 /* DACL_DAT_INV */ +#define WM8962_DAC_UNMUTE_RAMP 0x0008 /* DAC_UNMUTE_RAMP */ +#define WM8962_DAC_UNMUTE_RAMP_MASK 0x0008 /* DAC_UNMUTE_RAMP */ +#define WM8962_DAC_UNMUTE_RAMP_SHIFT 3 /* DAC_UNMUTE_RAMP */ +#define WM8962_DAC_UNMUTE_RAMP_WIDTH 1 /* DAC_UNMUTE_RAMP */ +#define WM8962_DAC_MUTERATE 0x0004 /* DAC_MUTERATE */ +#define WM8962_DAC_MUTERATE_MASK 0x0004 /* DAC_MUTERATE */ +#define WM8962_DAC_MUTERATE_SHIFT 2 /* DAC_MUTERATE */ +#define WM8962_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ +#define WM8962_DAC_HP 0x0001 /* DAC_HP */ +#define WM8962_DAC_HP_MASK 0x0001 /* DAC_HP */ +#define WM8962_DAC_HP_SHIFT 0 /* DAC_HP */ +#define WM8962_DAC_HP_WIDTH 1 /* DAC_HP */ + +/* + * R7 (0x07) - Audio Interface 0 + */ +#define WM8962_AIFDAC_TDM_MODE 0x1000 /* AIFDAC_TDM_MODE */ +#define WM8962_AIFDAC_TDM_MODE_MASK 0x1000 /* AIFDAC_TDM_MODE */ +#define WM8962_AIFDAC_TDM_MODE_SHIFT 12 /* AIFDAC_TDM_MODE */ +#define WM8962_AIFDAC_TDM_MODE_WIDTH 1 /* AIFDAC_TDM_MODE */ +#define WM8962_AIFDAC_TDM_SLOT 0x0800 /* AIFDAC_TDM_SLOT */ +#define WM8962_AIFDAC_TDM_SLOT_MASK 0x0800 /* AIFDAC_TDM_SLOT */ +#define WM8962_AIFDAC_TDM_SLOT_SHIFT 11 /* AIFDAC_TDM_SLOT */ +#define WM8962_AIFDAC_TDM_SLOT_WIDTH 1 /* AIFDAC_TDM_SLOT */ +#define WM8962_AIFADC_TDM_MODE 0x0400 /* AIFADC_TDM_MODE */ +#define WM8962_AIFADC_TDM_MODE_MASK 0x0400 /* AIFADC_TDM_MODE */ +#define WM8962_AIFADC_TDM_MODE_SHIFT 10 /* AIFADC_TDM_MODE */ +#define WM8962_AIFADC_TDM_MODE_WIDTH 1 /* AIFADC_TDM_MODE */ +#define WM8962_AIFADC_TDM_SLOT 0x0200 /* AIFADC_TDM_SLOT */ +#define WM8962_AIFADC_TDM_SLOT_MASK 0x0200 /* AIFADC_TDM_SLOT */ +#define WM8962_AIFADC_TDM_SLOT_SHIFT 9 /* AIFADC_TDM_SLOT */ +#define WM8962_AIFADC_TDM_SLOT_WIDTH 1 /* AIFADC_TDM_SLOT */ +#define WM8962_ADC_LRSWAP 0x0100 /* ADC_LRSWAP */ +#define WM8962_ADC_LRSWAP_MASK 0x0100 /* ADC_LRSWAP */ +#define WM8962_ADC_LRSWAP_SHIFT 8 /* ADC_LRSWAP */ +#define WM8962_ADC_LRSWAP_WIDTH 1 /* ADC_LRSWAP */ +#define WM8962_BCLK_INV 0x0080 /* BCLK_INV */ +#define WM8962_BCLK_INV_MASK 0x0080 /* BCLK_INV */ +#define WM8962_BCLK_INV_SHIFT 7 /* BCLK_INV */ +#define WM8962_BCLK_INV_WIDTH 1 /* BCLK_INV */ +#define WM8962_MSTR 0x0040 /* MSTR */ +#define WM8962_MSTR_MASK 0x0040 /* MSTR */ +#define WM8962_MSTR_SHIFT 6 /* MSTR */ +#define WM8962_MSTR_WIDTH 1 /* MSTR */ +#define WM8962_DAC_LRSWAP 0x0020 /* DAC_LRSWAP */ +#define WM8962_DAC_LRSWAP_MASK 0x0020 /* DAC_LRSWAP */ +#define WM8962_DAC_LRSWAP_SHIFT 5 /* DAC_LRSWAP */ +#define WM8962_DAC_LRSWAP_WIDTH 1 /* DAC_LRSWAP */ +#define WM8962_LRCLK_INV 0x0010 /* LRCLK_INV */ +#define WM8962_LRCLK_INV_MASK 0x0010 /* LRCLK_INV */ +#define WM8962_LRCLK_INV_SHIFT 4 /* LRCLK_INV */ +#define WM8962_LRCLK_INV_WIDTH 1 /* LRCLK_INV */ +#define WM8962_WL_MASK 0x000C /* WL - [3:2] */ +#define WM8962_WL_SHIFT 2 /* WL - [3:2] */ +#define WM8962_WL_WIDTH 2 /* WL - [3:2] */ +#define WM8962_FMT_MASK 0x0003 /* FMT - [1:0] */ +#define WM8962_FMT_SHIFT 0 /* FMT - [1:0] */ +#define WM8962_FMT_WIDTH 2 /* FMT - [1:0] */ + +/* + * R8 (0x08) - Clocking2 + */ +#define WM8962_CLKREG_OVD 0x0800 /* CLKREG_OVD */ +#define WM8962_CLKREG_OVD_MASK 0x0800 /* CLKREG_OVD */ +#define WM8962_CLKREG_OVD_SHIFT 11 /* CLKREG_OVD */ +#define WM8962_CLKREG_OVD_WIDTH 1 /* CLKREG_OVD */ +#define WM8962_SYSCLK_SRC_MASK 0x0600 /* SYSCLK_SRC - [10:9] */ +#define WM8962_SYSCLK_SRC_SHIFT 9 /* SYSCLK_SRC - [10:9] */ +#define WM8962_SYSCLK_SRC_WIDTH 2 /* SYSCLK_SRC - [10:9] */ +#define WM8962_CLASSD_CLK_DIV_MASK 0x01C0 /* CLASSD_CLK_DIV - [8:6] */ +#define WM8962_CLASSD_CLK_DIV_SHIFT 6 /* CLASSD_CLK_DIV - [8:6] */ +#define WM8962_CLASSD_CLK_DIV_WIDTH 3 /* CLASSD_CLK_DIV - [8:6] */ +#define WM8962_SYSCLK_ENA 0x0020 /* SYSCLK_ENA */ +#define WM8962_SYSCLK_ENA_MASK 0x0020 /* SYSCLK_ENA */ +#define WM8962_SYSCLK_ENA_SHIFT 5 /* SYSCLK_ENA */ +#define WM8962_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */ +#define WM8962_BCLK_DIV_MASK 0x000F /* BCLK_DIV - [3:0] */ +#define WM8962_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [3:0] */ +#define WM8962_BCLK_DIV_WIDTH 4 /* BCLK_DIV - [3:0] */ + +/* + * R9 (0x09) - Audio Interface 1 + */ +#define WM8962_AUTOMUTE_STS 0x0800 /* AUTOMUTE_STS */ +#define WM8962_AUTOMUTE_STS_MASK 0x0800 /* AUTOMUTE_STS */ +#define WM8962_AUTOMUTE_STS_SHIFT 11 /* AUTOMUTE_STS */ +#define WM8962_AUTOMUTE_STS_WIDTH 1 /* AUTOMUTE_STS */ +#define WM8962_DAC_AUTOMUTE_SAMPLES_MASK 0x0300 /* DAC_AUTOMUTE_SAMPLES - [9:8] */ +#define WM8962_DAC_AUTOMUTE_SAMPLES_SHIFT 8 /* DAC_AUTOMUTE_SAMPLES - [9:8] */ +#define WM8962_DAC_AUTOMUTE_SAMPLES_WIDTH 2 /* DAC_AUTOMUTE_SAMPLES - [9:8] */ +#define WM8962_DAC_AUTOMUTE 0x0080 /* DAC_AUTOMUTE */ +#define WM8962_DAC_AUTOMUTE_MASK 0x0080 /* DAC_AUTOMUTE */ +#define WM8962_DAC_AUTOMUTE_SHIFT 7 /* DAC_AUTOMUTE */ +#define WM8962_DAC_AUTOMUTE_WIDTH 1 /* DAC_AUTOMUTE */ +#define WM8962_DAC_COMP 0x0010 /* DAC_COMP */ +#define WM8962_DAC_COMP_MASK 0x0010 /* DAC_COMP */ +#define WM8962_DAC_COMP_SHIFT 4 /* DAC_COMP */ +#define WM8962_DAC_COMP_WIDTH 1 /* DAC_COMP */ +#define WM8962_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */ +#define WM8962_DAC_COMPMODE_MASK 0x0008 /* DAC_COMPMODE */ +#define WM8962_DAC_COMPMODE_SHIFT 3 /* DAC_COMPMODE */ +#define WM8962_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */ +#define WM8962_ADC_COMP 0x0004 /* ADC_COMP */ +#define WM8962_ADC_COMP_MASK 0x0004 /* ADC_COMP */ +#define WM8962_ADC_COMP_SHIFT 2 /* ADC_COMP */ +#define WM8962_ADC_COMP_WIDTH 1 /* ADC_COMP */ +#define WM8962_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */ +#define WM8962_ADC_COMPMODE_MASK 0x0002 /* ADC_COMPMODE */ +#define WM8962_ADC_COMPMODE_SHIFT 1 /* ADC_COMPMODE */ +#define WM8962_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */ +#define WM8962_LOOPBACK 0x0001 /* LOOPBACK */ +#define WM8962_LOOPBACK_MASK 0x0001 /* LOOPBACK */ +#define WM8962_LOOPBACK_SHIFT 0 /* LOOPBACK */ +#define WM8962_LOOPBACK_WIDTH 1 /* LOOPBACK */ + +/* + * R10 (0x0A) - Left DAC volume + */ +#define WM8962_DAC_VU 0x0100 /* DAC_VU */ +#define WM8962_DAC_VU_MASK 0x0100 /* DAC_VU */ +#define WM8962_DAC_VU_SHIFT 8 /* DAC_VU */ +#define WM8962_DAC_VU_WIDTH 1 /* DAC_VU */ +#define WM8962_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */ +#define WM8962_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */ +#define WM8962_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */ + +/* + * R11 (0x0B) - Right DAC volume + */ +#define WM8962_DAC_VU 0x0100 /* DAC_VU */ +#define WM8962_DAC_VU_MASK 0x0100 /* DAC_VU */ +#define WM8962_DAC_VU_SHIFT 8 /* DAC_VU */ +#define WM8962_DAC_VU_WIDTH 1 /* DAC_VU */ +#define WM8962_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */ +#define WM8962_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */ +#define WM8962_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */ + +/* + * R14 (0x0E) - Audio Interface 2 + */ +#define WM8962_AIF_RATE_MASK 0x07FF /* AIF_RATE - [10:0] */ +#define WM8962_AIF_RATE_SHIFT 0 /* AIF_RATE - [10:0] */ +#define WM8962_AIF_RATE_WIDTH 11 /* AIF_RATE - [10:0] */ + +/* + * R15 (0x0F) - Software Reset + */ +#define WM8962_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */ +#define WM8962_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */ +#define WM8962_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */ + +/* + * R17 (0x11) - ALC1 + */ +#define WM8962_ALC_INACTIVE_ENA 0x0400 /* ALC_INACTIVE_ENA */ +#define WM8962_ALC_INACTIVE_ENA_MASK 0x0400 /* ALC_INACTIVE_ENA */ +#define WM8962_ALC_INACTIVE_ENA_SHIFT 10 /* ALC_INACTIVE_ENA */ +#define WM8962_ALC_INACTIVE_ENA_WIDTH 1 /* ALC_INACTIVE_ENA */ +#define WM8962_ALC_LVL_MODE 0x0200 /* ALC_LVL_MODE */ +#define WM8962_ALC_LVL_MODE_MASK 0x0200 /* ALC_LVL_MODE */ +#define WM8962_ALC_LVL_MODE_SHIFT 9 /* ALC_LVL_MODE */ +#define WM8962_ALC_LVL_MODE_WIDTH 1 /* ALC_LVL_MODE */ +#define WM8962_ALCL_ENA 0x0100 /* ALCL_ENA */ +#define WM8962_ALCL_ENA_MASK 0x0100 /* ALCL_ENA */ +#define WM8962_ALCL_ENA_SHIFT 8 /* ALCL_ENA */ +#define WM8962_ALCL_ENA_WIDTH 1 /* ALCL_ENA */ +#define WM8962_ALCR_ENA 0x0080 /* ALCR_ENA */ +#define WM8962_ALCR_ENA_MASK 0x0080 /* ALCR_ENA */ +#define WM8962_ALCR_ENA_SHIFT 7 /* ALCR_ENA */ +#define WM8962_ALCR_ENA_WIDTH 1 /* ALCR_ENA */ +#define WM8962_ALC_MAXGAIN_MASK 0x0070 /* ALC_MAXGAIN - [6:4] */ +#define WM8962_ALC_MAXGAIN_SHIFT 4 /* ALC_MAXGAIN - [6:4] */ +#define WM8962_ALC_MAXGAIN_WIDTH 3 /* ALC_MAXGAIN - [6:4] */ +#define WM8962_ALC_LVL_MASK 0x000F /* ALC_LVL - [3:0] */ +#define WM8962_ALC_LVL_SHIFT 0 /* ALC_LVL - [3:0] */ +#define WM8962_ALC_LVL_WIDTH 4 /* ALC_LVL - [3:0] */ + +/* + * R18 (0x12) - ALC2 + */ +#define WM8962_ALC_LOCK_STS 0x8000 /* ALC_LOCK_STS */ +#define WM8962_ALC_LOCK_STS_MASK 0x8000 /* ALC_LOCK_STS */ +#define WM8962_ALC_LOCK_STS_SHIFT 15 /* ALC_LOCK_STS */ +#define WM8962_ALC_LOCK_STS_WIDTH 1 /* ALC_LOCK_STS */ +#define WM8962_ALC_THRESH_STS 0x4000 /* ALC_THRESH_STS */ +#define WM8962_ALC_THRESH_STS_MASK 0x4000 /* ALC_THRESH_STS */ +#define WM8962_ALC_THRESH_STS_SHIFT 14 /* ALC_THRESH_STS */ +#define WM8962_ALC_THRESH_STS_WIDTH 1 /* ALC_THRESH_STS */ +#define WM8962_ALC_SAT_STS 0x2000 /* ALC_SAT_STS */ +#define WM8962_ALC_SAT_STS_MASK 0x2000 /* ALC_SAT_STS */ +#define WM8962_ALC_SAT_STS_SHIFT 13 /* ALC_SAT_STS */ +#define WM8962_ALC_SAT_STS_WIDTH 1 /* ALC_SAT_STS */ +#define WM8962_ALC_PKOVR_STS 0x1000 /* ALC_PKOVR_STS */ +#define WM8962_ALC_PKOVR_STS_MASK 0x1000 /* ALC_PKOVR_STS */ +#define WM8962_ALC_PKOVR_STS_SHIFT 12 /* ALC_PKOVR_STS */ +#define WM8962_ALC_PKOVR_STS_WIDTH 1 /* ALC_PKOVR_STS */ +#define WM8962_ALC_NGATE_STS 0x0800 /* ALC_NGATE_STS */ +#define WM8962_ALC_NGATE_STS_MASK 0x0800 /* ALC_NGATE_STS */ +#define WM8962_ALC_NGATE_STS_SHIFT 11 /* ALC_NGATE_STS */ +#define WM8962_ALC_NGATE_STS_WIDTH 1 /* ALC_NGATE_STS */ +#define WM8962_ALC_ZC 0x0080 /* ALC_ZC */ +#define WM8962_ALC_ZC_MASK 0x0080 /* ALC_ZC */ +#define WM8962_ALC_ZC_SHIFT 7 /* ALC_ZC */ +#define WM8962_ALC_ZC_WIDTH 1 /* ALC_ZC */ +#define WM8962_ALC_MINGAIN_MASK 0x0070 /* ALC_MINGAIN - [6:4] */ +#define WM8962_ALC_MINGAIN_SHIFT 4 /* ALC_MINGAIN - [6:4] */ +#define WM8962_ALC_MINGAIN_WIDTH 3 /* ALC_MINGAIN - [6:4] */ +#define WM8962_ALC_HLD_MASK 0x000F /* ALC_HLD - [3:0] */ +#define WM8962_ALC_HLD_SHIFT 0 /* ALC_HLD - [3:0] */ +#define WM8962_ALC_HLD_WIDTH 4 /* ALC_HLD - [3:0] */ + +/* + * R19 (0x13) - ALC3 + */ +#define WM8962_ALC_NGATE_GAIN_MASK 0x1C00 /* ALC_NGATE_GAIN - [12:10] */ +#define WM8962_ALC_NGATE_GAIN_SHIFT 10 /* ALC_NGATE_GAIN - [12:10] */ +#define WM8962_ALC_NGATE_GAIN_WIDTH 3 /* ALC_NGATE_GAIN - [12:10] */ +#define WM8962_ALC_MODE 0x0100 /* ALC_MODE */ +#define WM8962_ALC_MODE_MASK 0x0100 /* ALC_MODE */ +#define WM8962_ALC_MODE_SHIFT 8 /* ALC_MODE */ +#define WM8962_ALC_MODE_WIDTH 1 /* ALC_MODE */ +#define WM8962_ALC_DCY_MASK 0x00F0 /* ALC_DCY - [7:4] */ +#define WM8962_ALC_DCY_SHIFT 4 /* ALC_DCY - [7:4] */ +#define WM8962_ALC_DCY_WIDTH 4 /* ALC_DCY - [7:4] */ +#define WM8962_ALC_ATK_MASK 0x000F /* ALC_ATK - [3:0] */ +#define WM8962_ALC_ATK_SHIFT 0 /* ALC_ATK - [3:0] */ +#define WM8962_ALC_ATK_WIDTH 4 /* ALC_ATK - [3:0] */ + +/* + * R20 (0x14) - Noise Gate + */ +#define WM8962_ALC_NGATE_DCY_MASK 0xF000 /* ALC_NGATE_DCY - [15:12] */ +#define WM8962_ALC_NGATE_DCY_SHIFT 12 /* ALC_NGATE_DCY - [15:12] */ +#define WM8962_ALC_NGATE_DCY_WIDTH 4 /* ALC_NGATE_DCY - [15:12] */ +#define WM8962_ALC_NGATE_ATK_MASK 0x0F00 /* ALC_NGATE_ATK - [11:8] */ +#define WM8962_ALC_NGATE_ATK_SHIFT 8 /* ALC_NGATE_ATK - [11:8] */ +#define WM8962_ALC_NGATE_ATK_WIDTH 4 /* ALC_NGATE_ATK - [11:8] */ +#define WM8962_ALC_NGATE_THR_MASK 0x00F8 /* ALC_NGATE_THR - [7:3] */ +#define WM8962_ALC_NGATE_THR_SHIFT 3 /* ALC_NGATE_THR - [7:3] */ +#define WM8962_ALC_NGATE_THR_WIDTH 5 /* ALC_NGATE_THR - [7:3] */ +#define WM8962_ALC_NGATE_MODE_MASK 0x0006 /* ALC_NGATE_MODE - [2:1] */ +#define WM8962_ALC_NGATE_MODE_SHIFT 1 /* ALC_NGATE_MODE - [2:1] */ +#define WM8962_ALC_NGATE_MODE_WIDTH 2 /* ALC_NGATE_MODE - [2:1] */ +#define WM8962_ALC_NGATE_ENA 0x0001 /* ALC_NGATE_ENA */ +#define WM8962_ALC_NGATE_ENA_MASK 0x0001 /* ALC_NGATE_ENA */ +#define WM8962_ALC_NGATE_ENA_SHIFT 0 /* ALC_NGATE_ENA */ +#define WM8962_ALC_NGATE_ENA_WIDTH 1 /* ALC_NGATE_ENA */ + +/* + * R21 (0x15) - Left ADC volume + */ +#define WM8962_ADC_VU 0x0100 /* ADC_VU */ +#define WM8962_ADC_VU_MASK 0x0100 /* ADC_VU */ +#define WM8962_ADC_VU_SHIFT 8 /* ADC_VU */ +#define WM8962_ADC_VU_WIDTH 1 /* ADC_VU */ +#define WM8962_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */ +#define WM8962_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */ +#define WM8962_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */ + +/* + * R22 (0x16) - Right ADC volume + */ +#define WM8962_ADC_VU 0x0100 /* ADC_VU */ +#define WM8962_ADC_VU_MASK 0x0100 /* ADC_VU */ +#define WM8962_ADC_VU_SHIFT 8 /* ADC_VU */ +#define WM8962_ADC_VU_WIDTH 1 /* ADC_VU */ +#define WM8962_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */ +#define WM8962_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */ +#define WM8962_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */ + +/* + * R23 (0x17) - Additional control(1) + */ +#define WM8962_THERR_ACT 0x0100 /* THERR_ACT */ +#define WM8962_THERR_ACT_MASK 0x0100 /* THERR_ACT */ +#define WM8962_THERR_ACT_SHIFT 8 /* THERR_ACT */ +#define WM8962_THERR_ACT_WIDTH 1 /* THERR_ACT */ +#define WM8962_ADC_BIAS 0x0040 /* ADC_BIAS */ +#define WM8962_ADC_BIAS_MASK 0x0040 /* ADC_BIAS */ +#define WM8962_ADC_BIAS_SHIFT 6 /* ADC_BIAS */ +#define WM8962_ADC_BIAS_WIDTH 1 /* ADC_BIAS */ +#define WM8962_ADC_HP 0x0020 /* ADC_HP */ +#define WM8962_ADC_HP_MASK 0x0020 /* ADC_HP */ +#define WM8962_ADC_HP_SHIFT 5 /* ADC_HP */ +#define WM8962_ADC_HP_WIDTH 1 /* ADC_HP */ +#define WM8962_TOCLK_ENA 0x0001 /* TOCLK_ENA */ +#define WM8962_TOCLK_ENA_MASK 0x0001 /* TOCLK_ENA */ +#define WM8962_TOCLK_ENA_SHIFT 0 /* TOCLK_ENA */ +#define WM8962_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */ + +/* + * R24 (0x18) - Additional control(2) + */ +#define WM8962_AIF_TRI 0x0008 /* AIF_TRI */ +#define WM8962_AIF_TRI_MASK 0x0008 /* AIF_TRI */ +#define WM8962_AIF_TRI_SHIFT 3 /* AIF_TRI */ +#define WM8962_AIF_TRI_WIDTH 1 /* AIF_TRI */ + +/* + * R25 (0x19) - Pwr Mgmt (1) + */ +#define WM8962_DMIC_ENA 0x0400 /* DMIC_ENA */ +#define WM8962_DMIC_ENA_MASK 0x0400 /* DMIC_ENA */ +#define WM8962_DMIC_ENA_SHIFT 10 /* DMIC_ENA */ +#define WM8962_DMIC_ENA_WIDTH 1 /* DMIC_ENA */ +#define WM8962_OPCLK_ENA 0x0200 /* OPCLK_ENA */ +#define WM8962_OPCLK_ENA_MASK 0x0200 /* OPCLK_ENA */ +#define WM8962_OPCLK_ENA_SHIFT 9 /* OPCLK_ENA */ +#define WM8962_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */ +#define WM8962_VMID_SEL_MASK 0x0180 /* VMID_SEL - [8:7] */ +#define WM8962_VMID_SEL_SHIFT 7 /* VMID_SEL - [8:7] */ +#define WM8962_VMID_SEL_WIDTH 2 /* VMID_SEL - [8:7] */ +#define WM8962_BIAS_ENA 0x0040 /* BIAS_ENA */ +#define WM8962_BIAS_ENA_MASK 0x0040 /* BIAS_ENA */ +#define WM8962_BIAS_ENA_SHIFT 6 /* BIAS_ENA */ +#define WM8962_BIAS_ENA_WIDTH 1 /* BIAS_ENA */ +#define WM8962_INL_ENA 0x0020 /* INL_ENA */ +#define WM8962_INL_ENA_MASK 0x0020 /* INL_ENA */ +#define WM8962_INL_ENA_SHIFT 5 /* INL_ENA */ +#define WM8962_INL_ENA_WIDTH 1 /* INL_ENA */ +#define WM8962_INR_ENA 0x0010 /* INR_ENA */ +#define WM8962_INR_ENA_MASK 0x0010 /* INR_ENA */ +#define WM8962_INR_ENA_SHIFT 4 /* INR_ENA */ +#define WM8962_INR_ENA_WIDTH 1 /* INR_ENA */ +#define WM8962_ADCL_ENA 0x0008 /* ADCL_ENA */ +#define WM8962_ADCL_ENA_MASK 0x0008 /* ADCL_ENA */ +#define WM8962_ADCL_ENA_SHIFT 3 /* ADCL_ENA */ +#define WM8962_ADCL_ENA_WIDTH 1 /* ADCL_ENA */ +#define WM8962_ADCR_ENA 0x0004 /* ADCR_ENA */ +#define WM8962_ADCR_ENA_MASK 0x0004 /* ADCR_ENA */ +#define WM8962_ADCR_ENA_SHIFT 2 /* ADCR_ENA */ +#define WM8962_ADCR_ENA_WIDTH 1 /* ADCR_ENA */ +#define WM8962_MICBIAS_ENA 0x0002 /* MICBIAS_ENA */ +#define WM8962_MICBIAS_ENA_MASK 0x0002 /* MICBIAS_ENA */ +#define WM8962_MICBIAS_ENA_SHIFT 1 /* MICBIAS_ENA */ +#define WM8962_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */ + +/* + * R26 (0x1A) - Pwr Mgmt (2) + */ +#define WM8962_DACL_ENA 0x0100 /* DACL_ENA */ +#define WM8962_DACL_ENA_MASK 0x0100 /* DACL_ENA */ +#define WM8962_DACL_ENA_SHIFT 8 /* DACL_ENA */ +#define WM8962_DACL_ENA_WIDTH 1 /* DACL_ENA */ +#define WM8962_DACR_ENA 0x0080 /* DACR_ENA */ +#define WM8962_DACR_ENA_MASK 0x0080 /* DACR_ENA */ +#define WM8962_DACR_ENA_SHIFT 7 /* DACR_ENA */ +#define WM8962_DACR_ENA_WIDTH 1 /* DACR_ENA */ +#define WM8962_HPOUTL_PGA_ENA 0x0040 /* HPOUTL_PGA_ENA */ +#define WM8962_HPOUTL_PGA_ENA_MASK 0x0040 /* HPOUTL_PGA_ENA */ +#define WM8962_HPOUTL_PGA_ENA_SHIFT 6 /* HPOUTL_PGA_ENA */ +#define WM8962_HPOUTL_PGA_ENA_WIDTH 1 /* HPOUTL_PGA_ENA */ +#define WM8962_HPOUTR_PGA_ENA 0x0020 /* HPOUTR_PGA_ENA */ +#define WM8962_HPOUTR_PGA_ENA_MASK 0x0020 /* HPOUTR_PGA_ENA */ +#define WM8962_HPOUTR_PGA_ENA_SHIFT 5 /* HPOUTR_PGA_ENA */ +#define WM8962_HPOUTR_PGA_ENA_WIDTH 1 /* HPOUTR_PGA_ENA */ +#define WM8962_SPKOUTL_PGA_ENA 0x0010 /* SPKOUTL_PGA_ENA */ +#define WM8962_SPKOUTL_PGA_ENA_MASK 0x0010 /* SPKOUTL_PGA_ENA */ +#define WM8962_SPKOUTL_PGA_ENA_SHIFT 4 /* SPKOUTL_PGA_ENA */ +#define WM8962_SPKOUTL_PGA_ENA_WIDTH 1 /* SPKOUTL_PGA_ENA */ +#define WM8962_SPKOUTR_PGA_ENA 0x0008 /* SPKOUTR_PGA_ENA */ +#define WM8962_SPKOUTR_PGA_ENA_MASK 0x0008 /* SPKOUTR_PGA_ENA */ +#define WM8962_SPKOUTR_PGA_ENA_SHIFT 3 /* SPKOUTR_PGA_ENA */ +#define WM8962_SPKOUTR_PGA_ENA_WIDTH 1 /* SPKOUTR_PGA_ENA */ +#define WM8962_HPOUTL_PGA_MUTE 0x0002 /* HPOUTL_PGA_MUTE */ +#define WM8962_HPOUTL_PGA_MUTE_MASK 0x0002 /* HPOUTL_PGA_MUTE */ +#define WM8962_HPOUTL_PGA_MUTE_SHIFT 1 /* HPOUTL_PGA_MUTE */ +#define WM8962_HPOUTL_PGA_MUTE_WIDTH 1 /* HPOUTL_PGA_MUTE */ +#define WM8962_HPOUTR_PGA_MUTE 0x0001 /* HPOUTR_PGA_MUTE */ +#define WM8962_HPOUTR_PGA_MUTE_MASK 0x0001 /* HPOUTR_PGA_MUTE */ +#define WM8962_HPOUTR_PGA_MUTE_SHIFT 0 /* HPOUTR_PGA_MUTE */ +#define WM8962_HPOUTR_PGA_MUTE_WIDTH 1 /* HPOUTR_PGA_MUTE */ + +/* + * R27 (0x1B) - Additional Control (3) + */ +#define WM8962_SAMPLE_RATE_INT_MODE 0x0010 /* SAMPLE_RATE_INT_MODE */ +#define WM8962_SAMPLE_RATE_INT_MODE_MASK 0x0010 /* SAMPLE_RATE_INT_MODE */ +#define WM8962_SAMPLE_RATE_INT_MODE_SHIFT 4 /* SAMPLE_RATE_INT_MODE */ +#define WM8962_SAMPLE_RATE_INT_MODE_WIDTH 1 /* SAMPLE_RATE_INT_MODE */ +#define WM8962_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */ +#define WM8962_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */ +#define WM8962_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */ + +/* + * R28 (0x1C) - Anti-pop + */ +#define WM8962_STARTUP_BIAS_ENA 0x0010 /* STARTUP_BIAS_ENA */ +#define WM8962_STARTUP_BIAS_ENA_MASK 0x0010 /* STARTUP_BIAS_ENA */ +#define WM8962_STARTUP_BIAS_ENA_SHIFT 4 /* STARTUP_BIAS_ENA */ +#define WM8962_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */ +#define WM8962_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */ +#define WM8962_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */ +#define WM8962_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */ +#define WM8962_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ +#define WM8962_VMID_RAMP 0x0004 /* VMID_RAMP */ +#define WM8962_VMID_RAMP_MASK 0x0004 /* VMID_RAMP */ +#define WM8962_VMID_RAMP_SHIFT 2 /* VMID_RAMP */ +#define WM8962_VMID_RAMP_WIDTH 1 /* VMID_RAMP */ + +/* + * R30 (0x1E) - Clocking 3 + */ +#define WM8962_DBCLK_DIV_MASK 0xE000 /* DBCLK_DIV - [15:13] */ +#define WM8962_DBCLK_DIV_SHIFT 13 /* DBCLK_DIV - [15:13] */ +#define WM8962_DBCLK_DIV_WIDTH 3 /* DBCLK_DIV - [15:13] */ +#define WM8962_OPCLK_DIV_MASK 0x1C00 /* OPCLK_DIV - [12:10] */ +#define WM8962_OPCLK_DIV_SHIFT 10 /* OPCLK_DIV - [12:10] */ +#define WM8962_OPCLK_DIV_WIDTH 3 /* OPCLK_DIV - [12:10] */ +#define WM8962_TOCLK_DIV_MASK 0x0380 /* TOCLK_DIV - [9:7] */ +#define WM8962_TOCLK_DIV_SHIFT 7 /* TOCLK_DIV - [9:7] */ +#define WM8962_TOCLK_DIV_WIDTH 3 /* TOCLK_DIV - [9:7] */ +#define WM8962_F256KCLK_DIV_MASK 0x007E /* F256KCLK_DIV - [6:1] */ +#define WM8962_F256KCLK_DIV_SHIFT 1 /* F256KCLK_DIV - [6:1] */ +#define WM8962_F256KCLK_DIV_WIDTH 6 /* F256KCLK_DIV - [6:1] */ + +/* + * R31 (0x1F) - Input mixer control (1) + */ +#define WM8962_MIXINL_MUTE 0x0008 /* MIXINL_MUTE */ +#define WM8962_MIXINL_MUTE_MASK 0x0008 /* MIXINL_MUTE */ +#define WM8962_MIXINL_MUTE_SHIFT 3 /* MIXINL_MUTE */ +#define WM8962_MIXINL_MUTE_WIDTH 1 /* MIXINL_MUTE */ +#define WM8962_MIXINR_MUTE 0x0004 /* MIXINR_MUTE */ +#define WM8962_MIXINR_MUTE_MASK 0x0004 /* MIXINR_MUTE */ +#define WM8962_MIXINR_MUTE_SHIFT 2 /* MIXINR_MUTE */ +#define WM8962_MIXINR_MUTE_WIDTH 1 /* MIXINR_MUTE */ +#define WM8962_MIXINL_ENA 0x0002 /* MIXINL_ENA */ +#define WM8962_MIXINL_ENA_MASK 0x0002 /* MIXINL_ENA */ +#define WM8962_MIXINL_ENA_SHIFT 1 /* MIXINL_ENA */ +#define WM8962_MIXINL_ENA_WIDTH 1 /* MIXINL_ENA */ +#define WM8962_MIXINR_ENA 0x0001 /* MIXINR_ENA */ +#define WM8962_MIXINR_ENA_MASK 0x0001 /* MIXINR_ENA */ +#define WM8962_MIXINR_ENA_SHIFT 0 /* MIXINR_ENA */ +#define WM8962_MIXINR_ENA_WIDTH 1 /* MIXINR_ENA */ + +/* + * R32 (0x20) - Left input mixer volume + */ +#define WM8962_IN2L_MIXINL_VOL_MASK 0x01C0 /* IN2L_MIXINL_VOL - [8:6] */ +#define WM8962_IN2L_MIXINL_VOL_SHIFT 6 /* IN2L_MIXINL_VOL - [8:6] */ +#define WM8962_IN2L_MIXINL_VOL_WIDTH 3 /* IN2L_MIXINL_VOL - [8:6] */ +#define WM8962_INPGAL_MIXINL_VOL_MASK 0x0038 /* INPGAL_MIXINL_VOL - [5:3] */ +#define WM8962_INPGAL_MIXINL_VOL_SHIFT 3 /* INPGAL_MIXINL_VOL - [5:3] */ +#define WM8962_INPGAL_MIXINL_VOL_WIDTH 3 /* INPGAL_MIXINL_VOL - [5:3] */ +#define WM8962_IN3L_MIXINL_VOL_MASK 0x0007 /* IN3L_MIXINL_VOL - [2:0] */ +#define WM8962_IN3L_MIXINL_VOL_SHIFT 0 /* IN3L_MIXINL_VOL - [2:0] */ +#define WM8962_IN3L_MIXINL_VOL_WIDTH 3 /* IN3L_MIXINL_VOL - [2:0] */ + +/* + * R33 (0x21) - Right input mixer volume + */ +#define WM8962_IN2R_MIXINR_VOL_MASK 0x01C0 /* IN2R_MIXINR_VOL - [8:6] */ +#define WM8962_IN2R_MIXINR_VOL_SHIFT 6 /* IN2R_MIXINR_VOL - [8:6] */ +#define WM8962_IN2R_MIXINR_VOL_WIDTH 3 /* IN2R_MIXINR_VOL - [8:6] */ +#define WM8962_INPGAR_MIXINR_VOL_MASK 0x0038 /* INPGAR_MIXINR_VOL - [5:3] */ +#define WM8962_INPGAR_MIXINR_VOL_SHIFT 3 /* INPGAR_MIXINR_VOL - [5:3] */ +#define WM8962_INPGAR_MIXINR_VOL_WIDTH 3 /* INPGAR_MIXINR_VOL - [5:3] */ +#define WM8962_IN3R_MIXINR_VOL_MASK 0x0007 /* IN3R_MIXINR_VOL - [2:0] */ +#define WM8962_IN3R_MIXINR_VOL_SHIFT 0 /* IN3R_MIXINR_VOL - [2:0] */ +#define WM8962_IN3R_MIXINR_VOL_WIDTH 3 /* IN3R_MIXINR_VOL - [2:0] */ + +/* + * R34 (0x22) - Input mixer control (2) + */ +#define WM8962_IN2L_TO_MIXINL 0x0020 /* IN2L_TO_MIXINL */ +#define WM8962_IN2L_TO_MIXINL_MASK 0x0020 /* IN2L_TO_MIXINL */ +#define WM8962_IN2L_TO_MIXINL_SHIFT 5 /* IN2L_TO_MIXINL */ +#define WM8962_IN2L_TO_MIXINL_WIDTH 1 /* IN2L_TO_MIXINL */ +#define WM8962_IN3L_TO_MIXINL 0x0010 /* IN3L_TO_MIXINL */ +#define WM8962_IN3L_TO_MIXINL_MASK 0x0010 /* IN3L_TO_MIXINL */ +#define WM8962_IN3L_TO_MIXINL_SHIFT 4 /* IN3L_TO_MIXINL */ +#define WM8962_IN3L_TO_MIXINL_WIDTH 1 /* IN3L_TO_MIXINL */ +#define WM8962_INPGAL_TO_MIXINL 0x0008 /* INPGAL_TO_MIXINL */ +#define WM8962_INPGAL_TO_MIXINL_MASK 0x0008 /* INPGAL_TO_MIXINL */ +#define WM8962_INPGAL_TO_MIXINL_SHIFT 3 /* INPGAL_TO_MIXINL */ +#define WM8962_INPGAL_TO_MIXINL_WIDTH 1 /* INPGAL_TO_MIXINL */ +#define WM8962_IN2R_TO_MIXINR 0x0004 /* IN2R_TO_MIXINR */ +#define WM8962_IN2R_TO_MIXINR_MASK 0x0004 /* IN2R_TO_MIXINR */ +#define WM8962_IN2R_TO_MIXINR_SHIFT 2 /* IN2R_TO_MIXINR */ +#define WM8962_IN2R_TO_MIXINR_WIDTH 1 /* IN2R_TO_MIXINR */ +#define WM8962_IN3R_TO_MIXINR 0x0002 /* IN3R_TO_MIXINR */ +#define WM8962_IN3R_TO_MIXINR_MASK 0x0002 /* IN3R_TO_MIXINR */ +#define WM8962_IN3R_TO_MIXINR_SHIFT 1 /* IN3R_TO_MIXINR */ +#define WM8962_IN3R_TO_MIXINR_WIDTH 1 /* IN3R_TO_MIXINR */ +#define WM8962_INPGAR_TO_MIXINR 0x0001 /* INPGAR_TO_MIXINR */ +#define WM8962_INPGAR_TO_MIXINR_MASK 0x0001 /* INPGAR_TO_MIXINR */ +#define WM8962_INPGAR_TO_MIXINR_SHIFT 0 /* INPGAR_TO_MIXINR */ +#define WM8962_INPGAR_TO_MIXINR_WIDTH 1 /* INPGAR_TO_MIXINR */ + +/* + * R35 (0x23) - Input bias control + */ +#define WM8962_MIXIN_BIAS_MASK 0x0038 /* MIXIN_BIAS - [5:3] */ +#define WM8962_MIXIN_BIAS_SHIFT 3 /* MIXIN_BIAS - [5:3] */ +#define WM8962_MIXIN_BIAS_WIDTH 3 /* MIXIN_BIAS - [5:3] */ +#define WM8962_INPGA_BIAS_MASK 0x0007 /* INPGA_BIAS - [2:0] */ +#define WM8962_INPGA_BIAS_SHIFT 0 /* INPGA_BIAS - [2:0] */ +#define WM8962_INPGA_BIAS_WIDTH 3 /* INPGA_BIAS - [2:0] */ + +/* + * R37 (0x25) - Left input PGA control + */ +#define WM8962_INPGAL_ENA 0x0010 /* INPGAL_ENA */ +#define WM8962_INPGAL_ENA_MASK 0x0010 /* INPGAL_ENA */ +#define WM8962_INPGAL_ENA_SHIFT 4 /* INPGAL_ENA */ +#define WM8962_INPGAL_ENA_WIDTH 1 /* INPGAL_ENA */ +#define WM8962_IN1L_TO_INPGAL 0x0008 /* IN1L_TO_INPGAL */ +#define WM8962_IN1L_TO_INPGAL_MASK 0x0008 /* IN1L_TO_INPGAL */ +#define WM8962_IN1L_TO_INPGAL_SHIFT 3 /* IN1L_TO_INPGAL */ +#define WM8962_IN1L_TO_INPGAL_WIDTH 1 /* IN1L_TO_INPGAL */ +#define WM8962_IN2L_TO_INPGAL 0x0004 /* IN2L_TO_INPGAL */ +#define WM8962_IN2L_TO_INPGAL_MASK 0x0004 /* IN2L_TO_INPGAL */ +#define WM8962_IN2L_TO_INPGAL_SHIFT 2 /* IN2L_TO_INPGAL */ +#define WM8962_IN2L_TO_INPGAL_WIDTH 1 /* IN2L_TO_INPGAL */ +#define WM8962_IN3L_TO_INPGAL 0x0002 /* IN3L_TO_INPGAL */ +#define WM8962_IN3L_TO_INPGAL_MASK 0x0002 /* IN3L_TO_INPGAL */ +#define WM8962_IN3L_TO_INPGAL_SHIFT 1 /* IN3L_TO_INPGAL */ +#define WM8962_IN3L_TO_INPGAL_WIDTH 1 /* IN3L_TO_INPGAL */ +#define WM8962_IN4L_TO_INPGAL 0x0001 /* IN4L_TO_INPGAL */ +#define WM8962_IN4L_TO_INPGAL_MASK 0x0001 /* IN4L_TO_INPGAL */ +#define WM8962_IN4L_TO_INPGAL_SHIFT 0 /* IN4L_TO_INPGAL */ +#define WM8962_IN4L_TO_INPGAL_WIDTH 1 /* IN4L_TO_INPGAL */ + +/* + * R38 (0x26) - Right input PGA control + */ +#define WM8962_INPGAR_ENA 0x0010 /* INPGAR_ENA */ +#define WM8962_INPGAR_ENA_MASK 0x0010 /* INPGAR_ENA */ +#define WM8962_INPGAR_ENA_SHIFT 4 /* INPGAR_ENA */ +#define WM8962_INPGAR_ENA_WIDTH 1 /* INPGAR_ENA */ +#define WM8962_IN1R_TO_INPGAR 0x0008 /* IN1R_TO_INPGAR */ +#define WM8962_IN1R_TO_INPGAR_MASK 0x0008 /* IN1R_TO_INPGAR */ +#define WM8962_IN1R_TO_INPGAR_SHIFT 3 /* IN1R_TO_INPGAR */ +#define WM8962_IN1R_TO_INPGAR_WIDTH 1 /* IN1R_TO_INPGAR */ +#define WM8962_IN2R_TO_INPGAR 0x0004 /* IN2R_TO_INPGAR */ +#define WM8962_IN2R_TO_INPGAR_MASK 0x0004 /* IN2R_TO_INPGAR */ +#define WM8962_IN2R_TO_INPGAR_SHIFT 2 /* IN2R_TO_INPGAR */ +#define WM8962_IN2R_TO_INPGAR_WIDTH 1 /* IN2R_TO_INPGAR */ +#define WM8962_IN3R_TO_INPGAR 0x0002 /* IN3R_TO_INPGAR */ +#define WM8962_IN3R_TO_INPGAR_MASK 0x0002 /* IN3R_TO_INPGAR */ +#define WM8962_IN3R_TO_INPGAR_SHIFT 1 /* IN3R_TO_INPGAR */ +#define WM8962_IN3R_TO_INPGAR_WIDTH 1 /* IN3R_TO_INPGAR */ +#define WM8962_IN4R_TO_INPGAR 0x0001 /* IN4R_TO_INPGAR */ +#define WM8962_IN4R_TO_INPGAR_MASK 0x0001 /* IN4R_TO_INPGAR */ +#define WM8962_IN4R_TO_INPGAR_SHIFT 0 /* IN4R_TO_INPGAR */ +#define WM8962_IN4R_TO_INPGAR_WIDTH 1 /* IN4R_TO_INPGAR */ + +/* + * R40 (0x28) - SPKOUTL volume + */ +#define WM8962_SPKOUT_VU 0x0100 /* SPKOUT_VU */ +#define WM8962_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */ +#define WM8962_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */ +#define WM8962_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */ +#define WM8962_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */ +#define WM8962_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */ +#define WM8962_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */ +#define WM8962_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */ +#define WM8962_SPKOUTL_VOL_MASK 0x007F /* SPKOUTL_VOL - [6:0] */ +#define WM8962_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [6:0] */ +#define WM8962_SPKOUTL_VOL_WIDTH 7 /* SPKOUTL_VOL - [6:0] */ + +/* + * R41 (0x29) - SPKOUTR volume + */ +#define WM8962_SPKOUTR_ZC 0x0080 /* SPKOUTR_ZC */ +#define WM8962_SPKOUTR_ZC_MASK 0x0080 /* SPKOUTR_ZC */ +#define WM8962_SPKOUTR_ZC_SHIFT 7 /* SPKOUTR_ZC */ +#define WM8962_SPKOUTR_ZC_WIDTH 1 /* SPKOUTR_ZC */ +#define WM8962_SPKOUTR_VOL_MASK 0x007F /* SPKOUTR_VOL - [6:0] */ +#define WM8962_SPKOUTR_VOL_SHIFT 0 /* SPKOUTR_VOL - [6:0] */ +#define WM8962_SPKOUTR_VOL_WIDTH 7 /* SPKOUTR_VOL - [6:0] */ + +/* + * R47 (0x2F) - Thermal Shutdown Status + */ +#define WM8962_TEMP_ERR_HP 0x0008 /* TEMP_ERR_HP */ +#define WM8962_TEMP_ERR_HP_MASK 0x0008 /* TEMP_ERR_HP */ +#define WM8962_TEMP_ERR_HP_SHIFT 3 /* TEMP_ERR_HP */ +#define WM8962_TEMP_ERR_HP_WIDTH 1 /* TEMP_ERR_HP */ +#define WM8962_TEMP_WARN_HP 0x0004 /* TEMP_WARN_HP */ +#define WM8962_TEMP_WARN_HP_MASK 0x0004 /* TEMP_WARN_HP */ +#define WM8962_TEMP_WARN_HP_SHIFT 2 /* TEMP_WARN_HP */ +#define WM8962_TEMP_WARN_HP_WIDTH 1 /* TEMP_WARN_HP */ +#define WM8962_TEMP_ERR_SPK 0x0002 /* TEMP_ERR_SPK */ +#define WM8962_TEMP_ERR_SPK_MASK 0x0002 /* TEMP_ERR_SPK */ +#define WM8962_TEMP_ERR_SPK_SHIFT 1 /* TEMP_ERR_SPK */ +#define WM8962_TEMP_ERR_SPK_WIDTH 1 /* TEMP_ERR_SPK */ +#define WM8962_TEMP_WARN_SPK 0x0001 /* TEMP_WARN_SPK */ +#define WM8962_TEMP_WARN_SPK_MASK 0x0001 /* TEMP_WARN_SPK */ +#define WM8962_TEMP_WARN_SPK_SHIFT 0 /* TEMP_WARN_SPK */ +#define WM8962_TEMP_WARN_SPK_WIDTH 1 /* TEMP_WARN_SPK */ + +/* + * R48 (0x30) - Additional Control (4) + */ +#define WM8962_MICDET_THR_MASK 0x7000 /* MICDET_THR - [14:12] */ +#define WM8962_MICDET_THR_SHIFT 12 /* MICDET_THR - [14:12] */ +#define WM8962_MICDET_THR_WIDTH 3 /* MICDET_THR - [14:12] */ +#define WM8962_MICSHORT_THR_MASK 0x0C00 /* MICSHORT_THR - [11:10] */ +#define WM8962_MICSHORT_THR_SHIFT 10 /* MICSHORT_THR - [11:10] */ +#define WM8962_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [11:10] */ +#define WM8962_MICDET_ENA 0x0200 /* MICDET_ENA */ +#define WM8962_MICDET_ENA_MASK 0x0200 /* MICDET_ENA */ +#define WM8962_MICDET_ENA_SHIFT 9 /* MICDET_ENA */ +#define WM8962_MICDET_ENA_WIDTH 1 /* MICDET_ENA */ +#define WM8962_MICDET_STS 0x0080 /* MICDET_STS */ +#define WM8962_MICDET_STS_MASK 0x0080 /* MICDET_STS */ +#define WM8962_MICDET_STS_SHIFT 7 /* MICDET_STS */ +#define WM8962_MICDET_STS_WIDTH 1 /* MICDET_STS */ +#define WM8962_MICSHORT_STS 0x0040 /* MICSHORT_STS */ +#define WM8962_MICSHORT_STS_MASK 0x0040 /* MICSHORT_STS */ +#define WM8962_MICSHORT_STS_SHIFT 6 /* MICSHORT_STS */ +#define WM8962_MICSHORT_STS_WIDTH 1 /* MICSHORT_STS */ +#define WM8962_TEMP_ENA_HP 0x0004 /* TEMP_ENA_HP */ +#define WM8962_TEMP_ENA_HP_MASK 0x0004 /* TEMP_ENA_HP */ +#define WM8962_TEMP_ENA_HP_SHIFT 2 /* TEMP_ENA_HP */ +#define WM8962_TEMP_ENA_HP_WIDTH 1 /* TEMP_ENA_HP */ +#define WM8962_TEMP_ENA_SPK 0x0002 /* TEMP_ENA_SPK */ +#define WM8962_TEMP_ENA_SPK_MASK 0x0002 /* TEMP_ENA_SPK */ +#define WM8962_TEMP_ENA_SPK_SHIFT 1 /* TEMP_ENA_SPK */ +#define WM8962_TEMP_ENA_SPK_WIDTH 1 /* TEMP_ENA_SPK */ +#define WM8962_MICBIAS_LVL 0x0001 /* MICBIAS_LVL */ +#define WM8962_MICBIAS_LVL_MASK 0x0001 /* MICBIAS_LVL */ +#define WM8962_MICBIAS_LVL_SHIFT 0 /* MICBIAS_LVL */ +#define WM8962_MICBIAS_LVL_WIDTH 1 /* MICBIAS_LVL */ + +/* + * R49 (0x31) - Class D Control 1 + */ +#define WM8962_SPKOUTR_ENA 0x0080 /* SPKOUTR_ENA */ +#define WM8962_SPKOUTR_ENA_MASK 0x0080 /* SPKOUTR_ENA */ +#define WM8962_SPKOUTR_ENA_SHIFT 7 /* SPKOUTR_ENA */ +#define WM8962_SPKOUTR_ENA_WIDTH 1 /* SPKOUTR_ENA */ +#define WM8962_SPKOUTL_ENA 0x0040 /* SPKOUTL_ENA */ +#define WM8962_SPKOUTL_ENA_MASK 0x0040 /* SPKOUTL_ENA */ +#define WM8962_SPKOUTL_ENA_SHIFT 6 /* SPKOUTL_ENA */ +#define WM8962_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */ +#define WM8962_SPKOUTL_PGA_MUTE 0x0002 /* SPKOUTL_PGA_MUTE */ +#define WM8962_SPKOUTL_PGA_MUTE_MASK 0x0002 /* SPKOUTL_PGA_MUTE */ +#define WM8962_SPKOUTL_PGA_MUTE_SHIFT 1 /* SPKOUTL_PGA_MUTE */ +#define WM8962_SPKOUTL_PGA_MUTE_WIDTH 1 /* SPKOUTL_PGA_MUTE */ +#define WM8962_SPKOUTR_PGA_MUTE 0x0001 /* SPKOUTR_PGA_MUTE */ +#define WM8962_SPKOUTR_PGA_MUTE_MASK 0x0001 /* SPKOUTR_PGA_MUTE */ +#define WM8962_SPKOUTR_PGA_MUTE_SHIFT 0 /* SPKOUTR_PGA_MUTE */ +#define WM8962_SPKOUTR_PGA_MUTE_WIDTH 1 /* SPKOUTR_PGA_MUTE */ + +/* + * R51 (0x33) - Class D Control 2 + */ +#define WM8962_SPK_MONO 0x0040 /* SPK_MONO */ +#define WM8962_SPK_MONO_MASK 0x0040 /* SPK_MONO */ +#define WM8962_SPK_MONO_SHIFT 6 /* SPK_MONO */ +#define WM8962_SPK_MONO_WIDTH 1 /* SPK_MONO */ +#define WM8962_CLASSD_VOL_MASK 0x0007 /* CLASSD_VOL - [2:0] */ +#define WM8962_CLASSD_VOL_SHIFT 0 /* CLASSD_VOL - [2:0] */ +#define WM8962_CLASSD_VOL_WIDTH 3 /* CLASSD_VOL - [2:0] */ + +/* + * R56 (0x38) - Clocking 4 + */ +#define WM8962_SYSCLK_RATE_MASK 0x001E /* SYSCLK_RATE - [4:1] */ +#define WM8962_SYSCLK_RATE_SHIFT 1 /* SYSCLK_RATE - [4:1] */ +#define WM8962_SYSCLK_RATE_WIDTH 4 /* SYSCLK_RATE - [4:1] */ + +/* + * R57 (0x39) - DAC DSP Mixing (1) + */ +#define WM8962_DAC_MONOMIX 0x0200 /* DAC_MONOMIX */ +#define WM8962_DAC_MONOMIX_MASK 0x0200 /* DAC_MONOMIX */ +#define WM8962_DAC_MONOMIX_SHIFT 9 /* DAC_MONOMIX */ +#define WM8962_DAC_MONOMIX_WIDTH 1 /* DAC_MONOMIX */ +#define WM8962_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */ +#define WM8962_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */ +#define WM8962_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */ +#define WM8962_ADC_TO_DACR_MASK 0x000C /* ADC_TO_DACR - [3:2] */ +#define WM8962_ADC_TO_DACR_SHIFT 2 /* ADC_TO_DACR - [3:2] */ +#define WM8962_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [3:2] */ + +/* + * R58 (0x3A) - DAC DSP Mixing (2) + */ +#define WM8962_ADCL_DAC_SVOL_MASK 0x00F0 /* ADCL_DAC_SVOL - [7:4] */ +#define WM8962_ADCL_DAC_SVOL_SHIFT 4 /* ADCL_DAC_SVOL - [7:4] */ +#define WM8962_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [7:4] */ +#define WM8962_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */ +#define WM8962_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */ +#define WM8962_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */ + +/* + * R60 (0x3C) - DC Servo 0 + */ +#define WM8962_INL_DCS_ENA 0x0080 /* INL_DCS_ENA */ +#define WM8962_INL_DCS_ENA_MASK 0x0080 /* INL_DCS_ENA */ +#define WM8962_INL_DCS_ENA_SHIFT 7 /* INL_DCS_ENA */ +#define WM8962_INL_DCS_ENA_WIDTH 1 /* INL_DCS_ENA */ +#define WM8962_INL_DCS_STARTUP 0x0040 /* INL_DCS_STARTUP */ +#define WM8962_INL_DCS_STARTUP_MASK 0x0040 /* INL_DCS_STARTUP */ +#define WM8962_INL_DCS_STARTUP_SHIFT 6 /* INL_DCS_STARTUP */ +#define WM8962_INL_DCS_STARTUP_WIDTH 1 /* INL_DCS_STARTUP */ +#define WM8962_INR_DCS_ENA 0x0008 /* INR_DCS_ENA */ +#define WM8962_INR_DCS_ENA_MASK 0x0008 /* INR_DCS_ENA */ +#define WM8962_INR_DCS_ENA_SHIFT 3 /* INR_DCS_ENA */ +#define WM8962_INR_DCS_ENA_WIDTH 1 /* INR_DCS_ENA */ +#define WM8962_INR_DCS_STARTUP 0x0004 /* INR_DCS_STARTUP */ +#define WM8962_INR_DCS_STARTUP_MASK 0x0004 /* INR_DCS_STARTUP */ +#define WM8962_INR_DCS_STARTUP_SHIFT 2 /* INR_DCS_STARTUP */ +#define WM8962_INR_DCS_STARTUP_WIDTH 1 /* INR_DCS_STARTUP */ + +/* + * R61 (0x3D) - DC Servo 1 + */ +#define WM8962_HP1L_DCS_ENA 0x0080 /* HP1L_DCS_ENA */ +#define WM8962_HP1L_DCS_ENA_MASK 0x0080 /* HP1L_DCS_ENA */ +#define WM8962_HP1L_DCS_ENA_SHIFT 7 /* HP1L_DCS_ENA */ +#define WM8962_HP1L_DCS_ENA_WIDTH 1 /* HP1L_DCS_ENA */ +#define WM8962_HP1L_DCS_STARTUP 0x0040 /* HP1L_DCS_STARTUP */ +#define WM8962_HP1L_DCS_STARTUP_MASK 0x0040 /* HP1L_DCS_STARTUP */ +#define WM8962_HP1L_DCS_STARTUP_SHIFT 6 /* HP1L_DCS_STARTUP */ +#define WM8962_HP1L_DCS_STARTUP_WIDTH 1 /* HP1L_DCS_STARTUP */ +#define WM8962_HP1L_DCS_SYNC 0x0010 /* HP1L_DCS_SYNC */ +#define WM8962_HP1L_DCS_SYNC_MASK 0x0010 /* HP1L_DCS_SYNC */ +#define WM8962_HP1L_DCS_SYNC_SHIFT 4 /* HP1L_DCS_SYNC */ +#define WM8962_HP1L_DCS_SYNC_WIDTH 1 /* HP1L_DCS_SYNC */ +#define WM8962_HP1R_DCS_ENA 0x0008 /* HP1R_DCS_ENA */ +#define WM8962_HP1R_DCS_ENA_MASK 0x0008 /* HP1R_DCS_ENA */ +#define WM8962_HP1R_DCS_ENA_SHIFT 3 /* HP1R_DCS_ENA */ +#define WM8962_HP1R_DCS_ENA_WIDTH 1 /* HP1R_DCS_ENA */ +#define WM8962_HP1R_DCS_STARTUP 0x0004 /* HP1R_DCS_STARTUP */ +#define WM8962_HP1R_DCS_STARTUP_MASK 0x0004 /* HP1R_DCS_STARTUP */ +#define WM8962_HP1R_DCS_STARTUP_SHIFT 2 /* HP1R_DCS_STARTUP */ +#define WM8962_HP1R_DCS_STARTUP_WIDTH 1 /* HP1R_DCS_STARTUP */ +#define WM8962_HP1R_DCS_SYNC 0x0001 /* HP1R_DCS_SYNC */ +#define WM8962_HP1R_DCS_SYNC_MASK 0x0001 /* HP1R_DCS_SYNC */ +#define WM8962_HP1R_DCS_SYNC_SHIFT 0 /* HP1R_DCS_SYNC */ +#define WM8962_HP1R_DCS_SYNC_WIDTH 1 /* HP1R_DCS_SYNC */ + +/* + * R64 (0x40) - DC Servo 4 + */ +#define WM8962_HP1_DCS_SYNC_STEPS_MASK 0x3F80 /* HP1_DCS_SYNC_STEPS - [13:7] */ +#define WM8962_HP1_DCS_SYNC_STEPS_SHIFT 7 /* HP1_DCS_SYNC_STEPS - [13:7] */ +#define WM8962_HP1_DCS_SYNC_STEPS_WIDTH 7 /* HP1_DCS_SYNC_STEPS - [13:7] */ + +/* + * R66 (0x42) - DC Servo 6 + */ +#define WM8962_DCS_STARTUP_DONE_INL 0x0400 /* DCS_STARTUP_DONE_INL */ +#define WM8962_DCS_STARTUP_DONE_INL_MASK 0x0400 /* DCS_STARTUP_DONE_INL */ +#define WM8962_DCS_STARTUP_DONE_INL_SHIFT 10 /* DCS_STARTUP_DONE_INL */ +#define WM8962_DCS_STARTUP_DONE_INL_WIDTH 1 /* DCS_STARTUP_DONE_INL */ +#define WM8962_DCS_STARTUP_DONE_INR 0x0200 /* DCS_STARTUP_DONE_INR */ +#define WM8962_DCS_STARTUP_DONE_INR_MASK 0x0200 /* DCS_STARTUP_DONE_INR */ +#define WM8962_DCS_STARTUP_DONE_INR_SHIFT 9 /* DCS_STARTUP_DONE_INR */ +#define WM8962_DCS_STARTUP_DONE_INR_WIDTH 1 /* DCS_STARTUP_DONE_INR */ +#define WM8962_DCS_STARTUP_DONE_HP1L 0x0100 /* DCS_STARTUP_DONE_HP1L */ +#define WM8962_DCS_STARTUP_DONE_HP1L_MASK 0x0100 /* DCS_STARTUP_DONE_HP1L */ +#define WM8962_DCS_STARTUP_DONE_HP1L_SHIFT 8 /* DCS_STARTUP_DONE_HP1L */ +#define WM8962_DCS_STARTUP_DONE_HP1L_WIDTH 1 /* DCS_STARTUP_DONE_HP1L */ +#define WM8962_DCS_STARTUP_DONE_HP1R 0x0080 /* DCS_STARTUP_DONE_HP1R */ +#define WM8962_DCS_STARTUP_DONE_HP1R_MASK 0x0080 /* DCS_STARTUP_DONE_HP1R */ +#define WM8962_DCS_STARTUP_DONE_HP1R_SHIFT 7 /* DCS_STARTUP_DONE_HP1R */ +#define WM8962_DCS_STARTUP_DONE_HP1R_WIDTH 1 /* DCS_STARTUP_DONE_HP1R */ + +/* + * R68 (0x44) - Analogue PGA Bias + */ +#define WM8962_HP_PGAS_BIAS_MASK 0x0007 /* HP_PGAS_BIAS - [2:0] */ +#define WM8962_HP_PGAS_BIAS_SHIFT 0 /* HP_PGAS_BIAS - [2:0] */ +#define WM8962_HP_PGAS_BIAS_WIDTH 3 /* HP_PGAS_BIAS - [2:0] */ + +/* + * R69 (0x45) - Analogue HP 0 + */ +#define WM8962_HP1L_RMV_SHORT 0x0080 /* HP1L_RMV_SHORT */ +#define WM8962_HP1L_RMV_SHORT_MASK 0x0080 /* HP1L_RMV_SHORT */ +#define WM8962_HP1L_RMV_SHORT_SHIFT 7 /* HP1L_RMV_SHORT */ +#define WM8962_HP1L_RMV_SHORT_WIDTH 1 /* HP1L_RMV_SHORT */ +#define WM8962_HP1L_ENA_OUTP 0x0040 /* HP1L_ENA_OUTP */ +#define WM8962_HP1L_ENA_OUTP_MASK 0x0040 /* HP1L_ENA_OUTP */ +#define WM8962_HP1L_ENA_OUTP_SHIFT 6 /* HP1L_ENA_OUTP */ +#define WM8962_HP1L_ENA_OUTP_WIDTH 1 /* HP1L_ENA_OUTP */ +#define WM8962_HP1L_ENA_DLY 0x0020 /* HP1L_ENA_DLY */ +#define WM8962_HP1L_ENA_DLY_MASK 0x0020 /* HP1L_ENA_DLY */ +#define WM8962_HP1L_ENA_DLY_SHIFT 5 /* HP1L_ENA_DLY */ +#define WM8962_HP1L_ENA_DLY_WIDTH 1 /* HP1L_ENA_DLY */ +#define WM8962_HP1L_ENA 0x0010 /* HP1L_ENA */ +#define WM8962_HP1L_ENA_MASK 0x0010 /* HP1L_ENA */ +#define WM8962_HP1L_ENA_SHIFT 4 /* HP1L_ENA */ +#define WM8962_HP1L_ENA_WIDTH 1 /* HP1L_ENA */ +#define WM8962_HP1R_RMV_SHORT 0x0008 /* HP1R_RMV_SHORT */ +#define WM8962_HP1R_RMV_SHORT_MASK 0x0008 /* HP1R_RMV_SHORT */ +#define WM8962_HP1R_RMV_SHORT_SHIFT 3 /* HP1R_RMV_SHORT */ +#define WM8962_HP1R_RMV_SHORT_WIDTH 1 /* HP1R_RMV_SHORT */ +#define WM8962_HP1R_ENA_OUTP 0x0004 /* HP1R_ENA_OUTP */ +#define WM8962_HP1R_ENA_OUTP_MASK 0x0004 /* HP1R_ENA_OUTP */ +#define WM8962_HP1R_ENA_OUTP_SHIFT 2 /* HP1R_ENA_OUTP */ +#define WM8962_HP1R_ENA_OUTP_WIDTH 1 /* HP1R_ENA_OUTP */ +#define WM8962_HP1R_ENA_DLY 0x0002 /* HP1R_ENA_DLY */ +#define WM8962_HP1R_ENA_DLY_MASK 0x0002 /* HP1R_ENA_DLY */ +#define WM8962_HP1R_ENA_DLY_SHIFT 1 /* HP1R_ENA_DLY */ +#define WM8962_HP1R_ENA_DLY_WIDTH 1 /* HP1R_ENA_DLY */ +#define WM8962_HP1R_ENA 0x0001 /* HP1R_ENA */ +#define WM8962_HP1R_ENA_MASK 0x0001 /* HP1R_ENA */ +#define WM8962_HP1R_ENA_SHIFT 0 /* HP1R_ENA */ +#define WM8962_HP1R_ENA_WIDTH 1 /* HP1R_ENA */ + +/* + * R71 (0x47) - Analogue HP 2 + */ +#define WM8962_HP1L_VOL_MASK 0x01C0 /* HP1L_VOL - [8:6] */ +#define WM8962_HP1L_VOL_SHIFT 6 /* HP1L_VOL - [8:6] */ +#define WM8962_HP1L_VOL_WIDTH 3 /* HP1L_VOL - [8:6] */ +#define WM8962_HP1R_VOL_MASK 0x0038 /* HP1R_VOL - [5:3] */ +#define WM8962_HP1R_VOL_SHIFT 3 /* HP1R_VOL - [5:3] */ +#define WM8962_HP1R_VOL_WIDTH 3 /* HP1R_VOL - [5:3] */ +#define WM8962_HP_BIAS_BOOST_MASK 0x0007 /* HP_BIAS_BOOST - [2:0] */ +#define WM8962_HP_BIAS_BOOST_SHIFT 0 /* HP_BIAS_BOOST - [2:0] */ +#define WM8962_HP_BIAS_BOOST_WIDTH 3 /* HP_BIAS_BOOST - [2:0] */ + +/* + * R72 (0x48) - Charge Pump 1 + */ +#define WM8962_CP_ENA 0x0001 /* CP_ENA */ +#define WM8962_CP_ENA_MASK 0x0001 /* CP_ENA */ +#define WM8962_CP_ENA_SHIFT 0 /* CP_ENA */ +#define WM8962_CP_ENA_WIDTH 1 /* CP_ENA */ + +/* + * R82 (0x52) - Charge Pump B + */ +#define WM8962_CP_DYN_PWR 0x0001 /* CP_DYN_PWR */ +#define WM8962_CP_DYN_PWR_MASK 0x0001 /* CP_DYN_PWR */ +#define WM8962_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR */ +#define WM8962_CP_DYN_PWR_WIDTH 1 /* CP_DYN_PWR */ + +/* + * R87 (0x57) - Write Sequencer Control 1 + */ +#define WM8962_WSEQ_AUTOSEQ_ENA 0x0080 /* WSEQ_AUTOSEQ_ENA */ +#define WM8962_WSEQ_AUTOSEQ_ENA_MASK 0x0080 /* WSEQ_AUTOSEQ_ENA */ +#define WM8962_WSEQ_AUTOSEQ_ENA_SHIFT 7 /* WSEQ_AUTOSEQ_ENA */ +#define WM8962_WSEQ_AUTOSEQ_ENA_WIDTH 1 /* WSEQ_AUTOSEQ_ENA */ +#define WM8962_WSEQ_ENA 0x0020 /* WSEQ_ENA */ +#define WM8962_WSEQ_ENA_MASK 0x0020 /* WSEQ_ENA */ +#define WM8962_WSEQ_ENA_SHIFT 5 /* WSEQ_ENA */ +#define WM8962_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ + +/* + * R90 (0x5A) - Write Sequencer Control 2 + */ +#define WM8962_WSEQ_ABORT 0x0100 /* WSEQ_ABORT */ +#define WM8962_WSEQ_ABORT_MASK 0x0100 /* WSEQ_ABORT */ +#define WM8962_WSEQ_ABORT_SHIFT 8 /* WSEQ_ABORT */ +#define WM8962_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ +#define WM8962_WSEQ_START 0x0080 /* WSEQ_START */ +#define WM8962_WSEQ_START_MASK 0x0080 /* WSEQ_START */ +#define WM8962_WSEQ_START_SHIFT 7 /* WSEQ_START */ +#define WM8962_WSEQ_START_WIDTH 1 /* WSEQ_START */ +#define WM8962_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */ +#define WM8962_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */ +#define WM8962_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */ + +/* + * R93 (0x5D) - Write Sequencer Control 3 + */ +#define WM8962_WSEQ_CURRENT_INDEX_MASK 0x03F8 /* WSEQ_CURRENT_INDEX - [9:3] */ +#define WM8962_WSEQ_CURRENT_INDEX_SHIFT 3 /* WSEQ_CURRENT_INDEX - [9:3] */ +#define WM8962_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [9:3] */ +#define WM8962_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ +#define WM8962_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ +#define WM8962_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ +#define WM8962_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ + +/* + * R94 (0x5E) - Control Interface + */ +#define WM8962_SPI_CONTRD 0x0040 /* SPI_CONTRD */ +#define WM8962_SPI_CONTRD_MASK 0x0040 /* SPI_CONTRD */ +#define WM8962_SPI_CONTRD_SHIFT 6 /* SPI_CONTRD */ +#define WM8962_SPI_CONTRD_WIDTH 1 /* SPI_CONTRD */ +#define WM8962_SPI_4WIRE 0x0020 /* SPI_4WIRE */ +#define WM8962_SPI_4WIRE_MASK 0x0020 /* SPI_4WIRE */ +#define WM8962_SPI_4WIRE_SHIFT 5 /* SPI_4WIRE */ +#define WM8962_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */ +#define WM8962_SPI_CFG 0x0010 /* SPI_CFG */ +#define WM8962_SPI_CFG_MASK 0x0010 /* SPI_CFG */ +#define WM8962_SPI_CFG_SHIFT 4 /* SPI_CFG */ +#define WM8962_SPI_CFG_WIDTH 1 /* SPI_CFG */ + +/* + * R99 (0x63) - Mixer Enables + */ +#define WM8962_HPMIXL_ENA 0x0008 /* HPMIXL_ENA */ +#define WM8962_HPMIXL_ENA_MASK 0x0008 /* HPMIXL_ENA */ +#define WM8962_HPMIXL_ENA_SHIFT 3 /* HPMIXL_ENA */ +#define WM8962_HPMIXL_ENA_WIDTH 1 /* HPMIXL_ENA */ +#define WM8962_HPMIXR_ENA 0x0004 /* HPMIXR_ENA */ +#define WM8962_HPMIXR_ENA_MASK 0x0004 /* HPMIXR_ENA */ +#define WM8962_HPMIXR_ENA_SHIFT 2 /* HPMIXR_ENA */ +#define WM8962_HPMIXR_ENA_WIDTH 1 /* HPMIXR_ENA */ +#define WM8962_SPKMIXL_ENA 0x0002 /* SPKMIXL_ENA */ +#define WM8962_SPKMIXL_ENA_MASK 0x0002 /* SPKMIXL_ENA */ +#define WM8962_SPKMIXL_ENA_SHIFT 1 /* SPKMIXL_ENA */ +#define WM8962_SPKMIXL_ENA_WIDTH 1 /* SPKMIXL_ENA */ +#define WM8962_SPKMIXR_ENA 0x0001 /* SPKMIXR_ENA */ +#define WM8962_SPKMIXR_ENA_MASK 0x0001 /* SPKMIXR_ENA */ +#define WM8962_SPKMIXR_ENA_SHIFT 0 /* SPKMIXR_ENA */ +#define WM8962_SPKMIXR_ENA_WIDTH 1 /* SPKMIXR_ENA */ + +/* + * R100 (0x64) - Headphone Mixer (1) + */ +#define WM8962_HPMIXL_TO_HPOUTL_PGA 0x0080 /* HPMIXL_TO_HPOUTL_PGA */ +#define WM8962_HPMIXL_TO_HPOUTL_PGA_MASK 0x0080 /* HPMIXL_TO_HPOUTL_PGA */ +#define WM8962_HPMIXL_TO_HPOUTL_PGA_SHIFT 7 /* HPMIXL_TO_HPOUTL_PGA */ +#define WM8962_HPMIXL_TO_HPOUTL_PGA_WIDTH 1 /* HPMIXL_TO_HPOUTL_PGA */ +#define WM8962_DACL_TO_HPMIXL 0x0020 /* DACL_TO_HPMIXL */ +#define WM8962_DACL_TO_HPMIXL_MASK 0x0020 /* DACL_TO_HPMIXL */ +#define WM8962_DACL_TO_HPMIXL_SHIFT 5 /* DACL_TO_HPMIXL */ +#define WM8962_DACL_TO_HPMIXL_WIDTH 1 /* DACL_TO_HPMIXL */ +#define WM8962_DACR_TO_HPMIXL 0x0010 /* DACR_TO_HPMIXL */ +#define WM8962_DACR_TO_HPMIXL_MASK 0x0010 /* DACR_TO_HPMIXL */ +#define WM8962_DACR_TO_HPMIXL_SHIFT 4 /* DACR_TO_HPMIXL */ +#define WM8962_DACR_TO_HPMIXL_WIDTH 1 /* DACR_TO_HPMIXL */ +#define WM8962_MIXINL_TO_HPMIXL 0x0008 /* MIXINL_TO_HPMIXL */ +#define WM8962_MIXINL_TO_HPMIXL_MASK 0x0008 /* MIXINL_TO_HPMIXL */ +#define WM8962_MIXINL_TO_HPMIXL_SHIFT 3 /* MIXINL_TO_HPMIXL */ +#define WM8962_MIXINL_TO_HPMIXL_WIDTH 1 /* MIXINL_TO_HPMIXL */ +#define WM8962_MIXINR_TO_HPMIXL 0x0004 /* MIXINR_TO_HPMIXL */ +#define WM8962_MIXINR_TO_HPMIXL_MASK 0x0004 /* MIXINR_TO_HPMIXL */ +#define WM8962_MIXINR_TO_HPMIXL_SHIFT 2 /* MIXINR_TO_HPMIXL */ +#define WM8962_MIXINR_TO_HPMIXL_WIDTH 1 /* MIXINR_TO_HPMIXL */ +#define WM8962_IN4L_TO_HPMIXL 0x0002 /* IN4L_TO_HPMIXL */ +#define WM8962_IN4L_TO_HPMIXL_MASK 0x0002 /* IN4L_TO_HPMIXL */ +#define WM8962_IN4L_TO_HPMIXL_SHIFT 1 /* IN4L_TO_HPMIXL */ +#define WM8962_IN4L_TO_HPMIXL_WIDTH 1 /* IN4L_TO_HPMIXL */ +#define WM8962_IN4R_TO_HPMIXL 0x0001 /* IN4R_TO_HPMIXL */ +#define WM8962_IN4R_TO_HPMIXL_MASK 0x0001 /* IN4R_TO_HPMIXL */ +#define WM8962_IN4R_TO_HPMIXL_SHIFT 0 /* IN4R_TO_HPMIXL */ +#define WM8962_IN4R_TO_HPMIXL_WIDTH 1 /* IN4R_TO_HPMIXL */ + +/* + * R101 (0x65) - Headphone Mixer (2) + */ +#define WM8962_HPMIXR_TO_HPOUTR_PGA 0x0080 /* HPMIXR_TO_HPOUTR_PGA */ +#define WM8962_HPMIXR_TO_HPOUTR_PGA_MASK 0x0080 /* HPMIXR_TO_HPOUTR_PGA */ +#define WM8962_HPMIXR_TO_HPOUTR_PGA_SHIFT 7 /* HPMIXR_TO_HPOUTR_PGA */ +#define WM8962_HPMIXR_TO_HPOUTR_PGA_WIDTH 1 /* HPMIXR_TO_HPOUTR_PGA */ +#define WM8962_DACL_TO_HPMIXR 0x0020 /* DACL_TO_HPMIXR */ +#define WM8962_DACL_TO_HPMIXR_MASK 0x0020 /* DACL_TO_HPMIXR */ +#define WM8962_DACL_TO_HPMIXR_SHIFT 5 /* DACL_TO_HPMIXR */ +#define WM8962_DACL_TO_HPMIXR_WIDTH 1 /* DACL_TO_HPMIXR */ +#define WM8962_DACR_TO_HPMIXR 0x0010 /* DACR_TO_HPMIXR */ +#define WM8962_DACR_TO_HPMIXR_MASK 0x0010 /* DACR_TO_HPMIXR */ +#define WM8962_DACR_TO_HPMIXR_SHIFT 4 /* DACR_TO_HPMIXR */ +#define WM8962_DACR_TO_HPMIXR_WIDTH 1 /* DACR_TO_HPMIXR */ +#define WM8962_MIXINL_TO_HPMIXR 0x0008 /* MIXINL_TO_HPMIXR */ +#define WM8962_MIXINL_TO_HPMIXR_MASK 0x0008 /* MIXINL_TO_HPMIXR */ +#define WM8962_MIXINL_TO_HPMIXR_SHIFT 3 /* MIXINL_TO_HPMIXR */ +#define WM8962_MIXINL_TO_HPMIXR_WIDTH 1 /* MIXINL_TO_HPMIXR */ +#define WM8962_MIXINR_TO_HPMIXR 0x0004 /* MIXINR_TO_HPMIXR */ +#define WM8962_MIXINR_TO_HPMIXR_MASK 0x0004 /* MIXINR_TO_HPMIXR */ +#define WM8962_MIXINR_TO_HPMIXR_SHIFT 2 /* MIXINR_TO_HPMIXR */ +#define WM8962_MIXINR_TO_HPMIXR_WIDTH 1 /* MIXINR_TO_HPMIXR */ +#define WM8962_IN4L_TO_HPMIXR 0x0002 /* IN4L_TO_HPMIXR */ +#define WM8962_IN4L_TO_HPMIXR_MASK 0x0002 /* IN4L_TO_HPMIXR */ +#define WM8962_IN4L_TO_HPMIXR_SHIFT 1 /* IN4L_TO_HPMIXR */ +#define WM8962_IN4L_TO_HPMIXR_WIDTH 1 /* IN4L_TO_HPMIXR */ +#define WM8962_IN4R_TO_HPMIXR 0x0001 /* IN4R_TO_HPMIXR */ +#define WM8962_IN4R_TO_HPMIXR_MASK 0x0001 /* IN4R_TO_HPMIXR */ +#define WM8962_IN4R_TO_HPMIXR_SHIFT 0 /* IN4R_TO_HPMIXR */ +#define WM8962_IN4R_TO_HPMIXR_WIDTH 1 /* IN4R_TO_HPMIXR */ + +/* + * R102 (0x66) - Headphone Mixer (3) + */ +#define WM8962_HPMIXL_MUTE 0x0100 /* HPMIXL_MUTE */ +#define WM8962_HPMIXL_MUTE_MASK 0x0100 /* HPMIXL_MUTE */ +#define WM8962_HPMIXL_MUTE_SHIFT 8 /* HPMIXL_MUTE */ +#define WM8962_HPMIXL_MUTE_WIDTH 1 /* HPMIXL_MUTE */ +#define WM8962_MIXINL_HPMIXL_VOL 0x0080 /* MIXINL_HPMIXL_VOL */ +#define WM8962_MIXINL_HPMIXL_VOL_MASK 0x0080 /* MIXINL_HPMIXL_VOL */ +#define WM8962_MIXINL_HPMIXL_VOL_SHIFT 7 /* MIXINL_HPMIXL_VOL */ +#define WM8962_MIXINL_HPMIXL_VOL_WIDTH 1 /* MIXINL_HPMIXL_VOL */ +#define WM8962_MIXINR_HPMIXL_VOL 0x0040 /* MIXINR_HPMIXL_VOL */ +#define WM8962_MIXINR_HPMIXL_VOL_MASK 0x0040 /* MIXINR_HPMIXL_VOL */ +#define WM8962_MIXINR_HPMIXL_VOL_SHIFT 6 /* MIXINR_HPMIXL_VOL */ +#define WM8962_MIXINR_HPMIXL_VOL_WIDTH 1 /* MIXINR_HPMIXL_VOL */ +#define WM8962_IN4L_HPMIXL_VOL_MASK 0x0038 /* IN4L_HPMIXL_VOL - [5:3] */ +#define WM8962_IN4L_HPMIXL_VOL_SHIFT 3 /* IN4L_HPMIXL_VOL - [5:3] */ +#define WM8962_IN4L_HPMIXL_VOL_WIDTH 3 /* IN4L_HPMIXL_VOL - [5:3] */ +#define WM8962_IN4R_HPMIXL_VOL_MASK 0x0007 /* IN4R_HPMIXL_VOL - [2:0] */ +#define WM8962_IN4R_HPMIXL_VOL_SHIFT 0 /* IN4R_HPMIXL_VOL - [2:0] */ +#define WM8962_IN4R_HPMIXL_VOL_WIDTH 3 /* IN4R_HPMIXL_VOL - [2:0] */ + +/* + * R103 (0x67) - Headphone Mixer (4) + */ +#define WM8962_HPMIXR_MUTE 0x0100 /* HPMIXR_MUTE */ +#define WM8962_HPMIXR_MUTE_MASK 0x0100 /* HPMIXR_MUTE */ +#define WM8962_HPMIXR_MUTE_SHIFT 8 /* HPMIXR_MUTE */ +#define WM8962_HPMIXR_MUTE_WIDTH 1 /* HPMIXR_MUTE */ +#define WM8962_MIXINL_HPMIXR_VOL 0x0080 /* MIXINL_HPMIXR_VOL */ +#define WM8962_MIXINL_HPMIXR_VOL_MASK 0x0080 /* MIXINL_HPMIXR_VOL */ +#define WM8962_MIXINL_HPMIXR_VOL_SHIFT 7 /* MIXINL_HPMIXR_VOL */ +#define WM8962_MIXINL_HPMIXR_VOL_WIDTH 1 /* MIXINL_HPMIXR_VOL */ +#define WM8962_MIXINR_HPMIXR_VOL 0x0040 /* MIXINR_HPMIXR_VOL */ +#define WM8962_MIXINR_HPMIXR_VOL_MASK 0x0040 /* MIXINR_HPMIXR_VOL */ +#define WM8962_MIXINR_HPMIXR_VOL_SHIFT 6 /* MIXINR_HPMIXR_VOL */ +#define WM8962_MIXINR_HPMIXR_VOL_WIDTH 1 /* MIXINR_HPMIXR_VOL */ +#define WM8962_IN4L_HPMIXR_VOL_MASK 0x0038 /* IN4L_HPMIXR_VOL - [5:3] */ +#define WM8962_IN4L_HPMIXR_VOL_SHIFT 3 /* IN4L_HPMIXR_VOL - [5:3] */ +#define WM8962_IN4L_HPMIXR_VOL_WIDTH 3 /* IN4L_HPMIXR_VOL - [5:3] */ +#define WM8962_IN4R_HPMIXR_VOL_MASK 0x0007 /* IN4R_HPMIXR_VOL - [2:0] */ +#define WM8962_IN4R_HPMIXR_VOL_SHIFT 0 /* IN4R_HPMIXR_VOL - [2:0] */ +#define WM8962_IN4R_HPMIXR_VOL_WIDTH 3 /* IN4R_HPMIXR_VOL - [2:0] */ + +/* + * R105 (0x69) - Speaker Mixer (1) + */ +#define WM8962_SPKMIXL_TO_SPKOUTL_PGA 0x0080 /* SPKMIXL_TO_SPKOUTL_PGA */ +#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_MASK 0x0080 /* SPKMIXL_TO_SPKOUTL_PGA */ +#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_SHIFT 7 /* SPKMIXL_TO_SPKOUTL_PGA */ +#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_WIDTH 1 /* SPKMIXL_TO_SPKOUTL_PGA */ +#define WM8962_DACL_TO_SPKMIXL 0x0020 /* DACL_TO_SPKMIXL */ +#define WM8962_DACL_TO_SPKMIXL_MASK 0x0020 /* DACL_TO_SPKMIXL */ +#define WM8962_DACL_TO_SPKMIXL_SHIFT 5 /* DACL_TO_SPKMIXL */ +#define WM8962_DACL_TO_SPKMIXL_WIDTH 1 /* DACL_TO_SPKMIXL */ +#define WM8962_DACR_TO_SPKMIXL 0x0010 /* DACR_TO_SPKMIXL */ +#define WM8962_DACR_TO_SPKMIXL_MASK 0x0010 /* DACR_TO_SPKMIXL */ +#define WM8962_DACR_TO_SPKMIXL_SHIFT 4 /* DACR_TO_SPKMIXL */ +#define WM8962_DACR_TO_SPKMIXL_WIDTH 1 /* DACR_TO_SPKMIXL */ +#define WM8962_MIXINL_TO_SPKMIXL 0x0008 /* MIXINL_TO_SPKMIXL */ +#define WM8962_MIXINL_TO_SPKMIXL_MASK 0x0008 /* MIXINL_TO_SPKMIXL */ +#define WM8962_MIXINL_TO_SPKMIXL_SHIFT 3 /* MIXINL_TO_SPKMIXL */ +#define WM8962_MIXINL_TO_SPKMIXL_WIDTH 1 /* MIXINL_TO_SPKMIXL */ +#define WM8962_MIXINR_TO_SPKMIXL 0x0004 /* MIXINR_TO_SPKMIXL */ +#define WM8962_MIXINR_TO_SPKMIXL_MASK 0x0004 /* MIXINR_TO_SPKMIXL */ +#define WM8962_MIXINR_TO_SPKMIXL_SHIFT 2 /* MIXINR_TO_SPKMIXL */ +#define WM8962_MIXINR_TO_SPKMIXL_WIDTH 1 /* MIXINR_TO_SPKMIXL */ +#define WM8962_IN4L_TO_SPKMIXL 0x0002 /* IN4L_TO_SPKMIXL */ +#define WM8962_IN4L_TO_SPKMIXL_MASK 0x0002 /* IN4L_TO_SPKMIXL */ +#define WM8962_IN4L_TO_SPKMIXL_SHIFT 1 /* IN4L_TO_SPKMIXL */ +#define WM8962_IN4L_TO_SPKMIXL_WIDTH 1 /* IN4L_TO_SPKMIXL */ +#define WM8962_IN4R_TO_SPKMIXL 0x0001 /* IN4R_TO_SPKMIXL */ +#define WM8962_IN4R_TO_SPKMIXL_MASK 0x0001 /* IN4R_TO_SPKMIXL */ +#define WM8962_IN4R_TO_SPKMIXL_SHIFT 0 /* IN4R_TO_SPKMIXL */ +#define WM8962_IN4R_TO_SPKMIXL_WIDTH 1 /* IN4R_TO_SPKMIXL */ + +/* + * R106 (0x6A) - Speaker Mixer (2) + */ +#define WM8962_SPKMIXR_TO_SPKOUTR_PGA 0x0080 /* SPKMIXR_TO_SPKOUTR_PGA */ +#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_MASK 0x0080 /* SPKMIXR_TO_SPKOUTR_PGA */ +#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_SHIFT 7 /* SPKMIXR_TO_SPKOUTR_PGA */ +#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_WIDTH 1 /* SPKMIXR_TO_SPKOUTR_PGA */ +#define WM8962_DACL_TO_SPKMIXR 0x0020 /* DACL_TO_SPKMIXR */ +#define WM8962_DACL_TO_SPKMIXR_MASK 0x0020 /* DACL_TO_SPKMIXR */ +#define WM8962_DACL_TO_SPKMIXR_SHIFT 5 /* DACL_TO_SPKMIXR */ +#define WM8962_DACL_TO_SPKMIXR_WIDTH 1 /* DACL_TO_SPKMIXR */ +#define WM8962_DACR_TO_SPKMIXR 0x0010 /* DACR_TO_SPKMIXR */ +#define WM8962_DACR_TO_SPKMIXR_MASK 0x0010 /* DACR_TO_SPKMIXR */ +#define WM8962_DACR_TO_SPKMIXR_SHIFT 4 /* DACR_TO_SPKMIXR */ +#define WM8962_DACR_TO_SPKMIXR_WIDTH 1 /* DACR_TO_SPKMIXR */ +#define WM8962_MIXINL_TO_SPKMIXR 0x0008 /* MIXINL_TO_SPKMIXR */ +#define WM8962_MIXINL_TO_SPKMIXR_MASK 0x0008 /* MIXINL_TO_SPKMIXR */ +#define WM8962_MIXINL_TO_SPKMIXR_SHIFT 3 /* MIXINL_TO_SPKMIXR */ +#define WM8962_MIXINL_TO_SPKMIXR_WIDTH 1 /* MIXINL_TO_SPKMIXR */ +#define WM8962_MIXINR_TO_SPKMIXR 0x0004 /* MIXINR_TO_SPKMIXR */ +#define WM8962_MIXINR_TO_SPKMIXR_MASK 0x0004 /* MIXINR_TO_SPKMIXR */ +#define WM8962_MIXINR_TO_SPKMIXR_SHIFT 2 /* MIXINR_TO_SPKMIXR */ +#define WM8962_MIXINR_TO_SPKMIXR_WIDTH 1 /* MIXINR_TO_SPKMIXR */ +#define WM8962_IN4L_TO_SPKMIXR 0x0002 /* IN4L_TO_SPKMIXR */ +#define WM8962_IN4L_TO_SPKMIXR_MASK 0x0002 /* IN4L_TO_SPKMIXR */ +#define WM8962_IN4L_TO_SPKMIXR_SHIFT 1 /* IN4L_TO_SPKMIXR */ +#define WM8962_IN4L_TO_SPKMIXR_WIDTH 1 /* IN4L_TO_SPKMIXR */ +#define WM8962_IN4R_TO_SPKMIXR 0x0001 /* IN4R_TO_SPKMIXR */ +#define WM8962_IN4R_TO_SPKMIXR_MASK 0x0001 /* IN4R_TO_SPKMIXR */ +#define WM8962_IN4R_TO_SPKMIXR_SHIFT 0 /* IN4R_TO_SPKMIXR */ +#define WM8962_IN4R_TO_SPKMIXR_WIDTH 1 /* IN4R_TO_SPKMIXR */ + +/* + * R107 (0x6B) - Speaker Mixer (3) + */ +#define WM8962_SPKMIXL_MUTE 0x0100 /* SPKMIXL_MUTE */ +#define WM8962_SPKMIXL_MUTE_MASK 0x0100 /* SPKMIXL_MUTE */ +#define WM8962_SPKMIXL_MUTE_SHIFT 8 /* SPKMIXL_MUTE */ +#define WM8962_SPKMIXL_MUTE_WIDTH 1 /* SPKMIXL_MUTE */ +#define WM8962_MIXINL_SPKMIXL_VOL 0x0080 /* MIXINL_SPKMIXL_VOL */ +#define WM8962_MIXINL_SPKMIXL_VOL_MASK 0x0080 /* MIXINL_SPKMIXL_VOL */ +#define WM8962_MIXINL_SPKMIXL_VOL_SHIFT 7 /* MIXINL_SPKMIXL_VOL */ +#define WM8962_MIXINL_SPKMIXL_VOL_WIDTH 1 /* MIXINL_SPKMIXL_VOL */ +#define WM8962_MIXINR_SPKMIXL_VOL 0x0040 /* MIXINR_SPKMIXL_VOL */ +#define WM8962_MIXINR_SPKMIXL_VOL_MASK 0x0040 /* MIXINR_SPKMIXL_VOL */ +#define WM8962_MIXINR_SPKMIXL_VOL_SHIFT 6 /* MIXINR_SPKMIXL_VOL */ +#define WM8962_MIXINR_SPKMIXL_VOL_WIDTH 1 /* MIXINR_SPKMIXL_VOL */ +#define WM8962_IN4L_SPKMIXL_VOL_MASK 0x0038 /* IN4L_SPKMIXL_VOL - [5:3] */ +#define WM8962_IN4L_SPKMIXL_VOL_SHIFT 3 /* IN4L_SPKMIXL_VOL - [5:3] */ +#define WM8962_IN4L_SPKMIXL_VOL_WIDTH 3 /* IN4L_SPKMIXL_VOL - [5:3] */ +#define WM8962_IN4R_SPKMIXL_VOL_MASK 0x0007 /* IN4R_SPKMIXL_VOL - [2:0] */ +#define WM8962_IN4R_SPKMIXL_VOL_SHIFT 0 /* IN4R_SPKMIXL_VOL - [2:0] */ +#define WM8962_IN4R_SPKMIXL_VOL_WIDTH 3 /* IN4R_SPKMIXL_VOL - [2:0] */ + +/* + * R108 (0x6C) - Speaker Mixer (4) + */ +#define WM8962_SPKMIXR_MUTE 0x0100 /* SPKMIXR_MUTE */ +#define WM8962_SPKMIXR_MUTE_MASK 0x0100 /* SPKMIXR_MUTE */ +#define WM8962_SPKMIXR_MUTE_SHIFT 8 /* SPKMIXR_MUTE */ +#define WM8962_SPKMIXR_MUTE_WIDTH 1 /* SPKMIXR_MUTE */ +#define WM8962_MIXINL_SPKMIXR_VOL 0x0080 /* MIXINL_SPKMIXR_VOL */ +#define WM8962_MIXINL_SPKMIXR_VOL_MASK 0x0080 /* MIXINL_SPKMIXR_VOL */ +#define WM8962_MIXINL_SPKMIXR_VOL_SHIFT 7 /* MIXINL_SPKMIXR_VOL */ +#define WM8962_MIXINL_SPKMIXR_VOL_WIDTH 1 /* MIXINL_SPKMIXR_VOL */ +#define WM8962_MIXINR_SPKMIXR_VOL 0x0040 /* MIXINR_SPKMIXR_VOL */ +#define WM8962_MIXINR_SPKMIXR_VOL_MASK 0x0040 /* MIXINR_SPKMIXR_VOL */ +#define WM8962_MIXINR_SPKMIXR_VOL_SHIFT 6 /* MIXINR_SPKMIXR_VOL */ +#define WM8962_MIXINR_SPKMIXR_VOL_WIDTH 1 /* MIXINR_SPKMIXR_VOL */ +#define WM8962_IN4L_SPKMIXR_VOL_MASK 0x0038 /* IN4L_SPKMIXR_VOL - [5:3] */ +#define WM8962_IN4L_SPKMIXR_VOL_SHIFT 3 /* IN4L_SPKMIXR_VOL - [5:3] */ +#define WM8962_IN4L_SPKMIXR_VOL_WIDTH 3 /* IN4L_SPKMIXR_VOL - [5:3] */ +#define WM8962_IN4R_SPKMIXR_VOL_MASK 0x0007 /* IN4R_SPKMIXR_VOL - [2:0] */ +#define WM8962_IN4R_SPKMIXR_VOL_SHIFT 0 /* IN4R_SPKMIXR_VOL - [2:0] */ +#define WM8962_IN4R_SPKMIXR_VOL_WIDTH 3 /* IN4R_SPKMIXR_VOL - [2:0] */ + +/* + * R109 (0x6D) - Speaker Mixer (5) + */ +#define WM8962_DACL_SPKMIXL_VOL 0x0080 /* DACL_SPKMIXL_VOL */ +#define WM8962_DACL_SPKMIXL_VOL_MASK 0x0080 /* DACL_SPKMIXL_VOL */ +#define WM8962_DACL_SPKMIXL_VOL_SHIFT 7 /* DACL_SPKMIXL_VOL */ +#define WM8962_DACL_SPKMIXL_VOL_WIDTH 1 /* DACL_SPKMIXL_VOL */ +#define WM8962_DACR_SPKMIXL_VOL 0x0040 /* DACR_SPKMIXL_VOL */ +#define WM8962_DACR_SPKMIXL_VOL_MASK 0x0040 /* DACR_SPKMIXL_VOL */ +#define WM8962_DACR_SPKMIXL_VOL_SHIFT 6 /* DACR_SPKMIXL_VOL */ +#define WM8962_DACR_SPKMIXL_VOL_WIDTH 1 /* DACR_SPKMIXL_VOL */ +#define WM8962_DACL_SPKMIXR_VOL 0x0020 /* DACL_SPKMIXR_VOL */ +#define WM8962_DACL_SPKMIXR_VOL_MASK 0x0020 /* DACL_SPKMIXR_VOL */ +#define WM8962_DACL_SPKMIXR_VOL_SHIFT 5 /* DACL_SPKMIXR_VOL */ +#define WM8962_DACL_SPKMIXR_VOL_WIDTH 1 /* DACL_SPKMIXR_VOL */ +#define WM8962_DACR_SPKMIXR_VOL 0x0010 /* DACR_SPKMIXR_VOL */ +#define WM8962_DACR_SPKMIXR_VOL_MASK 0x0010 /* DACR_SPKMIXR_VOL */ +#define WM8962_DACR_SPKMIXR_VOL_SHIFT 4 /* DACR_SPKMIXR_VOL */ +#define WM8962_DACR_SPKMIXR_VOL_WIDTH 1 /* DACR_SPKMIXR_VOL */ + +/* + * R110 (0x6E) - Beep Generator (1) + */ +#define WM8962_BEEP_GAIN_MASK 0x00F0 /* BEEP_GAIN - [7:4] */ +#define WM8962_BEEP_GAIN_SHIFT 4 /* BEEP_GAIN - [7:4] */ +#define WM8962_BEEP_GAIN_WIDTH 4 /* BEEP_GAIN - [7:4] */ +#define WM8962_BEEP_RATE_MASK 0x0006 /* BEEP_RATE - [2:1] */ +#define WM8962_BEEP_RATE_SHIFT 1 /* BEEP_RATE - [2:1] */ +#define WM8962_BEEP_RATE_WIDTH 2 /* BEEP_RATE - [2:1] */ +#define WM8962_BEEP_ENA 0x0001 /* BEEP_ENA */ +#define WM8962_BEEP_ENA_MASK 0x0001 /* BEEP_ENA */ +#define WM8962_BEEP_ENA_SHIFT 0 /* BEEP_ENA */ +#define WM8962_BEEP_ENA_WIDTH 1 /* BEEP_ENA */ + +/* + * R115 (0x73) - Oscillator Trim (3) + */ +#define WM8962_OSC_TRIM_XTI_MASK 0x001F /* OSC_TRIM_XTI - [4:0] */ +#define WM8962_OSC_TRIM_XTI_SHIFT 0 /* OSC_TRIM_XTI - [4:0] */ +#define WM8962_OSC_TRIM_XTI_WIDTH 5 /* OSC_TRIM_XTI - [4:0] */ + +/* + * R116 (0x74) - Oscillator Trim (4) + */ +#define WM8962_OSC_TRIM_XTO_MASK 0x001F /* OSC_TRIM_XTO - [4:0] */ +#define WM8962_OSC_TRIM_XTO_SHIFT 0 /* OSC_TRIM_XTO - [4:0] */ +#define WM8962_OSC_TRIM_XTO_WIDTH 5 /* OSC_TRIM_XTO - [4:0] */ + +/* + * R119 (0x77) - Oscillator Trim (7) + */ +#define WM8962_XTO_CAP_SEL_MASK 0x00F0 /* XTO_CAP_SEL - [7:4] */ +#define WM8962_XTO_CAP_SEL_SHIFT 4 /* XTO_CAP_SEL - [7:4] */ +#define WM8962_XTO_CAP_SEL_WIDTH 4 /* XTO_CAP_SEL - [7:4] */ +#define WM8962_XTI_CAP_SEL_MASK 0x000F /* XTI_CAP_SEL - [3:0] */ +#define WM8962_XTI_CAP_SEL_SHIFT 0 /* XTI_CAP_SEL - [3:0] */ +#define WM8962_XTI_CAP_SEL_WIDTH 4 /* XTI_CAP_SEL - [3:0] */ + +/* + * R124 (0x7C) - Analogue Clocking1 + */ +#define WM8962_CLKOUT2_SEL_MASK 0x0060 /* CLKOUT2_SEL - [6:5] */ +#define WM8962_CLKOUT2_SEL_SHIFT 5 /* CLKOUT2_SEL - [6:5] */ +#define WM8962_CLKOUT2_SEL_WIDTH 2 /* CLKOUT2_SEL - [6:5] */ +#define WM8962_CLKOUT3_SEL_MASK 0x0018 /* CLKOUT3_SEL - [4:3] */ +#define WM8962_CLKOUT3_SEL_SHIFT 3 /* CLKOUT3_SEL - [4:3] */ +#define WM8962_CLKOUT3_SEL_WIDTH 2 /* CLKOUT3_SEL - [4:3] */ +#define WM8962_CLKOUT5_SEL 0x0001 /* CLKOUT5_SEL */ +#define WM8962_CLKOUT5_SEL_MASK 0x0001 /* CLKOUT5_SEL */ +#define WM8962_CLKOUT5_SEL_SHIFT 0 /* CLKOUT5_SEL */ +#define WM8962_CLKOUT5_SEL_WIDTH 1 /* CLKOUT5_SEL */ + +/* + * R125 (0x7D) - Analogue Clocking2 + */ +#define WM8962_PLL2_OUTDIV 0x0080 /* PLL2_OUTDIV */ +#define WM8962_PLL2_OUTDIV_MASK 0x0080 /* PLL2_OUTDIV */ +#define WM8962_PLL2_OUTDIV_SHIFT 7 /* PLL2_OUTDIV */ +#define WM8962_PLL2_OUTDIV_WIDTH 1 /* PLL2_OUTDIV */ +#define WM8962_PLL3_OUTDIV 0x0040 /* PLL3_OUTDIV */ +#define WM8962_PLL3_OUTDIV_MASK 0x0040 /* PLL3_OUTDIV */ +#define WM8962_PLL3_OUTDIV_SHIFT 6 /* PLL3_OUTDIV */ +#define WM8962_PLL3_OUTDIV_WIDTH 1 /* PLL3_OUTDIV */ +#define WM8962_PLL_SYSCLK_DIV_MASK 0x0018 /* PLL_SYSCLK_DIV - [4:3] */ +#define WM8962_PLL_SYSCLK_DIV_SHIFT 3 /* PLL_SYSCLK_DIV - [4:3] */ +#define WM8962_PLL_SYSCLK_DIV_WIDTH 2 /* PLL_SYSCLK_DIV - [4:3] */ +#define WM8962_CLKOUT3_DIV 0x0004 /* CLKOUT3_DIV */ +#define WM8962_CLKOUT3_DIV_MASK 0x0004 /* CLKOUT3_DIV */ +#define WM8962_CLKOUT3_DIV_SHIFT 2 /* CLKOUT3_DIV */ +#define WM8962_CLKOUT3_DIV_WIDTH 1 /* CLKOUT3_DIV */ +#define WM8962_CLKOUT2_DIV 0x0002 /* CLKOUT2_DIV */ +#define WM8962_CLKOUT2_DIV_MASK 0x0002 /* CLKOUT2_DIV */ +#define WM8962_CLKOUT2_DIV_SHIFT 1 /* CLKOUT2_DIV */ +#define WM8962_CLKOUT2_DIV_WIDTH 1 /* CLKOUT2_DIV */ +#define WM8962_CLKOUT5_DIV 0x0001 /* CLKOUT5_DIV */ +#define WM8962_CLKOUT5_DIV_MASK 0x0001 /* CLKOUT5_DIV */ +#define WM8962_CLKOUT5_DIV_SHIFT 0 /* CLKOUT5_DIV */ +#define WM8962_CLKOUT5_DIV_WIDTH 1 /* CLKOUT5_DIV */ + +/* + * R126 (0x7E) - Analogue Clocking3 + */ +#define WM8962_CLKOUT2_OE 0x0008 /* CLKOUT2_OE */ +#define WM8962_CLKOUT2_OE_MASK 0x0008 /* CLKOUT2_OE */ +#define WM8962_CLKOUT2_OE_SHIFT 3 /* CLKOUT2_OE */ +#define WM8962_CLKOUT2_OE_WIDTH 1 /* CLKOUT2_OE */ +#define WM8962_CLKOUT3_OE 0x0004 /* CLKOUT3_OE */ +#define WM8962_CLKOUT3_OE_MASK 0x0004 /* CLKOUT3_OE */ +#define WM8962_CLKOUT3_OE_SHIFT 2 /* CLKOUT3_OE */ +#define WM8962_CLKOUT3_OE_WIDTH 1 /* CLKOUT3_OE */ +#define WM8962_CLKOUT5_OE 0x0001 /* CLKOUT5_OE */ +#define WM8962_CLKOUT5_OE_MASK 0x0001 /* CLKOUT5_OE */ +#define WM8962_CLKOUT5_OE_SHIFT 0 /* CLKOUT5_OE */ +#define WM8962_CLKOUT5_OE_WIDTH 1 /* CLKOUT5_OE */ + +/* + * R127 (0x7F) - PLL Software Reset + */ +#define WM8962_SW_RESET_PLL_MASK 0xFFFF /* SW_RESET_PLL - [15:0] */ +#define WM8962_SW_RESET_PLL_SHIFT 0 /* SW_RESET_PLL - [15:0] */ +#define WM8962_SW_RESET_PLL_WIDTH 16 /* SW_RESET_PLL - [15:0] */ + +/* + * R129 (0x81) - PLL2 + */ +#define WM8962_OSC_ENA 0x0080 /* OSC_ENA */ +#define WM8962_OSC_ENA_MASK 0x0080 /* OSC_ENA */ +#define WM8962_OSC_ENA_SHIFT 7 /* OSC_ENA */ +#define WM8962_OSC_ENA_WIDTH 1 /* OSC_ENA */ +#define WM8962_PLL2_ENA 0x0020 /* PLL2_ENA */ +#define WM8962_PLL2_ENA_MASK 0x0020 /* PLL2_ENA */ +#define WM8962_PLL2_ENA_SHIFT 5 /* PLL2_ENA */ +#define WM8962_PLL2_ENA_WIDTH 1 /* PLL2_ENA */ +#define WM8962_PLL3_ENA 0x0010 /* PLL3_ENA */ +#define WM8962_PLL3_ENA_MASK 0x0010 /* PLL3_ENA */ +#define WM8962_PLL3_ENA_SHIFT 4 /* PLL3_ENA */ +#define WM8962_PLL3_ENA_WIDTH 1 /* PLL3_ENA */ + +/* + * R131 (0x83) - PLL 4 + */ +#define WM8962_PLL_CLK_SRC 0x0002 /* PLL_CLK_SRC */ +#define WM8962_PLL_CLK_SRC_MASK 0x0002 /* PLL_CLK_SRC */ +#define WM8962_PLL_CLK_SRC_SHIFT 1 /* PLL_CLK_SRC */ +#define WM8962_PLL_CLK_SRC_WIDTH 1 /* PLL_CLK_SRC */ +#define WM8962_FLL_TO_PLL3 0x0001 /* FLL_TO_PLL3 */ +#define WM8962_FLL_TO_PLL3_MASK 0x0001 /* FLL_TO_PLL3 */ +#define WM8962_FLL_TO_PLL3_SHIFT 0 /* FLL_TO_PLL3 */ +#define WM8962_FLL_TO_PLL3_WIDTH 1 /* FLL_TO_PLL3 */ + +/* + * R136 (0x88) - PLL 9 + */ +#define WM8962_PLL2_FRAC 0x0040 /* PLL2_FRAC */ +#define WM8962_PLL2_FRAC_MASK 0x0040 /* PLL2_FRAC */ +#define WM8962_PLL2_FRAC_SHIFT 6 /* PLL2_FRAC */ +#define WM8962_PLL2_FRAC_WIDTH 1 /* PLL2_FRAC */ +#define WM8962_PLL2_N_MASK 0x001F /* PLL2_N - [4:0] */ +#define WM8962_PLL2_N_SHIFT 0 /* PLL2_N - [4:0] */ +#define WM8962_PLL2_N_WIDTH 5 /* PLL2_N - [4:0] */ + +/* + * R137 (0x89) - PLL 10 + */ +#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */ +#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */ +#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */ + +/* + * R138 (0x8A) - PLL 11 + */ +#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */ +#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */ +#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */ + +/* + * R139 (0x8B) - PLL 12 + */ +#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */ +#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */ +#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */ + +/* + * R140 (0x8C) - PLL 13 + */ +#define WM8962_PLL3_FRAC 0x0040 /* PLL3_FRAC */ +#define WM8962_PLL3_FRAC_MASK 0x0040 /* PLL3_FRAC */ +#define WM8962_PLL3_FRAC_SHIFT 6 /* PLL3_FRAC */ +#define WM8962_PLL3_FRAC_WIDTH 1 /* PLL3_FRAC */ +#define WM8962_PLL3_N_MASK 0x001F /* PLL3_N - [4:0] */ +#define WM8962_PLL3_N_SHIFT 0 /* PLL3_N - [4:0] */ +#define WM8962_PLL3_N_WIDTH 5 /* PLL3_N - [4:0] */ + +/* + * R141 (0x8D) - PLL 14 + */ +#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */ +#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */ +#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */ + +/* + * R142 (0x8E) - PLL 15 + */ +#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */ +#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */ +#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */ + +/* + * R143 (0x8F) - PLL 16 + */ +#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */ +#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */ +#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */ + +/* + * R155 (0x9B) - FLL Control (1) + */ +#define WM8962_FLL_REFCLK_SRC_MASK 0x0060 /* FLL_REFCLK_SRC - [6:5] */ +#define WM8962_FLL_REFCLK_SRC_SHIFT 5 /* FLL_REFCLK_SRC - [6:5] */ +#define WM8962_FLL_REFCLK_SRC_WIDTH 2 /* FLL_REFCLK_SRC - [6:5] */ +#define WM8962_FLL_FRAC 0x0004 /* FLL_FRAC */ +#define WM8962_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */ +#define WM8962_FLL_FRAC_SHIFT 2 /* FLL_FRAC */ +#define WM8962_FLL_FRAC_WIDTH 1 /* FLL_FRAC */ +#define WM8962_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */ +#define WM8962_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */ +#define WM8962_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */ +#define WM8962_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */ +#define WM8962_FLL_ENA 0x0001 /* FLL_ENA */ +#define WM8962_FLL_ENA_MASK 0x0001 /* FLL_ENA */ +#define WM8962_FLL_ENA_SHIFT 0 /* FLL_ENA */ +#define WM8962_FLL_ENA_WIDTH 1 /* FLL_ENA */ + +/* + * R156 (0x9C) - FLL Control (2) + */ +#define WM8962_FLL_OUTDIV_MASK 0x01F8 /* FLL_OUTDIV - [8:3] */ +#define WM8962_FLL_OUTDIV_SHIFT 3 /* FLL_OUTDIV - [8:3] */ +#define WM8962_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [8:3] */ +#define WM8962_FLL_REFCLK_DIV_MASK 0x0003 /* FLL_REFCLK_DIV - [1:0] */ +#define WM8962_FLL_REFCLK_DIV_SHIFT 0 /* FLL_REFCLK_DIV - [1:0] */ +#define WM8962_FLL_REFCLK_DIV_WIDTH 2 /* FLL_REFCLK_DIV - [1:0] */ + +/* + * R157 (0x9D) - FLL Control (3) + */ +#define WM8962_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */ +#define WM8962_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */ +#define WM8962_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */ + +/* + * R159 (0x9F) - FLL Control (5) + */ +#define WM8962_FLL_FRC_NCO_VAL_MASK 0x007E /* FLL_FRC_NCO_VAL - [6:1] */ +#define WM8962_FLL_FRC_NCO_VAL_SHIFT 1 /* FLL_FRC_NCO_VAL - [6:1] */ +#define WM8962_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [6:1] */ +#define WM8962_FLL_FRC_NCO 0x0001 /* FLL_FRC_NCO */ +#define WM8962_FLL_FRC_NCO_MASK 0x0001 /* FLL_FRC_NCO */ +#define WM8962_FLL_FRC_NCO_SHIFT 0 /* FLL_FRC_NCO */ +#define WM8962_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */ + +/* + * R160 (0xA0) - FLL Control (6) + */ +#define WM8962_FLL_THETA_MASK 0xFFFF /* FLL_THETA - [15:0] */ +#define WM8962_FLL_THETA_SHIFT 0 /* FLL_THETA - [15:0] */ +#define WM8962_FLL_THETA_WIDTH 16 /* FLL_THETA - [15:0] */ + +/* + * R161 (0xA1) - FLL Control (7) + */ +#define WM8962_FLL_LAMBDA_MASK 0xFFFF /* FLL_LAMBDA - [15:0] */ +#define WM8962_FLL_LAMBDA_SHIFT 0 /* FLL_LAMBDA - [15:0] */ +#define WM8962_FLL_LAMBDA_WIDTH 16 /* FLL_LAMBDA - [15:0] */ + +/* + * R162 (0xA2) - FLL Control (8) + */ +#define WM8962_FLL_N_MASK 0x03FF /* FLL_N - [9:0] */ +#define WM8962_FLL_N_SHIFT 0 /* FLL_N - [9:0] */ +#define WM8962_FLL_N_WIDTH 10 /* FLL_N - [9:0] */ + +/* + * R252 (0xFC) - General test 1 + */ +#define WM8962_REG_SYNC 0x0004 /* REG_SYNC */ +#define WM8962_REG_SYNC_MASK 0x0004 /* REG_SYNC */ +#define WM8962_REG_SYNC_SHIFT 2 /* REG_SYNC */ +#define WM8962_REG_SYNC_WIDTH 1 /* REG_SYNC */ +#define WM8962_AUTO_INC 0x0001 /* AUTO_INC */ +#define WM8962_AUTO_INC_MASK 0x0001 /* AUTO_INC */ +#define WM8962_AUTO_INC_SHIFT 0 /* AUTO_INC */ +#define WM8962_AUTO_INC_WIDTH 1 /* AUTO_INC */ + +/* + * R256 (0x100) - DF1 + */ +#define WM8962_DRC_DF1_ENA 0x0008 /* DRC_DF1_ENA */ +#define WM8962_DRC_DF1_ENA_MASK 0x0008 /* DRC_DF1_ENA */ +#define WM8962_DRC_DF1_ENA_SHIFT 3 /* DRC_DF1_ENA */ +#define WM8962_DRC_DF1_ENA_WIDTH 1 /* DRC_DF1_ENA */ +#define WM8962_DF1_SHARED_COEFF 0x0004 /* DF1_SHARED_COEFF */ +#define WM8962_DF1_SHARED_COEFF_MASK 0x0004 /* DF1_SHARED_COEFF */ +#define WM8962_DF1_SHARED_COEFF_SHIFT 2 /* DF1_SHARED_COEFF */ +#define WM8962_DF1_SHARED_COEFF_WIDTH 1 /* DF1_SHARED_COEFF */ +#define WM8962_DF1_SHARED_COEFF_SEL 0x0002 /* DF1_SHARED_COEFF_SEL */ +#define WM8962_DF1_SHARED_COEFF_SEL_MASK 0x0002 /* DF1_SHARED_COEFF_SEL */ +#define WM8962_DF1_SHARED_COEFF_SEL_SHIFT 1 /* DF1_SHARED_COEFF_SEL */ +#define WM8962_DF1_SHARED_COEFF_SEL_WIDTH 1 /* DF1_SHARED_COEFF_SEL */ +#define WM8962_DF1_ENA 0x0001 /* DF1_ENA */ +#define WM8962_DF1_ENA_MASK 0x0001 /* DF1_ENA */ +#define WM8962_DF1_ENA_SHIFT 0 /* DF1_ENA */ +#define WM8962_DF1_ENA_WIDTH 1 /* DF1_ENA */ + +/* + * R257 (0x101) - DF2 + */ +#define WM8962_DF1_COEFF_L0_MASK 0xFFFF /* DF1_COEFF_L0 - [15:0] */ +#define WM8962_DF1_COEFF_L0_SHIFT 0 /* DF1_COEFF_L0 - [15:0] */ +#define WM8962_DF1_COEFF_L0_WIDTH 16 /* DF1_COEFF_L0 - [15:0] */ + +/* + * R258 (0x102) - DF3 + */ +#define WM8962_DF1_COEFF_L1_MASK 0xFFFF /* DF1_COEFF_L1 - [15:0] */ +#define WM8962_DF1_COEFF_L1_SHIFT 0 /* DF1_COEFF_L1 - [15:0] */ +#define WM8962_DF1_COEFF_L1_WIDTH 16 /* DF1_COEFF_L1 - [15:0] */ + +/* + * R259 (0x103) - DF4 + */ +#define WM8962_DF1_COEFF_L2_MASK 0xFFFF /* DF1_COEFF_L2 - [15:0] */ +#define WM8962_DF1_COEFF_L2_SHIFT 0 /* DF1_COEFF_L2 - [15:0] */ +#define WM8962_DF1_COEFF_L2_WIDTH 16 /* DF1_COEFF_L2 - [15:0] */ + +/* + * R260 (0x104) - DF5 + */ +#define WM8962_DF1_COEFF_R0_MASK 0xFFFF /* DF1_COEFF_R0 - [15:0] */ +#define WM8962_DF1_COEFF_R0_SHIFT 0 /* DF1_COEFF_R0 - [15:0] */ +#define WM8962_DF1_COEFF_R0_WIDTH 16 /* DF1_COEFF_R0 - [15:0] */ + +/* + * R261 (0x105) - DF6 + */ +#define WM8962_DF1_COEFF_R1_MASK 0xFFFF /* DF1_COEFF_R1 - [15:0] */ +#define WM8962_DF1_COEFF_R1_SHIFT 0 /* DF1_COEFF_R1 - [15:0] */ +#define WM8962_DF1_COEFF_R1_WIDTH 16 /* DF1_COEFF_R1 - [15:0] */ + +/* + * R262 (0x106) - DF7 + */ +#define WM8962_DF1_COEFF_R2_MASK 0xFFFF /* DF1_COEFF_R2 - [15:0] */ +#define WM8962_DF1_COEFF_R2_SHIFT 0 /* DF1_COEFF_R2 - [15:0] */ +#define WM8962_DF1_COEFF_R2_WIDTH 16 /* DF1_COEFF_R2 - [15:0] */ + +/* + * R264 (0x108) - LHPF1 + */ +#define WM8962_LHPF_MODE 0x0002 /* LHPF_MODE */ +#define WM8962_LHPF_MODE_MASK 0x0002 /* LHPF_MODE */ +#define WM8962_LHPF_MODE_SHIFT 1 /* LHPF_MODE */ +#define WM8962_LHPF_MODE_WIDTH 1 /* LHPF_MODE */ +#define WM8962_LHPF_ENA 0x0001 /* LHPF_ENA */ +#define WM8962_LHPF_ENA_MASK 0x0001 /* LHPF_ENA */ +#define WM8962_LHPF_ENA_SHIFT 0 /* LHPF_ENA */ +#define WM8962_LHPF_ENA_WIDTH 1 /* LHPF_ENA */ + +/* + * R265 (0x109) - LHPF2 + */ +#define WM8962_LHPF_COEFF_MASK 0xFFFF /* LHPF_COEFF - [15:0] */ +#define WM8962_LHPF_COEFF_SHIFT 0 /* LHPF_COEFF - [15:0] */ +#define WM8962_LHPF_COEFF_WIDTH 16 /* LHPF_COEFF - [15:0] */ + +/* + * R268 (0x10C) - THREED1 + */ +#define WM8962_ADC_MONOMIX 0x0040 /* ADC_MONOMIX */ +#define WM8962_ADC_MONOMIX_MASK 0x0040 /* ADC_MONOMIX */ +#define WM8962_ADC_MONOMIX_SHIFT 6 /* ADC_MONOMIX */ +#define WM8962_ADC_MONOMIX_WIDTH 1 /* ADC_MONOMIX */ +#define WM8962_THREED_SIGN_L 0x0020 /* THREED_SIGN_L */ +#define WM8962_THREED_SIGN_L_MASK 0x0020 /* THREED_SIGN_L */ +#define WM8962_THREED_SIGN_L_SHIFT 5 /* THREED_SIGN_L */ +#define WM8962_THREED_SIGN_L_WIDTH 1 /* THREED_SIGN_L */ +#define WM8962_THREED_SIGN_R 0x0010 /* THREED_SIGN_R */ +#define WM8962_THREED_SIGN_R_MASK 0x0010 /* THREED_SIGN_R */ +#define WM8962_THREED_SIGN_R_SHIFT 4 /* THREED_SIGN_R */ +#define WM8962_THREED_SIGN_R_WIDTH 1 /* THREED_SIGN_R */ +#define WM8962_THREED_LHPF_MODE 0x0004 /* THREED_LHPF_MODE */ +#define WM8962_THREED_LHPF_MODE_MASK 0x0004 /* THREED_LHPF_MODE */ +#define WM8962_THREED_LHPF_MODE_SHIFT 2 /* THREED_LHPF_MODE */ +#define WM8962_THREED_LHPF_MODE_WIDTH 1 /* THREED_LHPF_MODE */ +#define WM8962_THREED_LHPF_ENA 0x0002 /* THREED_LHPF_ENA */ +#define WM8962_THREED_LHPF_ENA_MASK 0x0002 /* THREED_LHPF_ENA */ +#define WM8962_THREED_LHPF_ENA_SHIFT 1 /* THREED_LHPF_ENA */ +#define WM8962_THREED_LHPF_ENA_WIDTH 1 /* THREED_LHPF_ENA */ +#define WM8962_THREED_ENA 0x0001 /* THREED_ENA */ +#define WM8962_THREED_ENA_MASK 0x0001 /* THREED_ENA */ +#define WM8962_THREED_ENA_SHIFT 0 /* THREED_ENA */ +#define WM8962_THREED_ENA_WIDTH 1 /* THREED_ENA */ + +/* + * R269 (0x10D) - THREED2 + */ +#define WM8962_THREED_FGAINL_MASK 0xF800 /* THREED_FGAINL - [15:11] */ +#define WM8962_THREED_FGAINL_SHIFT 11 /* THREED_FGAINL - [15:11] */ +#define WM8962_THREED_FGAINL_WIDTH 5 /* THREED_FGAINL - [15:11] */ +#define WM8962_THREED_CGAINL_MASK 0x07C0 /* THREED_CGAINL - [10:6] */ +#define WM8962_THREED_CGAINL_SHIFT 6 /* THREED_CGAINL - [10:6] */ +#define WM8962_THREED_CGAINL_WIDTH 5 /* THREED_CGAINL - [10:6] */ +#define WM8962_THREED_DELAYL_MASK 0x003C /* THREED_DELAYL - [5:2] */ +#define WM8962_THREED_DELAYL_SHIFT 2 /* THREED_DELAYL - [5:2] */ +#define WM8962_THREED_DELAYL_WIDTH 4 /* THREED_DELAYL - [5:2] */ + +/* + * R270 (0x10E) - THREED3 + */ +#define WM8962_THREED_LHPF_COEFF_MASK 0xFFFF /* THREED_LHPF_COEFF - [15:0] */ +#define WM8962_THREED_LHPF_COEFF_SHIFT 0 /* THREED_LHPF_COEFF - [15:0] */ +#define WM8962_THREED_LHPF_COEFF_WIDTH 16 /* THREED_LHPF_COEFF - [15:0] */ + +/* + * R271 (0x10F) - THREED4 + */ +#define WM8962_THREED_FGAINR_MASK 0xF800 /* THREED_FGAINR - [15:11] */ +#define WM8962_THREED_FGAINR_SHIFT 11 /* THREED_FGAINR - [15:11] */ +#define WM8962_THREED_FGAINR_WIDTH 5 /* THREED_FGAINR - [15:11] */ +#define WM8962_THREED_CGAINR_MASK 0x07C0 /* THREED_CGAINR - [10:6] */ +#define WM8962_THREED_CGAINR_SHIFT 6 /* THREED_CGAINR - [10:6] */ +#define WM8962_THREED_CGAINR_WIDTH 5 /* THREED_CGAINR - [10:6] */ +#define WM8962_THREED_DELAYR_MASK 0x003C /* THREED_DELAYR - [5:2] */ +#define WM8962_THREED_DELAYR_SHIFT 2 /* THREED_DELAYR - [5:2] */ +#define WM8962_THREED_DELAYR_WIDTH 4 /* THREED_DELAYR - [5:2] */ + +/* + * R276 (0x114) - DRC 1 + */ +#define WM8962_DRC_SIG_DET_RMS_MASK 0x7C00 /* DRC_SIG_DET_RMS - [14:10] */ +#define WM8962_DRC_SIG_DET_RMS_SHIFT 10 /* DRC_SIG_DET_RMS - [14:10] */ +#define WM8962_DRC_SIG_DET_RMS_WIDTH 5 /* DRC_SIG_DET_RMS - [14:10] */ +#define WM8962_DRC_SIG_DET_PK_MASK 0x0300 /* DRC_SIG_DET_PK - [9:8] */ +#define WM8962_DRC_SIG_DET_PK_SHIFT 8 /* DRC_SIG_DET_PK - [9:8] */ +#define WM8962_DRC_SIG_DET_PK_WIDTH 2 /* DRC_SIG_DET_PK - [9:8] */ +#define WM8962_DRC_NG_ENA 0x0080 /* DRC_NG_ENA */ +#define WM8962_DRC_NG_ENA_MASK 0x0080 /* DRC_NG_ENA */ +#define WM8962_DRC_NG_ENA_SHIFT 7 /* DRC_NG_ENA */ +#define WM8962_DRC_NG_ENA_WIDTH 1 /* DRC_NG_ENA */ +#define WM8962_DRC_SIG_DET_MODE 0x0040 /* DRC_SIG_DET_MODE */ +#define WM8962_DRC_SIG_DET_MODE_MASK 0x0040 /* DRC_SIG_DET_MODE */ +#define WM8962_DRC_SIG_DET_MODE_SHIFT 6 /* DRC_SIG_DET_MODE */ +#define WM8962_DRC_SIG_DET_MODE_WIDTH 1 /* DRC_SIG_DET_MODE */ +#define WM8962_DRC_SIG_DET 0x0020 /* DRC_SIG_DET */ +#define WM8962_DRC_SIG_DET_MASK 0x0020 /* DRC_SIG_DET */ +#define WM8962_DRC_SIG_DET_SHIFT 5 /* DRC_SIG_DET */ +#define WM8962_DRC_SIG_DET_WIDTH 1 /* DRC_SIG_DET */ +#define WM8962_DRC_KNEE2_OP_ENA 0x0010 /* DRC_KNEE2_OP_ENA */ +#define WM8962_DRC_KNEE2_OP_ENA_MASK 0x0010 /* DRC_KNEE2_OP_ENA */ +#define WM8962_DRC_KNEE2_OP_ENA_SHIFT 4 /* DRC_KNEE2_OP_ENA */ +#define WM8962_DRC_KNEE2_OP_ENA_WIDTH 1 /* DRC_KNEE2_OP_ENA */ +#define WM8962_DRC_QR 0x0008 /* DRC_QR */ +#define WM8962_DRC_QR_MASK 0x0008 /* DRC_QR */ +#define WM8962_DRC_QR_SHIFT 3 /* DRC_QR */ +#define WM8962_DRC_QR_WIDTH 1 /* DRC_QR */ +#define WM8962_DRC_ANTICLIP 0x0004 /* DRC_ANTICLIP */ +#define WM8962_DRC_ANTICLIP_MASK 0x0004 /* DRC_ANTICLIP */ +#define WM8962_DRC_ANTICLIP_SHIFT 2 /* DRC_ANTICLIP */ +#define WM8962_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */ +#define WM8962_DRC_MODE 0x0002 /* DRC_MODE */ +#define WM8962_DRC_MODE_MASK 0x0002 /* DRC_MODE */ +#define WM8962_DRC_MODE_SHIFT 1 /* DRC_MODE */ +#define WM8962_DRC_MODE_WIDTH 1 /* DRC_MODE */ +#define WM8962_DRC_ENA 0x0001 /* DRC_ENA */ +#define WM8962_DRC_ENA_MASK 0x0001 /* DRC_ENA */ +#define WM8962_DRC_ENA_SHIFT 0 /* DRC_ENA */ +#define WM8962_DRC_ENA_WIDTH 1 /* DRC_ENA */ + +/* + * R277 (0x115) - DRC 2 + */ +#define WM8962_DRC_ATK_MASK 0x1E00 /* DRC_ATK - [12:9] */ +#define WM8962_DRC_ATK_SHIFT 9 /* DRC_ATK - [12:9] */ +#define WM8962_DRC_ATK_WIDTH 4 /* DRC_ATK - [12:9] */ +#define WM8962_DRC_DCY_MASK 0x01E0 /* DRC_DCY - [8:5] */ +#define WM8962_DRC_DCY_SHIFT 5 /* DRC_DCY - [8:5] */ +#define WM8962_DRC_DCY_WIDTH 4 /* DRC_DCY - [8:5] */ +#define WM8962_DRC_MINGAIN_MASK 0x001C /* DRC_MINGAIN - [4:2] */ +#define WM8962_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [4:2] */ +#define WM8962_DRC_MINGAIN_WIDTH 3 /* DRC_MINGAIN - [4:2] */ +#define WM8962_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */ +#define WM8962_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */ +#define WM8962_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */ + +/* + * R278 (0x116) - DRC 3 + */ +#define WM8962_DRC_NG_MINGAIN_MASK 0xF000 /* DRC_NG_MINGAIN - [15:12] */ +#define WM8962_DRC_NG_MINGAIN_SHIFT 12 /* DRC_NG_MINGAIN - [15:12] */ +#define WM8962_DRC_NG_MINGAIN_WIDTH 4 /* DRC_NG_MINGAIN - [15:12] */ +#define WM8962_DRC_QR_THR_MASK 0x0C00 /* DRC_QR_THR - [11:10] */ +#define WM8962_DRC_QR_THR_SHIFT 10 /* DRC_QR_THR - [11:10] */ +#define WM8962_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [11:10] */ +#define WM8962_DRC_QR_DCY_MASK 0x0300 /* DRC_QR_DCY - [9:8] */ +#define WM8962_DRC_QR_DCY_SHIFT 8 /* DRC_QR_DCY - [9:8] */ +#define WM8962_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [9:8] */ +#define WM8962_DRC_NG_EXP_MASK 0x00C0 /* DRC_NG_EXP - [7:6] */ +#define WM8962_DRC_NG_EXP_SHIFT 6 /* DRC_NG_EXP - [7:6] */ +#define WM8962_DRC_NG_EXP_WIDTH 2 /* DRC_NG_EXP - [7:6] */ +#define WM8962_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */ +#define WM8962_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */ +#define WM8962_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */ +#define WM8962_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */ +#define WM8962_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */ +#define WM8962_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */ + +/* + * R279 (0x117) - DRC 4 + */ +#define WM8962_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */ +#define WM8962_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */ +#define WM8962_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */ +#define WM8962_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */ +#define WM8962_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */ +#define WM8962_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */ + +/* + * R280 (0x118) - DRC 5 + */ +#define WM8962_DRC_KNEE2_IP_MASK 0x03E0 /* DRC_KNEE2_IP - [9:5] */ +#define WM8962_DRC_KNEE2_IP_SHIFT 5 /* DRC_KNEE2_IP - [9:5] */ +#define WM8962_DRC_KNEE2_IP_WIDTH 5 /* DRC_KNEE2_IP - [9:5] */ +#define WM8962_DRC_KNEE2_OP_MASK 0x001F /* DRC_KNEE2_OP - [4:0] */ +#define WM8962_DRC_KNEE2_OP_SHIFT 0 /* DRC_KNEE2_OP - [4:0] */ +#define WM8962_DRC_KNEE2_OP_WIDTH 5 /* DRC_KNEE2_OP - [4:0] */ + +/* + * R285 (0x11D) - Tloopback + */ +#define WM8962_TLB_ENA 0x0002 /* TLB_ENA */ +#define WM8962_TLB_ENA_MASK 0x0002 /* TLB_ENA */ +#define WM8962_TLB_ENA_SHIFT 1 /* TLB_ENA */ +#define WM8962_TLB_ENA_WIDTH 1 /* TLB_ENA */ +#define WM8962_TLB_MODE 0x0001 /* TLB_MODE */ +#define WM8962_TLB_MODE_MASK 0x0001 /* TLB_MODE */ +#define WM8962_TLB_MODE_SHIFT 0 /* TLB_MODE */ +#define WM8962_TLB_MODE_WIDTH 1 /* TLB_MODE */ + +/* + * R335 (0x14F) - EQ1 + */ +#define WM8962_EQ_SHARED_COEFF 0x0004 /* EQ_SHARED_COEFF */ +#define WM8962_EQ_SHARED_COEFF_MASK 0x0004 /* EQ_SHARED_COEFF */ +#define WM8962_EQ_SHARED_COEFF_SHIFT 2 /* EQ_SHARED_COEFF */ +#define WM8962_EQ_SHARED_COEFF_WIDTH 1 /* EQ_SHARED_COEFF */ +#define WM8962_EQ_SHARED_COEFF_SEL 0x0002 /* EQ_SHARED_COEFF_SEL */ +#define WM8962_EQ_SHARED_COEFF_SEL_MASK 0x0002 /* EQ_SHARED_COEFF_SEL */ +#define WM8962_EQ_SHARED_COEFF_SEL_SHIFT 1 /* EQ_SHARED_COEFF_SEL */ +#define WM8962_EQ_SHARED_COEFF_SEL_WIDTH 1 /* EQ_SHARED_COEFF_SEL */ +#define WM8962_EQ_ENA 0x0001 /* EQ_ENA */ +#define WM8962_EQ_ENA_MASK 0x0001 /* EQ_ENA */ +#define WM8962_EQ_ENA_SHIFT 0 /* EQ_ENA */ +#define WM8962_EQ_ENA_WIDTH 1 /* EQ_ENA */ + +/* + * R336 (0x150) - EQ2 + */ +#define WM8962_EQL_B1_GAIN_MASK 0xF800 /* EQL_B1_GAIN - [15:11] */ +#define WM8962_EQL_B1_GAIN_SHIFT 11 /* EQL_B1_GAIN - [15:11] */ +#define WM8962_EQL_B1_GAIN_WIDTH 5 /* EQL_B1_GAIN - [15:11] */ +#define WM8962_EQL_B2_GAIN_MASK 0x07C0 /* EQL_B2_GAIN - [10:6] */ +#define WM8962_EQL_B2_GAIN_SHIFT 6 /* EQL_B2_GAIN - [10:6] */ +#define WM8962_EQL_B2_GAIN_WIDTH 5 /* EQL_B2_GAIN - [10:6] */ +#define WM8962_EQL_B3_GAIN_MASK 0x003E /* EQL_B3_GAIN - [5:1] */ +#define WM8962_EQL_B3_GAIN_SHIFT 1 /* EQL_B3_GAIN - [5:1] */ +#define WM8962_EQL_B3_GAIN_WIDTH 5 /* EQL_B3_GAIN - [5:1] */ + +/* + * R337 (0x151) - EQ3 + */ +#define WM8962_EQL_B4_GAIN_MASK 0xF800 /* EQL_B4_GAIN - [15:11] */ +#define WM8962_EQL_B4_GAIN_SHIFT 11 /* EQL_B4_GAIN - [15:11] */ +#define WM8962_EQL_B4_GAIN_WIDTH 5 /* EQL_B4_GAIN - [15:11] */ +#define WM8962_EQL_B5_GAIN_MASK 0x07C0 /* EQL_B5_GAIN - [10:6] */ +#define WM8962_EQL_B5_GAIN_SHIFT 6 /* EQL_B5_GAIN - [10:6] */ +#define WM8962_EQL_B5_GAIN_WIDTH 5 /* EQL_B5_GAIN - [10:6] */ + +/* + * R338 (0x152) - EQ4 + */ +#define WM8962_EQL_B1_A_MASK 0xFFFF /* EQL_B1_A - [15:0] */ +#define WM8962_EQL_B1_A_SHIFT 0 /* EQL_B1_A - [15:0] */ +#define WM8962_EQL_B1_A_WIDTH 16 /* EQL_B1_A - [15:0] */ + +/* + * R339 (0x153) - EQ5 + */ +#define WM8962_EQL_B1_B_MASK 0xFFFF /* EQL_B1_B - [15:0] */ +#define WM8962_EQL_B1_B_SHIFT 0 /* EQL_B1_B - [15:0] */ +#define WM8962_EQL_B1_B_WIDTH 16 /* EQL_B1_B - [15:0] */ + +/* + * R340 (0x154) - EQ6 + */ +#define WM8962_EQL_B1_PG_MASK 0xFFFF /* EQL_B1_PG - [15:0] */ +#define WM8962_EQL_B1_PG_SHIFT 0 /* EQL_B1_PG - [15:0] */ +#define WM8962_EQL_B1_PG_WIDTH 16 /* EQL_B1_PG - [15:0] */ + +/* + * R341 (0x155) - EQ7 + */ +#define WM8962_EQL_B2_A_MASK 0xFFFF /* EQL_B2_A - [15:0] */ +#define WM8962_EQL_B2_A_SHIFT 0 /* EQL_B2_A - [15:0] */ +#define WM8962_EQL_B2_A_WIDTH 16 /* EQL_B2_A - [15:0] */ + +/* + * R342 (0x156) - EQ8 + */ +#define WM8962_EQL_B2_B_MASK 0xFFFF /* EQL_B2_B - [15:0] */ +#define WM8962_EQL_B2_B_SHIFT 0 /* EQL_B2_B - [15:0] */ +#define WM8962_EQL_B2_B_WIDTH 16 /* EQL_B2_B - [15:0] */ + +/* + * R343 (0x157) - EQ9 + */ +#define WM8962_EQL_B2_C_MASK 0xFFFF /* EQL_B2_C - [15:0] */ +#define WM8962_EQL_B2_C_SHIFT 0 /* EQL_B2_C - [15:0] */ +#define WM8962_EQL_B2_C_WIDTH 16 /* EQL_B2_C - [15:0] */ + +/* + * R344 (0x158) - EQ10 + */ +#define WM8962_EQL_B2_PG_MASK 0xFFFF /* EQL_B2_PG - [15:0] */ +#define WM8962_EQL_B2_PG_SHIFT 0 /* EQL_B2_PG - [15:0] */ +#define WM8962_EQL_B2_PG_WIDTH 16 /* EQL_B2_PG - [15:0] */ + +/* + * R345 (0x159) - EQ11 + */ +#define WM8962_EQL_B3_A_MASK 0xFFFF /* EQL_B3_A - [15:0] */ +#define WM8962_EQL_B3_A_SHIFT 0 /* EQL_B3_A - [15:0] */ +#define WM8962_EQL_B3_A_WIDTH 16 /* EQL_B3_A - [15:0] */ + +/* + * R346 (0x15A) - EQ12 + */ +#define WM8962_EQL_B3_B_MASK 0xFFFF /* EQL_B3_B - [15:0] */ +#define WM8962_EQL_B3_B_SHIFT 0 /* EQL_B3_B - [15:0] */ +#define WM8962_EQL_B3_B_WIDTH 16 /* EQL_B3_B - [15:0] */ + +/* + * R347 (0x15B) - EQ13 + */ +#define WM8962_EQL_B3_C_MASK 0xFFFF /* EQL_B3_C - [15:0] */ +#define WM8962_EQL_B3_C_SHIFT 0 /* EQL_B3_C - [15:0] */ +#define WM8962_EQL_B3_C_WIDTH 16 /* EQL_B3_C - [15:0] */ + +/* + * R348 (0x15C) - EQ14 + */ +#define WM8962_EQL_B3_PG_MASK 0xFFFF /* EQL_B3_PG - [15:0] */ +#define WM8962_EQL_B3_PG_SHIFT 0 /* EQL_B3_PG - [15:0] */ +#define WM8962_EQL_B3_PG_WIDTH 16 /* EQL_B3_PG - [15:0] */ + +/* + * R349 (0x15D) - EQ15 + */ +#define WM8962_EQL_B4_A_MASK 0xFFFF /* EQL_B4_A - [15:0] */ +#define WM8962_EQL_B4_A_SHIFT 0 /* EQL_B4_A - [15:0] */ +#define WM8962_EQL_B4_A_WIDTH 16 /* EQL_B4_A - [15:0] */ + +/* + * R350 (0x15E) - EQ16 + */ +#define WM8962_EQL_B4_B_MASK 0xFFFF /* EQL_B4_B - [15:0] */ +#define WM8962_EQL_B4_B_SHIFT 0 /* EQL_B4_B - [15:0] */ +#define WM8962_EQL_B4_B_WIDTH 16 /* EQL_B4_B - [15:0] */ + +/* + * R351 (0x15F) - EQ17 + */ +#define WM8962_EQL_B4_C_MASK 0xFFFF /* EQL_B4_C - [15:0] */ +#define WM8962_EQL_B4_C_SHIFT 0 /* EQL_B4_C - [15:0] */ +#define WM8962_EQL_B4_C_WIDTH 16 /* EQL_B4_C - [15:0] */ + +/* + * R352 (0x160) - EQ18 + */ +#define WM8962_EQL_B4_PG_MASK 0xFFFF /* EQL_B4_PG - [15:0] */ +#define WM8962_EQL_B4_PG_SHIFT 0 /* EQL_B4_PG - [15:0] */ +#define WM8962_EQL_B4_PG_WIDTH 16 /* EQL_B4_PG - [15:0] */ + +/* + * R353 (0x161) - EQ19 + */ +#define WM8962_EQL_B5_A_MASK 0xFFFF /* EQL_B5_A - [15:0] */ +#define WM8962_EQL_B5_A_SHIFT 0 /* EQL_B5_A - [15:0] */ +#define WM8962_EQL_B5_A_WIDTH 16 /* EQL_B5_A - [15:0] */ + +/* + * R354 (0x162) - EQ20 + */ +#define WM8962_EQL_B5_B_MASK 0xFFFF /* EQL_B5_B - [15:0] */ +#define WM8962_EQL_B5_B_SHIFT 0 /* EQL_B5_B - [15:0] */ +#define WM8962_EQL_B5_B_WIDTH 16 /* EQL_B5_B - [15:0] */ + +/* + * R355 (0x163) - EQ21 + */ +#define WM8962_EQL_B5_PG_MASK 0xFFFF /* EQL_B5_PG - [15:0] */ +#define WM8962_EQL_B5_PG_SHIFT 0 /* EQL_B5_PG - [15:0] */ +#define WM8962_EQL_B5_PG_WIDTH 16 /* EQL_B5_PG - [15:0] */ + +/* + * R356 (0x164) - EQ22 + */ +#define WM8962_EQR_B1_GAIN_MASK 0xF800 /* EQR_B1_GAIN - [15:11] */ +#define WM8962_EQR_B1_GAIN_SHIFT 11 /* EQR_B1_GAIN - [15:11] */ +#define WM8962_EQR_B1_GAIN_WIDTH 5 /* EQR_B1_GAIN - [15:11] */ +#define WM8962_EQR_B2_GAIN_MASK 0x07C0 /* EQR_B2_GAIN - [10:6] */ +#define WM8962_EQR_B2_GAIN_SHIFT 6 /* EQR_B2_GAIN - [10:6] */ +#define WM8962_EQR_B2_GAIN_WIDTH 5 /* EQR_B2_GAIN - [10:6] */ +#define WM8962_EQR_B3_GAIN_MASK 0x003E /* EQR_B3_GAIN - [5:1] */ +#define WM8962_EQR_B3_GAIN_SHIFT 1 /* EQR_B3_GAIN - [5:1] */ +#define WM8962_EQR_B3_GAIN_WIDTH 5 /* EQR_B3_GAIN - [5:1] */ + +/* + * R357 (0x165) - EQ23 + */ +#define WM8962_EQR_B4_GAIN_MASK 0xF800 /* EQR_B4_GAIN - [15:11] */ +#define WM8962_EQR_B4_GAIN_SHIFT 11 /* EQR_B4_GAIN - [15:11] */ +#define WM8962_EQR_B4_GAIN_WIDTH 5 /* EQR_B4_GAIN - [15:11] */ +#define WM8962_EQR_B5_GAIN_MASK 0x07C0 /* EQR_B5_GAIN - [10:6] */ +#define WM8962_EQR_B5_GAIN_SHIFT 6 /* EQR_B5_GAIN - [10:6] */ +#define WM8962_EQR_B5_GAIN_WIDTH 5 /* EQR_B5_GAIN - [10:6] */ + +/* + * R358 (0x166) - EQ24 + */ +#define WM8962_EQR_B1_A_MASK 0xFFFF /* EQR_B1_A - [15:0] */ +#define WM8962_EQR_B1_A_SHIFT 0 /* EQR_B1_A - [15:0] */ +#define WM8962_EQR_B1_A_WIDTH 16 /* EQR_B1_A - [15:0] */ + +/* + * R359 (0x167) - EQ25 + */ +#define WM8962_EQR_B1_B_MASK 0xFFFF /* EQR_B1_B - [15:0] */ +#define WM8962_EQR_B1_B_SHIFT 0 /* EQR_B1_B - [15:0] */ +#define WM8962_EQR_B1_B_WIDTH 16 /* EQR_B1_B - [15:0] */ + +/* + * R360 (0x168) - EQ26 + */ +#define WM8962_EQR_B1_PG_MASK 0xFFFF /* EQR_B1_PG - [15:0] */ +#define WM8962_EQR_B1_PG_SHIFT 0 /* EQR_B1_PG - [15:0] */ +#define WM8962_EQR_B1_PG_WIDTH 16 /* EQR_B1_PG - [15:0] */ + +/* + * R361 (0x169) - EQ27 + */ +#define WM8962_EQR_B2_A_MASK 0xFFFF /* EQR_B2_A - [15:0] */ +#define WM8962_EQR_B2_A_SHIFT 0 /* EQR_B2_A - [15:0] */ +#define WM8962_EQR_B2_A_WIDTH 16 /* EQR_B2_A - [15:0] */ + +/* + * R362 (0x16A) - EQ28 + */ +#define WM8962_EQR_B2_B_MASK 0xFFFF /* EQR_B2_B - [15:0] */ +#define WM8962_EQR_B2_B_SHIFT 0 /* EQR_B2_B - [15:0] */ +#define WM8962_EQR_B2_B_WIDTH 16 /* EQR_B2_B - [15:0] */ + +/* + * R363 (0x16B) - EQ29 + */ +#define WM8962_EQR_B2_C_MASK 0xFFFF /* EQR_B2_C - [15:0] */ +#define WM8962_EQR_B2_C_SHIFT 0 /* EQR_B2_C - [15:0] */ +#define WM8962_EQR_B2_C_WIDTH 16 /* EQR_B2_C - [15:0] */ + +/* + * R364 (0x16C) - EQ30 + */ +#define WM8962_EQR_B2_PG_MASK 0xFFFF /* EQR_B2_PG - [15:0] */ +#define WM8962_EQR_B2_PG_SHIFT 0 /* EQR_B2_PG - [15:0] */ +#define WM8962_EQR_B2_PG_WIDTH 16 /* EQR_B2_PG - [15:0] */ + +/* + * R365 (0x16D) - EQ31 + */ +#define WM8962_EQR_B3_A_MASK 0xFFFF /* EQR_B3_A - [15:0] */ +#define WM8962_EQR_B3_A_SHIFT 0 /* EQR_B3_A - [15:0] */ +#define WM8962_EQR_B3_A_WIDTH 16 /* EQR_B3_A - [15:0] */ + +/* + * R366 (0x16E) - EQ32 + */ +#define WM8962_EQR_B3_B_MASK 0xFFFF /* EQR_B3_B - [15:0] */ +#define WM8962_EQR_B3_B_SHIFT 0 /* EQR_B3_B - [15:0] */ +#define WM8962_EQR_B3_B_WIDTH 16 /* EQR_B3_B - [15:0] */ + +/* + * R367 (0x16F) - EQ33 + */ +#define WM8962_EQR_B3_C_MASK 0xFFFF /* EQR_B3_C - [15:0] */ +#define WM8962_EQR_B3_C_SHIFT 0 /* EQR_B3_C - [15:0] */ +#define WM8962_EQR_B3_C_WIDTH 16 /* EQR_B3_C - [15:0] */ + +/* + * R368 (0x170) - EQ34 + */ +#define WM8962_EQR_B3_PG_MASK 0xFFFF /* EQR_B3_PG - [15:0] */ +#define WM8962_EQR_B3_PG_SHIFT 0 /* EQR_B3_PG - [15:0] */ +#define WM8962_EQR_B3_PG_WIDTH 16 /* EQR_B3_PG - [15:0] */ + +/* + * R369 (0x171) - EQ35 + */ +#define WM8962_EQR_B4_A_MASK 0xFFFF /* EQR_B4_A - [15:0] */ +#define WM8962_EQR_B4_A_SHIFT 0 /* EQR_B4_A - [15:0] */ +#define WM8962_EQR_B4_A_WIDTH 16 /* EQR_B4_A - [15:0] */ + +/* + * R370 (0x172) - EQ36 + */ +#define WM8962_EQR_B4_B_MASK 0xFFFF /* EQR_B4_B - [15:0] */ +#define WM8962_EQR_B4_B_SHIFT 0 /* EQR_B4_B - [15:0] */ +#define WM8962_EQR_B4_B_WIDTH 16 /* EQR_B4_B - [15:0] */ + +/* + * R371 (0x173) - EQ37 + */ +#define WM8962_EQR_B4_C_MASK 0xFFFF /* EQR_B4_C - [15:0] */ +#define WM8962_EQR_B4_C_SHIFT 0 /* EQR_B4_C - [15:0] */ +#define WM8962_EQR_B4_C_WIDTH 16 /* EQR_B4_C - [15:0] */ + +/* + * R372 (0x174) - EQ38 + */ +#define WM8962_EQR_B4_PG_MASK 0xFFFF /* EQR_B4_PG - [15:0] */ +#define WM8962_EQR_B4_PG_SHIFT 0 /* EQR_B4_PG - [15:0] */ +#define WM8962_EQR_B4_PG_WIDTH 16 /* EQR_B4_PG - [15:0] */ + +/* + * R373 (0x175) - EQ39 + */ +#define WM8962_EQR_B5_A_MASK 0xFFFF /* EQR_B5_A - [15:0] */ +#define WM8962_EQR_B5_A_SHIFT 0 /* EQR_B5_A - [15:0] */ +#define WM8962_EQR_B5_A_WIDTH 16 /* EQR_B5_A - [15:0] */ + +/* + * R374 (0x176) - EQ40 + */ +#define WM8962_EQR_B5_B_MASK 0xFFFF /* EQR_B5_B - [15:0] */ +#define WM8962_EQR_B5_B_SHIFT 0 /* EQR_B5_B - [15:0] */ +#define WM8962_EQR_B5_B_WIDTH 16 /* EQR_B5_B - [15:0] */ + +/* + * R375 (0x177) - EQ41 + */ +#define WM8962_EQR_B5_PG_MASK 0xFFFF /* EQR_B5_PG - [15:0] */ +#define WM8962_EQR_B5_PG_SHIFT 0 /* EQR_B5_PG - [15:0] */ +#define WM8962_EQR_B5_PG_WIDTH 16 /* EQR_B5_PG - [15:0] */ + +/* + * R513 (0x201) - GPIO 2 + */ +#define WM8962_GP2_POL 0x0400 /* GP2_POL */ +#define WM8962_GP2_POL_MASK 0x0400 /* GP2_POL */ +#define WM8962_GP2_POL_SHIFT 10 /* GP2_POL */ +#define WM8962_GP2_POL_WIDTH 1 /* GP2_POL */ +#define WM8962_GP2_LVL 0x0040 /* GP2_LVL */ +#define WM8962_GP2_LVL_MASK 0x0040 /* GP2_LVL */ +#define WM8962_GP2_LVL_SHIFT 6 /* GP2_LVL */ +#define WM8962_GP2_LVL_WIDTH 1 /* GP2_LVL */ +#define WM8962_GP2_FN_MASK 0x001F /* GP2_FN - [4:0] */ +#define WM8962_GP2_FN_SHIFT 0 /* GP2_FN - [4:0] */ +#define WM8962_GP2_FN_WIDTH 5 /* GP2_FN - [4:0] */ + +/* + * R514 (0x202) - GPIO 3 + */ +#define WM8962_GP3_POL 0x0400 /* GP3_POL */ +#define WM8962_GP3_POL_MASK 0x0400 /* GP3_POL */ +#define WM8962_GP3_POL_SHIFT 10 /* GP3_POL */ +#define WM8962_GP3_POL_WIDTH 1 /* GP3_POL */ +#define WM8962_GP3_LVL 0x0040 /* GP3_LVL */ +#define WM8962_GP3_LVL_MASK 0x0040 /* GP3_LVL */ +#define WM8962_GP3_LVL_SHIFT 6 /* GP3_LVL */ +#define WM8962_GP3_LVL_WIDTH 1 /* GP3_LVL */ +#define WM8962_GP3_FN_MASK 0x001F /* GP3_FN - [4:0] */ +#define WM8962_GP3_FN_SHIFT 0 /* GP3_FN - [4:0] */ +#define WM8962_GP3_FN_WIDTH 5 /* GP3_FN - [4:0] */ + +/* + * R516 (0x204) - GPIO 5 + */ +#define WM8962_GP5_DIR 0x8000 /* GP5_DIR */ +#define WM8962_GP5_DIR_MASK 0x8000 /* GP5_DIR */ +#define WM8962_GP5_DIR_SHIFT 15 /* GP5_DIR */ +#define WM8962_GP5_DIR_WIDTH 1 /* GP5_DIR */ +#define WM8962_GP5_PU 0x4000 /* GP5_PU */ +#define WM8962_GP5_PU_MASK 0x4000 /* GP5_PU */ +#define WM8962_GP5_PU_SHIFT 14 /* GP5_PU */ +#define WM8962_GP5_PU_WIDTH 1 /* GP5_PU */ +#define WM8962_GP5_PD 0x2000 /* GP5_PD */ +#define WM8962_GP5_PD_MASK 0x2000 /* GP5_PD */ +#define WM8962_GP5_PD_SHIFT 13 /* GP5_PD */ +#define WM8962_GP5_PD_WIDTH 1 /* GP5_PD */ +#define WM8962_GP5_POL 0x0400 /* GP5_POL */ +#define WM8962_GP5_POL_MASK 0x0400 /* GP5_POL */ +#define WM8962_GP5_POL_SHIFT 10 /* GP5_POL */ +#define WM8962_GP5_POL_WIDTH 1 /* GP5_POL */ +#define WM8962_GP5_OP_CFG 0x0200 /* GP5_OP_CFG */ +#define WM8962_GP5_OP_CFG_MASK 0x0200 /* GP5_OP_CFG */ +#define WM8962_GP5_OP_CFG_SHIFT 9 /* GP5_OP_CFG */ +#define WM8962_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */ +#define WM8962_GP5_DB 0x0100 /* GP5_DB */ +#define WM8962_GP5_DB_MASK 0x0100 /* GP5_DB */ +#define WM8962_GP5_DB_SHIFT 8 /* GP5_DB */ +#define WM8962_GP5_DB_WIDTH 1 /* GP5_DB */ +#define WM8962_GP5_LVL 0x0040 /* GP5_LVL */ +#define WM8962_GP5_LVL_MASK 0x0040 /* GP5_LVL */ +#define WM8962_GP5_LVL_SHIFT 6 /* GP5_LVL */ +#define WM8962_GP5_LVL_WIDTH 1 /* GP5_LVL */ +#define WM8962_GP5_FN_MASK 0x001F /* GP5_FN - [4:0] */ +#define WM8962_GP5_FN_SHIFT 0 /* GP5_FN - [4:0] */ +#define WM8962_GP5_FN_WIDTH 5 /* GP5_FN - [4:0] */ + +/* + * R517 (0x205) - GPIO 6 + */ +#define WM8962_GP6_DIR 0x8000 /* GP6_DIR */ +#define WM8962_GP6_DIR_MASK 0x8000 /* GP6_DIR */ +#define WM8962_GP6_DIR_SHIFT 15 /* GP6_DIR */ +#define WM8962_GP6_DIR_WIDTH 1 /* GP6_DIR */ +#define WM8962_GP6_PU 0x4000 /* GP6_PU */ +#define WM8962_GP6_PU_MASK 0x4000 /* GP6_PU */ +#define WM8962_GP6_PU_SHIFT 14 /* GP6_PU */ +#define WM8962_GP6_PU_WIDTH 1 /* GP6_PU */ +#define WM8962_GP6_PD 0x2000 /* GP6_PD */ +#define WM8962_GP6_PD_MASK 0x2000 /* GP6_PD */ +#define WM8962_GP6_PD_SHIFT 13 /* GP6_PD */ +#define WM8962_GP6_PD_WIDTH 1 /* GP6_PD */ +#define WM8962_GP6_POL 0x0400 /* GP6_POL */ +#define WM8962_GP6_POL_MASK 0x0400 /* GP6_POL */ +#define WM8962_GP6_POL_SHIFT 10 /* GP6_POL */ +#define WM8962_GP6_POL_WIDTH 1 /* GP6_POL */ +#define WM8962_GP6_OP_CFG 0x0200 /* GP6_OP_CFG */ +#define WM8962_GP6_OP_CFG_MASK 0x0200 /* GP6_OP_CFG */ +#define WM8962_GP6_OP_CFG_SHIFT 9 /* GP6_OP_CFG */ +#define WM8962_GP6_OP_CFG_WIDTH 1 /* GP6_OP_CFG */ +#define WM8962_GP6_DB 0x0100 /* GP6_DB */ +#define WM8962_GP6_DB_MASK 0x0100 /* GP6_DB */ +#define WM8962_GP6_DB_SHIFT 8 /* GP6_DB */ +#define WM8962_GP6_DB_WIDTH 1 /* GP6_DB */ +#define WM8962_GP6_LVL 0x0040 /* GP6_LVL */ +#define WM8962_GP6_LVL_MASK 0x0040 /* GP6_LVL */ +#define WM8962_GP6_LVL_SHIFT 6 /* GP6_LVL */ +#define WM8962_GP6_LVL_WIDTH 1 /* GP6_LVL */ +#define WM8962_GP6_FN_MASK 0x001F /* GP6_FN - [4:0] */ +#define WM8962_GP6_FN_SHIFT 0 /* GP6_FN - [4:0] */ +#define WM8962_GP6_FN_WIDTH 5 /* GP6_FN - [4:0] */ + +/* + * R560 (0x230) - Interrupt Status 1 + */ +#define WM8962_GP6_EINT 0x0020 /* GP6_EINT */ +#define WM8962_GP6_EINT_MASK 0x0020 /* GP6_EINT */ +#define WM8962_GP6_EINT_SHIFT 5 /* GP6_EINT */ +#define WM8962_GP6_EINT_WIDTH 1 /* GP6_EINT */ +#define WM8962_GP5_EINT 0x0010 /* GP5_EINT */ +#define WM8962_GP5_EINT_MASK 0x0010 /* GP5_EINT */ +#define WM8962_GP5_EINT_SHIFT 4 /* GP5_EINT */ +#define WM8962_GP5_EINT_WIDTH 1 /* GP5_EINT */ + +/* + * R561 (0x231) - Interrupt Status 2 + */ +#define WM8962_MICSCD_EINT 0x8000 /* MICSCD_EINT */ +#define WM8962_MICSCD_EINT_MASK 0x8000 /* MICSCD_EINT */ +#define WM8962_MICSCD_EINT_SHIFT 15 /* MICSCD_EINT */ +#define WM8962_MICSCD_EINT_WIDTH 1 /* MICSCD_EINT */ +#define WM8962_MICD_EINT 0x4000 /* MICD_EINT */ +#define WM8962_MICD_EINT_MASK 0x4000 /* MICD_EINT */ +#define WM8962_MICD_EINT_SHIFT 14 /* MICD_EINT */ +#define WM8962_MICD_EINT_WIDTH 1 /* MICD_EINT */ +#define WM8962_FIFOS_ERR_EINT 0x2000 /* FIFOS_ERR_EINT */ +#define WM8962_FIFOS_ERR_EINT_MASK 0x2000 /* FIFOS_ERR_EINT */ +#define WM8962_FIFOS_ERR_EINT_SHIFT 13 /* FIFOS_ERR_EINT */ +#define WM8962_FIFOS_ERR_EINT_WIDTH 1 /* FIFOS_ERR_EINT */ +#define WM8962_ALC_LOCK_EINT 0x1000 /* ALC_LOCK_EINT */ +#define WM8962_ALC_LOCK_EINT_MASK 0x1000 /* ALC_LOCK_EINT */ +#define WM8962_ALC_LOCK_EINT_SHIFT 12 /* ALC_LOCK_EINT */ +#define WM8962_ALC_LOCK_EINT_WIDTH 1 /* ALC_LOCK_EINT */ +#define WM8962_ALC_THRESH_EINT 0x0800 /* ALC_THRESH_EINT */ +#define WM8962_ALC_THRESH_EINT_MASK 0x0800 /* ALC_THRESH_EINT */ +#define WM8962_ALC_THRESH_EINT_SHIFT 11 /* ALC_THRESH_EINT */ +#define WM8962_ALC_THRESH_EINT_WIDTH 1 /* ALC_THRESH_EINT */ +#define WM8962_ALC_SAT_EINT 0x0400 /* ALC_SAT_EINT */ +#define WM8962_ALC_SAT_EINT_MASK 0x0400 /* ALC_SAT_EINT */ +#define WM8962_ALC_SAT_EINT_SHIFT 10 /* ALC_SAT_EINT */ +#define WM8962_ALC_SAT_EINT_WIDTH 1 /* ALC_SAT_EINT */ +#define WM8962_ALC_PKOVR_EINT 0x0200 /* ALC_PKOVR_EINT */ +#define WM8962_ALC_PKOVR_EINT_MASK 0x0200 /* ALC_PKOVR_EINT */ +#define WM8962_ALC_PKOVR_EINT_SHIFT 9 /* ALC_PKOVR_EINT */ +#define WM8962_ALC_PKOVR_EINT_WIDTH 1 /* ALC_PKOVR_EINT */ +#define WM8962_ALC_NGATE_EINT 0x0100 /* ALC_NGATE_EINT */ +#define WM8962_ALC_NGATE_EINT_MASK 0x0100 /* ALC_NGATE_EINT */ +#define WM8962_ALC_NGATE_EINT_SHIFT 8 /* ALC_NGATE_EINT */ +#define WM8962_ALC_NGATE_EINT_WIDTH 1 /* ALC_NGATE_EINT */ +#define WM8962_WSEQ_DONE_EINT 0x0080 /* WSEQ_DONE_EINT */ +#define WM8962_WSEQ_DONE_EINT_MASK 0x0080 /* WSEQ_DONE_EINT */ +#define WM8962_WSEQ_DONE_EINT_SHIFT 7 /* WSEQ_DONE_EINT */ +#define WM8962_WSEQ_DONE_EINT_WIDTH 1 /* WSEQ_DONE_EINT */ +#define WM8962_DRC_ACTDET_EINT 0x0040 /* DRC_ACTDET_EINT */ +#define WM8962_DRC_ACTDET_EINT_MASK 0x0040 /* DRC_ACTDET_EINT */ +#define WM8962_DRC_ACTDET_EINT_SHIFT 6 /* DRC_ACTDET_EINT */ +#define WM8962_DRC_ACTDET_EINT_WIDTH 1 /* DRC_ACTDET_EINT */ +#define WM8962_FLL_LOCK_EINT 0x0020 /* FLL_LOCK_EINT */ +#define WM8962_FLL_LOCK_EINT_MASK 0x0020 /* FLL_LOCK_EINT */ +#define WM8962_FLL_LOCK_EINT_SHIFT 5 /* FLL_LOCK_EINT */ +#define WM8962_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */ +#define WM8962_PLL3_LOCK_EINT 0x0008 /* PLL3_LOCK_EINT */ +#define WM8962_PLL3_LOCK_EINT_MASK 0x0008 /* PLL3_LOCK_EINT */ +#define WM8962_PLL3_LOCK_EINT_SHIFT 3 /* PLL3_LOCK_EINT */ +#define WM8962_PLL3_LOCK_EINT_WIDTH 1 /* PLL3_LOCK_EINT */ +#define WM8962_PLL2_LOCK_EINT 0x0004 /* PLL2_LOCK_EINT */ +#define WM8962_PLL2_LOCK_EINT_MASK 0x0004 /* PLL2_LOCK_EINT */ +#define WM8962_PLL2_LOCK_EINT_SHIFT 2 /* PLL2_LOCK_EINT */ +#define WM8962_PLL2_LOCK_EINT_WIDTH 1 /* PLL2_LOCK_EINT */ +#define WM8962_TEMP_SHUT_EINT 0x0001 /* TEMP_SHUT_EINT */ +#define WM8962_TEMP_SHUT_EINT_MASK 0x0001 /* TEMP_SHUT_EINT */ +#define WM8962_TEMP_SHUT_EINT_SHIFT 0 /* TEMP_SHUT_EINT */ +#define WM8962_TEMP_SHUT_EINT_WIDTH 1 /* TEMP_SHUT_EINT */ + +/* + * R568 (0x238) - Interrupt Status 1 Mask + */ +#define WM8962_IM_GP6_EINT 0x0020 /* IM_GP6_EINT */ +#define WM8962_IM_GP6_EINT_MASK 0x0020 /* IM_GP6_EINT */ +#define WM8962_IM_GP6_EINT_SHIFT 5 /* IM_GP6_EINT */ +#define WM8962_IM_GP6_EINT_WIDTH 1 /* IM_GP6_EINT */ +#define WM8962_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */ +#define WM8962_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */ +#define WM8962_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */ +#define WM8962_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */ + +/* + * R569 (0x239) - Interrupt Status 2 Mask + */ +#define WM8962_IM_MICSCD_EINT 0x8000 /* IM_MICSCD_EINT */ +#define WM8962_IM_MICSCD_EINT_MASK 0x8000 /* IM_MICSCD_EINT */ +#define WM8962_IM_MICSCD_EINT_SHIFT 15 /* IM_MICSCD_EINT */ +#define WM8962_IM_MICSCD_EINT_WIDTH 1 /* IM_MICSCD_EINT */ +#define WM8962_IM_MICD_EINT 0x4000 /* IM_MICD_EINT */ +#define WM8962_IM_MICD_EINT_MASK 0x4000 /* IM_MICD_EINT */ +#define WM8962_IM_MICD_EINT_SHIFT 14 /* IM_MICD_EINT */ +#define WM8962_IM_MICD_EINT_WIDTH 1 /* IM_MICD_EINT */ +#define WM8962_IM_FIFOS_ERR_EINT 0x2000 /* IM_FIFOS_ERR_EINT */ +#define WM8962_IM_FIFOS_ERR_EINT_MASK 0x2000 /* IM_FIFOS_ERR_EINT */ +#define WM8962_IM_FIFOS_ERR_EINT_SHIFT 13 /* IM_FIFOS_ERR_EINT */ +#define WM8962_IM_FIFOS_ERR_EINT_WIDTH 1 /* IM_FIFOS_ERR_EINT */ +#define WM8962_IM_ALC_LOCK_EINT 0x1000 /* IM_ALC_LOCK_EINT */ +#define WM8962_IM_ALC_LOCK_EINT_MASK 0x1000 /* IM_ALC_LOCK_EINT */ +#define WM8962_IM_ALC_LOCK_EINT_SHIFT 12 /* IM_ALC_LOCK_EINT */ +#define WM8962_IM_ALC_LOCK_EINT_WIDTH 1 /* IM_ALC_LOCK_EINT */ +#define WM8962_IM_ALC_THRESH_EINT 0x0800 /* IM_ALC_THRESH_EINT */ +#define WM8962_IM_ALC_THRESH_EINT_MASK 0x0800 /* IM_ALC_THRESH_EINT */ +#define WM8962_IM_ALC_THRESH_EINT_SHIFT 11 /* IM_ALC_THRESH_EINT */ +#define WM8962_IM_ALC_THRESH_EINT_WIDTH 1 /* IM_ALC_THRESH_EINT */ +#define WM8962_IM_ALC_SAT_EINT 0x0400 /* IM_ALC_SAT_EINT */ +#define WM8962_IM_ALC_SAT_EINT_MASK 0x0400 /* IM_ALC_SAT_EINT */ +#define WM8962_IM_ALC_SAT_EINT_SHIFT 10 /* IM_ALC_SAT_EINT */ +#define WM8962_IM_ALC_SAT_EINT_WIDTH 1 /* IM_ALC_SAT_EINT */ +#define WM8962_IM_ALC_PKOVR_EINT 0x0200 /* IM_ALC_PKOVR_EINT */ +#define WM8962_IM_ALC_PKOVR_EINT_MASK 0x0200 /* IM_ALC_PKOVR_EINT */ +#define WM8962_IM_ALC_PKOVR_EINT_SHIFT 9 /* IM_ALC_PKOVR_EINT */ +#define WM8962_IM_ALC_PKOVR_EINT_WIDTH 1 /* IM_ALC_PKOVR_EINT */ +#define WM8962_IM_ALC_NGATE_EINT 0x0100 /* IM_ALC_NGATE_EINT */ +#define WM8962_IM_ALC_NGATE_EINT_MASK 0x0100 /* IM_ALC_NGATE_EINT */ +#define WM8962_IM_ALC_NGATE_EINT_SHIFT 8 /* IM_ALC_NGATE_EINT */ +#define WM8962_IM_ALC_NGATE_EINT_WIDTH 1 /* IM_ALC_NGATE_EINT */ +#define WM8962_IM_WSEQ_DONE_EINT 0x0080 /* IM_WSEQ_DONE_EINT */ +#define WM8962_IM_WSEQ_DONE_EINT_MASK 0x0080 /* IM_WSEQ_DONE_EINT */ +#define WM8962_IM_WSEQ_DONE_EINT_SHIFT 7 /* IM_WSEQ_DONE_EINT */ +#define WM8962_IM_WSEQ_DONE_EINT_WIDTH 1 /* IM_WSEQ_DONE_EINT */ +#define WM8962_IM_DRC_ACTDET_EINT 0x0040 /* IM_DRC_ACTDET_EINT */ +#define WM8962_IM_DRC_ACTDET_EINT_MASK 0x0040 /* IM_DRC_ACTDET_EINT */ +#define WM8962_IM_DRC_ACTDET_EINT_SHIFT 6 /* IM_DRC_ACTDET_EINT */ +#define WM8962_IM_DRC_ACTDET_EINT_WIDTH 1 /* IM_DRC_ACTDET_EINT */ +#define WM8962_IM_FLL_LOCK_EINT 0x0020 /* IM_FLL_LOCK_EINT */ +#define WM8962_IM_FLL_LOCK_EINT_MASK 0x0020 /* IM_FLL_LOCK_EINT */ +#define WM8962_IM_FLL_LOCK_EINT_SHIFT 5 /* IM_FLL_LOCK_EINT */ +#define WM8962_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */ +#define WM8962_IM_PLL3_LOCK_EINT 0x0008 /* IM_PLL3_LOCK_EINT */ +#define WM8962_IM_PLL3_LOCK_EINT_MASK 0x0008 /* IM_PLL3_LOCK_EINT */ +#define WM8962_IM_PLL3_LOCK_EINT_SHIFT 3 /* IM_PLL3_LOCK_EINT */ +#define WM8962_IM_PLL3_LOCK_EINT_WIDTH 1 /* IM_PLL3_LOCK_EINT */ +#define WM8962_IM_PLL2_LOCK_EINT 0x0004 /* IM_PLL2_LOCK_EINT */ +#define WM8962_IM_PLL2_LOCK_EINT_MASK 0x0004 /* IM_PLL2_LOCK_EINT */ +#define WM8962_IM_PLL2_LOCK_EINT_SHIFT 2 /* IM_PLL2_LOCK_EINT */ +#define WM8962_IM_PLL2_LOCK_EINT_WIDTH 1 /* IM_PLL2_LOCK_EINT */ +#define WM8962_IM_TEMP_SHUT_EINT 0x0001 /* IM_TEMP_SHUT_EINT */ +#define WM8962_IM_TEMP_SHUT_EINT_MASK 0x0001 /* IM_TEMP_SHUT_EINT */ +#define WM8962_IM_TEMP_SHUT_EINT_SHIFT 0 /* IM_TEMP_SHUT_EINT */ +#define WM8962_IM_TEMP_SHUT_EINT_WIDTH 1 /* IM_TEMP_SHUT_EINT */ + +/* + * R576 (0x240) - Interrupt Control + */ +#define WM8962_IRQ_POL 0x0001 /* IRQ_POL */ +#define WM8962_IRQ_POL_MASK 0x0001 /* IRQ_POL */ +#define WM8962_IRQ_POL_SHIFT 0 /* IRQ_POL */ +#define WM8962_IRQ_POL_WIDTH 1 /* IRQ_POL */ + +/* + * R584 (0x248) - IRQ Debounce + */ +#define WM8962_FLL_LOCK_DB 0x0020 /* FLL_LOCK_DB */ +#define WM8962_FLL_LOCK_DB_MASK 0x0020 /* FLL_LOCK_DB */ +#define WM8962_FLL_LOCK_DB_SHIFT 5 /* FLL_LOCK_DB */ +#define WM8962_FLL_LOCK_DB_WIDTH 1 /* FLL_LOCK_DB */ +#define WM8962_PLL3_LOCK_DB 0x0008 /* PLL3_LOCK_DB */ +#define WM8962_PLL3_LOCK_DB_MASK 0x0008 /* PLL3_LOCK_DB */ +#define WM8962_PLL3_LOCK_DB_SHIFT 3 /* PLL3_LOCK_DB */ +#define WM8962_PLL3_LOCK_DB_WIDTH 1 /* PLL3_LOCK_DB */ +#define WM8962_PLL2_LOCK_DB 0x0004 /* PLL2_LOCK_DB */ +#define WM8962_PLL2_LOCK_DB_MASK 0x0004 /* PLL2_LOCK_DB */ +#define WM8962_PLL2_LOCK_DB_SHIFT 2 /* PLL2_LOCK_DB */ +#define WM8962_PLL2_LOCK_DB_WIDTH 1 /* PLL2_LOCK_DB */ +#define WM8962_TEMP_SHUT_DB 0x0001 /* TEMP_SHUT_DB */ +#define WM8962_TEMP_SHUT_DB_MASK 0x0001 /* TEMP_SHUT_DB */ +#define WM8962_TEMP_SHUT_DB_SHIFT 0 /* TEMP_SHUT_DB */ +#define WM8962_TEMP_SHUT_DB_WIDTH 1 /* TEMP_SHUT_DB */ + +/* + * R586 (0x24A) - MICINT Source Pol + */ +#define WM8962_MICSCD_IRQ_POL 0x8000 /* MICSCD_IRQ_POL */ +#define WM8962_MICSCD_IRQ_POL_MASK 0x8000 /* MICSCD_IRQ_POL */ +#define WM8962_MICSCD_IRQ_POL_SHIFT 15 /* MICSCD_IRQ_POL */ +#define WM8962_MICSCD_IRQ_POL_WIDTH 1 /* MICSCD_IRQ_POL */ +#define WM8962_MICD_IRQ_POL 0x4000 /* MICD_IRQ_POL */ +#define WM8962_MICD_IRQ_POL_MASK 0x4000 /* MICD_IRQ_POL */ +#define WM8962_MICD_IRQ_POL_SHIFT 14 /* MICD_IRQ_POL */ +#define WM8962_MICD_IRQ_POL_WIDTH 1 /* MICD_IRQ_POL */ + +/* + * R768 (0x300) - DSP2 Power Management + */ +#define WM8962_DSP2_ENA 0x0001 /* DSP2_ENA */ +#define WM8962_DSP2_ENA_MASK 0x0001 /* DSP2_ENA */ +#define WM8962_DSP2_ENA_SHIFT 0 /* DSP2_ENA */ +#define WM8962_DSP2_ENA_WIDTH 1 /* DSP2_ENA */ + +/* + * R1037 (0x40D) - DSP2_ExecControl + */ +#define WM8962_DSP2_STOPC 0x0020 /* DSP2_STOPC */ +#define WM8962_DSP2_STOPC_MASK 0x0020 /* DSP2_STOPC */ +#define WM8962_DSP2_STOPC_SHIFT 5 /* DSP2_STOPC */ +#define WM8962_DSP2_STOPC_WIDTH 1 /* DSP2_STOPC */ +#define WM8962_DSP2_STOPS 0x0010 /* DSP2_STOPS */ +#define WM8962_DSP2_STOPS_MASK 0x0010 /* DSP2_STOPS */ +#define WM8962_DSP2_STOPS_SHIFT 4 /* DSP2_STOPS */ +#define WM8962_DSP2_STOPS_WIDTH 1 /* DSP2_STOPS */ +#define WM8962_DSP2_STOPI 0x0008 /* DSP2_STOPI */ +#define WM8962_DSP2_STOPI_MASK 0x0008 /* DSP2_STOPI */ +#define WM8962_DSP2_STOPI_SHIFT 3 /* DSP2_STOPI */ +#define WM8962_DSP2_STOPI_WIDTH 1 /* DSP2_STOPI */ +#define WM8962_DSP2_STOP 0x0004 /* DSP2_STOP */ +#define WM8962_DSP2_STOP_MASK 0x0004 /* DSP2_STOP */ +#define WM8962_DSP2_STOP_SHIFT 2 /* DSP2_STOP */ +#define WM8962_DSP2_STOP_WIDTH 1 /* DSP2_STOP */ +#define WM8962_DSP2_RUNR 0x0002 /* DSP2_RUNR */ +#define WM8962_DSP2_RUNR_MASK 0x0002 /* DSP2_RUNR */ +#define WM8962_DSP2_RUNR_SHIFT 1 /* DSP2_RUNR */ +#define WM8962_DSP2_RUNR_WIDTH 1 /* DSP2_RUNR */ +#define WM8962_DSP2_RUN 0x0001 /* DSP2_RUN */ +#define WM8962_DSP2_RUN_MASK 0x0001 /* DSP2_RUN */ +#define WM8962_DSP2_RUN_SHIFT 0 /* DSP2_RUN */ +#define WM8962_DSP2_RUN_WIDTH 1 /* DSP2_RUN */ + +/* + * R8192 (0x2000) - DSP2 Instruction RAM 0 + */ +#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_MASK 0x03FF /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */ +#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_SHIFT 0 /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */ +#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_WIDTH 10 /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */ + +/* + * R9216 (0x2400) - DSP2 Address RAM 2 + */ +#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_MASK 0x003F /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */ +#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */ +#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_WIDTH 6 /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */ + +/* + * R9217 (0x2401) - DSP2 Address RAM 1 + */ +#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_MASK 0xFFFF /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */ +#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */ +#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_WIDTH 16 /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */ + +/* + * R9218 (0x2402) - DSP2 Address RAM 0 + */ +#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_MASK 0xFFFF /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */ +#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */ +#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_WIDTH 16 /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */ + +/* + * R12288 (0x3000) - DSP2 Data1 RAM 1 + */ +#define WM8962_DSP2_DATA1_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */ +#define WM8962_DSP2_DATA1_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */ +#define WM8962_DSP2_DATA1_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */ + +/* + * R12289 (0x3001) - DSP2 Data1 RAM 0 + */ +#define WM8962_DSP2_DATA1_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */ +#define WM8962_DSP2_DATA1_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */ +#define WM8962_DSP2_DATA1_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */ + +/* + * R13312 (0x3400) - DSP2 Data2 RAM 1 + */ +#define WM8962_DSP2_DATA2_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */ +#define WM8962_DSP2_DATA2_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */ +#define WM8962_DSP2_DATA2_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */ + +/* + * R13313 (0x3401) - DSP2 Data2 RAM 0 + */ +#define WM8962_DSP2_DATA2_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */ +#define WM8962_DSP2_DATA2_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */ +#define WM8962_DSP2_DATA2_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */ + +/* + * R14336 (0x3800) - DSP2 Data3 RAM 1 + */ +#define WM8962_DSP2_DATA3_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */ +#define WM8962_DSP2_DATA3_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */ +#define WM8962_DSP2_DATA3_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */ + +/* + * R14337 (0x3801) - DSP2 Data3 RAM 0 + */ +#define WM8962_DSP2_DATA3_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */ +#define WM8962_DSP2_DATA3_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */ +#define WM8962_DSP2_DATA3_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */ + +/* + * R15360 (0x3C00) - DSP2 Coeff RAM 0 + */ +#define WM8962_DSP2_CMAP_RAM_384_11_10_0_MASK 0x07FF /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */ +#define WM8962_DSP2_CMAP_RAM_384_11_10_0_SHIFT 0 /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */ +#define WM8962_DSP2_CMAP_RAM_384_11_10_0_WIDTH 11 /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */ + +/* + * R16384 (0x4000) - RETUNEADC_SHARED_COEFF_1 + */ +#define WM8962_ADC_RETUNE_SCV 0x0080 /* ADC_RETUNE_SCV */ +#define WM8962_ADC_RETUNE_SCV_MASK 0x0080 /* ADC_RETUNE_SCV */ +#define WM8962_ADC_RETUNE_SCV_SHIFT 7 /* ADC_RETUNE_SCV */ +#define WM8962_ADC_RETUNE_SCV_WIDTH 1 /* ADC_RETUNE_SCV */ +#define WM8962_RETUNEADC_SHARED_COEFF_22_16_MASK 0x007F /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */ +#define WM8962_RETUNEADC_SHARED_COEFF_22_16_SHIFT 0 /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */ +#define WM8962_RETUNEADC_SHARED_COEFF_22_16_WIDTH 7 /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */ + +/* + * R16385 (0x4001) - RETUNEADC_SHARED_COEFF_0 + */ +#define WM8962_RETUNEADC_SHARED_COEFF_15_00_MASK 0xFFFF /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */ +#define WM8962_RETUNEADC_SHARED_COEFF_15_00_SHIFT 0 /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */ +#define WM8962_RETUNEADC_SHARED_COEFF_15_00_WIDTH 16 /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */ + +/* + * R16386 (0x4002) - RETUNEDAC_SHARED_COEFF_1 + */ +#define WM8962_DAC_RETUNE_SCV 0x0080 /* DAC_RETUNE_SCV */ +#define WM8962_DAC_RETUNE_SCV_MASK 0x0080 /* DAC_RETUNE_SCV */ +#define WM8962_DAC_RETUNE_SCV_SHIFT 7 /* DAC_RETUNE_SCV */ +#define WM8962_DAC_RETUNE_SCV_WIDTH 1 /* DAC_RETUNE_SCV */ +#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_MASK 0x007F /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */ +#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_SHIFT 0 /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */ +#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_WIDTH 7 /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */ + +/* + * R16387 (0x4003) - RETUNEDAC_SHARED_COEFF_0 + */ +#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_MASK 0xFFFF /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */ +#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_SHIFT 0 /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */ +#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_WIDTH 16 /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */ + +/* + * R16388 (0x4004) - SOUNDSTAGE_ENABLES_1 + */ +#define WM8962_SOUNDSTAGE_ENABLES_23_16_MASK 0x00FF /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */ +#define WM8962_SOUNDSTAGE_ENABLES_23_16_SHIFT 0 /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */ +#define WM8962_SOUNDSTAGE_ENABLES_23_16_WIDTH 8 /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */ + +/* + * R16389 (0x4005) - SOUNDSTAGE_ENABLES_0 + */ +#define WM8962_SOUNDSTAGE_ENABLES_15_06_MASK 0xFFC0 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */ +#define WM8962_SOUNDSTAGE_ENABLES_15_06_SHIFT 6 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */ +#define WM8962_SOUNDSTAGE_ENABLES_15_06_WIDTH 10 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */ +#define WM8962_RTN_ADC_ENA 0x0020 /* RTN_ADC_ENA */ +#define WM8962_RTN_ADC_ENA_MASK 0x0020 /* RTN_ADC_ENA */ +#define WM8962_RTN_ADC_ENA_SHIFT 5 /* RTN_ADC_ENA */ +#define WM8962_RTN_ADC_ENA_WIDTH 1 /* RTN_ADC_ENA */ +#define WM8962_RTN_DAC_ENA 0x0010 /* RTN_DAC_ENA */ +#define WM8962_RTN_DAC_ENA_MASK 0x0010 /* RTN_DAC_ENA */ +#define WM8962_RTN_DAC_ENA_SHIFT 4 /* RTN_DAC_ENA */ +#define WM8962_RTN_DAC_ENA_WIDTH 1 /* RTN_DAC_ENA */ +#define WM8962_HDBASS_ENA 0x0008 /* HDBASS_ENA */ +#define WM8962_HDBASS_ENA_MASK 0x0008 /* HDBASS_ENA */ +#define WM8962_HDBASS_ENA_SHIFT 3 /* HDBASS_ENA */ +#define WM8962_HDBASS_ENA_WIDTH 1 /* HDBASS_ENA */ +#define WM8962_HPF2_ENA 0x0004 /* HPF2_ENA */ +#define WM8962_HPF2_ENA_MASK 0x0004 /* HPF2_ENA */ +#define WM8962_HPF2_ENA_SHIFT 2 /* HPF2_ENA */ +#define WM8962_HPF2_ENA_WIDTH 1 /* HPF2_ENA */ +#define WM8962_HPF1_ENA 0x0002 /* HPF1_ENA */ +#define WM8962_HPF1_ENA_MASK 0x0002 /* HPF1_ENA */ +#define WM8962_HPF1_ENA_SHIFT 1 /* HPF1_ENA */ +#define WM8962_HPF1_ENA_WIDTH 1 /* HPF1_ENA */ +#define WM8962_VSS_ENA 0x0001 /* VSS_ENA */ +#define WM8962_VSS_ENA_MASK 0x0001 /* VSS_ENA */ +#define WM8962_VSS_ENA_SHIFT 0 /* VSS_ENA */ +#define WM8962_VSS_ENA_WIDTH 1 /* VSS_ENA */ + +extern const u16 wm8962_reg[WM8962_MAX_REGISTER + 1]; + +struct wm8962_reg_access { + u16 read; + u16 write; + u16 vol; +}; + +extern +const struct wm8962_reg_access wm8962_reg_access[WM8962_MAX_REGISTER + 1]; + +#endif -- cgit v1.2.3-59-g8ed1b From eef35c2d41ddcc653c20d26b977acaa45c811e1f Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 6 Aug 2010 21:11:15 +0200 Subject: Fix spelling fuction -> function in comments To avoid more patches, I also fixed other spelling and grammar bugs when they were in the same or following line: successfull -> successful parse -> parses controler -> controller controlers -> controllers Cc: Jiri Kosina Cc: linux-kernel@vger.kernel.org Signed-off-by: Stefan Weil Signed-off-by: Jiri Kosina --- arch/blackfin/mach-bf527/boards/ezkit.c | 2 +- arch/blackfin/mach-bf537/boards/stamp.c | 2 +- arch/xtensa/include/asm/uaccess.h | 2 +- block/blk-core.c | 2 +- drivers/base/core.c | 2 +- drivers/media/video/zoran/videocodec.h | 2 +- drivers/net/depca.c | 2 +- drivers/net/igb/igb_main.c | 2 +- drivers/net/skfp/hwt.c | 2 +- drivers/net/skfp/skfddi.c | 2 +- drivers/s390/block/dasd_3990_erp.c | 2 +- drivers/s390/char/tape_3590.c | 6 +++--- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- drivers/usb/host/imx21-hcd.c | 4 ++-- net/mac80211/mesh.h | 2 +- 15 files changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index a05c967a24cf..b182afb28d24 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -884,7 +884,7 @@ static struct adp5520_keys_platform_data adp5520_keys_data = { }; /* - * ADP5520/5501 Multifuction Device Init Data + * ADP5520/5501 Multifunction Device Init Data */ static struct adp5520_platform_data adp5520_pdev_data = { diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 9eaf5b05c11e..b342e1d144af 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -1644,7 +1644,7 @@ static struct adp5520_keys_platform_data adp5520_keys_data = { }; /* - * ADP5520/5501 Multifuction Device Init Data + * ADP5520/5501 Multifunction Device Init Data */ static struct adp5520_platform_data adp5520_pdev_data = { diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index b8528426ab1f..5b0c18c1cce1 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h @@ -4,7 +4,7 @@ * User space memory access functions * * These routines provide basic accessing functions to the user memory - * space for the kernel. This header file provides fuctions such as: + * space for the kernel. This header file provides functions such as: * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff --git a/block/blk-core.c b/block/blk-core.c index f0640d7f800f..7ac24fa71f7a 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1618,7 +1618,7 @@ EXPORT_SYMBOL(submit_bio); * the insertion using this generic function. * * This function should also be useful for request stacking drivers - * in some cases below, so export this fuction. + * in some cases below, so export this function. * Request stacking drivers like request-based dm may change the queue * limits while requests are in the queue (e.g. dm's table swapping). * Such request stacking drivers should check those requests agaist diff --git a/drivers/base/core.c b/drivers/base/core.c index f8e72724dd4b..74707b88f116 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -251,7 +251,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, __func__, retval); } - /* have the device type specific fuction add its stuff */ + /* have the device type specific function add its stuff */ if (dev->type && dev->type->uevent) { retval = dev->type->uevent(dev, env); if (retval) diff --git a/drivers/media/video/zoran/videocodec.h b/drivers/media/video/zoran/videocodec.h index 5c27b251354e..b654bfff8740 100644 --- a/drivers/media/video/zoran/videocodec.h +++ b/drivers/media/video/zoran/videocodec.h @@ -56,7 +56,7 @@ the slave is bound to it). Otherwise it doesn't need this functions and therfor they may not be initialized. - The other fuctions are just for convenience, as they are for sure used by + The other functions are just for convenience, as they are for sure used by most/all of the codecs. The last ones may be ommited, too. See the structure declaration below for more information and which data has diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 44c0694c1f4e..91b3846ffc8a 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1487,7 +1487,7 @@ static void __init depca_platform_probe (void) if (!pldev->dev.driver) { /* The driver was not bound to this device, there was * no hardware at this address. Unregister it, as the - * release fuction will take care of freeing the + * release function will take care of freeing the * allocated structure */ depca_io_ports[i].device = NULL; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index df5dcd23e4fc..f0f82dc7c5db 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3527,7 +3527,7 @@ enum latency_range { * Stores a new ITR value based on strictly on packet size. This * algorithm is less sophisticated than that used in igb_update_itr, * due to the difficulty of synchronizing statistics across multiple - * receive rings. The divisors and thresholds used by this fuction + * receive rings. The divisors and thresholds used by this function * were determined based on theoretical maximum wire speed and testing * data, in order to minimize response time while increasing bulk * throughput. diff --git a/drivers/net/skfp/hwt.c b/drivers/net/skfp/hwt.c index 053151468f93..465565e53a68 100644 --- a/drivers/net/skfp/hwt.c +++ b/drivers/net/skfp/hwt.c @@ -221,7 +221,7 @@ u_long hwt_quick_read(struct s_smc *smc) * para start start time * duration time to wait * - * NOTE: The fuction will return immediately, if the timer is not + * NOTE: The function will return immediately, if the timer is not * started ************************/ void hwt_wait_time(struct s_smc *smc, u_long start, long int duration) diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 31b2dabf094c..0ade12a21d16 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -33,7 +33,7 @@ * The driver architecture is based on the DEC FDDI driver by * Lawrence V. Stefani and several ethernet drivers. * I also used an existing Windows NT miniport driver. - * All hardware dependent fuctions are handled by the SysKonnect + * All hardware dependent functions are handled by the SysKonnect * Hardware Module. * The only headerfiles that are directly related to this source * are skfddi.c, h/types.h, h/osdef1st.h, h/targetos.h. diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 85bfd8794856..e82d427ff5eb 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -2197,7 +2197,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) /* ***************************************************************************** - * main ERP control fuctions (24 and 32 byte sense) + * main ERP control functions (24 and 32 byte sense) ***************************************************************************** */ diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index fc993acf99b6..deff2c3361e4 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -31,7 +31,7 @@ debug_info_t *TAPE_DBF_AREA = NULL; EXPORT_SYMBOL(TAPE_DBF_AREA); /******************************************************************* - * Error Recovery fuctions: + * Error Recovery functions: * - Read Opposite: implemented * - Read Device (buffered) log: BRA * - Read Library log: BRA @@ -798,7 +798,7 @@ tape_3590_done(struct tape_device *device, struct tape_request *request) } /* - * This fuction is called, when error recovery was successfull + * This function is called, when error recovery was successful */ static inline int tape_3590_erp_succeded(struct tape_device *device, struct tape_request *request) @@ -809,7 +809,7 @@ tape_3590_erp_succeded(struct tape_device *device, struct tape_request *request) } /* - * This fuction is called, when error recovery was not successfull + * This function is called, when error recovery was not successful */ static inline int tape_3590_erp_failed(struct tape_device *device, struct tape_request *request, diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 0639c994349c..b37fa202d1e3 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -5498,7 +5498,7 @@ lpfc_get_rec_conf23(uint8_t *buff, uint32_t size, uint8_t rec_type) * @buff: Buffer containing config region 23 data. * @size: Size of the data buffer. * - * This fuction parse the FCoE config parameters in config region 23 and + * This function parses the FCoE config parameters in config region 23 and * populate driver data structure with the parameters. */ void diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index ca0e98d8e1f4..caf116c09376 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -27,8 +27,8 @@ * * 32 transfer descriptors (called ETDs) * * 4Kb of Data memory * - * The data memory is shared between the host and fuction controlers - * (but this driver only supports the host controler) + * The data memory is shared between the host and function controllers + * (but this driver only supports the host controller) * * So setting up a transfer involves: * * Allocating a ETD diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index ebd3f1d9d889..58e741128968 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -115,7 +115,7 @@ struct mesh_path { * @hash_rnd: random value used for hash computations * @entries: number of entries in the table * @free_node: function to free nodes of the table - * @copy_node: fuction to copy nodes of the table + * @copy_node: function to copy nodes of the table * @size_order: determines size of the table, there will be 2^size_order hash * buckets * @mean_chain_len: maximum average length for the hash buckets' list, if it is -- cgit v1.2.3-59-g8ed1b From 426d31071ac476ea62c62656b242930c17b58c00 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sat, 7 Aug 2010 12:30:03 +0200 Subject: fix printk typo 'faild' Signed-off-by: Paul Bolle Signed-off-by: Jiri Kosina --- arch/arm/mach-omap1/board-nokia770.c | 2 +- drivers/ata/pata_bf54x.c | 2 +- drivers/gpu/drm/radeon/radeon_cs.c | 2 +- drivers/net/ps3_gelic_net.c | 4 ++-- drivers/net/tulip/pnic2.c | 2 +- drivers/rtc/rtc-nuc900.c | 2 +- drivers/video/bf54x-lq043fb.c | 6 +++--- drivers/video/bfin-t350mcqb-fb.c | 2 +- fs/exofs/inode.c | 14 +++++++------- fs/exofs/ios.c | 10 +++++----- fs/jfs/jfs_mount.c | 4 ++-- kernel/trace/trace_kprobe.c | 2 +- net/wanrouter/wanmain.c | 4 ++-- 13 files changed, 28 insertions(+), 28 deletions(-) diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 8c28b10f3dae..bc93afbb0a68 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -362,7 +362,7 @@ static __init int omap_dsp_init(void) ret = dsp_kfunc_device_register(&nokia770_audio_device); if (ret) { printk(KERN_ERR - "KFUNC device registration faild: %s\n", + "KFUNC device registration failed: %s\n", nokia770_audio_device.name); goto out; } diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index 9cae65de750e..be7b1b21e777 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -1588,7 +1588,7 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev) host->ports[0]->ioaddr.ctl_addr = (void *)res->start; if (peripheral_request_list(atapi_io_port, "atapi-io-port")) { - dev_err(&pdev->dev, "Requesting Peripherals faild\n"); + dev_err(&pdev->dev, "Requesting Peripherals failed\n"); return -EFAULT; } diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index ae0fb7356e62..8de578ee4987 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -268,7 +268,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) } r = radeon_ib_schedule(rdev, parser.ib); if (r) { - DRM_ERROR("Faild to schedule IB !\n"); + DRM_ERROR("Failed to schedule IB !\n"); } radeon_cs_parser_fini(&parser, r); mutex_unlock(&rdev->cs_mutex); diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index 87d6b8f36304..49f6700e2ec2 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -642,7 +642,7 @@ static inline void gelic_card_disable_rxdmac(struct gelic_card *card) status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card), 0); if (status) dev_err(ctodev(card), - "lv1_net_stop_rx_dma faild, %d\n", status); + "lv1_net_stop_rx_dma failed, %d\n", status); } /** @@ -660,7 +660,7 @@ static inline void gelic_card_disable_txdmac(struct gelic_card *card) status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card), 0); if (status) dev_err(ctodev(card), - "lv1_net_stop_tx_dma faild, status=%d\n", status); + "lv1_net_stop_tx_dma failed, status=%d\n", status); } /** diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c index b8197666021e..4690c8e69207 100644 --- a/drivers/net/tulip/pnic2.c +++ b/drivers/net/tulip/pnic2.c @@ -59,7 +59,7 @@ * Bit 14:12 - autonegotiation state (write 001 to start autonegotiate) * Bit 3 - Autopolarity state * Bit 2 - LS10B - link state of 10baseT 0 - good, 1 - failed - * Bit 1 - LS100B - link state of 100baseT 0 - good, 1- faild + * Bit 1 - LS100B - link state of 100baseT 0 - good, 1 - failed * * * Data Port Selection Info diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index a351bd5d8176..08f95bd3adb3 100644 --- a/drivers/rtc/rtc-nuc900.c +++ b/drivers/rtc/rtc-nuc900.c @@ -279,7 +279,7 @@ static int __devinit nuc900_rtc_probe(struct platform_device *pdev) nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, &nuc900_rtc_ops, THIS_MODULE); if (IS_ERR(nuc900_rtc->rtcdev)) { - dev_err(&pdev->dev, "rtc device register faild\n"); + dev_err(&pdev->dev, "rtc device register failed\n"); err = PTR_ERR(nuc900_rtc->rtcdev); goto fail4; } diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index b020ba7f1cf2..e7d0f525041e 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -241,12 +241,12 @@ static int request_ports(struct bfin_bf54xfb_info *fbi) u16 disp = fbi->mach_info->disp; if (gpio_request(disp, DRIVER_NAME)) { - printk(KERN_ERR "Requesting GPIO %d faild\n", disp); + printk(KERN_ERR "Requesting GPIO %d failed\n", disp); return -EFAULT; } if (peripheral_request_list(eppi_req_18, DRIVER_NAME)) { - printk(KERN_ERR "Requesting Peripherals faild\n"); + printk(KERN_ERR "Requesting Peripherals failed\n"); gpio_free(disp); return -EFAULT; } @@ -256,7 +256,7 @@ static int request_ports(struct bfin_bf54xfb_info *fbi) u16 eppi_req_24[] = EPPI0_24; if (peripheral_request_list(eppi_req_24, DRIVER_NAME)) { - printk(KERN_ERR "Requesting Peripherals faild\n"); + printk(KERN_ERR "Requesting Peripherals failed\n"); peripheral_free_list(eppi_req_18); gpio_free(disp); return -EFAULT; diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 7a50272eaab9..3cf77676947c 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -192,7 +192,7 @@ static int bfin_t350mcqb_request_ports(int action) { if (action) { if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) { - printk(KERN_ERR "Requesting Peripherals faild\n"); + printk(KERN_ERR "Requesting Peripherals failed\n"); return -EFAULT; } } else diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 4bb6ef822e46..5862ae87ed29 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -508,7 +508,7 @@ static int write_exec(struct page_collect *pcol) pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL); if (!pcol_copy) { - EXOFS_ERR("write_exec: Faild to kmalloc(pcol)\n"); + EXOFS_ERR("write_exec: Failed to kmalloc(pcol)\n"); ret = -ENOMEM; goto err; } @@ -524,7 +524,7 @@ static int write_exec(struct page_collect *pcol) ret = exofs_oi_write(oi, ios); if (unlikely(ret)) { - EXOFS_ERR("write_exec: exofs_oi_write() Faild\n"); + EXOFS_ERR("write_exec: exofs_oi_write() Failed\n"); goto err; } @@ -625,7 +625,7 @@ try_again: /* split the request, next loop will start again */ ret = write_exec(pcol); if (unlikely(ret)) { - EXOFS_DBGMSG("write_exec faild => %d", ret); + EXOFS_DBGMSG("write_exec failed => %d", ret); goto fail; } @@ -709,7 +709,7 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, ret = simple_write_begin(file, mapping, pos, len, flags, pagep, fsdata); if (ret) { - EXOFS_DBGMSG("simple_write_begin faild\n"); + EXOFS_DBGMSG("simple_write_begin failed\n"); return ret; } @@ -722,7 +722,7 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, if (ret) { /*SetPageError was done by _readpage. Is it ok?*/ unlock_page(page); - EXOFS_DBGMSG("__readpage_filler faild\n"); + EXOFS_DBGMSG("__readpage_filler failed\n"); } } @@ -1112,7 +1112,7 @@ static void create_done(struct exofs_io_state *ios, void *p) atomic_dec(&sbi->s_curr_pending); if (unlikely(ret)) { - EXOFS_ERR("object=0x%llx creation faild in pid=0x%llx", + EXOFS_ERR("object=0x%llx creation failed in pid=0x%llx", _LLU(exofs_oi_objno(oi)), _LLU(sbi->layout.s_pid)); /*TODO: When FS is corrupted creation can fail, object already * exist. Get rid of this asynchronous creation, if exist @@ -1232,7 +1232,7 @@ static int exofs_update_inode(struct inode *inode, int do_sync) args = kzalloc(sizeof(*args), GFP_KERNEL); if (!args) { - EXOFS_DBGMSG("Faild kzalloc of args\n"); + EXOFS_DBGMSG("Failed kzalloc of args\n"); return -ENOMEM; } diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c index 4337cad7777b..95921f501f2f 100644 --- a/fs/exofs/ios.c +++ b/fs/exofs/ios.c @@ -55,7 +55,7 @@ int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj, ret = osd_finalize_request(or, 0, cred, NULL); if (unlikely(ret)) { - EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n", ret); + EXOFS_DBGMSG("Failed to osd_finalize_request() => %d\n", ret); goto out; } @@ -79,7 +79,7 @@ int exofs_get_io_state(struct exofs_layout *layout, */ ios = kzalloc(exofs_io_state_size(layout->s_numdevs), GFP_KERNEL); if (unlikely(!ios)) { - EXOFS_DBGMSG("Faild kzalloc bytes=%d\n", + EXOFS_DBGMSG("Failed kzalloc bytes=%d\n", exofs_io_state_size(layout->s_numdevs)); *pios = NULL; return -ENOMEM; @@ -172,7 +172,7 @@ static int exofs_io_execute(struct exofs_io_state *ios) ret = osd_finalize_request(or, 0, ios->cred, NULL); if (unlikely(ret)) { - EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n", + EXOFS_DBGMSG("Failed to osd_finalize_request() => %d\n", ret); return ret; } @@ -365,7 +365,7 @@ static int _add_stripe_unit(struct exofs_io_state *ios, unsigned *cur_pg, per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size); if (unlikely(!per_dev->bio)) { - EXOFS_DBGMSG("Faild to allocate BIO size=%u\n", + EXOFS_DBGMSG("Failed to allocate BIO size=%u\n", bio_size); return -ENOMEM; } @@ -584,7 +584,7 @@ static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp) master_dev->bio->bi_max_vecs); if (unlikely(!bio)) { EXOFS_DBGMSG( - "Faild to allocate BIO size=%u\n", + "Failed to allocate BIO size=%u\n", master_dev->bio->bi_max_vecs); ret = -ENOMEM; goto out; diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c index 7b698f2ec45a..9895595fd2f2 100644 --- a/fs/jfs/jfs_mount.c +++ b/fs/jfs/jfs_mount.c @@ -97,7 +97,7 @@ int jfs_mount(struct super_block *sb) ipaimap = diReadSpecial(sb, AGGREGATE_I, 0); if (ipaimap == NULL) { - jfs_err("jfs_mount: Faild to read AGGREGATE_I"); + jfs_err("jfs_mount: Failed to read AGGREGATE_I"); rc = -EIO; goto errout20; } @@ -148,7 +148,7 @@ int jfs_mount(struct super_block *sb) if ((sbi->mntflag & JFS_BAD_SAIT) == 0) { ipaimap2 = diReadSpecial(sb, AGGREGATE_I, 1); if (!ipaimap2) { - jfs_err("jfs_mount: Faild to read AGGREGATE_I"); + jfs_err("jfs_mount: Failed to read AGGREGATE_I"); rc = -EIO; goto errout35; } diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index f52b5f50299d..58716e73e2a2 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -490,7 +490,7 @@ static int register_trace_probe(struct trace_probe *tp) } ret = register_probe_event(tp); if (ret) { - pr_warning("Faild to register probe event(%d)\n", ret); + pr_warning("Failed to register probe event(%d)\n", ret); goto end; } diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 2bf23406637a..74944a2dd436 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -471,7 +471,7 @@ static int wanrouter_device_setup(struct wan_device *wandev, data = vmalloc(conf->data_size); if (!data) { printk(KERN_INFO - "%s: ERROR, Faild allocate kernel memory !\n", + "%s: ERROR, Failed allocate kernel memory !\n", wandev->name); kfree(conf); return -ENOBUFS; @@ -481,7 +481,7 @@ static int wanrouter_device_setup(struct wan_device *wandev, err = wandev->setup(wandev, conf); } else { printk(KERN_INFO - "%s: ERROR, Faild to copy from user data !\n", + "%s: ERROR, Failed to copy from user data !\n", wandev->name); err = -EFAULT; } -- cgit v1.2.3-59-g8ed1b From 597603d615d2b19a9e451d8cfac24372856a522d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 9 Aug 2010 14:21:11 +0200 Subject: ALSA: introduce the snd-aloop module for the PCM loopback The snd-aloop module allows redirecting of the PCM playback in the kernel back to the user space using the standard ALSA PCM capture API. The module also allows time synchronization with another timing source and notifications of playback stream parameter changes. Signed-off-by: Jaroslav Kysela --- sound/drivers/Kconfig | 19 + sound/drivers/Makefile | 2 + sound/drivers/aloop.c | 1055 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1076 insertions(+) create mode 100644 sound/drivers/aloop.c diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig index 84714a65e5c8..b6ae76285255 100644 --- a/sound/drivers/Kconfig +++ b/sound/drivers/Kconfig @@ -74,6 +74,25 @@ config SND_DUMMY To compile this driver as a module, choose M here: the module will be called snd-dummy. +config SND_ALOOP + tristate "Generic loopback driver (PCM)" + select SND_PCM + help + Say 'Y' or 'M' to include support for the PCM loopback device. + This module returns played samples back to the user space using + the standard ALSA PCM device. The devices are routed 0->1 and + 1->0, where first number is the playback PCM device and second + number is the capture device. Module creates two PCM devices and + configured number of substreams (see the pcm_substreams module + parameter). + + The looback device allow time sychronization with an external + timing source using the time shift universal control (+-20% + of system time). + + To compile this driver as a module, choose M here: the module + will be called snd-aloop. + config SND_VIRMIDI tristate "Virtual MIDI soundcard" depends on SND_SEQUENCER diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile index d4a07f9ff2c7..1a8440c8b138 100644 --- a/sound/drivers/Makefile +++ b/sound/drivers/Makefile @@ -4,6 +4,7 @@ # snd-dummy-objs := dummy.o +snd-aloop-objs := aloop.o snd-mtpav-objs := mtpav.o snd-mts64-objs := mts64.o snd-portman2x4-objs := portman2x4.o @@ -13,6 +14,7 @@ snd-ml403-ac97cr-objs := ml403-ac97cr.o pcm-indirect2.o # Toplevel Module Dependency obj-$(CONFIG_SND_DUMMY) += snd-dummy.o +obj-$(CONFIG_SND_ALOOP) += snd-aloop.o obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c new file mode 100644 index 000000000000..3123a15d23f6 --- /dev/null +++ b/sound/drivers/aloop.c @@ -0,0 +1,1055 @@ +/* + * Loopback soundcard + * + * Original code: + * Copyright (c) by Jaroslav Kysela + * + * More accurate positioning and full-duplex support: + * Copyright (c) Ahmet Ä°nan + * + * Major (almost complete) rewrite: + * Copyright (c) by Takashi Iwai + * + * A next major update in 2010 (separate timers for playback and capture): + * Copyright (c) Jaroslav Kysela + * + * 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 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Jaroslav Kysela "); +MODULE_DESCRIPTION("A loopback soundcard"); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}"); + +#define MAX_PCM_SUBSTREAMS 8 + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ +static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; +static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; +static int pcm_notify[SNDRV_CARDS]; + +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for loopback soundcard."); +module_param_array(id, charp, NULL, 0444); +MODULE_PARM_DESC(id, "ID string for loopback soundcard."); +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable this loopback soundcard."); +module_param_array(pcm_substreams, int, NULL, 0444); +MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-8) for loopback driver."); +module_param_array(pcm_notify, int, NULL, 0444); +MODULE_PARM_DESC(pcm_notify, "Break capture when PCM format/rate/channels changes."); + +#define NO_PITCH 100000 + +struct loopback_pcm; + +struct loopback_cable { + spinlock_t lock; + struct loopback_pcm *streams[2]; + struct snd_pcm_hardware hw; + /* flags */ + unsigned int valid; + unsigned int running; +}; + +struct loopback_setup { + unsigned int notify: 1; + unsigned int rate_shift; + unsigned int format; + unsigned int rate; + unsigned int channels; + struct snd_ctl_elem_id active_id; + struct snd_ctl_elem_id format_id; + struct snd_ctl_elem_id rate_id; + struct snd_ctl_elem_id channels_id; +}; + +struct loopback { + struct snd_card *card; + struct mutex cable_lock; + struct loopback_cable *cables[MAX_PCM_SUBSTREAMS][2]; + struct snd_pcm *pcm[2]; + struct loopback_setup setup[MAX_PCM_SUBSTREAMS][2]; +}; + +struct loopback_pcm { + struct loopback *loopback; + struct snd_pcm_substream *substream; + struct loopback_cable *cable; + unsigned int pcm_buffer_size; + unsigned int buf_pos; /* position in buffer */ + unsigned int silent_size; + /* PCM parameters */ + unsigned int pcm_period_size; + unsigned int pcm_bps; /* bytes per second */ + unsigned int pcm_salign; /* bytes per sample * channels */ + unsigned int pcm_rate_shift; /* rate shift value */ + /* flags */ + unsigned int period_update_pending :1; + /* timer stuff */ + unsigned int irq_pos; /* fractional IRQ position */ + unsigned int period_size_frac; + unsigned long last_jiffies; + struct timer_list timer; +}; + +static struct platform_device *devices[SNDRV_CARDS]; + +static inline unsigned int byte_pos(struct loopback_pcm *dpcm, unsigned int x) +{ + if (dpcm->pcm_rate_shift == NO_PITCH) { + x /= HZ; + } else { + x = div_u64(NO_PITCH * (unsigned long long)x, + HZ * (unsigned long long)dpcm->pcm_rate_shift); + } + return x - (x % dpcm->pcm_salign); +} + +static inline unsigned int frac_pos(struct loopback_pcm *dpcm, unsigned int x) +{ + if (dpcm->pcm_rate_shift == NO_PITCH) { /* no pitch */ + return x * HZ; + } else { + x = div_u64(dpcm->pcm_rate_shift * (unsigned long long)x * HZ, + NO_PITCH); + } + return x; +} + +static inline struct loopback_setup *get_setup(struct loopback_pcm *dpcm) +{ + int device = dpcm->substream->pstr->pcm->device; + + if (dpcm->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + device ^= 1; + return &dpcm->loopback->setup[dpcm->substream->number][device]; +} + +static inline unsigned int get_notify(struct loopback_pcm *dpcm) +{ + return get_setup(dpcm)->notify; +} + +static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm) +{ + return get_setup(dpcm)->rate_shift; +} + +static void loopback_timer_start(struct loopback_pcm *dpcm) +{ + unsigned long tick; + unsigned int rate_shift = get_rate_shift(dpcm); + + if (rate_shift != dpcm->pcm_rate_shift) { + dpcm->pcm_rate_shift = rate_shift; + dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size); + } + tick = dpcm->period_size_frac - dpcm->irq_pos; + tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; + dpcm->timer.expires = jiffies + tick; + add_timer(&dpcm->timer); +} + +static inline void loopback_timer_stop(struct loopback_pcm *dpcm) +{ + del_timer(&dpcm->timer); +} + +#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) +#define CABLE_VALID_CAPTURE (1 << SNDRV_PCM_STREAM_CAPTURE) +#define CABLE_VALID_BOTH (CABLE_VALID_PLAYBACK|CABLE_VALID_CAPTURE) + +static int loopback_check_format(struct loopback_cable *cable, int stream) +{ + struct snd_pcm_runtime *runtime; + struct loopback_setup *setup; + struct snd_card *card; + int check; + + if (cable->valid != CABLE_VALID_BOTH) { + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + goto __notify; + return 0; + } + runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]-> + substream->runtime; + check = cable->hw.formats != (1ULL << runtime->format) || + cable->hw.rate_min != runtime->rate || + cable->hw.rate_max != runtime->rate || + cable->hw.channels_min != runtime->channels || + cable->hw.channels_max != runtime->channels; + if (!check) + return 0; + if (stream == SNDRV_PCM_STREAM_CAPTURE) { + return -EIO; + } else { + snd_pcm_stop(cable->streams[SNDRV_PCM_STREAM_CAPTURE]-> + substream, SNDRV_PCM_STATE_DRAINING); + __notify: + runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]-> + substream->runtime; + setup = get_setup(cable->streams[SNDRV_PCM_STREAM_PLAYBACK]); + card = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->loopback->card; + if (setup->format != runtime->format) { + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &setup->format_id); + setup->format = runtime->format; + } + if (setup->rate != runtime->rate) { + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &setup->rate_id); + setup->rate = runtime->rate; + } + if (setup->channels != runtime->channels) { + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &setup->channels_id); + setup->channels = runtime->channels; + } + } + return 0; +} + +static void loopback_active_notify(struct loopback_pcm *dpcm) +{ + snd_ctl_notify(dpcm->loopback->card, + SNDRV_CTL_EVENT_MASK_VALUE, + &get_setup(dpcm)->active_id); +} + +static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct loopback_pcm *dpcm = runtime->private_data; + struct loopback_cable *cable = dpcm->cable; + int err; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + err = loopback_check_format(cable, substream->stream); + if (err < 0) + return err; + dpcm->last_jiffies = jiffies; + dpcm->pcm_rate_shift = 0; + loopback_timer_start(dpcm); + cable->running |= (1 << substream->stream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + loopback_active_notify(dpcm); + break; + case SNDRV_PCM_TRIGGER_STOP: + cable->running &= ~(1 << substream->stream); + loopback_timer_stop(dpcm); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + loopback_active_notify(dpcm); + break; + default: + return -EINVAL; + } + return 0; +} + +static int loopback_prepare(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct loopback_pcm *dpcm = runtime->private_data; + struct loopback_cable *cable = dpcm->cable; + unsigned int bps, salign; + + salign = (snd_pcm_format_width(runtime->format) * + runtime->channels) / 8; + bps = salign * runtime->rate; + if (bps <= 0 || salign <= 0) + return -EINVAL; + + dpcm->buf_pos = 0; + dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size); + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + /* clear capture buffer */ + dpcm->silent_size = dpcm->pcm_buffer_size; + snd_pcm_format_set_silence(runtime->format, runtime->dma_area, + runtime->buffer_size * runtime->channels); + } + + dpcm->irq_pos = 0; + dpcm->period_update_pending = 0; + dpcm->pcm_bps = bps; + dpcm->pcm_salign = salign; + dpcm->pcm_period_size = frames_to_bytes(runtime, runtime->period_size); + + mutex_lock(&dpcm->loopback->cable_lock); + if (!(cable->valid & ~(1 << substream->stream))) { + cable->hw.formats = (1ULL << runtime->format); + cable->hw.rate_min = runtime->rate; + cable->hw.rate_max = runtime->rate; + cable->hw.channels_min = runtime->channels; + cable->hw.channels_max = runtime->channels; + } + cable->valid |= 1 << substream->stream; + mutex_unlock(&dpcm->loopback->cable_lock); + + return 0; +} + +static void clear_capture_buf(struct loopback_pcm *dpcm, unsigned int bytes) +{ + struct snd_pcm_runtime *runtime = dpcm->substream->runtime; + char *dst = runtime->dma_area; + unsigned int dst_off = dpcm->buf_pos; + + if (dpcm->silent_size >= dpcm->pcm_buffer_size) + return; + if (dpcm->silent_size + bytes > dpcm->pcm_buffer_size) + bytes = dpcm->pcm_buffer_size - dpcm->silent_size; + + for (;;) { + unsigned int size = bytes; + if (dst_off + size > dpcm->pcm_buffer_size) + size = dpcm->pcm_buffer_size - dst_off; + snd_pcm_format_set_silence(runtime->format, dst + dst_off, + bytes_to_frames(runtime, size) * + runtime->channels); + dpcm->silent_size += size; + bytes -= size; + if (!bytes) + break; + dst_off = 0; + } +} + +static void copy_play_buf(struct loopback_pcm *play, + struct loopback_pcm *capt, + unsigned int bytes) +{ + struct snd_pcm_runtime *runtime = play->substream->runtime; + char *src = play->substream->runtime->dma_area; + char *dst = capt->substream->runtime->dma_area; + unsigned int src_off = play->buf_pos; + unsigned int dst_off = capt->buf_pos; + unsigned int clear_bytes = 0; + + /* check if playback is draining, trim the capture copy size + * when our pointer is at the end of playback ring buffer */ + if (runtime->status->state == SNDRV_PCM_STATE_DRAINING && + snd_pcm_playback_hw_avail(runtime) < runtime->buffer_size) { + snd_pcm_uframes_t appl_ptr, appl_ptr1, diff; + appl_ptr = appl_ptr1 = runtime->control->appl_ptr; + appl_ptr1 -= appl_ptr1 % runtime->buffer_size; + appl_ptr1 += play->buf_pos / play->pcm_salign; + if (appl_ptr < appl_ptr1) + appl_ptr1 -= runtime->buffer_size; + diff = (appl_ptr - appl_ptr1) * play->pcm_salign; + if (diff < bytes) { + clear_bytes = bytes - diff; + bytes = diff; + } + } + + for (;;) { + unsigned int size = bytes; + if (src_off + size > play->pcm_buffer_size) + size = play->pcm_buffer_size - src_off; + if (dst_off + size > capt->pcm_buffer_size) + size = capt->pcm_buffer_size - dst_off; + memcpy(dst + dst_off, src + src_off, size); + capt->silent_size = 0; + bytes -= size; + if (!bytes) + break; + src_off = (src_off + size) % play->pcm_buffer_size; + dst_off = (dst_off + size) % capt->pcm_buffer_size; + } + + if (clear_bytes > 0) + clear_capture_buf(capt, clear_bytes); +} + +#define BYTEPOS_UPDATE_POSONLY 0 +#define BYTEPOS_UPDATE_CLEAR 1 +#define BYTEPOS_UPDATE_COPY 2 + +static void loopback_bytepos_update(struct loopback_pcm *dpcm, + unsigned int delta, + unsigned int cmd) +{ + unsigned int count; + unsigned long last_pos; + + last_pos = byte_pos(dpcm, dpcm->irq_pos); + dpcm->irq_pos += delta * dpcm->pcm_bps; + count = byte_pos(dpcm, dpcm->irq_pos) - last_pos; + if (!count) + return; + if (cmd == BYTEPOS_UPDATE_CLEAR) + clear_capture_buf(dpcm, count); + else if (cmd == BYTEPOS_UPDATE_COPY) + copy_play_buf(dpcm->cable->streams[SNDRV_PCM_STREAM_PLAYBACK], + dpcm->cable->streams[SNDRV_PCM_STREAM_CAPTURE], + count); + dpcm->buf_pos += count; + dpcm->buf_pos %= dpcm->pcm_buffer_size; + if (dpcm->irq_pos >= dpcm->period_size_frac) { + dpcm->irq_pos %= dpcm->period_size_frac; + dpcm->period_update_pending = 1; + } +} + +static void loopback_pos_update(struct loopback_cable *cable) +{ + struct loopback_pcm *dpcm_play = + cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; + struct loopback_pcm *dpcm_capt = + cable->streams[SNDRV_PCM_STREAM_CAPTURE]; + unsigned long delta_play = 0, delta_capt = 0; + + spin_lock(&cable->lock); + if (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { + delta_play = jiffies - dpcm_play->last_jiffies; + dpcm_play->last_jiffies += delta_play; + } + + if (cable->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { + delta_capt = jiffies - dpcm_capt->last_jiffies; + dpcm_capt->last_jiffies += delta_capt; + } + + if (delta_play == 0 && delta_capt == 0) { + spin_unlock(&cable->lock); + return; + } + + if (delta_play > delta_capt) { + loopback_bytepos_update(dpcm_play, delta_play - delta_capt, + BYTEPOS_UPDATE_POSONLY); + delta_play = delta_capt; + } else if (delta_play < delta_capt) { + loopback_bytepos_update(dpcm_capt, delta_capt - delta_play, + BYTEPOS_UPDATE_CLEAR); + delta_capt = delta_play; + } + + if (delta_play == 0 && delta_capt == 0) { + spin_unlock(&cable->lock); + return; + } + /* note delta_capt == delta_play at this moment */ + loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); + loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); + spin_unlock(&cable->lock); +} + +static void loopback_timer_function(unsigned long data) +{ + struct loopback_pcm *dpcm = (struct loopback_pcm *)data; + int stream; + + loopback_pos_update(dpcm->cable); + stream = dpcm->substream->stream; + if (dpcm->cable->running & (1 << stream)) + loopback_timer_start(dpcm); + if (dpcm->period_update_pending) { + dpcm->period_update_pending = 0; + if (dpcm->cable->running & (1 << stream)) + snd_pcm_period_elapsed(dpcm->substream); + } +} + +static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct loopback_pcm *dpcm = runtime->private_data; + + loopback_pos_update(dpcm->cable); + return bytes_to_frames(runtime, dpcm->buf_pos); +} + +static struct snd_pcm_hardware loopback_pcm_hardware = +{ + .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | + SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE), + .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 32, + .buffer_bytes_max = 2 * 1024 * 1024, + .period_bytes_min = 64, + .period_bytes_max = 2 * 1024 * 1024, + .periods_min = 1, + .periods_max = 1024, + .fifo_size = 0, +}; + +static void loopback_runtime_free(struct snd_pcm_runtime *runtime) +{ + struct loopback_pcm *dpcm = runtime->private_data; + kfree(dpcm); +} + +static int loopback_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); +} + +static int loopback_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct loopback_pcm *dpcm = runtime->private_data; + struct loopback_cable *cable = dpcm->cable; + + mutex_lock(&dpcm->loopback->cable_lock); + cable->valid &= ~(1 << substream->stream); + mutex_unlock(&dpcm->loopback->cable_lock); + return snd_pcm_lib_free_pages(substream); +} + +static unsigned int get_cable_index(struct snd_pcm_substream *substream) +{ + if (!substream->pcm->device) + return substream->stream; + else + return !substream->stream; +} + +static int loopback_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct loopback *loopback = substream->private_data; + struct loopback_pcm *dpcm; + struct loopback_cable *cable; + int err = 0; + int dev = get_cable_index(substream); + + mutex_lock(&loopback->cable_lock); + dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); + if (!dpcm) { + err = -ENOMEM; + goto unlock; + } + dpcm->loopback = loopback; + dpcm->substream = substream; + setup_timer(&dpcm->timer, loopback_timer_function, + (unsigned long)dpcm); + + cable = loopback->cables[substream->number][dev]; + if (!cable) { + cable = kzalloc(sizeof(*cable), GFP_KERNEL); + if (!cable) { + kfree(dpcm); + err = -ENOMEM; + goto unlock; + } + spin_lock_init(&cable->lock); + cable->hw = loopback_pcm_hardware; + loopback->cables[substream->number][dev] = cable; + } + dpcm->cable = cable; + cable->streams[substream->stream] = dpcm; + + snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + + runtime->private_data = dpcm; + runtime->private_free = loopback_runtime_free; + if (get_notify(dpcm) && + substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + runtime->hw = loopback_pcm_hardware; + } else { + runtime->hw = cable->hw; + } + unlock: + mutex_unlock(&loopback->cable_lock); + return err; +} + +static int loopback_close(struct snd_pcm_substream *substream) +{ + struct loopback *loopback = substream->private_data; + struct loopback_pcm *dpcm = substream->runtime->private_data; + struct loopback_cable *cable; + int dev = get_cable_index(substream); + + loopback_timer_stop(dpcm); + mutex_lock(&loopback->cable_lock); + cable = loopback->cables[substream->number][dev]; + if (cable->streams[!substream->stream]) { + /* other stream is still alive */ + cable->streams[substream->stream] = NULL; + } else { + /* free the cable */ + loopback->cables[substream->number][dev] = NULL; + kfree(cable); + } + mutex_unlock(&loopback->cable_lock); + return 0; +} + +static struct snd_pcm_ops loopback_playback_ops = { + .open = loopback_open, + .close = loopback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = loopback_hw_params, + .hw_free = loopback_hw_free, + .prepare = loopback_prepare, + .trigger = loopback_trigger, + .pointer = loopback_pointer, +}; + +static struct snd_pcm_ops loopback_capture_ops = { + .open = loopback_open, + .close = loopback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = loopback_hw_params, + .hw_free = loopback_hw_free, + .prepare = loopback_prepare, + .trigger = loopback_trigger, + .pointer = loopback_pointer, +}; + +static int __devinit loopback_pcm_new(struct loopback *loopback, + int device, int substreams) +{ + struct snd_pcm *pcm; + int err; + + err = snd_pcm_new(loopback->card, "Loopback PCM", device, + substreams, substreams, &pcm); + if (err < 0) + return err; + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_capture_ops); + + pcm->private_data = loopback; + pcm->info_flags = 0; + strcpy(pcm->name, "Loopback PCM"); + + loopback->pcm[device] = pcm; + + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, + snd_dma_continuous_data(GFP_KERNEL), + 0, 2 * 1024 * 1024); + return 0; +} + +static int loopback_rate_shift_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 80000; + uinfo->value.integer.max = 120000; + uinfo->value.integer.step = 1; + return 0; +} + +static int loopback_rate_shift_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].rate_shift; + return 0; +} + +static int loopback_rate_shift_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + unsigned int val; + int change = 0; + + val = ucontrol->value.integer.value[0]; + if (val < 80000) + val = 80000; + if (val > 120000) + val = 120000; + mutex_lock(&loopback->cable_lock); + if (val != loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].rate_shift) { + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].rate_shift = val; + change = 1; + } + mutex_unlock(&loopback->cable_lock); + return change; +} + +static int loopback_notify_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].notify; + return 0; +} + +static int loopback_notify_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + unsigned int val; + int change = 0; + + val = ucontrol->value.integer.value[0] ? 1 : 0; + if (val != loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].notify) { + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].notify = val; + change = 1; + } + return change; +} + +static int loopback_active_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + struct loopback_cable *cable = loopback->cables + [kcontrol->id.subdevice][kcontrol->id.device]; + unsigned int val = 0; + + if (cable != NULL) + val = (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? + 1 : 0; + ucontrol->value.integer.value[0] = val; + return 0; +} + +static int loopback_format_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = SNDRV_PCM_FORMAT_LAST; + uinfo->value.integer.step = 1; + return 0; +} + +static int loopback_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].format; + return 0; +} + +static int loopback_rate_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 192000; + uinfo->value.integer.step = 1; + return 0; +} + +static int loopback_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].rate; + return 0; +} + +static int loopback_channels_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 1; + uinfo->value.integer.max = 1024; + uinfo->value.integer.step = 1; + return 0; +} + +static int loopback_channels_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].rate; + return 0; +} + +static struct snd_kcontrol_new loopback_controls[] __devinitdata = { +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "PCM Rate Shift 100000", + .info = loopback_rate_shift_info, + .get = loopback_rate_shift_get, + .put = loopback_rate_shift_put, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "PCM Notify", + .info = snd_ctl_boolean_mono_info, + .get = loopback_notify_get, + .put = loopback_notify_put, +}, +#define ACTIVE_IDX 2 +{ + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "PCM Slave Active", + .info = snd_ctl_boolean_mono_info, + .get = loopback_active_get, +}, +#define FORMAT_IDX 3 +{ + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "PCM Slave Format", + .info = loopback_format_info, + .get = loopback_format_get +}, +#define RATE_IDX 4 +{ + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "PCM Slave Rate", + .info = loopback_rate_info, + .get = loopback_rate_get +}, +#define CHANNELS_IDX 5 +{ + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "PCM Slave Channels", + .info = loopback_channels_info, + .get = loopback_channels_get +} +}; + +static int __devinit loopback_mixer_new(struct loopback *loopback, int notify) +{ + struct snd_card *card = loopback->card; + struct snd_pcm *pcm; + struct snd_kcontrol *kctl; + struct loopback_setup *setup; + int err, dev, substr, substr_count, idx; + + strcpy(card->mixername, "Loopback Mixer"); + for (dev = 0; dev < 2; dev++) { + pcm = loopback->pcm[dev]; + substr_count = + pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count; + for (substr = 0; substr < substr_count; substr++) { + setup = &loopback->setup[substr][dev]; + setup->notify = notify; + setup->rate_shift = NO_PITCH; + setup->format = SNDRV_PCM_FORMAT_S16_LE; + setup->rate = 48000; + setup->channels = 2; + for (idx = 0; idx < ARRAY_SIZE(loopback_controls); + idx++) { + kctl = snd_ctl_new1(&loopback_controls[idx], + loopback); + if (!kctl) + return -ENOMEM; + kctl->id.device = dev; + kctl->id.subdevice = substr; + switch (idx) { + case ACTIVE_IDX: + setup->active_id = kctl->id; + break; + case FORMAT_IDX: + setup->format_id = kctl->id; + break; + case RATE_IDX: + setup->rate_id = kctl->id; + break; + case CHANNELS_IDX: + setup->channels_id = kctl->id; + break; + default: + break; + } + err = snd_ctl_add(card, kctl); + if (err < 0) + return err; + } + } + } + return 0; +} + +static int __devinit loopback_probe(struct platform_device *devptr) +{ + struct snd_card *card; + struct loopback *loopback; + int dev = devptr->id; + int err; + + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct loopback), &card); + if (err < 0) + return err; + loopback = card->private_data; + + if (pcm_substreams[dev] < 1) + pcm_substreams[dev] = 1; + if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS) + pcm_substreams[dev] = MAX_PCM_SUBSTREAMS; + + loopback->card = card; + mutex_init(&loopback->cable_lock); + + err = loopback_pcm_new(loopback, 0, pcm_substreams[dev]); + if (err < 0) + goto __nodev; + err = loopback_pcm_new(loopback, 1, pcm_substreams[dev]); + if (err < 0) + goto __nodev; + err = loopback_mixer_new(loopback, pcm_notify[dev] ? 1 : 0); + if (err < 0) + goto __nodev; + strcpy(card->driver, "Loopback"); + strcpy(card->shortname, "Loopback"); + sprintf(card->longname, "Loopback %i", dev + 1); + err = snd_card_register(card); + if (!err) { + platform_set_drvdata(devptr, card); + return 0; + } + __nodev: + snd_card_free(card); + return err; +} + +static int __devexit loopback_remove(struct platform_device *devptr) +{ + snd_card_free(platform_get_drvdata(devptr)); + platform_set_drvdata(devptr, NULL); + return 0; +} + +#ifdef CONFIG_PM +static int loopback_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct snd_card *card = platform_get_drvdata(pdev); + struct loopback *loopback = card->private_data; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + + snd_pcm_suspend_all(loopback->pcm[0]); + snd_pcm_suspend_all(loopback->pcm[1]); + return 0; +} + +static int loopback_resume(struct platform_device *pdev) +{ + struct snd_card *card = platform_get_drvdata(pdev); + + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} +#endif + +#define SND_LOOPBACK_DRIVER "snd_aloop" + +static struct platform_driver loopback_driver = { + .probe = loopback_probe, + .remove = __devexit_p(loopback_remove), +#ifdef CONFIG_PM + .suspend = loopback_suspend, + .resume = loopback_resume, +#endif + .driver = { + .name = SND_LOOPBACK_DRIVER + }, +}; + +static void loopback_unregister_all(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(devices); ++i) + platform_device_unregister(devices[i]); + platform_driver_unregister(&loopback_driver); +} + +static int __init alsa_card_loopback_init(void) +{ + int i, err, cards; + + err = platform_driver_register(&loopback_driver); + if (err < 0) + return err; + + + cards = 0; + for (i = 0; i < SNDRV_CARDS; i++) { + struct platform_device *device; + if (!enable[i]) + continue; + device = platform_device_register_simple(SND_LOOPBACK_DRIVER, + i, NULL, 0); + if (IS_ERR(device)) + continue; + if (!platform_get_drvdata(device)) { + platform_device_unregister(device); + continue; + } + devices[i] = device; + cards++; + } + if (!cards) { +#ifdef MODULE + printk(KERN_ERR "aloop: No loopback enabled\n"); +#endif + loopback_unregister_all(); + return -ENODEV; + } + return 0; +} + +static void __exit alsa_card_loopback_exit(void) +{ + loopback_unregister_all(); +} + +module_init(alsa_card_loopback_init) +module_exit(alsa_card_loopback_exit) -- cgit v1.2.3-59-g8ed1b From 73e4008ddddc84d5f2499c17012b340a0dae153e Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Fri, 6 Aug 2010 23:03:06 +0400 Subject: HID: allow resizing and replacing report descriptors Update hid_driver's report_fixup prototype to allow changing report descriptor size and/or returning completely different report descriptor. Update existing usage accordingly. This is to give more freedom in descriptor fixup and to allow having a whole fixed descriptor in the code for the sake of readability. Signed-off-by: Nikolai Kondrashov Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 7 ++++--- drivers/hid/hid-cherry.c | 7 ++++--- drivers/hid/hid-core.c | 2 +- drivers/hid/hid-cypress.c | 9 +++++---- drivers/hid/hid-elecom.c | 7 ++++--- drivers/hid/hid-kye.c | 7 ++++--- drivers/hid/hid-lg.c | 9 +++++---- drivers/hid/hid-microsoft.c | 7 ++++--- drivers/hid/hid-monterey.c | 7 ++++--- drivers/hid/hid-ortek.c | 7 ++++--- drivers/hid/hid-petalynx.c | 7 ++++--- drivers/hid/hid-prodikeys.c | 7 ++++--- drivers/hid/hid-samsung.c | 20 +++++++++++--------- drivers/hid/hid-sony.c | 7 ++++--- drivers/hid/hid-sunplus.c | 7 ++++--- drivers/hid/hid-zydacron.c | 7 ++++--- include/linux/hid.h | 4 ++-- 17 files changed, 72 insertions(+), 56 deletions(-) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index bba05d0a8980..eaeca564a8d3 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -246,17 +246,18 @@ static int apple_event(struct hid_device *hdev, struct hid_field *field, /* * MacBook JIS keyboard has wrong logical maximum */ -static void apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { struct apple_sc *asc = hid_get_drvdata(hdev); - if ((asc->quirks & APPLE_RDESC_JIS) && rsize >= 60 && + if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 && rdesc[53] == 0x65 && rdesc[59] == 0x65) { dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report " "descriptor\n"); rdesc[53] = rdesc[59] = 0xe7; } + return rdesc; } static void apple_setup_input(struct input_dev *input) diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c index 24663a8717b1..e880086c2311 100644 --- a/drivers/hid/hid-cherry.c +++ b/drivers/hid/hid-cherry.c @@ -26,15 +26,16 @@ * Cherry Cymotion keyboard have an invalid HID report descriptor, * that needs fixing before we can parse it. */ -static void ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { - if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { + if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { dev_info(&hdev->dev, "fixing up Cherry Cymotion report " "descriptor\n"); rdesc[11] = rdesc[16] = 0xff; rdesc[12] = rdesc[17] = 0x03; } + return rdesc; } #define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e635199a0cd2..ec20e83cbd61 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -651,7 +651,7 @@ int hid_parse_report(struct hid_device *device, __u8 *start, }; if (device->driver->report_fixup) - device->driver->report_fixup(device, start, size); + start = device->driver->report_fixup(device, start, &size); device->rdesc = kmemdup(start, size, GFP_KERNEL); if (device->rdesc == NULL) diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index 998b6f443d7d..4cd0e2345991 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c @@ -31,16 +31,16 @@ * Some USB barcode readers from cypress have usage min and usage max in * the wrong order */ -static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); unsigned int i; if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX)) - return; + return rdesc; - for (i = 0; i < rsize - 4; i++) + for (i = 0; i < *rsize - 4; i++) if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) { __u8 tmp; @@ -50,6 +50,7 @@ static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[i + 3] = rdesc[i + 1]; rdesc[i + 1] = tmp; } + return rdesc; } static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi, diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c index 7a40878f46b4..6e31f305397d 100644 --- a/drivers/hid/hid-elecom.c +++ b/drivers/hid/hid-elecom.c @@ -20,14 +20,15 @@ #include "hid-ids.h" -static void elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { - if (rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { + if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { dev_info(&hdev->dev, "Fixing up Elecom BM084 " "report descriptor.\n"); rdesc[47] = 0x00; } + return rdesc; } static const struct hid_device_id elecom_devices[] = { diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c index f8871712b7b5..817247ee006c 100644 --- a/drivers/hid/hid-kye.c +++ b/drivers/hid/hid-kye.c @@ -23,10 +23,10 @@ * - report size 8 count 1 must be size 1 count 8 for button bitfield * - change the button usage range to 4-7 for the extra buttons */ -static void kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { - if (rsize >= 74 && + if (*rsize >= 74 && rdesc[61] == 0x05 && rdesc[62] == 0x08 && rdesc[63] == 0x19 && rdesc[64] == 0x08 && rdesc[65] == 0x29 && rdesc[66] == 0x0f && @@ -40,6 +40,7 @@ static void kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[72] = 0x01; rdesc[74] = 0x08; } + return rdesc; } static const struct hid_device_id kye_devices[] = { diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index f6433d8050a9..68c0b68856c7 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -41,25 +41,26 @@ * above the logical maximum described in descriptor. This extends * the original value of 0x28c of logical maximum to 0x104d */ -static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - if ((quirks & LG_RDESC) && rsize >= 90 && rdesc[83] == 0x26 && + if ((quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && rdesc[84] == 0x8c && rdesc[85] == 0x02) { dev_info(&hdev->dev, "fixing up Logitech keyboard report " "descriptor\n"); rdesc[84] = rdesc[89] = 0x4d; rdesc[85] = rdesc[90] = 0x10; } - if ((quirks & LG_RDESC_REL_ABS) && rsize >= 50 && + if ((quirks & LG_RDESC_REL_ABS) && *rsize >= 50 && rdesc[32] == 0x81 && rdesc[33] == 0x06 && rdesc[49] == 0x81 && rdesc[50] == 0x06) { dev_info(&hdev->dev, "fixing up rel/abs in Logitech " "report descriptor\n"); rdesc[33] = rdesc[50] = 0x02; } + return rdesc; } #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 359cc447c6c6..dc618c33d0a2 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -33,18 +33,19 @@ * Microsoft Wireless Desktop Receiver (Model 1028) has * 'Usage Min/Max' where it ought to have 'Physical Min/Max' */ -static void ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - if ((quirks & MS_RDESC) && rsize == 571 && rdesc[557] == 0x19 && + if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && rdesc[559] == 0x29) { dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver " "Model 1028 report descriptor\n"); rdesc[557] = 0x35; rdesc[559] = 0x45; } + return rdesc; } #define ms_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c index 2cd05aa244b9..c95c31e2d869 100644 --- a/drivers/hid/hid-monterey.c +++ b/drivers/hid/hid-monterey.c @@ -22,14 +22,15 @@ #include "hid-ids.h" -static void mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { - if (rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { + if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { dev_info(&hdev->dev, "fixing up button/consumer in HID report " "descriptor\n"); rdesc[30] = 0x0c; } + return rdesc; } #define mr_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ diff --git a/drivers/hid/hid-ortek.c b/drivers/hid/hid-ortek.c index aa9a960f73a4..2e79716dca31 100644 --- a/drivers/hid/hid-ortek.c +++ b/drivers/hid/hid-ortek.c @@ -19,14 +19,15 @@ #include "hid-ids.h" -static void ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { - if (rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) { + if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) { dev_info(&hdev->dev, "Fixing up Ortek WKB-2000 " "report descriptor.\n"); rdesc[55] = 0x92; } + return rdesc; } static const struct hid_device_id ortek_devices[] = { diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c index 500fbd0652dc..308d6ae48a3e 100644 --- a/drivers/hid/hid-petalynx.c +++ b/drivers/hid/hid-petalynx.c @@ -23,10 +23,10 @@ #include "hid-ids.h" /* Petalynx Maxter Remote has maximum for consumer page set too low */ -static void pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { - if (rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && + if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && rdesc[41] == 0x00 && rdesc[59] == 0x26 && rdesc[60] == 0xf9 && rdesc[61] == 0x00) { dev_info(&hdev->dev, "fixing up Petalynx Maxter Remote report " @@ -34,6 +34,7 @@ static void pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[60] = 0xfa; rdesc[40] = 0xfa; } + return rdesc; } #define pl_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 845f428b8090..48eab84f53b5 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c @@ -740,10 +740,10 @@ int pcmidi_snd_terminate(struct pcmidi_snd *pm) /* * PC-MIDI report descriptor for report id is wrong. */ -static void pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { - if (rsize == 178 && + if (*rsize == 178 && rdesc[111] == 0x06 && rdesc[112] == 0x00 && rdesc[113] == 0xff) { dev_info(&hdev->dev, "fixing up pc-midi keyboard report " @@ -751,6 +751,7 @@ static void pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[144] = 0x18; /* report 4: was 0x10 report count */ } + return rdesc; } static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi, diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c index bda0fd60c98d..35894444e000 100644 --- a/drivers/hid/hid-samsung.c +++ b/drivers/hid/hid-samsung.c @@ -61,10 +61,10 @@ static inline void samsung_irda_dev_trace(struct hid_device *hdev, "descriptor\n", rsize); } -static void samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { - if (rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 && + if (*rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 && rdesc[177] == 0x75 && rdesc[178] == 0x30 && rdesc[179] == 0x95 && rdesc[180] == 0x01 && rdesc[182] == 0x40) { @@ -74,24 +74,25 @@ static void samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[180] = 0x06; rdesc[182] = 0x42; } else - if (rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 && + if (*rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 && rdesc[194] == 0x25 && rdesc[195] == 0x12) { samsung_irda_dev_trace(hdev, 203); rdesc[193] = 0x1; rdesc[195] = 0xf; } else - if (rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 && + if (*rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 && rdesc[126] == 0x25 && rdesc[127] == 0x11) { samsung_irda_dev_trace(hdev, 135); rdesc[125] = 0x1; rdesc[127] = 0xe; } else - if (rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 && + if (*rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 && rdesc[162] == 0x25 && rdesc[163] == 0x01) { samsung_irda_dev_trace(hdev, 171); rdesc[161] = 0x1; rdesc[163] = 0x3; } + return rdesc; } #define samsung_kbd_mouse_map_key_clear(c) \ @@ -130,11 +131,12 @@ static int samsung_kbd_mouse_input_mapping(struct hid_device *hdev, return 1; } -static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product) - samsung_irda_report_fixup(hdev, rdesc, rsize); + rdesc = samsung_irda_report_fixup(hdev, rdesc, rsize); + return rdesc; } static int samsung_input_mapping(struct hid_device *hdev, struct hid_input *hi, diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 402d5574b574..9fa034915185 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -31,17 +31,18 @@ struct sony_sc { }; /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ -static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { struct sony_sc *sc = hid_get_drvdata(hdev); if ((sc->quirks & VAIO_RDESC_CONSTANT) && - rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { + *rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report " "descriptor\n"); rdesc[55] = 0x06; } + return rdesc; } /* diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c index 438107d9f1b2..164ed568f6cf 100644 --- a/drivers/hid/hid-sunplus.c +++ b/drivers/hid/hid-sunplus.c @@ -22,16 +22,17 @@ #include "hid-ids.h" -static void sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { - if (rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && + if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && rdesc[106] == 0x03) { dev_info(&hdev->dev, "fixing up Sunplus Wireless Desktop " "report descriptor\n"); rdesc[105] = rdesc[110] = 0x03; rdesc[106] = rdesc[111] = 0x21; } + return rdesc; } #define sp_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ diff --git a/drivers/hid/hid-zydacron.c b/drivers/hid/hid-zydacron.c index 9e8d35a203e4..aac1f9273149 100644 --- a/drivers/hid/hid-zydacron.c +++ b/drivers/hid/hid-zydacron.c @@ -27,10 +27,10 @@ struct zc_device { * Zydacron remote control has an invalid HID report descriptor, * that needs fixing before we can parse it. */ -static void zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) +static __u8 *zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { - if (rsize >= 253 && + if (*rsize >= 253 && rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff && rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff && rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) { @@ -40,6 +40,7 @@ static void zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c; rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00; } + return rdesc; } #define zc_map_key_clear(c) \ diff --git a/include/linux/hid.h b/include/linux/hid.h index 42a0f1d11365..0a34fb071379 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -626,8 +626,8 @@ struct hid_driver { int (*event)(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage, __s32 value); - void (*report_fixup)(struct hid_device *hdev, __u8 *buf, - unsigned int size); + __u8 *(*report_fixup)(struct hid_device *hdev, __u8 *buf, + unsigned int *size); int (*input_mapping)(struct hid_device *hdev, struct hid_input *hidinput, struct hid_field *field, -- cgit v1.2.3-59-g8ed1b From 50b6369767f65c39de3d7ca17842ebc6c52888b8 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Fri, 6 Aug 2010 23:03:07 +0400 Subject: HID: Add Tablet Pick -> BTN_STYLUS2 mapping Many tablet input drivers use BTN_STYLUS2 code to report a second tablet stylus button. Yet, the generic HID input driver doesn't map it. Apparently, because there is no corresponding usage in the HID Usage Tables. This patch selects a compromise usage - "Tablet Pick" (0x46) to be mapped to BTN_STYLUS2. Some tablets use "Eraser" usage, but mapping it to a button wouldn't be entirely correct, because the specification says it may be "a pressure quantity". Signed-off-by: Nikolai Kondrashov Signed-off-by: Jiri Kosina --- drivers/hid/hid-input.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 6c03dcc5760a..0c2908f2dbe3 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -336,6 +336,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel map_key_clear(BTN_STYLUS); break; + case 0x46: /* TabletPick */ + map_key_clear(BTN_STYLUS2); + break; + default: goto unknown; } break; -- cgit v1.2.3-59-g8ed1b From f8a489cc5f7adafa9f1420279be793de0fba481c Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Mon, 9 Aug 2010 20:44:17 +0400 Subject: HID: Add support for UC-Logic WP????U tablets Add support for UC-Logic WP4030U, WP5540U and WP8060U tablets. These tablets are usually sold by Genius, Trust and possibly others under different names and in different cases, but with the original USB vendor/product IDs. Currently, these tablets are supported by standalone X.org driver WizardPen. This patch aims to fix them in the kernel and make them supported by the generic evdev X.org driver. Still, some minor fixes in the X.org driver are to be made for the full stack support. Signed-off-by: Nikolai Kondrashov Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 6 + drivers/hid/Makefile | 1 + drivers/hid/hid-core.c | 3 + drivers/hid/hid-ids.h | 2 + drivers/hid/hid-uclogic.c | 404 ++++++++++++++++++++++++++++++++++++++++ drivers/hid/usbhid/hid-quirks.c | 3 +- 6 files changed, 418 insertions(+), 1 deletion(-) create mode 100644 drivers/hid/hid-uclogic.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 6369ba7f96f8..d0b43c9fc245 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -176,6 +176,12 @@ config HID_KYE ---help--- Support for Kye/Genius Ergo Mouse. +config HID_UCLOGIC + tristate "UC-Logic" if EMBEDDED + depends on USB_HID + ---help--- + Support for UC-Logic tablets. + config HID_GYRATION tristate "Gyration" depends on USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 46f037f3df80..8c4a5107df77 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o +obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o obj-$(CONFIG_HID_WACOM) += hid-wacom.o diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ec20e83cbd61..7eb3b163406c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1383,6 +1383,9 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index d3fc13ae094d..b887e73da68a 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -506,6 +506,8 @@ #define USB_VENDOR_ID_UCLOGIC 0x5543 #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 +#define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 +#define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 #define USB_VENDOR_ID_VERNIER 0x08f7 #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c new file mode 100644 index 000000000000..107aa9fb07f2 --- /dev/null +++ b/drivers/hid/hid-uclogic.c @@ -0,0 +1,404 @@ +/* + * HID driver for UC-Logic devices not fully compliant with HID standard + * + * Copyright (c) 2010 Nikolai Kondrashov + */ + +/* + * 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. + */ + +#include +#include +#include + +#include "hid-ids.h" + +/* + * The original descriptors of WPXXXXU tablets have three report IDs, of + * which only two are used (8 and 9), and the remaining (7) seems to have + * the originally intended pen description which was abandoned for some + * reason. From this unused description it is possible to extract the + * actual physical extents and resolution. All the models use the same + * descriptor with different extents for the unused report ID. + * + * Here it is: + * + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Pen), ; Pen (02h, application collection) + * Collection (Application), + * Report ID (7), + * Usage (Stylus), ; Stylus (20h, logical collection) + * Collection (Physical), + * Usage (Tip Switch), ; Tip switch (42h, momentary control) + * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) + * Usage (Eraser), ; Eraser (45h, momentary control) + * Logical Minimum (0), + * Logical Maximum (1), + * Report Size (1), + * Report Count (3), + * Input (Variable), + * Report Count (3), + * Input (Constant, Variable), + * Usage (In Range), ; In range (32h, momentary control) + * Report Count (1), + * Input (Variable), + * Report Count (1), + * Input (Constant, Variable), + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (X), ; X (30h, dynamic value) + * Report Size (16), + * Report Count (1), + * Push, + * Unit Exponent (13), + * Unit (Inch^3), + * Physical Minimum (0), + * Physical Maximum (Xpm), + * Logical Maximum (Xlm), + * Input (Variable), + * Usage (Y), ; Y (31h, dynamic value) + * Physical Maximum (Ypm), + * Logical Maximum (Ylm), + * Input (Variable), + * Pop, + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) + * Logical Maximum (1023), + * Input (Variable), + * Report Size (16), + * End Collection, + * End Collection, + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (Mouse), ; Mouse (02h, application collection) + * Collection (Application), + * Report ID (8), + * Usage (Pointer), ; Pointer (01h, physical collection) + * Collection (Physical), + * Usage Page (Button), ; Button (09h) + * Usage Minimum (01h), + * Usage Maximum (03h), + * Logical Minimum (0), + * Logical Maximum (1), + * Report Count (3), + * Report Size (1), + * Input (Variable), + * Report Count (5), + * Input (Constant), + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (X), ; X (30h, dynamic value) + * Usage (Y), ; Y (31h, dynamic value) + * Usage (Wheel), ; Wheel (38h, dynamic value) + * Usage (00h), + * Logical Minimum (-127), + * Logical Maximum (127), + * Report Size (8), + * Report Count (4), + * Input (Variable, Relative), + * End Collection, + * End Collection, + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (Mouse), ; Mouse (02h, application collection) + * Collection (Application), + * Report ID (9), + * Usage (Pointer), ; Pointer (01h, physical collection) + * Collection (Physical), + * Usage Page (Button), ; Button (09h) + * Usage Minimum (01h), + * Usage Maximum (03h), + * Logical Minimum (0), + * Logical Maximum (1), + * Report Count (3), + * Report Size (1), + * Input (Variable), + * Report Count (5), + * Input (Constant), + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (X), ; X (30h, dynamic value) + * Usage (Y), ; Y (31h, dynamic value) + * Logical Minimum (0), + * Logical Maximum (32767), + * Physical Minimum (0), + * Physical Maximum (32767), + * Report Count (2), + * Report Size (16), + * Input (Variable), + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) + * Logical Maximum (1023), + * Report Count (1), + * Report Size (16), + * Input (Variable), + * End Collection, + * End Collection + * + * Here are the extents values for the WPXXXXU models: + * + * Xpm Xlm Ypm Ylm + * WP4030U 4000 8000 3000 6000 + * WP5540U 5500 11000 4000 8000 + * WP8060U 8000 16000 6000 12000 + * + * This suggests that all of them have 2000 LPI resolution, as advertised. + */ + +/* Size of the original descriptor of WPXXXXU tablets */ +#define WPXXXXU_RDESC_ORIG_SIZE 212 + +/* + * Fixed WP4030U report descriptor. + * Although the hardware might actually support it, the mouse description + * has been removed, since there seems to be no devices having one and it + * wouldn't make much sense because of the working area size. + */ +static __u8 wp4030u_rdesc_fixed[] = { + 0x05, 0x0D, /* Usage Page (Digitizer), */ + 0x09, 0x02, /* Usage (Pen), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x09, /* Report ID (9), */ + 0x09, 0x20, /* Usage (Stylus), */ + 0xA0, /* Collection (Physical), */ + 0x75, 0x01, /* Report Size (1), */ + 0x09, 0x42, /* Usage (Tip Switch), */ + 0x09, 0x44, /* Usage (Barrel Switch), */ + 0x09, 0x46, /* Usage (Tablet Pick), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x05, /* Report Count (5), */ + 0x81, 0x01, /* Input (Constant), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x01, /* Report Count (1), */ + 0x14, /* Logical Minimum (0), */ + 0xA4, /* Push, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x55, 0xFD, /* Unit Exponent (-3), */ + 0x65, 0x13, /* Unit (Inch), */ + 0x34, /* Physical Minimum (0), */ + 0x09, 0x30, /* Usage (X), */ + 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x31, /* Usage (Y), */ + 0x46, 0xB8, 0x0B, /* Physical Maximum (3000), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ + 0x81, 0x02, /* Input (Variable), */ + 0xB4, /* Pop, */ + 0x09, 0x30, /* Usage (Tip Pressure), */ + 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ + 0x81, 0x02, /* Input (Variable), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; + +/* Fixed WP5540U report descriptor */ +static __u8 wp5540u_rdesc_fixed[] = { + 0x05, 0x0D, /* Usage Page (Digitizer), */ + 0x09, 0x02, /* Usage (Pen), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x09, /* Report ID (9), */ + 0x09, 0x20, /* Usage (Stylus), */ + 0xA0, /* Collection (Physical), */ + 0x75, 0x01, /* Report Size (1), */ + 0x09, 0x42, /* Usage (Tip Switch), */ + 0x09, 0x44, /* Usage (Barrel Switch), */ + 0x09, 0x46, /* Usage (Tablet Pick), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x05, /* Report Count (5), */ + 0x81, 0x01, /* Input (Constant), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x01, /* Report Count (1), */ + 0x14, /* Logical Minimum (0), */ + 0xA4, /* Push, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x55, 0xFD, /* Unit Exponent (-3), */ + 0x65, 0x13, /* Unit (Inch), */ + 0x34, /* Physical Minimum (0), */ + 0x09, 0x30, /* Usage (X), */ + 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x31, /* Usage (Y), */ + 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ + 0x81, 0x02, /* Input (Variable), */ + 0xB4, /* Pop, */ + 0x09, 0x30, /* Usage (Tip Pressure), */ + 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ + 0x81, 0x02, /* Input (Variable), */ + 0xC0, /* End Collection, */ + 0xC0, /* End Collection, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x02, /* Usage (Mouse), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x08, /* Report ID (8), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xA0, /* Collection (Physical), */ + 0x75, 0x01, /* Report Size (1), */ + 0x05, 0x09, /* Usage Page (Button), */ + 0x19, 0x01, /* Usage Minimum (01h), */ + 0x29, 0x03, /* Usage Maximum (03h), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x05, /* Report Count (5), */ + 0x81, 0x01, /* Input (Constant), */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x75, 0x08, /* Report Size (8), */ + 0x09, 0x30, /* Usage (X), */ + 0x09, 0x31, /* Usage (Y), */ + 0x15, 0x81, /* Logical Minimum (-127), */ + 0x25, 0x7F, /* Logical Maximum (127), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x06, /* Input (Variable, Relative), */ + 0x09, 0x38, /* Usage (Wheel), */ + 0x15, 0xFF, /* Logical Minimum (-1), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x06, /* Input (Variable, Relative), */ + 0x81, 0x01, /* Input (Constant), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; + +/* Fixed WP8060U report descriptor */ +static __u8 wp8060u_rdesc_fixed[] = { + 0x05, 0x0D, /* Usage Page (Digitizer), */ + 0x09, 0x02, /* Usage (Pen), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x09, /* Report ID (9), */ + 0x09, 0x20, /* Usage (Stylus), */ + 0xA0, /* Collection (Physical), */ + 0x75, 0x01, /* Report Size (1), */ + 0x09, 0x42, /* Usage (Tip Switch), */ + 0x09, 0x44, /* Usage (Barrel Switch), */ + 0x09, 0x46, /* Usage (Tablet Pick), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x05, /* Report Count (5), */ + 0x81, 0x01, /* Input (Constant), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x01, /* Report Count (1), */ + 0x14, /* Logical Minimum (0), */ + 0xA4, /* Push, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x55, 0xFD, /* Unit Exponent (-3), */ + 0x65, 0x13, /* Unit (Inch), */ + 0x34, /* Physical Minimum (0), */ + 0x09, 0x30, /* Usage (X), */ + 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x31, /* Usage (Y), */ + 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ + 0x81, 0x02, /* Input (Variable), */ + 0xB4, /* Pop, */ + 0x09, 0x30, /* Usage (Tip Pressure), */ + 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ + 0x81, 0x02, /* Input (Variable), */ + 0xC0, /* End Collection, */ + 0xC0, /* End Collection, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x02, /* Usage (Mouse), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x08, /* Report ID (8), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xA0, /* Collection (Physical), */ + 0x75, 0x01, /* Report Size (1), */ + 0x05, 0x09, /* Usage Page (Button), */ + 0x19, 0x01, /* Usage Minimum (01h), */ + 0x29, 0x03, /* Usage Maximum (03h), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x05, /* Report Count (5), */ + 0x81, 0x01, /* Input (Constant), */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x75, 0x08, /* Report Size (8), */ + 0x09, 0x30, /* Usage (X), */ + 0x09, 0x31, /* Usage (Y), */ + 0x15, 0x81, /* Logical Minimum (-127), */ + 0x25, 0x7F, /* Logical Maximum (127), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x06, /* Input (Variable, Relative), */ + 0x09, 0x38, /* Usage (Wheel), */ + 0x15, 0xFF, /* Logical Minimum (-1), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x06, /* Input (Variable, Relative), */ + 0x81, 0x01, /* Input (Constant), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; + +static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + switch (hdev->product) { + case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U: + if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) + { + rdesc = wp4030u_rdesc_fixed; + *rsize = sizeof(wp4030u_rdesc_fixed); + } + break; + case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U: + if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) + { + rdesc = wp5540u_rdesc_fixed; + *rsize = sizeof(wp5540u_rdesc_fixed); + } + break; + case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U: + if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) + { + rdesc = wp8060u_rdesc_fixed; + *rsize = sizeof(wp8060u_rdesc_fixed); + } + break; + } + + return rdesc; +} + +static const struct hid_device_id uclogic_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, + USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, + USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, + USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, + { } +}; +MODULE_DEVICE_TABLE(hid, uclogic_devices); + +static struct hid_driver uclogic_driver = { + .name = "uclogic", + .id_table = uclogic_devices, + .report_fixup = uclogic_report_fixup, +}; + +static int __init uclogic_init(void) +{ + return hid_register_driver(&uclogic_driver); +} + +static void __exit uclogic_exit(void) +{ + hid_unregister_driver(&uclogic_driver); +} + +module_init(uclogic_init); +module_exit(uclogic_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 2643d3147621..162aa4b40205 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -68,7 +68,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, -- cgit v1.2.3-59-g8ed1b From f36ee074d5d563a832fbfc378207739db3a0a205 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Mon, 9 Aug 2010 19:56:01 +0200 Subject: HID: uclogic: fix up Kconfig entry Remove remains of the original dependency of the driver on CONFIG_EMBEDDED. Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index d0b43c9fc245..34402bb5f6a0 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -177,7 +177,7 @@ config HID_KYE Support for Kye/Genius Ergo Mouse. config HID_UCLOGIC - tristate "UC-Logic" if EMBEDDED + tristate "UC-Logic" depends on USB_HID ---help--- Support for UC-Logic tablets. -- cgit v1.2.3-59-g8ed1b From 698cb111f44d81dd3a604ba2a7f3f865b66b9ddf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 6 Aug 2010 17:23:02 +0100 Subject: ASoC: Remove /s from widget names on SMDK64xx WM8580 Otherwise debugfs gets upset when we try to create filenames with / in them. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/s3c24xx/smdk64xx_wm8580.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c index 07e8e51d10d6..5853f6609f6f 100644 --- a/sound/soc/s3c24xx/smdk64xx_wm8580.c +++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c @@ -138,9 +138,9 @@ static struct snd_soc_ops smdk64xx_ops = { /* SMDK64xx Playback widgets */ static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = { - SND_SOC_DAPM_HP("Front-L/R", NULL), - SND_SOC_DAPM_HP("Center/Sub", NULL), - SND_SOC_DAPM_HP("Rear-L/R", NULL), + SND_SOC_DAPM_HP("Front", NULL), + SND_SOC_DAPM_HP("Center+Sub", NULL), + SND_SOC_DAPM_HP("Rear", NULL), }; /* SMDK64xx Capture widgets */ @@ -162,16 +162,16 @@ static const struct snd_soc_dapm_route audio_map_tx[] = { /* SMDK-PAIFRX connections */ static const struct snd_soc_dapm_route audio_map_rx[] = { /* Front Left/Right are fed VOUT1L/R */ - {"Front-L/R", NULL, "VOUT1L"}, - {"Front-L/R", NULL, "VOUT1R"}, + {"Front", NULL, "VOUT1L"}, + {"Front", NULL, "VOUT1R"}, /* Center/Sub are fed VOUT2L/R */ - {"Center/Sub", NULL, "VOUT2L"}, - {"Center/Sub", NULL, "VOUT2R"}, + {"Center+Sub", NULL, "VOUT2L"}, + {"Center+Sub", NULL, "VOUT2R"}, /* Rear Left/Right are fed VOUT3L/R */ - {"Rear-L/R", NULL, "VOUT3L"}, - {"Rear-L/R", NULL, "VOUT3R"}, + {"Rear", NULL, "VOUT3L"}, + {"Rear", NULL, "VOUT3R"}, }; static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec) -- cgit v1.2.3-59-g8ed1b From 9d37e8947c613190b7b92c63830e638ffdb08e48 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 6 Aug 2010 17:57:45 +0100 Subject: ASoC: Document CFG switch settings for SMDK6410 WM8580 usage Sadly these aren't soft controllable and can't be read back either :( Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/s3c24xx/smdk64xx_wm8580.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c index 5853f6609f6f..4926acaaa8b0 100644 --- a/sound/soc/s3c24xx/smdk64xx_wm8580.c +++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c @@ -22,6 +22,12 @@ #include "s3c-dma.h" #include "s3c64xx-i2s.h" +/* + * Default CFG switch settings to use this driver: + * + * SMDK6410: Set CFG1 1-3 Off, CFG2 1-4 On + */ + /* SMDK64XX has a 12MHZ crystal attached to WM8580 */ #define SMDK64XX_WM8580_FREQ 12000000 -- cgit v1.2.3-59-g8ed1b From 6f341d14811550d863ba804ce6ec7757a7145081 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 6 Aug 2010 18:14:09 +0100 Subject: ASoC: Correct WM8580 Capture control names Should use Capture rather than ADC so the UI tools can identify their function more readily. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8580.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index c3571ee5c11b..1881b16bc248 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -273,8 +273,8 @@ SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 0), SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 0), SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 0), -SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), -SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), +SOC_DOUBLE("Capture Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), +SOC_SINGLE("Capture High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), }; static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { -- cgit v1.2.3-59-g8ed1b From 429d646d9aeafdb57717dab75c807215f5cce9c2 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 5 Aug 2010 10:44:48 +0200 Subject: Doc: Fix spelling Legned -> Legend mainatined -> maintained Legend is now Lenovo, so more fixes (text and url) would be possible, too. Cc: Jiri Kosina Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Stefan Weil Signed-off-by: Jiri Kosina --- Documentation/arm/SA1100/FreeBird | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/arm/SA1100/FreeBird b/Documentation/arm/SA1100/FreeBird index fb23b770aaf4..ab9193663b2b 100644 --- a/Documentation/arm/SA1100/FreeBird +++ b/Documentation/arm/SA1100/FreeBird @@ -1,6 +1,6 @@ -Freebird-1.1 is produced by Legned(C) ,Inc. +Freebird-1.1 is produced by Legend(C), Inc. http://web.archive.org/web/*/http://www.legend.com.cn -and software/linux mainatined by Coventive(C),Inc. +and software/linux maintained by Coventive(C), Inc. (http://www.coventive.com) Based on the Nicolas's strongarm kernel tree. -- cgit v1.2.3-59-g8ed1b From 7f26b3a7533bbc1ddd88b297c935ee4da8f74cea Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 4 Aug 2010 10:40:08 -0700 Subject: drivers/usb: Remove unnecessary return's from void functions Greg prefers this to go through the trivial tree. http://lkml.org/lkml/2010/6/24/1 There are about 2500 void functions in drivers/usb Only a few used return; at end of function. Standardize them a bit. Moved a statement down a line in drivers/usb/host/u132-hcd.c Signed-off-by: Joe Perches Signed-off-by: Jiri Kosina --- drivers/usb/gadget/at91_udc.c | 1 - drivers/usb/gadget/f_audio.c | 2 -- drivers/usb/gadget/f_hid.c | 4 ---- drivers/usb/gadget/fsl_udc_core.c | 6 ------ drivers/usb/gadget/langwell_udc.c | 3 --- drivers/usb/gadget/pxa27x_udc.c | 2 -- drivers/usb/gadget/rndis.c | 2 -- drivers/usb/host/ehci-hcd.c | 1 - drivers/usb/host/ohci-hcd.c | 1 - drivers/usb/host/oxu210hp-hcd.c | 9 --------- drivers/usb/host/pci-quirks.c | 2 -- drivers/usb/host/u132-hcd.c | 8 ++------ drivers/usb/image/microtek.c | 9 --------- drivers/usb/misc/ftdi-elan.c | 2 -- drivers/usb/mon/mon_main.c | 2 -- drivers/usb/musb/musb_gadget.c | 1 - drivers/usb/serial/cypress_m8.c | 2 -- drivers/usb/serial/ftdi_sio.c | 1 - drivers/usb/serial/garmin_gps.c | 1 - drivers/usb/serial/io_edgeport.c | 11 ----------- drivers/usb/serial/io_ti.c | 4 ---- drivers/usb/serial/iuu_phoenix.c | 1 - drivers/usb/serial/keyspan_pda.c | 1 - drivers/usb/serial/mos7720.c | 6 ------ drivers/usb/serial/mos7840.c | 7 ------- drivers/usb/serial/omninet.c | 2 -- drivers/usb/serial/sierra.c | 2 -- drivers/usb/serial/spcp8x5.c | 1 - drivers/usb/serial/usb_wwan.c | 1 - drivers/usb/serial/whiteheat.c | 6 ------ 30 files changed, 2 insertions(+), 99 deletions(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 93ead19507b6..d90c9e89688e 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1266,7 +1266,6 @@ write_in: csr |= AT91_UDP_TXPKTRDY; __raw_writel(csr, creg); udc->req_pending = 0; - return; } static void handle_ep0(struct at91_udc *udc) diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_audio.c index 1f48ceb55a77..00975ed903d1 100644 --- a/drivers/usb/gadget/f_audio.c +++ b/drivers/usb/gadget/f_audio.c @@ -317,8 +317,6 @@ static void f_audio_playback_work(struct work_struct *data) u_audio_playback(&audio->card, play_buf->buf, play_buf->actual); f_audio_buffer_free(play_buf); - - return; } static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req) diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c index 1e00ff9866af..9447427fcbff 100644 --- a/drivers/usb/gadget/f_hid.c +++ b/drivers/usb/gadget/f_hid.c @@ -318,8 +318,6 @@ static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) spin_unlock(&hidg->spinlock); wake_up(&hidg->read_queue); - - return; } static int hidg_setup(struct usb_function *f, @@ -413,8 +411,6 @@ static void hidg_disable(struct usb_function *f) usb_ep_disable(hidg->in_ep); hidg->in_ep->driver_data = NULL; - - return; } static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 08a9a62a39e3..d933e6398412 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -287,8 +287,6 @@ static void dr_controller_run(struct fsl_udc *udc) temp = fsl_readl(&dr_regs->usbcmd); temp |= USB_CMD_RUN_STOP; fsl_writel(temp, &dr_regs->usbcmd); - - return; } static void dr_controller_stop(struct fsl_udc *udc) @@ -308,8 +306,6 @@ static void dr_controller_stop(struct fsl_udc *udc) tmp = fsl_readl(&dr_regs->usbcmd); tmp &= ~USB_CMD_RUN_STOP; fsl_writel(tmp, &dr_regs->usbcmd); - - return; } static void dr_ep_setup(unsigned char ep_num, unsigned char dir, @@ -416,8 +412,6 @@ static void struct_ep_qh_setup(struct fsl_udc *udc, unsigned char ep_num, p_QH->max_pkt_length = cpu_to_le32(tmp); p_QH->next_dtd_ptr = 1; p_QH->size_ioc_int_sts = 0; - - return; } /* Setup qh structure and ep register for ep0. */ diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index a3913519fd58..f1a070280c9c 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -284,7 +284,6 @@ static void ep0_reset(struct langwell_udc *dev) } VDBG(dev, "<--- %s()\n", __func__); - return; } @@ -1486,7 +1485,6 @@ static void langwell_udc_start(struct langwell_udc *dev) writel(usbcmd, &dev->op_regs->usbcmd); DBG(dev, "<--- %s()\n", __func__); - return; } @@ -1509,7 +1507,6 @@ static void langwell_udc_stop(struct langwell_udc *dev) writel(usbcmd, &dev->op_regs->usbcmd); DBG(dev, "<--- %s()\n", __func__); - return; } diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 980762453a9c..98dfa181449f 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1394,8 +1394,6 @@ static void pxa_ep_fifo_flush(struct usb_ep *_ep) } spin_unlock_irqrestore(&ep->lock, flags); - - return; } /** diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 020fa5a25fda..eb61ab4b302c 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -916,8 +916,6 @@ void rndis_deregister (int configNr) if (configNr >= RNDIS_MAX_CONFIGS) return; rndis_per_dev_params [configNr].used = 0; - - return; } int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a3ef2a9d9dc2..6fcffe15a005 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1041,7 +1041,6 @@ nogood: ep->hcpriv = NULL; done: spin_unlock_irqrestore (&ehci->lock, flags); - return; } static void diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 02864a237a2c..3ceb097e165a 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -370,7 +370,6 @@ sanitize: } ep->hcpriv = NULL; spin_unlock_irqrestore (&ohci->lock, flags); - return; } static int ohci_get_frame (struct usb_hcd *hcd) diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index f608dfd09a8a..de9e1c35da45 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -544,8 +544,6 @@ static void oxu_buf_free(struct oxu_hcd *oxu, struct ehci_qtd *qtd) qtd->buffer = NULL; spin_unlock(&oxu->mem_lock); - - return; } static inline void ehci_qtd_init(struct ehci_qtd *qtd, dma_addr_t dma) @@ -571,8 +569,6 @@ static inline void oxu_qtd_free(struct oxu_hcd *oxu, struct ehci_qtd *qtd) oxu->qtd_used[index] = 0; spin_unlock(&oxu->mem_lock); - - return; } static struct ehci_qtd *ehci_qtd_alloc(struct oxu_hcd *oxu) @@ -615,8 +611,6 @@ static void oxu_qh_free(struct oxu_hcd *oxu, struct ehci_qh *qh) oxu->qh_used[index] = 0; spin_unlock(&oxu->mem_lock); - - return; } static void qh_destroy(struct kref *kref) @@ -693,8 +687,6 @@ static void oxu_murb_free(struct oxu_hcd *oxu, struct oxu_murb *murb) oxu->murb_used[index] = 0; spin_unlock(&oxu->mem_lock); - - return; } static struct oxu_murb *oxu_murb_alloc(struct oxu_hcd *oxu) @@ -3073,7 +3065,6 @@ nogood: ep->hcpriv = NULL; done: spin_unlock_irqrestore(&oxu->lock, flags); - return; } static int oxu_get_frame(struct usb_hcd *hcd) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 83b5f9cea85a..5b37b08e0d80 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -338,8 +338,6 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) writel(0x3f, op_reg_base + EHCI_USBSTS); iounmap(base); - - return; } /* diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 5b31bae92dbc..fab764946c74 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -316,7 +316,6 @@ static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring, } else if (queue_delayed_work(workqueue, &ring->scheduler, 0)) return; kref_put(&u132->kref, u132_hcd_delete); - return; } static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring, @@ -324,7 +323,6 @@ static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring, { kref_get(&u132->kref); u132_ring_requeue_work(u132, ring, delta); - return; } static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring) @@ -543,7 +541,6 @@ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp, mutex_unlock(&u132->scheduler_lock); u132_endp_put_kref(u132, endp); usb_hcd_giveback_urb(hcd, urb, status); - return; } static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp, @@ -574,8 +571,8 @@ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp, endp->active = 0; spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); kfree(urbq); - } usb_hcd_giveback_urb(hcd, urb, status); - return; + } + usb_hcd_giveback_urb(hcd, urb, status); } static inline int edset_input(struct u132 *u132, struct u132_ring *ring, @@ -3085,7 +3082,6 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) u132->endp[endps] = NULL; mutex_unlock(&u132->sw_lock); - return; } static int __devinit u132_probe(struct platform_device *pdev) diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 3a6bcd5fee09..5a47805d9580 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -398,7 +398,6 @@ void mts_int_submit_urb (struct urb* transfer, context->srb->result = DID_ERROR << 16; mts_transfer_cleanup(transfer); } - return; } @@ -409,7 +408,6 @@ static void mts_transfer_cleanup( struct urb *transfer ) if ( likely(context->final_callback != NULL) ) context->final_callback(context->srb); - } static void mts_transfer_done( struct urb *transfer ) @@ -420,8 +418,6 @@ static void mts_transfer_done( struct urb *transfer ) context->srb->result |= (unsigned)(*context->scsi_status)<<1; mts_transfer_cleanup(transfer); - - return; } @@ -452,8 +448,6 @@ static void mts_data_done( struct urb* transfer ) } mts_get_status(transfer); - - return; } @@ -496,8 +490,6 @@ static void mts_command_done( struct urb *transfer ) mts_get_status(transfer); } } - - return; } static void mts_do_sg (struct urb* transfer) @@ -522,7 +514,6 @@ static void mts_do_sg (struct urb* transfer) sg[context->fragment].length, context->fragment + 1 == scsi_sg_count(context->srb) ? mts_data_done : mts_do_sg); - return; } static const u8 mts_read_image_sig[] = { 0x28, 00, 00, 00 }; diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 82e16630a78b..d7e034a5e1f9 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -456,7 +456,6 @@ static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi) static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi) { ftdi_command_queue_work(ftdi, 0); - return; } static void ftdi_elan_command_work(struct work_struct *work) @@ -483,7 +482,6 @@ static void ftdi_elan_command_work(struct work_struct *work) static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi) { ftdi_respond_queue_work(ftdi, 0); - return; } static void ftdi_elan_respond_work(struct work_struct *work) diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 812dc288bb8c..10405119985c 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -90,7 +90,6 @@ static void mon_bus_submit(struct mon_bus *mbus, struct urb *urb) r->rnf_submit(r->r_data, urb); } spin_unlock_irqrestore(&mbus->lock, flags); - return; } static void mon_submit(struct usb_bus *ubus, struct urb *urb) @@ -117,7 +116,6 @@ static void mon_bus_submit_error(struct mon_bus *mbus, struct urb *urb, int erro r->rnf_error(r->r_data, urb, error); } spin_unlock_irqrestore(&mbus->lock, flags); - return; } static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 6fca870e957e..a83a139da5bc 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -829,7 +829,6 @@ void musb_g_rx(struct musb *musb, u8 epnum) DBG(3, "packet waiting for %s%s request\n", musb_ep->desc ? "" : "inactive ", musb_ep->end_point.name); - return; } /* ------------------------------------------------------------ */ diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index f5d06746cc3b..2edf238b00b9 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -1320,8 +1320,6 @@ continue_read: cypress_set_dead(port); } } - - return; } /* cypress_read_int_callback */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e298dc4baed7..e34023ff5771 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2065,7 +2065,6 @@ static void ftdi_set_termios(struct tty_struct *tty, /* lower DTR/RTS */ clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } - return; } static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index a42b29a695b2..26710b189918 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1264,7 +1264,6 @@ static void garmin_read_bulk_callback(struct urb *urb) garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE; spin_unlock_irqrestore(&garmin_data_p->lock, flags); } - return; } diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 76e6fb3aab7a..892e916ef67e 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1465,8 +1465,6 @@ static void edge_throttle(struct tty_struct *tty) if (status != 0) return; } - - return; } @@ -1770,8 +1768,6 @@ static void edge_break(struct tty_struct *tty, int break_state) dbg("%s - error sending break set/clear command.", __func__); } - - return; } @@ -2042,7 +2038,6 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, dbg("%s - Unrecognized IOSP status code %u", __func__, code); break; } - return; } @@ -2095,8 +2090,6 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr) /* Save the new modem status */ edge_port->shadowMSR = newMsr & 0xf0; - - return; } @@ -2143,8 +2136,6 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, icount->parity++; if (newLsr & LSR_FRM_ERR) icount->frame++; - - return; } @@ -2720,7 +2711,6 @@ static void change_port_settings(struct tty_struct *tty, baud = tty_termios_baud_rate(old_termios); tty_encode_baud_rate(tty, baud, baud); } - return; } @@ -2922,7 +2912,6 @@ static void load_application_firmware(struct edgeport_serial *edge_serial) 0x40, 0x4000, 0x0001, NULL, 0, 3000); release_firmware(fw); - return; } diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 0fca2659206f..4a6da66d5fd2 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -1571,8 +1571,6 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr) } } tty_kref_put(tty); - - return; } static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, @@ -2424,7 +2422,6 @@ static void change_port_settings(struct tty_struct *tty, dbg("%s - error %d when trying to write config to device", __func__, status); kfree(config); - return; } static void edge_set_termios(struct tty_struct *tty, @@ -2445,7 +2442,6 @@ static void edge_set_termios(struct tty_struct *tty, return; /* change the port settings to the new ones specified */ change_port_settings(tty, edge_port, old_termios); - return; } static int edge_tiocmset(struct tty_struct *tty, struct file *file, diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 74551cb2e8ee..55766a65f0ad 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -801,7 +801,6 @@ static void read_rxcmd_callback(struct urb *urb) iuu_uart_read_callback, port); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); dbg("%s - submit result = %d", __func__, result); - return; } static int iuu_uart_on(struct usb_serial_port *port) diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 185fe9a7d4e0..a10dd5676ccc 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -292,7 +292,6 @@ static void keyspan_pda_rx_unthrottle(struct tty_struct *tty) port->interrupt_in_urb->dev = port->serial->dev; if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL)) dbg(" usb_submit_urb(read urb) failed"); - return; } diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 30922a7e3347..f442333dfa99 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -827,7 +827,6 @@ exit: dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __func__, result); - return; } /* @@ -907,7 +906,6 @@ exit: dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __func__, result); - return; } /* @@ -1227,8 +1225,6 @@ static void mos7720_break(struct tty_struct *tty, int break_state) mos7720_port->shadowLCR = data; write_mos_reg(serial, port->number - port->serial->minor, LCR, mos7720_port->shadowLCR); - - return; } /* @@ -1746,7 +1742,6 @@ static void change_port_settings(struct tty_struct *tty, dbg("usb_submit_urb(read bulk) failed, status = %d", status); } - return; } /* @@ -1803,7 +1798,6 @@ static void mos7720_set_termios(struct tty_struct *tty, dbg("usb_submit_urb(read bulk) failed, status = %d", status); } - return; } /* diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 585b7e663740..d3fc30c5959d 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1355,8 +1355,6 @@ static void mos7840_break(struct tty_struct *tty, int break_state) mos7840_port->shadowLCR); mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, mos7840_port->shadowLCR); - - return; } /***************************************************************************** @@ -1587,8 +1585,6 @@ static void mos7840_throttle(struct tty_struct *tty) if (status < 0) return; } - - return; } /***************************************************************************** @@ -2063,8 +2059,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty, mos7840_port->delta_msr_cond = 1; dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x", mos7840_port->shadowLCR); - - return; } /***************************************************************************** @@ -2133,7 +2127,6 @@ static void mos7840_set_termios(struct tty_struct *tty, mos7840_port->read_urb_busy = false; } } - return; } /***************************************************************************** diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 89c724c0ac0a..60f38d5e64fc 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -246,8 +246,6 @@ static void omninet_read_bulk_callback(struct urb *urb) dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result); - - return; } static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index d47b56e9e8ce..7481ff8a49e4 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -620,8 +620,6 @@ static void sierra_indat_callback(struct urb *urb) dev_err(&port->dev, "resubmit read urb failed." "(%d)\n", err); } - - return; } static void sierra_instat_callback(struct urb *urb) diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 329d311a35d9..765aa983bf58 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -441,7 +441,6 @@ static void spcp8x5_set_termios(struct tty_struct *tty, spcp8x5_set_workMode(serial->dev, 0x000a, SET_WORKING_MODE_U2C, priv->type); } - return; } /* open the serial port. do some usb system call. set termios and get the line diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 0c70b4a621bb..fbc946797801 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -234,7 +234,6 @@ static void usb_wwan_indat_callback(struct urb *urb) } } - return; } static void usb_wwan_outdat_callback(struct urb *urb) diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 12ed8209ca72..3f9ac88d588c 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -655,8 +655,6 @@ static void whiteheat_release(struct usb_serial *serial) } kfree(info); } - - return; } static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -955,8 +953,6 @@ static void whiteheat_throttle(struct tty_struct *tty) spin_lock_irq(&info->lock); info->flags |= THROTTLED; spin_unlock_irq(&info->lock); - - return; } @@ -975,8 +971,6 @@ static void whiteheat_unthrottle(struct tty_struct *tty) if (actually_throttled) rx_data_softint(&info->rx_work); - - return; } -- cgit v1.2.3-59-g8ed1b From 4785879e4d340e24e54f6de2ccfc42728b912808 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 11 Aug 2010 11:24:10 +0900 Subject: fix a typo on comments in mm/percpu.c 'eqaul' should be 'equal'. Signed-off-by: Namhyung Kim Signed-off-by: Jiri Kosina --- mm/percpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/percpu.c b/mm/percpu.c index e61dc2cc5873..039f51a0dc3f 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -31,7 +31,7 @@ * as small as 4 bytes. The allocator organizes chunks into lists * according to free size and tries to allocate from the fullest one. * Each chunk keeps the maximum contiguous area size hint which is - * guaranteed to be eqaul to or larger than the maximum contiguous + * guaranteed to be equal to or larger than the maximum contiguous * area in the chunk. This helps the allocator not to iterate the * chunk maps unnecessarily. * -- cgit v1.2.3-59-g8ed1b From f0fba2ad1b6b53d5360125c41953b7afcd6deff0 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 17 Mar 2010 20:15:21 +0000 Subject: ASoC: multi-component - ASoC Multi-Component Support This patch extends the ASoC API to allow sound cards to have more than one CODEC and more than one platform DMA controller. This is achieved by dividing some current ASoC structures that contain both driver data and device data into structures that only either contain device data or driver data. i.e. struct snd_soc_codec ---> struct snd_soc_codec (device data) +-> struct snd_soc_codec_driver (driver data) struct snd_soc_platform ---> struct snd_soc_platform (device data) +-> struct snd_soc_platform_driver (driver data) struct snd_soc_dai ---> struct snd_soc_dai (device data) +-> struct snd_soc_dai_driver (driver data) struct snd_soc_device ---> deleted This now allows ASoC to be more tightly aligned with the Linux driver model and also means that every ASoC codec, platform and (platform) DAI is a kernel device. ASoC component private data is now stored as device private data. The ASoC sound card struct snd_soc_card has also been updated to store lists of it's components rather than a pointer to a codec and platform. The PCM runtime struct soc_pcm_runtime now has pointers to all its components. This patch adds DAPM support for ASoC multi-component and removes struct snd_soc_socdev from DAPM core. All DAPM calls are now made on a card, codec or runtime PCM level basis rather than using snd_soc_socdev. Other notable multi-component changes:- * Stream operations now de-reference less structures. * close_delayed work() now runs on a DAI basis rather than looping all DAIs in a card. * PM suspend()/resume() operations can now handle N CODECs and Platforms per sound card. * Added soc_bind_dai_link() to bind the component devices to the sound card. * Added soc_dai_link_probe() and soc_dai_link_remove() to probe and remove DAI link components. * sysfs entries can now be registered per component per card. * snd_soc_new_pcms() functionailty rolled into dai_link_probe(). * snd_soc_register_codec() now does all the codec list and mutex init. This patch changes the probe() and remove() of the CODEC drivers as follows:- o Make CODEC driver a platform driver o Moved all struct snd_soc_codec list, mutex, etc initialiasation to core. o Removed all static codec pointers (drivers now support > 1 codec dev) o snd_soc_register_pcms() now done by core. o snd_soc_register_dai() folded into snd_soc_register_codec(). CS4270 portions: Acked-by: Timur Tabi Some TLV320aic23 and Cirrus platform fixes. Signed-off-by: Ryan Mallon TI CODEC and OMAP fixes Signed-off-by: Peter Ujfalusi Signed-off-by: Janusz Krzysztofik Signed-off-by: Jarkko Nikula Samsung platform and misc fixes :- Signed-off-by: Chanwoo Choi Signed-off-by: Joonyoung Shim Signed-off-by: Kyungmin Park Reviewed-by: Jassi Brar Signed-off-by: Seungwhan Youn MPC8610 and PPC fixes. Signed-off-by: Timur Tabi i.MX fixes and some core fixes. Signed-off-by: Sascha Hauer J4740 platform fixes:- Signed-off-by: Lars-Peter Clausen CC: Tony Lindgren CC: Nicolas Ferre CC: Kevin Hilman CC: Sascha Hauer CC: Atsushi Nemoto CC: Kuninori Morimoto CC: Daniel Gloeckner CC: Manuel Lauss CC: Mike Frysinger CC: Arnaud Patard CC: Wan ZongShun Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- arch/arm/mach-davinci/devices.c | 13 + arch/arm/mach-ep93xx/core.c | 6 + arch/arm/mach-kirkwood/common.c | 6 + arch/arm/mach-mx2/clock_imx27.c | 4 +- arch/arm/mach-mx2/devices.c | 2 +- arch/arm/mach-mx3/clock-imx31.c | 4 +- arch/arm/mach-mx3/clock-imx35.c | 4 +- arch/arm/mach-mx3/devices.c | 4 +- arch/arm/mach-omap1/devices.c | 26 + arch/arm/mach-omap2/board-n8x0.c | 15 + arch/arm/mach-omap2/board-rx51-peripherals.c | 14 +- arch/arm/mach-omap2/board-zoom2.c | 28 +- arch/arm/mach-omap2/devices.c | 39 + arch/arm/mach-omap2/include/mach/board-zoom.h | 2 + arch/arm/mach-pxa/devices.c | 25 + arch/arm/mach-pxa/devices.h | 6 + arch/arm/mach-pxa/pxa27x.c | 4 + arch/arm/mach-pxa/pxa3xx.c | 5 + arch/arm/mach-pxa/zylonite.c | 11 + arch/arm/mach-s3c64xx/dev-audio.c | 13 + arch/arm/mach-s3c64xx/mach-smdk6410.c | 1 + arch/arm/plat-mxc/audmux-v2.c | 4 +- arch/arm/plat-omap/include/plat/mcbsp.h | 7 + arch/arm/plat-s3c24xx/devs.c | 30 +- arch/arm/plat-samsung/include/plat/devs.h | 2 + drivers/input/misc/twl4030-vibra.c | 4 +- drivers/mfd/twl-core.c | 6 +- drivers/mfd/twl4030-codec.c | 8 +- include/linux/i2c/twl.h | 6 +- include/sound/sh_fsi.h | 4 +- include/sound/soc-dai.h | 98 +- include/sound/soc-dapm.h | 8 +- include/sound/soc-of-simple.h | 25 - include/sound/soc.h | 236 ++-- include/sound/tlv320aic3x.h | 43 +- sound/soc/atmel/atmel-pcm.c | 59 +- sound/soc/atmel/atmel-pcm.h | 3 - sound/soc/atmel/atmel_ssc_dai.c | 97 +- sound/soc/atmel/atmel_ssc_dai.h | 1 - sound/soc/atmel/playpaq_wm8510.c | 65 +- sound/soc/atmel/sam9g20_wm8731.c | 51 +- sound/soc/atmel/snd-soc-afeb9260.c | 35 +- sound/soc/au1x/db1200.c | 35 +- sound/soc/au1x/dbdma2.c | 19 +- sound/soc/au1x/psc-ac97.c | 20 +- sound/soc/au1x/psc-i2s.c | 21 +- sound/soc/au1x/psc.h | 3 - sound/soc/blackfin/bf5xx-ac97-pcm.c | 43 +- sound/soc/blackfin/bf5xx-ac97-pcm.h | 3 - sound/soc/blackfin/bf5xx-ac97.c | 41 +- sound/soc/blackfin/bf5xx-ac97.h | 2 - sound/soc/blackfin/bf5xx-ad1836.c | 23 +- sound/soc/blackfin/bf5xx-ad193x.c | 23 +- sound/soc/blackfin/bf5xx-ad1980.c | 19 +- sound/soc/blackfin/bf5xx-ad73311.c | 22 +- sound/soc/blackfin/bf5xx-i2s-pcm.c | 44 +- sound/soc/blackfin/bf5xx-i2s-pcm.h | 3 - sound/soc/blackfin/bf5xx-i2s.c | 45 +- sound/soc/blackfin/bf5xx-i2s.h | 14 - sound/soc/blackfin/bf5xx-ssm2602.c | 38 +- sound/soc/blackfin/bf5xx-tdm-pcm.c | 43 +- sound/soc/blackfin/bf5xx-tdm-pcm.h | 3 - sound/soc/blackfin/bf5xx-tdm.c | 15 +- sound/soc/blackfin/bf5xx-tdm.h | 2 - sound/soc/codecs/ac97.c | 124 +- sound/soc/codecs/ac97.h | 19 - sound/soc/codecs/ad1836.c | 191 +-- sound/soc/codecs/ad1836.h | 2 - sound/soc/codecs/ad193x.c | 217 ++- sound/soc/codecs/ad193x.h | 3 - sound/soc/codecs/ad1980.c | 107 +- sound/soc/codecs/ad1980.h | 3 - sound/soc/codecs/ad73311.c | 66 +- sound/soc/codecs/ad73311.h | 2 - sound/soc/codecs/ads117x.c | 72 +- sound/soc/codecs/ads117x.h | 4 +- sound/soc/codecs/ak4104.c | 149 +-- sound/soc/codecs/ak4104.h | 7 - sound/soc/codecs/ak4535.c | 236 +--- sound/soc/codecs/ak4535.h | 8 - sound/soc/codecs/ak4642.c | 175 +-- sound/soc/codecs/ak4642.h | 20 - sound/soc/codecs/ak4671.c | 141 +- sound/soc/codecs/ak4671.h | 3 - sound/soc/codecs/cq93vc.c | 132 +- sound/soc/codecs/cq93vc.h | 29 - sound/soc/codecs/cs4270.c | 393 ++---- sound/soc/codecs/cs4270.h | 28 - sound/soc/codecs/cs42l51.c | 293 ++--- sound/soc/codecs/cs42l51.h | 2 - sound/soc/codecs/cx20442.c | 173 +-- sound/soc/codecs/cx20442.h | 2 - sound/soc/codecs/da7210.c | 157 +-- sound/soc/codecs/da7210.h | 24 - sound/soc/codecs/jz4740.c | 116 +- sound/soc/codecs/jz4740.h | 20 - sound/soc/codecs/pcm3008.c | 92 +- sound/soc/codecs/pcm3008.h | 3 - sound/soc/codecs/spdif_transciever.c | 102 +- sound/soc/codecs/spdif_transciever.h | 18 - sound/soc/codecs/ssm2602.c | 219 +--- sound/soc/codecs/ssm2602.h | 3 - sound/soc/codecs/stac9766.c | 118 +- sound/soc/codecs/stac9766.h | 4 - sound/soc/codecs/tlv320aic23.c | 182 +-- sound/soc/codecs/tlv320aic23.h | 3 - sound/soc/codecs/tlv320aic26.c | 180 +-- sound/soc/codecs/tlv320aic26.h | 3 - sound/soc/codecs/tlv320aic3x.c | 223 +--- sound/soc/codecs/tlv320aic3x.h | 43 - sound/soc/codecs/tlv320dac33.c | 249 ++-- sound/soc/codecs/tlv320dac33.h | 3 - sound/soc/codecs/twl4030.c | 231 +--- sound/soc/codecs/twl4030.h | 55 - sound/soc/codecs/twl6040.c | 170 +-- sound/soc/codecs/twl6040.h | 3 - sound/soc/codecs/uda134x.c | 154 +-- sound/soc/codecs/uda134x.h | 3 - sound/soc/codecs/uda1380.c | 211 +-- sound/soc/codecs/uda1380.h | 3 - sound/soc/codecs/wm2000.h | 3 - sound/soc/codecs/wm8350.c | 231 ++-- sound/soc/codecs/wm8350.h | 3 - sound/soc/codecs/wm8400.c | 181 +-- sound/soc/codecs/wm8400.h | 3 - sound/soc/codecs/wm8510.c | 290 ++--- sound/soc/codecs/wm8510.h | 3 - sound/soc/codecs/wm8523.c | 180 +-- sound/soc/codecs/wm8523.h | 3 - sound/soc/codecs/wm8580.c | 186 +-- sound/soc/codecs/wm8580.h | 3 - sound/soc/codecs/wm8711.c | 206 +-- sound/soc/codecs/wm8711.h | 3 - sound/soc/codecs/wm8727.c | 106 +- sound/soc/codecs/wm8727.h | 21 - sound/soc/codecs/wm8728.c | 294 ++--- sound/soc/codecs/wm8728.h | 9 - sound/soc/codecs/wm8731.c | 217 +-- sound/soc/codecs/wm8731.h | 3 - sound/soc/codecs/wm8741.c | 204 +-- sound/soc/codecs/wm8741.h | 3 - sound/soc/codecs/wm8750.c | 269 ++-- sound/soc/codecs/wm8750.h | 9 - sound/soc/codecs/wm8753.c | 407 +++--- sound/soc/codecs/wm8753.h | 3 - sound/soc/codecs/wm8776.c | 251 +--- sound/soc/codecs/wm8776.h | 3 - sound/soc/codecs/wm8900.c | 251 ++-- sound/soc/codecs/wm8900.h | 3 - sound/soc/codecs/wm8903.c | 268 ++-- sound/soc/codecs/wm8903.h | 3 - sound/soc/codecs/wm8904.c | 208 +-- sound/soc/codecs/wm8904.h | 3 - sound/soc/codecs/wm8940.c | 199 +-- sound/soc/codecs/wm8940.h | 2 - sound/soc/codecs/wm8955.c | 184 +-- sound/soc/codecs/wm8955.h | 3 - sound/soc/codecs/wm8960.c | 209 +-- sound/soc/codecs/wm8960.h | 3 - sound/soc/codecs/wm8961.c | 241 ++-- sound/soc/codecs/wm8961.h | 3 - sound/soc/codecs/wm8971.c | 250 +--- sound/soc/codecs/wm8971.h | 8 - sound/soc/codecs/wm8974.c | 171 +-- sound/soc/codecs/wm8974.h | 3 - sound/soc/codecs/wm8978.c | 190 +-- sound/soc/codecs/wm8978.h | 3 - sound/soc/codecs/wm8988.c | 266 ++-- sound/soc/codecs/wm8988.h | 3 - sound/soc/codecs/wm8990.c | 226 +--- sound/soc/codecs/wm8990.h | 8 - sound/soc/codecs/wm8993.c | 307 ++--- sound/soc/codecs/wm8993.h | 3 - sound/soc/codecs/wm8994.c | 230 ++-- sound/soc/codecs/wm8994.h | 3 - sound/soc/codecs/wm9081.c | 208 +-- sound/soc/codecs/wm9081.h | 3 - sound/soc/codecs/wm9090.c | 183 +-- sound/soc/codecs/wm9090.h | 2 - sound/soc/codecs/wm9705.c | 116 +- sound/soc/codecs/wm9705.h | 3 - sound/soc/codecs/wm9712.c | 124 +- sound/soc/codecs/wm9712.h | 3 - sound/soc/codecs/wm9713.c | 131 +- sound/soc/codecs/wm9713.h | 3 - sound/soc/davinci/davinci-evm.c | 109 +- sound/soc/davinci/davinci-i2s.c | 44 +- sound/soc/davinci/davinci-i2s.h | 2 - sound/soc/davinci/davinci-mcasp.c | 32 +- sound/soc/davinci/davinci-mcasp.h | 2 - sound/soc/davinci/davinci-pcm.c | 45 +- sound/soc/davinci/davinci-pcm.h | 3 - sound/soc/davinci/davinci-sffsdr.c | 27 +- sound/soc/davinci/davinci-vcif.c | 25 +- sound/soc/davinci/davinci-vcif.h | 28 - sound/soc/ep93xx/ep93xx-i2s.c | 34 +- sound/soc/ep93xx/ep93xx-i2s.h | 18 - sound/soc/ep93xx/ep93xx-pcm.c | 37 +- sound/soc/ep93xx/ep93xx-pcm.h | 2 - sound/soc/ep93xx/snappercl15.c | 24 +- sound/soc/fsl/Kconfig | 3 - sound/soc/fsl/Makefile | 3 - sound/soc/fsl/efika-audio-fabric.c | 20 +- sound/soc/fsl/fsl_dma.c | 312 +++-- sound/soc/fsl/fsl_dma.h | 20 - sound/soc/fsl/fsl_ssi.c | 249 ++-- sound/soc/fsl/fsl_ssi.h | 26 - sound/soc/fsl/mpc5200_dma.c | 66 +- sound/soc/fsl/mpc5200_dma.h | 5 - sound/soc/fsl/mpc5200_psc_ac97.c | 34 +- sound/soc/fsl/mpc5200_psc_ac97.h | 2 - sound/soc/fsl/mpc5200_psc_i2s.c | 19 +- sound/soc/fsl/mpc8610_hpcd.c | 658 +++++----- sound/soc/fsl/pcm030-audio-fabric.c | 21 +- sound/soc/fsl/soc-of-simple.c | 172 --- sound/soc/imx/Kconfig | 16 + sound/soc/imx/Makefile | 10 +- sound/soc/imx/eukrea-tlv320.c | 16 +- sound/soc/imx/imx-pcm-dma-mx2.c | 43 +- sound/soc/imx/imx-pcm-fiq.c | 68 +- sound/soc/imx/imx-ssi.c | 148 +-- sound/soc/imx/imx-ssi.h | 7 +- sound/soc/imx/phycore-ac97.c | 19 +- sound/soc/imx/wm1133-ev1.c | 27 +- sound/soc/jz4740/jz4740-i2s.c | 104 +- sound/soc/jz4740/jz4740-i2s.h | 2 - sound/soc/jz4740/jz4740-pcm.c | 18 +- sound/soc/jz4740/jz4740-pcm.h | 2 - sound/soc/jz4740/qi_lb60.c | 20 +- sound/soc/kirkwood/kirkwood-dma.c | 64 +- sound/soc/kirkwood/kirkwood-dma.h | 17 - sound/soc/kirkwood/kirkwood-i2s.c | 52 +- sound/soc/kirkwood/kirkwood-i2s.h | 17 - sound/soc/kirkwood/kirkwood-openrd.c | 21 +- sound/soc/nuc900/nuc900-ac97.c | 12 +- sound/soc/nuc900/nuc900-audio.c | 16 +- sound/soc/nuc900/nuc900-audio.h | 4 - sound/soc/nuc900/nuc900-pcm.c | 38 +- sound/soc/omap/am3517evm.c | 25 +- sound/soc/omap/ams-delta.c | 98 +- sound/soc/omap/igep0020.c | 22 +- sound/soc/omap/mcpdm.c | 19 +- sound/soc/omap/mcpdm.h | 2 + sound/soc/omap/n810.c | 42 +- sound/soc/omap/omap-mcbsp.c | 123 +- sound/soc/omap/omap-mcbsp.h | 2 - sound/soc/omap/omap-mcpdm.c | 71 +- sound/soc/omap/omap-mcpdm.h | 29 - sound/soc/omap/omap-pcm.c | 47 +- sound/soc/omap/omap-pcm.h | 2 - sound/soc/omap/omap2evm.c | 25 +- sound/soc/omap/omap3beagle.c | 23 +- sound/soc/omap/omap3evm.c | 30 +- sound/soc/omap/omap3pandora.c | 36 +- sound/soc/omap/osk5912.c | 24 +- sound/soc/omap/overo.c | 22 +- sound/soc/omap/rx51.c | 37 +- sound/soc/omap/sdp3430.c | 56 +- sound/soc/omap/sdp4430.c | 23 +- sound/soc/omap/zoom2.c | 64 +- sound/soc/pxa/corgi.c | 25 +- sound/soc/pxa/e740_wm9705.c | 26 +- sound/soc/pxa/e750_wm9705.c | 26 +- sound/soc/pxa/e800_wm9712.c | 26 +- sound/soc/pxa/em-x270.c | 21 +- sound/soc/pxa/imote2.c | 20 +- sound/soc/pxa/magician.c | 35 +- sound/soc/pxa/mioa701_wm9713.c | 33 +- sound/soc/pxa/palm27x.c | 27 +- sound/soc/pxa/poodle.c | 27 +- sound/soc/pxa/pxa-ssp.c | 148 +-- sound/soc/pxa/pxa-ssp.h | 2 - sound/soc/pxa/pxa2xx-ac97.c | 45 +- sound/soc/pxa/pxa2xx-ac97.h | 2 - sound/soc/pxa/pxa2xx-i2s.c | 89 +- sound/soc/pxa/pxa2xx-i2s.h | 2 - sound/soc/pxa/pxa2xx-pcm.c | 45 +- sound/soc/pxa/pxa2xx-pcm.h | 19 - sound/soc/pxa/raumfeld.c | 114 +- sound/soc/pxa/spitz.c | 62 +- sound/soc/pxa/tosa.c | 27 +- sound/soc/pxa/z2.c | 26 +- sound/soc/pxa/zylonite.c | 40 +- sound/soc/s3c24xx/jive_wm8750.c | 23 +- sound/soc/s3c24xx/ln2440sbc_alc650.c | 17 +- sound/soc/s3c24xx/neo1973_gta02_wm8753.c | 58 +- sound/soc/s3c24xx/neo1973_wm8753.c | 37 +- sound/soc/s3c24xx/s3c-ac97.c | 21 +- sound/soc/s3c24xx/s3c-ac97.h | 2 - sound/soc/s3c24xx/s3c-dma.c | 45 +- sound/soc/s3c24xx/s3c-dma.h | 1 - sound/soc/s3c24xx/s3c-i2s-v2.c | 50 +- sound/soc/s3c24xx/s3c-i2s-v2.h | 13 +- sound/soc/s3c24xx/s3c-pcm.c | 41 +- sound/soc/s3c24xx/s3c2412-i2s.c | 53 +- sound/soc/s3c24xx/s3c2412-i2s.h | 2 - sound/soc/s3c24xx/s3c24xx-i2s.c | 39 +- sound/soc/s3c24xx/s3c24xx-i2s.h | 2 - sound/soc/s3c24xx/s3c24xx_simtec.c | 15 +- sound/soc/s3c24xx/s3c24xx_simtec.h | 4 +- sound/soc/s3c24xx/s3c24xx_simtec_hermes.c | 25 +- sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c | 21 +- sound/soc/s3c24xx/s3c24xx_uda134x.c | 21 +- sound/soc/s3c24xx/s3c64xx-i2s-v4.c | 123 +- sound/soc/s3c24xx/s3c64xx-i2s.c | 205 +-- sound/soc/s3c24xx/s3c64xx-i2s.h | 2 - sound/soc/s3c24xx/smartq_wm8987.c | 15 +- sound/soc/s3c24xx/smdk2443_wm9710.c | 17 +- sound/soc/s3c24xx/smdk64xx_wm8580.c | 33 +- sound/soc/s3c24xx/smdk_wm9713.c | 38 +- sound/soc/s6000/s6000-i2s.c | 56 +- sound/soc/s6000/s6000-i2s.h | 2 - sound/soc/s6000/s6000-pcm.c | 100 +- sound/soc/s6000/s6000-pcm.h | 2 - sound/soc/s6000/s6105-ipcam.c | 31 +- sound/soc/sh/dma-sh7760.c | 53 +- sound/soc/sh/fsi-ak4642.c | 24 +- sound/soc/sh/fsi-da7210.c | 22 +- sound/soc/sh/fsi.c | 47 +- sound/soc/sh/hac.c | 46 +- sound/soc/sh/migor.c | 29 +- sound/soc/sh/sh7760-ac97.c | 25 +- sound/soc/sh/siu.h | 5 +- sound/soc/sh/siu_dai.c | 66 +- sound/soc/sh/siu_pcm.c | 32 +- sound/soc/sh/ssi.c | 55 +- sound/soc/soc-cache.c | 34 +- sound/soc/soc-core.c | 1665 ++++++++++++++---------- sound/soc/soc-dapm.c | 88 +- sound/soc/soc-jack.c | 10 +- sound/soc/txx9/txx9aclc-ac97.c | 55 +- sound/soc/txx9/txx9aclc-generic.c | 24 +- sound/soc/txx9/txx9aclc.c | 141 +- sound/soc/txx9/txx9aclc.h | 13 +- 334 files changed, 8543 insertions(+), 13316 deletions(-) delete mode 100644 include/sound/soc-of-simple.h delete mode 100644 sound/soc/blackfin/bf5xx-i2s.h delete mode 100644 sound/soc/codecs/ac97.h delete mode 100644 sound/soc/codecs/ak4104.h delete mode 100644 sound/soc/codecs/ak4642.h delete mode 100644 sound/soc/codecs/cq93vc.h delete mode 100644 sound/soc/codecs/cs4270.h delete mode 100644 sound/soc/codecs/da7210.h delete mode 100644 sound/soc/codecs/jz4740.h delete mode 100644 sound/soc/codecs/spdif_transciever.h delete mode 100644 sound/soc/codecs/twl4030.h delete mode 100644 sound/soc/codecs/wm8727.h delete mode 100644 sound/soc/davinci/davinci-vcif.h delete mode 100644 sound/soc/ep93xx/ep93xx-i2s.h delete mode 100644 sound/soc/fsl/soc-of-simple.c delete mode 100644 sound/soc/kirkwood/kirkwood-dma.h delete mode 100644 sound/soc/kirkwood/kirkwood-i2s.h delete mode 100644 sound/soc/omap/omap-mcpdm.h delete mode 100644 sound/soc/pxa/pxa2xx-pcm.h diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 8b7201e4c79c..de40e9c787e1 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -295,6 +295,18 @@ static void davinci_init_wdt(void) /*-------------------------------------------------------------------------*/ +struct platform_device davinci_pcm_device = { + .name = "davinci-pcm-audio", + .id = -1, +}; + +static void davinci_init_pcm(void) +{ + platform_device_register(&davinci_pcm_device); +} + +/*-------------------------------------------------------------------------*/ + struct davinci_timer_instance davinci_timer_instance[2] = { { .base = DAVINCI_TIMER0_BASE, @@ -315,6 +327,7 @@ static int __init davinci_init_devices(void) /* please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ + davinci_init_pcm(); davinci_init_wdt(); return 0; diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index b4ee5409eb72..b5261d44b263 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -732,9 +732,15 @@ static struct platform_device ep93xx_i2s_device = { .resource = ep93xx_i2s_resource, }; +static struct platform_device ep93xx_pcm_device = { + .name = "ep93xx-pcm-audio", + .id = -1, +}; + void __init ep93xx_register_i2s(void) { platform_device_register(&ep93xx_i2s_device); + platform_device_register(&ep93xx_pcm_device); } #define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \ diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index e1f3efedbcf1..07690132cdbf 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -896,10 +896,16 @@ static struct platform_device kirkwood_i2s_device = { }, }; +static struct platform_device kirkwood_pcm_device = { + .name = "kirkwood-pcm", + .id = -1, +}; + void __init kirkwood_audio_init(void) { kirkwood_clk_ctrl |= CGC_AUDIO; platform_device_register(&kirkwood_i2s_device); + platform_device_register(&kirkwood_pcm_device); } /***************************************************************************** diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c index 0f0823c8b170..379de9c59332 100644 --- a/arch/arm/mach-mx2/clock_imx27.c +++ b/arch/arm/mach-mx2/clock_imx27.c @@ -653,8 +653,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1) _REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk) _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1) - _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) - _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + _REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk) _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) _REGISTER_CLOCK(NULL, "vpu", vpu_clk) _REGISTER_CLOCK(NULL, "dma", dma_clk) diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index a0aeb8a4adc1..2354d67a10db 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -415,7 +415,7 @@ struct platform_device mxc_usbh2 = { }; \ \ struct platform_device imx_ssi_device ## n = { \ - .name = "imx-ssi", \ + .name = "imx-ssi-dai", \ .id = n, \ .num_resources = ARRAY_SIZE(imx_ssi_resources ## n), \ .resource = imx_ssi_resources ## n, \ diff --git a/arch/arm/mach-mx3/clock-imx31.c b/arch/arm/mach-mx3/clock-imx31.c index 9a9eb6de6127..9b52a67abf2d 100644 --- a/arch/arm/mach-mx3/clock-imx31.c +++ b/arch/arm/mach-mx3/clock-imx31.c @@ -558,8 +558,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk) _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk) _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk) - _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) - _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + _REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk) _REGISTER_CLOCK(NULL, "firi", firi_clk) _REGISTER_CLOCK(NULL, "ata", ata_clk) _REGISTER_CLOCK(NULL, "rtic", rtic_clk) diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index 9f3e943e2232..7b5acd5aa7c1 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -464,8 +464,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "sdma", sdma_clk) _REGISTER_CLOCK(NULL, "spba", spba_clk) _REGISTER_CLOCK(NULL, "spdif", spdif_clk) - _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) - _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + _REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk) _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk) _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk) _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index db7acd6e9101..27cfc39106a8 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -562,14 +562,14 @@ static struct resource imx_ssi_resources1[] = { }; struct platform_device imx_ssi_device0 = { - .name = "imx-ssi", + .name = "imx-ssi-dai", .id = 0, .num_resources = ARRAY_SIZE(imx_ssi_resources0), .resource = imx_ssi_resources0, }; struct platform_device imx_ssi_device1 = { - .name = "imx-ssi", + .name = "imx-ssi-dai", .id = 1, .num_resources = ARRAY_SIZE(imx_ssi_resources1), .resource = imx_ssi_resources1, diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 379100c17639..eb98eb8d3731 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -25,6 +25,7 @@ #include #include #include +#include /*-------------------------------------------------------------------------*/ @@ -267,6 +268,30 @@ static inline void omap_init_sti(void) static inline void omap_init_sti(void) {} #endif +#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE) + +static struct platform_device omap_pcm = { + .name = "omap-pcm-audio", + .id = -1, +}; + +OMAP_MCBSP_PLATFORM_DEVICE(1); +OMAP_MCBSP_PLATFORM_DEVICE(2); +OMAP_MCBSP_PLATFORM_DEVICE(3); + +static void omap_init_audio(void) +{ + platform_device_register(&omap_mcbsp1); + platform_device_register(&omap_mcbsp2); + if (!cpu_is_omap7xx()) + platform_device_register(&omap_mcbsp3); + platform_device_register(&omap_pcm); +} + +#else +static inline void omap_init_audio(void) {} +#endif + /*-------------------------------------------------------------------------*/ /* @@ -299,6 +324,7 @@ static int __init omap1_init_devices(void) omap_init_rtc(); omap_init_spi100k(); omap_init_sti(); + omap_init_audio(); return 0; } diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 3ccc34ebdcc7..04df912a7b55 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -612,11 +613,25 @@ static int n8x0_menelaus_late_init(struct device *dev) return 0; } +static struct aic3x_setup_data n810_aic33_setup = { + .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, + .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, +}; + +static struct aic3x_pdata n810_aic33_data = { + .setup = &n810_aic33_setup, + .gpio_reset = -1, +}; + static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] = { { I2C_BOARD_INFO("menelaus", 0x72), .irq = INT_24XX_SYS_NIRQ, }, + { + I2C_BOARD_INFO("tlv320aic3x", 0x1b), + .platform_data = &n810_aic33_data, + }, }; static struct menelaus_platform_data n8x0_menelaus_platform_data = { diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index abdf321c2d41..28978c08bced 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -686,7 +687,6 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = { }; - static struct twl4030_platform_data rx51_twldata __initdata = { .irq_base = TWL4030_IRQ_BASE, .irq_end = TWL4030_IRQ_END, @@ -716,9 +716,21 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_1[] = { }, }; +/* Audio setup data */ +static struct aic3x_setup_data rx51_aic34_setup = { + .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, + .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, +}; + +static struct aic3x_pdata rx51_aic34_data = { + .setup = &rx51_aic34_setup, + .gpio_reset = 60, +}; + static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = { { I2C_BOARD_INFO("tlv320aic3x", 0x18), + .platform_data = &rx51_aic34_data, }, }; diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c index 803ef14cbf2d..410fe006c0f6 100644 --- a/arch/arm/mach-omap2/board-zoom2.c +++ b/arch/arm/mach-omap2/board-zoom2.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -34,8 +35,11 @@ static void __init omap_zoom2_init_irq(void) omap_gpio_init(); } -/* REVISIT: These audio entries can be removed once MFD code is merged */ -#if 0 +/* EXTMUTE callback function */ +void zoom2_set_hs_extmute(int mute) +{ + gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute); +} static struct twl4030_madc_platform_data zoom2_madc_data = { .irq_line = 1, @@ -43,6 +47,9 @@ static struct twl4030_madc_platform_data zoom2_madc_data = { static struct twl4030_codec_audio_data zoom2_audio_data = { .audio_mclk = 26000000, + .ramp_delay_value = 3, /* 161 ms */ + .hs_extmute = 1, + .set_hs_extmute = zoom2_set_hs_extmute, }; static struct twl4030_codec_data zoom2_codec_data = { @@ -64,10 +71,24 @@ static struct twl4030_platform_data zoom2_twldata = { .vmmc1 = &zoom2_vmmc1, .vmmc2 = &zoom2_vmmc2, .vsim = &zoom2_vsim, +}; +static struct i2c_board_info __initdata zoom2_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &zoom2_twldata, + }, }; -#endif +static int __init omap3_zoom2_i2c_init(void) +{ + omap_register_i2c_bus(1, 2600, zoom2_i2c_boardinfo, + ARRAY_SIZE(zoom2_i2c_boardinfo)); + return 0; +} + #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { @@ -81,6 +102,7 @@ static void __init omap_zoom2_init(void) { omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); zoom_peripherals_init(); + omap3_zoom2_i2c_init(); zoom_debugboard_init(); } diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 03e6c9ed82a4..f9a5961d23a7 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "mux.h" @@ -289,6 +290,43 @@ static inline void omap_init_sti(void) static inline void omap_init_sti(void) {} #endif +#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE) + +static struct platform_device omap_pcm = { + .name = "omap-pcm-audio", + .id = -1, +}; + +/* + * OMAP2420 has 2 McBSP ports + * OMAP2430 has 5 McBSP ports + * OMAP3 has 5 McBSP ports + * OMAP4 has 4 McBSP ports + */ +OMAP_MCBSP_PLATFORM_DEVICE(1); +OMAP_MCBSP_PLATFORM_DEVICE(2); +OMAP_MCBSP_PLATFORM_DEVICE(3); +OMAP_MCBSP_PLATFORM_DEVICE(4); +OMAP_MCBSP_PLATFORM_DEVICE(5); + +static void omap_init_audio(void) +{ + platform_device_register(&omap_mcbsp1); + platform_device_register(&omap_mcbsp2); + if (cpu_is_omap243x() || cpu_is_omap34xx() || cpu_is_omap44xx()) { + platform_device_register(&omap_mcbsp3); + platform_device_register(&omap_mcbsp4); + } + if (cpu_is_omap243x() || cpu_is_omap34xx()) + platform_device_register(&omap_mcbsp5); + + platform_device_register(&omap_pcm); +} + +#else +static inline void omap_init_audio(void) {} +#endif + #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE) #include @@ -901,6 +939,7 @@ static int __init omap2_init_devices(void) * in alphabetical order so they're easier to sort through. */ omap_hsmmc_reset(); + omap_init_audio(); omap_init_camera(); omap_init_mbox(); omap_init_mcspi(); diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/include/mach/board-zoom.h index c93b29e21b78..b6a010fc8bda 100644 --- a/arch/arm/mach-omap2/include/mach/board-zoom.h +++ b/arch/arm/mach-omap2/include/mach/board-zoom.h @@ -3,3 +3,5 @@ */ extern int __init zoom_debugboard_init(void); extern void __init zoom_peripherals_init(void); + +#define ZOOM2_HEADSET_EXTMUTE_GPIO 153 diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 8e10db148f1b..200c31a2730e 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -340,6 +340,31 @@ struct platform_device pxa_device_i2s = { .num_resources = ARRAY_SIZE(pxai2s_resources), }; +struct platform_device pxa_device_asoc_ssp1 = { + .name = "pxa-ssp-dai", + .id = 0, +}; + +struct platform_device pxa_device_asoc_ssp2= { + .name = "pxa-ssp-dai", + .id = 1, +}; + +struct platform_device pxa_device_asoc_ssp3 = { + .name = "pxa-ssp-dai", + .id = 2, +}; + +struct platform_device pxa_device_asoc_ssp4 = { + .name = "pxa-ssp-dai", + .id = 3, +}; + +struct platform_device pxa_device_asoc_platform = { + .name = "pxa-pcm-audio", + .id = -1, +}; + static u64 pxaficp_dmamask = ~(u32)0; struct platform_device pxa_device_ficp = { diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h index 93817d99761e..506fd5753ccc 100644 --- a/arch/arm/mach-pxa/devices.h +++ b/arch/arm/mach-pxa/devices.h @@ -37,4 +37,10 @@ extern struct platform_device pxa3xx_device_i2c_power; extern struct platform_device pxa3xx_device_gcu; +extern struct platform_device pxa_device_asoc_platform; +extern struct platform_device pxa_device_asoc_ssp1; +extern struct platform_device pxa_device_asoc_ssp2; +extern struct platform_device pxa_device_asoc_ssp3; +extern struct platform_device pxa_device_asoc_ssp4; + void __init pxa_register_device(struct platform_device *dev, void *data); diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 0af36177ff08..465008293a25 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -384,6 +384,10 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info) static struct platform_device *devices[] __initdata = { &pxa27x_device_udc, &pxa_device_i2s, + &pxa_device_asoc_ssp1, + &pxa_device_asoc_ssp2, + &pxa_device_asoc_ssp3, + &pxa_device_asoc_platform, &sa1100_device_rtc, &pxa_device_rtc, &pxa27x_device_ssp1, diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index f544e58e1536..f7a3b158ca97 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -597,6 +597,11 @@ void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info) static struct platform_device *devices[] __initdata = { &pxa27x_device_udc, &pxa_device_i2s, + &pxa_device_asoc_ssp1, + &pxa_device_asoc_ssp2, + &pxa_device_asoc_ssp3, + &pxa_device_asoc_ssp4, + &pxa_device_asoc_platform, &sa1100_device_rtc, &pxa_device_rtc, &pxa27x_device_ssp1, diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index c479cbecf784..5ba9d99a1bf6 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c @@ -45,6 +45,16 @@ int wm9713_irq; int lcd_id; int lcd_orientation; +struct platform_device pxa_device_wm9713_audio = { + .name = "wm9713-codec", + .id = -1, +}; + +static void __init zylonite_init_wm9713_audio(void) +{ + platform_device_register(&pxa_device_wm9713_audio); +} + static struct resource smc91x_resources[] = { [0] = { .start = ZYLONITE_ETH_PHYS + 0x300, @@ -408,6 +418,7 @@ static void __init zylonite_init(void) zylonite_init_nand(); zylonite_init_leds(); zylonite_init_ohci(); + zylonite_init_wm9713_audio(); } MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)") diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c index c3e9e73bd0f9..55ae1b0afae9 100644 --- a/arch/arm/mach-s3c64xx/dev-audio.c +++ b/arch/arm/mach-s3c64xx/dev-audio.c @@ -333,3 +333,16 @@ void __init s3c64xx_ac97_setup_gpio(int num) else s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe; } + +static u64 s3c_device_audio_dmamask = 0xffffffffUL; + +struct platform_device s3c_device_pcm = { + .name = "s3c24xx-pcm-audio", + .id = -1, + .dev = { + .dma_mask = &s3c_device_audio_dmamask, + .coherent_dma_mask = 0xffffffffUL + } +}; +EXPORT_SYMBOL(s3c_device_pcm); + diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index d9a03555f88b..362fc76ee726 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -256,6 +256,7 @@ static struct platform_device *smdk6410_devices[] __initdata = { &s3c_device_fb, &s3c_device_ohci, &s3c_device_usb_hsotg, + &s3c_device_pcm, &s3c64xx_device_iisv4, #ifdef CONFIG_REGULATOR diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c index 0c2cc5cd4d83..7c479e4fa999 100644 --- a/arch/arm/plat-mxc/audmux-v2.c +++ b/arch/arm/plat-mxc/audmux-v2.c @@ -49,9 +49,9 @@ static const char *audmux_port_string(int port) { switch (port) { case MX31_AUDMUX_PORT1_SSI0: - return "imx-ssi.0"; + return "imx-ssi-dai.0"; case MX31_AUDMUX_PORT2_SSI1: - return "imx-ssi.1"; + return "imx-ssi-dai.1"; case MX31_AUDMUX_PORT3_SSI_PINS_3: return "SSI3"; case MX31_AUDMUX_PORT4_SSI_PINS_4: diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index b4ff6a11a8f2..5b20103e68eb 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/mcbsp.h @@ -30,6 +30,13 @@ #include #include +/* macro for building platform_device for McBSP ports */ +#define OMAP_MCBSP_PLATFORM_DEVICE(port_nr) \ +static struct platform_device omap_mcbsp##port_nr = { \ + .name = "omap-mcbsp-dai", \ + .id = OMAP_MCBSP##port_nr, \ +} + #define OMAP7XX_MCBSP1_BASE 0xfffb1000 #define OMAP7XX_MCBSP2_BASE 0xfffb1800 diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index 452e18438b41..9f8ee5e38615 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c @@ -481,7 +481,7 @@ static struct resource s3c_ac97_resource[] = { }, }; -static u64 s3c_device_ac97_dmamask = 0xffffffffUL; +static u64 s3c_device_audio_dmamask = 0xffffffffUL; struct platform_device s3c_device_ac97 = { .name = "s3c-ac97", @@ -489,11 +489,37 @@ struct platform_device s3c_device_ac97 = { .num_resources = ARRAY_SIZE(s3c_ac97_resource), .resource = s3c_ac97_resource, .dev = { - .dma_mask = &s3c_device_ac97_dmamask, + .dma_mask = &s3c_device_audio_dmamask, .coherent_dma_mask = 0xffffffffUL } }; EXPORT_SYMBOL(s3c_device_ac97); +/* ASoC PCM DMA */ + +struct platform_device s3c_device_pcm = { + .name = "s3c24xx-pcm-audio", + .id = -1, + .dev = { + .dma_mask = &s3c_device_audio_dmamask, + .coherent_dma_mask = 0xffffffffUL + } +}; + +EXPORT_SYMBOL(s3c_device_pcm); + +/* ASoC I2S */ + +struct platform_device s3c2412_device_iis = { + .name = "s3c2412-iis", + .id = -1, + .dev = { + .dma_mask = &s3c_device_audio_dmamask, + .coherent_dma_mask = 0xffffffffUL + } +}; + +EXPORT_SYMBOL(s3c2412_device_iis); + #endif // CONFIG_CPU_S32440 diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index e6144e4b9118..9ea6786d459d 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -32,6 +32,8 @@ extern struct platform_device s3c64xx_device_iisv4; extern struct platform_device s3c64xx_device_spi0; extern struct platform_device s3c64xx_device_spi1; +extern struct platform_device s3c_device_pcm; + extern struct platform_device s3c64xx_device_pcm0; extern struct platform_device s3c64xx_device_pcm1; diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 4f9b2afc24e8..014dd4ad0d4f 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -271,7 +271,7 @@ static struct platform_driver twl4030_vibra_driver = { .probe = twl4030_vibra_probe, .remove = __devexit_p(twl4030_vibra_remove), .driver = { - .name = "twl4030_codec_vibra", + .name = "twl4030-vibra", .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &twl4030_vibra_pm_ops, @@ -291,7 +291,7 @@ static void __exit twl4030_vibra_exit(void) } module_exit(twl4030_vibra_exit); -MODULE_ALIAS("platform:twl4030_codec_vibra"); +MODULE_ALIAS("platform:twl4030-vibra"); MODULE_DESCRIPTION("TWL4030 Vibra driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 720e099e506d..5d0fb60a4c14 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -698,17 +698,17 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) if (twl_has_codec() && pdata->codec && twl_class_is_4030()) { sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; - child = add_child(sub_chip_id, "twl4030_codec", + child = add_child(sub_chip_id, "twl4030-audio", pdata->codec, sizeof(*pdata->codec), false, 0, 0); if (IS_ERR(child)) return PTR_ERR(child); } - /* Phoenix*/ + /* Phoenix codec driver is probed directly atm */ if (twl_has_codec() && pdata->codec && twl_class_is_6030()) { sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; - child = add_child(sub_chip_id, "twl6040_codec", + child = add_child(sub_chip_id, "twl6040-codec", pdata->codec, sizeof(*pdata->codec), false, 0, 0); if (IS_ERR(child)) diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c index add6f67d8032..9a4b196d6deb 100644 --- a/drivers/mfd/twl4030-codec.c +++ b/drivers/mfd/twl4030-codec.c @@ -207,14 +207,14 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev) if (pdata->audio) { cell = &codec->cells[childs]; - cell->name = "twl4030_codec_audio"; + cell->name = "twl4030-codec"; cell->platform_data = pdata->audio; cell->data_size = sizeof(*pdata->audio); childs++; } if (pdata->vibra) { cell = &codec->cells[childs]; - cell->name = "twl4030_codec_vibra"; + cell->name = "twl4030-vibra"; cell->platform_data = pdata->vibra; cell->data_size = sizeof(*pdata->vibra); childs++; @@ -249,14 +249,14 @@ static int __devexit twl4030_codec_remove(struct platform_device *pdev) return 0; } -MODULE_ALIAS("platform:twl4030_codec"); +MODULE_ALIAS("platform:twl4030-audio"); static struct platform_driver twl4030_codec_driver = { .probe = twl4030_codec_probe, .remove = __devexit_p(twl4030_codec_remove), .driver = { .owner = THIS_MODULE, - .name = "twl4030_codec", + .name = "twl4030-audio", }, }; diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 6de90bfc6acd..4793d8a7f480 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -553,8 +553,12 @@ extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts); extern int twl4030_remove_script(u8 flags); struct twl4030_codec_audio_data { - unsigned int audio_mclk; + unsigned int audio_mclk; /* not used, will be removed */ + unsigned int digimic_delay; /* in ms */ unsigned int ramp_delay_value; + unsigned int offset_cncl_path; + unsigned int check_defaults:1; + unsigned int reset_registers:1; unsigned int hs_extmute:1; void (*set_hs_extmute)(int mute); }; diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index 9d51d6f35893..3fd6456d07d7 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h @@ -114,7 +114,7 @@ struct sh_fsi_platform_info { int (*set_rate)(int is_porta, int rate); /* for master mode */ }; -extern struct snd_soc_dai fsi_soc_dai[2]; -extern struct snd_soc_platform fsi_soc_platform; +extern struct snd_soc_dai_driver fsi_soc_dai[2]; +extern struct snd_soc_platform_driver fsi_soc_platform; #endif /* __SOUND_FSI_H */ diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 377693a14385..e7b680248006 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -91,15 +91,17 @@ struct snd_pcm_substream; SNDRV_PCM_FMTBIT_S32_LE |\ SNDRV_PCM_FMTBIT_S32_BE) -struct snd_soc_dai_ops; +struct snd_soc_dai_driver; struct snd_soc_dai; struct snd_ac97_bus_ops; /* Digital Audio Interface registration */ -int snd_soc_register_dai(struct snd_soc_dai *dai); -void snd_soc_unregister_dai(struct snd_soc_dai *dai); -int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count); -void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count); +int snd_soc_register_dai(struct device *dev, + struct snd_soc_dai_driver *dai_drv); +void snd_soc_unregister_dai(struct device *dev); +int snd_soc_register_dais(struct device *dev, + struct snd_soc_dai_driver *dai_drv, size_t count); +void snd_soc_unregister_dais(struct device *dev, size_t count); /* Digital Audio Interface clocking API.*/ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, @@ -126,16 +128,6 @@ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate); /* Digital Audio Interface mute */ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute); -/* - * Digital Audio Interface. - * - * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97 - * operations and capabilities. Codec and platform drivers will register this - * structure for every DAI they have. - * - * This structure covers the clocking, formating and ALSA operations for each - * interface. - */ struct snd_soc_dai_ops { /* * DAI clocking configuration, all optional. @@ -191,24 +183,24 @@ struct snd_soc_dai_ops { }; /* - * Digital Audio Interface runtime data. + * Digital Audio Interface Driver. * - * Holds runtime data for a DAI. + * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97 + * operations and capabilities. Codec and platform drivers will register this + * structure for every DAI they have. + * + * This structure covers the clocking, formating and ALSA operations for each + * interface. */ -struct snd_soc_dai { +struct snd_soc_dai_driver { /* DAI description */ - char *name; + const char *name; unsigned int id; int ac97_control; - struct device *dev; - void *ac97_pdata; /* platform_data for the ac97 codec */ - - /* DAI callbacks */ - int (*probe)(struct platform_device *pdev, - struct snd_soc_dai *dai); - void (*remove)(struct platform_device *pdev, - struct snd_soc_dai *dai); + /* DAI driver callbacks */ + int (*probe)(struct snd_soc_dai *dai); + int (*remove)(struct snd_soc_dai *dai); int (*suspend)(struct snd_soc_dai *dai); int (*resume)(struct snd_soc_dai *dai); @@ -219,26 +211,51 @@ struct snd_soc_dai { struct snd_soc_pcm_stream capture; struct snd_soc_pcm_stream playback; unsigned int symmetric_rates:1; +}; + +/* + * Digital Audio Interface runtime data. + * + * Holds runtime data for a DAI. + */ +struct snd_soc_dai { + const char *name; + int id; + struct device *dev; + void *ac97_pdata; /* platform_data for the ac97 codec */ + + /* driver ops */ + struct snd_soc_dai_driver *driver; /* DAI runtime info */ - struct snd_soc_codec *codec; + unsigned int capture_active:1; /* stream is in use */ + unsigned int playback_active:1; /* stream is in use */ + unsigned int symmetric_rates:1; + struct snd_pcm_runtime *runtime; unsigned int active; unsigned char pop_wait:1; + unsigned char probed:1; - /* DAI private data */ - void *private_data; + /* DAI DMA data */ + void *playback_dma_data; + void *capture_dma_data; - /* parent platform */ - struct snd_soc_platform *platform; + /* parent platform/codec */ + union { + struct snd_soc_platform *platform; + struct snd_soc_codec *codec; + }; + struct snd_soc_card *card; struct list_head list; + struct list_head card_list; }; static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, const struct snd_pcm_substream *ss) { return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - dai->playback.dma_data : dai->capture.dma_data; + dai->playback_dma_data : dai->capture_dma_data; } static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai, @@ -246,9 +263,20 @@ static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai, void *data) { if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) - dai->playback.dma_data = data; + dai->playback_dma_data = data; else - dai->capture.dma_data = data; + dai->capture_dma_data = data; +} + +static inline void snd_soc_dai_set_drvdata(struct snd_soc_dai *dai, + void *data) +{ + dev_set_drvdata(dai->dev, data); +} + +static inline void *snd_soc_dai_get_drvdata(struct snd_soc_dai *dai) +{ + return dev_get_drvdata(dai->dev); } #endif diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c5d9987bc897..c4a445651ca0 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -322,14 +322,14 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec, /* dapm path setup */ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec); -void snd_soc_dapm_free(struct snd_soc_device *socdev); +void snd_soc_dapm_free(struct snd_soc_codec *codec); int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, const struct snd_soc_dapm_route *route, int num); /* dapm events */ -int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream, - int event); -void snd_soc_dapm_shutdown(struct snd_soc_device *socdev); +int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, + const char *stream, int event); +void snd_soc_dapm_shutdown(struct snd_soc_card *card); /* dapm sys fs - used by the core */ int snd_soc_dapm_sys_add(struct device *dev); diff --git a/include/sound/soc-of-simple.h b/include/sound/soc-of-simple.h deleted file mode 100644 index a064e1934a56..000000000000 --- a/include/sound/soc-of-simple.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * OF helpers for ALSA SoC - * - * Copyright (C) 2008, Secret Lab Technologies Ltd. - */ - -#ifndef _INCLUDE_SOC_OF_H_ -#define _INCLUDE_SOC_OF_H_ - -#if defined(CONFIG_SND_SOC_OF_SIMPLE) || defined(CONFIG_SND_SOC_OF_SIMPLE_MODULE) - -#include -#include - -int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev, - void *codec_data, struct snd_soc_dai *dai, - struct device_node *node); - -int of_snd_soc_register_platform(struct snd_soc_platform *platform, - struct device_node *node, - struct snd_soc_dai *cpu_dai); - -#endif - -#endif /* _INCLUDE_SOC_OF_H_ */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 65e9d03ed4f5..d31e8b7b2d5e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -228,13 +228,17 @@ struct snd_soc_ops; struct snd_soc_dai_mode; struct snd_soc_pcm_runtime; struct snd_soc_dai; +struct snd_soc_dai_driver; struct snd_soc_platform; struct snd_soc_dai_link; +struct snd_soc_platform_driver; struct snd_soc_codec; +struct snd_soc_codec_driver; struct soc_enum; struct snd_soc_ac97_ops; struct snd_soc_jack; struct snd_soc_jack_pin; + #ifdef CONFIG_GPIOLIB struct snd_soc_jack_gpio; #endif @@ -249,19 +253,18 @@ enum snd_soc_control_type { SND_SOC_SPI, }; -int snd_soc_register_platform(struct snd_soc_platform *platform); -void snd_soc_unregister_platform(struct snd_soc_platform *platform); -int snd_soc_register_codec(struct snd_soc_codec *codec); -void snd_soc_unregister_codec(struct snd_soc_codec *codec); +int snd_soc_register_platform(struct device *dev, + struct snd_soc_platform_driver *platform_drv); +void snd_soc_unregister_platform(struct device *dev); +int snd_soc_register_codec(struct device *dev, + struct snd_soc_codec_driver *codec_drv, + struct snd_soc_dai_driver *dai_drv, int num_dai); +void snd_soc_unregister_codec(struct device *dev); int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg); int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, int addr_bits, int data_bits, enum snd_soc_control_type control); -/* pcm <-> DAI connect */ -void snd_soc_free_pcms(struct snd_soc_device *socdev); -int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid); - /* Utility functions to get clock rates from various things */ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); @@ -273,7 +276,7 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, const struct snd_pcm_hardware *hw); /* Jack reporting */ -int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, +int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type, struct snd_soc_jack *jack); void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, @@ -390,7 +393,7 @@ struct snd_soc_jack_gpio { struct snd_soc_jack { struct snd_jack *jack; - struct snd_soc_card *card; + struct snd_soc_codec *codec; struct list_head pins; int status; struct blocking_notifier_head notifier; @@ -398,15 +401,13 @@ struct snd_soc_jack { /* SoC PCM stream information */ struct snd_soc_pcm_stream { - char *stream_name; + const char *stream_name; u64 formats; /* SNDRV_PCM_FMTBIT_* */ unsigned int rates; /* SNDRV_PCM_RATE_* */ unsigned int rate_min; /* min rate */ unsigned int rate_max; /* max rate */ unsigned int channels_min; /* min channels */ unsigned int channels_max; /* max channels */ - unsigned int active; /* stream is in use */ - void *dma_data; /* used by platform code */ }; /* SoC audio ops */ @@ -419,44 +420,35 @@ struct snd_soc_ops { int (*trigger)(struct snd_pcm_substream *, int); }; -/* SoC Audio Codec */ +/* SoC Audio Codec device */ struct snd_soc_codec { - char *name; - struct module *owner; - struct mutex mutex; + const char *name; + int id; struct device *dev; - struct snd_soc_device *socdev; + struct snd_soc_codec_driver *driver; + struct mutex mutex; + struct snd_soc_card *card; struct list_head list; - - /* callbacks */ - int (*set_bias_level)(struct snd_soc_codec *, - enum snd_soc_bias_level level); + struct list_head card_list; + int num_dai; /* runtime */ - struct snd_card *card; struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ unsigned int active; - unsigned int pcm_devs; - void *drvdata; + unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ + unsigned int cache_only:1; /* Suppress writes to hardware */ + unsigned int cache_sync:1; /* Cache needs to be synced to hardware */ + unsigned int suspended:1; /* Codec is in suspend PM state */ + unsigned int probed:1; /* Codec has been probed */ + unsigned int ac97_registered:1; /* Codec has been AC97 registered */ + unsigned int sysfs_registered:1; /* codec has been sysfs registered */ /* codec IO */ void *control_data; /* codec control (i2c/3wire) data */ - unsigned int (*read)(struct snd_soc_codec *, unsigned int); - int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); - int (*display_register)(struct snd_soc_codec *, char *, - size_t, unsigned int); - int (*volatile_register)(unsigned int); - int (*readable_register)(unsigned int); hw_write_t hw_write; unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int); void *reg_cache; - short reg_cache_size; - short reg_cache_step; - - unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ - unsigned int cache_only:1; /* Suppress writes to hardware */ - unsigned int cache_sync:1; /* Cache needs to be synced to hardware */ /* dapm */ u32 pop_time; @@ -466,10 +458,6 @@ struct snd_soc_codec { enum snd_soc_bias_level suspend_bias_level; struct delayed_work delayed_work; - /* codec DAI's */ - struct snd_soc_dai *dai; - unsigned int num_dai; - #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_codec_root; struct dentry *debugfs_reg; @@ -478,23 +466,40 @@ struct snd_soc_codec { #endif }; -/* codec device */ -struct snd_soc_codec_device { - int (*probe)(struct platform_device *pdev); - int (*remove)(struct platform_device *pdev); - int (*suspend)(struct platform_device *pdev, pm_message_t state); - int (*resume)(struct platform_device *pdev); +/* codec driver */ +struct snd_soc_codec_driver { + + /* driver ops */ + int (*probe)(struct snd_soc_codec *); + int (*remove)(struct snd_soc_codec *); + int (*suspend)(struct snd_soc_codec *, + pm_message_t state); + int (*resume)(struct snd_soc_codec *); + + /* codec IO */ + unsigned int (*read)(struct snd_soc_codec *, unsigned int); + int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); + int (*display_register)(struct snd_soc_codec *, char *, + size_t, unsigned int); + int (*volatile_register)(unsigned int); + int (*readable_register)(unsigned int); + short reg_cache_size; + short reg_cache_step; + short reg_word_size; + const void *reg_cache_default; + + /* codec bias level */ + int (*set_bias_level)(struct snd_soc_codec *, + enum snd_soc_bias_level level); }; /* SoC platform interface */ -struct snd_soc_platform { - char *name; - struct list_head list; +struct snd_soc_platform_driver { - int (*probe)(struct platform_device *pdev); - int (*remove)(struct platform_device *pdev); - int (*suspend)(struct snd_soc_dai_link *dai_link); - int (*resume)(struct snd_soc_dai_link *dai_link); + int (*probe)(struct snd_soc_platform *); + int (*remove)(struct snd_soc_platform *); + int (*suspend)(struct snd_soc_dai *dai); + int (*resume)(struct snd_soc_dai *dai); /* pcm creation and destruction */ int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, @@ -509,23 +514,31 @@ struct snd_soc_platform { struct snd_soc_dai *); /* platform stream ops */ - struct snd_pcm_ops *pcm_ops; + struct snd_pcm_ops *ops; }; -/* SoC machine DAI configuration, glues a codec and cpu DAI together */ -struct snd_soc_dai_link { - char *name; /* Codec name */ - char *stream_name; /* Stream name */ +struct snd_soc_platform { + const char *name; + int id; + struct device *dev; + struct snd_soc_platform_driver *driver; - /* DAI */ - struct snd_soc_dai *codec_dai; - struct snd_soc_dai *cpu_dai; + unsigned int suspended:1; /* platform is suspended */ + unsigned int probed:1; - /* machine stream operations */ - struct snd_soc_ops *ops; + struct snd_soc_card *card; + struct list_head list; + struct list_head card_list; +}; - /* codec/machine specific init - e.g. add machine controls */ - int (*init)(struct snd_soc_codec *codec); +struct snd_soc_dai_link { + /* config - must be set by machine driver */ + const char *name; /* Codec name */ + const char *stream_name; /* Stream name */ + const char *codec_name; /* for multi-codec */ + const char *platform_name; /* for multi-platform */ + const char *cpu_dai_name; + const char *codec_dai_name; /* Keep DAI active over suspend */ unsigned int ignore_suspend:1; @@ -533,21 +546,24 @@ struct snd_soc_dai_link { /* Symmetry requirements */ unsigned int symmetric_rates:1; - /* Symmetry data - only valid if symmetry is being enforced */ - unsigned int rate; + /* codec/machine specific init - e.g. add machine controls */ + int (*init)(struct snd_soc_pcm_runtime *rtd); - /* DAI pcm */ - struct snd_pcm *pcm; + /* machine stream operations */ + struct snd_soc_ops *ops; }; /* SoC card */ struct snd_soc_card { - char *name; + const char *name; struct device *dev; + struct snd_card *snd_card; + struct module *owner; struct list_head list; + struct mutex mutex; - int instantiated; + bool instantiated; int (*probe)(struct platform_device *pdev); int (*remove)(struct platform_device *pdev); @@ -568,28 +584,38 @@ struct snd_soc_card { /* CPU <--> Codec DAI links */ struct snd_soc_dai_link *dai_link; int num_links; + struct snd_soc_pcm_runtime *rtd; + int num_rtd; - struct snd_soc_device *socdev; - - struct snd_soc_codec *codec; - - struct snd_soc_platform *platform; - struct delayed_work delayed_work; struct work_struct deferred_resume_work; + + /* lists of probed devices belonging to this card */ + struct list_head codec_dev_list; + struct list_head platform_dev_list; + struct list_head dai_dev_list; }; -/* SoC Device - the audio subsystem */ -struct snd_soc_device { - struct device *dev; +/* SoC machine DAI configuration, glues a codec and cpu DAI together */ +struct snd_soc_pcm_runtime { + struct device dev; struct snd_soc_card *card; - struct snd_soc_codec_device *codec_dev; - void *codec_data; -}; + struct snd_soc_dai_link *dai_link; + + unsigned int complete:1; + unsigned int dev_registered:1; -/* runtime channel data */ -struct snd_soc_pcm_runtime { - struct snd_soc_dai_link *dai; - struct snd_soc_device *socdev; + /* Symmetry data - only valid if symmetry is being enforced */ + unsigned int rate; + long pmdown_time; + + /* runtime devices */ + struct snd_pcm *pcm; + struct snd_soc_codec *codec; + struct snd_soc_platform *platform; + struct snd_soc_dai *codec_dai; + struct snd_soc_dai *cpu_dai; + + struct delayed_work delayed_work; }; /* mixer control */ @@ -615,24 +641,48 @@ struct soc_enum { static inline unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg) { - return codec->read(codec, reg); + return codec->driver->read(codec, reg); } static inline unsigned int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val) { - return codec->write(codec, reg, val); + return codec->driver->write(codec, reg, val); } +/* device driver data */ + static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec, - void *data) + void *data) { - codec->drvdata = data; + dev_set_drvdata(codec->dev, data); } static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec) { - return codec->drvdata; + return dev_get_drvdata(codec->dev); +} + +static inline void snd_soc_platform_set_drvdata(struct snd_soc_platform *platform, + void *data) +{ + dev_set_drvdata(platform->dev, data); +} + +static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platform) +{ + return dev_get_drvdata(platform->dev); +} + +static inline void snd_soc_pcm_set_drvdata(struct snd_soc_pcm_runtime *rtd, + void *data) +{ + dev_set_drvdata(&rtd->dev, data); +} + +static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd) +{ + return dev_get_drvdata(&rtd->dev); } #include diff --git a/include/sound/tlv320aic3x.h b/include/sound/tlv320aic3x.h index b1a5f34e5cfa..99e0308bf2c2 100644 --- a/include/sound/tlv320aic3x.h +++ b/include/sound/tlv320aic3x.h @@ -10,8 +10,49 @@ #ifndef __TLV320AIC3x_H__ #define __TLV320AIC3x_H__ +/* GPIO API */ +enum { + AIC3X_GPIO1_FUNC_DISABLED = 0, + AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC = 1, + AIC3X_GPIO1_FUNC_CLOCK_MUX = 2, + AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2 = 3, + AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4 = 4, + AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8 = 5, + AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ = 6, + AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ = 7, + AIC3X_GPIO1_FUNC_INPUT = 8, + AIC3X_GPIO1_FUNC_OUTPUT = 9, + AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK = 10, + AIC3X_GPIO1_FUNC_AUDIO_WORDCLK = 11, + AIC3X_GPIO1_FUNC_BUTTON_IRQ = 12, + AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ = 13, + AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 14, + AIC3X_GPIO1_FUNC_ALL_IRQ = 16 +}; + +enum { + AIC3X_GPIO2_FUNC_DISABLED = 0, + AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ = 2, + AIC3X_GPIO2_FUNC_INPUT = 3, + AIC3X_GPIO2_FUNC_OUTPUT = 4, + AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT = 5, + AIC3X_GPIO2_FUNC_AUDIO_BITCLK = 8, + AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9, + AIC3X_GPIO2_FUNC_ALL_IRQ = 10, + AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11, + AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12, + AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ = 13, + AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ = 14, + AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15 +}; + +struct aic3x_setup_data { + unsigned int gpio_func[2]; +}; + struct aic3x_pdata { int gpio_reset; /* < 0 if not used */ + struct aic3x_setup_data *setup; }; -#endif \ No newline at end of file +#endif diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c index dc5249fba85c..d0e75323ec19 100644 --- a/sound/soc/atmel/atmel-pcm.c +++ b/sound/soc/atmel/atmel-pcm.c @@ -179,7 +179,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream, snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = params_buffer_bytes(params); - prtd->params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); prtd->params->dma_intr_handler = atmel_pcm_dma_irq; prtd->dma_buffer = runtime->dma_addr; @@ -374,14 +374,14 @@ static int atmel_pcm_new(struct snd_card *card, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = 0xffffffff; - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = atmel_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto out; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { pr_debug("at32-pcm:" "Allocating PCM capture DMA buffer\n"); ret = atmel_pcm_preallocate_dma_buffer(pcm, @@ -414,12 +414,9 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm) } #ifdef CONFIG_PM -static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link) +static int atmel_pcm_suspend(struct snd_soc_dai *dai) { - struct snd_pcm *pcm = dai_link->pcm; - struct snd_pcm_str *stream = &pcm->streams[0]; - struct snd_pcm_substream *substream = stream->substream; - struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = dai->runtime; struct atmel_runtime_data *prtd; struct atmel_pcm_dma_params *params; @@ -441,12 +438,9 @@ static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link) return 0; } -static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link) +static int atmel_pcm_resume(struct snd_soc_dai *dai) { - struct snd_pcm *pcm = dai_link->pcm; - struct snd_pcm_str *stream = &pcm->streams[0]; - struct snd_pcm_substream *substream = stream->substream; - struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = dai->runtime; struct atmel_runtime_data *prtd; struct atmel_pcm_dma_params *params; @@ -470,27 +464,46 @@ static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link) #define atmel_pcm_resume NULL #endif -struct snd_soc_platform atmel_soc_platform = { - .name = "atmel-audio", - .pcm_ops = &atmel_pcm_ops, +static struct snd_soc_platform_driver atmel_soc_platform = { + .ops = &atmel_pcm_ops, .pcm_new = atmel_pcm_new, .pcm_free = atmel_pcm_free_dma_buffers, .suspend = atmel_pcm_suspend, .resume = atmel_pcm_resume, }; -EXPORT_SYMBOL_GPL(atmel_soc_platform); -static int __init atmel_pcm_modinit(void) +static int __devinit atmel_soc_platform_probe(struct platform_device *pdev) +{ + return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform); +} + +static int __devexit atmel_soc_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver atmel_pcm_driver = { + .driver = { + .name = "atmel-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = atmel_soc_platform_probe, + .remove = __devexit_p(atmel_soc_platform_remove), +}; + +static int __init snd_atmel_pcm_init(void) { - return snd_soc_register_platform(&atmel_soc_platform); + return platform_driver_register(&atmel_pcm_driver); } -module_init(atmel_pcm_modinit); +module_init(snd_atmel_pcm_init); -static void __exit atmel_pcm_modexit(void) +static void __exit snd_atmel_pcm_exit(void) { - snd_soc_unregister_platform(&atmel_soc_platform); + platform_driver_unregister(&atmel_pcm_driver); } -module_exit(atmel_pcm_modexit); +module_exit(snd_atmel_pcm_exit); MODULE_AUTHOR("Sedji Gaouaou "); MODULE_DESCRIPTION("Atmel PCM module"); diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h index ec9b2824b663..2597329302e7 100644 --- a/sound/soc/atmel/atmel-pcm.h +++ b/sound/soc/atmel/atmel-pcm.h @@ -74,9 +74,6 @@ struct atmel_pcm_dma_params { void (*dma_intr_handler)(u32, struct snd_pcm_substream *); }; -extern struct snd_soc_platform atmel_soc_platform; - - /* * SSC register access (since ssc_writel() / ssc_readl() require literal name) */ diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index c85844d4845b..eabf66af12cd 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -205,8 +205,7 @@ static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id) static int atmel_ssc_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); - struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; + struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; int dir_mask; pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", @@ -235,8 +234,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream, static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); - struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; + struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; struct atmel_pcm_dma_params *dma_params; int dir, dir_mask; @@ -338,7 +336,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); - int id = rtd->dai->cpu_dai->id; + int id = dai->id; struct atmel_ssc_info *ssc_p = &ssc_info[id]; struct atmel_pcm_dma_params *dma_params; int dir, channels, bits; @@ -368,7 +366,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, * function. It should not be used for other purposes * as it is common to all substreams. */ - snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_params); + snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_params); channels = params_channels(params); @@ -605,8 +603,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, static int atmel_ssc_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); - struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; + struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; struct atmel_pcm_dma_params *dma_params; int dir; @@ -690,6 +687,32 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai) # define atmel_ssc_resume NULL #endif /* CONFIG_PM */ +static int atmel_ssc_probe(struct snd_soc_dai *dai) +{ + struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; + int ret = 0; + + snd_soc_dai_set_drvdata(dai, ssc_p); + + /* + * Request SSC device + */ + ssc_p->ssc = ssc_request(dai->id); + if (IS_ERR(ssc_p->ssc)) { + printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id); + ret = PTR_ERR(ssc_p->ssc); + } + + return ret; +} + +static int atmel_ssc_remove(struct snd_soc_dai *dai) +{ + struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai); + + ssc_free(ssc_p->ssc); + return 0; +} #define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000) @@ -705,9 +728,11 @@ static struct snd_soc_dai_ops atmel_ssc_dai_ops = { .set_clkdiv = atmel_ssc_set_dai_clkdiv, }; -struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { - { .name = "atmel-ssc0", - .id = 0, +static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = { + { + .name = "atmel-ssc-dai.0", + .probe = atmel_ssc_probe, + .remove = atmel_ssc_remove, .suspend = atmel_ssc_suspend, .resume = atmel_ssc_resume, .playback = { @@ -721,11 +746,12 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { .rates = ATMEL_SSC_RATES, .formats = ATMEL_SSC_FORMATS,}, .ops = &atmel_ssc_dai_ops, - .private_data = &ssc_info[0], }, #if NUM_SSC_DEVICES == 3 - { .name = "atmel-ssc1", - .id = 1, + { + .name = "atmel-ssc-dai.1", + .probe = atmel_ssc_probe, + .remove = atmel_ssc_remove, .suspend = atmel_ssc_suspend, .resume = atmel_ssc_resume, .playback = { @@ -739,10 +765,11 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { .rates = ATMEL_SSC_RATES, .formats = ATMEL_SSC_FORMATS,}, .ops = &atmel_ssc_dai_ops, - .private_data = &ssc_info[1], }, - { .name = "atmel-ssc2", - .id = 2, + { + .name = "atmel-ssc-dai.2", + .probe = atmel_ssc_probe, + .remove = atmel_ssc_remove, .suspend = atmel_ssc_suspend, .resume = atmel_ssc_resume, .playback = { @@ -756,23 +783,43 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { .rates = ATMEL_SSC_RATES, .formats = ATMEL_SSC_FORMATS,}, .ops = &atmel_ssc_dai_ops, - .private_data = &ssc_info[2], }, #endif }; -EXPORT_SYMBOL_GPL(atmel_ssc_dai); -static int __init atmel_ssc_modinit(void) +static __devinit int asoc_ssc_probe(struct platform_device *pdev) +{ + return snd_soc_register_dais(&pdev->dev, atmel_ssc_dai, + ARRAY_SIZE(atmel_ssc_dai)); +} + +static int __devexit asoc_ssc_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(atmel_ssc_dai)); + return 0; +} + +static struct platform_driver asoc_ssc_driver = { + .driver = { + .name = "atmel-ssc-dai", + .owner = THIS_MODULE, + }, + + .probe = asoc_ssc_probe, + .remove = __devexit_p(asoc_ssc_remove), +}; + +static int __init snd_atmel_ssc_init(void) { - return snd_soc_register_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); + return platform_driver_register(&asoc_ssc_driver); } -module_init(atmel_ssc_modinit); +module_init(snd_atmel_ssc_init); -static void __exit atmel_ssc_modexit(void) +static void __exit snd_atmel_ssc_exit(void) { - snd_soc_unregister_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); + platform_driver_unregister(&asoc_ssc_driver); } -module_exit(atmel_ssc_modexit); +module_exit(snd_atmel_ssc_exit); /* Module information */ MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com"); diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h index 391135f9c6c1..392a46953112 100644 --- a/sound/soc/atmel/atmel_ssc_dai.h +++ b/sound/soc/atmel/atmel_ssc_dai.h @@ -116,6 +116,5 @@ struct atmel_ssc_info { struct atmel_pcm_dma_params *dma_params[2]; struct atmel_ssc_state ssc_state; }; -extern struct snd_soc_dai atmel_ssc_dai[]; #endif /* _AT91_SSC_DAI_H */ diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c index 9df4c68ef000..5f4e59f4461c 100644 --- a/sound/soc/atmel/playpaq_wm8510.c +++ b/sound/soc/atmel/playpaq_wm8510.c @@ -83,7 +83,7 @@ static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock( struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { - struct at32_ssc_info *ssc_p = cpu_dai->private_data; + struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); struct ssc_device *ssc = ssc_p->ssc; struct ssc_clock_data cd; unsigned int rate, width_bits, channels; @@ -131,9 +131,9 @@ static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct at32_ssc_info *ssc_p = cpu_dai->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); struct ssc_device *ssc = ssc_p->ssc; unsigned int pll_out = 0, bclk = 0, mclk_div = 0; int ret; @@ -315,8 +315,9 @@ static const struct snd_soc_dapm_route intercon[] = { -static int playpaq_wm8510_init(struct snd_soc_codec *codec) +static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int i; /* @@ -342,7 +343,7 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec) /* Make CSB show PLL rate */ - snd_soc_dai_set_clkdiv(codec->dai, WM8510_OPCLKDIV, + snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV, WM8510_OPCLKDIV_1 | 4); return 0; @@ -353,8 +354,10 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link playpaq_wm8510_dai = { .name = "WM8510", .stream_name = "WM8510 PCM", - .cpu_dai = &at32_ssc_dai[0], - .codec_dai = &wm8510_dai, + .cpu_dai_name= "atmel-ssc-dai.0", + .platform_name = "atmel-pcm-audio", + .codec_name = "wm8510-codec.0-0x1a", + .codec_dai_name = "wm8510-hifi", .init = playpaq_wm8510_init, .ops = &playpaq_wm8510_ops, }; @@ -363,46 +366,16 @@ static struct snd_soc_dai_link playpaq_wm8510_dai = { static struct snd_soc_card snd_soc_playpaq = { .name = "LRS_PlayPaq_WM8510", - .platform = &at32_soc_platform, .dai_link = &playpaq_wm8510_dai, .num_links = 1, }; - - -static struct wm8510_setup_data playpaq_wm8510_setup = { - .i2c_bus = 0, - .i2c_address = 0x1a, -}; - - - -static struct snd_soc_device playpaq_wm8510_snd_devdata = { - .card = &snd_soc_playpaq, - .codec_dev = &soc_codec_dev_wm8510, - .codec_data = &playpaq_wm8510_setup, -}; - static struct platform_device *playpaq_snd_device; static int __init playpaq_asoc_init(void) { int ret = 0; - struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data; - struct ssc_device *ssc = NULL; - - - /* - * Request SSC device - */ - ssc = ssc_request(0); - if (IS_ERR(ssc)) { - ret = PTR_ERR(ssc); - goto err_ssc; - } - ssc_p->ssc = ssc; - /* * Configure MCLK for WM8510 @@ -439,8 +412,7 @@ static int __init playpaq_asoc_init(void) goto err_device_alloc; } - platform_set_drvdata(playpaq_snd_device, &playpaq_wm8510_snd_devdata); - playpaq_wm8510_snd_devdata.dev = &playpaq_snd_device->dev; + platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq); ret = platform_device_add(playpaq_snd_device); if (ret) { @@ -468,25 +440,12 @@ err_pll0: clk_put(_gclk0); _gclk0 = NULL; } -err_gclk0: - ssc_free(ssc); -err_ssc: return ret; } static void __exit playpaq_asoc_exit(void) { - struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data; - struct ssc_device *ssc; - - if (ssc_p != NULL) { - ssc = ssc_p->ssc; - if (ssc != NULL) - ssc_free(ssc); - ssc_p->ssc = NULL; - } - if (_gclk0 != NULL) { clk_put(_gclk0); _gclk0 = NULL; diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index e028744c32ce..66a6f1879689 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -69,8 +69,8 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* set codec DAI configuration */ @@ -136,9 +136,10 @@ static const struct snd_soc_dapm_route intercon[] = { /* * Logic for a wm8731 as connected on a at91sam9g20ek board. */ -static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) +static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_dai *codec_dai = &codec->dai[0]; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret; printk(KERN_DEBUG @@ -179,31 +180,25 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link at91sam9g20ek_dai = { .name = "WM8731", .stream_name = "WM8731 PCM", - .cpu_dai = &atmel_ssc_dai[0], - .codec_dai = &wm8731_dai, + .cpu_dai_name = "atmel-ssc-dai.0", + .codec_dai_name = "wm8731-hifi", .init = at91sam9g20ek_wm8731_init, + .platform_name = "atmel_pcm-audio", + .codec_name = "wm8731-codec.0-001a", .ops = &at91sam9g20ek_ops, }; static struct snd_soc_card snd_soc_at91sam9g20ek = { .name = "AT91SAMG20-EK", - .platform = &atmel_soc_platform, .dai_link = &at91sam9g20ek_dai, .num_links = 1, .set_bias_level = at91sam9g20ek_set_bias_level, }; -static struct snd_soc_device at91sam9g20ek_snd_devdata = { - .card = &snd_soc_at91sam9g20ek, - .codec_dev = &soc_codec_dev_wm8731, -}; - static struct platform_device *at91sam9g20ek_snd_device; static int __init at91sam9g20ek_init(void) { - struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data; - struct ssc_device *ssc = NULL; struct clk *pllb; int ret; @@ -235,18 +230,6 @@ static int __init at91sam9g20ek_init(void) clk_set_rate(mclk, MCLK_RATE); - /* - * Request SSC device - */ - ssc = ssc_request(0); - if (IS_ERR(ssc)) { - printk(KERN_ERR "ASoC: Failed to request SSC 0\n"); - ret = PTR_ERR(ssc); - ssc = NULL; - goto err_ssc; - } - ssc_p->ssc = ssc; - at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); if (!at91sam9g20ek_snd_device) { printk(KERN_ERR "ASoC: Platform device allocation failed\n"); @@ -254,8 +237,7 @@ static int __init at91sam9g20ek_init(void) } platform_set_drvdata(at91sam9g20ek_snd_device, - &at91sam9g20ek_snd_devdata); - at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev; + &snd_soc_at91sam9g20ek); ret = platform_device_add(at91sam9g20ek_snd_device); if (ret) { @@ -265,9 +247,6 @@ static int __init at91sam9g20ek_init(void) return ret; -err_ssc: - ssc_free(ssc); - ssc_p->ssc = NULL; err_mclk: clk_put(mclk); mclk = NULL; @@ -277,16 +256,6 @@ err: static void __exit at91sam9g20ek_exit(void) { - struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data; - struct ssc_device *ssc; - - if (ssc_p != NULL) { - ssc = ssc_p->ssc; - if (ssc != NULL) - ssc_free(ssc); - ssc_p->ssc = NULL; - } - platform_device_unregister(at91sam9g20ek_snd_device); at91sam9g20ek_snd_device = NULL; clk_put(mclk); diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c index 23349de27313..e3d283561c19 100644 --- a/sound/soc/atmel/snd-soc-afeb9260.c +++ b/sound/soc/atmel/snd-soc-afeb9260.c @@ -46,8 +46,8 @@ static int afeb9260_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int err; /* Set codec DAI configuration */ @@ -102,8 +102,9 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MICIN", NULL, "Mic Jack"}, }; -static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec) +static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; /* Add afeb9260 specific widgets */ snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, @@ -125,8 +126,10 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link afeb9260_dai = { .name = "TLV320AIC23", .stream_name = "AIC23", - .cpu_dai = &atmel_ssc_dai[0], - .codec_dai = &tlv320aic23_dai, + .cpu_dai_name = "atmel-ssc-dai.0", + .codec_dai_name = "tlv320aic23-hifi", + .platform_name = "atmel_pcm-audio", + .codec_name = "tlv320aic23-codec.0-0x1a", .init = afeb9260_tlv320aic23_init, .ops = &afeb9260_ops, }; @@ -134,37 +137,20 @@ static struct snd_soc_dai_link afeb9260_dai = { /* Audio machine driver */ static struct snd_soc_card snd_soc_machine_afeb9260 = { .name = "AFEB9260", - .platform = &atmel_soc_platform, .dai_link = &afeb9260_dai, .num_links = 1, }; -/* Audio subsystem */ -static struct snd_soc_device afeb9260_snd_devdata = { - .card = &snd_soc_machine_afeb9260, - .codec_dev = &soc_codec_dev_tlv320aic23, -}; - static struct platform_device *afeb9260_snd_device; static int __init afeb9260_soc_init(void) { int err; struct device *dev; - struct atmel_ssc_info *ssc_p = afeb9260_dai.cpu_dai->private_data; - struct ssc_device *ssc = NULL; if (!(machine_is_afeb9260())) return -ENODEV; - ssc = ssc_request(0); - if (IS_ERR(ssc)) { - printk(KERN_ERR "ASoC: Failed to request SSC 0\n"); - err = PTR_ERR(ssc); - ssc = NULL; - goto err_ssc; - } - ssc_p->ssc = ssc; afeb9260_snd_device = platform_device_alloc("soc-audio", -1); if (!afeb9260_snd_device) { @@ -172,8 +158,7 @@ static int __init afeb9260_soc_init(void) return -ENOMEM; } - platform_set_drvdata(afeb9260_snd_device, &afeb9260_snd_devdata); - afeb9260_snd_devdata.dev = &afeb9260_snd_device->dev; + platform_set_drvdata(afeb9260_snd_device, &snd_soc_machine_afeb9260); err = platform_device_add(afeb9260_snd_device); if (err) goto err1; @@ -184,9 +169,7 @@ static int __init afeb9260_soc_init(void) err1: platform_device_del(afeb9260_snd_device); platform_device_put(afeb9260_snd_device); -err_ssc: return err; - } static void __exit afeb9260_soc_exit(void) diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index cdf7be1b9b91..8780c90107fc 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c @@ -19,7 +19,6 @@ #include #include -#include "../codecs/ac97.h" #include "../codecs/wm8731.h" #include "psc.h" @@ -28,20 +27,16 @@ static struct snd_soc_dai_link db1200_ac97_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &au1xpsc_ac97_dai, - .codec_dai = &ac97_dai, + .cpu_dai_name = "au1xpsc-ac97", + .codec_dai_name = "ac97-hifi", + .platform_name = "au1xpsc-pcm-audio", + .codec_name = "ac97-codec", }; static struct snd_soc_card db1200_ac97_machine = { .name = "DB1200_AC97", .dai_link = &db1200_ac97_dai, .num_links = 1, - .platform = &au1xpsc_soc_platform, -}; - -static struct snd_soc_device db1200_ac97_devdata = { - .card = &db1200_ac97_machine, - .codec_dev = &soc_codec_dev_ac97, }; /*------------------------- I2S PART ---------------------------*/ @@ -49,8 +44,8 @@ static struct snd_soc_device db1200_ac97_devdata = { static int db1200_i2s_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* WM8731 has its own 12MHz crystal */ @@ -80,8 +75,10 @@ static struct snd_soc_ops db1200_i2s_wm8731_ops = { static struct snd_soc_dai_link db1200_i2s_dai = { .name = "WM8731", .stream_name = "WM8731 PCM", - .cpu_dai = &au1xpsc_i2s_dai, - .codec_dai = &wm8731_dai, + .cpu_dai_name = "au1xpsc", + .codec_dai_name = "wm8731-hifi" + .platform_name = "au1xpsc-pcm-audio", + .codec_name = "wm8731-codec.0-001a", .ops = &db1200_i2s_wm8731_ops, }; @@ -89,12 +86,6 @@ static struct snd_soc_card db1200_i2s_machine = { .name = "DB1200_I2S", .dai_link = &db1200_i2s_dai, .num_links = 1, - .platform = &au1xpsc_soc_platform, -}; - -static struct snd_soc_device db1200_i2s_devdata = { - .card = &db1200_i2s_machine, - .codec_dev = &soc_codec_dev_wm8731, }; /*------------------------- COMMON PART ---------------------------*/ @@ -112,12 +103,10 @@ static int __init db1200_audio_load(void) /* DB1200 board setup set PSC1MUX to preferred audio device */ if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX) - platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_devdata); + platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_machine); else - platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_devdata); + platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_machine); - db1200_ac97_devdata.dev = &db1200_asoc_dev->dev; - db1200_i2s_devdata.dev = &db1200_asoc_dev->dev; ret = platform_device_add(db1200_asoc_dev); if (ret) { diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 6d9f4c624949..00fdb9cbfc2d 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -329,7 +329,7 @@ static int au1xpsc_pcm_new(struct snd_card *card, return 0; } -static int au1xpsc_pcm_probe(struct platform_device *pdev) +static int au1xpsc_pcm_probe(struct snd_soc_platform *platform) { if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX]) return -ENODEV; @@ -337,17 +337,10 @@ static int au1xpsc_pcm_probe(struct platform_device *pdev) return 0; } -static int au1xpsc_pcm_remove(struct platform_device *pdev) -{ - return 0; -} - /* au1xpsc audio platform */ -struct snd_soc_platform au1xpsc_soc_platform = { - .name = "au1xpsc-pcm-dbdma", +struct snd_soc_platform_driver au1xpsc_soc_platform = { .probe = au1xpsc_pcm_probe, - .remove = au1xpsc_pcm_remove, - .pcm_ops = &au1xpsc_pcm_ops, + .ops = &au1xpsc_pcm_ops, .pcm_new = au1xpsc_pcm_new, .pcm_free = au1xpsc_pcm_free_dma_buffers, }; @@ -387,7 +380,7 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) } (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start; - ret = snd_soc_register_platform(&au1xpsc_soc_platform); + ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform); if (!ret) return ret; @@ -404,7 +397,7 @@ static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev) { int i; - snd_soc_unregister_platform(&au1xpsc_soc_platform); + snd_soc_unregister_platform(&pdev->dev); for (i = 0; i < 2; i++) { if (au1xpsc_audio_pcmdma[i]) { @@ -419,7 +412,7 @@ static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev) static struct platform_driver au1xpsc_pcm_driver = { .driver = { - .name = "au1xpsc-pcm", + .name = "au1xpsc-pcm-audio", .owner = THIS_MODULE, }, .probe = au1xpsc_pcm_drvprobe, diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index d14a5a91a465..6a9516cbe424 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c @@ -315,27 +315,19 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, return ret; } -static int au1xpsc_ac97_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int au1xpsc_ac97_probe(struct snd_soc_dai *dai) { return au1xpsc_ac97_workdata ? 0 : -ENODEV; } -static void au1xpsc_ac97_remove(struct platform_device *pdev, - struct snd_soc_dai *dai) -{ -} - static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { .trigger = au1xpsc_ac97_trigger, .hw_params = au1xpsc_ac97_hw_params, }; -struct snd_soc_dai au1xpsc_ac97_dai = { - .name = "au1xpsc_ac97", +struct snd_soc_dai_driver au1xpsc_ac97_dai = { .ac97_control = 1, .probe = au1xpsc_ac97_probe, - .remove = au1xpsc_ac97_remove, .playback = { .rates = AC97_RATES, .formats = AC97_FMTS, @@ -395,7 +387,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd)); au_sync(); - ret = snd_soc_register_dai(&au1xpsc_ac97_dai); + ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_ac97_dai); if (ret) goto out1; @@ -406,7 +398,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) return 0; } - snd_soc_unregister_dai(&au1xpsc_ac97_dai); + snd_soc_unregister_dai(&pdev->dev); out1: release_mem_region(r->start, resource_size(r)); out0: @@ -422,7 +414,7 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev) if (wd->dmapd) au1xpsc_pcm_destroy(wd->dmapd); - snd_soc_unregister_dai(&au1xpsc_ac97_dai); + snd_soc_unregister_dai(&pdev->dev); /* disable PSC completely */ au_writel(0, AC97_CFG(wd)); @@ -485,7 +477,7 @@ static struct dev_pm_ops au1xpscac97_pmops = { static struct platform_driver au1xpsc_ac97_driver = { .driver = { - .name = "au1xpsc_ac97", + .name = "au1xpsc-ac97", .owner = THIS_MODULE, .pm = AU1XPSCAC97_PMOPS, }, diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 6083fe7799fa..94e560a8756d 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -263,27 +263,19 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, return ret; } -static int au1xpsc_i2s_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int au1xpsc_i2s_probe(struct snd_soc_dai *dai) { return au1xpsc_i2s_workdata ? 0 : -ENODEV; } -static void au1xpsc_i2s_remove(struct platform_device *pdev, - struct snd_soc_dai *dai) -{ -} - static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { .trigger = au1xpsc_i2s_trigger, .hw_params = au1xpsc_i2s_hw_params, .set_fmt = au1xpsc_i2s_set_fmt, }; -struct snd_soc_dai au1xpsc_i2s_dai = { - .name = "au1xpsc_i2s", +static struct snd_soc_dai_driver au1xpsc_i2s_dai = { .probe = au1xpsc_i2s_probe, - .remove = au1xpsc_i2s_remove, .playback = { .rates = AU1XPSC_I2S_RATES, .formats = AU1XPSC_I2S_FMTS, @@ -298,7 +290,6 @@ struct snd_soc_dai au1xpsc_i2s_dai = { }, .ops = &au1xpsc_i2s_dai_ops, }; -EXPORT_SYMBOL(au1xpsc_i2s_dai); static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) { @@ -346,7 +337,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) * time out. */ - ret = snd_soc_register_dai(&au1xpsc_i2s_dai); + ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_i2s_dai); if (ret) goto out1; @@ -358,7 +349,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) return 0; } - snd_soc_unregister_dai(&au1xpsc_i2s_dai); + snd_soc_unregister_dai(&pdev->dev); out1: release_mem_region(r->start, resource_size(r)); out0: @@ -374,7 +365,7 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev) if (wd->dmapd) au1xpsc_pcm_destroy(wd->dmapd); - snd_soc_unregister_dai(&au1xpsc_i2s_dai); + snd_soc_unregister_dai(&pdev->dev); au_writel(0, I2S_CFG(wd)); au_sync(); @@ -436,7 +427,7 @@ static struct dev_pm_ops au1xpsci2s_pmops = { static struct platform_driver au1xpsc_i2s_driver = { .driver = { - .name = "au1xpsc_i2s", + .name = "au1xpsc", .owner = THIS_MODULE, .pm = AU1XPSCI2S_PMOPS, }, diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h index 093775d4dc3e..f281443fd52f 100644 --- a/sound/soc/au1x/psc.h +++ b/sound/soc/au1x/psc.h @@ -16,9 +16,6 @@ #ifndef _AU1X_PCM_H #define _AU1X_PCM_H -extern struct snd_soc_dai au1xpsc_ac97_dai; -extern struct snd_soc_dai au1xpsc_i2s_dai; -extern struct snd_soc_platform au1xpsc_soc_platform; extern struct snd_ac97_bus_ops soc_ac97_ops; /* DBDMA helpers */ diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 5e7aacf3bb5a..5a2fd8abaefa 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c @@ -422,14 +422,14 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = bf5xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto out; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { ret = bf5xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) @@ -439,25 +439,44 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai, return ret; } -struct snd_soc_platform bf5xx_ac97_soc_platform = { - .name = "bf5xx-audio", - .pcm_ops = &bf5xx_pcm_ac97_ops, +static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = { + .ops = &bf5xx_pcm_ac97_ops, .pcm_new = bf5xx_pcm_ac97_new, .pcm_free = bf5xx_pcm_free_dma_buffers, }; -EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform); -static int __init bfin_ac97_init(void) +static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev) { - return snd_soc_register_platform(&bf5xx_ac97_soc_platform); + return snd_soc_register_platform(&pdev->dev, &bf5xx_ac97_soc_platform); } -module_init(bfin_ac97_init); -static void __exit bfin_ac97_exit(void) +static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev) { - snd_soc_unregister_platform(&bf5xx_ac97_soc_platform); + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver bf5xx_pcm_driver = { + .driver = { + .name = "bf5xx-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = bf5xx_soc_platform_probe, + .remove = __devexit_p(bf5xx_soc_platform_remove), +}; + +static int __init snd_bf5xx_pcm_init(void) +{ + return platform_driver_register(&bf5xx_pcm_driver); +} +module_init(snd_bf5xx_pcm_init); + +static void __exit snd_bf5xx_pcm_exit(void) +{ + platform_driver_unregister(&bf5xx_pcm_driver); } -module_exit(bfin_ac97_exit); +module_exit(snd_bf5xx_pcm_exit); MODULE_AUTHOR("Cliff Cai"); MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.h b/sound/soc/blackfin/bf5xx-ac97-pcm.h index 350125a0ae21..d324d5826a9b 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.h +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.h @@ -23,7 +23,4 @@ struct bf5xx_gpio { u32 frm; }; -/* platform data */ -extern struct snd_soc_platform bf5xx_ac97_soc_platform; - #endif diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index c0eba5109980..c5f856ec27ca 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c @@ -255,7 +255,7 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops); #ifdef CONFIG_PM static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) { - struct sport_device *sport = dai->private_data; + struct sport_device *sport = snd_soc_dai_get_drvdata(dai); pr_debug("%s : sport %d\n", __func__, dai->id); if (!dai->active) @@ -270,7 +270,7 @@ static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) static int bf5xx_ac97_resume(struct snd_soc_dai *dai) { int ret; - struct sport_device *sport = dai->private_data; + struct sport_device *sport = snd_soc_dai_get_drvdata(dai); pr_debug("%s : sport %d\n", __func__, dai->id); if (!dai->active) @@ -306,8 +306,7 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai) #define bf5xx_ac97_resume NULL #endif -static int bf5xx_ac97_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int bf5xx_ac97_probe(struct snd_soc_dai *dai) { int ret = 0; cmd_count = (int *)get_zeroed_page(GFP_KERNEL); @@ -379,8 +378,7 @@ peripheral_err: return ret; } -static void bf5xx_ac97_remove(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int bf5xx_ac97_remove(struct snd_soc_dai *dai) { free_page((unsigned long)cmd_count); cmd_count = NULL; @@ -388,11 +386,10 @@ static void bf5xx_ac97_remove(struct platform_device *pdev, #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); #endif + return 0; } -struct snd_soc_dai bfin_ac97_dai = { - .name = "bf5xx-ac97", - .id = 0, +struct snd_soc_dai_driver bfin_ac97_dai = { .ac97_control = 1, .probe = bf5xx_ac97_probe, .remove = bf5xx_ac97_remove, @@ -417,18 +414,40 @@ struct snd_soc_dai bfin_ac97_dai = { }; EXPORT_SYMBOL_GPL(bfin_ac97_dai); +static __devinit int asoc_bfin_ac97_probe(struct platform_device *pdev) +{ + return snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai); +} + +static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + return 0; +} + +static struct platform_driver asoc_bfin_ac97_driver = { + .driver = { + .name = "bfin-ac97", + .owner = THIS_MODULE, + }, + + .probe = asoc_bfin_ac97_probe, + .remove = __devexit_p(asoc_bfin_ac97_remove), +}; + static int __init bfin_ac97_init(void) { - return snd_soc_register_dai(&bfin_ac97_dai); + return platform_driver_register(&asoc_bfin_ac97_driver); } module_init(bfin_ac97_init); static void __exit bfin_ac97_exit(void) { - snd_soc_unregister_dai(&bfin_ac97_dai); + platform_driver_unregister(&asoc_bfin_ac97_driver); } module_exit(bfin_ac97_exit); + MODULE_AUTHOR("Roy Huang"); MODULE_DESCRIPTION("AC97 driver for ADI Blackfin"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h index a1f97dd809d6..15c635e33f4d 100644 --- a/sound/soc/blackfin/bf5xx-ac97.h +++ b/sound/soc/blackfin/bf5xx-ac97.h @@ -50,8 +50,6 @@ struct ac97_frame { #define TAG_PCM_SR 0x0080 #define TAG_PCM_LFE 0x0040 -extern struct snd_soc_dai bfin_ac97_dai; - void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \ size_t count, unsigned int chan_mask); diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index 0f45a3f56be8..2394bff2b655 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c @@ -40,9 +40,9 @@ static struct snd_soc_card bf5xx_ad1836; static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - cpu_dai->private_data = sport_handle; + snd_soc_dai_set_drvdata(cpu_dai, sport_handle); return 0; } @@ -50,8 +50,8 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7}; int ret = 0; /* set cpu DAI configuration */ @@ -83,23 +83,19 @@ static struct snd_soc_ops bf5xx_ad1836_ops = { static struct snd_soc_dai_link bf5xx_ad1836_dai = { .name = "ad1836", .stream_name = "AD1836", - .cpu_dai = &bf5xx_tdm_dai, - .codec_dai = &ad1836_dai, + .cpu_dai_name = "bf5xx-tdm", + .codec_dai_name = "ad1836-hifi", + .platform_name = "bf5xx-tdm-pcm-audio", + .codec_name = "ad1836-codec.0", .ops = &bf5xx_ad1836_ops, }; static struct snd_soc_card bf5xx_ad1836 = { .name = "bf5xx_ad1836", - .platform = &bf5xx_tdm_soc_platform, .dai_link = &bf5xx_ad1836_dai, .num_links = 1, }; -static struct snd_soc_device bf5xx_ad1836_snd_devdata = { - .card = &bf5xx_ad1836, - .codec_dev = &soc_codec_dev_ad1836, -}; - static struct platform_device *bfxx_ad1836_snd_device; static int __init bf5xx_ad1836_init(void) @@ -110,8 +106,7 @@ static int __init bf5xx_ad1836_init(void) if (!bfxx_ad1836_snd_device) return -ENOMEM; - platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836_snd_devdata); - bf5xx_ad1836_snd_devdata.dev = &bfxx_ad1836_snd_device->dev; + platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836); ret = platform_device_add(bfxx_ad1836_snd_device); if (ret) diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c index b8c9060cfd8e..e4a625317a1a 100644 --- a/sound/soc/blackfin/bf5xx-ad193x.c +++ b/sound/soc/blackfin/bf5xx-ad193x.c @@ -49,9 +49,9 @@ static struct snd_soc_card bf5xx_ad193x; static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - cpu_dai->private_data = sport_handle; + snd_soc_dai_set_drvdata(cpu_dai, sport_handle); return 0; } @@ -59,8 +59,8 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7}; int ret = 0; /* set cpu DAI configuration */ @@ -97,23 +97,19 @@ static struct snd_soc_ops bf5xx_ad193x_ops = { static struct snd_soc_dai_link bf5xx_ad193x_dai = { .name = "ad193x", .stream_name = "AD193X", - .cpu_dai = &bf5xx_tdm_dai, - .codec_dai = &ad193x_dai, + .cpu_dai_name = "bf5xx-tdm", + .codec_dai_name ="ad193x-hifi", + .platform_name = "bf5xx-tdm-pcm-audio", + .codec_name = "ad193x-codec.5", .ops = &bf5xx_ad193x_ops, }; static struct snd_soc_card bf5xx_ad193x = { .name = "bf5xx_ad193x", - .platform = &bf5xx_tdm_soc_platform, .dai_link = &bf5xx_ad193x_dai, .num_links = 1, }; -static struct snd_soc_device bf5xx_ad193x_snd_devdata = { - .card = &bf5xx_ad193x, - .codec_dev = &soc_codec_dev_ad193x, -}; - static struct platform_device *bfxx_ad193x_snd_device; static int __init bf5xx_ad193x_init(void) @@ -124,8 +120,7 @@ static int __init bf5xx_ad193x_init(void) if (!bfxx_ad193x_snd_device) return -ENOMEM; - platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x_snd_devdata); - bf5xx_ad193x_snd_devdata.dev = &bfxx_ad193x_snd_device->dev; + platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x); ret = platform_device_add(bfxx_ad193x_snd_device); if (ret) diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c index d8f591273778..a31bdf656fce 100644 --- a/sound/soc/blackfin/bf5xx-ad1980.c +++ b/sound/soc/blackfin/bf5xx-ad1980.c @@ -48,10 +48,10 @@ static struct snd_soc_card bf5xx_board; static int bf5xx_board_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; pr_debug("%s enter\n", __func__); - cpu_dai->private_data = sport_handle; + snd_soc_dai_set_drvdata(cpu_dai, sport_handle); return 0; } @@ -62,23 +62,19 @@ static struct snd_soc_ops bf5xx_board_ops = { static struct snd_soc_dai_link bf5xx_board_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &bfin_ac97_dai, - .codec_dai = &ad1980_dai, + .cpu_dai_name = "bfin-ac97", + .codec_dai_name = "ad1980-hifi", + .platform_name = "bfin-pcm-audio", + .codec_name = "ad1980-codec", .ops = &bf5xx_board_ops, }; static struct snd_soc_card bf5xx_board = { .name = "bf5xx-board", - .platform = &bf5xx_ac97_soc_platform, .dai_link = &bf5xx_board_dai, .num_links = 1, }; -static struct snd_soc_device bf5xx_board_snd_devdata = { - .card = &bf5xx_board, - .codec_dev = &soc_codec_dev_ad1980, -}; - static struct platform_device *bf5xx_board_snd_device; static int __init bf5xx_board_init(void) @@ -89,8 +85,7 @@ static int __init bf5xx_board_init(void) if (!bf5xx_board_snd_device) return -ENOMEM; - platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board_snd_devdata); - bf5xx_board_snd_devdata.dev = &bf5xx_board_snd_device->dev; + platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board); ret = platform_device_add(bf5xx_board_snd_device); if (ret) diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c index 9825b71d0e28..900ced54ac79 100644 --- a/sound/soc/blackfin/bf5xx-ad73311.c +++ b/sound/soc/blackfin/bf5xx-ad73311.c @@ -47,7 +47,6 @@ #include "../codecs/ad73311.h" #include "bf5xx-sport.h" #include "bf5xx-i2s-pcm.h" -#include "bf5xx-i2s.h" #if CONFIG_SND_BF5XX_SPORT_NUM == 0 #define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1 @@ -150,10 +149,10 @@ static int bf5xx_probe(struct platform_device *pdev) static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; pr_debug("%s enter\n", __func__); - cpu_dai->private_data = sport_handle; + snd_soc_dai_set_drvdata(cpu_dai, sport_handle); return 0; } @@ -161,7 +160,7 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret = 0; pr_debug("%s rate %d format %x\n", __func__, params_rate(params), @@ -185,24 +184,20 @@ static struct snd_soc_ops bf5xx_ad73311_ops = { static struct snd_soc_dai_link bf5xx_ad73311_dai = { .name = "ad73311", .stream_name = "AD73311", - .cpu_dai = &bf5xx_i2s_dai, - .codec_dai = &ad73311_dai, + .cpu_dai_name = "bf5xx-i2s", + .codec_dai_name = "ad73311-hifi", + .platform_name = "bfin-pcm-audio", + .codec_name = "ad73311-codec", .ops = &bf5xx_ad73311_ops, }; static struct snd_soc_card bf5xx_ad73311 = { .name = "bf5xx_ad73311", - .platform = &bf5xx_i2s_soc_platform, .probe = bf5xx_probe, .dai_link = &bf5xx_ad73311_dai, .num_links = 1, }; -static struct snd_soc_device bf5xx_ad73311_snd_devdata = { - .card = &bf5xx_ad73311, - .codec_dev = &soc_codec_dev_ad73311, -}; - static struct platform_device *bf5xx_ad73311_snd_device; static int __init bf5xx_ad73311_init(void) @@ -214,8 +209,7 @@ static int __init bf5xx_ad73311_init(void) if (!bf5xx_ad73311_snd_device) return -ENOMEM; - platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata); - bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev; + platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311); ret = platform_device_add(bf5xx_ad73311_snd_device); if (ret) diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 1d2a1adf2575..890a0dccf902 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c @@ -40,7 +40,6 @@ #include #include "bf5xx-i2s-pcm.h" -#include "bf5xx-i2s.h" #include "bf5xx-sport.h" static void bf5xx_dma_irq(void *data) @@ -257,14 +256,14 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = bf5xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto out; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { ret = bf5xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) @@ -274,25 +273,44 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai, return ret; } -struct snd_soc_platform bf5xx_i2s_soc_platform = { - .name = "bf5xx-audio", - .pcm_ops = &bf5xx_pcm_i2s_ops, +static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = { + .ops = &bf5xx_pcm_i2s_ops, .pcm_new = bf5xx_pcm_i2s_new, .pcm_free = bf5xx_pcm_free_dma_buffers, }; -EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform); -static int __init bfin_i2s_init(void) +static int __devinit bfin_i2s_soc_platform_probe(struct platform_device *pdev) { - return snd_soc_register_platform(&bf5xx_i2s_soc_platform); + return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform); } -module_init(bfin_i2s_init); -static void __exit bfin_i2s_exit(void) +static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev) { - snd_soc_unregister_platform(&bf5xx_i2s_soc_platform); + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver bfin_i2s_pcm_driver = { + .driver = { + .name = "bfin-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = bfin_i2s_soc_platform_probe, + .remove = __devexit_p(bfin_i2s_soc_platform_remove), +}; + +static int __init snd_bfin_i2s_pcm_init(void) +{ + return platform_driver_register(&bfin_i2s_pcm_driver); +} +module_init(snd_bfin_i2s_pcm_init); + +static void __exit snd_bfin_i2s_pcm_exit(void) +{ + platform_driver_unregister(&bfin_i2s_pcm_driver); } -module_exit(bfin_i2s_exit); +module_exit(snd_bfin_i2s_pcm_exit); MODULE_AUTHOR("Cliff Cai"); MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.h b/sound/soc/blackfin/bf5xx-i2s-pcm.h index 4d4609a97c59..0c2c5a68d4ff 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.h +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.h @@ -23,7 +23,4 @@ struct bf5xx_gpio { u32 frm; }; -/* platform data */ -extern struct snd_soc_platform bf5xx_i2s_soc_platform; - #endif diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index 3e6ada0dd1c4..d453b1e9d607 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c @@ -42,7 +42,6 @@ #include #include "bf5xx-sport.h" -#include "bf5xx-i2s.h" struct bf5xx_i2s_port { u16 tcr1; @@ -195,8 +194,7 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream, bf5xx_i2s.configured = 0; } -static int bf5xx_i2s_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int bf5xx_i2s_probe(struct snd_soc_dai *dai) { pr_debug("%s enter\n", __func__); if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { @@ -215,11 +213,11 @@ static int bf5xx_i2s_probe(struct platform_device *pdev, return 0; } -static void bf5xx_i2s_remove(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int bf5xx_i2s_remove(struct snd_soc_dai *dai) { pr_debug("%s enter\n", __func__); peripheral_free_list(&sport_req[sport_num][0]); + return 0; } #ifdef CONFIG_PM @@ -228,9 +226,9 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) pr_debug("%s : sport %d\n", __func__, dai->id); - if (dai->capture.active) + if (dai->capture_active) sport_rx_stop(sport_handle); - if (dai->playback.active) + if (dai->playback_active) sport_tx_stop(sport_handle); return 0; } @@ -277,9 +275,7 @@ static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { .set_fmt = bf5xx_i2s_set_dai_fmt, }; -struct snd_soc_dai bf5xx_i2s_dai = { - .name = "bf5xx-i2s", - .id = 0, +static struct snd_soc_dai_driver bf5xx_i2s_dai = { .probe = bf5xx_i2s_probe, .remove = bf5xx_i2s_remove, .suspend = bf5xx_i2s_suspend, @@ -296,18 +292,39 @@ struct snd_soc_dai bf5xx_i2s_dai = { .formats = BF5XX_I2S_FORMATS,}, .ops = &bf5xx_i2s_dai_ops, }; -EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); + +static int bfin_i2s_drv_probe(struct platform_device *pdev) +{ + return snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai); +} + +static int __devexit bfin_i2s_drv_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + return 0; +} + +static struct platform_driver bfin_i2s_driver = { + .probe = bfin_i2s_drv_probe, + .remove = __devexit_p(bfin_i2s_drv_remove), + + .driver = { + .name = "bf5xx-i2s", + .owner = THIS_MODULE, + }, +}; static int __init bfin_i2s_init(void) { - return snd_soc_register_dai(&bf5xx_i2s_dai); + return platform_driver_register(&bfin_i2s_driver); } -module_init(bfin_i2s_init); static void __exit bfin_i2s_exit(void) { - snd_soc_unregister_dai(&bf5xx_i2s_dai); + platform_driver_unregister(&bfin_i2s_driver); } + +module_init(bfin_i2s_init); module_exit(bfin_i2s_exit); /* Module information */ diff --git a/sound/soc/blackfin/bf5xx-i2s.h b/sound/soc/blackfin/bf5xx-i2s.h deleted file mode 100644 index 264ecdcba35a..000000000000 --- a/sound/soc/blackfin/bf5xx-i2s.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * sound/soc/blackfin/bf5xx-i2s.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _BF5XX_I2S_H -#define _BF5XX_I2S_H - -extern struct snd_soc_dai bf5xx_i2s_dai; - -#endif diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c index 3a00fa4dbe6d..36f2769eb912 100644 --- a/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/sound/soc/blackfin/bf5xx-ssm2602.c @@ -42,17 +42,16 @@ #include "../codecs/ssm2602.h" #include "bf5xx-sport.h" #include "bf5xx-i2s-pcm.h" -#include "bf5xx-i2s.h" static struct snd_soc_card bf5xx_ssm2602; static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; pr_debug("%s enter\n", __func__); - cpu_dai->private_data = sport_handle; + snd_soc_dai_set_drvdata(cpu_dai, sport_handle); return 0; } @@ -60,8 +59,8 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int clk = 0; int ret = 0; @@ -118,36 +117,19 @@ static struct snd_soc_ops bf5xx_ssm2602_ops = { static struct snd_soc_dai_link bf5xx_ssm2602_dai = { .name = "ssm2602", .stream_name = "SSM2602", - .cpu_dai = &bf5xx_i2s_dai, - .codec_dai = &ssm2602_dai, + .cpu_dai_name = "bf5xx-i2s", + .codec_dai_name = "ssm2602-hifi", + .platform_name = "bf5xx-pcm-audio", + .codec_name = "ssm2602-codec.0-0x1b", .ops = &bf5xx_ssm2602_ops, }; -/* - * SSM2602 2 wire address is determined by CSB - * state during powerup. - * low = 0x1a - * high = 0x1b - */ - -static struct ssm2602_setup_data bf5xx_ssm2602_setup = { - .i2c_bus = 0, - .i2c_address = 0x1b, -}; - static struct snd_soc_card bf5xx_ssm2602 = { .name = "bf5xx_ssm2602", - .platform = &bf5xx_i2s_soc_platform, .dai_link = &bf5xx_ssm2602_dai, .num_links = 1, }; -static struct snd_soc_device bf5xx_ssm2602_snd_devdata = { - .card = &bf5xx_ssm2602, - .codec_dev = &soc_codec_dev_ssm2602, - .codec_data = &bf5xx_ssm2602_setup, -}; - static struct platform_device *bf5xx_ssm2602_snd_device; static int __init bf5xx_ssm2602_init(void) @@ -159,9 +141,7 @@ static int __init bf5xx_ssm2602_init(void) if (!bf5xx_ssm2602_snd_device) return -ENOMEM; - platform_set_drvdata(bf5xx_ssm2602_snd_device, - &bf5xx_ssm2602_snd_devdata); - bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev; + platform_set_drvdata(bf5xx_ssm2602_snd_device, &bf5xx_ssm2602); ret = platform_device_add(bf5xx_ssm2602_snd_device); if (ret) diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c index 6bac1ac1a315..74cf759b78a6 100644 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.c +++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c @@ -290,14 +290,14 @@ static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = bf5xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto out; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { ret = bf5xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) @@ -307,25 +307,44 @@ out: return ret; } -struct snd_soc_platform bf5xx_tdm_soc_platform = { - .name = "bf5xx-audio", - .pcm_ops = &bf5xx_pcm_tdm_ops, +static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = { + .ops = &bf5xx_pcm_tdm_ops, .pcm_new = bf5xx_pcm_tdm_new, .pcm_free = bf5xx_pcm_free_dma_buffers, }; -EXPORT_SYMBOL_GPL(bf5xx_tdm_soc_platform); -static int __init bfin_pcm_tdm_init(void) +static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev) { - return snd_soc_register_platform(&bf5xx_tdm_soc_platform); + return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform); } -module_init(bfin_pcm_tdm_init); -static void __exit bfin_pcm_tdm_exit(void) +static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev) { - snd_soc_unregister_platform(&bf5xx_tdm_soc_platform); + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver bfin_tdm_driver = { + .driver = { + .name = "bf5xx-tdm-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = bf5xx_soc_platform_probe, + .remove = __devexit_p(bf5xx_soc_platform_remove), +}; + +static int __init snd_bfin_tdm_init(void) +{ + return platform_driver_register(&bfin_tdm_driver); +} +module_init(snd_bfin_tdm_init); + +static void __exit snd_bfin_tdm_exit(void) +{ + platform_driver_unregister(&bfin_tdm_driver); } -module_exit(bfin_pcm_tdm_exit); +module_exit(snd_bfin_tdm_exit); MODULE_AUTHOR("Barry Song"); MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module"); diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.h b/sound/soc/blackfin/bf5xx-tdm-pcm.h index ddc5047df88c..7f8cc01c4477 100644 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.h +++ b/sound/soc/blackfin/bf5xx-tdm-pcm.h @@ -15,7 +15,4 @@ struct bf5xx_pcm_dma_params { char *name; /* stream identifier */ }; -/* platform data */ -extern struct snd_soc_platform bf5xx_tdm_soc_platform; - #endif diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c index 24c14269f4bc..125123929f16 100644 --- a/sound/soc/blackfin/bf5xx-tdm.c +++ b/sound/soc/blackfin/bf5xx-tdm.c @@ -214,9 +214,9 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) if (!dai->active) return 0; - if (dai->capture.active) + if (dai->capture_active) sport_rx_stop(sport); - if (dai->playback.active) + if (dai->playback_active) sport_tx_stop(sport); return 0; } @@ -224,7 +224,7 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) static int bf5xx_tdm_resume(struct snd_soc_dai *dai) { int ret; - struct sport_device *sport = dai->private_data; + struct sport_device *sport = snd_soc_dai_get_drvdata(dai); if (!dai->active) return 0; @@ -262,9 +262,7 @@ static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = { .set_channel_map = bf5xx_tdm_set_channel_map, }; -struct snd_soc_dai bf5xx_tdm_dai = { - .name = "bf5xx-tdm", - .id = 0, +static struct snd_soc_dai_driver bf5xx_tdm_dai = { .suspend = bf5xx_tdm_suspend, .resume = bf5xx_tdm_resume, .playback = { @@ -279,7 +277,6 @@ struct snd_soc_dai bf5xx_tdm_dai = { .formats = SNDRV_PCM_FMTBIT_S32_LE,}, .ops = &bf5xx_tdm_dai_ops, }; -EXPORT_SYMBOL_GPL(bf5xx_tdm_dai); static int __devinit bfin_tdm_probe(struct platform_device *pdev) { @@ -320,7 +317,7 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev) goto sport_config_err; } - ret = snd_soc_register_dai(&bf5xx_tdm_dai); + ret = snd_soc_register_dai(&pdev->dev, &bf5xx_tdm_dai); if (ret) { pr_err("Failed to register DAI: %d\n", ret); goto sport_config_err; @@ -337,7 +334,7 @@ sport_config_err: static int __devexit bfin_tdm_remove(struct platform_device *pdev) { peripheral_free_list(&sport_req[sport_num][0]); - snd_soc_unregister_dai(&bf5xx_tdm_dai); + snd_soc_unregister_dai(&pdev->dev); return 0; } diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h index 04189a18c1ba..e986a3ea3315 100644 --- a/sound/soc/blackfin/bf5xx-tdm.h +++ b/sound/soc/blackfin/bf5xx-tdm.h @@ -20,6 +20,4 @@ struct bf5xx_tdm_port { int configured; }; -extern struct snd_soc_dai bf5xx_tdm_dai; - #endif diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 1f5e57a4bb7a..12c87d37eba1 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -21,7 +21,6 @@ #include #include #include -#include "ac97.h" #define AC97_VERSION "0.6" @@ -30,8 +29,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; @@ -46,8 +44,8 @@ static struct snd_soc_dai_ops ac97_dai_ops = { .prepare = ac97_prepare, }; -struct snd_soc_dai ac97_dai = { - .name = "AC97 HiFi", +static struct snd_soc_dai_driver ac97_dai = { + .name = "ac97-hifi", .ac97_control = 1, .playback = { .stream_name = "AC97 Playback", @@ -63,7 +61,6 @@ struct snd_soc_dai ac97_dai = { .formats = SND_SOC_STD_AC97_FMTS,}, .ops = &ac97_dai_ops, }; -EXPORT_SYMBOL_GPL(ac97_dai); static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) @@ -78,95 +75,49 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, return 0; } -static int ac97_soc_probe(struct platform_device *pdev) +static int ac97_soc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_card *card = socdev->card; - struct snd_soc_codec *codec; struct snd_ac97_bus *ac97_bus; struct snd_ac97_template ac97_template; - int i; - int ret = 0; + int ret; printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); - socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (!socdev->card->codec) - return -ENOMEM; - codec = socdev->card->codec; - mutex_init(&codec->mutex); - - codec->name = "AC97"; - codec->owner = THIS_MODULE; - codec->dai = &ac97_dai; - codec->num_dai = 1; - codec->write = ac97_write; - codec->read = ac97_read; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) - goto err; + ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); + if (ret < 0) { + printk(KERN_ERR "ASoC: failed to init gen ac97 glue\n"); + return ret; + } /* add codec as bus device for standard ac97 */ - ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus); + ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus); if (ret < 0) - goto bus_err; + return ret; memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); if (ret < 0) - goto bus_err; - - for (i = 0; i < card->num_links; i++) { - if (card->dai_link[i].codec_dai->ac97_control) { - snd_ac97_dev_add_pdata(codec->ac97, - card->dai_link[i].cpu_dai->ac97_pdata); - } - } + return ret; return 0; - -bus_err: - snd_soc_free_pcms(socdev); - -err: - kfree(socdev->card->codec); - socdev->card->codec = NULL; - return ret; } -static int ac97_soc_remove(struct platform_device *pdev) +static int ac97_soc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (!codec) - return 0; - - snd_soc_free_pcms(socdev); - kfree(socdev->card->codec); - return 0; } #ifdef CONFIG_PM -static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg) +static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_ac97_suspend(socdev->card->codec->ac97); + snd_ac97_suspend(codec->ac97); return 0; } -static int ac97_soc_resume(struct platform_device *pdev) +static int ac97_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_ac97_resume(socdev->card->codec->ac97); + snd_ac97_resume(codec->ac97); return 0; } @@ -175,13 +126,48 @@ static int ac97_soc_resume(struct platform_device *pdev) #define ac97_soc_resume NULL #endif -struct snd_soc_codec_device soc_codec_dev_ac97 = { +static struct snd_soc_codec_driver soc_codec_dev_ac97 = { + .write = ac97_write, + .read = ac97_read, .probe = ac97_soc_probe, .remove = ac97_soc_remove, .suspend = ac97_soc_suspend, .resume = ac97_soc_resume, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ac97); + +static __devinit int ac97_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_ac97, &ac97_dai, 1); +} + +static int __devexit ac97_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static struct platform_driver ac97_codec_driver = { + .driver = { + .name = "ac97-codec", + .owner = THIS_MODULE, + }, + + .probe = ac97_probe, + .remove = __devexit_p(ac97_remove), +}; + +static int __init ac97_init(void) +{ + return platform_driver_register(&ac97_codec_driver); +} +module_init(ac97_init); + +static void __exit ac97_exit(void) +{ + platform_driver_unregister(&ac97_codec_driver); +} +module_exit(ac97_exit); MODULE_DESCRIPTION("Soc Generic AC97 driver"); MODULE_AUTHOR("Liam Girdwood"); diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h deleted file mode 100644 index 281aa42e2bbb..000000000000 --- a/sound/soc/codecs/ac97.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/sound/codecs/ac97.h -- ALSA SoC Layer - * - * Author: Liam Girdwood - * Created: Dec 1st 2005 - * Copyright: Wolfson Microelectronics. PLC. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __LINUX_SND_SOC_AC97_H -#define __LINUX_SND_SOC_AC97_H - -extern struct snd_soc_codec_device soc_codec_dev_ac97; -extern struct snd_soc_dai ac97_dai; - -#endif diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index a01006c8c606..d272534c8f84 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -33,15 +33,10 @@ /* codec private data */ struct ad1836_priv { - struct snd_soc_codec codec; - u16 reg_cache[AD1836_NUM_REGS]; + enum snd_soc_control_type control_type; + void *control_data; }; -static struct snd_soc_codec *ad1836_codec; -struct snd_soc_codec_device soc_codec_dev_ad1836; -static int ad1836_register(struct ad1836_priv *ad1836); -static void ad1836_unregister(struct ad1836_priv *ad1836); - /* * AD1836 volume/mute/de-emphasis etc. controls */ @@ -146,8 +141,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, int word_len = 0; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; /* bit size */ switch (params_format(params)) { @@ -173,12 +167,9 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, } #ifdef CONFIG_PM -static int ad1836_soc_suspend(struct platform_device *pdev, +static int ad1836_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - /* reset clock control mode */ u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; @@ -186,11 +177,8 @@ static int ad1836_soc_suspend(struct platform_device *pdev, return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); } -static int ad1836_soc_resume(struct platform_device *pdev) +static int ad1836_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - /* restore clock control mode */ u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); adc_ctrl2 |= AD1836_ADC_AUX; @@ -202,49 +190,14 @@ static int ad1836_soc_resume(struct platform_device *pdev) #define ad1836_soc_resume NULL #endif -static int __devinit ad1836_spi_probe(struct spi_device *spi) -{ - struct snd_soc_codec *codec; - struct ad1836_priv *ad1836; - - ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL); - if (ad1836 == NULL) - return -ENOMEM; - - codec = &ad1836->codec; - codec->control_data = spi; - codec->dev = &spi->dev; - - dev_set_drvdata(&spi->dev, ad1836); - - return ad1836_register(ad1836); -} - -static int __devexit ad1836_spi_remove(struct spi_device *spi) -{ - struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev); - - ad1836_unregister(ad1836); - return 0; -} - -static struct spi_driver ad1836_spi_driver = { - .driver = { - .name = "ad1836", - .owner = THIS_MODULE, - }, - .probe = ad1836_spi_probe, - .remove = __devexit_p(ad1836_spi_remove), -}; - static struct snd_soc_dai_ops ad1836_dai_ops = { .hw_params = ad1836_hw_params, .set_fmt = ad1836_set_dai_fmt, }; /* codec DAI instance */ -struct snd_soc_dai ad1836_dai = { - .name = "AD1836", +static struct snd_soc_dai_driver ad1836_dai = { + .name = "ad1836-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -263,35 +216,13 @@ struct snd_soc_dai ad1836_dai = { }, .ops = &ad1836_dai_ops, }; -EXPORT_SYMBOL_GPL(ad1836_dai); -static int ad1836_register(struct ad1836_priv *ad1836) +static int ad1836_probe(struct snd_soc_codec *codec) { - int ret; - struct snd_soc_codec *codec = &ad1836->codec; - - if (ad1836_codec) { - dev_err(codec->dev, "Another ad1836 is registered\n"); - kfree(ad1836); - return -EINVAL; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - snd_soc_codec_set_drvdata(codec, ad1836); - codec->reg_cache = ad1836->reg_cache; - codec->reg_cache_size = AD1836_NUM_REGS; - codec->name = "AD1836"; - codec->owner = THIS_MODULE; - codec->dai = &ad1836_dai; - codec->num_dai = 1; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - ad1836_dai.dev = codec->dev; - ad1836_codec = codec; + struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); + int ret = 0; + codec->control_data = ad1836->control_data; ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); if (ret < 0) { dev_err(codec->dev, "failed to set cache I/O: %d\n", @@ -319,81 +250,69 @@ static int ad1836_register(struct ad1836_priv *ad1836) snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - kfree(ad1836); - return ret; - } - - ret = snd_soc_register_dai(&ad1836_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - kfree(ad1836); - return ret; - } - - return 0; -} - -static void ad1836_unregister(struct ad1836_priv *ad1836) -{ - snd_soc_unregister_dai(&ad1836_dai); - snd_soc_unregister_codec(&ad1836->codec); - kfree(ad1836); - ad1836_codec = NULL; -} - -static int ad1836_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (ad1836_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = ad1836_codec; - codec = ad1836_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - snd_soc_add_controls(codec, ad1836_snd_controls, ARRAY_SIZE(ad1836_snd_controls)); snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, ARRAY_SIZE(ad1836_dapm_widgets)); snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); -pcm_err: return ret; } /* power down chip */ -static int ad1836_remove(struct platform_device *pdev) +static int ad1836_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); + /* reset clock control mode */ + u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); + adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; - return 0; + return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); } -struct snd_soc_codec_device soc_codec_dev_ad1836 = { +static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { .probe = ad1836_probe, .remove = ad1836_remove, .suspend = ad1836_soc_suspend, .resume = ad1836_soc_resume, + .reg_cache_size = AD1836_NUM_REGS, + .reg_word_size = sizeof(u16), +}; + +static int __devinit ad1836_spi_probe(struct spi_device *spi) +{ + struct ad1836_priv *ad1836; + int ret; + + ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL); + if (ad1836 == NULL) + return -ENOMEM; + + spi_set_drvdata(spi, ad1836); + ad1836->control_data = spi; + ad1836->control_type = SND_SOC_SPI; + + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_ad1836, &ad1836_dai, 1); + if (ret < 0) + kfree(ad1836); + return ret; +} + +static int __devexit ad1836_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); + return 0; +} + +static struct spi_driver ad1836_spi_driver = { + .driver = { + .name = "ad1836-codec", + .owner = THIS_MODULE, + }, + .probe = ad1836_spi_probe, + .remove = __devexit_p(ad1836_spi_remove), }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836); static int __init ad1836_init(void) { diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index e9d90d3951c5..845596717fdf 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h @@ -60,6 +60,4 @@ #define AD1836_NUM_REGS 16 -extern struct snd_soc_dai ad1836_dai; -extern struct snd_soc_codec_device soc_codec_dev_ad1836; #endif diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 1def75e4862f..fa2834c91b9f 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -24,9 +24,10 @@ /* codec private data */ struct ad193x_priv { - unsigned int sysclk; - struct snd_soc_codec codec; u8 reg_cache[AD193X_NUM_REGS]; + enum snd_soc_control_type bus_type; + void *control_data; + int sysclk; }; /* ad193x register cache & default register settings */ @@ -34,9 +35,6 @@ static const u8 ad193x_reg[AD193X_NUM_REGS] = { 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, }; -static struct snd_soc_codec *ad193x_codec; -struct snd_soc_codec_device soc_codec_dev_ad193x; - /* * AD193X volume/mute/de-emphasis etc. controls */ @@ -275,8 +273,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, int word_len = 0, reg = 0, master_rate = 0; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); /* bit size */ @@ -323,100 +320,6 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, return 0; } -static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type) -{ - struct snd_soc_codec *codec; - struct ad193x_priv *ad193x; - int ret; - - if (ad193x_codec) { - dev_err(dev, "Another ad193x is registered\n"); - return -EINVAL; - } - - ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); - if (ad193x == NULL) - return -ENOMEM; - - dev_set_drvdata(dev, ad193x); - - codec = &ad193x->codec; - mutex_init(&codec->mutex); - codec->control_data = ctrl_data; - codec->dev = dev; - snd_soc_codec_set_drvdata(codec, ad193x); - codec->reg_cache = ad193x->reg_cache; - codec->reg_cache_size = AD193X_NUM_REGS; - codec->name = "AD193X"; - codec->owner = THIS_MODULE; - codec->dai = &ad193x_dai; - codec->num_dai = 1; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - ad193x_dai.dev = codec->dev; - ad193x_codec = codec; - - memcpy(codec->reg_cache, ad193x_reg, AD193X_NUM_REGS); - - if (bus_type == SND_SOC_I2C) - ret = snd_soc_codec_set_cache_io(codec, 8, 8, bus_type); - else - ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", - ret); - kfree(ad193x); - return ret; - } - - /* default setting for ad193x */ - - /* unmute dac channels */ - snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0); - /* de-emphasis: 48kHz, powedown dac */ - snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A); - /* powerdown dac, dac in tdm mode */ - snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41); - /* high-pass filter enable */ - snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3); - /* sata delay=1, adc aux mode */ - snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43); - /* pll input: mclki/xi */ - snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ - snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); - ad193x->sysclk = 12288000; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - kfree(ad193x); - return ret; - } - - ret = snd_soc_register_dai(&ad193x_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - kfree(ad193x); - return ret; - } - - return 0; -} - -static int ad193x_bus_remove(struct device *dev) -{ - struct ad193x_priv *ad193x = dev_get_drvdata(dev); - - snd_soc_unregister_dai(&ad193x_dai); - snd_soc_unregister_codec(&ad193x->codec); - kfree(ad193x); - ad193x_codec = NULL; - - return 0; -} - static struct snd_soc_dai_ops ad193x_dai_ops = { .hw_params = ad193x_hw_params, .digital_mute = ad193x_mute, @@ -426,8 +329,8 @@ static struct snd_soc_dai_ops ad193x_dai_ops = { }; /* codec DAI instance */ -struct snd_soc_dai ad193x_dai = { - .name = "AD193X", +static struct snd_soc_dai_driver ad193x_dai = { + .name = "ad193x-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -446,28 +349,39 @@ struct snd_soc_dai ad193x_dai = { }, .ops = &ad193x_dai_ops, }; -EXPORT_SYMBOL_GPL(ad193x_dai); -static int ad193x_probe(struct platform_device *pdev) +static int ad193x_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; + struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); + int ret; - if (ad193x_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; + codec->control_data = ad193x->control_data; + if (ad193x->bus_type == SND_SOC_I2C) + ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->bus_type); + else + ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->bus_type); + if (ret < 0) { + dev_err(codec->dev, "failed to set cache I/O: %d\n", + ret); + kfree(ad193x); + return ret; } - socdev->card->codec = ad193x_codec; - codec = ad193x_codec; + /* default setting for ad193x */ - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } + /* unmute dac channels */ + snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0); + /* de-emphasis: 48kHz, powedown dac */ + snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A); + /* powerdown dac, dac in tdm mode */ + snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41); + /* high-pass filter enable */ + snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3); + /* sata delay=1, adc aux mode */ + snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43); + /* pll input: mclki/xi */ + snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ + snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); snd_soc_add_controls(codec, ad193x_snd_controls, ARRAY_SIZE(ad193x_snd_controls)); @@ -475,41 +389,47 @@ static int ad193x_probe(struct platform_device *pdev) ARRAY_SIZE(ad193x_dapm_widgets)); snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); -pcm_err: return ret; } -/* power down chip */ -static int ad193x_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_ad193x = { +static struct snd_soc_codec_driver soc_codec_dev_ad193x = { .probe = ad193x_probe, - .remove = ad193x_remove, + .reg_cache_default = ad193x_reg, + .reg_cache_size = AD193X_NUM_REGS, + .reg_word_size = sizeof(u16), }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ad193x); #if defined(CONFIG_SPI_MASTER) static int __devinit ad193x_spi_probe(struct spi_device *spi) { - return ad193x_bus_probe(&spi->dev, spi, SND_SOC_SPI); + struct ad193x_priv *ad193x; + int ret; + + ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); + if (ad193x == NULL) + return -ENOMEM; + + spi_set_drvdata(spi, ad193x); + ad193x->control_data = spi; + ad193x->bus_type = SND_SOC_SPI; + + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_ad193x, &ad193x_dai, 1); + if (ret < 0) + kfree(ad193x); + return ret; } static int __devexit ad193x_spi_remove(struct spi_device *spi) { - return ad193x_bus_remove(&spi->dev); + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); + return 0; } static struct spi_driver ad193x_spi_driver = { .driver = { - .name = "ad193x", + .name = "ad193x-codec", .owner = THIS_MODULE, }, .probe = ad193x_spi_probe, @@ -528,17 +448,34 @@ MODULE_DEVICE_TABLE(i2c, ad193x_id); static int __devinit ad193x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { - return ad193x_bus_probe(&client->dev, client, SND_SOC_I2C); + struct ad193x_priv *ad193x; + int ret; + + ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); + if (ad193x == NULL) + return -ENOMEM; + + i2c_set_clientdata(client, ad193x); + ad193x->control_data = client; + ad193x->bus_type = SND_SOC_I2C; + + ret = snd_soc_register_codec(&client->dev, + &soc_codec_dev_ad193x, &ad193x_dai, 1); + if (ret < 0) + kfree(ad193x); + return ret; } static int __devexit ad193x_i2c_remove(struct i2c_client *client) { - return ad193x_bus_remove(&client->dev); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); + return 0; } static struct i2c_driver ad193x_i2c_driver = { .driver = { - .name = "ad193x", + .name = "ad193x-codec", }, .probe = ad193x_i2c_probe, .remove = __devexit_p(ad193x_i2c_remove), diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 654ba64ae04c..9747b5497877 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h @@ -80,7 +80,4 @@ #define AD193X_NUM_REGS 17 -extern struct snd_soc_dai ad193x_dai; -extern struct snd_soc_codec_device soc_codec_dev_ad193x; - #endif diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 042072738cdc..1371afac657b 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -130,8 +130,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, return 0; } -struct snd_soc_dai ad1980_dai = { - .name = "AC97", +struct snd_soc_dai_driver ad1980_dai = { + .name = "ad1980-hifi", .ac97_control = 1, .playback = { .stream_name = "Playback", @@ -177,53 +177,20 @@ err: return -EIO; } -static int ad1980_soc_probe(struct platform_device *pdev) +static int ad1980_soc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; + int ret; u16 vendor_id2; u16 ext_status; printk(KERN_INFO "AD1980 SoC Audio Codec\n"); - socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->card->codec == NULL) - return -ENOMEM; - codec = socdev->card->codec; - mutex_init(&codec->mutex); - - codec->reg_cache = - kzalloc(sizeof(u16) * ARRAY_SIZE(ad1980_reg), GFP_KERNEL); - if (codec->reg_cache == NULL) { - ret = -ENOMEM; - goto cache_err; - } - memcpy(codec->reg_cache, ad1980_reg, sizeof(u16) * \ - ARRAY_SIZE(ad1980_reg)); - codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ad1980_reg); - codec->reg_cache_step = 2; - codec->name = "AD1980"; - codec->owner = THIS_MODULE; - codec->dai = &ad1980_dai; - codec->num_dai = 1; - codec->write = ac97_write; - codec->read = ac97_read; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); - goto codec_err; + return ret; } - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) - goto pcm_err; - - ret = ad1980_reset(codec, 0); if (ret < 0) { printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); @@ -262,41 +229,59 @@ static int ad1980_soc_probe(struct platform_device *pdev) return 0; reset_err: - snd_soc_free_pcms(socdev); - -pcm_err: snd_soc_free_ac97_codec(codec); - -codec_err: - kfree(codec->reg_cache); - -cache_err: - kfree(socdev->card->codec); - socdev->card->codec = NULL; return ret; } -static int ad1980_soc_remove(struct platform_device *pdev) +static int ad1980_soc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec == NULL) - return 0; - - snd_soc_dapm_free(socdev); - snd_soc_free_pcms(socdev); snd_soc_free_ac97_codec(codec); - kfree(codec->reg_cache); - kfree(codec); return 0; } -struct snd_soc_codec_device soc_codec_dev_ad1980 = { +static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { .probe = ad1980_soc_probe, .remove = ad1980_soc_remove, + .reg_cache_size = ARRAY_SIZE(ad1980_reg), + .reg_word_size = sizeof(u16), + .reg_cache_step = 2, + .write = ac97_write, + .read = ac97_read, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980); + +static __devinit int ad1980_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_ad1980, &ad1980_dai, 1); +} + +static int __devexit ad1980_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static struct platform_driver ad1980_codec_driver = { + .driver = { + .name = "ad1980-codec", + .owner = THIS_MODULE, + }, + + .probe = ad1980_probe, + .remove = __devexit_p(ad1980_remove), +}; + +static int __init ad1980_init(void) +{ + return platform_driver_register(&ad1980_codec_driver); +} +module_init(ad1980_init); + +static void __exit ad1980_exit(void) +{ + platform_driver_unregister(&ad1980_codec_driver); +} +module_exit(ad1980_exit); MODULE_DESCRIPTION("ASoC ad1980 driver"); MODULE_AUTHOR("Roy Huang, Cliff Cai"); diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h index db6c8500d66b..29b5a8750926 100644 --- a/sound/soc/codecs/ad1980.h +++ b/sound/soc/codecs/ad1980.h @@ -17,7 +17,4 @@ #define PR5 0x2000 #define PR6 0x4000 -extern struct snd_soc_dai ad1980_dai; -extern struct snd_soc_codec_device soc_codec_dev_ad1980; - #endif diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index 475807bea2c2..c53955fe17b6 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c @@ -23,8 +23,8 @@ #include "ad73311.h" -struct snd_soc_dai ad73311_dai = { - .name = "AD73311", +static struct snd_soc_dai_driver ad73311_dai = { + .name = "ad73311-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -38,68 +38,40 @@ struct snd_soc_dai ad73311_dai = { .rates = SNDRV_PCM_RATE_8000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, }; -EXPORT_SYMBOL_GPL(ad73311_dai); -static int ad73311_soc_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) - return -ENOMEM; - mutex_init(&codec->mutex); - codec->name = "AD73311"; - codec->owner = THIS_MODULE; - codec->dai = &ad73311_dai; - codec->num_dai = 1; - socdev->card->codec = codec; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "ad73311: failed to create pcms\n"); - goto pcm_err; - } - - return ret; +static struct snd_soc_codec_driver soc_codec_dev_ad73311; -pcm_err: - kfree(socdev->card->codec); - socdev->card->codec = NULL; - return ret; +static int ad73311_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_ad73311, &ad73311_dai, 1); } -static int ad73311_soc_remove(struct platform_device *pdev) +static int ad73311_remove(struct platform_device *pdev) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec == NULL) - return 0; - snd_soc_free_pcms(socdev); - kfree(codec); + snd_soc_unregister_codec(&pdev->dev); return 0; } -struct snd_soc_codec_device soc_codec_dev_ad73311 = { - .probe = ad73311_soc_probe, - .remove = ad73311_soc_remove, +static struct platform_driver ad73311_codec_driver = { + .driver = { + .name = "ad73311-codec", + .owner = THIS_MODULE, + }, + + .probe = ad73311_probe, + .remove = __devexit_p(ad73311_remove), }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311); static int __init ad73311_init(void) { - return snd_soc_register_dai(&ad73311_dai); + return platform_driver_register(&ad73311_codec_driver); } module_init(ad73311_init); static void __exit ad73311_exit(void) { - snd_soc_unregister_dai(&ad73311_dai); + platform_driver_unregister(&ad73311_codec_driver); } module_exit(ad73311_exit); diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h index 569573d2d4d7..4b353eefc0bf 100644 --- a/sound/soc/codecs/ad73311.h +++ b/sound/soc/codecs/ad73311.h @@ -85,6 +85,4 @@ #define REGF_INV (1 << 6) #define REGF_ALB (1 << 7) -extern struct snd_soc_dai ad73311_dai; -extern struct snd_soc_codec_device soc_codec_dev_ad73311; #endif diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c index f8e75edb27b7..8402854ec15e 100644 --- a/sound/soc/codecs/ads117x.c +++ b/sound/soc/codecs/ads117x.c @@ -19,16 +19,12 @@ #include #include -#include "ads117x.h" - #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) - #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) -struct snd_soc_dai ads117x_dai = { +static struct snd_soc_dai_driver ads117x_dai = { /* ADC */ - .name = "ADS117X ADC", - .id = 1, + .name = "ads117x-hifi", .capture = { .stream_name = "Capture", .channels_min = 1, @@ -36,75 +32,29 @@ struct snd_soc_dai ads117x_dai = { .rates = ADS117X_RATES, .formats = ADS117X_FORMATS,}, }; -EXPORT_SYMBOL_GPL(ads117x_dai); - -static int ads117x_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret; - - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) - return -ENOMEM; - socdev->card->codec = codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - codec->name = "ADS117X"; - codec->owner = THIS_MODULE; - codec->dai = &ads117x_dai; - codec->num_dai = 1; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "ads117x: failed to create pcms\n"); - kfree(codec); - return ret; - } - - return 0; -} - -static int ads117x_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - snd_soc_free_pcms(socdev); - kfree(codec); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_ads117x = { - .probe = ads117x_probe, - .remove = ads117x_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ads117x); +static struct snd_soc_codec_driver soc_codec_dev_ads117x; -static __devinit int ads117x_platform_probe(struct platform_device *pdev) +static __devinit int ads117x_probe(struct platform_device *pdev) { - ads117x_dai.dev = &pdev->dev; - return snd_soc_register_dai(&ads117x_dai); + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_ads117x, &ads117x_dai, 1); } -static int __devexit ads117x_platform_remove(struct platform_device *pdev) +static int __devexit ads117x_remove(struct platform_device *pdev) { - snd_soc_unregister_dai(&ads117x_dai); + snd_soc_unregister_codec(&pdev->dev); return 0; } static struct platform_driver ads117x_codec_driver = { .driver = { - .name = "ads117x", + .name = "ads117x-codec", .owner = THIS_MODULE, }, - .probe = ads117x_platform_probe, - .remove = __devexit_p(ads117x_platform_remove), + .probe = ads117x_probe, + .remove = __devexit_p(ads117x_remove), }; static int __init ads117x_init(void) diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h index dbcf50ec9bd1..3ce028614002 100644 --- a/sound/soc/codecs/ads117x.h +++ b/sound/soc/codecs/ads117x.h @@ -9,5 +9,5 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -extern struct snd_soc_dai ads117x_dai; -extern struct snd_soc_codec_device soc_codec_dev_ads117x; +extern struct snd_soc_dai_driver ads117x_dai; +extern struct snd_soc_codec_driver soc_codec_dev_ads117x; diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 192aebda3029..c27f8f59dc66 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -17,8 +17,6 @@ #include #include -#include "ak4104.h" - /* AK4104 registers addresses */ #define AK4104_REG_CONTROL1 0x00 #define AK4104_REG_RESERVED 0x01 @@ -45,11 +43,11 @@ #define AK4104_TX_TXE (1 << 0) #define AK4104_TX_V (1 << 1) -#define DRV_NAME "ak4104" +#define DRV_NAME "ak4104-codec" struct ak4104_private { - struct snd_soc_codec codec; - u8 reg_cache[AK4104_NUM_REGS]; + enum snd_soc_control_type control_type; + void *control_data; }; static int ak4104_fill_cache(struct snd_soc_codec *codec) @@ -58,7 +56,7 @@ static int ak4104_fill_cache(struct snd_soc_codec *codec) u8 *reg_cache = codec->reg_cache; struct spi_device *spi = codec->control_data; - for (i = 0; i < codec->reg_cache_size; i++) { + for (i = 0; i < codec->driver->reg_cache_size; i++) { int ret = spi_w8r8(spi, i | AK4104_READ); if (ret < 0) { dev_err(&spi->dev, "SPI write failure\n"); @@ -76,7 +74,7 @@ static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec, { u8 *reg_cache = codec->reg_cache; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -EINVAL; return reg_cache[reg]; @@ -88,7 +86,7 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg, u8 *cache = codec->reg_cache; struct spi_device *spi = codec->control_data; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -EINVAL; /* only write to the hardware if value has changed */ @@ -145,8 +143,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; int val = 0; /* set the IEC958 bits: consumer mode, no copyright bit */ @@ -178,8 +175,8 @@ static struct snd_soc_dai_ops ak4101_dai_ops = { .set_fmt = ak4104_set_dai_fmt, }; -struct snd_soc_dai ak4104_dai = { - .name = DRV_NAME, +static struct snd_soc_dai_driver ak4104_dai = { + .name = "ak4104-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -192,45 +189,17 @@ struct snd_soc_dai ak4104_dai = { .ops = &ak4101_dai_ops, }; -static struct snd_soc_codec *ak4104_codec; - -static int ak4104_spi_probe(struct spi_device *spi) +static int ak4104_probe(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec; - struct ak4104_private *ak4104; + struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); int ret, val; - spi->bits_per_word = 8; - spi->mode = SPI_MODE_0; - ret = spi_setup(spi); - if (ret < 0) - return ret; - - ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL); - if (!ak4104) { - dev_err(&spi->dev, "could not allocate codec\n"); - return -ENOMEM; - } - - codec = &ak4104->codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->dev = &spi->dev; - codec->name = DRV_NAME; - codec->owner = THIS_MODULE; - codec->dai = &ak4104_dai; - codec->num_dai = 1; - snd_soc_codec_set_drvdata(codec, ak4104); - codec->control_data = spi; - codec->reg_cache = ak4104->reg_cache; - codec->reg_cache_size = AK4104_NUM_REGS; + codec->control_data = ak4104->control_data; /* read all regs and fill the cache */ ret = ak4104_fill_cache(codec); if (ret < 0) { - dev_err(&spi->dev, "failed to fill register cache\n"); + dev_err(codec->dev, "failed to fill register cache\n"); return ret; } @@ -238,93 +207,81 @@ static int ak4104_spi_probe(struct spi_device *spi) * should contain 0x5b. Not a good way to verify the presence of * the device, but there is no hardware ID register. */ if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) != - AK4104_RESERVED_VAL) { - ret = -ENODEV; - goto error_free_codec; - } + AK4104_RESERVED_VAL) + return -ENODEV; /* set power-up and non-reset bits */ val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN; ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); if (ret < 0) - goto error_free_codec; + return ret; /* enable transmitter */ val = ak4104_read_reg_cache(codec, AK4104_REG_TX); val |= AK4104_TX_TXE; ret = ak4104_spi_write(codec, AK4104_REG_TX, val); if (ret < 0) - goto error_free_codec; - - ak4104_codec = codec; - ret = snd_soc_register_dai(&ak4104_dai); - if (ret < 0) { - dev_err(&spi->dev, "failed to register DAI\n"); - goto error_free_codec; - } + return ret; - spi_set_drvdata(spi, ak4104); - dev_info(&spi->dev, "SPI device initialized\n"); + dev_info(codec->dev, "SPI device initialized\n"); return 0; - -error_free_codec: - kfree(ak4104); - ak4104_dai.dev = NULL; - return ret; } -static int __devexit ak4104_spi_remove(struct spi_device *spi) +static int ak4104_remove(struct snd_soc_codec *codec) { - int ret, val; - struct ak4104_private *ak4104 = spi_get_drvdata(spi); + int val, ret; - val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1); + val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); if (val < 0) return val; /* clear power-up and non-reset bits */ val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); - ret = ak4104_spi_write(&ak4104->codec, AK4104_REG_CONTROL1, val); - if (ret < 0) - return ret; + ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); - ak4104_codec = NULL; - kfree(ak4104); - return 0; + return ret; } -static int ak4104_probe(struct platform_device *pdev) +static struct snd_soc_codec_driver soc_codec_device_ak4104 = { + .probe = ak4104_probe, + .remove = ak4104_remove, + .reg_cache_size = AK4104_NUM_REGS, + .reg_word_size = sizeof(u16), +}; + +static int ak4104_spi_probe(struct spi_device *spi) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = ak4104_codec; + struct ak4104_private *ak4104; int ret; - /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ - socdev->card->codec = codec; - - /* Register PCMs */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms\n"); + spi->bits_per_word = 8; + spi->mode = SPI_MODE_0; + ret = spi_setup(spi); + if (ret < 0) return ret; - } - return 0; + ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL); + if (ak4104 == NULL) + return -ENOMEM; + + ak4104->control_data = spi; + ak4104->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, ak4104); + + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_device_ak4104, &ak4104_dai, 1); + if (ret < 0) + kfree(ak4104); + return ret; } -static int ak4104_remove(struct platform_device *pdev) +static int __devexit ak4104_spi_remove(struct spi_device *spi) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - snd_soc_free_pcms(socdev); + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); return 0; -}; - -struct snd_soc_codec_device soc_codec_device_ak4104 = { - .probe = ak4104_probe, - .remove = ak4104_remove -}; -EXPORT_SYMBOL_GPL(soc_codec_device_ak4104); +} static struct spi_driver ak4104_spi_driver = { .driver = { diff --git a/sound/soc/codecs/ak4104.h b/sound/soc/codecs/ak4104.h deleted file mode 100644 index eb88fe7e4def..000000000000 --- a/sound/soc/codecs/ak4104.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _AK4104_H -#define _AK4104_H - -extern struct snd_soc_dai ak4104_dai; -extern struct snd_soc_codec_device soc_codec_device_ak4104; - -#endif diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index d4253675b2d3..cd88c8f32a38 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -31,11 +31,11 @@ #define AK4535_VERSION "0.3" -struct snd_soc_codec_device soc_codec_dev_ak4535; - /* codec private data */ struct ak4535_priv { unsigned int sysclk; + enum snd_soc_control_type control_type; + void *control_data; }; /* @@ -313,8 +313,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); int rate = params_rate(params), fs = 256; @@ -378,14 +377,16 @@ static int ak4535_mute(struct snd_soc_dai *dai, int mute) static int ak4535_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 i; + u16 i, mute_reg; switch (level) { case SND_SOC_BIAS_ON: - ak4535_mute(codec->dai, 0); + mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf; + ak4535_write(codec, AK4535_DAC, mute_reg); break; case SND_SOC_BIAS_PREPARE: - ak4535_mute(codec->dai, 1); + mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf; + ak4535_write(codec, AK4535_DAC, mute_reg | 0x20); break; case SND_SOC_BIAS_STANDBY: i = ak4535_read_reg_cache(codec, AK4535_PM1); @@ -413,8 +414,8 @@ static struct snd_soc_dai_ops ak4535_dai_ops = { .set_sysclk = ak4535_set_dai_sysclk, }; -struct snd_soc_dai ak4535_dai = { - .name = "AK4535", +static struct snd_soc_dai_driver ak4535_dai = { + .name = "ak4535-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -429,54 +430,27 @@ struct snd_soc_dai ak4535_dai = { .formats = SNDRV_PCM_FMTBIT_S16_LE,}, .ops = &ak4535_dai_ops, }; -EXPORT_SYMBOL_GPL(ak4535_dai); -static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) +static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int ak4535_resume(struct platform_device *pdev) +static int ak4535_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; ak4535_sync(codec); ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } -/* - * initialise the AK4535 driver - * register the mixer and dsp interfaces with the kernel - */ -static int ak4535_init(struct snd_soc_device *socdev) +static int ak4535_probe(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = socdev->card->codec; - int ret = 0; + struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); - codec->name = "AK4535"; - codec->owner = THIS_MODULE; - codec->read = ak4535_read_reg_cache; - codec->write = ak4535_write; - codec->set_bias_level = ak4535_set_bias_level; - codec->dai = &ak4535_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(ak4535_reg); - codec->reg_cache = kmemdup(ak4535_reg, sizeof(ak4535_reg), GFP_KERNEL); - - if (codec->reg_cache == NULL) - return -ENOMEM; + printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "ak4535: failed to create pcms\n"); - goto pcm_err; - } + codec->control_data = ak4535->control_data; /* power on device */ ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -485,39 +459,55 @@ static int ak4535_init(struct snd_soc_device *socdev) ARRAY_SIZE(ak4535_snd_controls)); ak4535_add_widgets(codec); - return ret; - -pcm_err: - kfree(codec->reg_cache); + return 0; +} - return ret; +/* power down chip */ +static int ak4535_remove(struct snd_soc_codec *codec) +{ + ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; } -static struct snd_soc_device *ak4535_socdev; +static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { + .probe = ak4535_probe, + .remove = ak4535_remove, + .suspend = ak4535_suspend, + .resume = ak4535_resume, + .read = ak4535_read_reg_cache, + .write = ak4535_write, + .set_bias_level = ak4535_set_bias_level, + .reg_cache_size = ARRAY_SIZE(ak4535_reg), + .reg_word_size = sizeof(u8), + .reg_cache_default = ak4535_reg, +}; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -static int ak4535_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static __devinit int ak4535_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - struct snd_soc_device *socdev = ak4535_socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct ak4535_priv *ak4535; int ret; - i2c_set_clientdata(i2c, codec); - codec->control_data = i2c; + ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL); + if (ak4535 == NULL) + return -ENOMEM; - ret = ak4535_init(socdev); - if (ret < 0) - printk(KERN_ERR "failed to initialise AK4535\n"); + i2c_set_clientdata(i2c, ak4535); + ak4535->control_data = i2c; + ak4535->control_type = SND_SOC_I2C; + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_ak4535, &ak4535_dai, 1); + if (ret < 0) + kfree(ak4535); return ret; } -static int ak4535_i2c_remove(struct i2c_client *client) +static __devexit int ak4535_i2c_remove(struct i2c_client *client) { - struct snd_soc_codec *codec = i2c_get_clientdata(client); - kfree(codec->reg_cache); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -529,138 +519,34 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id); static struct i2c_driver ak4535_i2c_driver = { .driver = { - .name = "AK4535 I2C Codec", + .name = "ak4535-codec", .owner = THIS_MODULE, }, .probe = ak4535_i2c_probe, - .remove = ak4535_i2c_remove, + .remove = __devexit_p(ak4535_i2c_remove), .id_table = ak4535_i2c_id, }; - -static int ak4535_add_i2c_device(struct platform_device *pdev, - const struct ak4535_setup_data *setup) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - int ret; - - ret = i2c_add_driver(&ak4535_i2c_driver); - if (ret != 0) { - dev_err(&pdev->dev, "can't add i2c driver\n"); - return ret; - } - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = setup->i2c_address; - strlcpy(info.type, "ak4535", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(setup->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "can't get i2c adapter %d\n", - setup->i2c_bus); - goto err_driver; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - goto err_driver; - } - - return 0; - -err_driver: - i2c_del_driver(&ak4535_i2c_driver); - return -ENODEV; -} #endif -static int ak4535_probe(struct platform_device *pdev) +static int __init ak4535_modinit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct ak4535_setup_data *setup; - struct snd_soc_codec *codec; - struct ak4535_priv *ak4535; - int ret; - - printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); - - setup = socdev->codec_data; - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) - return -ENOMEM; - - ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL); - if (ak4535 == NULL) { - kfree(codec); - return -ENOMEM; - } - - snd_soc_codec_set_drvdata(codec, ak4535); - socdev->card->codec = codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - ak4535_socdev = socdev; - ret = -ENODEV; - + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - if (setup->i2c_address) { - codec->hw_write = (hw_write_t)i2c_master_send; - ret = ak4535_add_i2c_device(pdev, setup); - } -#endif - + ret = i2c_add_driver(&ak4535_i2c_driver); if (ret != 0) { - kfree(snd_soc_codec_get_drvdata(codec)); - kfree(codec); + printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n", + ret); } +#endif return ret; } +module_init(ak4535_modinit); -/* power down chip */ -static int ak4535_remove(struct platform_device *pdev) +static void __exit ak4535_exit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->control_data) - ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - if (codec->control_data) - i2c_unregister_device(codec->control_data); i2c_del_driver(&ak4535_i2c_driver); #endif - kfree(snd_soc_codec_get_drvdata(codec)); - kfree(codec); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_ak4535 = { - .probe = ak4535_probe, - .remove = ak4535_remove, - .suspend = ak4535_suspend, - .resume = ak4535_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535); - -static int __init ak4535_modinit(void) -{ - return snd_soc_register_dai(&ak4535_dai); -} -module_init(ak4535_modinit); - -static void __exit ak4535_exit(void) -{ - snd_soc_unregister_dai(&ak4535_dai); } module_exit(ak4535_exit); diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h index c7a58703ea39..0431e5f634a2 100644 --- a/sound/soc/codecs/ak4535.h +++ b/sound/soc/codecs/ak4535.h @@ -36,12 +36,4 @@ #define AK4535_CACHEREGNUM 0x10 -struct ak4535_setup_data { - int i2c_bus; - unsigned short i2c_address; -}; - -extern struct snd_soc_dai ak4535_dai; -extern struct snd_soc_codec_device soc_codec_dev_ak4535; - #endif diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 3d7dc55305ec..31b35e967398 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -30,8 +30,6 @@ #include #include -#include "ak4642.h" - #define AK4642_VERSION "0.0.1" #define PW_MGMT1 0x00 @@ -102,7 +100,6 @@ #define FS3 (1 << 5) #define FS_MASK (FS0 | FS1 | FS2 | FS3) -struct snd_soc_codec_device soc_codec_dev_ak4642; /* * Playback Volume (table 39) @@ -123,11 +120,11 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = { /* codec private data */ struct ak4642_priv { - struct snd_soc_codec codec; + unsigned int sysclk; + enum snd_soc_control_type control_type; + void *control_data; }; -static struct snd_soc_codec *ak4642_codec; - /* * ak4642 register cache */ @@ -393,8 +390,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = { .hw_params = ak4642_dai_hw_params, }; -struct snd_soc_dai ak4642_dai = { - .name = "AK4642", +static struct snd_soc_dai_driver ak4642_dai = { + .name = "ak4642-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -410,112 +407,63 @@ struct snd_soc_dai ak4642_dai = { .ops = &ak4642_dai_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(ak4642_dai); -static int ak4642_resume(struct platform_device *pdev) +static int ak4642_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - ak4642_sync(codec); return 0; } -/* - * initialise the AK4642 driver - * register the mixer and dsp interfaces with the kernel - */ -static int ak4642_init(struct ak4642_priv *ak4642) + +static int ak4642_probe(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = &ak4642->codec; - int ret = 0; + struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec); - if (ak4642_codec) { - dev_err(codec->dev, "Another ak4642 is registered\n"); - return -EINVAL; - } + dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION); - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, ak4642); - codec->name = "AK4642"; - codec->owner = THIS_MODULE; - codec->read = ak4642_read_reg_cache; - codec->write = ak4642_write; - codec->dai = &ak4642_dai; - codec->num_dai = 1; codec->hw_write = (hw_write_t)i2c_master_send; - codec->reg_cache_size = ARRAY_SIZE(ak4642_reg); - codec->reg_cache = kmemdup(ak4642_reg, - sizeof(ak4642_reg), GFP_KERNEL); - - if (!codec->reg_cache) - return -ENOMEM; - - ak4642_dai.dev = codec->dev; - ak4642_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto reg_cache_err; - } + codec->control_data = ak4642->control_data; - ret = snd_soc_register_dai(&ak4642_dai); - if (ret) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - goto reg_cache_err; - } - - return ret; - -reg_cache_err: - kfree(codec->reg_cache); - codec->reg_cache = NULL; - return ret; + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { + .probe = ak4642_probe, + .resume = ak4642_resume, + .read = ak4642_read_reg_cache, + .write = ak4642_write, + .reg_cache_size = ARRAY_SIZE(ak4642_reg), + .reg_word_size = sizeof(u8), + .reg_cache_default = ak4642_reg, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static int ak4642_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { struct ak4642_priv *ak4642; - struct snd_soc_codec *codec; int ret; ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); - if (!ak4642) + if (ak4642 == NULL) return -ENOMEM; - codec = &ak4642->codec; - codec->dev = &i2c->dev; - i2c_set_clientdata(i2c, ak4642); - codec->control_data = i2c; + ak4642->control_data = i2c; + ak4642->control_type = SND_SOC_I2C; - ret = ak4642_init(ak4642); - if (ret < 0) { - printk(KERN_ERR "failed to initialise AK4642\n"); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_ak4642, &ak4642_dai, 1); + if (ret < 0) kfree(ak4642); - } - return ret; } -static int ak4642_i2c_remove(struct i2c_client *client) +static __devexit int ak4642_i2c_remove(struct i2c_client *client) { - struct ak4642_priv *ak4642 = i2c_get_clientdata(client); - - snd_soc_unregister_dai(&ak4642_dai); - snd_soc_unregister_codec(&ak4642->codec); - kfree(ak4642->codec.reg_cache); - kfree(ak4642); - ak4642_codec = NULL; - + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -528,64 +476,15 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); static struct i2c_driver ak4642_i2c_driver = { .driver = { - .name = "AK4642 I2C Codec", + .name = "ak4642-codec", .owner = THIS_MODULE, }, - .probe = ak4642_i2c_probe, - .remove = ak4642_i2c_remove, - .id_table = ak4642_i2c_id, + .probe = ak4642_i2c_probe, + .remove = __devexit_p(ak4642_i2c_remove), + .id_table = ak4642_i2c_id, }; - #endif -static int ak4642_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - int ret; - - if (!ak4642_codec) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = ak4642_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "ak4642: failed to create pcms\n"); - goto pcm_err; - } - - snd_soc_add_controls(ak4642_codec, ak4642_snd_controls, - ARRAY_SIZE(ak4642_snd_controls)); - - dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); - return ret; - -pcm_err: - return ret; - -} - -/* power down chip */ -static int ak4642_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_ak4642 = { - .probe = ak4642_probe, - .remove = ak4642_remove, - .resume = ak4642_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642); - static int __init ak4642_modinit(void) { int ret = 0; diff --git a/sound/soc/codecs/ak4642.h b/sound/soc/codecs/ak4642.h deleted file mode 100644 index e476833d314e..000000000000 --- a/sound/soc/codecs/ak4642.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * ak4642.h -- AK4642 Soc Audio driver - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Kuninori Morimoto - * - * Based on ak4535.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _AK4642_H -#define _AK4642_H - -extern struct snd_soc_dai ak4642_dai; -extern struct snd_soc_codec_device soc_codec_dev_ak4642; - -#endif diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 87566932a3b1..239f0562003c 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -23,11 +23,11 @@ #include "ak4671.h" -static struct snd_soc_codec *ak4671_codec; /* codec private data */ struct ak4671_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; u8 reg_cache[AK4671_CACHEREGNUM]; }; @@ -619,8 +619,8 @@ static struct snd_soc_dai_ops ak4671_dai_ops = { .set_fmt = ak4671_set_dai_fmt, }; -struct snd_soc_dai ak4671_dai = { - .name = "AK4671", +static struct snd_soc_dai_driver ak4671_dai = { + .name = "ak4671-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -635,27 +635,19 @@ struct snd_soc_dai ak4671_dai = { .formats = AK4671_FORMATS,}, .ops = &ak4671_dai_ops, }; -EXPORT_SYMBOL_GPL(ak4671_dai); -static int ak4671_probe(struct platform_device *pdev) +static int ak4671_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (ak4671_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } + struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec); + int ret; - socdev->card->codec = ak4671_codec; - codec = ak4671_codec; + codec->hw_write = (hw_write_t)i2c_master_send; + codec->bias_level = SND_SOC_BIAS_OFF; - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type); if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; } snd_soc_add_controls(codec, ak4671_snd_controls, @@ -665,121 +657,48 @@ static int ak4671_probe(struct platform_device *pdev) ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return ret; - -pcm_err: - return ret; } -static int ak4671_remove(struct platform_device *pdev) +static int ak4671_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - + ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -struct snd_soc_codec_device soc_codec_dev_ak4671 = { +static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { .probe = ak4671_probe, .remove = ak4671_remove, + .set_bias_level = ak4671_set_bias_level, + .reg_cache_size = AK4671_CACHEREGNUM, + .reg_word_size = sizeof(u8), + .reg_cache_default = ak4671_reg, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671); - -static int ak4671_register(struct ak4671_priv *ak4671, - enum snd_soc_control_type control) -{ - int ret; - struct snd_soc_codec *codec = &ak4671->codec; - - if (ak4671_codec) { - dev_err(codec->dev, "Another AK4671 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, ak4671); - codec->name = "AK4671"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = ak4671_set_bias_level; - codec->dai = &ak4671_dai; - codec->num_dai = 1; - codec->reg_cache_size = AK4671_CACHEREGNUM; - codec->reg_cache = &ak4671->reg_cache; - - memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg)); - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, control); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - ak4671_dai.dev = codec->dev; - ak4671_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&ak4671_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(ak4671); - return ret; -} - -static void ak4671_unregister(struct ak4671_priv *ak4671) -{ - ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&ak4671_dai); - snd_soc_unregister_codec(&ak4671->codec); - kfree(ak4671); - ak4671_codec = NULL; -} static int __devinit ak4671_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ak4671_priv *ak4671; - struct snd_soc_codec *codec; + int ret; ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL); if (ak4671 == NULL) return -ENOMEM; - codec = &ak4671->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - i2c_set_clientdata(client, ak4671); - codec->control_data = client; - - codec->dev = &client->dev; + ak4671->control_data = client; + ak4671->control_type = SND_SOC_I2C; - return ak4671_register(ak4671, SND_SOC_I2C); + ret = snd_soc_register_codec(&client->dev, + &soc_codec_dev_ak4671, &ak4671_dai, 1); + if (ret < 0) + kfree(ak4671); + return ret; } static __devexit int ak4671_i2c_remove(struct i2c_client *client) { - struct ak4671_priv *ak4671 = i2c_get_clientdata(client); - - ak4671_unregister(ak4671); - + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -791,7 +710,7 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id); static struct i2c_driver ak4671_i2c_driver = { .driver = { - .name = "ak4671", + .name = "ak4671-codec", .owner = THIS_MODULE, }, .probe = ak4671_i2c_probe, diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h index e2fad964e88b..61cb7ab7552c 100644 --- a/sound/soc/codecs/ak4671.h +++ b/sound/soc/codecs/ak4671.h @@ -150,7 +150,4 @@ /* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */ #define AK4671_MUTEN 0x04 -extern struct snd_soc_dai ak4671_dai; -extern struct snd_soc_codec_device soc_codec_dev_ak4671; - #endif diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index a320fb5a0e26..823643932dde 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -41,8 +42,6 @@ #include -#include "cq93vc.h" - static inline unsigned int cq93vc_read(struct snd_soc_codec *codec, unsigned int reg) { @@ -130,8 +129,8 @@ static struct snd_soc_dai_ops cq93vc_dai_ops = { .set_sysclk = cq93vc_set_dai_sysclk, }; -struct snd_soc_dai cq93vc_dai = { - .name = "CQ93VC", +static struct snd_soc_dai_driver cq93vc_dai = { + .name = "cq93vc-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -146,36 +145,20 @@ struct snd_soc_dai cq93vc_dai = { .formats = CQ93VC_FORMATS,}, .ops = &cq93vc_dai_ops, }; -EXPORT_SYMBOL_GPL(cq93vc_dai); -static int cq93vc_resume(struct platform_device *pdev) +static int cq93vc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } -static struct snd_soc_codec *cq93vc_codec; - -static int cq93vc_probe(struct platform_device *pdev) +static int cq93vc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct device *dev = &pdev->dev; - struct snd_soc_codec *codec; - int ret; - - socdev->card->codec = cq93vc_codec; - codec = socdev->card->codec; - - /* Register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(dev, "%s: failed to create pcms\n", pdev->name); - return ret; - } + struct davinci_vc *davinci_vc = codec->dev->platform_data; + + davinci_vc->cq93vc.codec = codec; + codec->control_data = davinci_vc; /* Set controls */ snd_soc_add_controls(codec, cq93vc_snd_controls, @@ -187,108 +170,51 @@ static int cq93vc_probe(struct platform_device *pdev) return 0; } -static int cq93vc_remove(struct platform_device *pdev) +static int cq93vc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); + cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -struct snd_soc_codec_device soc_codec_dev_cq93vc = { +static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { + .read = cq93vc_read, + .write = cq93vc_write, + .set_bias_level = cq93vc_set_bias_level, .probe = cq93vc_probe, .remove = cq93vc_remove, .resume = cq93vc_resume, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc); -static __init int cq93vc_codec_probe(struct platform_device *pdev) +static int cq93vc_platform_probe(struct platform_device *pdev) { - struct davinci_vc *davinci_vc = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret; - - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) { - dev_dbg(davinci_vc->dev, - "could not allocate memory for codec data\n"); - return -ENOMEM; - } - - davinci_vc->cq93vc.codec = codec; - - cq93vc_dai.dev = &pdev->dev; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - codec->dev = &pdev->dev; - codec->name = "CQ93VC"; - codec->owner = THIS_MODULE; - codec->read = cq93vc_read; - codec->write = cq93vc_write; - codec->set_bias_level = cq93vc_set_bias_level; - codec->dai = &cq93vc_dai; - codec->num_dai = 1; - codec->control_data = davinci_vc; - - cq93vc_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret) { - dev_err(davinci_vc->dev, "failed to register codec\n"); - goto fail1; - } - - ret = snd_soc_register_dai(&cq93vc_dai); - if (ret) { - dev_err(davinci_vc->dev, "could register dai\n"); - goto fail2; - } - return 0; - -fail2: - snd_soc_unregister_codec(codec); - -fail1: - kfree(codec); - cq93vc_codec = NULL; - - return ret; + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_cq93vc, &cq93vc_dai, 1); } -static int __devexit cq93vc_codec_remove(struct platform_device *pdev) +static int cq93vc_platform_remove(struct platform_device *pdev) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - snd_soc_unregister_dai(&cq93vc_dai); - snd_soc_unregister_codec(&codec); - - kfree(codec); - cq93vc_codec = NULL; - + snd_soc_unregister_codec(&pdev->dev); return 0; } static struct platform_driver cq93vc_codec_driver = { .driver = { - .name = "cq93vc", - .owner = THIS_MODULE, - }, - .probe = cq93vc_codec_probe, - .remove = __devexit_p(cq93vc_codec_remove), + .name = "cq93vc-codec", + .owner = THIS_MODULE, + }, + + .probe = cq93vc_platform_probe, + .remove = __devexit_p(cq93vc_platform_remove), }; -static __init int cq93vc_init(void) +static int __init cq93vc_init(void) { - return platform_driver_probe(&cq93vc_codec_driver, cq93vc_codec_probe); + return platform_driver_register(&cq93vc_codec_driver); } module_init(cq93vc_init); -static __exit void cq93vc_exit(void) +static void __exit cq93vc_exit(void) { platform_driver_unregister(&cq93vc_codec_driver); } diff --git a/sound/soc/codecs/cq93vc.h b/sound/soc/codecs/cq93vc.h deleted file mode 100644 index 845b1968ef9c..000000000000 --- a/sound/soc/codecs/cq93vc.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms - * - * Copyright (C) 2010 Texas Instruments, Inc - * - * Author: Miguel Aguilar - * - * 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 - */ - -#ifndef _CQ93VC_H -#define _CQ93VC_H - -extern struct snd_soc_dai cq93vc_dai; -extern struct snd_soc_codec_device soc_codec_dev_cq93vc; - -#endif diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 30d949239def..6542dc038951 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -31,8 +31,6 @@ #include #include -#include "cs4270.h" - /* * The codec isn't really big-endian or little-endian, since the I2S * interface requires data to be sent serially with the MSbit first. @@ -114,7 +112,8 @@ static const char *supply_names[] = { /* Private data for the CS4270 */ struct cs4270_private { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; u8 reg_cache[CS4270_NUMREGS]; unsigned int mclk; /* Input frequency of the MCLK pin */ unsigned int mode; /* The mode (I2S or left-justified) */ @@ -212,44 +211,8 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - unsigned int rates = 0; - unsigned int rate_min = -1; - unsigned int rate_max = 0; - unsigned int i; cs4270->mclk = freq; - - if (cs4270->mclk) { - for (i = 0; i < NUM_MCLK_RATIOS; i++) { - unsigned int rate = freq / cs4270_mode_ratios[i].ratio; - rates |= snd_pcm_rate_to_rate_bit(rate); - if (rate < rate_min) - rate_min = rate; - if (rate > rate_max) - rate_max = rate; - } - /* FIXME: soc should support a rate list */ - rates &= ~SNDRV_PCM_RATE_KNOT; - - if (!rates) { - dev_err(codec->dev, "could not find a valid sample rate\n"); - return -EINVAL; - } - } else { - /* enable all possible rates */ - rates = SNDRV_PCM_RATE_8000_192000; - rate_min = 8000; - rate_max = 192000; - } - - codec_dai->playback.rates = rates; - codec_dai->playback.rate_min = rate_min; - codec_dai->playback.rate_max = rate_max; - - codec_dai->capture.rates = rates; - codec_dai->capture.rate_min = rate_min; - codec_dai->capture.rate_max = rate_max; - return 0; } @@ -410,8 +373,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); int ret; unsigned int i; @@ -549,19 +511,6 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { snd_soc_get_volsw, cs4270_soc_put_mute), }; -/* - * cs4270_codec - global variable to store codec for the ASoC probe function - * - * If struct i2c_driver had a private_data field, we wouldn't need to use - * cs4270_codec. This is the only way to pass the codec structure from - * cs4270_i2c_probe() to cs4270_probe(). Unfortunately, there is no good - * way to synchronize these two functions. cs4270_i2c_probe() can be called - * multiple times before cs4270_probe() is called even once. So for now, we - * also only allow cs4270_i2c_probe() to be run once. That means that we do - * not support more than one cs4270 device in the system, at least for now. - */ -static struct snd_soc_codec *cs4270_codec; - static struct snd_soc_dai_ops cs4270_dai_ops = { .hw_params = cs4270_hw_params, .set_sysclk = cs4270_set_dai_sysclk, @@ -569,20 +518,24 @@ static struct snd_soc_dai_ops cs4270_dai_ops = { .digital_mute = cs4270_dai_mute, }; -struct snd_soc_dai cs4270_dai = { - .name = "cs4270", +struct snd_soc_dai_driver cs4270_dai = { + .name = "cs4270-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, .channels_max = 2, - .rates = 0, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 4000, + .rate_max = 216000, .formats = CS4270_FORMATS, }, .capture = { .stream_name = "Capture", .channels_min = 1, .channels_max = 2, - .rates = 0, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 4000, + .rate_max = 216000, .formats = CS4270_FORMATS, }, .ops = &cs4270_dai_ops, @@ -596,153 +549,19 @@ EXPORT_SYMBOL_GPL(cs4270_dai); * This function is called when ASoC has all the pieces it needs to * instantiate a sound driver. */ -static int cs4270_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = cs4270_codec; - struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - int i, ret; - - /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ - socdev->card->codec = codec; - - /* Register PCMs */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms\n"); - return ret; - } - - /* Add the non-DAPM controls */ - ret = snd_soc_add_controls(codec, cs4270_snd_controls, - ARRAY_SIZE(cs4270_snd_controls)); - if (ret < 0) { - dev_err(codec->dev, "failed to add controls\n"); - goto error_free_pcms; - } - - /* get the power supply regulators */ - for (i = 0; i < ARRAY_SIZE(supply_names); i++) - cs4270->supplies[i].supply = supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); - if (ret < 0) - goto error_free_pcms; - - ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); - if (ret < 0) - goto error_free_regulators; - - return 0; - -error_free_regulators: - regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); - -error_free_pcms: - snd_soc_free_pcms(socdev); - - return ret; -} - -/** - * cs4270_remove - ASoC remove function - * @pdev: platform device - * - * This function is the counterpart to cs4270_probe(). - */ -static int cs4270_remove(struct platform_device *pdev) +static int cs4270_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = cs4270_codec; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); + int i, ret, reg; - snd_soc_free_pcms(socdev); - regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); - regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); - - return 0; -}; - -/** - * cs4270_i2c_probe - initialize the I2C interface of the CS4270 - * @i2c_client: the I2C client object - * @id: the I2C device ID (ignored) - * - * This function is called whenever the I2C subsystem finds a device that - * matches the device ID given via a prior call to i2c_add_driver(). - */ -static int cs4270_i2c_probe(struct i2c_client *i2c_client, - const struct i2c_device_id *id) -{ - struct snd_soc_codec *codec; - struct cs4270_private *cs4270; - unsigned int reg; - int ret; - - /* For now, we only support one cs4270 device in the system. See the - * comment for cs4270_codec. - */ - if (cs4270_codec) { - dev_err(&i2c_client->dev, "ignoring CS4270 at addr %X\n", - i2c_client->addr); - dev_err(&i2c_client->dev, "only one per board allowed\n"); - /* Should we return something other than ENODEV here? */ - return -ENODEV; - } - - /* Verify that we have a CS4270 */ - - ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); - if (ret < 0) { - dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", - i2c_client->addr); - return ret; - } - /* The top four bits of the chip ID should be 1100. */ - if ((ret & 0xF0) != 0xC0) { - dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", - i2c_client->addr); - return -ENODEV; - } - - dev_info(&i2c_client->dev, "found device at i2c address %X\n", - i2c_client->addr); - dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); - - /* Allocate enough space for the snd_soc_codec structure - and our private data together. */ - cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); - if (!cs4270) { - dev_err(&i2c_client->dev, "could not allocate codec\n"); - return -ENOMEM; - } - codec = &cs4270->codec; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->dev = &i2c_client->dev; - codec->name = "CS4270"; - codec->owner = THIS_MODULE; - codec->dai = &cs4270_dai; - codec->num_dai = 1; - snd_soc_codec_set_drvdata(codec, cs4270); - codec->control_data = i2c_client; - codec->read = cs4270_read_reg_cache; - codec->write = cs4270_i2c_write; - codec->reg_cache = cs4270->reg_cache; - codec->reg_cache_size = CS4270_NUMREGS; + codec->control_data = cs4270->control_data; /* The I2C interface is set up, so pre-fill our register cache */ ret = cs4270_fill_cache(codec); if (ret < 0) { - dev_err(&i2c_client->dev, "failed to fill register cache\n"); - goto error_free_codec; + dev_err(codec->dev, "failed to fill register cache\n"); + return ret; } /* Disable auto-mute. This feature appears to be buggy. In some @@ -755,7 +574,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, reg &= ~CS4270_MUTE_AUTO; ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); if (ret < 0) { - dev_err(&i2c_client->dev, "i2c write failed\n"); + dev_err(codec->dev, "i2c write failed\n"); return ret; } @@ -769,65 +588,56 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); if (ret < 0) { - dev_err(&i2c_client->dev, "i2c write failed\n"); + dev_err(codec->dev, "i2c write failed\n"); return ret; } - /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI - * structure for each CS4270 device, but the machine driver needs to - * have a pointer to the DAI structure, so for now it must be a global - * variable. - */ - cs4270_dai.dev = &i2c_client->dev; - - /* Register the DAI. If all the other ASoC driver have already - * registered, then this will call our probe function, so - * cs4270_codec needs to be ready. - */ - cs4270_codec = codec; - ret = snd_soc_register_dai(&cs4270_dai); + /* Add the non-DAPM controls */ + ret = snd_soc_add_controls(codec, cs4270_snd_controls, + ARRAY_SIZE(cs4270_snd_controls)); if (ret < 0) { - dev_err(&i2c_client->dev, "failed to register DAIe\n"); - goto error_free_codec; + dev_err(codec->dev, "failed to add controls\n"); + return ret; } - i2c_set_clientdata(i2c_client, cs4270); + /* get the power supply regulators */ + for (i = 0; i < ARRAY_SIZE(supply_names); i++) + cs4270->supplies[i].supply = supply_names[i]; + + ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), + cs4270->supplies); + if (ret < 0) + return ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), + cs4270->supplies); + if (ret < 0) + goto error_free_regulators; return 0; -error_free_codec: - kfree(cs4270); - cs4270_codec = NULL; - cs4270_dai.dev = NULL; +error_free_regulators: + regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), + cs4270->supplies); return ret; } /** - * cs4270_i2c_remove - remove an I2C device - * @i2c_client: the I2C client object + * cs4270_remove - ASoC remove function + * @pdev: platform device * - * This function is the counterpart to cs4270_i2c_probe(). + * This function is the counterpart to cs4270_probe(). */ -static int cs4270_i2c_remove(struct i2c_client *i2c_client) +static int cs4270_remove(struct snd_soc_codec *codec) { - struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); + struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - kfree(cs4270); - cs4270_codec = NULL; - cs4270_dai.dev = NULL; + regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); + regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); return 0; -} - -/* - * cs4270_id - I2C device IDs supported by this driver - */ -static struct i2c_device_id cs4270_id[] = { - {"cs4270", 0}, - {} }; -MODULE_DEVICE_TABLE(i2c, cs4270_id); #ifdef CONFIG_PM @@ -840,9 +650,8 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id); * and all registers are written back to the hardware when resuming. */ -static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) +static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg) { - struct snd_soc_codec *codec = cs4270_codec; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); int reg, ret; @@ -860,9 +669,8 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) return 0; } -static int cs4270_soc_resume(struct platform_device *pdev) +static int cs4270_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = cs4270_codec; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); struct i2c_client *i2c_client = codec->control_data; int reg; @@ -895,6 +703,95 @@ static int cs4270_soc_resume(struct platform_device *pdev) #define cs4270_soc_resume NULL #endif /* CONFIG_PM */ +/* + * ASoC codec device structure + * + * Assign this variable to the codec_dev field of the machine driver's + * snd_soc_device structure. + */ +static struct snd_soc_codec_driver soc_codec_device_cs4270 = { + .probe = cs4270_probe, + .remove = cs4270_remove, + .suspend = cs4270_soc_suspend, + .resume = cs4270_soc_resume, + .read = cs4270_read_reg_cache, + .write = cs4270_i2c_write, + .reg_cache_size = CS4270_NUMREGS, + .reg_word_size = sizeof(u8), +}; + +/** + * cs4270_i2c_probe - initialize the I2C interface of the CS4270 + * @i2c_client: the I2C client object + * @id: the I2C device ID (ignored) + * + * This function is called whenever the I2C subsystem finds a device that + * matches the device ID given via a prior call to i2c_add_driver(). + */ +static int cs4270_i2c_probe(struct i2c_client *i2c_client, + const struct i2c_device_id *id) +{ + struct cs4270_private *cs4270; + int ret; + + /* Verify that we have a CS4270 */ + + ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); + if (ret < 0) { + dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", + i2c_client->addr); + return ret; + } + /* The top four bits of the chip ID should be 1100. */ + if ((ret & 0xF0) != 0xC0) { + dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", + i2c_client->addr); + return -ENODEV; + } + + dev_info(&i2c_client->dev, "found device at i2c address %X\n", + i2c_client->addr); + dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); + + cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); + if (!cs4270) { + dev_err(&i2c_client->dev, "could not allocate codec\n"); + return -ENOMEM; + } + + i2c_set_clientdata(i2c_client, cs4270); + cs4270->control_data = i2c_client; + cs4270->control_type = SND_SOC_I2C; + + ret = snd_soc_register_codec(&i2c_client->dev, + &soc_codec_device_cs4270, &cs4270_dai, 1); + if (ret < 0) + kfree(cs4270); + return ret; +} + +/** + * cs4270_i2c_remove - remove an I2C device + * @i2c_client: the I2C client object + * + * This function is the counterpart to cs4270_i2c_probe(). + */ +static int cs4270_i2c_remove(struct i2c_client *i2c_client) +{ + snd_soc_unregister_codec(&i2c_client->dev); + kfree(i2c_get_clientdata(i2c_client)); + return 0; +} + +/* + * cs4270_id - I2C device IDs supported by this driver + */ +static struct i2c_device_id cs4270_id[] = { + {"cs4270", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs4270_id); + /* * cs4270_i2c_driver - I2C device identification * @@ -903,7 +800,7 @@ static int cs4270_soc_resume(struct platform_device *pdev) */ static struct i2c_driver cs4270_i2c_driver = { .driver = { - .name = "cs4270", + .name = "cs4270-codec", .owner = THIS_MODULE, }, .id_table = cs4270_id, @@ -911,20 +808,6 @@ static struct i2c_driver cs4270_i2c_driver = { .remove = cs4270_i2c_remove, }; -/* - * ASoC codec device structure - * - * Assign this variable to the codec_dev field of the machine driver's - * snd_soc_device structure. - */ -struct snd_soc_codec_device soc_codec_device_cs4270 = { - .probe = cs4270_probe, - .remove = cs4270_remove, - .suspend = cs4270_soc_suspend, - .resume = cs4270_soc_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); - static int __init cs4270_init(void) { pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); diff --git a/sound/soc/codecs/cs4270.h b/sound/soc/codecs/cs4270.h deleted file mode 100644 index adc6cd9667d4..000000000000 --- a/sound/soc/codecs/cs4270.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Cirrus Logic CS4270 ALSA SoC Codec Driver - * - * Author: Timur Tabi - * - * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifndef _CS4270_H -#define _CS4270_H - -/* - * The ASoC codec DAI structure for the CS4270. Assign this structure to - * the .codec_dai field of your machine driver's snd_soc_dai_link structure. - */ -extern struct snd_soc_dai cs4270_dai; - -/* - * The ASoC codec device structure for the CS4270. Assign this structure - * to the .codec_dev field of your machine driver's snd_soc_device - * structure. - */ -extern struct snd_soc_codec_device soc_codec_device_cs4270; - -#endif diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index dd9b8550c402..8a25743870c2 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -42,15 +42,14 @@ enum master_slave_mode { }; struct cs42l51_private { + enum snd_soc_control_type control_type; + void *control_data; unsigned int mclk; unsigned int audio_mode; /* The mode (I2S or left-justified) */ enum master_slave_mode func; - struct snd_soc_codec codec; u8 reg_cache[CS42L51_NUMREGS]; }; -static struct snd_soc_codec *cs42l51_codec; - #define CS42L51_FORMATS ( \ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ @@ -75,134 +74,6 @@ static int cs42l51_fill_cache(struct snd_soc_codec *codec) return 0; } -static int cs42l51_i2c_probe(struct i2c_client *i2c_client, - const struct i2c_device_id *id) -{ - struct snd_soc_codec *codec; - struct cs42l51_private *cs42l51; - int ret = 0; - int reg; - - if (cs42l51_codec) - return -EBUSY; - - /* Verify that we have a CS42L51 */ - ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); - if (ret < 0) { - dev_err(&i2c_client->dev, "failed to read I2C\n"); - goto error; - } - - if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && - (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { - dev_err(&i2c_client->dev, "Invalid chip id\n"); - ret = -ENODEV; - goto error; - } - - dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", - ret & 7); - - cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL); - if (!cs42l51) { - dev_err(&i2c_client->dev, "could not allocate codec\n"); - return -ENOMEM; - } - codec = &cs42l51->codec; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->dev = &i2c_client->dev; - codec->name = "CS42L51"; - codec->owner = THIS_MODULE; - codec->dai = &cs42l51_dai; - codec->num_dai = 1; - snd_soc_codec_set_drvdata(codec, cs42l51); - - codec->control_data = i2c_client; - codec->reg_cache = cs42l51->reg_cache; - codec->reg_cache_size = CS42L51_NUMREGS; - i2c_set_clientdata(i2c_client, codec); - - ret = cs42l51_fill_cache(codec); - if (ret < 0) { - dev_err(&i2c_client->dev, "failed to fill register cache\n"); - goto error_alloc; - } - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); - if (ret < 0) { - dev_err(&i2c_client->dev, "Failed to set cache I/O: %d\n", ret); - goto error_alloc; - } - - /* - * DAC configuration - * - Use signal processor - * - auto mute - * - vol changes immediate - * - no de-emphasize - */ - reg = CS42L51_DAC_CTL_DATA_SEL(1) - | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0); - ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg); - if (ret < 0) - goto error_alloc; - - cs42l51_dai.dev = codec->dev; - cs42l51_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto error_alloc; - } - - ret = snd_soc_register_dai(&cs42l51_dai); - if (ret < 0) { - dev_err(&i2c_client->dev, "failed to register DAIe\n"); - goto error_reg; - } - - return 0; - -error_reg: - snd_soc_unregister_codec(codec); -error_alloc: - kfree(cs42l51); -error: - return ret; -} - -static int cs42l51_i2c_remove(struct i2c_client *client) -{ - struct cs42l51_private *cs42l51 = i2c_get_clientdata(client); - snd_soc_unregister_dai(&cs42l51_dai); - snd_soc_unregister_codec(cs42l51_codec); - cs42l51_codec = NULL; - kfree(cs42l51); - return 0; -} - - -static const struct i2c_device_id cs42l51_id[] = { - {"cs42l51", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, cs42l51_id); - -static struct i2c_driver cs42l51_i2c_driver = { - .driver = { - .name = "CS42L51 I2C", - .owner = THIS_MODULE, - }, - .id_table = cs42l51_id, - .probe = cs42l51_i2c_probe, - .remove = cs42l51_i2c_remove, -}; - static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -484,51 +355,8 @@ static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); - struct cs42l51_ratios *ratios = NULL; - int nr_ratios = 0; - unsigned int rates = 0; - unsigned int rate_min = -1; - unsigned int rate_max = 0; - int i; cs42l51->mclk = freq; - - switch (cs42l51->func) { - case MODE_MASTER: - return -EINVAL; - case MODE_SLAVE: - ratios = slave_ratios; - nr_ratios = ARRAY_SIZE(slave_ratios); - break; - case MODE_SLAVE_AUTO: - ratios = slave_auto_ratios; - nr_ratios = ARRAY_SIZE(slave_auto_ratios); - break; - } - - for (i = 0; i < nr_ratios; i++) { - unsigned int rate = freq / ratios[i].ratio; - rates |= snd_pcm_rate_to_rate_bit(rate); - if (rate < rate_min) - rate_min = rate; - if (rate > rate_max) - rate_max = rate; - } - rates &= ~SNDRV_PCM_RATE_KNOT; - - if (!rates) { - dev_err(codec->dev, "could not find a valid sample rate\n"); - return -EINVAL; - } - - codec_dai->playback.rates = rates; - codec_dai->playback.rate_min = rate_min; - codec_dai->playback.rate_max = rate_max; - - codec_dai->capture.rates = rates; - codec_dai->capture.rate_min = rate_min; - codec_dai->capture.rate_max = rate_max; - return 0; } @@ -537,8 +365,7 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); int ret; unsigned int i; @@ -670,8 +497,8 @@ static struct snd_soc_dai_ops cs42l51_dai_ops = { .digital_mute = cs42l51_dai_mute, }; -struct snd_soc_dai cs42l51_dai = { - .name = "CS42L51 HiFi", +static struct snd_soc_dai_driver cs42l51_dai = { + .name = "cs42l51-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -688,30 +515,39 @@ struct snd_soc_dai cs42l51_dai = { }, .ops = &cs42l51_dai_ops, }; -EXPORT_SYMBOL_GPL(cs42l51_dai); - -static int cs42l51_probe(struct platform_device *pdev) +static int cs42l51_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; + struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); + int ret, reg; - if (!cs42l51_codec) { - dev_err(&pdev->dev, "CS42L51 codec not yet registered\n"); - return -EINVAL; - } + codec->control_data = cs42l51->control_data; - socdev->card->codec = cs42l51_codec; - codec = socdev->card->codec; + ret = cs42l51_fill_cache(codec); + if (ret < 0) { + dev_err(codec->dev, "failed to fill register cache\n"); + return ret; + } - /* Register PCMs */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type); if (ret < 0) { - dev_err(&pdev->dev, "failed to create PCMs\n"); + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } + /* + * DAC configuration + * - Use signal processor + * - auto mute + * - vol changes immediate + * - no de-emphasize + */ + reg = CS42L51_DAC_CTL_DATA_SEL(1) + | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0); + ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg); + if (ret < 0) + return ret; + snd_soc_add_controls(codec, cs42l51_snd_controls, ARRAY_SIZE(cs42l51_snd_controls)); snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets, @@ -722,22 +558,77 @@ static int cs42l51_probe(struct platform_device *pdev) return 0; } +static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { + .probe = cs42l51_probe, + .reg_cache_size = CS42L51_NUMREGS, + .reg_word_size = sizeof(u8), +}; -static int cs42l51_remove(struct platform_device *pdev) +static int cs42l51_i2c_probe(struct i2c_client *i2c_client, + const struct i2c_device_id *id) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct cs42l51_private *cs42l51; + int ret; - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); + /* Verify that we have a CS42L51 */ + ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); + if (ret < 0) { + dev_err(&i2c_client->dev, "failed to read I2C\n"); + goto error; + } + + if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && + (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { + dev_err(&i2c_client->dev, "Invalid chip id\n"); + ret = -ENODEV; + goto error; + } + + dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", + ret & 7); + + cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL); + if (!cs42l51) { + dev_err(&i2c_client->dev, "could not allocate codec\n"); + return -ENOMEM; + } + + i2c_set_clientdata(i2c_client, cs42l51); + cs42l51->control_data = i2c_client; + cs42l51->control_type = SND_SOC_I2C; + ret = snd_soc_register_codec(&i2c_client->dev, + &soc_codec_device_cs42l51, &cs42l51_dai, 1); + if (ret < 0) + kfree(cs42l51); +error: + return ret; +} + +static int cs42l51_i2c_remove(struct i2c_client *client) +{ + struct cs42l51_private *cs42l51 = i2c_get_clientdata(client); + + snd_soc_unregister_codec(&client->dev); + kfree(cs42l51); return 0; } -struct snd_soc_codec_device soc_codec_device_cs42l51 = { - .probe = cs42l51_probe, - .remove = cs42l51_remove +static const struct i2c_device_id cs42l51_id[] = { + {"cs42l51", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs42l51_id); + +static struct i2c_driver cs42l51_i2c_driver = { + .driver = { + .name = "cs42L51-codec", + .owner = THIS_MODULE, + }, + .id_table = cs42l51_id, + .probe = cs42l51_i2c_probe, + .remove = cs42l51_i2c_remove, }; -EXPORT_SYMBOL_GPL(soc_codec_device_cs42l51); static int __init cs42l51_init(void) { diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h index 8f0bd9786ad2..2beeb171db4b 100644 --- a/sound/soc/codecs/cs42l51.h +++ b/sound/soc/codecs/cs42l51.h @@ -158,6 +158,4 @@ #define CS42L51_LASTREG 0x20 #define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1) -extern struct snd_soc_dai cs42l51_dai; -extern struct snd_soc_codec_device soc_codec_device_cs42l51; #endif diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index f07a415c753f..cf4323dbf9c4 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -24,7 +24,8 @@ struct cx20442_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; u8 reg_cache[1]; }; @@ -102,7 +103,7 @@ static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec, { u8 *reg_cache = codec->reg_cache; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -EINVAL; return reg_cache[reg]; @@ -164,16 +165,17 @@ static int cx20442_pm_to_v253_vsp(u8 value) static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { + struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); u8 *reg_cache = codec->reg_cache; int vls, vsp, old, len; char buf[18]; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -EINVAL; /* hw_write and control_data pointers required for talking to the modem * are expected to be set by the line discipline initialization code */ - if (!codec->hw_write || !codec->control_data) + if (!codec->hw_write || !cx20442->control_data) return -EIO; old = reg_cache[reg]; @@ -202,17 +204,13 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, return -ENOMEM; dev_dbg(codec->dev, "%s: %s\n", __func__, buf); - if (codec->hw_write(codec->control_data, buf, len) != len) + if (codec->hw_write(cx20442->control_data, buf, len) != len) return -EIO; return 0; } -/* Moved up here as line discipline referres it during initialization */ -static struct snd_soc_codec *cx20442_codec; - - /* * Line discpline related code * @@ -228,15 +226,15 @@ static const char *v253_init = "ate0m0q0+fclass=8\r"; /* Line discipline .open() */ static int v253_open(struct tty_struct *tty) { - struct snd_soc_codec *codec = cx20442_codec; int ret, len = strlen(v253_init); /* Doesn't make sense without write callback */ if (!tty->ops->write) return -EINVAL; - /* Pass the codec structure address for use by other ldisc callbacks */ - tty->disc_data = codec; + /* Won't work if no codec pointer has been passed by a card driver */ + if (!tty->disc_data) + return -ENODEV; if (tty->ops->write(tty, v253_init, len) != len) { ret = -EIO; @@ -253,15 +251,18 @@ err: static void v253_close(struct tty_struct *tty) { struct snd_soc_codec *codec = tty->disc_data; + struct cx20442_priv *cx20442; tty->disc_data = NULL; if (!codec) return; + cx20442 = snd_soc_codec_get_drvdata(codec); + /* Prevent the codec driver from further accessing the modem */ codec->hw_write = NULL; - codec->control_data = NULL; + cx20442->control_data = NULL; codec->pop_time = 0; } @@ -277,15 +278,18 @@ static void v253_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct snd_soc_codec *codec = tty->disc_data; + struct cx20442_priv *cx20442; if (!codec) return; - if (!codec->control_data) { + cx20442 = snd_soc_codec_get_drvdata(codec); + + if (!cx20442->control_data) { /* First modem response, complete setup procedure */ /* Set up codec driver access to modem controls */ - codec->control_data = tty; + cx20442->control_data = tty; codec->hw_write = (hw_write_t)tty->ops->write; codec->pop_time = 1; } @@ -313,8 +317,8 @@ EXPORT_SYMBOL_GPL(v253_ops); * Codec DAI */ -struct snd_soc_dai cx20442_dai = { - .name = "CX20442", +static struct snd_soc_dai_driver cx20442_dai = { + .name = "cx20442-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -330,142 +334,63 @@ struct snd_soc_dai cx20442_dai = { .formats = SNDRV_PCM_FMTBIT_S16_LE, }, }; -EXPORT_SYMBOL_GPL(cx20442_dai); -static int cx20442_codec_probe(struct platform_device *pdev) +static int cx20442_codec_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret; - - if (!cx20442_codec) { - dev_err(&pdev->dev, "cx20442 not yet discovered\n"); - return -ENODEV; - } - codec = cx20442_codec; - - socdev->card->codec = codec; + struct cx20442_priv *cx20442; - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(&pdev->dev, "failed to create pcms\n"); - goto pcm_err; - } + cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); + if (cx20442 == NULL) + return -ENOMEM; + snd_soc_codec_set_drvdata(codec, cx20442); cx20442_add_widgets(codec); -pcm_err: - return ret; + cx20442->control_data = NULL; + codec->hw_write = NULL; + codec->pop_time = 0; + + return 0; } /* power down chip */ -static int cx20442_codec_remove(struct platform_device *pdev) +static int cx20442_codec_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); + if (cx20442->control_data) { + struct tty_struct *tty = cx20442->control_data; + tty_hangup(tty); + } + kfree(cx20442); return 0; } -struct snd_soc_codec_device cx20442_codec_dev = { +static struct snd_soc_codec_driver cx20442_codec_dev = { .probe = cx20442_codec_probe, .remove = cx20442_codec_remove, + .reg_cache_size = 1, + .reg_word_size = sizeof(u8), + .read = cx20442_read_reg_cache, + .write = cx20442_write, }; -EXPORT_SYMBOL_GPL(cx20442_codec_dev); - -static int cx20442_register(struct cx20442_priv *cx20442) -{ - struct snd_soc_codec *codec = &cx20442->codec; - int ret; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "CX20442"; - codec->owner = THIS_MODULE; - snd_soc_codec_set_drvdata(codec, cx20442); - - codec->dai = &cx20442_dai; - codec->num_dai = 1; - - codec->reg_cache = &cx20442->reg_cache; - codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache); - codec->read = cx20442_read_reg_cache; - codec->write = cx20442_write; - - codec->bias_level = SND_SOC_BIAS_OFF; - - cx20442_dai.dev = codec->dev; - - cx20442_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&cx20442_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - cx20442_codec = NULL; - kfree(cx20442); - return ret; -} - -static void cx20442_unregister(struct cx20442_priv *cx20442) -{ - snd_soc_unregister_dai(&cx20442_dai); - snd_soc_unregister_codec(&cx20442->codec); - - cx20442_codec = NULL; - kfree(cx20442); -} static int cx20442_platform_probe(struct platform_device *pdev) { - struct cx20442_priv *cx20442; - struct snd_soc_codec *codec; - - cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); - if (cx20442 == NULL) - return -ENOMEM; - - codec = &cx20442->codec; - - codec->control_data = NULL; - codec->hw_write = NULL; - codec->pop_time = 0; - - codec->dev = &pdev->dev; - platform_set_drvdata(pdev, cx20442); - - return cx20442_register(cx20442); + return snd_soc_register_codec(&pdev->dev, + &cx20442_codec_dev, &cx20442_dai, 1); } static int __exit cx20442_platform_remove(struct platform_device *pdev) { - struct cx20442_priv *cx20442 = platform_get_drvdata(pdev); - - cx20442_unregister(cx20442); + snd_soc_unregister_codec(&pdev->dev); return 0; } static struct platform_driver cx20442_platform_driver = { .driver = { - .name = "cx20442", + .name = "cx20442-codec", .owner = THIS_MODULE, }, .probe = cx20442_platform_probe, @@ -487,4 +412,4 @@ module_exit(cx20442_exit); MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver"); MODULE_AUTHOR("Janusz Krzysztofik"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:cx20442"); +MODULE_ALIAS("platform:cx20442-codec"); diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h index 688a5eb62e17..c7a7c79ef0cd 100644 --- a/sound/soc/codecs/cx20442.h +++ b/sound/soc/codecs/cx20442.h @@ -13,8 +13,6 @@ #ifndef _CX20442_CODEC_H #define _CX20442_CODEC_H -extern struct snd_soc_dai cx20442_dai; -extern struct snd_soc_codec_device cx20442_codec_dev; extern struct tty_ldisc_ops v253_ops; #endif diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 3c51d6a57523..eabf3c062500 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -25,8 +25,6 @@ #include #include -#include "da7210.h" - /* DA7210 register space */ #define DA7210_STATUS 0x02 #define DA7210_STARTUP1 0x03 @@ -162,11 +160,10 @@ static const struct snd_kcontrol_new da7210_snd_controls[] = { /* Codec private data */ struct da7210_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; }; -static struct snd_soc_codec *da7210_codec; - /* * Register cache */ @@ -209,12 +206,12 @@ static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value) u8 *cache = codec->reg_cache; u8 data[2]; - BUG_ON(codec->volatile_register); + BUG_ON(codec->driver->volatile_register); data[0] = reg & 0xff; data[1] = value & 0xff; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -EIO; if (2 != codec->hw_write(codec->control_data, data, 2)) @@ -267,8 +264,7 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u32 dai_cfg1; u32 hpf_reg, hpf_mask, hpf_value; u32 fs, bypass; @@ -430,9 +426,8 @@ static struct snd_soc_dai_ops da7210_dai_ops = { .set_fmt = da7210_set_dai_fmt, }; -struct snd_soc_dai da7210_dai = { - .name = "DA7210 IIS", - .id = 0, +static struct snd_soc_dai_driver da7210_dai = { + .name = "da7210-hifi", /* playback capabilities */ .playback = { .stream_name = "Playback", @@ -452,55 +447,15 @@ struct snd_soc_dai da7210_dai = { .ops = &da7210_dai_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(da7210_dai); -/* - * Initialize the DA7210 driver - * register the mixer and dsp interfaces with the kernel - */ -static int da7210_init(struct da7210_priv *da7210) +static int da7210_probe(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = &da7210->codec; - int ret = 0; + struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec); - if (da7210_codec) { - dev_err(codec->dev, "Another da7210 is registered\n"); - return -EINVAL; - } + dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, da7210); - codec->name = "DA7210"; - codec->owner = THIS_MODULE; - codec->read = da7210_read; - codec->write = da7210_write; - codec->dai = &da7210_dai; - codec->num_dai = 1; + codec->control_data = da7210->control_data; codec->hw_write = (hw_write_t)i2c_master_send; - codec->reg_cache_size = ARRAY_SIZE(da7210_reg); - codec->reg_cache = kmemdup(da7210_reg, - sizeof(da7210_reg), GFP_KERNEL); - - if (!codec->reg_cache) - return -ENOMEM; - - da7210_dai.dev = codec->dev; - da7210_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret) { - dev_err(codec->dev, "Failed to register CODEC: %d\n", ret); - goto init_err; - } - - ret = snd_soc_register_dai(&da7210_dai); - if (ret) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto codec_err; - } /* FIXME * @@ -583,54 +538,50 @@ static int da7210_init(struct da7210_priv *da7210) /* Activate all enabled subsystem */ da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); - return ret; - -codec_err: - snd_soc_unregister_codec(codec); -init_err: - kfree(codec->reg_cache); - codec->reg_cache = NULL; + snd_soc_add_controls(codec, da7210_snd_controls, + ARRAY_SIZE(da7210_snd_controls)); - return ret; + dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_da7210 = { + .probe = da7210_probe, + .read = da7210_read, + .write = da7210_write, + .reg_cache_size = ARRAY_SIZE(da7210_reg), + .reg_word_size = sizeof(u8), + .reg_cache_default = da7210_reg, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static int __devinit da7210_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct da7210_priv *da7210; - struct snd_soc_codec *codec; int ret; da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL); if (!da7210) return -ENOMEM; - codec = &da7210->codec; - codec->dev = &i2c->dev; - i2c_set_clientdata(i2c, da7210); - codec->control_data = i2c; + da7210->control_data = i2c; + da7210->control_type = SND_SOC_I2C; - ret = da7210_init(da7210); - if (ret < 0) { - pr_err("Failed to initialise da7210 audio codec\n"); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_da7210, &da7210_dai, 1); + if (ret < 0) kfree(da7210); - } return ret; } static int __devexit da7210_i2c_remove(struct i2c_client *client) { - struct da7210_priv *da7210 = i2c_get_clientdata(client); - - snd_soc_unregister_dai(&da7210_dai); - kfree(da7210->codec.reg_cache); - kfree(da7210); - da7210_codec = NULL; - + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -643,7 +594,7 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id); /* I2C codec control layer */ static struct i2c_driver da7210_i2c_driver = { .driver = { - .name = "DA7210 I2C Codec", + .name = "da7210-codec", .owner = THIS_MODULE, }, .probe = da7210_i2c_probe, @@ -652,50 +603,6 @@ static struct i2c_driver da7210_i2c_driver = { }; #endif -static int da7210_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret; - - if (!da7210_codec) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = da7210_codec; - codec = da7210_codec; - - /* Register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) - goto pcm_err; - - snd_soc_add_controls(da7210_codec, da7210_snd_controls, - ARRAY_SIZE(da7210_snd_controls)); - - dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); - -pcm_err: - return ret; -} - -static int da7210_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_da7210 = { - .probe = da7210_probe, - .remove = da7210_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_da7210); - static int __init da7210_modinit(void) { int ret = 0; diff --git a/sound/soc/codecs/da7210.h b/sound/soc/codecs/da7210.h deleted file mode 100644 index 390d621eb742..000000000000 --- a/sound/soc/codecs/da7210.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * da7210.h -- audio driver for da7210 - * - * Copyright (c) 2009 Dialog Semiconductor - * Written by David Chen - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Cleanups by Kuninori Morimoto - * - * 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. - * - */ - -#ifndef _DA7210_H -#define _DA7210_H - -extern struct snd_soc_dai da7210_dai; -extern struct snd_soc_codec_device soc_codec_dev_da7210; - -#endif - diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 66557de1e4fe..16253ec9b022 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c @@ -74,29 +74,22 @@ static const uint32_t jz4740_codec_regs[] = { struct jz4740_codec { void __iomem *base; struct resource *mem; - - uint32_t reg_cache[2]; - struct snd_soc_codec codec; }; -static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec) -{ - return container_of(codec, struct jz4740_codec, codec); -} - static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, unsigned int reg) { - struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); + struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); return readl(jz4740_codec->base + (reg << 2)); } static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val) { - struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); + struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); + u32 *cache = codec->reg_cache; - jz4740_codec->reg_cache[reg] = val; + cache[reg] = val; writel(val, jz4740_codec->base + (reg << 2)); return 0; @@ -172,8 +165,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream, { uint32_t val; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec =rtd->codec; switch (params_rate(params)) { case 8000: @@ -219,8 +211,8 @@ static struct snd_soc_dai_ops jz4740_codec_dai_ops = { .hw_params = jz4740_codec_hw_params, }; -struct snd_soc_dai jz4740_codec_dai = { - .name = "jz4740", +static struct snd_soc_dai_driver jz4740_codec_dai = { + .name = "jz4740-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -238,7 +230,6 @@ struct snd_soc_dai jz4740_codec_dai = { .ops = &jz4740_codec_dai_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(jz4740_codec_dai); static void jz4740_codec_wakeup(struct snd_soc_codec *codec) { @@ -302,23 +293,10 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, return 0; } -static struct snd_soc_codec *jz4740_codec_codec; - -static int jz4740_codec_dev_probe(struct platform_device *pdev) +static int jz4740_codec_dev_probe(struct snd_soc_codec *codec) { - int ret; - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = jz4740_codec_codec; - - BUG_ON(!codec); - - socdev->card->codec = codec; - - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret) { - dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret); - return ret; - } + snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, + JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); snd_soc_add_controls(codec, jz4740_codec_controls, ARRAY_SIZE(jz4740_codec_controls)); @@ -331,34 +309,27 @@ static int jz4740_codec_dev_probe(struct platform_device *pdev) snd_soc_dapm_new_widgets(codec); + jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + return 0; } -static int jz4740_codec_dev_remove(struct platform_device *pdev) +static int jz4740_codec_dev_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); + jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } #ifdef CONFIG_PM_SLEEP -static int jz4740_codec_suspend(struct platform_device *pdev, pm_message_t state) +static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); } -static int jz4740_codec_resume(struct platform_device *pdev) +static int jz4740_codec_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); } @@ -367,19 +338,23 @@ static int jz4740_codec_resume(struct platform_device *pdev) #define jz4740_codec_resume NULL #endif -struct snd_soc_codec_device soc_codec_dev_jz4740_codec = { +static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = { .probe = jz4740_codec_dev_probe, .remove = jz4740_codec_dev_remove, .suspend = jz4740_codec_suspend, .resume = jz4740_codec_resume, + .read = jz4740_codec_read, + .write = jz4740_codec_write, + .set_bias_level = jz4740_codec_set_bias_level, + .reg_cache_default = jz4740_codec_regs, + .reg_word_size = sizeof(u32), + .reg_cache_size = 2, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec); static int __devinit jz4740_codec_probe(struct platform_device *pdev) { int ret; struct jz4740_codec *jz4740_codec; - struct snd_soc_codec *codec; struct resource *mem; jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL); @@ -408,55 +383,17 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev) } jz4740_codec->mem = mem; - jz4740_codec_dai.dev = &pdev->dev; - - codec = &jz4740_codec->codec; - - codec->dev = &pdev->dev; - codec->name = "jz4740"; - codec->owner = THIS_MODULE; - - codec->read = jz4740_codec_read; - codec->write = jz4740_codec_write; - codec->set_bias_level = jz4740_codec_set_bias_level; - codec->bias_level = SND_SOC_BIAS_OFF; - - codec->dai = &jz4740_codec_dai; - codec->num_dai = 1; - - codec->reg_cache = jz4740_codec->reg_cache; - codec->reg_cache_size = 2; - memcpy(codec->reg_cache, jz4740_codec_regs, sizeof(jz4740_codec_regs)); - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - jz4740_codec_codec = codec; - - snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); - platform_set_drvdata(pdev, jz4740_codec); - ret = snd_soc_register_codec(codec); + ret = snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1); if (ret) { dev_err(&pdev->dev, "Failed to register codec\n"); goto err_iounmap; } - ret = snd_soc_register_dai(&jz4740_codec_dai); - if (ret) { - dev_err(&pdev->dev, "Failed to register codec dai\n"); - goto err_unregister_codec; - } - - jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -err_unregister_codec: - snd_soc_unregister_codec(codec); err_iounmap: iounmap(jz4740_codec->base); err_release_mem_region: @@ -472,8 +409,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev) struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev); struct resource *mem = jz4740_codec->mem; - snd_soc_unregister_dai(&jz4740_codec_dai); - snd_soc_unregister_codec(&jz4740_codec->codec); + snd_soc_unregister_codec(&pdev->dev); iounmap(jz4740_codec->base); release_mem_region(mem->start, resource_size(mem)); diff --git a/sound/soc/codecs/jz4740.h b/sound/soc/codecs/jz4740.h deleted file mode 100644 index b5a0691be763..000000000000 --- a/sound/soc/codecs/jz4740.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2009, Lars-Peter Clausen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__ -#define __SND_SOC_CODECS_JZ4740_CODEC_H__ - -extern struct snd_soc_dai jz4740_codec_dai; -extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec; - -#endif diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 5a5f187a2657..bd8f26e41602 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c @@ -32,8 +32,8 @@ #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000) -struct snd_soc_dai pcm3008_dai = { - .name = "PCM3008 HiFi", +static struct snd_soc_dai_driver pcm3008_dai = { + .name = "pcm3008-hifi", .playback = { .stream_name = "PCM3008 Playback", .channels_min = 1, @@ -49,7 +49,6 @@ struct snd_soc_dai pcm3008_dai = { .formats = SNDRV_PCM_FMTBIT_S16_LE, }, }; -EXPORT_SYMBOL_GPL(pcm3008_dai); static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) { @@ -59,38 +58,13 @@ static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) gpio_free(setup->pdda_pin); } -static int pcm3008_soc_probe(struct platform_device *pdev) +static int pcm3008_soc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct pcm3008_setup_data *setup = socdev->codec_data; + struct pcm3008_setup_data *setup = codec->dev->platform_data; int ret = 0; printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); - socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (!socdev->card->codec) - return -ENOMEM; - - codec = socdev->card->codec; - mutex_init(&codec->mutex); - - codec->name = "PCM3008"; - codec->owner = THIS_MODULE; - codec->dai = &pcm3008_dai; - codec->num_dai = 1; - codec->write = NULL; - codec->read = NULL; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - /* Register PCMs. */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "pcm3008: failed to create pcms\n"); - goto pcm_err; - } - /* DEM1 DEM0 DE-EMPHASIS_MODE * Low Low De-emphasis 44.1 kHz ON * Low High De-emphasis OFF @@ -130,33 +104,22 @@ static int pcm3008_soc_probe(struct platform_device *pdev) gpio_err: pcm3008_gpio_free(setup); -pcm_err: - kfree(socdev->card->codec); return ret; } -static int pcm3008_soc_remove(struct platform_device *pdev) +static int pcm3008_soc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - struct pcm3008_setup_data *setup = socdev->codec_data; - - if (!codec) - return 0; + struct pcm3008_setup_data *setup = codec->dev->platform_data; pcm3008_gpio_free(setup); - snd_soc_free_pcms(socdev); - kfree(socdev->card->codec); - return 0; } #ifdef CONFIG_PM -static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg) +static int pcm3008_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct pcm3008_setup_data *setup = socdev->codec_data; + struct pcm3008_setup_data *setup = codec->dev->platform_data; gpio_set_value(setup->pdad_pin, 0); gpio_set_value(setup->pdda_pin, 0); @@ -164,10 +127,9 @@ static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg) return 0; } -static int pcm3008_soc_resume(struct platform_device *pdev) +static int pcm3008_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct pcm3008_setup_data *setup = socdev->codec_data; + struct pcm3008_setup_data *setup = codec->dev->platform_data; gpio_set_value(setup->pdad_pin, 1); gpio_set_value(setup->pdda_pin, 1); @@ -179,23 +141,45 @@ static int pcm3008_soc_resume(struct platform_device *pdev) #define pcm3008_soc_resume NULL #endif -struct snd_soc_codec_device soc_codec_dev_pcm3008 = { +static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = { .probe = pcm3008_soc_probe, .remove = pcm3008_soc_remove, .suspend = pcm3008_soc_suspend, .resume = pcm3008_soc_resume, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008); -static int __init pcm3008_init(void) +static int __devinit pcm3008_codec_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_pcm3008, &pcm3008_dai, 1); +} + +static int __devexit pcm3008_codec_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +MODULE_ALIAS("platform:pcm3008-codec"); + +static struct platform_driver pcm3008_codec_driver = { + .probe = pcm3008_codec_probe, + .remove = __devexit_p(pcm3008_codec_remove), + .driver = { + .name = "pcm3008-codec", + .owner = THIS_MODULE, + }, +}; + +static int __init pcm3008_modinit(void) { - return snd_soc_register_dai(&pcm3008_dai); + return platform_driver_register(&pcm3008_codec_driver); } -module_init(pcm3008_init); +module_init(pcm3008_modinit); static void __exit pcm3008_exit(void) { - snd_soc_unregister_dai(&pcm3008_dai); + platform_driver_unregister(&pcm3008_codec_driver); } module_exit(pcm3008_exit); diff --git a/sound/soc/codecs/pcm3008.h b/sound/soc/codecs/pcm3008.h index d04e87d3c060..7e5489ab4812 100644 --- a/sound/soc/codecs/pcm3008.h +++ b/sound/soc/codecs/pcm3008.h @@ -19,7 +19,4 @@ struct pcm3008_setup_data { unsigned pdda_pin; }; -extern struct snd_soc_codec_device soc_codec_dev_pcm3008; -extern struct snd_soc_dai pcm3008_dai; - #endif diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c index 9119836051a4..4c32b54913ad 100644 --- a/sound/soc/codecs/spdif_transciever.c +++ b/sound/soc/codecs/spdif_transciever.c @@ -21,57 +21,16 @@ #include #include -#include "spdif_transciever.h" - MODULE_LICENSE("GPL"); #define STUB_RATES SNDRV_PCM_RATE_8000_96000 #define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE -static struct snd_soc_codec *spdif_dit_codec; - -static int spdif_dit_codec_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret; - - if (spdif_dit_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = spdif_dit_codec; - codec = spdif_dit_codec; - - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto err_create_pcms; - } - - return 0; - -err_create_pcms: - return ret; -} - -static int spdif_dit_codec_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - - return 0; -} -struct snd_soc_codec_device soc_codec_dev_spdif_dit = { - .probe = spdif_dit_codec_probe, - .remove = spdif_dit_codec_remove, -}; EXPORT_SYMBOL_GPL(soc_codec_dev_spdif_dit); +static struct snd_soc_codec_driver soc_codec_spdif_dit; -struct snd_soc_dai dit_stub_dai = { - .name = "DIT", +static struct snd_soc_dai_driver dit_stub_dai = { + .name = "dit-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -80,65 +39,16 @@ struct snd_soc_dai dit_stub_dai = { .formats = STUB_FORMATS, }, }; -EXPORT_SYMBOL_GPL(dit_stub_dai); static int spdif_dit_probe(struct platform_device *pdev) { - struct snd_soc_codec *codec; - int ret; - - if (spdif_dit_codec) { - dev_err(&pdev->dev, "Another Codec is registered\n"); - ret = -EINVAL; - goto err_reg_codec; - } - - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) - return -ENOMEM; - - codec->dev = &pdev->dev; - - mutex_init(&codec->mutex); - - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "spdif-dit"; - codec->owner = THIS_MODULE; - codec->dai = &dit_stub_dai; - codec->num_dai = 1; - - spdif_dit_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_reg_codec; - } - - dit_stub_dai.dev = &pdev->dev; - ret = snd_soc_register_dai(&dit_stub_dai); - if (ret < 0) { - dev_err(codec->dev, "Failed to register dai: %d\n", ret); - goto err_reg_dai; - } - - return 0; - -err_reg_dai: - snd_soc_unregister_codec(codec); -err_reg_codec: - kfree(spdif_dit_codec); - return ret; + return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit, + &dit_stub_dai, 1); } static int spdif_dit_remove(struct platform_device *pdev) { - snd_soc_unregister_dai(&dit_stub_dai); - snd_soc_unregister_codec(spdif_dit_codec); - kfree(spdif_dit_codec); - spdif_dit_codec = NULL; + snd_soc_unregister_codec(&pdev->dev); return 0; } diff --git a/sound/soc/codecs/spdif_transciever.h b/sound/soc/codecs/spdif_transciever.h deleted file mode 100644 index 1e102124f546..000000000000 --- a/sound/soc/codecs/spdif_transciever.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * ALSA SoC DIT/DIR driver header - * - * Author: Steve Chen, - * Copyright: (C) 2008 MontaVista Software, Inc., - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef CODEC_STUBS_H -#define CODEC_STUBS_H - -extern struct snd_soc_codec_device soc_codec_dev_spdif_dit; -extern struct snd_soc_dai dit_stub_dai; - -#endif /* CODEC_STUBS_H */ diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index b47ed4f6ab20..67d8c044ca04 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -45,11 +45,11 @@ #define SSM2602_VERSION "0.1" -struct snd_soc_codec_device soc_codec_dev_ssm2602; - /* codec private data */ struct ssm2602_priv { unsigned int sysclk; + enum snd_soc_control_type control_type; + void *control_data; struct snd_pcm_substream *master_substream; struct snd_pcm_substream *slave_substream; }; @@ -276,8 +276,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, { u16 srate; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); struct i2c_client *i2c = codec->control_data; u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; @@ -321,8 +320,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); struct i2c_client *i2c = codec->control_data; struct snd_pcm_runtime *master_runtime; @@ -360,8 +358,7 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; /* set active */ ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); @@ -372,8 +369,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); /* deactivate */ @@ -518,8 +514,8 @@ static struct snd_soc_dai_ops ssm2602_dai_ops = { .set_fmt = ssm2602_set_dai_fmt, }; -struct snd_soc_dai ssm2602_dai = { - .name = "SSM2602", +static struct snd_soc_dai_driver ssm2602_dai = { + .name = "ssm2602-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -534,21 +530,15 @@ struct snd_soc_dai ssm2602_dai = { .formats = SSM2602_FORMATS,}, .ops = &ssm2602_dai_ops, }; -EXPORT_SYMBOL_GPL(ssm2602_dai); -static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) +static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int ssm2602_resume(struct platform_device *pdev) +static int ssm2602_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -563,36 +553,18 @@ static int ssm2602_resume(struct platform_device *pdev) return 0; } -/* - * initialise the ssm2602 driver - * register the mixer and dsp interfaces with the kernel - */ -static int ssm2602_init(struct snd_soc_device *socdev) +static int ssm2602_probe(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = socdev->card->codec; - int reg, ret = 0; - - codec->name = "SSM2602"; - codec->owner = THIS_MODULE; - codec->read = ssm2602_read_reg_cache; - codec->write = ssm2602_write; - codec->set_bias_level = ssm2602_set_bias_level; - codec->dai = &ssm2602_dai; - codec->num_dai = 1; - codec->reg_cache_size = sizeof(ssm2602_reg); - codec->reg_cache = kmemdup(ssm2602_reg, sizeof(ssm2602_reg), - GFP_KERNEL); - if (codec->reg_cache == NULL) - return -ENOMEM; + struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); + int ret = 0, reg; + + pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); + + codec->bias_level = SND_SOC_BIAS_OFF, + codec->control_data = ssm2602->control_data; ssm2602_reset(codec); - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - pr_err("ssm2602: failed to create pcms\n"); - goto pcm_err; - } /*power on device*/ ssm2602_write(codec, SSM2602_ACTIVE, 0); /* set the update bits */ @@ -614,13 +586,27 @@ static int ssm2602_init(struct snd_soc_device *socdev) ssm2602_add_widgets(codec); return ret; +} -pcm_err: - kfree(codec->reg_cache); - return ret; +/* remove everything here */ +static int ssm2602_remove(struct snd_soc_codec *codec) +{ + ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; } -static struct snd_soc_device *ssm2602_socdev; +static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { + .probe = ssm2602_probe, + .remove = ssm2602_remove, + .suspend = ssm2602_suspend, + .resume = ssm2602_resume, + .read = ssm2602_read_reg_cache, + .write = ssm2602_write, + .set_bias_level = ssm2602_set_bias_level, + .reg_cache_size = sizeof(ssm2602_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = ssm2602_reg, +}; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) /* @@ -632,24 +618,28 @@ static struct snd_soc_device *ssm2602_socdev; static int ssm2602_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct snd_soc_device *socdev = ssm2602_socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct ssm2602_priv *ssm2602; int ret; - i2c_set_clientdata(i2c, codec); - codec->control_data = i2c; + ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); + if (ssm2602 == NULL) + return -ENOMEM; - ret = ssm2602_init(socdev); - if (ret < 0) - pr_err("failed to initialise SSM2602\n"); + i2c_set_clientdata(i2c, ssm2602); + ssm2602->control_data = i2c; + ssm2602->control_type = SND_SOC_I2C; + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_ssm2602, &ssm2602_dai, 1); + if (ret < 0) + kfree(ssm2602); return ret; } static int ssm2602_i2c_remove(struct i2c_client *client) { - struct snd_soc_codec *codec = i2c_get_clientdata(client); - kfree(codec->reg_cache); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -658,130 +648,39 @@ static const struct i2c_device_id ssm2602_i2c_id[] = { { } }; MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); + /* corgi i2c codec control layer */ static struct i2c_driver ssm2602_i2c_driver = { .driver = { - .name = "SSM2602 I2C Codec", + .name = "ssm2602-codec", .owner = THIS_MODULE, }, .probe = ssm2602_i2c_probe, .remove = ssm2602_i2c_remove, .id_table = ssm2602_i2c_id, }; - -static int ssm2602_add_i2c_device(struct platform_device *pdev, - const struct ssm2602_setup_data *setup) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - int ret; - - ret = i2c_add_driver(&ssm2602_i2c_driver); - if (ret != 0) { - dev_err(&pdev->dev, "can't add i2c driver\n"); - return ret; - } - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = setup->i2c_address; - strlcpy(info.type, "ssm2602", I2C_NAME_SIZE); - adapter = i2c_get_adapter(setup->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "can't get i2c adapter %d\n", - setup->i2c_bus); - goto err_driver; - } - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - goto err_driver; - } - return 0; -err_driver: - i2c_del_driver(&ssm2602_i2c_driver); - return -ENODEV; -} #endif -static int ssm2602_probe(struct platform_device *pdev) + +static int __init ssm2602_modinit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct ssm2602_setup_data *setup; - struct snd_soc_codec *codec; - struct ssm2602_priv *ssm2602; int ret = 0; - - pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); - - setup = socdev->codec_data; - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) - return -ENOMEM; - - ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); - if (ssm2602 == NULL) { - kfree(codec); - return -ENOMEM; - } - - snd_soc_codec_set_drvdata(codec, ssm2602); - socdev->card->codec = codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - ssm2602_socdev = socdev; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - if (setup->i2c_address) { - codec->hw_write = (hw_write_t)i2c_master_send; - ret = ssm2602_add_i2c_device(pdev, setup); + ret = i2c_add_driver(&ssm2602_i2c_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register SSM2602 I2C driver: %d\n", + ret); } -#else - /* other interfaces */ #endif return ret; } +module_init(ssm2602_modinit); -/* remove everything here */ -static int ssm2602_remove(struct platform_device *pdev) +static void __exit ssm2602_exit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->control_data) - ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_unregister_device(codec->control_data); i2c_del_driver(&ssm2602_i2c_driver); #endif - kfree(snd_soc_codec_get_drvdata(codec)); - kfree(codec); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_ssm2602 = { - .probe = ssm2602_probe, - .remove = ssm2602_remove, - .suspend = ssm2602_suspend, - .resume = ssm2602_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602); - -static int __init ssm2602_modinit(void) -{ - return snd_soc_register_dai(&ssm2602_dai); -} -module_init(ssm2602_modinit); - -static void __exit ssm2602_exit(void) -{ - snd_soc_unregister_dai(&ssm2602_dai); } module_exit(ssm2602_exit); diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h index f344e6d76e31..42a47d0f8e25 100644 --- a/sound/soc/codecs/ssm2602.h +++ b/sound/soc/codecs/ssm2602.h @@ -124,7 +124,4 @@ struct ssm2602_setup_data { unsigned short i2c_address; }; -extern struct snd_soc_dai ssm2602_dai; -extern struct snd_soc_codec_device soc_codec_dev_ssm2602; - #endif diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index ee86568545c2..00d67cc8e206 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "stac9766.h" @@ -257,20 +256,15 @@ static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) return 0; } -static int stac9766_codec_suspend(struct platform_device *pdev, +static int stac9766_codec_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int stac9766_codec_resume(struct platform_device *pdev) +static int stac9766_codec_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; u16 id, reset; reset = 0; @@ -300,10 +294,9 @@ static struct snd_soc_dai_ops stac9766_dai_ops_digital = { .prepare = ac97_digital_prepare, }; -struct snd_soc_dai stac9766_dai[] = { +static struct snd_soc_dai_driver stac9766_dai[] = { { - .name = "stac9766 analog", - .id = 0, + .name = "stac9766-hifi-analog", .ac97_control = 1, /* stream cababilities */ @@ -325,8 +318,7 @@ struct snd_soc_dai stac9766_dai[] = { .ops = &stac9766_dai_ops_analog, }, { - .name = "stac9766 IEC958", - .id = 1, + .name = "stac9766-hifi-IEC958", .ac97_control = 1, /* stream cababilities */ @@ -342,57 +334,24 @@ struct snd_soc_dai stac9766_dai[] = { .ops = &stac9766_dai_ops_digital, } }; -EXPORT_SYMBOL_GPL(stac9766_dai); -static int stac9766_codec_probe(struct platform_device *pdev) +static int stac9766_codec_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; int ret = 0; printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); - socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->card->codec == NULL) - return -ENOMEM; - codec = socdev->card->codec; - mutex_init(&codec->mutex); - - codec->reg_cache = kmemdup(stac9766_reg, sizeof(stac9766_reg), - GFP_KERNEL); - if (codec->reg_cache == NULL) { - ret = -ENOMEM; - goto cache_err; - } - codec->reg_cache_size = sizeof(stac9766_reg); - codec->reg_cache_step = 2; - - codec->name = "STAC9766"; - codec->owner = THIS_MODULE; - codec->dai = stac9766_dai; - codec->num_dai = ARRAY_SIZE(stac9766_dai); - codec->write = stac9766_ac97_write; - codec->read = stac9766_ac97_read; - codec->set_bias_level = stac9766_set_bias_level; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) goto codec_err; - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) - goto pcm_err; - /* do a cold reset for the controller and then try * a warm reset followed by an optional cold reset for codec */ stac9766_reset(codec, 0); ret = stac9766_reset(codec, 1); if (ret < 0) { printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n"); - goto reset_err; + goto codec_err; } stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -402,40 +361,63 @@ static int stac9766_codec_probe(struct platform_device *pdev) return 0; -reset_err: - snd_soc_free_pcms(socdev); -pcm_err: - snd_soc_free_ac97_codec(codec); codec_err: - kfree(snd_soc_codec_get_drvdata(codec)); -cache_err: - kfree(socdev->card->codec); - socdev->card->codec = NULL; + snd_soc_free_ac97_codec(codec); return ret; } -static int stac9766_codec_remove(struct platform_device *pdev) +static int stac9766_codec_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec == NULL) - return 0; - - snd_soc_free_pcms(socdev); snd_soc_free_ac97_codec(codec); - kfree(codec->reg_cache); - kfree(codec); return 0; } -struct snd_soc_codec_device soc_codec_dev_stac9766 = { +static struct snd_soc_codec_driver soc_codec_dev_stac9766 = { + .write = stac9766_ac97_write, + .read = stac9766_ac97_read, + .set_bias_level = stac9766_set_bias_level, .probe = stac9766_codec_probe, .remove = stac9766_codec_remove, .suspend = stac9766_codec_suspend, .resume = stac9766_codec_resume, + .reg_cache_size = sizeof(stac9766_reg), + .reg_word_size = sizeof(u16), + .reg_cache_step = 2, +}; + +static __devinit int stac9766_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai)); +} + +static int __devexit stac9766_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static struct platform_driver stac9766_codec_driver = { + .driver = { + .name = "stac9766-codec", + .owner = THIS_MODULE, + }, + + .probe = stac9766_probe, + .remove = __devexit_p(stac9766_remove), }; -EXPORT_SYMBOL_GPL(soc_codec_dev_stac9766); + +static int __init stac9766_init(void) +{ + return platform_driver_register(&stac9766_codec_driver); +} +module_init(stac9766_init); + +static void __exit stac9766_exit(void) +{ + platform_driver_unregister(&stac9766_codec_driver); +} +module_exit(stac9766_exit); MODULE_DESCRIPTION("ASoC stac9766 driver"); MODULE_AUTHOR("Jon Smirl "); diff --git a/sound/soc/codecs/stac9766.h b/sound/soc/codecs/stac9766.h index 65642eb8393e..c726f907e2c0 100644 --- a/sound/soc/codecs/stac9766.h +++ b/sound/soc/codecs/stac9766.h @@ -14,8 +14,4 @@ #define STAC9766_DAI_AC97_ANALOG 0 #define STAC9766_DAI_AC97_DIGITAL 1 -extern struct snd_soc_dai stac9766_dai[]; -extern struct snd_soc_codec_device soc_codec_dev_stac9766; - - #endif diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 0a4b0fef3355..e8652b1ae326 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -240,7 +240,8 @@ static const struct snd_soc_dapm_route intercon[] = { /* AIC23 driver data */ struct aic23 { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; int mclk; int requested_adc; int requested_dac; @@ -404,11 +405,10 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u16 iface_reg; int ret; - struct aic23 *aic23 = container_of(codec, struct aic23, codec); + struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); u32 sample_rate_adc = aic23->requested_adc; u32 sample_rate_dac = aic23->requested_dac; u32 sample_rate = params_rate(params); @@ -452,8 +452,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; /* set active */ tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); @@ -465,9 +464,8 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - struct aic23 *aic23 = container_of(codec, struct aic23, codec); + struct snd_soc_codec *codec = rtd->codec; + struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); /* deactivate */ if (!codec->active) { @@ -546,8 +544,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) { - struct snd_soc_codec *codec = codec_dai->codec; - struct aic23 *aic23 = container_of(codec, struct aic23, codec); + struct aic23 *aic23 = snd_soc_dai_get_drvdata(codec_dai); aic23->mclk = freq; return 0; } @@ -594,8 +591,8 @@ static struct snd_soc_dai_ops tlv320aic23_dai_ops = { .set_sysclk = tlv320aic23_set_dai_sysclk, }; -struct snd_soc_dai tlv320aic23_dai = { - .name = "tlv320aic23", +static struct snd_soc_dai_driver tlv320aic23_dai = { + .name = "tlv320aic23-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -610,23 +607,17 @@ struct snd_soc_dai tlv320aic23_dai = { .formats = AIC23_FORMATS,}, .ops = &tlv320aic23_dai_ops, }; -EXPORT_SYMBOL_GPL(tlv320aic23_dai); -static int tlv320aic23_suspend(struct platform_device *pdev, +static int tlv320aic23_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int tlv320aic23_resume(struct platform_device *pdev) +static int tlv320aic23_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; u16 reg; /* Sync reg_cache with the hardware */ @@ -639,39 +630,19 @@ static int tlv320aic23_resume(struct platform_device *pdev) return 0; } -/* - * initialise the AIC23 driver - * register the mixer and dsp interfaces with the kernel - */ -static int tlv320aic23_init(struct snd_soc_device *socdev) +static int tlv320aic23_probe(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = socdev->card->codec; - int ret = 0; - u16 reg; + struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); + int reg; - codec->name = "tlv320aic23"; - codec->owner = THIS_MODULE; - codec->read = tlv320aic23_read_reg_cache; - codec->write = tlv320aic23_write; - codec->set_bias_level = tlv320aic23_set_bias_level; - codec->dai = &tlv320aic23_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg); - codec->reg_cache = - kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL); - if (codec->reg_cache == NULL) - return -ENOMEM; + printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); + codec->control_data = aic23->control_data; + codec->hw_write = (hw_write_t)i2c_master_send; + codec->hw_read = NULL; /* Reset codec */ tlv320aic23_write(codec, TLV320AIC23_RESET, 0); - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "tlv320aic23: failed to create pcms\n"); - goto pcm_err; - } - /* power on device */ tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -707,13 +678,27 @@ static int tlv320aic23_init(struct snd_soc_device *socdev) ARRAY_SIZE(tlv320aic23_snd_controls)); tlv320aic23_add_widgets(codec); - return ret; + return 0; +} -pcm_err: - kfree(codec->reg_cache); - return ret; +static int tlv320aic23_remove(struct snd_soc_codec *codec) +{ + tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; } -static struct snd_soc_device *tlv320aic23_socdev; + +static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { + .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = tlv320aic23_reg, + .probe = tlv320aic23_probe, + .remove = tlv320aic23_remove, + .suspend = tlv320aic23_suspend, + .resume = tlv320aic23_resume, + .read = tlv320aic23_read_reg_cache, + .write = tlv320aic23_write, + .set_bias_level = tlv320aic23_set_bias_level, +}; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) /* @@ -723,31 +708,30 @@ static struct snd_soc_device *tlv320aic23_socdev; static int tlv320aic23_codec_probe(struct i2c_client *i2c, const struct i2c_device_id *i2c_id) { - struct snd_soc_device *socdev = tlv320aic23_socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct aic23 *aic23; int ret; if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EINVAL; - i2c_set_clientdata(i2c, codec); - codec->control_data = i2c; + aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL); + if (aic23 == NULL) + return -ENOMEM; - ret = tlv320aic23_init(socdev); - if (ret < 0) { - printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n"); - goto err; - } - return ret; + i2c_set_clientdata(i2c, aic23); + aic23->control_data = i2c; + aic23->control_type = SND_SOC_I2C; -err: - kfree(codec); - kfree(i2c); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); + if (ret < 0) + kfree(aic23); return ret; } static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) { - put_device(&i2c->dev); + snd_soc_unregister_codec(&i2c->dev); + kfree(i2c_get_clientdata(i2c)); return 0; } @@ -760,7 +744,7 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); static struct i2c_driver tlv320aic23_i2c_driver = { .driver = { - .name = "tlv320aic23", + .name = "tlv320aic23-codec", }, .probe = tlv320aic23_codec_probe, .remove = __exit_p(tlv320aic23_i2c_remove), @@ -769,71 +753,25 @@ static struct i2c_driver tlv320aic23_i2c_driver = { #endif -static int tlv320aic23_probe(struct platform_device *pdev) +static int __init tlv320aic23_modinit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct aic23 *aic23; - int ret = 0; - - printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); - - aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL); - if (aic23 == NULL) - return -ENOMEM; - codec = &aic23->codec; - socdev->card->codec = codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - tlv320aic23_socdev = socdev; + int ret; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - codec->hw_write = (hw_write_t) i2c_master_send; - codec->hw_read = NULL; ret = i2c_add_driver(&tlv320aic23_i2c_driver); - if (ret != 0) - printk(KERN_ERR "can't add i2c driver"); + if (ret != 0) { + printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n", + ret); + } #endif return ret; } +module_init(tlv320aic23_modinit); -static int tlv320aic23_remove(struct platform_device *pdev) +static void __exit tlv320aic23_exit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - struct aic23 *aic23 = container_of(codec, struct aic23, codec); - - if (codec->control_data) - tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&tlv320aic23_i2c_driver); #endif - kfree(codec->reg_cache); - kfree(aic23); - - return 0; -} -struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = { - .probe = tlv320aic23_probe, - .remove = tlv320aic23_remove, - .suspend = tlv320aic23_suspend, - .resume = tlv320aic23_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23); - -static int __init tlv320aic23_modinit(void) -{ - return snd_soc_register_dai(&tlv320aic23_dai); -} -module_init(tlv320aic23_modinit); - -static void __exit tlv320aic23_exit(void) -{ - snd_soc_unregister_dai(&tlv320aic23_dai); } module_exit(tlv320aic23_exit); diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h index 79d1faf8e570..e804120bd3da 100644 --- a/sound/soc/codecs/tlv320aic23.h +++ b/sound/soc/codecs/tlv320aic23.h @@ -116,7 +116,4 @@ #define TLV320AIC23_SIDETONE_12 0x080 #define TLV320AIC23_SIDETONE_18 0x0c0 -extern struct snd_soc_dai tlv320aic23_dai; -extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23; - #endif /* _TLV320AIC23_H */ diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index f0e00fd4b435..6b7d71ec0004 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "tlv320aic26.h" @@ -130,8 +129,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); int fsref, divisor, wlen, pval, jval, dval, qval; u16 reg; @@ -278,8 +276,8 @@ static struct snd_soc_dai_ops aic26_dai_ops = { .set_fmt = aic26_set_fmt, }; -struct snd_soc_dai aic26_dai = { - .name = "tlv320aic26", +static struct snd_soc_dai_driver aic26_dai = { + .name = "tlv320aic26-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -296,7 +294,6 @@ struct snd_soc_dai aic26_dai = { }, .ops = &aic26_dai_ops, }; -EXPORT_SYMBOL_GPL(aic26_dai); /* --------------------------------------------------------------------- * ALSA controls @@ -318,61 +315,6 @@ static const struct snd_kcontrol_new aic26_snd_controls[] = { SOC_ENUM("Capture Source", aic26_capture_src_enum), }; -/* --------------------------------------------------------------------- - * SoC CODEC portion of driver: probe and release routines - */ -static int aic26_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct aic26 *aic26; - int ret, err; - - dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n"); - dev_dbg(&pdev->dev, "socdev=%p\n", socdev); - dev_dbg(&pdev->dev, "codec_data=%p\n", socdev->codec_data); - - /* Fetch the relevant aic26 private data here (it's already been - * stored in the .codec pointer) */ - aic26 = socdev->codec_data; - if (aic26 == NULL) { - dev_err(&pdev->dev, "aic26: missing codec pointer\n"); - return -ENODEV; - } - codec = &aic26->codec; - socdev->card->codec = codec; - - dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n", - &pdev->dev, socdev->dev); - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(&pdev->dev, "aic26: failed to create pcms\n"); - return -ENODEV; - } - - /* register controls */ - dev_dbg(&pdev->dev, "Registering controls\n"); - err = snd_soc_add_controls(codec, aic26_snd_controls, - ARRAY_SIZE(aic26_snd_controls)); - WARN_ON(err < 0); - - return 0; -} - -static int aic26_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - snd_soc_free_pcms(socdev); - return 0; -} - -struct snd_soc_codec_device aic26_soc_codec_dev = { - .probe = aic26_probe, - .remove = aic26_remove, -}; -EXPORT_SYMBOL_GPL(aic26_soc_codec_dev); - /* --------------------------------------------------------------------- * SPI device portion of driver: sysfs files for debugging */ @@ -409,95 +351,95 @@ static ssize_t aic26_keyclick_set(struct device *dev, static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); /* --------------------------------------------------------------------- - * SPI device portion of driver: probe and release routines and SPI - * driver registration. + * SoC CODEC portion of driver: probe and release routines */ -static int aic26_spi_probe(struct spi_device *spi) +static int aic26_probe(struct snd_soc_codec *codec) { - struct aic26 *aic26; - int ret, i, reg; - - dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); - - /* Allocate driver data */ - aic26 = kzalloc(sizeof *aic26, GFP_KERNEL); - if (!aic26) - return -ENOMEM; - - /* Initialize the driver data */ - aic26->spi = spi; - dev_set_drvdata(&spi->dev, aic26); + struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); + int ret, err, i, reg; - /* Setup what we can in the codec structure so that the register - * access functions will work as expected. More will be filled - * out when it is probed by the SoC CODEC part of this driver */ - snd_soc_codec_set_drvdata(&aic26->codec, aic26); - aic26->codec.name = "aic26"; - aic26->codec.owner = THIS_MODULE; - aic26->codec.dai = &aic26_dai; - aic26->codec.num_dai = 1; - aic26->codec.read = aic26_reg_read; - aic26->codec.write = aic26_reg_write; - aic26->master = 1; - mutex_init(&aic26->codec.mutex); - INIT_LIST_HEAD(&aic26->codec.dapm_widgets); - INIT_LIST_HEAD(&aic26->codec.dapm_paths); - aic26->codec.reg_cache_size = AIC26_NUM_REGS; - aic26->codec.reg_cache = aic26->reg_cache; - - aic26_dai.dev = &spi->dev; - ret = snd_soc_register_dai(&aic26_dai); - if (ret != 0) { - dev_err(&spi->dev, "Failed to register DAI: %d\n", ret); - kfree(aic26); - return ret; - } + dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n"); /* Reset the codec to power on defaults */ - aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00); + aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00); /* Power up CODEC */ - aic26_reg_write(&aic26->codec, AIC26_REG_POWER_CTRL, 0); + aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0); /* Audio Control 3 (master mode, fsref rate) */ - reg = aic26_reg_read(&aic26->codec, AIC26_REG_AUDIO_CTRL3); + reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3); reg &= ~0xf800; reg |= 0x0800; /* set master mode */ - aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL3, reg); + aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg); /* Fill register cache */ for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++) - aic26_reg_read(&aic26->codec, i); + aic26_reg_read(codec, i); /* Register the sysfs files for debugging */ /* Create SysFS files */ - ret = device_create_file(&spi->dev, &dev_attr_keyclick); + ret = device_create_file(codec->dev, &dev_attr_keyclick); if (ret) - dev_info(&spi->dev, "error creating sysfs files\n"); + dev_info(codec->dev, "error creating sysfs files\n"); -#if defined(CONFIG_SND_SOC_OF_SIMPLE) - /* Tell the of_soc helper about this codec */ - of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai, - spi->dev.archdata.of_node); -#endif + /* register controls */ + dev_dbg(codec->dev, "Registering controls\n"); + err = snd_soc_add_controls(codec, aic26_snd_controls, + ARRAY_SIZE(aic26_snd_controls)); + WARN_ON(err < 0); - dev_dbg(&spi->dev, "SPI device initialized\n"); return 0; } -static int aic26_spi_remove(struct spi_device *spi) +static struct snd_soc_codec_driver aic26_soc_codec_dev = { + .probe = aic26_probe, + .read = aic26_reg_read, + .write = aic26_reg_write, + .reg_cache_size = AIC26_NUM_REGS, + .reg_word_size = sizeof(u16), +}; + +/* --------------------------------------------------------------------- + * SPI device portion of driver: probe and release routines and SPI + * driver registration. + */ +static int aic26_spi_probe(struct spi_device *spi) { - struct aic26 *aic26 = dev_get_drvdata(&spi->dev); + struct aic26 *aic26; + int ret; - snd_soc_unregister_dai(&aic26_dai); - kfree(aic26); + dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); + + /* Allocate driver data */ + aic26 = kzalloc(sizeof *aic26, GFP_KERNEL); + if (!aic26) + return -ENOMEM; + /* Initialize the driver data */ + aic26->spi = spi; + dev_set_drvdata(&spi->dev, aic26); + aic26->master = 1; + + ret = snd_soc_register_codec(&spi->dev, + &aic26_soc_codec_dev, &aic26_dai, 1); + if (ret < 0) + kfree(aic26); + return ret; + + dev_dbg(&spi->dev, "SPI device initialized\n"); + return 0; +} + +static int aic26_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); return 0; } static struct spi_driver aic26_spi = { .driver = { - .name = "tlv320aic26", + .name = "tlv320aic26-codec", .owner = THIS_MODULE, }, .probe = aic26_spi_probe, diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h index 786ba16c945f..62b1f2261429 100644 --- a/sound/soc/codecs/tlv320aic26.h +++ b/sound/soc/codecs/tlv320aic26.h @@ -90,7 +90,4 @@ enum aic26_wlen { AIC26_WLEN_32 = 3 << 10, }; -extern struct snd_soc_dai aic26_dai; -extern struct snd_soc_codec_device aic26_soc_codec_dev; - #endif /* _TLV320AIC16_H_ */ diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 71a69908ccf6..43fd9c171742 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -63,8 +63,10 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = { /* codec private data */ struct aic3x_priv { - struct snd_soc_codec codec; struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; + enum snd_soc_control_type control_type; + struct aic3x_setup_data *setup; + void *control_data; unsigned int sysclk; int master; int gpio_reset; @@ -773,8 +775,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec =rtd->codec; struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; @@ -1101,8 +1102,8 @@ static struct snd_soc_dai_ops aic3x_dai_ops = { .set_fmt = aic3x_set_dai_fmt, }; -struct snd_soc_dai aic3x_dai = { - .name = "tlv320aic3x", +static struct snd_soc_dai_driver aic3x_dai = { + .name = "tlv320aic3x-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -1117,22 +1118,16 @@ struct snd_soc_dai aic3x_dai = { .formats = AIC3X_FORMATS,}, .ops = &aic3x_dai_ops, }; -EXPORT_SYMBOL_GPL(aic3x_dai); -static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) +static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int aic3x_resume(struct platform_device *pdev) +static int aic3x_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u8 *cache = codec->reg_cache; @@ -1157,22 +1152,6 @@ static int aic3x_init(struct snd_soc_codec *codec) { int reg; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "tlv320aic3x"; - codec->owner = THIS_MODULE; - codec->read = aic3x_read_reg_cache; - codec->write = aic3x_write; - codec->set_bias_level = aic3x_set_bias_level; - codec->dai = &aic3x_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(aic3x_reg); - codec->reg_cache = kmemdup(aic3x_reg, sizeof(aic3x_reg), GFP_KERNEL); - if (codec->reg_cache == NULL) - return -ENOMEM; - aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); aic3x_write(codec, AIC3X_RESET, SOFT_RESET); @@ -1245,56 +1224,50 @@ static int aic3x_init(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec *aic3x_codec; - -static int aic3x_register(struct snd_soc_codec *codec) +static int aic3x_probe(struct snd_soc_codec *codec) { - int ret; + struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); + + codec->hw_write = (hw_write_t) i2c_master_send; + codec->control_data = aic3x->control_data; - ret = aic3x_init(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to initialise device\n"); - return ret; + if (aic3x->setup) { + /* setup GPIO functions */ + aic3x_write(codec, AIC3X_GPIO1_REG, + (aic3x->setup->gpio_func[0] & 0xf) << 4); + aic3x_write(codec, AIC3X_GPIO2_REG, + (aic3x->setup->gpio_func[1] & 0xf) << 4); } - aic3x_codec = codec; + aic3x_init(codec); - ret = snd_soc_register_codec(codec); - if (ret) { - dev_err(codec->dev, "Failed to register codec\n"); - return ret; - } + snd_soc_add_controls(codec, aic3x_snd_controls, + ARRAY_SIZE(aic3x_snd_controls)); - ret = snd_soc_register_dai(&aic3x_dai); - if (ret) { - dev_err(codec->dev, "Failed to register dai\n"); - snd_soc_unregister_codec(codec); - return ret; - } + aic3x_add_widgets(codec); return 0; } -static int aic3x_unregister(struct aic3x_priv *aic3x) +static int aic3x_remove(struct snd_soc_codec *codec) { - aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF); - - snd_soc_unregister_dai(&aic3x_dai); - snd_soc_unregister_codec(&aic3x->codec); - - if (aic3x->gpio_reset >= 0) { - gpio_set_value(aic3x->gpio_reset, 0); - gpio_free(aic3x->gpio_reset); - } - regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); - regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); - - kfree(aic3x); - aic3x_codec = NULL; - + aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } +static struct snd_soc_codec_driver soc_codec_dev_aic3x = { + .read = aic3x_read_reg_cache, + .write = aic3x_write, + .set_bias_level = aic3x_set_bias_level, + .reg_cache_size = ARRAY_SIZE(aic3x_reg), + .reg_word_size = sizeof(u8), + .reg_cache_default = aic3x_reg, + .probe = aic3x_probe, + .remove = aic3x_remove, + .suspend = aic3x_suspend, + .resume = aic3x_resume, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) /* * AIC3X 2 wire address can be up to 4 devices with device addresses @@ -1308,9 +1281,9 @@ static int aic3x_unregister(struct aic3x_priv *aic3x) static int aic3x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct snd_soc_codec *codec; - struct aic3x_priv *aic3x; struct aic3x_pdata *pdata = i2c->dev.platform_data; + struct aic3x_setup_data *setup = pdata->setup; + struct aic3x_priv *aic3x; int ret, i; aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); @@ -1319,12 +1292,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, return -ENOMEM; } - codec = &aic3x->codec; - codec->dev = &i2c->dev; - snd_soc_codec_set_drvdata(codec, aic3x); - codec->control_data = i2c; - codec->hw_write = (hw_write_t) i2c_master_send; - + aic3x->control_data = i2c; + aic3x->setup = setup; i2c_set_clientdata(i2c, aic3x); aic3x->gpio_reset = -1; @@ -1339,17 +1308,17 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) aic3x->supplies[i].supply = aic3x_supply_names[i]; - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies), + ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(aic3x->supplies), aic3x->supplies); if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); goto err_get; } ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); + dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); goto err_enable; } @@ -1358,7 +1327,11 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, gpio_set_value(aic3x->gpio_reset, 1); } - return aic3x_register(codec); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_aic3x, &aic3x_dai, 1); + if (ret < 0) + goto err_enable; + return ret; err_enable: regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); @@ -1374,7 +1347,16 @@ static int aic3x_i2c_remove(struct i2c_client *client) { struct aic3x_priv *aic3x = i2c_get_clientdata(client); - return aic3x_unregister(aic3x); + if (aic3x->gpio_reset >= 0) { + gpio_set_value(aic3x->gpio_reset, 0); + gpio_free(aic3x->gpio_reset); + } + regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); + regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); + + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); + return 0; } static const struct i2c_device_id aic3x_i2c_id[] = { @@ -1387,7 +1369,7 @@ MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); /* machine i2c codec control layer */ static struct i2c_driver aic3x_i2c_driver = { .driver = { - .name = "aic3x I2C Codec", + .name = "tlv320aic3x-codec", .owner = THIS_MODULE, }, .probe = aic3x_i2c_probe, @@ -1409,90 +1391,27 @@ static inline void aic3x_i2c_exit(void) { i2c_del_driver(&aic3x_i2c_driver); } -#else -static inline void aic3x_i2c_init(void) { } -static inline void aic3x_i2c_exit(void) { } #endif -static int aic3x_probe(struct platform_device *pdev) +static int __init aic3x_modinit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct aic3x_setup_data *setup; - struct snd_soc_codec *codec; int ret = 0; - - codec = aic3x_codec; - if (!codec) { - dev_err(&pdev->dev, "Codec not registered\n"); - return -ENODEV; - } - - socdev->card->codec = codec; - setup = socdev->codec_data; - - if (setup) { - /* setup GPIO functions */ - aic3x_write(codec, AIC3X_GPIO1_REG, - (setup->gpio_func[0] & 0xf) << 4); - aic3x_write(codec, AIC3X_GPIO2_REG, - (setup->gpio_func[1] & 0xf) << 4); - } - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "aic3x: failed to create pcms\n"); - goto pcm_err; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + ret = i2c_add_driver(&aic3x_i2c_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n", + ret); } - - snd_soc_add_controls(codec, aic3x_snd_controls, - ARRAY_SIZE(aic3x_snd_controls)); - - aic3x_add_widgets(codec); - - return ret; - -pcm_err: - kfree(codec->reg_cache); +#endif return ret; } - -static int aic3x_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - /* power down chip */ - if (codec->control_data) - aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - kfree(codec->reg_cache); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_aic3x = { - .probe = aic3x_probe, - .remove = aic3x_remove, - .suspend = aic3x_suspend, - .resume = aic3x_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x); - -static int __init aic3x_modinit(void) -{ - aic3x_i2c_init(); - - return 0; -} module_init(aic3x_modinit); static void __exit aic3x_exit(void) { - aic3x_i2c_exit(); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_del_driver(&aic3x_i2c_driver); +#endif } module_exit(aic3x_exit); diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 9af1c886213c..f6e3d9b42daf 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -199,42 +199,6 @@ /* Default input volume */ #define DEFAULT_GAIN 0x20 -/* GPIO API */ -enum { - AIC3X_GPIO1_FUNC_DISABLED = 0, - AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC = 1, - AIC3X_GPIO1_FUNC_CLOCK_MUX = 2, - AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2 = 3, - AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4 = 4, - AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8 = 5, - AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ = 6, - AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ = 7, - AIC3X_GPIO1_FUNC_INPUT = 8, - AIC3X_GPIO1_FUNC_OUTPUT = 9, - AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK = 10, - AIC3X_GPIO1_FUNC_AUDIO_WORDCLK = 11, - AIC3X_GPIO1_FUNC_BUTTON_IRQ = 12, - AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ = 13, - AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 14, - AIC3X_GPIO1_FUNC_ALL_IRQ = 16 -}; - -enum { - AIC3X_GPIO2_FUNC_DISABLED = 0, - AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ = 2, - AIC3X_GPIO2_FUNC_INPUT = 3, - AIC3X_GPIO2_FUNC_OUTPUT = 4, - AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT = 5, - AIC3X_GPIO2_FUNC_AUDIO_BITCLK = 8, - AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9, - AIC3X_GPIO2_FUNC_ALL_IRQ = 10, - AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11, - AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12, - AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ = 13, - AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ = 14, - AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15 -}; - void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state); int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio); @@ -281,11 +245,4 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect, int aic3x_headset_detected(struct snd_soc_codec *codec); int aic3x_button_pressed(struct snd_soc_codec *codec); -struct aic3x_setup_data { - unsigned int gpio_func[2]; -}; - -extern struct snd_soc_dai aic3x_dai; -extern struct snd_soc_codec_device soc_codec_dev_aic3x; - #endif /* _AIC3X_H */ diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 8651b01ed223..a3c5b521da6a 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -66,8 +66,6 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream); static int dac33_prepare_chip(struct snd_pcm_substream *substream); -static struct snd_soc_codec *tlv320dac33_codec; - enum dac33_state { DAC33_IDLE = 0, DAC33_PREFILL, @@ -93,7 +91,7 @@ struct tlv320dac33_priv { struct mutex mutex; struct workqueue_struct *dac33_wq; struct work_struct work; - struct snd_soc_codec codec; + struct snd_soc_codec *codec; struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; struct snd_pcm_substream *substream; int power_gpio; @@ -128,6 +126,8 @@ struct tlv320dac33_priv { unsigned int uthr; enum dac33_state state; + enum snd_soc_control_type control_type; + void *control_data; }; static const u8 dac33_reg[DAC33_CACHEREGNUM] = { @@ -650,9 +650,7 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec, static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) { - struct snd_soc_codec *codec; - - codec = &dac33->codec; + struct snd_soc_codec *codec = dac33->codec; switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: @@ -695,9 +693,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33) { - struct snd_soc_codec *codec; - - codec = &dac33->codec; + struct snd_soc_codec *codec = dac33->codec; switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: @@ -726,7 +722,7 @@ static void dac33_work(struct work_struct *work) u8 reg; dac33 = container_of(work, struct tlv320dac33_priv, work); - codec = &dac33->codec; + codec = dac33->codec; mutex_lock(&dac33->mutex); switch (dac33->state) { @@ -787,8 +783,7 @@ static int dac33_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); /* Stream started, save the substream pointer */ @@ -801,8 +796,7 @@ static void dac33_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); dac33->substream = NULL; @@ -817,8 +811,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; /* Check parameters for validity */ switch (params_rate(params)) { @@ -856,8 +849,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream, static int dac33_prepare_chip(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); unsigned int oscset, ratioset, pwr_ctrl, reg_tmp; u8 aictrl_a, aictrl_b, fifoctrl_a; @@ -1049,8 +1041,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) static void dac33_calculate_times(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); unsigned int period_size = substream->runtime->period_size; unsigned int rate = substream->runtime->rate; @@ -1129,8 +1120,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); int ret = 0; @@ -1163,8 +1153,7 @@ static snd_pcm_sframes_t dac33_dai_delay( struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); unsigned long long t0, t1, t_now; unsigned int time_delta, uthr; @@ -1389,24 +1378,47 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int dac33_soc_probe(struct platform_device *pdev) +static int dac33_soc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct tlv320dac33_priv *dac33; + struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); int ret = 0; - BUG_ON(!tlv320dac33_codec); + codec->control_data = dac33->control_data; + codec->hw_write = (hw_write_t) i2c_master_send; + codec->bias_level = SND_SOC_BIAS_OFF; + codec->idle_bias_off = 1; + dac33->codec = codec; - codec = tlv320dac33_codec; - socdev->card->codec = codec; - dac33 = snd_soc_codec_get_drvdata(codec); + /* Read the tlv320dac33 ID registers */ + ret = dac33_hard_power(codec, 1); + if (ret != 0) { + dev_err(codec->dev, "Failed to power up codec: %d\n", ret); + goto err_power; + } + dac33_read_id(codec); + dac33_hard_power(codec, 0); - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms\n"); - goto pcm_err; + /* Check if the IRQ number is valid and request it */ + if (dac33->irq >= 0) { + ret = request_irq(dac33->irq, dac33_interrupt_handler, + IRQF_TRIGGER_RISING | IRQF_DISABLED, + codec->name, codec); + if (ret < 0) { + dev_err(codec->dev, "Could not request IRQ%d (%d)\n", + dac33->irq, ret); + dac33->irq = -1; + } + if (dac33->irq != -1) { + /* Setup work queue */ + dac33->dac33_wq = + create_singlethread_workqueue("tlv320dac33"); + if (dac33->dac33_wq == NULL) { + free_irq(dac33->irq, codec); + return -ENOMEM; + } + + INIT_WORK(&dac33->work, dac33_work); + } } snd_soc_add_controls(codec, dac33_snd_controls, @@ -1420,56 +1432,51 @@ static int dac33_soc_probe(struct platform_device *pdev) snd_soc_add_controls(codec, dac33_fifo_snd_controls, ARRAY_SIZE(dac33_fifo_snd_controls)); } - dac33_add_widgets(codec); - return 0; - -pcm_err: - dac33_hard_power(codec, 0); +err_power: return ret; } -static int dac33_soc_remove(struct platform_device *pdev) +static int dac33_soc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; + struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - + if (dac33->irq >= 0) { + free_irq(dac33->irq, dac33->codec); + destroy_workqueue(dac33->dac33_wq); + } return 0; } -static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state) +static int dac33_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int dac33_soc_resume(struct platform_device *pdev) +static int dac33_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } -struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = { +static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = { + .read = dac33_read_reg_cache, + .write = dac33_write_locked, + .set_bias_level = dac33_set_bias_level, + .reg_cache_size = ARRAY_SIZE(dac33_reg), + .reg_word_size = sizeof(u8), + .reg_cache_default = dac33_reg, .probe = dac33_soc_probe, .remove = dac33_soc_remove, .suspend = dac33_soc_suspend, .resume = dac33_soc_resume, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33); #define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000) @@ -1485,8 +1492,8 @@ static struct snd_soc_dai_ops dac33_dai_ops = { .set_fmt = dac33_set_dai_fmt, }; -struct snd_soc_dai dac33_dai = { - .name = "tlv320dac33", +static struct snd_soc_dai_driver dac33_dai = { + .name = "tlv320dac33-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -1495,14 +1502,12 @@ struct snd_soc_dai dac33_dai = { .formats = DAC33_FORMATS,}, .ops = &dac33_dai_ops, }; -EXPORT_SYMBOL_GPL(dac33_dai); static int __devinit dac33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tlv320dac33_platform_data *pdata; struct tlv320dac33_priv *dac33; - struct snd_soc_codec *codec; int ret, i; if (client->dev.platform_data == NULL) { @@ -1515,33 +1520,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, if (dac33 == NULL) return -ENOMEM; - codec = &dac33->codec; - snd_soc_codec_set_drvdata(codec, dac33); - codec->control_data = client; - - mutex_init(&codec->mutex); + dac33->control_data = client; mutex_init(&dac33->mutex); spin_lock_init(&dac33->lock); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "tlv320dac33"; - codec->owner = THIS_MODULE; - codec->read = dac33_read_reg_cache; - codec->write = dac33_write_locked; - codec->hw_write = (hw_write_t) i2c_master_send; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = dac33_set_bias_level; - codec->idle_bias_off = 1; - codec->dai = &dac33_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(dac33_reg); - codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg), - GFP_KERNEL); - if (codec->reg_cache == NULL) { - ret = -ENOMEM; - goto error_reg; - } i2c_set_clientdata(client, dac33); @@ -1561,125 +1542,59 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, /* Disable FIFO use by default */ dac33->fifo_mode = DAC33_FIFO_BYPASS; - tlv320dac33_codec = codec; - - codec->dev = &client->dev; - dac33_dai.dev = codec->dev; - /* Check if the reset GPIO number is valid and request it */ if (dac33->power_gpio >= 0) { ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset"); if (ret < 0) { - dev_err(codec->dev, + dev_err(&client->dev, "Failed to request reset GPIO (%d)\n", dac33->power_gpio); - snd_soc_unregister_dai(&dac33_dai); - snd_soc_unregister_codec(codec); - goto error_gpio; + goto err_gpio; } gpio_direction_output(dac33->power_gpio, 0); } - /* Check if the IRQ number is valid and request it */ - if (dac33->irq >= 0) { - ret = request_irq(dac33->irq, dac33_interrupt_handler, - IRQF_TRIGGER_RISING | IRQF_DISABLED, - codec->name, codec); - if (ret < 0) { - dev_err(codec->dev, "Could not request IRQ%d (%d)\n", - dac33->irq, ret); - dac33->irq = -1; - } - if (dac33->irq != -1) { - /* Setup work queue */ - dac33->dac33_wq = - create_singlethread_workqueue("tlv320dac33"); - if (dac33->dac33_wq == NULL) { - free_irq(dac33->irq, &dac33->codec); - ret = -ENOMEM; - goto error_wq; - } - - INIT_WORK(&dac33->work, dac33_work); - } - } - for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) dac33->supplies[i].supply = dac33_supply_names[i]; - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(dac33->supplies), + ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies), dac33->supplies); if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); + dev_err(&client->dev, "Failed to request supplies: %d\n", ret); goto err_get; } - /* Read the tlv320dac33 ID registers */ - ret = dac33_hard_power(codec, 1); - if (ret != 0) { - dev_err(codec->dev, "Failed to power up codec: %d\n", ret); - goto error_codec; - } - dac33_read_id(codec); - dac33_hard_power(codec, 0); - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto error_codec; - } - - ret = snd_soc_register_dai(&dac33_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - goto error_codec; - } + ret = snd_soc_register_codec(&client->dev, + &soc_codec_dev_tlv320dac33, &dac33_dai, 1); + if (ret < 0) + goto err_register; return ret; - -error_codec: +err_register: regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); err_get: - if (dac33->irq >= 0) { - free_irq(dac33->irq, &dac33->codec); - destroy_workqueue(dac33->dac33_wq); - } -error_wq: if (dac33->power_gpio >= 0) gpio_free(dac33->power_gpio); -error_gpio: - kfree(codec->reg_cache); -error_reg: - tlv320dac33_codec = NULL; +err_gpio: kfree(dac33); - return ret; } static int __devexit dac33_i2c_remove(struct i2c_client *client) { - struct tlv320dac33_priv *dac33; - - dac33 = i2c_get_clientdata(client); + struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client); if (unlikely(dac33->chip_power)) - dac33_hard_power(&dac33->codec, 0); + dac33_hard_power(dac33->codec, 0); if (dac33->power_gpio >= 0) gpio_free(dac33->power_gpio); - if (dac33->irq >= 0) - free_irq(dac33->irq, &dac33->codec); regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); - destroy_workqueue(dac33->dac33_wq); - snd_soc_unregister_dai(&dac33_dai); - snd_soc_unregister_codec(&dac33->codec); - kfree(dac33->codec.reg_cache); + snd_soc_unregister_codec(&client->dev); kfree(dac33); - tlv320dac33_codec = NULL; return 0; } @@ -1694,7 +1609,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = { static struct i2c_driver tlv320dac33_i2c_driver = { .driver = { - .name = "tlv320dac33", + .name = "tlv320dac33-codec", .owner = THIS_MODULE, }, .probe = dac33_i2c_probe, diff --git a/sound/soc/codecs/tlv320dac33.h b/sound/soc/codecs/tlv320dac33.h index eb8ae07f0bd2..7c318b5da437 100644 --- a/sound/soc/codecs/tlv320dac33.h +++ b/sound/soc/codecs/tlv320dac33.h @@ -261,7 +261,4 @@ #define TLV320DAC33_MCLK 0 #define TLV320DAC33_SLEEPCLK 1 -extern struct snd_soc_dai dac33_dai; -extern struct snd_soc_codec_device soc_codec_dev_tlv320dac33; - #endif /* __TLV320DAC33_H */ diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 7b618bbff884..898430f44f9d 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -36,7 +36,16 @@ #include #include -#include "twl4030.h" +/* Register descriptions are here */ +#include + +/* Shadow register used by the audio driver */ +#define TWL4030_REG_SW_SHADOW 0x4A +#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) + +/* TWL4030_REG_SW_SHADOW (0x4A) Fields */ +#define TWL4030_HFL_EN 0x01 +#define TWL4030_HFR_EN 0x02 /* * twl4030 register cache & default register settings @@ -277,21 +286,19 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec) } -static void twl4030_init_chip(struct platform_device *pdev) +static void twl4030_init_chip(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct twl4030_setup_data *setup = socdev->codec_data; - struct snd_soc_codec *codec = socdev->card->codec; + struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev); struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); u8 reg, byte; int i = 0; /* Check defaults, if instructed before anything else */ - if (setup && setup->check_defaults) + if (pdata && pdata->check_defaults) twl4030_check_defaults(codec); /* Reset registers, if no setup data or if instructed to do so */ - if (!setup || (setup && setup->reset_registers)) + if (!pdata || (pdata && pdata->reset_registers)) twl4030_reset_registers(codec); /* Refresh APLL_CTL register from HW */ @@ -312,20 +319,14 @@ static void twl4030_init_chip(struct platform_device *pdev) twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32); /* Machine dependent setup */ - if (!setup) + if (!pdata) return; - twl4030->digimic_delay = setup->digimic_delay; - - /* Configuration for headset ramp delay from setup data */ - if (setup->sysclk != twl4030->sysclk) - dev_warn(codec->dev, - "Mismatch in APLL mclk: %u (configured: %u)\n", - setup->sysclk, twl4030->sysclk); + twl4030->digimic_delay = pdata->digimic_delay; reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); reg &= ~TWL4030_RAMP_DELAY; - reg |= (setup->ramp_delay_value << 2); + reg |= (pdata->ramp_delay_value << 2); twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg); /* initiate offset cancellation */ @@ -333,7 +334,7 @@ static void twl4030_init_chip(struct platform_device *pdev) reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); reg &= ~TWL4030_OFFSET_CNCL_SEL; - reg |= setup->offset_cncl_path; + reg |= pdata->offset_cncl_path; twl4030_write(codec, TWL4030_REG_ANAMICL, reg | TWL4030_CNCL_OFFSET_START); @@ -718,9 +719,7 @@ static int aif_event(struct snd_soc_dapm_widget *w, static void headset_ramp(struct snd_soc_codec *codec, int ramp) { - struct snd_soc_device *socdev = codec->socdev; - struct twl4030_setup_data *setup = socdev->codec_data; - + struct twl4030_codec_audio_data *pdata = codec->dev->platform_data; unsigned char hs_gain, hs_pop; struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); /* Base values for ramp delay calculation: 2^19 - 2^26 */ @@ -732,9 +731,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) /* Enable external mute control, this dramatically reduces * the pop-noise */ - if (setup && setup->hs_extmute) { - if (setup->set_hs_extmute) { - setup->set_hs_extmute(1); + if (pdata && pdata->hs_extmute) { + if (pdata->set_hs_extmute) { + pdata->set_hs_extmute(1); } else { hs_pop |= TWL4030_EXTMUTE; twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); @@ -772,9 +771,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) } /* Disable external mute */ - if (setup && setup->hs_extmute) { - if (setup->set_hs_extmute) { - setup->set_hs_extmute(0); + if (pdata && pdata->hs_extmute) { + if (pdata->set_hs_extmute) { + pdata->set_hs_extmute(0); } else { hs_pop &= ~TWL4030_EXTMUTE; twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); @@ -1707,8 +1706,7 @@ static int twl4030_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); if (twl4030->master_substream) { @@ -1738,8 +1736,7 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); if (twl4030->master_substream == substream) @@ -1764,8 +1761,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); u8 mode, old_mode, format, old_format; @@ -1999,8 +1995,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); u8 mode; @@ -2033,8 +2028,7 @@ static void twl4030_voice_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; /* Enable voice digital filters */ twl4030_voice_enable(codec, substream->stream, 0); @@ -2044,8 +2038,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); u8 old_mode, mode; @@ -2175,7 +2168,7 @@ static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate) #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) -static struct snd_soc_dai_ops twl4030_dai_ops = { +static struct snd_soc_dai_ops twl4030_dai_hifi_ops = { .startup = twl4030_startup, .shutdown = twl4030_shutdown, .hw_params = twl4030_hw_params, @@ -2193,9 +2186,9 @@ static struct snd_soc_dai_ops twl4030_dai_voice_ops = { .set_tristate = twl4030_voice_set_tristate, }; -struct snd_soc_dai twl4030_dai[] = { +static struct snd_soc_dai_driver twl4030_dai[] = { { - .name = "twl4030", + .name = "twl4030-hifi", .playback = { .stream_name = "HiFi Playback", .channels_min = 2, @@ -2208,10 +2201,10 @@ struct snd_soc_dai twl4030_dai[] = { .channels_max = 4, .rates = TWL4030_RATES, .formats = TWL4030_FORMATS,}, - .ops = &twl4030_dai_ops, + .ops = &twl4030_dai_hifi_ops, }, { - .name = "twl4030 Voice", + .name = "twl4030-voice", .playback = { .stream_name = "Voice Playback", .channels_min = 1, @@ -2227,164 +2220,90 @@ struct snd_soc_dai twl4030_dai[] = { .ops = &twl4030_dai_voice_ops, }, }; -EXPORT_SYMBOL_GPL(twl4030_dai); -static int twl4030_soc_suspend(struct platform_device *pdev, pm_message_t state) +static int twl4030_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; } -static int twl4030_soc_resume(struct platform_device *pdev) +static int twl4030_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } -static struct snd_soc_codec *twl4030_codec; - -static int twl4030_soc_probe(struct platform_device *pdev) +static int twl4030_soc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret; - - BUG_ON(!twl4030_codec); - - codec = twl4030_codec; - socdev->card->codec = codec; - - twl4030_init_chip(pdev); + struct twl4030_priv *twl4030; - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(&pdev->dev, "failed to create pcms\n"); - return ret; + twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); + if (twl4030 == NULL) { + printk("Can not allocate memroy\n"); + return -ENOMEM; } + snd_soc_codec_set_drvdata(codec, twl4030); + /* Set the defaults, and power up the codec */ + twl4030->sysclk = twl4030_codec_get_mclk() / 1000; + codec->bias_level = SND_SOC_BIAS_OFF; + codec->idle_bias_off = 1; + + twl4030_init_chip(codec); snd_soc_add_controls(codec, twl4030_snd_controls, ARRAY_SIZE(twl4030_snd_controls)); twl4030_add_widgets(codec); - return 0; } -static int twl4030_soc_remove(struct platform_device *pdev) +static int twl4030_soc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - /* Reset registers to their chip default before leaving */ - twl4030_reset_registers(codec); twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - return 0; } +static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { + .probe = twl4030_soc_probe, + .remove = twl4030_soc_remove, + .suspend = twl4030_soc_suspend, + .resume = twl4030_soc_resume, + .read = twl4030_read_reg_cache, + .write = twl4030_write, + .set_bias_level = twl4030_set_bias_level, + .reg_cache_size = sizeof(twl4030_reg), + .reg_word_size = sizeof(u8), + .reg_cache_default = twl4030_reg, +}; + static int __devinit twl4030_codec_probe(struct platform_device *pdev) { struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; - struct snd_soc_codec *codec; - struct twl4030_priv *twl4030; - int ret; if (!pdata) { dev_err(&pdev->dev, "platform_data is missing\n"); return -EINVAL; } - twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); - if (twl4030 == NULL) { - dev_err(&pdev->dev, "Can not allocate memroy\n"); - return -ENOMEM; - } - - codec = &twl4030->codec; - snd_soc_codec_set_drvdata(codec, twl4030); - codec->dev = &pdev->dev; - twl4030_dai[0].dev = &pdev->dev; - twl4030_dai[1].dev = &pdev->dev; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "twl4030"; - codec->owner = THIS_MODULE; - codec->read = twl4030_read_reg_cache; - codec->write = twl4030_write; - codec->set_bias_level = twl4030_set_bias_level; - codec->idle_bias_off = 1; - codec->dai = twl4030_dai; - codec->num_dai = ARRAY_SIZE(twl4030_dai); - codec->reg_cache_size = sizeof(twl4030_reg); - codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), - GFP_KERNEL); - if (codec->reg_cache == NULL) { - ret = -ENOMEM; - goto error_cache; - } - - platform_set_drvdata(pdev, twl4030); - twl4030_codec = codec; - - /* Set the defaults, and power up the codec */ - twl4030->sysclk = twl4030_codec_get_mclk() / 1000; - codec->bias_level = SND_SOC_BIAS_OFF; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto error_codec; - } - - ret = snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); - snd_soc_unregister_codec(codec); - goto error_codec; - } - - return 0; - -error_codec: - twl4030_codec_enable(codec, 0); - kfree(codec->reg_cache); -error_cache: - kfree(twl4030); - return ret; + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030, + twl4030_dai, ARRAY_SIZE(twl4030_dai)); } static int __devexit twl4030_codec_remove(struct platform_device *pdev) { - struct twl4030_priv *twl4030 = platform_get_drvdata(pdev); + struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev); - snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); - snd_soc_unregister_codec(&twl4030->codec); - kfree(twl4030->codec.reg_cache); + snd_soc_unregister_codec(&pdev->dev); kfree(twl4030); - - twl4030_codec = NULL; return 0; } -MODULE_ALIAS("platform:twl4030_codec_audio"); +MODULE_ALIAS("platform:twl4030-codec"); static struct platform_driver twl4030_codec_driver = { .probe = twl4030_codec_probe, .remove = __devexit_p(twl4030_codec_remove), .driver = { - .name = "twl4030_codec_audio", + .name = "twl4030-codec", .owner = THIS_MODULE, }, }; @@ -2401,14 +2320,6 @@ static void __exit twl4030_exit(void) } module_exit(twl4030_exit); -struct snd_soc_codec_device soc_codec_dev_twl4030 = { - .probe = twl4030_soc_probe, - .remove = twl4030_soc_remove, - .suspend = twl4030_soc_suspend, - .resume = twl4030_soc_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030); - MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); MODULE_AUTHOR("Steve Sakoman"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h deleted file mode 100644 index 6c57430f6e24..000000000000 --- a/sound/soc/codecs/twl4030.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * ALSA SoC TWL4030 codec driver - * - * Author: Steve Sakoman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __TWL4030_AUDIO_H__ -#define __TWL4030_AUDIO_H__ - -/* Register descriptions are here */ -#include - -/* Shadow register used by the audio driver */ -#define TWL4030_REG_SW_SHADOW 0x4A -#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) - -/* TWL4030_REG_SW_SHADOW (0x4A) Fields */ -#define TWL4030_HFL_EN 0x01 -#define TWL4030_HFR_EN 0x02 - -#define TWL4030_DAI_HIFI 0 -#define TWL4030_DAI_VOICE 1 - -extern struct snd_soc_dai twl4030_dai[2]; -extern struct snd_soc_codec_device soc_codec_dev_twl4030; - -struct twl4030_setup_data { - unsigned int ramp_delay_value; - unsigned int digimic_delay; /* in ms */ - unsigned int sysclk; - unsigned int offset_cncl_path; - unsigned int check_defaults:1; - unsigned int reset_registers:1; - unsigned int hs_extmute:1; - void (*set_hs_extmute)(int mute); -}; - -#endif /* End of __TWL4030_AUDIO_H__ */ - - diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 64a807f1a8a1..10f6e5214511 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -45,7 +45,6 @@ /* codec private data */ struct twl6040_data { - struct snd_soc_codec codec; int audpwron; int naudint; int codec_powered; @@ -770,8 +769,7 @@ static int twl6040_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); if (!priv->sysclk) { @@ -803,8 +801,7 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); u8 lppllctl; int rate; @@ -839,8 +836,7 @@ static int twl6040_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); switch (cmd) { @@ -978,8 +974,8 @@ static struct snd_soc_dai_ops twl6040_dai_ops = { .set_sysclk = twl6040_set_dai_sysclk, }; -struct snd_soc_dai twl6040_dai = { - .name = "twl6040", +static struct snd_soc_dai_driver twl6040_dai = { + .name = "twl6040-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -996,24 +992,17 @@ struct snd_soc_dai twl6040_dai = { }, .ops = &twl6040_dai_ops, }; -EXPORT_SYMBOL_GPL(twl6040_dai); #ifdef CONFIG_PM -static int twl6040_suspend(struct platform_device *pdev, pm_message_t state) +static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int twl6040_resume(struct platform_device *pdev) +static int twl6040_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; @@ -1023,68 +1012,9 @@ static int twl6040_resume(struct platform_device *pdev) #define twl6040_resume NULL #endif -static struct snd_soc_codec *twl6040_codec; - -static int twl6040_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - BUG_ON(!twl6040_codec); - - codec = twl6040_codec; - socdev->card->codec = codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(&pdev->dev, "failed to create pcms\n"); - return ret; - } - - snd_soc_add_controls(codec, twl6040_snd_controls, - ARRAY_SIZE(twl6040_snd_controls)); - twl6040_add_widgets(codec); - - if (ret < 0) { - dev_err(&pdev->dev, "failed to register card\n"); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - return ret; -} - -static int twl6040_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - kfree(codec); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_twl6040 = { - .probe = twl6040_probe, - .remove = twl6040_remove, - .suspend = twl6040_suspend, - .resume = twl6040_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_twl6040); - -static int __devinit twl6040_codec_probe(struct platform_device *pdev) +static int twl6040_probe(struct snd_soc_codec *codec) { - struct twl4030_codec_data *twl_codec = pdev->dev.platform_data; - struct snd_soc_codec *codec; + struct twl4030_codec_data *twl_codec = codec->dev->platform_data; struct twl6040_data *priv; int audpwron, naudint; int ret = 0; @@ -1092,6 +1022,7 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev) priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); if (priv == NULL) return -ENOMEM; + snd_soc_codec_set_drvdata(codec, priv); if (twl_codec) { audpwron = twl_codec->audpwron_gpio; @@ -1104,29 +1035,6 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev) priv->audpwron = audpwron; priv->naudint = naudint; - codec = &priv->codec; - codec->dev = &pdev->dev; - twl6040_dai.dev = &pdev->dev; - - codec->name = "twl6040"; - codec->owner = THIS_MODULE; - codec->read = twl6040_read_reg_cache; - codec->write = twl6040_write; - codec->set_bias_level = twl6040_set_bias_level; - snd_soc_codec_set_drvdata(codec, priv); - codec->dai = &twl6040_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(twl6040_reg); - codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg), - GFP_KERNEL); - if (codec->reg_cache == NULL) { - ret = -ENOMEM; - goto cache_err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); init_completion(&priv->ready); if (gpio_is_valid(audpwron)) { @@ -1169,23 +1077,12 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev) if (ret) goto irq_err; - ret = snd_soc_register_codec(codec); - if (ret) - goto reg_err; - - twl6040_codec = codec; - - ret = snd_soc_register_dai(&twl6040_dai); - if (ret) - goto dai_err; + snd_soc_add_controls(codec, twl6040_snd_controls, + ARRAY_SIZE(twl6040_snd_controls)); + twl6040_add_widgets(codec); return 0; -dai_err: - snd_soc_unregister_codec(codec); - twl6040_codec = NULL; -reg_err: - twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); irq_err: if (naudint) free_irq(naudint, codec); @@ -1193,36 +1090,57 @@ gpio2_err: if (gpio_is_valid(audpwron)) gpio_free(audpwron); gpio1_err: - kfree(codec->reg_cache); -cache_err: kfree(priv); return ret; } -static int __devexit twl6040_codec_remove(struct platform_device *pdev) +static int twl6040_remove(struct snd_soc_codec *codec) { - struct twl6040_data *priv = snd_soc_codec_get_drvdata(twl6040_codec); + struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); int audpwron = priv->audpwron; int naudint = priv->naudint; + twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); + if (gpio_is_valid(audpwron)) gpio_free(audpwron); if (naudint) - free_irq(naudint, twl6040_codec); + free_irq(naudint, codec); - snd_soc_unregister_dai(&twl6040_dai); - snd_soc_unregister_codec(twl6040_codec); + kfree(priv); - kfree(twl6040_codec); - twl6040_codec = NULL; + return 0; +} +static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { + .probe = twl6040_probe, + .remove = twl6040_remove, + .suspend = twl6040_suspend, + .resume = twl6040_resume, + .read = twl6040_read_reg_cache, + .write = twl6040_write, + .set_bias_level = twl6040_set_bias_level, + .reg_cache_size = ARRAY_SIZE(twl6040_reg), + .reg_word_size = sizeof(u8), + .reg_cache_default = twl6040_reg, +}; + +static int __devinit twl6040_codec_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_twl6040, &twl6040_dai, 1); +} + +static int __devexit twl6040_codec_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); return 0; } static struct platform_driver twl6040_codec_driver = { .driver = { - .name = "twl6040_codec", + .name = "twl6040-codec", .owner = THIS_MODULE, }, .probe = twl6040_codec_probe, diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h index c472070a1da2..f7c77fa58a3c 100644 --- a/sound/soc/codecs/twl6040.h +++ b/sound/soc/codecs/twl6040.h @@ -135,7 +135,4 @@ #define TWL6040_HPPLL_ID 1 #define TWL6040_LPPLL_ID 2 -extern struct snd_soc_dai twl6040_dai; -extern struct snd_soc_codec_device soc_codec_dev_twl6040; - #endif /* End of __TWL6040_H__ */ diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index f3b4c1d6a82d..7540a509a6f5 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -161,8 +161,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec =rtd->codec; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); struct snd_pcm_runtime *master_runtime; @@ -194,8 +193,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); if (uda134x->master_substream == substream) @@ -209,8 +207,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); u8 hw_params; @@ -364,7 +361,7 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec, pd->power(1); /* Sync reg_cache with the hardware */ for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) - codec->write(codec, i, *cache++); + codec->driver->write(codec, i, *cache++); } break; case SND_SOC_BIAS_STANDBY: @@ -465,8 +462,8 @@ static struct snd_soc_dai_ops uda134x_dai_ops = { .set_fmt = uda134x_set_dai_fmt, }; -struct snd_soc_dai uda134x_dai = { - .name = "UDA134X", +static struct snd_soc_dai_driver uda134x_dai = { + .name = "uda134x-hifi", /* playback capabilities */ .playback = { .stream_name = "Playback", @@ -486,27 +483,21 @@ struct snd_soc_dai uda134x_dai = { /* pcm operations */ .ops = &uda134x_dai_ops, }; -EXPORT_SYMBOL(uda134x_dai); - -static int uda134x_soc_probe(struct platform_device *pdev) +static int uda134x_soc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; struct uda134x_priv *uda134x; - void *codec_setup_data = socdev->codec_data; - int ret = -ENOMEM; - struct uda134x_platform_data *pd; + struct uda134x_platform_data *pd = dev_get_drvdata(codec->card->dev); + int ret; printk(KERN_INFO "UDA134X SoC Audio Codec\n"); - if (!codec_setup_data) { + if (!pd) { printk(KERN_ERR "UDA134X SoC codec: " "missing L3 bitbang function\n"); return -ENODEV; } - pd = codec_setup_data; switch (pd->model) { case UDA134X_UDA1340: case UDA134X_UDA1341: @@ -520,58 +511,22 @@ static int uda134x_soc_probe(struct platform_device *pdev) return -EINVAL; } - socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->card->codec == NULL) - return ret; - - codec = socdev->card->codec; - uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); if (uda134x == NULL) - goto priv_err; + return -ENOMEM; snd_soc_codec_set_drvdata(codec, uda134x); - codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg), - GFP_KERNEL); - if (codec->reg_cache == NULL) - goto reg_err; - - mutex_init(&codec->mutex); - - codec->reg_cache_size = sizeof(uda134x_reg); - codec->reg_cache_step = 1; - - codec->name = "UDA134X"; - codec->owner = THIS_MODULE; - codec->dai = &uda134x_dai; - codec->num_dai = 1; - codec->read = uda134x_read_reg_cache; - codec->write = uda134x_write; - - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->control_data = codec_setup_data; + codec->control_data = pd; if (pd->power) pd->power(1); uda134x_reset(codec); - if (pd->is_powered_on_standby) { - codec->set_bias_level = NULL; + if (pd->is_powered_on_standby) uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); - } else { - codec->set_bias_level = uda134x_set_bias_level; + else uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - } - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "UDA134X: failed to register pcms\n"); - goto pcm_err; - } switch (pd->model) { case UDA134X_UDA1340: @@ -590,61 +545,42 @@ static int uda134x_soc_probe(struct platform_device *pdev) default: printk(KERN_ERR "%s unknown codec type: %d", __func__, pd->model); - return -EINVAL; + kfree(uda134x); + return -EINVAL; } if (ret < 0) { printk(KERN_ERR "UDA134X: failed to register controls\n"); - goto pcm_err; + kfree(uda134x); + return ret; } return 0; - -pcm_err: - kfree(codec->reg_cache); -reg_err: - kfree(snd_soc_codec_get_drvdata(codec)); -priv_err: - kfree(codec); - return ret; } /* power down chip */ -static int uda134x_soc_remove(struct platform_device *pdev) +static int uda134x_soc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; + struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - kfree(snd_soc_codec_get_drvdata(codec)); - kfree(codec->reg_cache); - kfree(codec); - + kfree(uda134x); return 0; } #if defined(CONFIG_PM) -static int uda134x_soc_suspend(struct platform_device *pdev, +static int uda134x_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int uda134x_soc_resume(struct platform_device *pdev) +static int uda134x_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); return 0; @@ -654,25 +590,53 @@ static int uda134x_soc_resume(struct platform_device *pdev) #define uda134x_soc_resume NULL #endif /* CONFIG_PM */ -struct snd_soc_codec_device soc_codec_dev_uda134x = { +static struct snd_soc_codec_driver soc_codec_dev_uda134x = { .probe = uda134x_soc_probe, .remove = uda134x_soc_remove, .suspend = uda134x_soc_suspend, .resume = uda134x_soc_resume, + .reg_cache_size = sizeof(uda134x_reg), + .reg_word_size = sizeof(u8), + .reg_cache_step = 1, + .read = uda134x_read_reg_cache, + .write = uda134x_write, +#ifdef POWER_OFF_ON_STANDBY + .set_bias_level = uda134x_set_bias_level, +#endif +}; + +static int __devinit uda134x_codec_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_uda134x, &uda134x_dai, 1); +} + +static int __devexit uda134x_codec_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static struct platform_driver uda134x_codec_driver = { + .driver = { + .name = "uda134x-codec", + .owner = THIS_MODULE, + }, + .probe = uda134x_codec_probe, + .remove = __devexit_p(uda134x_codec_remove), }; -EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x); -static int __init uda134x_init(void) +static int __init uda134x_codec_init(void) { - return snd_soc_register_dai(&uda134x_dai); + return platform_driver_register(&uda134x_codec_driver); } -module_init(uda134x_init); +module_init(uda134x_codec_init); -static void __exit uda134x_exit(void) +static void __exit uda134x_codec_exit(void) { - snd_soc_unregister_dai(&uda134x_dai); + platform_driver_unregister(&uda134x_codec_driver); } -module_exit(uda134x_exit); +module_exit(uda134x_codec_exit); MODULE_DESCRIPTION("UDA134X ALSA soc codec driver"); MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin "); diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h index 205f03b3eaf8..9faae06972b3 100644 --- a/sound/soc/codecs/uda134x.h +++ b/sound/soc/codecs/uda134x.h @@ -31,7 +31,4 @@ #define STATUS0_DAIFMT_MASK (~(7<<1)) #define STATUS0_SYSCLK_MASK (~(3<<4)) -extern struct snd_soc_dai uda134x_dai; -extern struct snd_soc_codec_device soc_codec_dev_uda134x; - #endif diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 2f925a27dcde..1a51c816e542 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -33,11 +33,9 @@ #include "uda1380.h" -static struct snd_soc_codec *uda1380_codec; - /* codec private data */ struct uda1380_priv { - struct snd_soc_codec codec; + struct snd_soc_codec *codec; u16 reg_cache[UDA1380_CACHEREGNUM]; unsigned int dac_clk; struct work_struct work; @@ -135,6 +133,8 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, static void uda1380_flush_work(struct work_struct *work) { + struct uda1380_priv *uda1380 = container_of(work, struct uda1380_priv, work); + struct snd_soc_codec *uda1380_codec = uda1380->codec; int bit, reg; for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { @@ -145,6 +145,7 @@ static void uda1380_flush_work(struct work_struct *work) uda1380_read_reg_cache(uda1380_codec, reg)); clear_bit(bit, &uda1380_cache_dirty); } + } /* declarations of ALSA reg_elem_REAL controls */ @@ -474,8 +475,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); @@ -501,8 +501,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); /* set WSPLL power and divider if running from this clock */ @@ -540,8 +539,7 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); /* shut down WSPLL power if running from this clock */ @@ -604,9 +602,9 @@ static struct snd_soc_dai_ops uda1380_dai_ops_capture = { .set_fmt = uda1380_set_dai_fmt_capture, }; -struct snd_soc_dai uda1380_dai[] = { +static struct snd_soc_dai_driver uda1380_dai[] = { { - .name = "UDA1380", + .name = "uda1380-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -622,7 +620,7 @@ struct snd_soc_dai uda1380_dai[] = { .ops = &uda1380_dai_ops, }, { /* playback only - dual interface */ - .name = "UDA1380", + .name = "uda1380-hifi-playback", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -633,7 +631,7 @@ struct snd_soc_dai uda1380_dai[] = { .ops = &uda1380_dai_ops_playback, }, { /* capture only - dual interface*/ - .name = "UDA1380", + .name = "uda1380-hifi-capture", .capture = { .stream_name = "Capture", .channels_min = 1, @@ -644,21 +642,15 @@ struct snd_soc_dai uda1380_dai[] = { .ops = &uda1380_dai_ops_capture, }, }; -EXPORT_SYMBOL_GPL(uda1380_dai); -static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) +static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int uda1380_resume(struct platform_device *pdev) +static int uda1380_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -673,91 +665,20 @@ static int uda1380_resume(struct platform_device *pdev) return 0; } -static int uda1380_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct uda1380_platform_data *pdata; - int ret = 0; - - if (uda1380_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = uda1380_codec; - codec = uda1380_codec; - pdata = codec->dev->platform_data; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - /* power on device */ - uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - /* set clock input */ - switch (pdata->dac_clk) { - case UDA1380_DAC_CLK_SYSCLK: - uda1380_write(codec, UDA1380_CLK, 0); - break; - case UDA1380_DAC_CLK_WSPLL: - uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); - break; - } - - snd_soc_add_controls(codec, uda1380_snd_controls, - ARRAY_SIZE(uda1380_snd_controls)); - uda1380_add_widgets(codec); - - return ret; - -pcm_err: - return ret; -} - -/* power down chip */ -static int uda1380_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->control_data) - uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_uda1380 = { - .probe = uda1380_probe, - .remove = uda1380_remove, - .suspend = uda1380_suspend, - .resume = uda1380_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); - -static int uda1380_register(struct uda1380_priv *uda1380) +static int uda1380_probe(struct snd_soc_codec *codec) { - int ret, i; - struct snd_soc_codec *codec = &uda1380->codec; - struct uda1380_platform_data *pdata = codec->dev->platform_data; + struct uda1380_platform_data *pdata =codec->dev->platform_data; + struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); + int ret; - if (uda1380_codec) { - dev_err(codec->dev, "Another UDA1380 is registered\n"); - return -EINVAL; - } + codec->hw_write = (hw_write_t)i2c_master_send; if (!pdata || !pdata->gpio_power || !pdata->gpio_reset) return -EINVAL; ret = gpio_request(pdata->gpio_power, "uda1380 power"); if (ret) - goto err_out; + return ret; ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); if (ret) goto err_gpio; @@ -769,25 +690,6 @@ static int uda1380_register(struct uda1380_priv *uda1380) udelay(5); gpio_set_value(pdata->gpio_reset, 0); - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, uda1380); - codec->name = "UDA1380"; - codec->owner = THIS_MODULE; - codec->read = uda1380_read_reg_cache; - codec->write = uda1380_write; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = uda1380_set_bias_level; - codec->dai = uda1380_dai; - codec->num_dai = ARRAY_SIZE(uda1380_dai); - codec->reg_cache_size = ARRAY_SIZE(uda1380_reg); - codec->reg_cache = &uda1380->reg_cache; - codec->reg_cache_step = 1; - - memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg)); - ret = uda1380_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); @@ -796,83 +698,84 @@ static int uda1380_register(struct uda1380_priv *uda1380) INIT_WORK(&uda1380->work, uda1380_flush_work); - for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++) - uda1380_dai[i].dev = codec->dev; - - uda1380_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_reset; + /* power on device */ + uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + /* set clock input */ + switch (pdata->dac_clk) { + case UDA1380_DAC_CLK_SYSCLK: + uda1380_write(codec, UDA1380_CLK, 0); + break; + case UDA1380_DAC_CLK_WSPLL: + uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); + break; } - ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); - goto err_dai; - } + snd_soc_add_controls(codec, uda1380_snd_controls, + ARRAY_SIZE(uda1380_snd_controls)); + uda1380_add_widgets(codec); return 0; -err_dai: - snd_soc_unregister_codec(codec); err_reset: gpio_set_value(pdata->gpio_power, 0); gpio_free(pdata->gpio_reset); err_gpio: gpio_free(pdata->gpio_power); -err_out: return ret; } -static void uda1380_unregister(struct uda1380_priv *uda1380) +/* power down chip */ +static int uda1380_remove(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = &uda1380->codec; - struct uda1380_platform_data *pdata = codec->dev->platform_data; + struct uda1380_platform_data *pdata =codec->dev->platform_data; - snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); - snd_soc_unregister_codec(&uda1380->codec); + uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); gpio_set_value(pdata->gpio_power, 0); gpio_free(pdata->gpio_reset); gpio_free(pdata->gpio_power); - kfree(uda1380); - uda1380_codec = NULL; + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { + .probe = uda1380_probe, + .remove = uda1380_remove, + .suspend = uda1380_suspend, + .resume = uda1380_resume, + .read = uda1380_read_reg_cache, + .write = uda1380_write, + .set_bias_level = uda1380_set_bias_level, + .reg_cache_size = ARRAY_SIZE(uda1380_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = uda1380_reg, + .reg_cache_step = 1, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct uda1380_priv *uda1380; - struct snd_soc_codec *codec; int ret; uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL); if (uda1380 == NULL) return -ENOMEM; - codec = &uda1380->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - i2c_set_clientdata(i2c, uda1380); - codec->control_data = i2c; - - codec->dev = &i2c->dev; - ret = uda1380_register(uda1380); - if (ret != 0) + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai)); + if (ret < 0) kfree(uda1380); - return ret; } static int __devexit uda1380_i2c_remove(struct i2c_client *i2c) { - struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c); - uda1380_unregister(uda1380); + snd_soc_unregister_codec(&i2c->dev); + kfree(i2c_get_clientdata(i2c)); return 0; } @@ -884,7 +787,7 @@ MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); static struct i2c_driver uda1380_i2c_driver = { .driver = { - .name = "UDA1380 I2C Codec", + .name = "uda1380-codec", .owner = THIS_MODULE, }, .probe = uda1380_i2c_probe, diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h index 9cefa8a54770..942e3927c72b 100644 --- a/sound/soc/codecs/uda1380.h +++ b/sound/soc/codecs/uda1380.h @@ -76,7 +76,4 @@ #define UDA1380_DAI_PLAYBACK 1 /* playback DAI */ #define UDA1380_DAI_CAPTURE 2 /* capture DAI */ -extern struct snd_soc_dai uda1380_dai[3]; -extern struct snd_soc_codec_device soc_codec_dev_uda1380; - #endif /* _UDA1380_H */ diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h index c18e261c3c7f..0b6f056f73cc 100644 --- a/sound/soc/codecs/wm2000.h +++ b/sound/soc/codecs/wm2000.h @@ -16,9 +16,6 @@ struct wm2000_setup_data { extern int wm2000_add_controls(struct snd_soc_codec *codec); -extern struct snd_soc_dai wm2000_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm2000; - #define WM2000_REG_SYS_START 0x8000 #define WM2000_REG_SPEECH_CLARITY 0x8fef #define WM2000_REG_SYS_WATCHDOG 0x8ff6 diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 0221ca79b3ae..f4f1fba38eb9 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1321,20 +1321,14 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec, return 0; } -static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8350_resume(struct platform_device *pdev) +static int wm8350_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; @@ -1489,24 +1483,74 @@ int wm8350_mic_jack_detect(struct snd_soc_codec *codec, } EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect); -static struct snd_soc_codec *wm8350_codec; +#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000) + +#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE) + +static struct snd_soc_dai_ops wm8350_dai_ops = { + .hw_params = wm8350_pcm_hw_params, + .digital_mute = wm8350_mute, + .trigger = wm8350_pcm_trigger, + .set_fmt = wm8350_set_dai_fmt, + .set_sysclk = wm8350_set_dai_sysclk, + .set_pll = wm8350_set_fll, + .set_clkdiv = wm8350_set_clkdiv, +}; + +static struct snd_soc_dai_driver wm8350_dai = { + .name = "wm8350-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM8350_RATES, + .formats = WM8350_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM8350_RATES, + .formats = WM8350_FORMATS, + }, + .ops = &wm8350_dai_ops, +}; -static int wm8350_probe(struct platform_device *pdev) +static int wm8350_codec_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct wm8350 *wm8350; + struct wm8350 *wm8350 = dev_get_platdata(codec->dev); struct wm8350_data *priv; - int ret; struct wm8350_output *out1; struct wm8350_output *out2; + int ret, i; - BUG_ON(!wm8350_codec); + if (wm8350->codec.platform_data == NULL) { + dev_err(codec->dev, "No audio platform data supplied\n"); + return -EINVAL; + } + + priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + snd_soc_codec_set_drvdata(codec, priv); + + for (i = 0; i < ARRAY_SIZE(supply_names); i++) + priv->supplies[i].supply = supply_names[i]; + + ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), + priv->supplies); + if (ret != 0) + goto err_priv; + + wm8350->codec.codec = codec; + codec->control_data = wm8350; - socdev->card->codec = wm8350_codec; - codec = socdev->card->codec; - wm8350 = codec->control_data; - priv = snd_soc_codec_get_drvdata(codec); + /* Put the codec into reset if it wasn't already */ + wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); + + INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work); /* Enable the codec */ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); @@ -1557,11 +1601,6 @@ static int wm8350_probe(struct platform_device *pdev) wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD, wm8350_mic_handler, 0, "Microphone detect", priv); - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(&pdev->dev, "failed to create pcms\n"); - return ret; - } snd_soc_add_controls(codec, wm8350_snd_controls, ARRAY_SIZE(wm8350_snd_controls)); @@ -1570,14 +1609,16 @@ static int wm8350_probe(struct platform_device *pdev) wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; + +err_priv: + kfree(priv); + return ret; } -static int wm8350_remove(struct platform_device *pdev) +static int wm8350_codec_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - struct wm8350 *wm8350 = codec->control_data; struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); + struct wm8350 *wm8350 = dev_get_platdata(codec->dev); int ret; wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, @@ -1607,134 +1648,30 @@ static int wm8350_remove(struct platform_device *pdev) wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); + regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); + kfree(priv); return 0; } -#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000) - -#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static struct snd_soc_dai_ops wm8350_dai_ops = { - .hw_params = wm8350_pcm_hw_params, - .digital_mute = wm8350_mute, - .trigger = wm8350_pcm_trigger, - .set_fmt = wm8350_set_dai_fmt, - .set_sysclk = wm8350_set_dai_sysclk, - .set_pll = wm8350_set_fll, - .set_clkdiv = wm8350_set_clkdiv, -}; - -struct snd_soc_dai wm8350_dai = { - .name = "WM8350", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8350_RATES, - .formats = WM8350_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8350_RATES, - .formats = WM8350_FORMATS, - }, - .ops = &wm8350_dai_ops, -}; -EXPORT_SYMBOL_GPL(wm8350_dai); - -struct snd_soc_codec_device soc_codec_dev_wm8350 = { - .probe = wm8350_probe, - .remove = wm8350_remove, +static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { + .probe = wm8350_codec_probe, + .remove = wm8350_codec_remove, .suspend = wm8350_suspend, .resume = wm8350_resume, + .read = wm8350_codec_read, + .write = wm8350_codec_write, + .set_bias_level = wm8350_set_bias_level, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350); -static __devinit int wm8350_codec_probe(struct platform_device *pdev) +static int __devinit wm8350_probe(struct platform_device *pdev) { - struct wm8350 *wm8350 = platform_get_drvdata(pdev); - struct wm8350_data *priv; - struct snd_soc_codec *codec; - int ret, i; - - if (wm8350->codec.platform_data == NULL) { - dev_err(&pdev->dev, "No audio platform data supplied\n"); - return -EINVAL; - } - - priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(supply_names); i++) - priv->supplies[i].supply = supply_names[i]; - - ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), - priv->supplies); - if (ret != 0) - goto err_priv; - - codec = &priv->codec; - wm8350->codec.codec = codec; - - wm8350_dai.dev = &pdev->dev; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - codec->dev = &pdev->dev; - codec->name = "WM8350"; - codec->owner = THIS_MODULE; - codec->read = wm8350_codec_read; - codec->write = wm8350_codec_write; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8350_set_bias_level; - codec->dai = &wm8350_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8350_MAX_REGISTER; - snd_soc_codec_set_drvdata(codec, priv); - codec->control_data = wm8350; - - /* Put the codec into reset if it wasn't already */ - wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); - - INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work); - ret = snd_soc_register_codec(codec); - if (ret != 0) - goto err_supply; - - wm8350_codec = codec; - - ret = snd_soc_register_dai(&wm8350_dai); - if (ret != 0) - goto err_codec; - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err_supply: - regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); -err_priv: - kfree(priv); - wm8350_codec = NULL; - return ret; + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350, + &wm8350_dai, 1); } -static int __devexit wm8350_codec_remove(struct platform_device *pdev) +static int __devexit wm8350_remove(struct platform_device *pdev) { - struct wm8350 *wm8350 = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = wm8350->codec.codec; - struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); - - snd_soc_unregister_dai(&wm8350_dai); - snd_soc_unregister_codec(codec); - regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); - kfree(priv); - wm8350_codec = NULL; + snd_soc_unregister_codec(&pdev->dev); return 0; } @@ -1743,8 +1680,8 @@ static struct platform_driver wm8350_codec_driver = { .name = "wm8350-codec", .owner = THIS_MODULE, }, - .probe = wm8350_codec_probe, - .remove = __devexit_p(wm8350_codec_remove), + .probe = wm8350_probe, + .remove = __devexit_p(wm8350_remove), }; static __init int wm8350_init(void) diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h index 9ed0467c71db..74108eb82938 100644 --- a/sound/soc/codecs/wm8350.h +++ b/sound/soc/codecs/wm8350.h @@ -15,9 +15,6 @@ #include #include -extern struct snd_soc_dai wm8350_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8350; - enum wm8350_jack { WM8350_JDL = 1, WM8350_JDR = 2, diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 8f294066b0ed..850299786e02 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -65,7 +65,7 @@ static struct regulator_bulk_data power[] = { /* codec private data */ struct wm8400_priv { - struct snd_soc_codec codec; + struct snd_soc_codec *codec; struct wm8400 *wm8400; u16 fake_register; unsigned int sysclk; @@ -1163,8 +1163,7 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); audio1 &= ~WM8400_AIF_WL_MASK; @@ -1332,10 +1331,9 @@ static struct snd_soc_dai_ops wm8400_dai_ops = { * 1. ADC/DAC on Primary Interface * 2. ADC on Primary Interface/DAC on secondary */ -struct snd_soc_dai wm8400_dai = { +static struct snd_soc_dai_driver wm8400_dai = { /* ADC/DAC on primary */ - .name = "WM8400 ADC/DAC Primary", - .id = 1, + .name = "wm8400-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -1352,147 +1350,53 @@ struct snd_soc_dai wm8400_dai = { }, .ops = &wm8400_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8400_dai); -static int wm8400_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8400_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8400_resume(struct platform_device *pdev) +static int wm8400_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } -static struct snd_soc_codec *wm8400_codec; - -static int wm8400_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret; - - if (!wm8400_codec) { - dev_err(&pdev->dev, "wm8400 not yet discovered\n"); - return -ENODEV; - } - codec = wm8400_codec; - - socdev->card->codec = codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(&pdev->dev, "failed to create pcms\n"); - goto pcm_err; - } - - wm8400_add_controls(codec); - wm8400_add_widgets(codec); - -pcm_err: - return ret; -} - -/* power down chip */ -static int wm8400_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8400 = { - .probe = wm8400_probe, - .remove = wm8400_remove, - .suspend = wm8400_suspend, - .resume = wm8400_resume, -}; - static void wm8400_probe_deferred(struct work_struct *work) { struct wm8400_priv *priv = container_of(work, struct wm8400_priv, work); - struct snd_soc_codec *codec = &priv->codec; - int ret; + struct snd_soc_codec *codec = priv->codec; /* charge output caps */ wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* We're done, tell the subsystem. */ - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(priv->wm8400->dev, - "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&wm8400_dai); - if (ret != 0) { - dev_err(priv->wm8400->dev, - "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return; - -err_codec: - snd_soc_unregister_codec(codec); -err: - wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); } -static int wm8400_codec_probe(struct platform_device *dev) +static int wm8400_codec_probe(struct snd_soc_codec *codec) { + struct wm8400 *wm8400 = dev_get_platdata(codec->dev); struct wm8400_priv *priv; int ret; u16 reg; - struct snd_soc_codec *codec; priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - codec = &priv->codec; snd_soc_codec_set_drvdata(codec, priv); - codec->control_data = dev_get_drvdata(&dev->dev); - priv->wm8400 = dev_get_drvdata(&dev->dev); + codec->control_data = priv->wm8400 = wm8400; + priv->codec = codec; - ret = regulator_bulk_get(priv->wm8400->dev, + ret = regulator_bulk_get(wm8400->dev, ARRAY_SIZE(power), &power[0]); if (ret != 0) { - dev_err(&dev->dev, "Failed to get regulators: %d\n", ret); + dev_err(codec->dev, "Failed to get regulators: %d\n", ret); goto err; } - codec->dev = &dev->dev; - wm8400_dai.dev = &dev->dev; - - codec->name = "WM8400"; - codec->owner = THIS_MODULE; - codec->read = wm8400_read; - codec->write = wm8400_write; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8400_set_bias_level; - codec->dai = &wm8400_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8400_REGISTER_COUNT; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); INIT_WORK(&priv->work, wm8400_probe_deferred); wm8400_codec_reset(codec); @@ -1511,65 +1415,78 @@ static int wm8400_codec_probe(struct platform_device *dev) wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); - wm8400_codec = codec; - if (!schedule_work(&priv->work)) { ret = -EINVAL; goto err_regulator; } - + wm8400_add_controls(codec); + wm8400_add_widgets(codec); return 0; err_regulator: - wm8400_codec = NULL; regulator_bulk_free(ARRAY_SIZE(power), power); err: kfree(priv); return ret; } -static int __exit wm8400_codec_remove(struct platform_device *dev) +static int wm8400_codec_remove(struct snd_soc_codec *codec) { - struct wm8400_priv *priv = snd_soc_codec_get_drvdata(wm8400_codec); + struct wm8400_priv *priv = snd_soc_codec_get_drvdata(codec); u16 reg; - snd_soc_unregister_dai(&wm8400_dai); - snd_soc_unregister_codec(wm8400_codec); - - reg = wm8400_read(wm8400_codec, WM8400_POWER_MANAGEMENT_1); - wm8400_write(wm8400_codec, WM8400_POWER_MANAGEMENT_1, + reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); + wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, reg & (~WM8400_CODEC_ENA)); regulator_bulk_free(ARRAY_SIZE(power), power); kfree(priv); - wm8400_codec = NULL; + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_wm8400 = { + .probe = wm8400_codec_probe, + .remove = wm8400_codec_remove, + .suspend = wm8400_suspend, + .resume = wm8400_resume, + .read = wm8400_read, + .write = wm8400_write, + .set_bias_level = wm8400_set_bias_level, +}; + +static int __devinit wm8400_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400, + &wm8400_dai, 1); +} +static int __devexit wm8400_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); return 0; } static struct platform_driver wm8400_codec_driver = { .driver = { - .name = "wm8400-codec", - .owner = THIS_MODULE, - }, - .probe = wm8400_codec_probe, - .remove = __exit_p(wm8400_codec_remove), + .name = "wm8400-codec", + .owner = THIS_MODULE, + }, + .probe = wm8400_probe, + .remove = __devexit_p(wm8400_remove), }; -static int __init wm8400_codec_init(void) +static __init int wm8400_init(void) { return platform_driver_register(&wm8400_codec_driver); } -module_init(wm8400_codec_init); +module_init(wm8400_init); -static void __exit wm8400_codec_exit(void) +static __exit void wm8400_exit(void) { platform_driver_unregister(&wm8400_codec_driver); } -module_exit(wm8400_codec_exit); - -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8400); +module_exit(wm8400_exit); MODULE_DESCRIPTION("ASoC WM8400 driver"); MODULE_AUTHOR("Mark Brown"); diff --git a/sound/soc/codecs/wm8400.h b/sound/soc/codecs/wm8400.h index 79c5934d4776..521adb193870 100644 --- a/sound/soc/codecs/wm8400.h +++ b/sound/soc/codecs/wm8400.h @@ -56,7 +56,4 @@ #define WM8400_BCLK_DIV_44 (0xE << 1) #define WM8400_BCLK_DIV_48 (0xF << 1) -extern struct snd_soc_dai wm8400_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8400; - #endif diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 0f7bcb61071a..dbfa05d2cb92 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -31,8 +31,6 @@ #define WM8510_VERSION "0.6" -struct snd_soc_codec_device soc_codec_dev_wm8510; - /* * wm8510 register cache * We can't read the WM8510 register space when we are @@ -61,6 +59,12 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { #define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0) +/* codec private data */ +struct wm8510_priv { + enum snd_soc_control_type control_type; + void *control_data; +}; + static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; static const char *wm8510_alc[] = { "ALC", "Limiter" }; @@ -403,8 +407,7 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f; u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; @@ -514,8 +517,8 @@ static struct snd_soc_dai_ops wm8510_dai_ops = { .set_pll = wm8510_set_dai_pll, }; -struct snd_soc_dai wm8510_dai = { - .name = "WM8510 HiFi", +static struct snd_soc_dai_driver wm8510_dai = { + .name = "wm8510-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -531,21 +534,15 @@ struct snd_soc_dai wm8510_dai = { .ops = &wm8510_dai_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(wm8510_dai); -static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8510_resume(struct platform_device *pdev) +static int wm8510_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -561,43 +558,22 @@ static int wm8510_resume(struct platform_device *pdev) return 0; } -/* - * initialise the WM8510 driver - * register the mixer and dsp interfaces with the kernel - */ -static int wm8510_init(struct snd_soc_device *socdev, - enum snd_soc_control_type control) +static int wm8510_probe(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = socdev->card->codec; - int ret = 0; - - codec->name = "WM8510"; - codec->owner = THIS_MODULE; - codec->set_bias_level = wm8510_set_bias_level; - codec->dai = &wm8510_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(wm8510_reg); - codec->reg_cache = kmemdup(wm8510_reg, sizeof(wm8510_reg), GFP_KERNEL); + struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); + int ret; - if (codec->reg_cache == NULL) - return -ENOMEM; + pr_info("WM8510 Audio Codec %s", WM8510_VERSION); - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + codec->control_data = wm8510->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type); if (ret < 0) { - printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", - ret); - goto err; + printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); + return ret; } wm8510_reset(codec); - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "wm8510: failed to create pcms\n"); - goto err; - } - /* power on device */ codec->bias_level = SND_SOC_BIAS_OFF; wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -606,119 +582,53 @@ static int wm8510_init(struct snd_soc_device *socdev, wm8510_add_widgets(codec); return ret; - -err: - kfree(codec->reg_cache); - return ret; } -static struct snd_soc_device *wm8510_socdev; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -/* - * WM8510 2 wire address is 0x1a - */ - -static int wm8510_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +/* power down chip */ +static int wm8510_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = wm8510_socdev; - struct snd_soc_codec *codec = socdev->card->codec; - int ret; - - i2c_set_clientdata(i2c, codec); - codec->control_data = i2c; - - ret = wm8510_init(socdev, SND_SOC_I2C); - if (ret < 0) - pr_err("failed to initialise WM8510\n"); - - return ret; -} + struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); -static int wm8510_i2c_remove(struct i2c_client *client) -{ - struct snd_soc_codec *codec = i2c_get_clientdata(client); - kfree(codec->reg_cache); + wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); + kfree(wm8510); return 0; } -static const struct i2c_device_id wm8510_i2c_id[] = { - { "wm8510", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); - -static struct i2c_driver wm8510_i2c_driver = { - .driver = { - .name = "WM8510 I2C Codec", - .owner = THIS_MODULE, - }, - .probe = wm8510_i2c_probe, - .remove = wm8510_i2c_remove, - .id_table = wm8510_i2c_id, +static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { + .probe = wm8510_probe, + .remove = wm8510_remove, + .suspend = wm8510_suspend, + .resume = wm8510_resume, + .set_bias_level = wm8510_set_bias_level, + .reg_cache_size = ARRAY_SIZE(wm8510_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default =wm8510_reg, }; -static int wm8510_add_i2c_device(struct platform_device *pdev, - const struct wm8510_setup_data *setup) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - int ret; - - ret = i2c_add_driver(&wm8510_i2c_driver); - if (ret != 0) { - dev_err(&pdev->dev, "can't add i2c driver\n"); - return ret; - } - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = setup->i2c_address; - strlcpy(info.type, "wm8510", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(setup->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "can't get i2c adapter %d\n", - setup->i2c_bus); - goto err_driver; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - goto err_driver; - } - - return 0; - -err_driver: - i2c_del_driver(&wm8510_i2c_driver); - return -ENODEV; -} -#endif - #if defined(CONFIG_SPI_MASTER) static int __devinit wm8510_spi_probe(struct spi_device *spi) { - struct snd_soc_device *socdev = wm8510_socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct wm8510_priv *wm8510; int ret; - codec->control_data = spi; + wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); + if (wm8510 == NULL) + return -ENOMEM; + + wm8510->control_data = spi; + wm8510->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, wm8510); - ret = wm8510_init(socdev, SND_SOC_SPI); + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8510, &wm8510_dai, 1); if (ret < 0) - dev_err(&spi->dev, "failed to initialise WM8510\n"); - + kfree(wm8510); return ret; } static int __devexit wm8510_spi_remove(struct spi_device *spi) { + snd_soc_unregister_codec(&spi->dev); return 0; } @@ -733,84 +643,80 @@ static struct spi_driver wm8510_spi_driver = { }; #endif /* CONFIG_SPI_MASTER */ -static int wm8510_probe(struct platform_device *pdev) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct wm8510_setup_data *setup; - struct snd_soc_codec *codec; - int ret = 0; - - pr_info("WM8510 Audio Codec %s", WM8510_VERSION); + struct wm8510_priv *wm8510; + int ret; - setup = socdev->codec_data; - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) + wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); + if (wm8510 == NULL) return -ENOMEM; - socdev->card->codec = codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); + i2c_set_clientdata(i2c, wm8510); + wm8510->control_data = i2c; + wm8510->control_type = SND_SOC_I2C; - wm8510_socdev = socdev; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - if (setup->i2c_address) { - ret = wm8510_add_i2c_device(pdev, setup); - } -#endif -#if defined(CONFIG_SPI_MASTER) - if (setup->spi) { - ret = spi_register_driver(&wm8510_spi_driver); - if (ret != 0) - printk(KERN_ERR "can't add spi driver"); - } -#endif - - if (ret != 0) - kfree(codec); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8510, &wm8510_dai, 1); + if (ret < 0) + kfree(wm8510); return ret; } -/* power down chip */ -static int wm8510_remove(struct platform_device *pdev) +static __devexit int wm8510_i2c_remove(struct i2c_client *client) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->control_data) - wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_unregister_device(codec->control_data); - i2c_del_driver(&wm8510_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8510_spi_driver); -#endif - kfree(codec); - + snd_soc_unregister_codec(&client->dev); return 0; } -struct snd_soc_codec_device soc_codec_dev_wm8510 = { - .probe = wm8510_probe, - .remove = wm8510_remove, - .suspend = wm8510_suspend, - .resume = wm8510_resume, +static const struct i2c_device_id wm8510_i2c_id[] = { + { "wm8510", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); + +static struct i2c_driver wm8510_i2c_driver = { + .driver = { + .name = "wm8510-codec", + .owner = THIS_MODULE, + }, + .probe = wm8510_i2c_probe, + .remove = __devexit_p(wm8510_i2c_remove), + .id_table = wm8510_i2c_id, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510); +#endif static int __init wm8510_modinit(void) { - return snd_soc_register_dai(&wm8510_dai); + int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + ret = i2c_add_driver(&wm8510_i2c_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n", + ret); + } +#endif +#if defined(CONFIG_SPI_MASTER) + ret = spi_register_driver(&wm8510_spi_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register WM8510 SPI driver: %d\n", + ret); + } +#endif + return ret; } module_init(wm8510_modinit); static void __exit wm8510_exit(void) { - snd_soc_unregister_dai(&wm8510_dai); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_del_driver(&wm8510_i2c_driver); +#endif +#if defined(CONFIG_SPI_MASTER) + spi_unregister_driver(&wm8510_spi_driver); +#endif } module_exit(wm8510_exit); diff --git a/sound/soc/codecs/wm8510.h b/sound/soc/codecs/wm8510.h index bdefcf5c69ff..b3e26ed9f2d0 100644 --- a/sound/soc/codecs/wm8510.h +++ b/sound/soc/codecs/wm8510.h @@ -99,7 +99,4 @@ struct wm8510_setup_data { unsigned short i2c_address; }; -extern struct snd_soc_dai wm8510_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8510; - #endif diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 0ad039b4adf5..58d411b6faaf 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -30,9 +30,6 @@ #include "wm8523.h" -static struct snd_soc_codec *wm8523_codec; -struct snd_soc_codec_device soc_codec_dev_wm8523; - #define WM8523_NUM_SUPPLIES 2 static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { "AVDD", @@ -43,7 +40,8 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { /* codec private data */ struct wm8523_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; u16 reg_cache[WM8523_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; unsigned int sysclk; @@ -162,8 +160,7 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); int i; u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); @@ -387,8 +384,8 @@ static struct snd_soc_dai_ops wm8523_dai_ops = { .set_fmt = wm8523_set_dai_fmt, }; -struct snd_soc_dai wm8523_dai = { - .name = "WM8523", +static struct snd_soc_dai_driver wm8523_dai = { + .name = "wm8523-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, /* Mono modes not yet supported */ @@ -398,25 +395,17 @@ struct snd_soc_dai wm8523_dai = { }, .ops = &wm8523_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8523_dai); #ifdef CONFIG_PM -static int wm8523_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8523_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8523_resume(struct platform_device *pdev) +static int wm8523_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; } #else @@ -424,93 +413,21 @@ static int wm8523_resume(struct platform_device *pdev) #define wm8523_resume NULL #endif -static int wm8523_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8523_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8523_codec; - codec = wm8523_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8523_snd_controls, - ARRAY_SIZE(wm8523_snd_controls)); - wm8523_add_widgets(codec); - - return ret; - -pcm_err: - return ret; -} - -static int wm8523_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8523 = { - .probe = wm8523_probe, - .remove = wm8523_remove, - .suspend = wm8523_suspend, - .resume = wm8523_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523); - -static int wm8523_register(struct wm8523_priv *wm8523, - enum snd_soc_control_type control) +static int wm8523_probe(struct snd_soc_codec *codec) { - int ret; - struct snd_soc_codec *codec = &wm8523->codec; - int i; - - if (wm8523_codec) { - dev_err(codec->dev, "Another WM8523 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8523); - codec->name = "WM8523"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8523_set_bias_level; - codec->dai = &wm8523_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8523_REGISTER_COUNT; - codec->reg_cache = &wm8523->reg_cache; - codec->volatile_register = wm8523_volatile_register; + struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); + int ret, i; + codec->hw_write = (hw_write_t)i2c_master_send; + codec->control_data = wm8523->control_data; wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; wm8523->rate_constraint.count = ARRAY_SIZE(wm8523->rate_constraint_list); - memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg)); - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); + ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + return ret; } for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) @@ -520,7 +437,7 @@ static int wm8523_register(struct wm8523_priv *wm8523, wm8523->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; + return ret; } ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), @@ -555,8 +472,6 @@ static int wm8523_register(struct wm8523_priv *wm8523, goto err_enable; } - wm8523_dai.dev = codec->dev; - /* Change some default settings - latch VU and enable ZC */ wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; @@ -566,69 +481,68 @@ static int wm8523_register(struct wm8523_priv *wm8523, /* Bias level configuration will have done an extra enable */ regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - wm8523_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_enable; - } - - ret = snd_soc_register_dai(&wm8523_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } + snd_soc_add_controls(codec, wm8523_snd_controls, + ARRAY_SIZE(wm8523_snd_controls)); + wm8523_add_widgets(codec); return 0; -err_codec: - snd_soc_unregister_codec(codec); err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); err_get: regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); -err: - kfree(wm8523); + return ret; } -static void wm8523_unregister(struct wm8523_priv *wm8523) +static int wm8523_remove(struct snd_soc_codec *codec) { - wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF); + struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); + + wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - snd_soc_unregister_dai(&wm8523_dai); - snd_soc_unregister_codec(&wm8523->codec); - kfree(wm8523); - wm8523_codec = NULL; + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { + .probe = wm8523_probe, + .remove = wm8523_remove, + .suspend = wm8523_suspend, + .resume = wm8523_resume, + .set_bias_level = wm8523_set_bias_level, + .reg_cache_size = WM8523_REGISTER_COUNT, + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8523_reg, + .volatile_register = wm8523_volatile_register, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8523_priv *wm8523; - struct snd_soc_codec *codec; + int ret; wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); if (wm8523 == NULL) return -ENOMEM; - codec = &wm8523->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - i2c_set_clientdata(i2c, wm8523); - codec->control_data = i2c; + wm8523->control_data = i2c; + wm8523->control_type = SND_SOC_I2C; - codec->dev = &i2c->dev; + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8523, &wm8523_dai, 1); + if (ret < 0) + kfree(wm8523); + return ret; - return wm8523_register(wm8523, SND_SOC_I2C); } static __devexit int wm8523_i2c_remove(struct i2c_client *client) { - struct wm8523_priv *wm8523 = i2c_get_clientdata(client); - wm8523_unregister(wm8523); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -640,7 +554,7 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); static struct i2c_driver wm8523_i2c_driver = { .driver = { - .name = "WM8523", + .name = "wm8523-codec", .owner = THIS_MODULE, }, .probe = wm8523_i2c_probe, diff --git a/sound/soc/codecs/wm8523.h b/sound/soc/codecs/wm8523.h index 1aa9ce3e1357..4d5b1eb8f2fc 100644 --- a/sound/soc/codecs/wm8523.h +++ b/sound/soc/codecs/wm8523.h @@ -154,7 +154,4 @@ #define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */ #define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */ -extern struct snd_soc_dai wm8523_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8523; - #endif diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index c3571ee5c11b..cae58941a32f 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -199,7 +199,8 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { /* codec private data */ struct wm8580_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; u16 reg_cache[WM8580_MAX_REGISTER + 1]; struct pll_state a; @@ -484,9 +485,8 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id); + struct snd_soc_codec *codec = rtd->codec; + u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->driver->id); paifb &= ~WM8580_AIF_LENGTH_MASK; /* bit size */ @@ -506,7 +506,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb); + snd_soc_write(codec, WM8580_PAIF3 + dai->driver->id, paifb); return 0; } @@ -518,8 +518,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int aifb; int can_invert_lrclk; - aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id); - aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id); + aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->driver->id); + aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->driver->id); aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); @@ -585,8 +585,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); - snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); + snd_soc_write(codec, WM8580_PAIF1 + codec_dai->driver->id, aifa); + snd_soc_write(codec, WM8580_PAIF3 + codec_dai->driver->id, aifb); return 0; } @@ -746,10 +746,10 @@ static struct snd_soc_dai_ops wm8580_dai_ops_capture = { .set_pll = wm8580_set_dai_pll, }; -struct snd_soc_dai wm8580_dai[] = { +static struct snd_soc_dai_driver wm8580_dai[] = { { - .name = "WM8580 PAIFRX", - .id = 0, + .name = "wm8580-hifi-playback", + .id = WM8580_DAI_PAIFRX, .playback = { .stream_name = "Playback", .channels_min = 1, @@ -760,8 +760,8 @@ struct snd_soc_dai wm8580_dai[] = { .ops = &wm8580_dai_ops_playback, }, { - .name = "WM8580 PAIFTX", - .id = 1, + .name = "wm8580-hifi-capture", + .id = WM8580_DAI_PAIFTX, .capture = { .stream_name = "Capture", .channels_min = 2, @@ -772,90 +772,17 @@ struct snd_soc_dai wm8580_dai[] = { .ops = &wm8580_dai_ops_capture, }, }; -EXPORT_SYMBOL_GPL(wm8580_dai); -static struct snd_soc_codec *wm8580_codec; - -static int wm8580_probe(struct platform_device *pdev) +static int wm8580_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8580_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8580_codec; - codec = wm8580_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8580_snd_controls, - ARRAY_SIZE(wm8580_snd_controls)); - wm8580_add_widgets(codec); - - return ret; - -pcm_err: - return ret; -} - -/* power down chip */ -static int wm8580_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8580 = { - .probe = wm8580_probe, - .remove = wm8580_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); - -static int wm8580_register(struct wm8580_priv *wm8580, - enum snd_soc_control_type control) -{ - int ret, i; - struct snd_soc_codec *codec = &wm8580->codec; - - if (wm8580_codec) { - dev_err(codec->dev, "Another WM8580 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8580); - codec->name = "WM8580"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8580_set_bias_level; - codec->dai = wm8580_dai; - codec->num_dai = ARRAY_SIZE(wm8580_dai); - codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache); - codec->reg_cache = &wm8580->reg_cache; - - memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); + struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); + int ret = 0,i; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + codec->control_data = wm8580->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + return ret; } for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) @@ -865,7 +792,7 @@ static int wm8580_register(struct wm8580_priv *wm8580, wm8580->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; + return ret; } ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), @@ -882,74 +809,69 @@ static int wm8580_register(struct wm8580_priv *wm8580, goto err_regulator_enable; } - for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) - wm8580_dai[i].dev = codec->dev; - wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm8580_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_regulator_enable; - } - - ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } + snd_soc_add_controls(codec, wm8580_snd_controls, + ARRAY_SIZE(wm8580_snd_controls)); + wm8580_add_widgets(codec); return 0; -err_codec: - snd_soc_unregister_codec(codec); err_regulator_enable: regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); err_regulator_get: regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); -err: - kfree(wm8580); return ret; } -static void wm8580_unregister(struct wm8580_priv *wm8580) +/* power down chip */ +static int wm8580_remove(struct snd_soc_codec *codec) { - wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); - snd_soc_unregister_codec(&wm8580->codec); + struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); + + wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); + regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); - kfree(wm8580); - wm8580_codec = NULL; + + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { + .probe = wm8580_probe, + .remove = wm8580_remove, + .set_bias_level = wm8580_set_bias_level, + .reg_cache_size = sizeof(wm8580_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = &wm8580_reg, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static int wm8580_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8580_priv *wm8580; - struct snd_soc_codec *codec; + int ret; wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); if (wm8580 == NULL) return -ENOMEM; - codec = &wm8580->codec; - i2c_set_clientdata(i2c, wm8580); - codec->control_data = i2c; - - codec->dev = &i2c->dev; + wm8580->control_data = i2c; + wm8580->control_type = SND_SOC_I2C; - return wm8580_register(wm8580, SND_SOC_I2C); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); + if (ret < 0) + kfree(wm8580); + return ret; } static int wm8580_i2c_remove(struct i2c_client *client) { - struct wm8580_priv *wm8580 = i2c_get_clientdata(client); - wm8580_unregister(wm8580); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -961,7 +883,7 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); static struct i2c_driver wm8580_i2c_driver = { .driver = { - .name = "wm8580", + .name = "wm8580-codec", .owner = THIS_MODULE, }, .probe = wm8580_i2c_probe, @@ -972,7 +894,7 @@ static struct i2c_driver wm8580_i2c_driver = { static int __init wm8580_modinit(void) { - int ret; + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8580_i2c_driver); @@ -981,7 +903,7 @@ static int __init wm8580_modinit(void) } #endif - return 0; + return ret; } module_init(wm8580_modinit); diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h index 0dfb5ddde6a2..8328ef667593 100644 --- a/sound/soc/codecs/wm8580.h +++ b/sound/soc/codecs/wm8580.h @@ -31,8 +31,5 @@ #define WM8580_DAI_PAIFRX 0 #define WM8580_DAI_PAIFTX 1 -extern struct snd_soc_dai wm8580_dai[]; -extern struct snd_soc_codec_device soc_codec_dev_wm8580; - #endif diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index e2dba07f0260..8d942b3b111f 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -31,11 +31,10 @@ #include "wm8711.h" -static struct snd_soc_codec *wm8711_codec; - /* codec private data */ struct wm8711_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type bus_type; + void *control_data; u16 reg_cache[WM8711_CACHEREGNUM]; unsigned int sysclk; }; @@ -163,7 +162,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; - struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); + struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc; int i = get_coeff(wm8711->sysclk, params_rate(params)); u16 srate = (coeff_div[i].sr << 2) | @@ -227,7 +226,7 @@ static int wm8711_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) { struct snd_soc_codec *codec = codec_dai->codec; - struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); + struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); switch (freq) { case 11289600: @@ -338,8 +337,8 @@ static struct snd_soc_dai_ops wm8711_ops = { .set_fmt = wm8711_set_dai_fmt, }; -struct snd_soc_dai wm8711_dai = { - .name = "WM8711", +static struct snd_soc_dai_driver wm8711_dai = { + .name = "wm8711-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -349,22 +348,16 @@ struct snd_soc_dai wm8711_dai = { }, .ops = &wm8711_ops, }; -EXPORT_SYMBOL_GPL(wm8711_dai); -static int wm8711_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - snd_soc_write(codec, WM8711_ACTIVE, 0x0); wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8711_resume(struct platform_device *pdev) +static int wm8711_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -380,99 +373,24 @@ static int wm8711_resume(struct platform_device *pdev) return 0; } -static int wm8711_probe(struct platform_device *pdev) +static int wm8711_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8711_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8711_codec; - codec = wm8711_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8711_snd_controls, - ARRAY_SIZE(wm8711_snd_controls)); - wm8711_add_widgets(codec); - - return ret; - -pcm_err: - return ret; -} - -/* power down chip */ -static int wm8711_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8711 = { - .probe = wm8711_probe, - .remove = wm8711_remove, - .suspend = wm8711_suspend, - .resume = wm8711_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711); - -static int wm8711_register(struct wm8711_priv *wm8711, - enum snd_soc_control_type control) -{ - int ret; - struct snd_soc_codec *codec = &wm8711->codec; - u16 reg; - - if (wm8711_codec) { - dev_err(codec->dev, "Another WM8711 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8711); - codec->name = "WM8711"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8711_set_bias_level; - codec->dai = &wm8711_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8711_CACHEREGNUM; - codec->reg_cache = &wm8711->reg_cache; - - memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg)); + struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); + int ret, reg; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + codec->control_data = wm8711->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + return ret; } ret = wm8711_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); - goto err; + return ret; } - wm8711_dai.dev = codec->dev; - wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the update bits */ @@ -481,69 +399,63 @@ static int wm8711_register(struct wm8711_priv *wm8711, reg = snd_soc_read(codec, WM8711_ROUT1V); snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); - wm8711_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&wm8711_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return 0; + snd_soc_add_controls(codec, wm8711_snd_controls, + ARRAY_SIZE(wm8711_snd_controls)); + wm8711_add_widgets(codec); -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8711); return ret; + } -static void wm8711_unregister(struct wm8711_priv *wm8711) +/* power down chip */ +static int wm8711_remove(struct snd_soc_codec *codec) { - wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm8711_dai); - snd_soc_unregister_codec(&wm8711->codec); - kfree(wm8711); - wm8711_codec = NULL; + wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { + .probe = wm8711_probe, + .remove = wm8711_remove, + .suspend = wm8711_suspend, + .resume = wm8711_resume, + .set_bias_level = wm8711_set_bias_level, + .reg_cache_size = sizeof(wm8711_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8711_reg, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8711_spi_probe(struct spi_device *spi) { - struct snd_soc_codec *codec; struct wm8711_priv *wm8711; + int ret; wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); if (wm8711 == NULL) return -ENOMEM; - codec = &wm8711->codec; - codec->control_data = spi; - codec->dev = &spi->dev; + spi_set_drvdata(spi, wm8711); + wm8711->control_data = spi; + wm8711->bus_type = SND_SOC_SPI; - dev_set_drvdata(&spi->dev, wm8711); - - return wm8711_register(wm8711, SND_SOC_SPI); + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8711, &wm8711_dai, 1); + if (ret < 0) + kfree(wm8711); + return ret; } static int __devexit wm8711_spi_remove(struct spi_device *spi) { - struct wm8711_priv *wm8711 = dev_get_drvdata(&spi->dev); - - wm8711_unregister(wm8711); - + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); return 0; } static struct spi_driver wm8711_spi_driver = { .driver = { - .name = "wm8711", + .name = "wm8711-codec", .bus = &spi_bus_type, .owner = THIS_MODULE, }, @@ -553,31 +465,31 @@ static struct spi_driver wm8711_spi_driver = { #endif /* CONFIG_SPI_MASTER */ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8711_i2c_probe(struct i2c_client *i2c, +static __devinit int wm8711_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct wm8711_priv *wm8711; - struct snd_soc_codec *codec; + int ret; wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); if (wm8711 == NULL) return -ENOMEM; - codec = &wm8711->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - - i2c_set_clientdata(i2c, wm8711); - codec->control_data = i2c; + i2c_set_clientdata(client, wm8711); + wm8711->control_data = client; + wm8711->bus_type = SND_SOC_I2C; - codec->dev = &i2c->dev; - - return wm8711_register(wm8711, SND_SOC_I2C); + ret = snd_soc_register_codec(&client->dev, + &soc_codec_dev_wm8711, &wm8711_dai, 1); + if (ret < 0) + kfree(wm8711); + return ret; } static __devexit int wm8711_i2c_remove(struct i2c_client *client) { - struct wm8711_priv *wm8711 = i2c_get_clientdata(client); - wm8711_unregister(wm8711); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -589,7 +501,7 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); static struct i2c_driver wm8711_i2c_driver = { .driver = { - .name = "WM8711 I2C Codec", + .name = "wm8711-codec", .owner = THIS_MODULE, }, .probe = wm8711_i2c_probe, diff --git a/sound/soc/codecs/wm8711.h b/sound/soc/codecs/wm8711.h index 381e84a43816..a61db985499f 100644 --- a/sound/soc/codecs/wm8711.h +++ b/sound/soc/codecs/wm8711.h @@ -36,7 +36,4 @@ struct wm8711_setup_data { unsigned short i2c_address; }; -extern struct snd_soc_dai wm8711_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8711; - #endif diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c index 9d1df2628136..6a40080ba701 100644 --- a/sound/soc/codecs/wm8727.c +++ b/sound/soc/codecs/wm8727.c @@ -23,7 +23,6 @@ #include #include -#include "wm8727.h" /* * Note this is a simple chip with no configuration interface, sample rate is * determined automatically by examining the Master clock and Bit clock ratios @@ -33,8 +32,8 @@ SNDRV_PCM_RATE_192000) -struct snd_soc_dai wm8727_dai = { - .name = "WM8727", +static struct snd_soc_dai_driver wm8727_dai = { + .name = "wm8727-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -43,103 +42,18 @@ struct snd_soc_dai wm8727_dai = { .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, }, }; -EXPORT_SYMBOL_GPL(wm8727_dai); -static struct snd_soc_codec *wm8727_codec; +struct snd_soc_codec_driver soc_codec_dev_wm8727; -static int wm8727_soc_probe(struct platform_device *pdev) +static __devinit int wm8727_probe(struct platform_device *pdev) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - int ret = 0; - - BUG_ON(!wm8727_codec); - - socdev->card->codec = wm8727_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "wm8727: failed to create pcms\n"); - goto pcm_err; - } - - return ret; - -pcm_err: - kfree(socdev->card->codec); - socdev->card->codec = NULL; - return ret; -} - -static int wm8727_soc_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8727 = { - .probe = wm8727_soc_probe, - .remove = wm8727_soc_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8727); - - -static __devinit int wm8727_platform_probe(struct platform_device *pdev) -{ - struct snd_soc_codec *codec; - int ret; - - if (wm8727_codec) { - dev_err(&pdev->dev, "Another WM8727 is registered\n"); - return -EBUSY; - } - - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) - return -ENOMEM; - wm8727_codec = codec; - - platform_set_drvdata(pdev, codec); - - mutex_init(&codec->mutex); - codec->dev = &pdev->dev; - codec->name = "WM8727"; - codec->owner = THIS_MODULE; - codec->dai = &wm8727_dai; - codec->num_dai = 1; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - wm8727_dai.dev = &pdev->dev; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to register CODEC: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&wm8727_dai); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(codec); - return ret; + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_wm8727, &wm8727_dai, 1); } -static int __devexit wm8727_platform_remove(struct platform_device *pdev) +static int __devexit wm8727_remove(struct platform_device *pdev) { - snd_soc_unregister_dai(&wm8727_dai); - snd_soc_unregister_codec(platform_get_drvdata(pdev)); + snd_soc_unregister_codec(&pdev->dev); return 0; } @@ -149,8 +63,8 @@ static struct platform_driver wm8727_codec_driver = { .owner = THIS_MODULE, }, - .probe = wm8727_platform_probe, - .remove = __devexit_p(wm8727_platform_remove), + .probe = wm8727_probe, + .remove = __devexit_p(wm8727_remove), }; static int __init wm8727_init(void) diff --git a/sound/soc/codecs/wm8727.h b/sound/soc/codecs/wm8727.h deleted file mode 100644 index ee19aa71bcdc..000000000000 --- a/sound/soc/codecs/wm8727.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * wm8727.h - * - * Created on: 15-Oct-2009 - * Author: neil.jones@imgtec.com - * - * Copyright (C) 2009 Imagination Technologies Ltd. - * - * 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. - */ - -#ifndef WM8727_H_ -#define WM8727_H_ - -extern struct snd_soc_dai wm8727_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8727; - -#endif /* WM8727_H_ */ diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 34be2d2b69ef..ae2292444783 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -29,8 +29,6 @@ #include "wm8728.h" -struct snd_soc_codec_device soc_codec_dev_wm8728; - /* * We can't read the WM8728 register space so we cache them instead. * Note that the defaults here aren't the physical defaults, we latch @@ -44,6 +42,12 @@ static const u16 wm8728_reg_defaults[] = { 0x100, }; +/* codec private data */ +struct wm8728_priv { + enum snd_soc_control_type control_type; + void *control_data; +}; + static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); static const struct snd_kcontrol_new wm8728_snd_controls[] = { @@ -96,8 +100,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u16 dac = snd_soc_read(codec, WM8728_DACCTL); dac &= ~0x18; @@ -210,8 +213,8 @@ static struct snd_soc_dai_ops wm8728_dai_ops = { .set_fmt = wm8728_set_dai_fmt, }; -struct snd_soc_dai wm8728_dai = { - .name = "WM8728", +static struct snd_soc_dai_driver wm8728_dai = { + .name = "wm8728-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -221,63 +224,32 @@ struct snd_soc_dai wm8728_dai = { }, .ops = &wm8728_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8728_dai); -static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8728_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8728_resume(struct platform_device *pdev) +static int wm8728_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } -/* - * initialise the WM8728 driver - * register the mixer and dsp interfaces with the kernel - */ -static int wm8728_init(struct snd_soc_device *socdev, - enum snd_soc_control_type control) +static int wm8728_probe(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = socdev->card->codec; - int ret = 0; - - codec->name = "WM8728"; - codec->owner = THIS_MODULE; - codec->set_bias_level = wm8728_set_bias_level; - codec->dai = &wm8728_dai; - codec->num_dai = 1; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults); - codec->reg_cache = kmemdup(wm8728_reg_defaults, - sizeof(wm8728_reg_defaults), - GFP_KERNEL); - if (codec->reg_cache == NULL) - return -ENOMEM; + struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); + int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + codec->control_data = wm8728->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type); if (ret < 0) { printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", ret); - goto err; - } - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "wm8728: failed to create pcms\n"); - goto err; + return ret; } /* power on device */ @@ -288,128 +260,56 @@ static int wm8728_init(struct snd_soc_device *socdev, wm8728_add_widgets(codec); return ret; - -err: - kfree(codec->reg_cache); - return ret; } -static struct snd_soc_device *wm8728_socdev; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -/* - * WM8728 2 wire address is determined by GPIO5 - * state during powerup. - * low = 0x1a - * high = 0x1b - */ - -static int wm8728_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int wm8728_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = wm8728_socdev; - struct snd_soc_codec *codec = socdev->card->codec; - int ret; - - i2c_set_clientdata(i2c, codec); - codec->control_data = i2c; - - ret = wm8728_init(socdev, SND_SOC_I2C); - if (ret < 0) - pr_err("failed to initialise WM8728\n"); - - return ret; -} - -static int wm8728_i2c_remove(struct i2c_client *client) -{ - struct snd_soc_codec *codec = i2c_get_clientdata(client); - kfree(codec->reg_cache); + wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static const struct i2c_device_id wm8728_i2c_id[] = { - { "wm8728", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); - -static struct i2c_driver wm8728_i2c_driver = { - .driver = { - .name = "WM8728 I2C Codec", - .owner = THIS_MODULE, - }, - .probe = wm8728_i2c_probe, - .remove = wm8728_i2c_remove, - .id_table = wm8728_i2c_id, +static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { + .probe = wm8728_probe, + .remove = wm8728_remove, + .suspend = wm8728_suspend, + .resume = wm8728_resume, + .set_bias_level = wm8728_set_bias_level, + .reg_cache_size = sizeof(wm8728_reg_defaults), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8728_reg_defaults, }; -static int wm8728_add_i2c_device(struct platform_device *pdev, - const struct wm8728_setup_data *setup) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - int ret; - - ret = i2c_add_driver(&wm8728_i2c_driver); - if (ret != 0) { - dev_err(&pdev->dev, "can't add i2c driver\n"); - return ret; - } - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = setup->i2c_address; - strlcpy(info.type, "wm8728", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(setup->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "can't get i2c adapter %d\n", - setup->i2c_bus); - goto err_driver; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - goto err_driver; - } - - return 0; - -err_driver: - i2c_del_driver(&wm8728_i2c_driver); - return -ENODEV; -} -#endif - #if defined(CONFIG_SPI_MASTER) static int __devinit wm8728_spi_probe(struct spi_device *spi) { - struct snd_soc_device *socdev = wm8728_socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct wm8728_priv *wm8728; int ret; - codec->control_data = spi; + wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); + if (wm8728 == NULL) + return -ENOMEM; - ret = wm8728_init(socdev, SND_SOC_SPI); - if (ret < 0) - dev_err(&spi->dev, "failed to initialise WM8728\n"); + wm8728->control_data = spi; + wm8728->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, wm8728); + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8728, &wm8728_dai, 1); + if (ret < 0) + kfree(wm8728); return ret; } static int __devexit wm8728_spi_remove(struct spi_device *spi) { + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); return 0; } static struct spi_driver wm8728_spi_driver = { .driver = { - .name = "wm8728", + .name = "wm8728-codec", .bus = &spi_bus_type, .owner = THIS_MODULE, }, @@ -418,85 +318,81 @@ static struct spi_driver wm8728_spi_driver = { }; #endif /* CONFIG_SPI_MASTER */ -static int wm8728_probe(struct platform_device *pdev) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct wm8728_setup_data *setup; - struct snd_soc_codec *codec; - int ret = 0; + struct wm8728_priv *wm8728; + int ret; - setup = socdev->codec_data; - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) + wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); + if (wm8728 == NULL) return -ENOMEM; - socdev->card->codec = codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); + i2c_set_clientdata(i2c, wm8728); + wm8728->control_data = i2c; + wm8728->control_type = SND_SOC_I2C; + + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8728, &wm8728_dai, 1); + if (ret < 0) + kfree(wm8728); + return ret; +} + +static __devexit int wm8728_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); + return 0; +} - wm8728_socdev = socdev; - ret = -ENODEV; +static const struct i2c_device_id wm8728_i2c_id[] = { + { "wm8728", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); + +static struct i2c_driver wm8728_i2c_driver = { + .driver = { + .name = "wm8728-codec", + .owner = THIS_MODULE, + }, + .probe = wm8728_i2c_probe, + .remove = __devexit_p(wm8728_i2c_remove), + .id_table = wm8728_i2c_id, +}; +#endif +static int __init wm8728_modinit(void) +{ + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - if (setup->i2c_address) { - ret = wm8728_add_i2c_device(pdev, setup); + ret = i2c_add_driver(&wm8728_i2c_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n", + ret); } #endif #if defined(CONFIG_SPI_MASTER) - if (setup->spi) { - ret = spi_register_driver(&wm8728_spi_driver); - if (ret != 0) - printk(KERN_ERR "can't add spi driver"); + ret = spi_register_driver(&wm8728_spi_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8728 SPI driver: %d\n", + ret); } #endif - - if (ret != 0) - kfree(codec); - return ret; } +module_init(wm8728_modinit); -/* power down chip */ -static int wm8728_remove(struct platform_device *pdev) +static void __exit wm8728_exit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->control_data) - wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_unregister_device(codec->control_data); i2c_del_driver(&wm8728_i2c_driver); #endif #if defined(CONFIG_SPI_MASTER) spi_unregister_driver(&wm8728_spi_driver); #endif - kfree(codec); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8728 = { - .probe = wm8728_probe, - .remove = wm8728_remove, - .suspend = wm8728_suspend, - .resume = wm8728_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728); - -static int __init wm8728_modinit(void) -{ - return snd_soc_register_dai(&wm8728_dai); -} -module_init(wm8728_modinit); - -static void __exit wm8728_exit(void) -{ - snd_soc_unregister_dai(&wm8728_dai); } module_exit(wm8728_exit); diff --git a/sound/soc/codecs/wm8728.h b/sound/soc/codecs/wm8728.h index d269c132474b..8aea362ffd47 100644 --- a/sound/soc/codecs/wm8728.h +++ b/sound/soc/codecs/wm8728.h @@ -18,13 +18,4 @@ #define WM8728_DACCTL 0x02 #define WM8728_IFCTL 0x03 -struct wm8728_setup_data { - int spi; - int i2c_bus; - unsigned short i2c_address; -}; - -extern struct snd_soc_dai wm8728_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8728; - #endif diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 0ab9b6355297..7da360ee1fee 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -32,9 +32,6 @@ #include "wm8731.h" -static struct snd_soc_codec *wm8731_codec; -struct snd_soc_codec_device soc_codec_dev_wm8731; - #define WM8731_NUM_SUPPLIES 4 static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { "AVDD", @@ -45,7 +42,8 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { /* codec private data */ struct wm8731_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; u16 reg_cache[WM8731_CACHEREGNUM]; unsigned int sysclk; @@ -222,9 +220,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = dai->codec; struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3; int i = get_coeff(wm8731->sysclk, params_rate(params)); @@ -252,9 +248,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = dai->codec; /* set active */ snd_soc_write(codec, WM8731_ACTIVE, 0x0001); @@ -265,9 +259,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, static void wm8731_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = dai->codec; /* deactivate */ if (!codec->active) { @@ -428,8 +420,8 @@ static struct snd_soc_dai_ops wm8731_dai_ops = { .set_fmt = wm8731_set_dai_fmt, }; -struct snd_soc_dai wm8731_dai = { - .name = "WM8731", +static struct snd_soc_dai_driver wm8731_dai = { + .name = "wm8731-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -445,24 +437,17 @@ struct snd_soc_dai wm8731_dai = { .ops = &wm8731_dai_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(wm8731_dai); #ifdef CONFIG_PM -static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8731_resume(struct platform_device *pdev) +static int wm8731_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; @@ -472,88 +457,18 @@ static int wm8731_resume(struct platform_device *pdev) #define wm8731_resume NULL #endif -static int wm8731_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8731_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8731_codec; - codec = wm8731_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8731_snd_controls, - ARRAY_SIZE(wm8731_snd_controls)); - wm8731_add_widgets(codec); - - return ret; - -pcm_err: - return ret; -} - -/* power down chip */ -static int wm8731_remove(struct platform_device *pdev) +static int wm8731_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8731 = { - .probe = wm8731_probe, - .remove = wm8731_remove, - .suspend = wm8731_suspend, - .resume = wm8731_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); - -static int wm8731_register(struct wm8731_priv *wm8731, - enum snd_soc_control_type control) -{ - int ret, i; - struct snd_soc_codec *codec = &wm8731->codec; - - if (wm8731_codec) { - dev_err(codec->dev, "Another WM8731 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8731); - codec->name = "WM8731"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8731_set_bias_level; - codec->dai = &wm8731_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8731_CACHEREGNUM; - codec->reg_cache = &wm8731->reg_cache; + struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); + int ret = 0, i; - memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); + codec->bias_level = SND_SOC_BIAS_OFF, + codec->control_data = wm8731->control_data; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + return ret; } for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) @@ -563,7 +478,7 @@ static int wm8731_register(struct wm8731_priv *wm8731, wm8731->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; + return ret; } ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), @@ -579,8 +494,6 @@ static int wm8731_register(struct wm8731_priv *wm8731, goto err_regulator_enable; } - wm8731_dai.dev = codec->dev; - wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the update bits */ @@ -592,78 +505,79 @@ static int wm8731_register(struct wm8731_priv *wm8731, /* Disable bypass path by default */ snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); - wm8731_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_regulator_enable; - } - - ret = snd_soc_register_dai(&wm8731_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - goto err_codec; - } + snd_soc_add_controls(codec, wm8731_snd_controls, + ARRAY_SIZE(wm8731_snd_controls)); + wm8731_add_widgets(codec); /* Regulators will have been enabled by bias management */ regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); return 0; -err_codec: - snd_soc_unregister_codec(codec); err_regulator_enable: regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); err_regulator_get: regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); -err: + kfree(wm8731); return ret; } -static void wm8731_unregister(struct wm8731_priv *wm8731) +/* power down chip */ +static int wm8731_remove(struct snd_soc_codec *codec) { - wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm8731_dai); - snd_soc_unregister_codec(&wm8731->codec); + struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); + + wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); + + regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); - kfree(wm8731); - wm8731_codec = NULL; + + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { + .probe = wm8731_probe, + .remove = wm8731_remove, + .suspend = wm8731_suspend, + .resume = wm8731_resume, + .set_bias_level = wm8731_set_bias_level, + .reg_cache_size = sizeof(wm8731_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8731_reg, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8731_spi_probe(struct spi_device *spi) { - struct snd_soc_codec *codec; struct wm8731_priv *wm8731; + int ret; wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); if (wm8731 == NULL) return -ENOMEM; - codec = &wm8731->codec; - codec->control_data = spi; - codec->dev = &spi->dev; - - dev_set_drvdata(&spi->dev, wm8731); + wm8731->control_data = spi; + wm8731->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, wm8731); - return wm8731_register(wm8731, SND_SOC_SPI); + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8731, &wm8731_dai, 1); + if (ret < 0) + kfree(wm8731); + return ret; } static int __devexit wm8731_spi_remove(struct spi_device *spi) { - struct wm8731_priv *wm8731 = dev_get_drvdata(&spi->dev); - - wm8731_unregister(wm8731); - + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); return 0; } static struct spi_driver wm8731_spi_driver = { .driver = { - .name = "wm8731", + .name = "wm8731-codec", .bus = &spi_bus_type, .owner = THIS_MODULE, }, @@ -677,26 +591,27 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8731_priv *wm8731; - struct snd_soc_codec *codec; + int ret; wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); if (wm8731 == NULL) return -ENOMEM; - codec = &wm8731->codec; - i2c_set_clientdata(i2c, wm8731); - codec->control_data = i2c; + wm8731->control_data = i2c; + wm8731->control_type = SND_SOC_I2C; - codec->dev = &i2c->dev; - - return wm8731_register(wm8731, SND_SOC_I2C); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8731, &wm8731_dai, 1); + if (ret < 0) + kfree(wm8731); + return ret; } static __devexit int wm8731_i2c_remove(struct i2c_client *client) { - struct wm8731_priv *wm8731 = i2c_get_clientdata(client); - wm8731_unregister(wm8731); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -708,7 +623,7 @@ MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); static struct i2c_driver wm8731_i2c_driver = { .driver = { - .name = "wm8731", + .name = "wm8731-codec", .owner = THIS_MODULE, }, .probe = wm8731_i2c_probe, @@ -719,7 +634,7 @@ static struct i2c_driver wm8731_i2c_driver = { static int __init wm8731_modinit(void) { - int ret; + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8731_i2c_driver); if (ret != 0) { @@ -734,7 +649,7 @@ static int __init wm8731_modinit(void) ret); } #endif - return 0; + return ret; } module_init(wm8731_modinit); diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h index cd7b806e8ad0..73a70e206ba9 100644 --- a/sound/soc/codecs/wm8731.h +++ b/sound/soc/codecs/wm8731.h @@ -34,7 +34,4 @@ #define WM8731_SYSCLK 0 #define WM8731_DAI 0 -extern struct snd_soc_dai wm8731_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8731; - #endif diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index b9ea8904ad4b..0c6d59e4d226 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -30,9 +30,6 @@ #include "wm8741.h" -static struct snd_soc_codec *wm8741_codec; -struct snd_soc_codec_device soc_codec_dev_wm8741; - #define WM8741_NUM_SUPPLIES 2 static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { "AVDD", @@ -43,7 +40,8 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { /* codec private data */ struct wm8741_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; u16 reg_cache[WM8741_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; @@ -145,8 +143,7 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC; int i; @@ -314,7 +311,7 @@ static struct snd_soc_dai_ops wm8741_dai_ops = { .set_fmt = wm8741_set_dai_fmt, }; -struct snd_soc_dai wm8741_dai = { +static struct snd_soc_dai_driver wm8741_dai = { .name = "WM8741", .playback = { .stream_name = "Playback", @@ -325,13 +322,10 @@ struct snd_soc_dai wm8741_dai = { }, .ops = &wm8741_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8741_dai); #ifdef CONFIG_PM -static int wm8741_resume(struct platform_device *pdev) +static int wm8741_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; u16 *cache = codec->reg_cache; int i; @@ -348,189 +342,105 @@ static int wm8741_resume(struct platform_device *pdev) #define wm8741_resume NULL #endif -static int wm8741_probe(struct platform_device *pdev) +static int wm8741_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; + struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); int ret = 0; - if (wm8741_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; + codec->control_data = wm8741->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); + if (ret != 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; } - socdev->card->codec = wm8741_codec; - codec = wm8741_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + ret = wm8741_reset(codec); if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; + dev_err(codec->dev, "Failed to issue reset\n"); + return ret; } + /* Change some default settings - latch VU */ + wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; + wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; + wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; + wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; + snd_soc_add_controls(codec, wm8741_snd_controls, ARRAY_SIZE(wm8741_snd_controls)); wm8741_add_widgets(codec); + dev_dbg(codec->dev, "Successful registration\n"); return ret; - -pcm_err: - return ret; -} - -static int wm8741_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; } -struct snd_soc_codec_device soc_codec_dev_wm8741 = { +static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { .probe = wm8741_probe, - .remove = wm8741_remove, .resume = wm8741_resume, + .reg_cache_size = sizeof(wm8741_reg_defaults), + .reg_word_size = sizeof(u16), + .reg_cache_default = &wm8741_reg_defaults, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8741); -static int wm8741_register(struct wm8741_priv *wm8741, - enum snd_soc_control_type control) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static int wm8741_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - int ret; - struct snd_soc_codec *codec = &wm8741->codec; - int i; - - if (wm8741_codec) { - dev_err(codec->dev, "Another WM8741 is registered\n"); - return -EINVAL; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); + struct wm8741_priv *wm8741; + int ret, i; - snd_soc_codec_set_drvdata(codec, wm8741); - codec->name = "WM8741"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = NULL; - codec->dai = &wm8741_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8741_REGISTER_COUNT; - codec->reg_cache = &wm8741->reg_cache; + wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); + if (wm8741 == NULL) + return -ENOMEM; wm8741->rate_constraint.list = &wm8741->rate_constraint_list[0]; wm8741->rate_constraint.count = ARRAY_SIZE(wm8741->rate_constraint_list); - memcpy(codec->reg_cache, wm8741_reg_defaults, - sizeof(wm8741->reg_cache)); - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) wm8741->supplies[i].supply = wm8741_supply_names[i]; - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), + ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), wm8741->supplies); if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); goto err; } ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); + dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); goto err_get; } - ret = wm8741_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_enable; - } - - wm8741_dai.dev = codec->dev; - - /* Change some default settings - latch VU */ - wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; - wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; - wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; - wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; - - wm8741_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - return ret; - } - - ret = snd_soc_register_dai(&wm8741_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - return ret; - } + i2c_set_clientdata(i2c, wm8741); + wm8741->control_data = i2c; + wm8741->control_type = SND_SOC_I2C; - dev_dbg(codec->dev, "Successful registration\n"); - return 0; + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8741, &wm8741_dai, 1); + if (ret < 0) + goto err_enable; + return ret; err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); err_get: regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); - err: kfree(wm8741); return ret; } -static void wm8741_unregister(struct wm8741_priv *wm8741) -{ - regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); - - snd_soc_unregister_dai(&wm8741_dai); - snd_soc_unregister_codec(&wm8741->codec); - kfree(wm8741); - wm8741_codec = NULL; -} - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8741_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8741_priv *wm8741; - struct snd_soc_codec *codec; - - wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); - if (wm8741 == NULL) - return -ENOMEM; - - codec = &wm8741->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - - i2c_set_clientdata(i2c, wm8741); - codec->control_data = i2c; - - codec->dev = &i2c->dev; - - return wm8741_register(wm8741, SND_SOC_I2C); -} - -static __devexit int wm8741_i2c_remove(struct i2c_client *client) +static int wm8741_i2c_remove(struct i2c_client *client) { struct wm8741_priv *wm8741 = i2c_get_clientdata(client); - wm8741_unregister(wm8741); + + snd_soc_unregister_codec(&client->dev); + regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); + kfree(i2c_get_clientdata(client)); return 0; } @@ -540,29 +450,29 @@ static const struct i2c_device_id wm8741_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); - static struct i2c_driver wm8741_i2c_driver = { .driver = { - .name = "WM8741", + .name = "wm8741-codec", .owner = THIS_MODULE, }, .probe = wm8741_i2c_probe, - .remove = __devexit_p(wm8741_i2c_remove), + .remove = wm8741_i2c_remove, .id_table = wm8741_i2c_id, }; #endif static int __init wm8741_modinit(void) { - int ret; + int ret = 0; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8741_i2c_driver); if (ret != 0) { - printk(KERN_ERR "Failed to register WM8741 I2C driver: %d\n", - ret); + pr_err("Failed to register WM8741 I2C driver: %d\n", ret); } #endif - return 0; + + return ret; } module_init(wm8741_modinit); diff --git a/sound/soc/codecs/wm8741.h b/sound/soc/codecs/wm8741.h index fdef6ecd1f6f..56c1b1d4a681 100644 --- a/sound/soc/codecs/wm8741.h +++ b/sound/soc/codecs/wm8741.h @@ -208,7 +208,4 @@ #define WM8741_SYSCLK 0 -extern struct snd_soc_dai wm8741_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8741; - #endif diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index e2c05e3e323a..89863a5bc830 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -52,7 +52,8 @@ static const u16 wm8750_reg[] = { /* codec private data */ struct wm8750_priv { unsigned int sysclk; - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; }; @@ -560,8 +561,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3; u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0; @@ -649,8 +649,8 @@ static struct snd_soc_dai_ops wm8750_dai_ops = { .set_sysclk = wm8750_set_dai_sysclk, }; -struct snd_soc_dai wm8750_dai = { - .name = "WM8750", +static struct snd_soc_dai_driver wm8750_dai = { + .name = "wm8750-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -665,21 +665,15 @@ struct snd_soc_dai wm8750_dai = { .formats = WM8750_FORMATS,}, .ops = &wm8750_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8750_dai); -static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8750_resume(struct platform_device *pdev) +static int wm8750_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -698,100 +692,22 @@ static int wm8750_resume(struct platform_device *pdev) return 0; } -static struct snd_soc_codec *wm8750_codec; - -static int wm8750_probe(struct platform_device *pdev) +static int wm8750_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (!wm8750_codec) { - dev_err(&pdev->dev, "WM8750 codec not yet registered\n"); - return -EINVAL; - } - - socdev->card->codec = wm8750_codec; - codec = wm8750_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "wm8750: failed to create pcms\n"); - goto err; - } - - snd_soc_add_controls(codec, wm8750_snd_controls, - ARRAY_SIZE(wm8750_snd_controls)); - wm8750_add_widgets(codec); - - return 0; - -err: - return ret; -} - -/* power down chip */ -static int wm8750_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8750 = { - .probe = wm8750_probe, - .remove = wm8750_remove, - .suspend = wm8750_suspend, - .resume = wm8750_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750); - -/* - * initialise the WM8750 driver - * register the mixer and dsp interfaces with the kernel - */ -static int wm8750_register(struct wm8750_priv *wm8750, - enum snd_soc_control_type control) -{ - struct snd_soc_codec *codec = &wm8750->codec; - int reg, ret = 0; - - if (wm8750_codec) { - dev_err(codec->dev, "Multiple WM8750 devices not supported\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "WM8750"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_STANDBY; - codec->set_bias_level = wm8750_set_bias_level; - codec->dai = &wm8750_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(wm8750->reg_cache) + 1; - codec->reg_cache = &wm8750->reg_cache; - snd_soc_codec_set_drvdata(codec, wm8750); - - memcpy(codec->reg_cache, wm8750_reg, sizeof(wm8750->reg_cache)); + struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); + int reg, ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + codec->control_data = wm8750->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type); if (ret < 0) { printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); - goto err; + return ret; } ret = wm8750_reset(codec); if (ret < 0) { printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); - goto err; + return ret; } /* charge output caps */ @@ -815,150 +731,133 @@ static int wm8750_register(struct wm8750_priv *wm8750, reg = snd_soc_read(codec, WM8750_RINVOL); snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); - wm8750_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dais(&wm8750_dai, 1); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8750); + snd_soc_add_controls(codec, wm8750_snd_controls, + ARRAY_SIZE(wm8750_snd_controls)); + wm8750_add_widgets(codec); return ret; } -static void wm8750_unregister(struct wm8750_priv *wm8750) +static int wm8750_remove(struct snd_soc_codec *codec) { - wm8750_set_bias_level(&wm8750->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dais(&wm8750_dai, 1); - snd_soc_unregister_codec(&wm8750->codec); - kfree(wm8750); - wm8750_codec = NULL; + wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; } -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -/* - * WM8750 2 wire address is determined by GPIO5 - * state during powerup. - * low = 0x1a - * high = 0x1b - */ +static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { + .probe = wm8750_probe, + .remove = wm8750_remove, + .suspend = wm8750_suspend, + .resume = wm8750_resume, + .set_bias_level = wm8750_set_bias_level, + .reg_cache_size = sizeof(wm8750_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8750_reg, +}; -static int wm8750_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +#if defined(CONFIG_SPI_MASTER) +static int __devinit wm8750_spi_probe(struct spi_device *spi) { - struct snd_soc_codec *codec; struct wm8750_priv *wm8750; + int ret; wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); if (wm8750 == NULL) return -ENOMEM; - codec = &wm8750->codec; - codec->control_data = i2c; - i2c_set_clientdata(i2c, wm8750); - - codec->dev = &i2c->dev; + wm8750->control_data = spi; + wm8750->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, wm8750); - return wm8750_register(wm8750, SND_SOC_I2C); + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8750, &wm8750_dai, 1); + if (ret < 0) + kfree(wm8750); + return ret; } -static int wm8750_i2c_remove(struct i2c_client *client) +static int __devexit wm8750_spi_remove(struct spi_device *spi) { - struct wm8750_priv *wm8750 = i2c_get_clientdata(client); - wm8750_unregister(wm8750); + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); return 0; } -static const struct i2c_device_id wm8750_i2c_id[] = { - { "wm8750", 0 }, - { "wm8987", 0 }, /* WM8987 is register compatible with WM8750 */ - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); - -static struct i2c_driver wm8750_i2c_driver = { +static struct spi_driver wm8750_spi_driver = { .driver = { - .name = "WM8750 I2C Codec", - .owner = THIS_MODULE, + .name = "wm8750-codec", + .bus = &spi_bus_type, + .owner = THIS_MODULE, }, - .probe = wm8750_i2c_probe, - .remove = wm8750_i2c_remove, - .id_table = wm8750_i2c_id, + .probe = wm8750_spi_probe, + .remove = __devexit_p(wm8750_spi_remove), }; -#endif +#endif /* CONFIG_SPI_MASTER */ -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8750_spi_probe(struct spi_device *spi) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8750_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - struct snd_soc_codec *codec; struct wm8750_priv *wm8750; + int ret; wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); if (wm8750 == NULL) return -ENOMEM; - codec = &wm8750->codec; - codec->control_data = spi; - codec->dev = &spi->dev; - - dev_set_drvdata(&spi->dev, wm8750); + i2c_set_clientdata(i2c, wm8750); + wm8750->control_data = i2c; + wm8750->control_type = SND_SOC_I2C; - return wm8750_register(wm8750, SND_SOC_SPI); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8750, &wm8750_dai, 1); + if (ret < 0) + kfree(wm8750); + return ret; } -static int __devexit wm8750_spi_remove(struct spi_device *spi) +static __devexit int wm8750_i2c_remove(struct i2c_client *client) { - struct wm8750_priv *wm8750 = dev_get_drvdata(&spi->dev); - wm8750_unregister(wm8750); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } -static const struct spi_device_id wm8750_spi_id[] = { +static const struct i2c_device_id wm8750_i2c_id[] = { { "wm8750", 0 }, { "wm8987", 0 }, { } }; -MODULE_DEVICE_TABLE(spi, wm8750_spi_id); +MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); -static struct spi_driver wm8750_spi_driver = { +static struct i2c_driver wm8750_i2c_driver = { .driver = { - .name = "WM8750 SPI Codec", - .bus = &spi_bus_type, - .owner = THIS_MODULE, + .name = "wm8750-codec", + .owner = THIS_MODULE, }, - .probe = wm8750_spi_probe, - .remove = __devexit_p(wm8750_spi_remove), - .id_table = wm8750_spi_id, + .probe = wm8750_i2c_probe, + .remove = __devexit_p(wm8750_i2c_remove), + .id_table = wm8750_i2c_id, }; #endif static int __init wm8750_modinit(void) { - int ret; + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8750_i2c_driver); - if (ret != 0) - pr_err("Failed to register WM8750 I2C driver: %d\n", ret); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n", + ret); + } #endif #if defined(CONFIG_SPI_MASTER) ret = spi_register_driver(&wm8750_spi_driver); - if (ret != 0) - pr_err("Failed to register WM8750 SPI driver: %d\n", ret); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8750 SPI driver: %d\n", + ret); + } #endif - return 0; + return ret; } module_init(wm8750_modinit); diff --git a/sound/soc/codecs/wm8750.h b/sound/soc/codecs/wm8750.h index 1dc100e19cfe..121427c047fb 100644 --- a/sound/soc/codecs/wm8750.h +++ b/sound/soc/codecs/wm8750.h @@ -57,13 +57,4 @@ #define WM8750_SYSCLK 0 -struct wm8750_setup_data { - int spi; - int i2c_bus; - unsigned short i2c_address; -}; - -extern struct snd_soc_dai wm8750_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8750; - #endif diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index b59f349c5218..976e408b3616 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -57,7 +57,7 @@ module_param(caps_charge, int, 0); MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); static void wm8753_set_dai_mode(struct snd_soc_codec *codec, - unsigned int mode); + struct snd_soc_dai *dai, unsigned int hifi); /* * wm8753 register cache @@ -85,10 +85,12 @@ static const u16 wm8753_reg[] = { /* codec private data */ struct wm8753_priv { + enum snd_soc_control_type control_type; + void *control_data; unsigned int sysclk; unsigned int pcmclk; - struct snd_soc_codec codec; u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; + int dai_func; }; /* @@ -228,6 +230,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); + struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) return 0; @@ -235,8 +238,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, mode &= 0xfff3; mode |= (ucontrol->value.integer.value[0] << 2); - wm8753_write(codec, WM8753_IOCTL, mode); - wm8753_set_dai_mode(codec, ucontrol->value.integer.value[0]); + wm8753->dai_func = ucontrol->value.integer.value[0]; return 1; } @@ -904,6 +906,13 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } +static int wm8753_pcm_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + wm8753_set_dai_mode(dai->codec, dai, 0); + return 0; +} + /* * Set PCM DAI bit size and sample rate. */ @@ -912,8 +921,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; @@ -1138,6 +1146,13 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } +static int wm8753_i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + wm8753_set_dai_mode(dai->codec, dai, 1); + return 0; +} + /* * Set PCM DAI bit size and sample rate. */ @@ -1146,8 +1161,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; @@ -1240,12 +1254,12 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; + struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); /* the digital mute covers the HiFi and Voice DAC's on the WM8753. * make sure we check if they are not both active when we mute */ - if (mute && dai->id == 1) { - if (!wm8753_dai[WM8753_DAI_VOICE].playback.active || - !wm8753_dai[WM8753_DAI_HIFI].playback.active) + if (mute && wm8753->dai_func == 1) { + if (!codec->active) wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); } else { if (mute) @@ -1303,6 +1317,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec, * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture */ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { + .startup = wm8753_i2s_startup, .hw_params = wm8753_i2s_hw_params, .digital_mute = wm8753_mute, .set_fmt = wm8753_mode1h_set_dai_fmt, @@ -1312,6 +1327,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { }; static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { + .startup = wm8753_pcm_startup, .hw_params = wm8753_pcm_hw_params, .digital_mute = wm8753_mute, .set_fmt = wm8753_mode1v_set_dai_fmt, @@ -1321,6 +1337,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { }; static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { + .startup = wm8753_pcm_startup, .hw_params = wm8753_pcm_hw_params, .digital_mute = wm8753_mute, .set_fmt = wm8753_mode2_set_dai_fmt, @@ -1330,6 +1347,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { }; static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { + .startup = wm8753_i2s_startup, .hw_params = wm8753_i2s_hw_params, .digital_mute = wm8753_mute, .set_fmt = wm8753_mode3_4_set_dai_fmt, @@ -1339,6 +1357,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { }; static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { + .startup = wm8753_i2s_startup, .hw_params = wm8753_i2s_hw_params, .digital_mute = wm8753_mute, .set_fmt = wm8753_mode3_4_set_dai_fmt, @@ -1347,10 +1366,9 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { .set_sysclk = wm8753_set_dai_sysclk, }; -static const struct snd_soc_dai wm8753_all_dai[] = { +static struct snd_soc_dai_driver wm8753_all_dai[] = { /* DAI HiFi mode 1 */ -{ .name = "WM8753 HiFi", - .id = 1, +{ .name = "wm8753-hifi", .playback = { .stream_name = "HiFi Playback", .channels_min = 1, @@ -1366,8 +1384,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { .ops = &wm8753_dai_ops_hifi_mode1, }, /* DAI Voice mode 1 */ -{ .name = "WM8753 Voice", - .id = 1, +{ .name = "wm8753-voice", .playback = { .stream_name = "Voice Playback", .channels_min = 1, @@ -1383,12 +1400,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = { .ops = &wm8753_dai_ops_voice_mode1, }, /* DAI HiFi mode 2 - dummy */ -{ .name = "WM8753 HiFi", - .id = 2, +{ .name = "wm8753-hifi", }, /* DAI Voice mode 2 */ -{ .name = "WM8753 Voice", - .id = 2, +{ .name = "wm8753-voice", .playback = { .stream_name = "Voice Playback", .channels_min = 1, @@ -1404,8 +1419,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { .ops = &wm8753_dai_ops_voice_mode2, }, /* DAI HiFi mode 3 */ -{ .name = "WM8753 HiFi", - .id = 3, +{ .name = "wm8753-hifi", .playback = { .stream_name = "HiFi Playback", .channels_min = 1, @@ -1421,12 +1435,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = { .ops = &wm8753_dai_ops_hifi_mode3, }, /* DAI Voice mode 3 - dummy */ -{ .name = "WM8753 Voice", - .id = 3, +{ .name = "wm8753-voice", }, /* DAI HiFi mode 4 */ -{ .name = "WM8753 HiFi", - .id = 4, +{ .name = "wm8753-hifi", .playback = { .stream_name = "HiFi Playback", .channels_min = 1, @@ -1442,58 +1454,31 @@ static const struct snd_soc_dai wm8753_all_dai[] = { .ops = &wm8753_dai_ops_hifi_mode4, }, /* DAI Voice mode 4 - dummy */ -{ .name = "WM8753 Voice", - .id = 4, +{ .name = "wm8753-voice", }, }; -struct snd_soc_dai wm8753_dai[] = { +static struct snd_soc_dai_driver wm8753_dai[] = { { - .name = "WM8753 DAI 0", + .name = "wm8753-aif0", }, { - .name = "WM8753 DAI 1", + .name = "wm8753-aif1", }, }; -EXPORT_SYMBOL_GPL(wm8753_dai); -static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode) +static void wm8753_set_dai_mode(struct snd_soc_codec *codec, + struct snd_soc_dai *dai, unsigned int hifi) { - if (mode < 4) { - int playback_active, capture_active, codec_active, pop_wait; - void *private_data; - struct list_head list; - - playback_active = wm8753_dai[0].playback.active; - capture_active = wm8753_dai[0].capture.active; - codec_active = wm8753_dai[0].active; - private_data = wm8753_dai[0].private_data; - pop_wait = wm8753_dai[0].pop_wait; - list = wm8753_dai[0].list; - wm8753_dai[0] = wm8753_all_dai[mode << 1]; - wm8753_dai[0].playback.active = playback_active; - wm8753_dai[0].capture.active = capture_active; - wm8753_dai[0].active = codec_active; - wm8753_dai[0].private_data = private_data; - wm8753_dai[0].pop_wait = pop_wait; - wm8753_dai[0].list = list; - - playback_active = wm8753_dai[1].playback.active; - capture_active = wm8753_dai[1].capture.active; - codec_active = wm8753_dai[1].active; - private_data = wm8753_dai[1].private_data; - pop_wait = wm8753_dai[1].pop_wait; - list = wm8753_dai[1].list; - wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1]; - wm8753_dai[1].playback.active = playback_active; - wm8753_dai[1].capture.active = capture_active; - wm8753_dai[1].active = codec_active; - wm8753_dai[1].private_data = private_data; - wm8753_dai[1].pop_wait = pop_wait; - wm8753_dai[1].list = list; + struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); + + if (wm8753->dai_func < 4) { + if (hifi) + dai->driver = &wm8753_all_dai[wm8753->dai_func << 1]; + else + dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1]; } - wm8753_dai[0].codec = codec; - wm8753_dai[1].codec = codec; + wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func); } static void wm8753_work(struct work_struct *work) @@ -1503,19 +1488,14 @@ static void wm8753_work(struct work_struct *work) wm8753_set_bias_level(codec, codec->bias_level); } -static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8753_resume(struct platform_device *pdev) +static int wm8753_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -1547,41 +1527,6 @@ static int wm8753_resume(struct platform_device *pdev) return 0; } -static struct snd_soc_codec *wm8753_codec; - -static int wm8753_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (!wm8753_codec) { - dev_err(&pdev->dev, "WM8753 codec not yet registered\n"); - return -EINVAL; - } - - socdev->card->codec = wm8753_codec; - codec = wm8753_codec; - - wm8753_set_dai_mode(codec, 0); - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "wm8753: failed to create pcms\n"); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8753_snd_controls, - ARRAY_SIZE(wm8753_snd_controls)); - wm8753_add_widgets(codec); - - return 0; - -pcm_err: - return ret; -} - /* * This function forces any delayed work to be queued and run. */ @@ -1601,62 +1546,30 @@ static int run_delayed_work(struct delayed_work *dwork) return ret; } -/* power down chip */ -static int wm8753_remove(struct platform_device *pdev) +static int wm8753_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8753 = { - .probe = wm8753_probe, - .remove = wm8753_remove, - .suspend = wm8753_suspend, - .resume = wm8753_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753); + struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); + int ret = 0, reg; -static int wm8753_register(struct wm8753_priv *wm8753) -{ - int ret, i; - struct snd_soc_codec *codec = &wm8753->codec; - u16 reg; + codec->bias_level = SND_SOC_BIAS_OFF, + codec->control_data = wm8753->control_data; + INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); - if (wm8753_codec) { - dev_err(codec->dev, "Multiple WM8753 devices not supported\n"); - ret = -EINVAL; - goto err; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; } - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "WM8753"; - codec->owner = THIS_MODULE; - codec->read = wm8753_read_reg_cache; - codec->write = wm8753_write; - codec->bias_level = SND_SOC_BIAS_STANDBY; - codec->set_bias_level = wm8753_set_bias_level; - codec->dai = wm8753_dai; - codec->num_dai = 2; - codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1; - codec->reg_cache = &wm8753->reg_cache; - snd_soc_codec_set_drvdata(codec, wm8753); - - memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache)); - INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); - ret = wm8753_reset(codec); if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err; + dev_err(codec->dev, "Failed to issue reset: %d\n", ret); + return ret; } + wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + wm8753->dai_func = 0; + /* charge output caps */ wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); schedule_delayed_work(&codec->delayed_work, @@ -1684,165 +1597,139 @@ static int wm8753_register(struct wm8753_priv *wm8753) reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); - wm8753_codec = codec; - - for (i = 0; i < ARRAY_SIZE(wm8753_dai); i++) - wm8753_dai[i].dev = codec->dev; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai)); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); - goto err_codec; - } + snd_soc_add_controls(codec, wm8753_snd_controls, + ARRAY_SIZE(wm8753_snd_controls)); + wm8753_add_widgets(codec); return 0; -err_codec: run_delayed_work(&codec->delayed_work); - snd_soc_unregister_codec(codec); -err: - kfree(wm8753); return ret; } -static void wm8753_unregister(struct wm8753_priv *wm8753) +/* power down chip */ +static int wm8753_remove(struct snd_soc_codec *codec) { - wm8753_set_bias_level(&wm8753->codec, SND_SOC_BIAS_OFF); - run_delayed_work(&wm8753->codec.delayed_work); - snd_soc_unregister_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai)); - snd_soc_unregister_codec(&wm8753->codec); - kfree(wm8753); - wm8753_codec = NULL; + run_delayed_work(&codec->delayed_work); + wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); + + return 0; } -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { + .probe = wm8753_probe, + .remove = wm8753_remove, + .suspend = wm8753_suspend, + .resume = wm8753_resume, + .set_bias_level = wm8753_set_bias_level, + .reg_cache_size = sizeof(wm8753_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8753_reg, +}; -static int wm8753_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +#if defined(CONFIG_SPI_MASTER) +static int __devinit wm8753_spi_probe(struct spi_device *spi) { - struct snd_soc_codec *codec; struct wm8753_priv *wm8753; + int ret; wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); if (wm8753 == NULL) return -ENOMEM; - codec = &wm8753->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - codec->control_data = i2c; - i2c_set_clientdata(i2c, wm8753); - - codec->dev = &i2c->dev; + wm8753->control_data = spi; + wm8753->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, wm8753); - return wm8753_register(wm8753); + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai)); + if (ret < 0) + kfree(wm8753); + return ret; } -static int wm8753_i2c_remove(struct i2c_client *client) +static int __devexit wm8753_spi_remove(struct spi_device *spi) { - struct wm8753_priv *wm8753 = i2c_get_clientdata(client); - wm8753_unregister(wm8753); - return 0; + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); + return 0; } -static const struct i2c_device_id wm8753_i2c_id[] = { - { "wm8753", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); - -static struct i2c_driver wm8753_i2c_driver = { +static struct spi_driver wm8753_spi_driver = { .driver = { - .name = "wm8753", - .owner = THIS_MODULE, + .name = "wm8753-codec", + .bus = &spi_bus_type, + .owner = THIS_MODULE, }, - .probe = wm8753_i2c_probe, - .remove = wm8753_i2c_remove, - .id_table = wm8753_i2c_id, + .probe = wm8753_spi_probe, + .remove = __devexit_p(wm8753_spi_remove), }; -#endif - -#if defined(CONFIG_SPI_MASTER) -static int wm8753_spi_write(struct spi_device *spi, const char *data, int len) -{ - struct spi_transfer t; - struct spi_message m; - u8 msg[2]; - - if (len <= 0) - return 0; - - msg[0] = data[0]; - msg[1] = data[1]; +#endif /* CONFIG_SPI_MASTER */ - spi_message_init(&m); - memset(&t, 0, (sizeof t)); - - t.tx_buf = &msg[0]; - t.len = len; - - spi_message_add_tail(&t, &m); - spi_sync(spi, &m); - - return len; -} - -static int __devinit wm8753_spi_probe(struct spi_device *spi) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8753_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - struct snd_soc_codec *codec; struct wm8753_priv *wm8753; + int ret; wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); if (wm8753 == NULL) return -ENOMEM; - codec = &wm8753->codec; - codec->control_data = spi; - codec->hw_write = (hw_write_t)wm8753_spi_write; - codec->dev = &spi->dev; - - dev_set_drvdata(&spi->dev, wm8753); + i2c_set_clientdata(i2c, wm8753); + wm8753->control_data = i2c; + wm8753->control_type = SND_SOC_I2C; - return wm8753_register(wm8753); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai)); + if (ret < 0) + kfree(wm8753); + return ret; } -static int __devexit wm8753_spi_remove(struct spi_device *spi) +static __devexit int wm8753_i2c_remove(struct i2c_client *client) { - struct wm8753_priv *wm8753 = dev_get_drvdata(&spi->dev); - wm8753_unregister(wm8753); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } -static struct spi_driver wm8753_spi_driver = { +static const struct i2c_device_id wm8753_i2c_id[] = { + { "wm8753", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); + +static struct i2c_driver wm8753_i2c_driver = { .driver = { - .name = "wm8753", - .bus = &spi_bus_type, - .owner = THIS_MODULE, + .name = "wm8753-codec", + .owner = THIS_MODULE, }, - .probe = wm8753_spi_probe, - .remove = __devexit_p(wm8753_spi_remove), + .probe = wm8753_i2c_probe, + .remove = __devexit_p(wm8753_i2c_remove), + .id_table = wm8753_i2c_id, }; #endif static int __init wm8753_modinit(void) { - int ret; + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8753_i2c_driver); - if (ret != 0) - pr_err("Failed to register WM8753 I2C driver: %d\n", ret); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n", + ret); + } #endif #if defined(CONFIG_SPI_MASTER) ret = spi_register_driver(&wm8753_spi_driver); - if (ret != 0) - pr_err("Failed to register WM8753 SPI driver: %d\n", ret); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8753 SPI driver: %d\n", + ret); + } #endif - return 0; + return ret; } module_init(wm8753_modinit); diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h index 57b2ba244040..94edac144bcb 100644 --- a/sound/soc/codecs/wm8753.h +++ b/sound/soc/codecs/wm8753.h @@ -115,7 +115,4 @@ #define WM8753_DAI_HIFI 0 #define WM8753_DAI_VOICE 1 -extern struct snd_soc_dai wm8753_dai[2]; -extern struct snd_soc_codec_device soc_codec_dev_wm8753; - #endif diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 4e212ed62ea6..51a2d265d40e 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -31,20 +31,14 @@ #include "wm8776.h" -static struct snd_soc_codec *wm8776_codec; -struct snd_soc_codec_device soc_codec_dev_wm8776; - /* codec private data */ struct wm8776_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; u16 reg_cache[WM8776_CACHEREGNUM]; int sysclk[2]; }; -#ifdef CONFIG_SPI_MASTER -static int wm8776_spi_write(struct spi_device *spi, const char *data, int len); -#endif - static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ @@ -144,7 +138,7 @@ static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct snd_soc_codec *codec = dai->codec; int reg, iface, master; - switch (dai->id) { + switch (dai->driver->id) { case WM8776_DAI_DAC: reg = WM8776_DACIFCTRL; master = 0x80; @@ -233,7 +227,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, iface = 0; - switch (dai->id) { + switch (dai->driver->id) { case WM8776_DAI_DAC: iface_reg = WM8776_DACIFCTRL; master = 0x80; @@ -267,7 +261,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, /* Only need to set MCLK/LRCLK ratio if we're master */ if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) { for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { - if (wm8776->sysclk[dai->id] / params_rate(params) + if (wm8776->sysclk[dai->driver->id] / params_rate(params) == mclk_ratios[i]) break; } @@ -275,7 +269,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, if (i == ARRAY_SIZE(mclk_ratios)) { dev_err(codec->dev, "Unable to configure MCLK ratio %d/%d\n", - wm8776->sysclk[dai->id], params_rate(params)); + wm8776->sysclk[dai->driver->id], params_rate(params)); return -EINVAL; } @@ -305,9 +299,9 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai, struct snd_soc_codec *codec = dai->codec; struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); - BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk)); + BUG_ON(dai->driver->id >= ARRAY_SIZE(wm8776->sysclk)); - wm8776->sysclk[dai->id] = freq; + wm8776->sysclk[dai->driver->id] = freq; return 0; } @@ -357,10 +351,10 @@ static struct snd_soc_dai_ops wm8776_adc_ops = { .set_sysclk = wm8776_set_sysclk, }; -struct snd_soc_dai wm8776_dai[] = { +static struct snd_soc_dai_driver wm8776_dai[] = { { - .name = "WM8776 Playback", - .id = WM8776_DAI_DAC, + .name = "wm8776-hifi-playback", + .id = WM8776_DAI_DAC, .playback = { .stream_name = "Playback", .channels_min = 2, @@ -371,8 +365,8 @@ struct snd_soc_dai wm8776_dai[] = { .ops = &wm8776_dac_ops, }, { - .name = "WM8776 Capture", - .id = WM8776_DAI_ADC, + .name = "wm8776-hifi-capture", + .id = WM8776_DAI_ADC, .capture = { .stream_name = "Capture", .channels_min = 2, @@ -383,23 +377,17 @@ struct snd_soc_dai wm8776_dai[] = { .ops = &wm8776_adc_ops, }, }; -EXPORT_SYMBOL_GPL(wm8776_dai); #ifdef CONFIG_PM -static int wm8776_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8776_resume(struct platform_device *pdev) +static int wm8776_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -422,27 +410,31 @@ static int wm8776_resume(struct platform_device *pdev) #define wm8776_resume NULL #endif -static int wm8776_probe(struct platform_device *pdev) +static int wm8776_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; + struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); int ret = 0; - if (wm8776_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; + codec->control_data = wm8776->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; } - socdev->card->codec = wm8776_codec; - codec = wm8776_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + ret = wm8776_reset(codec); if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; + dev_err(codec->dev, "Failed to issue reset: %d\n", ret); + return ret; } + wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + /* Latch the update bits; right channel only since we always + * update both. */ + snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); + snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); + snd_soc_add_controls(codec, wm8776_snd_controls, ARRAY_SIZE(wm8776_snd_controls)); snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets, @@ -450,168 +442,57 @@ static int wm8776_probe(struct platform_device *pdev) snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); return ret; - -pcm_err: - return ret; } /* power down chip */ -static int wm8776_remove(struct platform_device *pdev) +static int wm8776_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - + wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -struct snd_soc_codec_device soc_codec_dev_wm8776 = { +static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { .probe = wm8776_probe, .remove = wm8776_remove, .suspend = wm8776_suspend, .resume = wm8776_resume, + .set_bias_level = wm8776_set_bias_level, + .reg_cache_size = sizeof(wm8776_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8776_reg, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776); - -static int wm8776_register(struct wm8776_priv *wm8776, - enum snd_soc_control_type control) -{ - int ret, i; - struct snd_soc_codec *codec = &wm8776->codec; - - if (wm8776_codec) { - dev_err(codec->dev, "Another WM8776 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8776); - codec->name = "WM8776"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8776_set_bias_level; - codec->dai = wm8776_dai; - codec->num_dai = ARRAY_SIZE(wm8776_dai); - codec->reg_cache_size = WM8776_CACHEREGNUM; - codec->reg_cache = &wm8776->reg_cache; - - memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg)); - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++) - wm8776_dai[i].dev = codec->dev; - - ret = wm8776_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - goto err; - } - - wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Latch the update bits; right channel only since we always - * update both. */ - snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); - - wm8776_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8776); - return ret; -} - -static void wm8776_unregister(struct wm8776_priv *wm8776) -{ - wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); - snd_soc_unregister_codec(&wm8776->codec); - kfree(wm8776); - wm8776_codec = NULL; -} #if defined(CONFIG_SPI_MASTER) -static int wm8776_spi_write(struct spi_device *spi, const char *data, int len) -{ - struct spi_transfer t; - struct spi_message m; - u8 msg[2]; - - if (len <= 0) - return 0; - - msg[0] = data[0]; - msg[1] = data[1]; - - spi_message_init(&m); - memset(&t, 0, (sizeof t)); - - t.tx_buf = &msg[0]; - t.len = len; - - spi_message_add_tail(&t, &m); - spi_sync(spi, &m); - - return len; -} - static int __devinit wm8776_spi_probe(struct spi_device *spi) { - struct snd_soc_codec *codec; struct wm8776_priv *wm8776; + int ret; wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); if (wm8776 == NULL) return -ENOMEM; - codec = &wm8776->codec; - codec->control_data = spi; - codec->hw_write = (hw_write_t)wm8776_spi_write; - codec->dev = &spi->dev; + wm8776->control_data = spi; + wm8776->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, wm8776); - dev_set_drvdata(&spi->dev, wm8776); - - return wm8776_register(wm8776, SND_SOC_SPI); + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); + if (ret < 0) + kfree(wm8776); + return ret; } static int __devexit wm8776_spi_remove(struct spi_device *spi) { - struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev); - - wm8776_unregister(wm8776); - + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); return 0; } static struct spi_driver wm8776_spi_driver = { .driver = { - .name = "wm8776", + .name = "wm8776-codec", .bus = &spi_bus_type, .owner = THIS_MODULE, }, @@ -625,27 +506,27 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8776_priv *wm8776; - struct snd_soc_codec *codec; + int ret; wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); if (wm8776 == NULL) return -ENOMEM; - codec = &wm8776->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - i2c_set_clientdata(i2c, wm8776); - codec->control_data = i2c; - - codec->dev = &i2c->dev; + wm8776->control_data = i2c; + wm8776->control_type = SND_SOC_I2C; - return wm8776_register(wm8776, SND_SOC_I2C); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); + if (ret < 0) + kfree(wm8776); + return ret; } static __devexit int wm8776_i2c_remove(struct i2c_client *client) { - struct wm8776_priv *wm8776 = i2c_get_clientdata(client); - wm8776_unregister(wm8776); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -657,7 +538,7 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); static struct i2c_driver wm8776_i2c_driver = { .driver = { - .name = "wm8776", + .name = "wm8776-codec", .owner = THIS_MODULE, }, .probe = wm8776_i2c_probe, @@ -668,22 +549,22 @@ static struct i2c_driver wm8776_i2c_driver = { static int __init wm8776_modinit(void) { - int ret; + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8776_i2c_driver); if (ret != 0) { - printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n", + printk(KERN_ERR "Failed to register wm8776 I2C driver: %d\n", ret); } #endif #if defined(CONFIG_SPI_MASTER) ret = spi_register_driver(&wm8776_spi_driver); if (ret != 0) { - printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n", + printk(KERN_ERR "Failed to register wm8776 SPI driver: %d\n", ret); } #endif - return 0; + return ret; } module_init(wm8776_modinit); diff --git a/sound/soc/codecs/wm8776.h b/sound/soc/codecs/wm8776.h index 6606d25d2d83..4cf1c8e0bfc9 100644 --- a/sound/soc/codecs/wm8776.h +++ b/sound/soc/codecs/wm8776.h @@ -45,7 +45,4 @@ #define WM8776_DAI_DAC 0 #define WM8776_DAI_ADC 1 -extern struct snd_soc_dai wm8776_dai[]; -extern struct snd_soc_codec_device soc_codec_dev_wm8776; - #endif diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5da17a704e5a..33c3b57f3f66 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -137,11 +138,9 @@ #define WM8900_LRC_MASK 0xfc00 -struct snd_soc_codec_device soc_codec_dev_wm8900; - struct wm8900_priv { - struct snd_soc_codec codec; - + enum snd_soc_control_type control_type; + void *control_data; u16 reg_cache[WM8900_MAXREG]; u32 fll_in; /* FLL input frequency */ @@ -627,8 +626,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u16 reg; reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; @@ -1015,8 +1013,8 @@ static struct snd_soc_dai_ops wm8900_dai_ops = { .digital_mute = wm8900_digital_mute, }; -struct snd_soc_dai wm8900_dai = { - .name = "WM8900 HiFi", +static struct snd_soc_dai_driver wm8900_dai = { + .name = "wm8900-hifi", .playback = { .stream_name = "HiFi Playback", .channels_min = 1, @@ -1033,7 +1031,6 @@ struct snd_soc_dai wm8900_dai = { }, .ops = &wm8900_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8900_dai); static int wm8900_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) @@ -1128,10 +1125,8 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, return 0; } -static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); int fll_out = wm8900->fll_out; int fll_in = wm8900->fll_in; @@ -1140,7 +1135,7 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) /* Stop the FLL in an orderly fashion */ ret = wm8900_set_fll(codec, 0, 0, 0); if (ret != 0) { - dev_err(&pdev->dev, "Failed to stop FLL\n"); + dev_err(codec->dev, "Failed to stop FLL\n"); return ret; } @@ -1152,10 +1147,8 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int wm8900_resume(struct platform_device *pdev) +static int wm8900_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); u16 *cache; int i, ret; @@ -1176,7 +1169,7 @@ static int wm8900_resume(struct platform_device *pdev) ret = wm8900_set_fll(codec, 0, fll_in, fll_out); if (ret != 0) { - dev_err(&pdev->dev, "Failed to restart FLL\n"); + dev_err(codec->dev, "Failed to restart FLL\n"); return ret; } } @@ -1186,60 +1179,33 @@ static int wm8900_resume(struct platform_device *pdev) snd_soc_write(codec, i, cache[i]); kfree(cache); } else - dev_err(&pdev->dev, "Unable to allocate register cache\n"); + dev_err(codec->dev, "Unable to allocate register cache\n"); return 0; } -static struct snd_soc_codec *wm8900_codec; - -static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int wm8900_probe(struct snd_soc_codec *codec) { - struct wm8900_priv *wm8900; - struct snd_soc_codec *codec; - unsigned int reg; - int ret; - - wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); - if (wm8900 == NULL) - return -ENOMEM; + struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); + int ret = 0, reg; - codec = &wm8900->codec; - snd_soc_codec_set_drvdata(codec, wm8900); - codec->reg_cache = &wm8900->reg_cache[0]; - codec->reg_cache_size = WM8900_MAXREG; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "WM8900"; - codec->owner = THIS_MODULE; - codec->dai = &wm8900_dai; - codec->num_dai = 1; - codec->control_data = i2c; - codec->set_bias_level = wm8900_set_bias_level; - codec->volatile_register = wm8900_volatile_register; - codec->dev = &i2c->dev; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); + codec->control_data = wm8900->control_data; + ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type); if (ret != 0) { - dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; } reg = snd_soc_read(codec, WM8900_REG_ID); if (reg != 0x8900) { - dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg); - ret = -ENODEV; - goto err; + dev_err(codec->dev, "Device is not a WM8900 - ID %x\n", reg); + return -ENODEV; } /* Read back from the chip */ reg = snd_soc_read(codec, WM8900_REG_POWER1); reg = (reg >> 12) & 0xf; - dev_info(&i2c->dev, "WM8900 revision %d\n", reg); + dev_info(codec->dev, "WM8900 revision %d\n", reg); wm8900_reset(codec); @@ -1271,43 +1237,97 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, /* Set the DAC and mixer output bias */ snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); - wm8900_dai.dev = &i2c->dev; + snd_soc_add_controls(codec, wm8900_snd_controls, + ARRAY_SIZE(wm8900_snd_controls)); + wm8900_add_widgets(codec); - wm8900_codec = codec; + return 0; +} - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); - goto err; - } +/* power down chip */ +static int wm8900_remove(struct snd_soc_codec *codec) +{ + wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} - ret = snd_soc_register_dai(&wm8900_dai); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } +static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { + .probe = wm8900_probe, + .remove = wm8900_remove, + .suspend = wm8900_suspend, + .resume = wm8900_resume, + .set_bias_level = wm8900_set_bias_level, + .volatile_register = wm8900_volatile_register, + .reg_cache_size = sizeof(wm8900_reg_defaults), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8900_reg_defaults, +}; - return ret; +#if defined(CONFIG_SPI_MASTER) +static int __devinit wm8900_spi_probe(struct spi_device *spi) +{ + struct wm8900_priv *wm8900; + int ret; + + wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); + if (wm8900 == NULL) + return -ENOMEM; -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8900); - wm8900_codec = NULL; + wm8900->control_data = spi; + wm8900->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, wm8900); + + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8900, &wm8900_dai, 1); + if (ret < 0) + kfree(wm8900); return ret; } -static __devexit int wm8900_i2c_remove(struct i2c_client *client) +static int __devexit wm8900_spi_remove(struct spi_device *spi) { - snd_soc_unregister_dai(&wm8900_dai); - snd_soc_unregister_codec(wm8900_codec); + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); + return 0; +} - wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF); +static struct spi_driver wm8900_spi_driver = { + .driver = { + .name = "wm8900-codec", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = wm8900_spi_probe, + .remove = __devexit_p(wm8900_spi_remove), +}; +#endif /* CONFIG_SPI_MASTER */ + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct wm8900_priv *wm8900; + int ret; + + wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); + if (wm8900 == NULL) + return -ENOMEM; + + i2c_set_clientdata(i2c, wm8900); + wm8900->control_data = i2c; + wm8900->control_type = SND_SOC_I2C; - wm8900_dai.dev = NULL; - kfree(snd_soc_codec_get_drvdata(wm8900_codec)); - wm8900_codec = NULL; + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8900, &wm8900_dai, 1); + if (ret < 0) + kfree(wm8900); + return ret; +} +static __devexit int wm8900_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -1319,71 +1339,44 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id); static struct i2c_driver wm8900_i2c_driver = { .driver = { - .name = "WM8900", + .name = "wm8900-codec", .owner = THIS_MODULE, }, - .probe = wm8900_i2c_probe, - .remove = __devexit_p(wm8900_i2c_remove), + .probe = wm8900_i2c_probe, + .remove = __devexit_p(wm8900_i2c_remove), .id_table = wm8900_i2c_id, }; +#endif -static int wm8900_probe(struct platform_device *pdev) +static int __init wm8900_modinit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; int ret = 0; - - if (!wm8900_codec) { - dev_err(&pdev->dev, "I2C client not yet instantiated\n"); - return -ENODEV; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + ret = i2c_add_driver(&wm8900_i2c_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n", + ret); } - - codec = wm8900_codec; - socdev->card->codec = codec; - - /* Register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register new PCMs\n"); - goto pcm_err; +#endif +#if defined(CONFIG_SPI_MASTER) + ret = spi_register_driver(&wm8900_spi_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8900 SPI driver: %d\n", + ret); } - - snd_soc_add_controls(codec, wm8900_snd_controls, - ARRAY_SIZE(wm8900_snd_controls)); - wm8900_add_widgets(codec); - -pcm_err: +#endif return ret; } - -/* power down chip */ -static int wm8900_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8900 = { - .probe = wm8900_probe, - .remove = wm8900_remove, - .suspend = wm8900_suspend, - .resume = wm8900_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900); - -static int __init wm8900_modinit(void) -{ - return i2c_add_driver(&wm8900_i2c_driver); -} module_init(wm8900_modinit); static void __exit wm8900_exit(void) { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8900_i2c_driver); +#endif +#if defined(CONFIG_SPI_MASTER) + spi_unregister_driver(&wm8900_spi_driver); +#endif } module_exit(wm8900_exit); diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h index fd15007d10c7..583f257e799b 100644 --- a/sound/soc/codecs/wm8900.h +++ b/sound/soc/codecs/wm8900.h @@ -52,7 +52,4 @@ #define WM8900_DAC_CLKDIV_5_5 0x14 #define WM8900_DAC_CLKDIV_6 0x18 -extern struct snd_soc_dai wm8900_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8900; - #endif diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index bf08282d5ee5..f5d73ed72cbd 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -213,10 +213,12 @@ static u16 wm8903_reg_defaults[] = { }; struct wm8903_priv { - struct snd_soc_codec codec; + u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)]; int sysclk; + struct i2c_client *control_data; + int irq; /* Reference counts */ int class_w_users; @@ -252,7 +254,6 @@ static int wm8903_volatile_register(unsigned int reg) static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) { u16 reg[5]; - struct i2c_client *i2c = codec->control_data; struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); BUG_ON(start > 48); @@ -262,7 +263,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0] | WM8903_WSEQ_ENA); - dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); + dev_dbg(codec->dev, "Starting sequence at %d\n", start); snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3, start | WM8903_WSEQ_START); @@ -277,7 +278,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); } while (reg[4] & WM8903_WSEQ_BUSY); - dev_dbg(&i2c->dev, "Sequence complete\n"); + dev_dbg(codec->dev, "Sequence complete\n"); /* Disable the sequencer again if we enabled it */ snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); @@ -422,7 +423,6 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = widget->codec; struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - struct i2c_client *i2c = codec->control_data; u16 reg; int ret; @@ -431,7 +431,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, /* Turn it off if we're about to enable bypass */ if (ucontrol->value.integer.value[0]) { if (wm8903->class_w_users == 0) { - dev_dbg(&i2c->dev, "Disabling Class W\n"); + dev_dbg(codec->dev, "Disabling Class W\n"); snd_soc_write(codec, WM8903_CLASS_W_0, reg & ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); } @@ -444,14 +444,14 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, /* If we've just disabled the last bypass path turn Class W on */ if (!ucontrol->value.integer.value[0]) { if (wm8903->class_w_users == 1) { - dev_dbg(&i2c->dev, "Enabling Class W\n"); + dev_dbg(codec->dev, "Enabling Class W\n"); snd_soc_write(codec, WM8903_CLASS_W_0, reg | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); } wm8903->class_w_users--; } - dev_dbg(&i2c->dev, "Bypass use count now %d\n", + dev_dbg(codec->dev, "Bypass use count now %d\n", wm8903->class_w_users); return ret; @@ -935,7 +935,6 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec) static int wm8903_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - struct i2c_client *i2c = codec->control_data; u16 reg, reg2; switch (level) { @@ -974,7 +973,7 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, /* By default no bypass paths are enabled so * enable Class W support. */ - dev_dbg(&i2c->dev, "Enabling Class W\n"); + dev_dbg(codec->dev, "Enabling Class W\n"); snd_soc_write(codec, WM8903_CLASS_W_0, reg | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); } @@ -1228,10 +1227,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - struct i2c_client *i2c = codec->control_data; struct snd_pcm_runtime *master_runtime; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -1245,7 +1242,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream, if (wm8903->master_substream) { master_runtime = wm8903->master_substream->runtime; - dev_dbg(&i2c->dev, "Constraining to %d bits\n", + dev_dbg(codec->dev, "Constraining to %d bits\n", master_runtime->sample_bits); snd_pcm_hw_constraint_minmax(substream->runtime, @@ -1264,8 +1261,7 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -1284,10 +1280,8 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec =rtd->codec; struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - struct i2c_client *i2c = codec->control_data; int fs = params_rate(params); int bclk; int bclk_div; @@ -1306,7 +1300,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); if (substream == wm8903->slave_substream) { - dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); + dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n"); return 0; } @@ -1332,7 +1326,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, switch (sample_rates[dsp_config].rate) { case 88200: case 96000: - dev_err(&i2c->dev, "%dHz unsupported by ADC\n", + dev_err(codec->dev, "%dHz unsupported by ADC\n", fs); return -EINVAL; @@ -1340,7 +1334,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, break; } - dev_dbg(&i2c->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); + dev_dbg(codec->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); clock1 &= ~WM8903_SAMPLE_RATE_MASK; clock1 |= sample_rates[dsp_config].value; @@ -1366,7 +1360,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - dev_dbg(&i2c->dev, "MCLK = %dHz, target sample rate = %dHz\n", + dev_dbg(codec->dev, "MCLK = %dHz, target sample rate = %dHz\n", wm8903->sysclk, fs); /* We may not have an MCLK which allows us to generate exactly @@ -1401,12 +1395,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT; clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT; - dev_dbg(&i2c->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", + dev_dbg(codec->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", clk_sys_ratios[clk_config].rate, clk_sys_ratios[clk_config].mode, clk_sys_ratios[clk_config].div); - dev_dbg(&i2c->dev, "Actual CLK_SYS = %dHz\n", clk_sys); + dev_dbg(codec->dev, "Actual CLK_SYS = %dHz\n", clk_sys); /* We may not get quite the right frequency if using * approximate clocks so look for the closest match that is @@ -1428,7 +1422,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, aif2 &= ~WM8903_BCLK_DIV_MASK; aif3 &= ~WM8903_LRCLK_RATE_MASK; - dev_dbg(&i2c->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", + dev_dbg(codec->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", bclk_divs[bclk_div].ratio / 10, bclk, (clk_sys * 10) / bclk_divs[bclk_div].ratio); @@ -1504,8 +1498,8 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect); static irqreturn_t wm8903_irq(int irq, void *data) { - struct wm8903_priv *wm8903 = data; - struct snd_soc_codec *codec = &wm8903->codec; + struct snd_soc_codec *codec = data; + struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); int mic_report; int int_pol; int int_val = 0; @@ -1586,8 +1580,8 @@ static struct snd_soc_dai_ops wm8903_dai_ops = { .set_sysclk = wm8903_set_dai_sysclk, }; -struct snd_soc_dai wm8903_dai = { - .name = "WM8903", +static struct snd_soc_dai_driver wm8903_dai = { + .name = "wm8903-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -1605,23 +1599,16 @@ struct snd_soc_dai wm8903_dai = { .ops = &wm8903_dai_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(wm8903_dai); -static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8903_resume(struct platform_device *pdev) +static int wm8903_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - struct i2c_client *i2c = codec->control_data; int i; u16 *reg_cache = codec->reg_cache; u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), @@ -1637,65 +1624,38 @@ static int wm8903_resume(struct platform_device *pdev) snd_soc_write(codec, i, tmp_cache[i]); kfree(tmp_cache); } else { - dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); + dev_err(codec->dev, "Failed to allocate temporary cache\n"); } return 0; } -static struct snd_soc_codec *wm8903_codec; - -static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int wm8903_probe(struct snd_soc_codec *codec) { - struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); - struct wm8903_priv *wm8903; - struct snd_soc_codec *codec; + struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); + struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); int ret, i; int trigger, irq_pol; u16 val; - wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); - if (wm8903 == NULL) - return -ENOMEM; - - codec = &wm8903->codec; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->dev = &i2c->dev; - codec->name = "WM8903"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8903_set_bias_level; - codec->dai = &wm8903_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache); - codec->reg_cache = &wm8903->reg_cache[0]; - snd_soc_codec_set_drvdata(codec, wm8903); - codec->volatile_register = wm8903_volatile_register; init_completion(&wm8903->wseq); - - i2c_set_clientdata(i2c, codec); - codec->control_data = i2c; + codec->control_data = wm8903->control_data; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret != 0) { - dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; } val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID); if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { - dev_err(&i2c->dev, + dev_err(codec->dev, "Device with ID register %x is not a WM8903\n", val); return -ENODEV; } val = snd_soc_read(codec, WM8903_REVISION_NUMBER); - dev_info(&i2c->dev, "WM8903 revision %d\n", + dev_info(codec->dev, "WM8903 revision %d\n", val & WM8903_CHIP_REV_MASK); wm8903_reset(codec); @@ -1721,7 +1681,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, wm8903->mic_delay = pdata->micdet_delay; } - if (i2c->irq) { + if (wm8903->irq) { if (pdata && pdata->irq_active_low) { trigger = IRQF_TRIGGER_LOW; irq_pol = WM8903_IRQ_POL; @@ -1733,13 +1693,13 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL, WM8903_IRQ_POL, irq_pol); - ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq, + ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq, trigger | IRQF_ONESHOT, - "wm8903", wm8903); + "wm8903", codec); if (ret != 0) { - dev_err(&i2c->dev, "Failed to request IRQ: %d\n", + dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); - goto err; + return ret; } /* Enable write sequencer interrupts */ @@ -1781,133 +1741,97 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, val |= WM8903_DAC_MUTEMODE; snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val); - wm8903_dai.dev = &i2c->dev; - wm8903_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); - goto err_irq; - } - - ret = snd_soc_register_dai(&wm8903_dai); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return ret; + snd_soc_add_controls(codec, wm8903_snd_controls, + ARRAY_SIZE(wm8903_snd_controls)); + wm8903_add_widgets(codec); -err_codec: - snd_soc_unregister_codec(codec); -err_irq: - if (i2c->irq) - free_irq(i2c->irq, wm8903); -err: - wm8903_codec = NULL; - kfree(wm8903); return ret; } -static __devexit int wm8903_i2c_remove(struct i2c_client *client) +/* power down chip */ +static int wm8903_remove(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = i2c_get_clientdata(client); - struct wm8903_priv *priv = snd_soc_codec_get_drvdata(codec); + wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} - snd_soc_unregister_dai(&wm8903_dai); - snd_soc_unregister_codec(codec); +static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { + .probe = wm8903_probe, + .remove = wm8903_remove, + .suspend = wm8903_suspend, + .resume = wm8903_resume, + .set_bias_level = wm8903_set_bias_level, + .reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8903_reg_defaults, + .volatile_register = wm8903_volatile_register, +}; - wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct wm8903_priv *wm8903; + int ret; - if (client->irq) - free_irq(client->irq, priv); + wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); + if (wm8903 == NULL) + return -ENOMEM; - kfree(priv); + i2c_set_clientdata(i2c, wm8903); + wm8903->control_data = i2c; + wm8903->irq = i2c->irq; - wm8903_codec = NULL; - wm8903_dai.dev = NULL; + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8903, &wm8903_dai, 1); + if (ret < 0) + kfree(wm8903); + return ret; +} +static __devexit int wm8903_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } -/* i2c codec control layer */ static const struct i2c_device_id wm8903_i2c_id[] = { - { "wm8903", 0 }, - { } + { "wm8903", 0 }, + { } }; MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); static struct i2c_driver wm8903_i2c_driver = { .driver = { - .name = "WM8903", + .name = "wm8903-codec", .owner = THIS_MODULE, }, - .probe = wm8903_i2c_probe, - .remove = __devexit_p(wm8903_i2c_remove), + .probe = wm8903_i2c_probe, + .remove = __devexit_p(wm8903_i2c_remove), .id_table = wm8903_i2c_id, }; +#endif -static int wm8903_probe(struct platform_device *pdev) +static int __init wm8903_modinit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); int ret = 0; - - if (!wm8903_codec) { - dev_err(&pdev->dev, "I2C device not yet probed\n"); - goto err; - } - - socdev->card->codec = wm8903_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(&pdev->dev, "failed to create pcms\n"); - goto err; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + ret = i2c_add_driver(&wm8903_i2c_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n", + ret); } - - snd_soc_add_controls(socdev->card->codec, wm8903_snd_controls, - ARRAY_SIZE(wm8903_snd_controls)); - wm8903_add_widgets(socdev->card->codec); - +#endif return ret; - -err: - return ret; -} - -/* power down chip */ -static int wm8903_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->control_data) - wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8903 = { - .probe = wm8903_probe, - .remove = wm8903_remove, - .suspend = wm8903_suspend, - .resume = wm8903_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903); - -static int __init wm8903_modinit(void) -{ - return i2c_add_driver(&wm8903_i2c_driver); } module_init(wm8903_modinit); static void __exit wm8903_exit(void) { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8903_i2c_driver); +#endif } module_exit(wm8903_exit); diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h index ce384a2ad820..996435e681e5 100644 --- a/sound/soc/codecs/wm8903.h +++ b/sound/soc/codecs/wm8903.h @@ -15,9 +15,6 @@ #include -extern struct snd_soc_dai wm8903_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8903; - extern int wm8903_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, int det, int shrt); diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index f7dcabf6283c..33be84e506ea 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -31,9 +31,6 @@ #include "wm8904.h" -static struct snd_soc_codec *wm8904_codec; -struct snd_soc_codec_device soc_codec_dev_wm8904; - enum wm8904_type { WM8904, WM8912, @@ -52,10 +49,11 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = { /* codec private data */ struct wm8904_priv { - struct snd_soc_codec codec; + u16 reg_cache[WM8904_MAX_REGISTER + 1]; enum wm8904_type devtype; + void *control_data; struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; @@ -689,7 +687,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); struct wm8904_pdata *pdata = wm8904->pdata; int value = ucontrol->value.integer.value[0]; @@ -760,7 +758,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); struct wm8904_pdata *pdata = wm8904->pdata; int value = ucontrol->value.integer.value[0]; @@ -2218,8 +2216,8 @@ static struct snd_soc_dai_ops wm8904_dai_ops = { .digital_mute = wm8904_digital_mute, }; -struct snd_soc_dai wm8904_dai = { - .name = "WM8904", +static struct snd_soc_dai_driver wm8904_dai = { + .name = "wm8904-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -2237,24 +2235,17 @@ struct snd_soc_dai wm8904_dai = { .ops = &wm8904_dai_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(wm8904_dai); #ifdef CONFIG_PM -static int wm8904_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8904_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8904_resume(struct platform_device *pdev) +static int wm8904_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; @@ -2264,9 +2255,9 @@ static int wm8904_resume(struct platform_device *pdev) #define wm8904_resume NULL #endif -static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904) +static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = &wm8904->codec; + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); struct wm8904_pdata *pdata = wm8904->pdata; struct snd_kcontrol_new control = SOC_ENUM_EXT("EQ Mode", @@ -2315,20 +2306,20 @@ static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904) wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; - ret = snd_soc_add_controls(&wm8904->codec, &control, 1); + ret = snd_soc_add_controls(codec, &control, 1); if (ret != 0) - dev_err(wm8904->codec.dev, + dev_err(codec->dev, "Failed to add ReTune Mobile control: %d\n", ret); } -static void wm8904_handle_pdata(struct wm8904_priv *wm8904) +static void wm8904_handle_pdata(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = &wm8904->codec; + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); struct wm8904_pdata *pdata = wm8904->pdata; int ret, i; if (!pdata) { - snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, + snd_soc_add_controls(codec, wm8904_eq_controls, ARRAY_SIZE(wm8904_eq_controls)); return; } @@ -2344,7 +2335,7 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904) wm8904->drc_texts = kmalloc(sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); if (!wm8904->drc_texts) { - dev_err(wm8904->codec.dev, + dev_err(codec->dev, "Failed to allocate %d DRC config texts\n", pdata->num_drc_cfgs); return; @@ -2356,9 +2347,9 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904) wm8904->drc_enum.max = pdata->num_drc_cfgs; wm8904->drc_enum.texts = wm8904->drc_texts; - ret = snd_soc_add_controls(&wm8904->codec, &control, 1); + ret = snd_soc_add_controls(codec, &control, 1); if (ret != 0) - dev_err(wm8904->codec.dev, + dev_err(codec->dev, "Failed to add DRC mode control: %d\n", ret); wm8904_set_drc(codec); @@ -2368,89 +2359,19 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904) pdata->num_retune_mobile_cfgs); if (pdata->num_retune_mobile_cfgs) - wm8904_handle_retune_mobile_pdata(wm8904); + wm8904_handle_retune_mobile_pdata(codec); else - snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, + snd_soc_add_controls(codec, wm8904_eq_controls, ARRAY_SIZE(wm8904_eq_controls)); } -static int wm8904_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8904_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - socdev->card->codec = wm8904_codec; - codec = wm8904_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - wm8904_handle_pdata(snd_soc_codec_get_drvdata(codec)); - - wm8904_add_widgets(codec); - - return ret; - -pcm_err: - return ret; -} - -static int wm8904_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8904 = { - .probe = wm8904_probe, - .remove = wm8904_remove, - .suspend = wm8904_suspend, - .resume = wm8904_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8904); - -static int wm8904_register(struct wm8904_priv *wm8904, - enum snd_soc_control_type control) +static int wm8904_probe(struct snd_soc_codec *codec) { + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); struct wm8904_pdata *pdata = wm8904->pdata; - int ret; - struct snd_soc_codec *codec = &wm8904->codec; - int i; - - if (wm8904_codec) { - dev_err(codec->dev, "Another WM8904 is registered\n"); - ret = -EINVAL; - goto err; - } + int ret, i; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8904); - codec->name = "WM8904"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8904_set_bias_level; - codec->dai = &wm8904_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8904_MAX_REGISTER; - codec->reg_cache = &wm8904->reg_cache; - codec->volatile_register = wm8904_volatile_register; codec->cache_sync = 1; codec->idle_bias_off = 1; @@ -2463,16 +2384,13 @@ static int wm8904_register(struct wm8904_priv *wm8904, default: dev_err(codec->dev, "Unknown device type %d\n", wm8904->devtype); - ret = -EINVAL; - goto err; + return -EINVAL; } - memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg)); - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + return ret; } for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) @@ -2482,7 +2400,7 @@ static int wm8904_register(struct wm8904_priv *wm8904, wm8904->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; + return ret; } ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), @@ -2517,8 +2435,6 @@ static int wm8904_register(struct wm8904_priv *wm8904, goto err_enable; } - wm8904_dai.dev = codec->dev; - /* Change some default settings - latch VU and enable ZC */ wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; @@ -2563,72 +2479,68 @@ static int wm8904_register(struct wm8904_priv *wm8904, /* Bias level configuration will have done an extra enable */ regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); - wm8904_codec = codec; + wm8904_handle_pdata(codec); - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_enable; - } - - ret = snd_soc_register_dai(&wm8904_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } + wm8904_add_widgets(codec); return 0; -err_codec: - snd_soc_unregister_codec(codec); err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); err_get: regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); -err: - kfree(wm8904); return ret; } -static void wm8904_unregister(struct wm8904_priv *wm8904) +static int wm8904_remove(struct snd_soc_codec *codec) { - wm8904_set_bias_level(&wm8904->codec, SND_SOC_BIAS_OFF); + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); + + wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); - snd_soc_unregister_dai(&wm8904_dai); - snd_soc_unregister_codec(&wm8904->codec); - kfree(wm8904); - wm8904_codec = NULL; + + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_wm8904 = { + .probe = wm8904_probe, + .remove = wm8904_remove, + .suspend = wm8904_suspend, + .resume = wm8904_resume, + .set_bias_level = wm8904_set_bias_level, + .reg_cache_size = ARRAY_SIZE(wm8904_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8904_reg, + .volatile_register = wm8904_volatile_register, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8904_priv *wm8904; - struct snd_soc_codec *codec; + int ret; wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL); if (wm8904 == NULL) return -ENOMEM; - codec = &wm8904->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - wm8904->devtype = id->driver_data; - i2c_set_clientdata(i2c, wm8904); - codec->control_data = i2c; + wm8904->control_data = i2c; wm8904->pdata = i2c->dev.platform_data; - codec->dev = &i2c->dev; - - return wm8904_register(wm8904, SND_SOC_I2C); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8904, &wm8904_dai, 1); + if (ret < 0) + kfree(wm8904); + return ret; } static __devexit int wm8904_i2c_remove(struct i2c_client *client) { - struct wm8904_priv *wm8904 = i2c_get_clientdata(client); - wm8904_unregister(wm8904); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -2641,7 +2553,7 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); static struct i2c_driver wm8904_i2c_driver = { .driver = { - .name = "WM8904", + .name = "wm8904-codec", .owner = THIS_MODULE, }, .probe = wm8904_i2c_probe, @@ -2652,15 +2564,15 @@ static struct i2c_driver wm8904_i2c_driver = { static int __init wm8904_modinit(void) { - int ret; + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8904_i2c_driver); if (ret != 0) { - printk(KERN_ERR "Failed to register WM8904 I2C driver: %d\n", + printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n", ret); } #endif - return 0; + return ret; } module_init(wm8904_modinit); diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h index abe5059b3004..9e8c84188ba7 100644 --- a/sound/soc/codecs/wm8904.h +++ b/sound/soc/codecs/wm8904.h @@ -21,9 +21,6 @@ #define WM8904_FLL_LRCLK 3 #define WM8904_FLL_FREE_RUNNING 4 -extern struct snd_soc_dai wm8904_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8904; - /* * Register values. */ diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index f0c11138e610..d28bf0dfdb1d 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -44,7 +44,8 @@ struct wm8940_priv { unsigned int sysclk; u16 reg_cache[WM8940_CACHEREGNUM]; - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; }; static u16 wm8940_reg_defaults[] = { @@ -365,8 +366,7 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F; u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1; u16 companding = snd_soc_read(codec, @@ -636,8 +636,8 @@ static struct snd_soc_dai_ops wm8940_dai_ops = { .set_pll = wm8940_set_dai_pll, }; -struct snd_soc_dai wm8940_dai = { - .name = "WM8940", +static struct snd_soc_dai_driver wm8940_dai = { + .name = "wm8940-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -655,20 +655,14 @@ struct snd_soc_dai wm8940_dai = { .ops = &wm8940_dai_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(wm8940_dai); -static int wm8940_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); } -static int wm8940_resume(struct platform_device *pdev) +static int wm8940_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; int ret; u8 data[3]; @@ -697,108 +691,26 @@ error_ret: return ret; } -static struct snd_soc_codec *wm8940_codec; - -static int wm8940_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - - int ret = 0; - - if (wm8940_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8940_codec; - codec = wm8940_codec; - - mutex_init(&codec->mutex); - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - ret = snd_soc_add_controls(codec, wm8940_snd_controls, - ARRAY_SIZE(wm8940_snd_controls)); - if (ret) - goto error_free_pcms; - ret = wm8940_add_widgets(codec); - if (ret) - goto error_free_pcms; - - return ret; - -error_free_pcms: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -static int wm8940_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8940 = { - .probe = wm8940_probe, - .remove = wm8940_remove, - .suspend = wm8940_suspend, - .resume = wm8940_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940); - -static int wm8940_register(struct wm8940_priv *wm8940, - enum snd_soc_control_type control) +static int wm8940_probe(struct snd_soc_codec *codec) { - struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data; - struct snd_soc_codec *codec = &wm8940->codec; + struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec); + struct wm8940_setup_data *pdata = codec->dev->platform_data; int ret; u16 reg; - if (wm8940_codec) { - dev_err(codec->dev, "Another WM8940 is registered\n"); - return -EINVAL; - } - - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8940); - codec->name = "WM8940"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8940_set_bias_level; - codec->dai = &wm8940_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults); - codec->reg_cache = &wm8940->reg_cache; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); + codec->control_data = wm8940->control_data; + ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } - memcpy(codec->reg_cache, wm8940_reg_defaults, - sizeof(wm8940_reg_defaults)); - ret = wm8940_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); return ret; } - wm8940_dai.dev = codec->dev; - wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); ret = snd_soc_write(codec, WM8940_POWER1, 0x180); @@ -814,64 +726,60 @@ static int wm8940_register(struct wm8940_priv *wm8940, return ret; } - - wm8940_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); + ret = snd_soc_add_controls(codec, wm8940_snd_controls, + ARRAY_SIZE(wm8940_snd_controls)); + if (ret) return ret; - } - - ret = snd_soc_register_dai(&wm8940_dai); - if (ret) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); + ret = wm8940_add_widgets(codec); + if (ret) return ret; - } - return 0; + return ret; +; } -static void wm8940_unregister(struct wm8940_priv *wm8940) +static int wm8940_remove(struct snd_soc_codec *codec) { - wm8940_set_bias_level(&wm8940->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm8940_dai); - snd_soc_unregister_codec(&wm8940->codec); - kfree(wm8940); - wm8940_codec = NULL; + wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; } -static int wm8940_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { + .probe = wm8940_probe, + .remove = wm8940_remove, + .suspend = wm8940_suspend, + .resume = wm8940_resume, + .set_bias_level = wm8940_set_bias_level, + .reg_cache_size = sizeof(wm8940_reg_defaults), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8940_reg_defaults, +}; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8940_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - int ret; struct wm8940_priv *wm8940; - struct snd_soc_codec *codec; + int ret; - wm8940 = kzalloc(sizeof *wm8940, GFP_KERNEL); + wm8940 = kzalloc(sizeof(struct wm8940_priv), GFP_KERNEL); if (wm8940 == NULL) return -ENOMEM; - codec = &wm8940->codec; - codec->hw_write = (hw_write_t)i2c_master_send; i2c_set_clientdata(i2c, wm8940); - codec->control_data = i2c; - codec->dev = &i2c->dev; + wm8940->control_data = i2c; - ret = wm8940_register(wm8940, SND_SOC_I2C); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8940, &wm8940_dai, 1); if (ret < 0) kfree(wm8940); - return ret; } -static int __devexit wm8940_i2c_remove(struct i2c_client *client) +static __devexit int wm8940_i2c_remove(struct i2c_client *client) { - struct wm8940_priv *wm8940 = i2c_get_clientdata(client); - - wm8940_unregister(wm8940); - + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -883,29 +791,34 @@ MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id); static struct i2c_driver wm8940_i2c_driver = { .driver = { - .name = "WM8940 I2C Codec", + .name = "wm8940-codec", .owner = THIS_MODULE, }, - .probe = wm8940_i2c_probe, - .remove = __devexit_p(wm8940_i2c_remove), + .probe = wm8940_i2c_probe, + .remove = __devexit_p(wm8940_i2c_remove), .id_table = wm8940_i2c_id, }; +#endif static int __init wm8940_modinit(void) { - int ret; - + int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8940_i2c_driver); - if (ret) - printk(KERN_ERR "Failed to register WM8940 I2C driver: %d\n", + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n", ret); + } +#endif return ret; } module_init(wm8940_modinit); static void __exit wm8940_exit(void) { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8940_i2c_driver); +#endif } module_exit(wm8940_exit); diff --git a/sound/soc/codecs/wm8940.h b/sound/soc/codecs/wm8940.h index 8410eed3ef84..907fe192e9e0 100644 --- a/sound/soc/codecs/wm8940.h +++ b/sound/soc/codecs/wm8940.h @@ -15,8 +15,6 @@ struct wm8940_setup_data { #define WM8940_VROI_30K 1 unsigned int vroi:1; }; -extern struct snd_soc_dai wm8940_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8940; /* WM8940 register space */ #define WM8940_SOFTRESET 0x00 diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 5f025593d84d..a5a9f8ef5771 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -30,9 +30,6 @@ #include "wm8955.h" -static struct snd_soc_codec *wm8955_codec; -struct snd_soc_codec_device soc_codec_dev_wm8955; - #define WM8955_NUM_SUPPLIES 4 static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { "DCVDD", @@ -43,7 +40,9 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { /* codec private data */ struct wm8955_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; + u16 reg_cache[WM8955_MAX_REGISTER + 1]; unsigned int mclk_rate; @@ -52,8 +51,6 @@ struct wm8955_priv { int fs; struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; - - struct wm8955_pdata *pdata; }; static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { @@ -870,8 +867,8 @@ static struct snd_soc_dai_ops wm8955_dai_ops = { .digital_mute = wm8955_digital_mute, }; -struct snd_soc_dai wm8955_dai = { - .name = "WM8955", +static struct snd_soc_dai_driver wm8955_dai = { + .name = "wm8955-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -881,24 +878,17 @@ struct snd_soc_dai wm8955_dai = { }, .ops = &wm8955_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8955_dai); #ifdef CONFIG_PM -static int wm8955_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8955_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8955_resume(struct platform_device *pdev) +static int wm8955_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; @@ -908,86 +898,17 @@ static int wm8955_resume(struct platform_device *pdev) #define wm8955_resume NULL #endif -static int wm8955_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8955_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8955_codec; - codec = wm8955_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - wm8955_add_widgets(codec); - - return ret; - -pcm_err: - return ret; -} - -static int wm8955_remove(struct platform_device *pdev) +static int wm8955_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8955 = { - .probe = wm8955_probe, - .remove = wm8955_remove, - .suspend = wm8955_suspend, - .resume = wm8955_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8955); - -static int wm8955_register(struct wm8955_priv *wm8955, - enum snd_soc_control_type control) -{ - int ret; - struct snd_soc_codec *codec = &wm8955->codec; - int i; - - if (wm8955_codec) { - dev_err(codec->dev, "Another WM8955 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8955); - codec->name = "WM8955"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8955_set_bias_level; - codec->dai = &wm8955_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8955_MAX_REGISTER; - codec->reg_cache = &wm8955->reg_cache; - - memcpy(codec->reg_cache, wm8955_reg, sizeof(wm8955_reg)); + struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); + struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); + int ret, i; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + codec->control_data = wm8955->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + return ret; } for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) @@ -997,7 +918,7 @@ static int wm8955_register(struct wm8955_priv *wm8955, wm8955->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; + return ret; } ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), @@ -1013,8 +934,6 @@ static int wm8955_register(struct wm8955_priv *wm8955, goto err_enable; } - wm8955_dai.dev = codec->dev; - /* Change some default settings - latch VU and enable ZC */ wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; @@ -1028,12 +947,12 @@ static int wm8955_register(struct wm8955_priv *wm8955, wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; /* Set platform data values */ - if (wm8955->pdata) { - if (wm8955->pdata->out2_speaker) + if (pdata) { + if (pdata->out2_speaker) wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] |= WM8955_ROUT2INV; - if (wm8955->pdata->monoin_diff) + if (pdata->monoin_diff) wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] |= WM8955_DMEN; } @@ -1043,70 +962,61 @@ static int wm8955_register(struct wm8955_priv *wm8955, /* Bias level configuration will have done an extra enable */ regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); - wm8955_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_enable; - } - - ret = snd_soc_register_dai(&wm8955_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } - + wm8955_add_widgets(codec); return 0; -err_codec: - snd_soc_unregister_codec(codec); err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); err_get: regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); -err: - kfree(wm8955); return ret; } -static void wm8955_unregister(struct wm8955_priv *wm8955) +static int wm8955_remove(struct snd_soc_codec *codec) { - wm8955_set_bias_level(&wm8955->codec, SND_SOC_BIAS_OFF); + struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); + + wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); - snd_soc_unregister_dai(&wm8955_dai); - snd_soc_unregister_codec(&wm8955->codec); - kfree(wm8955); - wm8955_codec = NULL; + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { + .probe = wm8955_probe, + .remove = wm8955_remove, + .suspend = wm8955_suspend, + .resume = wm8955_resume, + .set_bias_level = wm8955_set_bias_level, + .reg_cache_size = ARRAY_SIZE(wm8955_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8955_reg, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8955_priv *wm8955; - struct snd_soc_codec *codec; + int ret; wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL); if (wm8955 == NULL) return -ENOMEM; - codec = &wm8955->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - i2c_set_clientdata(i2c, wm8955); - codec->control_data = i2c; - wm8955->pdata = i2c->dev.platform_data; - - codec->dev = &i2c->dev; + wm8955->control_data = i2c; - return wm8955_register(wm8955, SND_SOC_I2C); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8955, &wm8955_dai, 1); + if (ret < 0) + kfree(wm8955); + return ret; } static __devexit int wm8955_i2c_remove(struct i2c_client *client) { - struct wm8955_priv *wm8955 = i2c_get_clientdata(client); - wm8955_unregister(wm8955); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -1118,7 +1028,7 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id); static struct i2c_driver wm8955_i2c_driver = { .driver = { - .name = "wm8955", + .name = "wm8955-codec", .owner = THIS_MODULE, }, .probe = wm8955_i2c_probe, @@ -1129,7 +1039,7 @@ static struct i2c_driver wm8955_i2c_driver = { static int __init wm8955_modinit(void) { - int ret; + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8955_i2c_driver); if (ret != 0) { @@ -1137,7 +1047,7 @@ static int __init wm8955_modinit(void) ret); } #endif - return 0; + return ret; } module_init(wm8955_modinit); diff --git a/sound/soc/codecs/wm8955.h b/sound/soc/codecs/wm8955.h index ae349c8531f6..d13fd5c5fa63 100644 --- a/sound/soc/codecs/wm8955.h +++ b/sound/soc/codecs/wm8955.h @@ -15,9 +15,6 @@ #define WM8955_CLK_MCLK 1 -extern struct snd_soc_dai wm8955_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8955; - /* * Register values. */ diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 3c6ee61f6c95..8d5efb333c33 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -29,8 +29,6 @@ #define AUDIO_NAME "wm8960" -struct snd_soc_codec_device soc_codec_dev_wm8960; - /* R25 - Power 1 */ #define WM8960_VMID_MASK 0x180 #define WM8960_VREF 0x40 @@ -75,7 +73,10 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { struct wm8960_priv { u16 reg_cache[WM8960_CACHEREGNUM]; - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; + int (*set_bias_level)(struct snd_soc_codec *, + enum snd_soc_bias_level level); struct snd_soc_dapm_widget *lout1; struct snd_soc_dapm_widget *rout1; struct snd_soc_dapm_widget *out3; @@ -507,8 +508,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; int i; @@ -849,6 +849,14 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, return 0; } +static int wm8960_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + + return wm8960->set_bias_level(codec, level); +} + #define WM8960_RATES SNDRV_PCM_RATE_8000_48000 #define WM8960_FORMATS \ @@ -863,8 +871,8 @@ static struct snd_soc_dai_ops wm8960_dai_ops = { .set_pll = wm8960_set_dai_pll, }; -struct snd_soc_dai wm8960_dai = { - .name = "WM8960", +static struct snd_soc_dai_driver wm8960_dai = { + .name = "wm8960-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -880,21 +888,18 @@ struct snd_soc_dai wm8960_dai = { .ops = &wm8960_dai_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(wm8960_dai); -static int wm8960_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - codec->set_bias_level(codec, SND_SOC_BIAS_OFF); + wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8960_resume(struct platform_device *pdev) +static int wm8960_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -906,78 +911,19 @@ static int wm8960_resume(struct platform_device *pdev) codec->hw_write(codec->control_data, data, 2); } - codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); - + wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } -static struct snd_soc_codec *wm8960_codec; - -static int wm8960_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8960_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8960_codec; - codec = wm8960_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8960_snd_controls, - ARRAY_SIZE(wm8960_snd_controls)); - wm8960_add_widgets(codec); - - return ret; - -pcm_err: - return ret; -} - -/* power down chip */ -static int wm8960_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8960 = { - .probe = wm8960_probe, - .remove = wm8960_remove, - .suspend = wm8960_suspend, - .resume = wm8960_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960); - -static int wm8960_register(struct wm8960_priv *wm8960, - enum snd_soc_control_type control) +static int wm8960_probe(struct snd_soc_codec *codec) { - struct wm8960_data *pdata = wm8960->codec.dev->platform_data; - struct snd_soc_codec *codec = &wm8960->codec; + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + struct wm8960_data *pdata = dev_get_platdata(codec->dev); int ret; u16 reg; - if (wm8960_codec) { - dev_err(codec->dev, "Another WM8960 is registered\n"); - ret = -EINVAL; - goto err; - } - - codec->set_bias_level = wm8960_set_bias_level_out3; + wm8960->set_bias_level = wm8960_set_bias_level_out3; + codec->control_data = wm8960->control_data; if (!pdata) { dev_warn(codec->dev, "No platform data supplied\n"); @@ -988,39 +934,22 @@ static int wm8960_register(struct wm8960_priv *wm8960, } if (pdata->capless) - codec->set_bias_level = wm8960_set_bias_level_capless; + wm8960->set_bias_level = wm8960_set_bias_level_capless; } - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8960); - codec->name = "WM8960"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->dai = &wm8960_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8960_CACHEREGNUM; - codec->reg_cache = &wm8960->reg_cache; - - memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg)); - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + return ret; } ret = wm8960_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); - goto err; + return ret; } - wm8960_dai.dev = codec->dev; - - codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); + wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the update bits */ reg = snd_soc_read(codec, WM8960_LINVOL); @@ -1044,62 +973,58 @@ static int wm8960_register(struct wm8960_priv *wm8960, reg = snd_soc_read(codec, WM8960_ROUT2); snd_soc_write(codec, WM8960_ROUT2, reg | 0x100); - wm8960_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&wm8960_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } + snd_soc_add_controls(codec, wm8960_snd_controls, + ARRAY_SIZE(wm8960_snd_controls)); + wm8960_add_widgets(codec); return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8960); - return ret; } -static void wm8960_unregister(struct wm8960_priv *wm8960) +/* power down chip */ +static int wm8960_remove(struct snd_soc_codec *codec) { - wm8960->codec.set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm8960_dai); - snd_soc_unregister_codec(&wm8960->codec); - kfree(wm8960); - wm8960_codec = NULL; + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + + wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { + .probe = wm8960_probe, + .remove = wm8960_remove, + .suspend = wm8960_suspend, + .resume = wm8960_resume, + .set_bias_level = wm8960_set_bias_level, + .reg_cache_size = ARRAY_SIZE(wm8960_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8960_reg, +}; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8960_priv *wm8960; - struct snd_soc_codec *codec; + int ret; wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL); if (wm8960 == NULL) return -ENOMEM; - codec = &wm8960->codec; - i2c_set_clientdata(i2c, wm8960); - codec->control_data = i2c; - - codec->dev = &i2c->dev; + wm8960->control_data = i2c; - return wm8960_register(wm8960, SND_SOC_I2C); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8960, &wm8960_dai, 1); + if (ret < 0) + kfree(wm8960); + return ret; } static __devexit int wm8960_i2c_remove(struct i2c_client *client) { - struct wm8960_priv *wm8960 = i2c_get_clientdata(client); - wm8960_unregister(wm8960); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -1111,35 +1036,37 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id); static struct i2c_driver wm8960_i2c_driver = { .driver = { - .name = "wm8960", + .name = "wm8960-codec", .owner = THIS_MODULE, }, .probe = wm8960_i2c_probe, .remove = __devexit_p(wm8960_i2c_remove), .id_table = wm8960_i2c_id, }; +#endif static int __init wm8960_modinit(void) { - int ret; - + int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8960_i2c_driver); if (ret != 0) { printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", ret); } - +#endif return ret; } module_init(wm8960_modinit); static void __exit wm8960_exit(void) { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8960_i2c_driver); +#endif } module_exit(wm8960_exit); - MODULE_DESCRIPTION("ASoC WM8960 driver"); MODULE_AUTHOR("Liam Girdwood"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h index a5ef65481b86..2d8163d7004b 100644 --- a/sound/soc/codecs/wm8960.h +++ b/sound/soc/codecs/wm8960.h @@ -110,7 +110,4 @@ #define WM8960_OPCLK_DIV_5_5 (4 << 0) #define WM8960_OPCLK_DIV_6 (5 << 0) -extern struct snd_soc_dai wm8960_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8960; - #endif diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 2549d3a297ab..5ebe2c04e5cf 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -288,7 +288,8 @@ static u16 wm8961_reg_defaults[] = { }; struct wm8961_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; int sysclk; u16 reg_cache[WM8961_MAX_REGISTER]; }; @@ -940,8 +941,8 @@ static struct snd_soc_dai_ops wm8961_dai_ops = { .set_clkdiv = wm8961_set_clkdiv, }; -struct snd_soc_dai wm8961_dai = { - .name = "WM8961", +static struct snd_soc_dai_driver wm8961_dai = { + .name = "wm8961-hifi", .playback = { .stream_name = "HiFi Playback", .channels_min = 1, @@ -956,140 +957,24 @@ struct snd_soc_dai wm8961_dai = { .formats = WM8961_FORMATS,}, .ops = &wm8961_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8961_dai); - -static struct snd_soc_codec *wm8961_codec; - -static int wm8961_probe(struct platform_device *pdev) +static int wm8961_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; + struct wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec); int ret = 0; - - if (wm8961_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8961_codec; - codec = wm8961_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8961_snd_controls, - ARRAY_SIZE(wm8961_snd_controls)); - snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, - ARRAY_SIZE(wm8961_dapm_widgets)); - snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); - - return ret; - -pcm_err: - return ret; -} - -static int wm8961_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -#ifdef CONFIG_PM -static int wm8961_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8961_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - u16 *reg_cache = codec->reg_cache; - int i; - - for (i = 0; i < codec->reg_cache_size; i++) { - if (reg_cache[i] == wm8961_reg_defaults[i]) - continue; - - if (i == WM8961_SOFTWARE_RESET) - continue; - - snd_soc_write(codec, i, reg_cache[i]); - } - - wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm8961_suspend NULL -#define wm8961_resume NULL -#endif - -struct snd_soc_codec_device soc_codec_dev_wm8961 = { - .probe = wm8961_probe, - .remove = wm8961_remove, - .suspend = wm8961_suspend, - .resume = wm8961_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961); - -static int wm8961_register(struct wm8961_priv *wm8961) -{ - struct snd_soc_codec *codec = &wm8961->codec; - int ret; u16 reg; - if (wm8961_codec) { - dev_err(codec->dev, "Another WM8961 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8961); - codec->name = "WM8961"; - codec->owner = THIS_MODULE; - codec->dai = &wm8961_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache); - codec->reg_cache = &wm8961->reg_cache; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8961_set_bias_level; - codec->volatile_register = wm8961_volatile_register; - - memcpy(codec->reg_cache, wm8961_reg_defaults, - sizeof(wm8961_reg_defaults)); - + codec->control_data = wm8961->control_data; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + return ret; } reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); if (reg != 0x1801) { dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); - ret = -EINVAL; - goto err; + return -EINVAL; } /* This isn't volatile - readback doesn't correspond to write */ @@ -1102,7 +987,7 @@ static int wm8961_register(struct wm8961_priv *wm8961) ret = wm8961_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); - goto err; + return ret; } /* Enable class W */ @@ -1140,64 +1025,90 @@ static int wm8961_register(struct wm8961_priv *wm8961) wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm8961_dai.dev = codec->dev; + snd_soc_add_controls(codec, wm8961_snd_controls, + ARRAY_SIZE(wm8961_snd_controls)); + snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, + ARRAY_SIZE(wm8961_dapm_widgets)); + snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); - wm8961_codec = codec; + return 0; +} - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } +static int wm8961_remove(struct snd_soc_codec *codec) +{ + wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} - ret = snd_soc_register_dai(&wm8961_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } +#ifdef CONFIG_PM +static int wm8961_suspend(struct snd_soc_codec *codec, pm_message_t state) +{ + wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8961); - return ret; } -static void wm8961_unregister(struct wm8961_priv *wm8961) +static int wm8961_resume(struct snd_soc_codec *codec) { - wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm8961_dai); - snd_soc_unregister_codec(&wm8961->codec); - kfree(wm8961); - wm8961_codec = NULL; + u16 *reg_cache = codec->reg_cache; + int i; + + for (i = 0; i < codec->driver->reg_cache_size; i++) { + if (reg_cache[i] == wm8961_reg_defaults[i]) + continue; + + if (i == WM8961_SOFTWARE_RESET) + continue; + + snd_soc_write(codec, i, reg_cache[i]); + } + + wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; } +#else +#define wm8961_suspend NULL +#define wm8961_resume NULL +#endif +static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { + .probe = wm8961_probe, + .remove = wm8961_remove, + .suspend = wm8961_suspend, + .resume = wm8961_resume, + .set_bias_level = wm8961_set_bias_level, + .reg_cache_size = sizeof(wm8961_reg_defaults), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8961_reg_defaults, + .volatile_register = wm8961_volatile_register, +}; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8961_priv *wm8961; - struct snd_soc_codec *codec; + int ret; wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL); if (wm8961 == NULL) return -ENOMEM; - codec = &wm8961->codec; - i2c_set_clientdata(i2c, wm8961); - codec->control_data = i2c; - - codec->dev = &i2c->dev; + wm8961->control_data = i2c; - return wm8961_register(wm8961); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8961, &wm8961_dai, 1); + if (ret < 0) + kfree(wm8961); + return ret; } static __devexit int wm8961_i2c_remove(struct i2c_client *client) { - struct wm8961_priv *wm8961 = i2c_get_clientdata(client); - wm8961_unregister(wm8961); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -1209,35 +1120,37 @@ MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id); static struct i2c_driver wm8961_i2c_driver = { .driver = { - .name = "wm8961", + .name = "wm8961-codec", .owner = THIS_MODULE, }, .probe = wm8961_i2c_probe, .remove = __devexit_p(wm8961_i2c_remove), .id_table = wm8961_i2c_id, }; +#endif static int __init wm8961_modinit(void) { - int ret; - + int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8961_i2c_driver); if (ret != 0) { - printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n", + printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n", ret); } - +#endif return ret; } module_init(wm8961_modinit); static void __exit wm8961_exit(void) { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8961_i2c_driver); +#endif } module_exit(wm8961_exit); - MODULE_DESCRIPTION("ASoC WM8961 driver"); MODULE_AUTHOR("Mark Brown "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wm8961.h b/sound/soc/codecs/wm8961.h index 5513bfd720d6..1d736e5701c8 100644 --- a/sound/soc/codecs/wm8961.h +++ b/sound/soc/codecs/wm8961.h @@ -11,9 +11,6 @@ #include -extern struct snd_soc_codec_device soc_codec_dev_wm8961; -extern struct snd_soc_dai wm8961_dai; - #define WM8961_BCLK 1 #define WM8961_LRCLK 2 diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index a99620f335d2..ad2692afbb31 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -38,6 +38,8 @@ static struct workqueue_struct *wm8971_workq = NULL; /* codec private data */ struct wm8971_priv { + enum snd_soc_control_type control_type; + void *control_data; unsigned int sysclk; }; @@ -492,8 +494,7 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3; u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0; @@ -573,8 +574,8 @@ static struct snd_soc_dai_ops wm8971_dai_ops = { .set_sysclk = wm8971_set_dai_sysclk, }; -struct snd_soc_dai wm8971_dai = { - .name = "WM8971", +static struct snd_soc_dai_driver wm8971_dai = { + .name = "wm8971-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -589,7 +590,6 @@ struct snd_soc_dai wm8971_dai = { .formats = WM8971_FORMATS,}, .ops = &wm8971_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8971_dai); static void wm8971_work(struct work_struct *work) { @@ -598,19 +598,14 @@ static void wm8971_work(struct work_struct *work) wm8971_set_bias_level(codec, codec->bias_level); } -static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8971_resume(struct platform_device *pdev) +static int wm8971_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -639,37 +634,27 @@ static int wm8971_resume(struct platform_device *pdev) return 0; } -static int wm8971_init(struct snd_soc_device *socdev, - enum snd_soc_control_type control) +static int wm8971_probe(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = socdev->card->codec; - int reg, ret = 0; - - codec->name = "WM8971"; - codec->owner = THIS_MODULE; - codec->set_bias_level = wm8971_set_bias_level; - codec->dai = &wm8971_dai; - codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); - codec->num_dai = 1; - codec->reg_cache = kmemdup(wm8971_reg, sizeof(wm8971_reg), GFP_KERNEL); - - if (codec->reg_cache == NULL) - return -ENOMEM; + struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); + int ret = 0; + u16 reg; + + pr_info("WM8971 Audio Codec %s", WM8971_VERSION); - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + codec->control_data = wm8971->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type); if (ret < 0) { printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); - goto err; + return ret; } - wm8971_reset(codec); + INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work); + wm8971_workq = create_workqueue("wm8971"); + if (wm8971_workq == NULL) + return -ENOMEM; - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "wm8971: failed to create pcms\n"); - goto err; - } + wm8971_reset(codec); /* charge output caps - set vmid to 5k for quick power up */ reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; @@ -704,40 +689,55 @@ static int wm8971_init(struct snd_soc_device *socdev, wm8971_add_widgets(codec); return ret; - -err: - kfree(codec->reg_cache); - return ret; } -/* If the i2c layer weren't so broken, we could pass this kind of data - around */ -static struct snd_soc_device *wm8971_socdev; -#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) +/* power down chip */ +static int wm8971_remove(struct snd_soc_codec *codec) +{ + wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); + + if (wm8971_workq) + destroy_workqueue(wm8971_workq); + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { + .probe = wm8971_probe, + .remove = wm8971_remove, + .suspend = wm8971_suspend, + .resume = wm8971_resume, + .set_bias_level = wm8971_set_bias_level, + .reg_cache_size = ARRAY_SIZE(wm8971_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8971_reg, +}; -static int wm8971_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8971_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - struct snd_soc_device *socdev = wm8971_socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct wm8971_priv *wm8971; int ret; - i2c_set_clientdata(i2c, codec); + wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL); + if (wm8971 == NULL) + return -ENOMEM; - codec->control_data = i2c; + i2c_set_clientdata(i2c, wm8971); + wm8971->control_data = i2c; - ret = wm8971_init(socdev, SND_SOC_I2C); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8971, &wm8971_dai, 1); if (ret < 0) - pr_err("failed to initialise WM8971\n"); - + kfree(wm8971); return ret; } -static int wm8971_i2c_remove(struct i2c_client *client) +static __devexit int wm8971_i2c_remove(struct i2c_client *client) { - struct snd_soc_codec *codec = i2c_get_clientdata(client); - kfree(codec->reg_cache); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -749,148 +749,34 @@ MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id); static struct i2c_driver wm8971_i2c_driver = { .driver = { - .name = "WM8971 I2C Codec", + .name = "wm8971-codec", .owner = THIS_MODULE, }, - .probe = wm8971_i2c_probe, - .remove = wm8971_i2c_remove, + .probe = wm8971_i2c_probe, + .remove = __devexit_p(wm8971_i2c_remove), .id_table = wm8971_i2c_id, }; - -static int wm8971_add_i2c_device(struct platform_device *pdev, - const struct wm8971_setup_data *setup) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - int ret; - - ret = i2c_add_driver(&wm8971_i2c_driver); - if (ret != 0) { - dev_err(&pdev->dev, "can't add i2c driver\n"); - return ret; - } - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = setup->i2c_address; - strlcpy(info.type, "wm8971", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(setup->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "can't get i2c adapter %d\n", - setup->i2c_bus); - goto err_driver; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - goto err_driver; - } - - return 0; - -err_driver: - i2c_del_driver(&wm8971_i2c_driver); - return -ENODEV; -} - #endif -static int wm8971_probe(struct platform_device *pdev) +static int __init wm8971_modinit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct wm8971_setup_data *setup; - struct snd_soc_codec *codec; - struct wm8971_priv *wm8971; int ret = 0; - - pr_info("WM8971 Audio Codec %s", WM8971_VERSION); - - setup = socdev->codec_data; - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) - return -ENOMEM; - - wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL); - if (wm8971 == NULL) { - kfree(codec); - return -ENOMEM; - } - - snd_soc_codec_set_drvdata(codec, wm8971); - socdev->card->codec = codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - wm8971_socdev = socdev; - - INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work); - wm8971_workq = create_workqueue("wm8971"); - if (wm8971_workq == NULL) { - kfree(snd_soc_codec_get_drvdata(codec)); - kfree(codec); - return -ENOMEM; - } - -#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) - if (setup->i2c_address) { - ret = wm8971_add_i2c_device(pdev, setup); - } -#endif - /* Add other interfaces here */ - +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + ret = i2c_add_driver(&wm8971_i2c_driver); if (ret != 0) { - destroy_workqueue(wm8971_workq); - kfree(snd_soc_codec_get_drvdata(codec)); - kfree(codec); + printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n", + ret); } - - return ret; -} - -/* power down chip */ -static int wm8971_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->control_data) - wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); - if (wm8971_workq) - destroy_workqueue(wm8971_workq); - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) - i2c_unregister_device(codec->control_data); - i2c_del_driver(&wm8971_i2c_driver); #endif - kfree(snd_soc_codec_get_drvdata(codec)); - kfree(codec); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8971 = { - .probe = wm8971_probe, - .remove = wm8971_remove, - .suspend = wm8971_suspend, - .resume = wm8971_resume, -}; - -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971); - -static int __init wm8971_modinit(void) -{ - return snd_soc_register_dai(&wm8971_dai); + return ret; } module_init(wm8971_modinit); static void __exit wm8971_exit(void) { - snd_soc_unregister_dai(&wm8971_dai); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_del_driver(&wm8971_i2c_driver); +#endif } module_exit(wm8971_exit); diff --git a/sound/soc/codecs/wm8971.h b/sound/soc/codecs/wm8971.h index ef4f08f9f344..f31c38fddfc4 100644 --- a/sound/soc/codecs/wm8971.h +++ b/sound/soc/codecs/wm8971.h @@ -53,12 +53,4 @@ #define WM8971_SYSCLK 0 -struct wm8971_setup_data { - int i2c_bus; - unsigned short i2c_address; -}; - -extern struct snd_soc_dai wm8971_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8971; - #endif diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 1468fe10cbbe..52f631c62e29 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -51,12 +51,11 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { #define WM8974_POWER1_BUFIOEN 0x04 struct wm8974_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; u16 reg_cache[WM8974_CACHEREGNUM]; }; -static struct snd_soc_codec *wm8974_codec; - #define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0) static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" }; @@ -566,8 +565,8 @@ static struct snd_soc_dai_ops wm8974_ops = { .set_pll = wm8974_set_dai_pll, }; -struct snd_soc_dai wm8974_dai = { - .name = "WM8974 HiFi", +static struct snd_soc_dai_driver wm8974_dai = { + .name = "wm8974-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -583,21 +582,15 @@ struct snd_soc_dai wm8974_dai = { .ops = &wm8974_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(wm8974_dai); -static int wm8974_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8974_resume(struct platform_device *pdev) +static int wm8974_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -613,156 +606,75 @@ static int wm8974_resume(struct platform_device *pdev) return 0; } -static int wm8974_probe(struct platform_device *pdev) +static int wm8974_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; + struct wm8974_priv *wm8974 = snd_soc_codec_get_drvdata(codec); int ret = 0; - if (wm8974_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; + codec->control_data = wm8974->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; } - socdev->card->codec = wm8974_codec; - codec = wm8974_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + ret = wm8974_reset(codec); if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; + dev_err(codec->dev, "Failed to issue reset\n"); + return ret; } + wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); snd_soc_add_controls(codec, wm8974_snd_controls, ARRAY_SIZE(wm8974_snd_controls)); wm8974_add_widgets(codec); return ret; - -pcm_err: - return ret; } /* power down chip */ -static int wm8974_remove(struct platform_device *pdev) +static int wm8974_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - + wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -struct snd_soc_codec_device soc_codec_dev_wm8974 = { +static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { .probe = wm8974_probe, .remove = wm8974_remove, .suspend = wm8974_suspend, .resume = wm8974_resume, + .set_bias_level = wm8974_set_bias_level, + .reg_cache_size = ARRAY_SIZE(wm8974_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8974_reg, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8974); - -static __devinit int wm8974_register(struct wm8974_priv *wm8974) -{ - int ret; - struct snd_soc_codec *codec = &wm8974->codec; - - if (wm8974_codec) { - dev_err(codec->dev, "Another WM8974 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8974); - codec->name = "WM8974"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8974_set_bias_level; - codec->dai = &wm8974_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8974_CACHEREGNUM; - codec->reg_cache = &wm8974->reg_cache; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - memcpy(codec->reg_cache, wm8974_reg, sizeof(wm8974_reg)); - - ret = wm8974_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err; - } - - wm8974_dai.dev = codec->dev; - - wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - wm8974_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&wm8974_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8974); - return ret; -} - -static __devexit void wm8974_unregister(struct wm8974_priv *wm8974) -{ - wm8974_set_bias_level(&wm8974->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm8974_dai); - snd_soc_unregister_codec(&wm8974->codec); - kfree(wm8974); - wm8974_codec = NULL; -} +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8974_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8974_priv *wm8974; - struct snd_soc_codec *codec; + int ret; wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL); if (wm8974 == NULL) return -ENOMEM; - codec = &wm8974->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - i2c_set_clientdata(i2c, wm8974); - codec->control_data = i2c; - - codec->dev = &i2c->dev; + wm8974->control_data = i2c; - return wm8974_register(wm8974); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8974, &wm8974_dai, 1); + if (ret < 0) + kfree(wm8974); + return ret; } static __devexit int wm8974_i2c_remove(struct i2c_client *client) { - struct wm8974_priv *wm8974 = i2c_get_clientdata(client); - wm8974_unregister(wm8974); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -774,23 +686,34 @@ MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id); static struct i2c_driver wm8974_i2c_driver = { .driver = { - .name = "WM8974", + .name = "wm8974-codec", .owner = THIS_MODULE, }, .probe = wm8974_i2c_probe, .remove = __devexit_p(wm8974_i2c_remove), .id_table = wm8974_i2c_id, }; +#endif static int __init wm8974_modinit(void) { - return i2c_add_driver(&wm8974_i2c_driver); + int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + ret = i2c_add_driver(&wm8974_i2c_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n", + ret); + } +#endif + return ret; } module_init(wm8974_modinit); static void __exit wm8974_exit(void) { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8974_i2c_driver); +#endif } module_exit(wm8974_exit); diff --git a/sound/soc/codecs/wm8974.h b/sound/soc/codecs/wm8974.h index 896a7f0f3fc4..3c94e7bb55a6 100644 --- a/sound/soc/codecs/wm8974.h +++ b/sound/soc/codecs/wm8974.h @@ -83,7 +83,4 @@ #define WM8974_MCLKDIV_8 (6 << 5) #define WM8974_MCLKDIV_12 (7 << 5) -extern struct snd_soc_dai wm8974_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8974; - #endif diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 8a1ad778e7e3..676a4306cc87 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -31,8 +31,6 @@ #include "wm8978.h" -static struct snd_soc_codec *wm8978_codec; - /* wm8978 register cache. Note that register 0 is not included in the cache. */ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { 0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */ @@ -54,7 +52,8 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { /* codec private data */ struct wm8978_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; unsigned int f_pllout; unsigned int f_mclk; unsigned int f_256fs; @@ -374,8 +373,8 @@ struct wm8978_pll_div { #define FIXED_PLL_SIZE (1 << 24) -static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target, - unsigned int source) +static void pll_factors(struct snd_soc_codec *codec, + struct wm8978_pll_div *pll_div, unsigned int target, unsigned int source) { u64 k_part; unsigned int k, n_div, n_mod; @@ -390,7 +389,7 @@ static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target, } if (n_div < 6 || n_div > 12) - dev_warn(wm8978_codec->dev, + dev_warn(codec->dev, "WM8978 N value exceeds recommended range! N = %u\n", n_div); @@ -505,7 +504,7 @@ static int wm8978_configure_pll(struct snd_soc_codec *codec) dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__, wm8978->f_mclk, wm8978->f_pllout); - pll_factors(&pll_div, f2, wm8978->f_mclk); + pll_factors(codec, &pll_div, f2, wm8978->f_mclk); dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n", __func__, pll_div.n, pll_div.k, pll_div.div2); @@ -690,8 +689,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); /* Word length mask = 0x60 */ u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60; @@ -875,9 +873,8 @@ static struct snd_soc_dai_ops wm8978_dai_ops = { }; /* Also supports 12kHz */ -struct snd_soc_dai wm8978_dai = { - .name = "WM8978 HiFi", - .id = 1, +static struct snd_soc_dai_driver wm8978_dai = { + .name = "wm8978-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -894,13 +891,9 @@ struct snd_soc_dai wm8978_dai = { }, .ops = &wm8978_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8978_dai); -static int wm8978_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8978_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); /* Also switch PLL off */ snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); @@ -908,10 +901,8 @@ static int wm8978_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int wm8978_resume(struct platform_device *pdev) +static int wm8978_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); int i; u16 *cache = codec->reg_cache; @@ -933,54 +924,6 @@ static int wm8978_resume(struct platform_device *pdev) return 0; } -static int wm8978_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8978_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8978_codec; - codec = wm8978_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8978_snd_controls, - ARRAY_SIZE(wm8978_snd_controls)); - wm8978_add_widgets(codec); - -pcm_err: - return ret; -} - -/* power down chip */ -static int wm8978_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8978 = { - .probe = wm8978_probe, - .remove = wm8978_remove, - .suspend = wm8978_suspend, - .resume = wm8978_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8978); - /* * These registers contain an "update" bit - bit 8. This means, for example, * that one can write new DAC digital volume for both channels, but only when @@ -1000,44 +943,23 @@ static const int update_reg[] = { WM8978_ROUT2_SPK_CONTROL, }; -static __devinit int wm8978_register(struct wm8978_priv *wm8978) +static int wm8978_probe(struct snd_soc_codec *codec) { - int ret, i; - struct snd_soc_codec *codec = &wm8978->codec; - - if (wm8978_codec) { - dev_err(codec->dev, "Another WM8978 is registered\n"); - return -EINVAL; - } + struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); + int ret = 0, i; /* * Set default system clock to PLL, it is more precise, this is also the * default hardware setting */ wm8978->sysclk = WM8978_PLL; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8978); - codec->name = "WM8978"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8978_set_bias_level; - codec->dai = &wm8978_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8978_CACHEREGNUM; - codec->reg_cache = &wm8978->reg_cache; - + codec->control_data = wm8978->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + return ret; } - memcpy(codec->reg_cache, wm8978_reg, sizeof(wm8978_reg)); - /* * Set the update bit in all registers, that have one. This way all * writes to those registers will also cause the update bit to be @@ -1050,74 +972,61 @@ static __devinit int wm8978_register(struct wm8978_priv *wm8978) ret = snd_soc_write(codec, WM8978_RESET, 0); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); - goto err; + return ret; } - wm8978_dai.dev = codec->dev; - wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm8978_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&wm8978_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } + snd_soc_add_controls(codec, wm8978_snd_controls, + ARRAY_SIZE(wm8978_snd_controls)); + wm8978_add_widgets(codec); return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - return ret; } -static __devexit void wm8978_unregister(struct wm8978_priv *wm8978) +/* power down chip */ +static int wm8978_remove(struct snd_soc_codec *codec) { - wm8978_set_bias_level(&wm8978->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm8978_dai); - snd_soc_unregister_codec(&wm8978->codec); - wm8978_codec = NULL; + wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_wm8978 = { + .probe = wm8978_probe, + .remove = wm8978_remove, + .suspend = wm8978_suspend, + .resume = wm8978_resume, + .set_bias_level = wm8978_set_bias_level, + .reg_cache_size = ARRAY_SIZE(wm8978_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8978_reg, +}; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - int ret; struct wm8978_priv *wm8978; - struct snd_soc_codec *codec; + int ret; wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL); if (wm8978 == NULL) return -ENOMEM; - codec = &wm8978->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - i2c_set_clientdata(i2c, wm8978); - codec->control_data = i2c; - - codec->dev = &i2c->dev; + wm8978->control_data = i2c; - ret = wm8978_register(wm8978); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8978, &wm8978_dai, 1); if (ret < 0) kfree(wm8978); - return ret; } static __devexit int wm8978_i2c_remove(struct i2c_client *client) { - struct wm8978_priv *wm8978 = i2c_get_clientdata(client); - wm8978_unregister(wm8978); - kfree(wm8978); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -1129,23 +1038,34 @@ MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id); static struct i2c_driver wm8978_i2c_driver = { .driver = { - .name = "WM8978", + .name = "WM8978-codec", .owner = THIS_MODULE, }, .probe = wm8978_i2c_probe, .remove = __devexit_p(wm8978_i2c_remove), .id_table = wm8978_i2c_id, }; +#endif static int __init wm8978_modinit(void) { - return i2c_add_driver(&wm8978_i2c_driver); + int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + ret = i2c_add_driver(&wm8978_i2c_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n", + ret); + } +#endif + return ret; } module_init(wm8978_modinit); static void __exit wm8978_exit(void) { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8978_i2c_driver); +#endif } module_exit(wm8978_exit); diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h index 56ec83270917..c75525b7f154 100644 --- a/sound/soc/codecs/wm8978.h +++ b/sound/soc/codecs/wm8978.h @@ -80,7 +80,4 @@ enum wm8978_sysclk_src { WM8978_MCLK }; -extern struct snd_soc_dai wm8978_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8978; - #endif /* __WM8978_H__ */ diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 19ad590ca0b3..ecbffcea71db 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -52,7 +52,8 @@ static const u16 wm8988_reg[] = { /* codec private data */ struct wm8988_priv { unsigned int sysclk; - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; struct snd_pcm_hw_constraint_list *sysclk_constraints; u16 reg_cache[WM8988_NUM_REG]; }; @@ -608,8 +609,7 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3; u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180; @@ -711,8 +711,8 @@ static struct snd_soc_dai_ops wm8988_ops = { .digital_mute = wm8988_mute, }; -struct snd_soc_dai wm8988_dai = { - .name = "WM8988", +static struct snd_soc_dai_driver wm8988_dai = { + .name = "wm8988-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -730,21 +730,15 @@ struct snd_soc_dai wm8988_dai = { .ops = &wm8988_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(wm8988_dai); -static int wm8988_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8988_resume(struct platform_device *pdev) +static int wm8988_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -763,99 +757,23 @@ static int wm8988_resume(struct platform_device *pdev) return 0; } -static struct snd_soc_codec *wm8988_codec; - -static int wm8988_probe(struct platform_device *pdev) +static int wm8988_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; + struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); int ret = 0; - - if (wm8988_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8988_codec; - codec = wm8988_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8988_snd_controls, - ARRAY_SIZE(wm8988_snd_controls)); - snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, - ARRAY_SIZE(wm8988_dapm_widgets)); - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - - return ret; - -pcm_err: - return ret; -} - -static int wm8988_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8988 = { - .probe = wm8988_probe, - .remove = wm8988_remove, - .suspend = wm8988_suspend, - .resume = wm8988_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988); - -static int wm8988_register(struct wm8988_priv *wm8988, - enum snd_soc_control_type control) -{ - struct snd_soc_codec *codec = &wm8988->codec; - int ret; u16 reg; - if (wm8988_codec) { - dev_err(codec->dev, "Another WM8988 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8988); - codec->name = "WM8988"; - codec->owner = THIS_MODULE; - codec->dai = &wm8988_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache); - codec->reg_cache = &wm8988->reg_cache; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8988_set_bias_level; - - memcpy(codec->reg_cache, wm8988_reg, - sizeof(wm8988_reg)); - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + codec->control_data = wm8988->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; + return ret; } ret = wm8988_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); - goto err; + return ret; } /* set the update bits (we always update left then right) */ @@ -870,139 +788,135 @@ static int wm8988_register(struct wm8988_priv *wm8988, reg = snd_soc_read(codec, WM8988_RINVOL); snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); - wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY); - - wm8988_dai.dev = codec->dev; - - wm8988_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } + wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - ret = snd_soc_register_dai(&wm8988_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } + snd_soc_add_controls(codec, wm8988_snd_controls, + ARRAY_SIZE(wm8988_snd_controls)); + snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, + ARRAY_SIZE(wm8988_dapm_widgets)); + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8988); - return ret; } -static void wm8988_unregister(struct wm8988_priv *wm8988) +static int wm8988_remove(struct snd_soc_codec *codec) { - wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm8988_dai); - snd_soc_unregister_codec(&wm8988->codec); - kfree(wm8988); - wm8988_codec = NULL; + wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; } -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static int wm8988_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static struct snd_soc_codec_driver soc_codec_dev_wm8988 = { + .probe = wm8988_probe, + .remove = wm8988_remove, + .suspend = wm8988_suspend, + .resume = wm8988_resume, + .set_bias_level = wm8988_set_bias_level, + .reg_cache_size = sizeof(wm8988_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8988_reg, +}; + +#if defined(CONFIG_SPI_MASTER) +static int __devinit wm8988_spi_probe(struct spi_device *spi) { struct wm8988_priv *wm8988; - struct snd_soc_codec *codec; + int ret; wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); if (wm8988 == NULL) return -ENOMEM; - codec = &wm8988->codec; - - i2c_set_clientdata(i2c, wm8988); - codec->control_data = i2c; - - codec->dev = &i2c->dev; + wm8988->control_data = spi; + wm8988->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, wm8988); - return wm8988_register(wm8988, SND_SOC_I2C); + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8988, &wm8988_dai, 1); + if (ret < 0) + kfree(wm8988); + return ret; } -static int wm8988_i2c_remove(struct i2c_client *client) +static int __devexit wm8988_spi_remove(struct spi_device *spi) { - struct wm8988_priv *wm8988 = i2c_get_clientdata(client); - wm8988_unregister(wm8988); + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); return 0; } -static const struct i2c_device_id wm8988_i2c_id[] = { - { "wm8988", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); - -static struct i2c_driver wm8988_i2c_driver = { +static struct spi_driver wm8988_spi_driver = { .driver = { - .name = "WM8988", - .owner = THIS_MODULE, + .name = "wm8988-codec", + .bus = &spi_bus_type, + .owner = THIS_MODULE, }, - .probe = wm8988_i2c_probe, - .remove = wm8988_i2c_remove, - .id_table = wm8988_i2c_id, + .probe = wm8988_spi_probe, + .remove = __devexit_p(wm8988_spi_remove), }; -#endif +#endif /* CONFIG_SPI_MASTER */ -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8988_spi_probe(struct spi_device *spi) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8988_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { struct wm8988_priv *wm8988; - struct snd_soc_codec *codec; + int ret; wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); if (wm8988 == NULL) return -ENOMEM; - codec = &wm8988->codec; - codec->control_data = spi; - codec->dev = &spi->dev; - - dev_set_drvdata(&spi->dev, wm8988); + i2c_set_clientdata(i2c, wm8988); + wm8988->control_data = i2c; + wm8988->control_type = SND_SOC_I2C; - return wm8988_register(wm8988, SND_SOC_SPI); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8988, &wm8988_dai, 1); + if (ret < 0) + kfree(wm8988); + return ret; } -static int __devexit wm8988_spi_remove(struct spi_device *spi) +static __devexit int wm8988_i2c_remove(struct i2c_client *client) { - struct wm8988_priv *wm8988 = dev_get_drvdata(&spi->dev); - - wm8988_unregister(wm8988); - + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } -static struct spi_driver wm8988_spi_driver = { +static const struct i2c_device_id wm8988_i2c_id[] = { + { "wm8988", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); + +static struct i2c_driver wm8988_i2c_driver = { .driver = { - .name = "wm8988", - .bus = &spi_bus_type, - .owner = THIS_MODULE, + .name = "wm8988-codec", + .owner = THIS_MODULE, }, - .probe = wm8988_spi_probe, - .remove = __devexit_p(wm8988_spi_remove), + .probe = wm8988_i2c_probe, + .remove = __devexit_p(wm8988_i2c_remove), + .id_table = wm8988_i2c_id, }; #endif static int __init wm8988_modinit(void) { - int ret; - + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8988_i2c_driver); - if (ret != 0) - pr_err("WM8988: Unable to register I2C driver: %d\n", ret); + if (ret != 0) { + printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n", + ret); + } #endif #if defined(CONFIG_SPI_MASTER) ret = spi_register_driver(&wm8988_spi_driver); - if (ret != 0) - pr_err("WM8988: Unable to register SPI driver: %d\n", ret); + if (ret != 0) { + printk(KERN_ERR "Failed to register WM8988 SPI driver: %d\n", + ret); + } #endif return ret; } diff --git a/sound/soc/codecs/wm8988.h b/sound/soc/codecs/wm8988.h index 4552d37fdd41..5c04024e5f9f 100644 --- a/sound/soc/codecs/wm8988.h +++ b/sound/soc/codecs/wm8988.h @@ -54,7 +54,4 @@ #define WM8988_SYSCLK 0 -extern struct snd_soc_dai wm8988_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8988; - #endif diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index dd8d909788c1..b25243382966 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -32,6 +32,8 @@ /* codec private data */ struct wm8990_priv { + enum snd_soc_control_type control_type; + void *control_data; unsigned int sysclk; unsigned int pcmclk; }; @@ -1114,8 +1116,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); audio1 &= ~WM8990_AIF_WL_MASK; @@ -1293,10 +1294,9 @@ static struct snd_soc_dai_ops wm8990_dai_ops = { .set_sysclk = wm8990_set_dai_sysclk, }; -struct snd_soc_dai wm8990_dai = { +static struct snd_soc_dai_driver wm8990_dai = { /* ADC/DAC on primary */ - .name = "WM8990 ADC/DAC Primary", - .id = 1, + .name = "wm8990-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -1311,21 +1311,15 @@ struct snd_soc_dai wm8990_dai = { .formats = WM8990_FORMATS,}, .ops = &wm8990_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8990_dai); -static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8990_resume(struct platform_device *pdev) +static int wm8990_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -1347,38 +1341,21 @@ static int wm8990_resume(struct platform_device *pdev) * initialise the WM8990 driver * register the mixer and dsp interfaces with the kernel */ -static int wm8990_init(struct snd_soc_device *socdev) +static int wm8990_probe(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = socdev->card->codec; + struct wm8990_priv *wm8990 = snd_soc_codec_get_drvdata(codec); + int ret; u16 reg; - int ret = 0; - - codec->name = "WM8990"; - codec->owner = THIS_MODULE; - codec->set_bias_level = wm8990_set_bias_level; - codec->dai = &wm8990_dai; - codec->num_dai = 2; - codec->reg_cache_size = ARRAY_SIZE(wm8990_reg); - codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL); - - if (codec->reg_cache == NULL) - return -ENOMEM; + codec->control_data = wm8990->control_data; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret < 0) { printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); - goto pcm_err; + return ret; } wm8990_reset(codec); - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "wm8990: failed to create pcms\n"); - goto pcm_err; - } - /* charge output caps */ codec->bias_level = SND_SOC_BIAS_OFF; wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1400,47 +1377,52 @@ static int wm8990_init(struct snd_soc_device *socdev) ARRAY_SIZE(wm8990_snd_controls)); wm8990_add_widgets(codec); - return ret; + return 0; +} -pcm_err: - kfree(codec->reg_cache); - return ret; +/* power down chip */ +static int wm8990_remove(struct snd_soc_codec *codec) +{ + wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; } -/* If the i2c layer weren't so broken, we could pass this kind of data - around */ -static struct snd_soc_device *wm8990_socdev; +static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { + .probe = wm8990_probe, + .remove = wm8990_remove, + .suspend = wm8990_suspend, + .resume = wm8990_resume, + .set_bias_level = wm8990_set_bias_level, + .reg_cache_size = ARRAY_SIZE(wm8990_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8990_reg, +}; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -/* - * WM891 2 wire address is determined by GPIO5 - * state during powerup. - * low = 0x34 - * high = 0x36 - */ - -static int wm8990_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - struct snd_soc_device *socdev = wm8990_socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct wm8990_priv *wm8990; int ret; - i2c_set_clientdata(i2c, codec); - codec->control_data = i2c; + wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); + if (wm8990 == NULL) + return -ENOMEM; - ret = wm8990_init(socdev); - if (ret < 0) - pr_err("failed to initialise WM8990\n"); + i2c_set_clientdata(i2c, wm8990); + wm8990->control_data = i2c; + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8990, &wm8990_dai, 1); + if (ret < 0) + kfree(wm8990); return ret; } -static int wm8990_i2c_remove(struct i2c_client *client) +static __devexit int wm8990_i2c_remove(struct i2c_client *client) { - struct snd_soc_codec *codec = i2c_get_clientdata(client); - kfree(codec->reg_cache); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -1452,134 +1434,34 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id); static struct i2c_driver wm8990_i2c_driver = { .driver = { - .name = "WM8990 I2C Codec", + .name = "wm8990-codec", .owner = THIS_MODULE, }, .probe = wm8990_i2c_probe, - .remove = wm8990_i2c_remove, + .remove = __devexit_p(wm8990_i2c_remove), .id_table = wm8990_i2c_id, }; - -static int wm8990_add_i2c_device(struct platform_device *pdev, - const struct wm8990_setup_data *setup) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - int ret; - - ret = i2c_add_driver(&wm8990_i2c_driver); - if (ret != 0) { - dev_err(&pdev->dev, "can't add i2c driver\n"); - return ret; - } - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = setup->i2c_address; - strlcpy(info.type, "wm8990", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(setup->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "can't get i2c adapter %d\n", - setup->i2c_bus); - goto err_driver; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - goto err_driver; - } - - return 0; - -err_driver: - i2c_del_driver(&wm8990_i2c_driver); - return -ENODEV; -} #endif -static int wm8990_probe(struct platform_device *pdev) +static int __init wm8990_modinit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct wm8990_setup_data *setup; - struct snd_soc_codec *codec; - struct wm8990_priv *wm8990; - int ret; - - setup = socdev->codec_data; - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) - return -ENOMEM; - - wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); - if (wm8990 == NULL) { - kfree(codec); - return -ENOMEM; - } - - snd_soc_codec_set_drvdata(codec, wm8990); - socdev->card->codec = codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - wm8990_socdev = socdev; - - ret = -ENODEV; - + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - if (setup->i2c_address) { - codec->hw_write = (hw_write_t)i2c_master_send; - ret = wm8990_add_i2c_device(pdev, setup); - } -#endif - + ret = i2c_add_driver(&wm8990_i2c_driver); if (ret != 0) { - kfree(snd_soc_codec_get_drvdata(codec)); - kfree(codec); + printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n", + ret); } +#endif return ret; } +module_init(wm8990_modinit); -/* power down chip */ -static int wm8990_remove(struct platform_device *pdev) +static void __exit wm8990_exit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->control_data) - wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_unregister_device(codec->control_data); i2c_del_driver(&wm8990_i2c_driver); #endif - kfree(snd_soc_codec_get_drvdata(codec)); - kfree(codec); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8990 = { - .probe = wm8990_probe, - .remove = wm8990_remove, - .suspend = wm8990_suspend, - .resume = wm8990_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990); - -static int __init wm8990_modinit(void) -{ - return snd_soc_register_dai(&wm8990_dai); -} -module_init(wm8990_modinit); - -static void __exit wm8990_exit(void) -{ - snd_soc_unregister_dai(&wm8990_dai); } module_exit(wm8990_exit); diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h index 7114ddc88b4b..77c98a4bfe9c 100644 --- a/sound/soc/codecs/wm8990.h +++ b/sound/soc/codecs/wm8990.h @@ -826,18 +826,10 @@ #define WM8990_INMIXR_PWR_BIT 2 #define WM8990_AINRMUX_PWR_BIT 3 -struct wm8990_setup_data { - unsigned i2c_bus; - unsigned short i2c_address; -}; - #define WM8990_MCLK_DIV 0 #define WM8990_DACCLK_DIV 1 #define WM8990_ADCCLK_DIV 2 #define WM8990_BCLK_DIV 3 -extern struct snd_soc_dai wm8990_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8990; - #endif /* __WM8990REGISTERDEFS_H__ */ /*------------------------------ END OF FILE ---------------------------------*/ diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index d8d300c6175f..1d9e1837a2df 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -229,7 +229,8 @@ struct wm8993_priv { u16 reg_cache[WM8993_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; struct wm8993_platform_data pdata; - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; int master; int sysclk_source; int tdm_slots; @@ -367,10 +368,9 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, return 0; } -static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, +static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source, unsigned int Fref, unsigned int Fout) { - struct snd_soc_codec *codec = dai->codec; struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); u16 reg1, reg4, reg5; struct _fll_div fll_div; @@ -456,6 +456,12 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, return 0; } +static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, + unsigned int Fref, unsigned int Fout) +{ + return _wm8993_set_fll(dai->codec, fll_id, source, Fref, Fout); +} + static int configure_clock(struct snd_soc_codec *codec) { struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); @@ -1394,8 +1400,8 @@ static struct snd_soc_dai_ops wm8993_ops = { SNDRV_PCM_FMTBIT_S24_LE |\ SNDRV_PCM_FMTBIT_S32_LE) -struct snd_soc_dai wm8993_dai = { - .name = "WM8993", +static struct snd_soc_dai_driver wm8993_dai = { + .name = "wm8993-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, @@ -1413,32 +1419,82 @@ struct snd_soc_dai wm8993_dai = { .ops = &wm8993_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(wm8993_dai); - -static struct snd_soc_codec *wm8993_codec; -static int wm8993_probe(struct platform_device *pdev) +static int wm8993_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct wm8993_priv *wm8993; - int ret = 0; + struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); + int ret, i, val; + + codec->control_data = wm8993->control_data; + wm8993->hubs_data.hp_startup_mode = 1; + wm8993->hubs_data.dcs_codes = -2; + + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); + if (ret != 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) + wm8993->supplies[i].supply = wm8993_supply_names[i]; - if (!wm8993_codec) { - dev_err(&pdev->dev, "I2C device not yet probed\n"); - goto err; + ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies), + wm8993->supplies); + if (ret != 0) { + dev_err(codec->dev, "Failed to request supplies: %d\n", ret); + return ret; } - socdev->card->codec = wm8993_codec; - codec = wm8993_codec; - wm8993 = snd_soc_codec_get_drvdata(codec); + ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), + wm8993->supplies); + if (ret != 0) { + dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); + goto err_get; + } - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms\n"); - goto err; + val = snd_soc_read(codec, WM8993_SOFTWARE_RESET); + if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { + dev_err(codec->dev, "Invalid ID register value %x\n", val); + ret = -EINVAL; + goto err_enable; } + ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff); + if (ret != 0) + goto err_enable; + + codec->cache_only = 1; + + /* By default we're using the output mixers */ + wm8993->class_w_users = 2; + + /* Latch volume update bits and default ZC on */ + snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, + WM8993_DAC_VU, WM8993_DAC_VU); + snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, + WM8993_ADC_VU, WM8993_ADC_VU); + + /* Manualy manage the HPOUT sequencing for independent stereo + * control. */ + snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, + WM8993_HPOUT1_AUTO_PU, 0); + + /* Use automatic clock configuration */ + snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); + + wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, + wm8993->pdata.lineout2_diff, + wm8993->pdata.lineout1fb, + wm8993->pdata.lineout2fb, + wm8993->pdata.jd_scthr, + wm8993->pdata.jd_thr, + wm8993->pdata.micbias1_lvl, + wm8993->pdata.micbias2_lvl); + + ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + if (ret != 0) + goto err_enable; + snd_soc_add_controls(codec, wm8993_snd_controls, ARRAY_SIZE(wm8993_snd_controls)); if (wm8993->pdata.num_retune_configs != 0) { @@ -1457,36 +1513,36 @@ static int wm8993_probe(struct platform_device *pdev) wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, wm8993->pdata.lineout2_diff); - return ret; + return 0; -err: +err_enable: + regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); +err_get: + regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); return ret; } -static int wm8993_remove(struct platform_device *pdev) +static int wm8993_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); + struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); + wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); + regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); return 0; } #ifdef CONFIG_PM -static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8993_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); int fll_fout = wm8993->fll_fout; int fll_fref = wm8993->fll_fref; int ret; /* Stop the FLL in an orderly fashion */ - ret = wm8993_set_fll(codec->dai, 0, 0, 0, 0); + ret = _wm8993_set_fll(codec, 0, 0, 0, 0); if (ret != 0) { - dev_err(&pdev->dev, "Failed to stop FLL\n"); + dev_err(codec->dev, "Failed to stop FLL\n"); return ret; } @@ -1498,10 +1554,8 @@ static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int wm8993_resume(struct platform_device *pdev) +static int wm8993_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); int ret; @@ -1515,7 +1569,7 @@ static int wm8993_resume(struct platform_device *pdev) wm8993->fll_fref = 0; wm8993->fll_fout = 0; - ret = wm8993_set_fll(codec->dai, 0, wm8993->fll_src, + ret = _wm8993_set_fll(codec, 0, wm8993->fll_src, fll_fref, fll_fout); if (ret != 0) dev_err(codec->dev, "Failed to restart FLL\n"); @@ -1528,162 +1582,43 @@ static int wm8993_resume(struct platform_device *pdev) #define wm8993_resume NULL #endif -struct snd_soc_codec_device soc_codec_dev_wm8993 = { +static struct snd_soc_codec_driver soc_codec_dev_wm8993 = { .probe = wm8993_probe, .remove = wm8993_remove, .suspend = wm8993_suspend, .resume = wm8993_resume, + .set_bias_level = wm8993_set_bias_level, + .reg_cache_size = sizeof(wm8993_reg_defaults), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8993_reg_defaults, + .volatile_register = wm8993_volatile, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993); -static int wm8993_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { struct wm8993_priv *wm8993; - struct snd_soc_codec *codec; - unsigned int val; int ret; - int i; - - if (wm8993_codec) { - dev_err(&i2c->dev, "A WM8993 is already registered\n"); - return -EINVAL; - } wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL); if (wm8993 == NULL) return -ENOMEM; - codec = &wm8993->codec; - if (i2c->dev.platform_data) - memcpy(&wm8993->pdata, i2c->dev.platform_data, - sizeof(wm8993->pdata)); - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "WM8993"; - codec->volatile_register = wm8993_volatile; - codec->reg_cache = wm8993->reg_cache; - codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache); - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8993_set_bias_level; - codec->dai = &wm8993_dai; - codec->num_dai = 1; - snd_soc_codec_set_drvdata(codec, wm8993); - - wm8993->hubs_data.hp_startup_mode = 1; - wm8993->hubs_data.dcs_codes = -2; - - memcpy(wm8993->reg_cache, wm8993_reg_defaults, - sizeof(wm8993->reg_cache)); - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - i2c_set_clientdata(i2c, wm8993); - codec->control_data = i2c; - wm8993_codec = codec; - - codec->dev = &i2c->dev; - - for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) - wm8993->supplies[i].supply = wm8993_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies), - wm8993->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), - wm8993->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - val = snd_soc_read(codec, WM8993_SOFTWARE_RESET); - if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { - dev_err(codec->dev, "Invalid ID register value %x\n", val); - ret = -EINVAL; - goto err_enable; - } - - ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff); - if (ret != 0) - goto err_enable; - - codec->cache_only = 1; - - /* By default we're using the output mixers */ - wm8993->class_w_users = 2; - - /* Latch volume update bits and default ZC on */ - snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, - WM8993_DAC_VU, WM8993_DAC_VU); - snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, - WM8993_ADC_VU, WM8993_ADC_VU); + wm8993->control_data = i2c; - /* Manualy manage the HPOUT sequencing for independent stereo - * control. */ - snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, - WM8993_HPOUT1_AUTO_PU, 0); - - /* Use automatic clock configuration */ - snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); - - wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, - wm8993->pdata.lineout2_diff, - wm8993->pdata.lineout1fb, - wm8993->pdata.lineout2fb, - wm8993->pdata.jd_scthr, - wm8993->pdata.jd_thr, - wm8993->pdata.micbias1_lvl, - wm8993->pdata.micbias2_lvl); - - ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - if (ret != 0) - goto err_enable; - - wm8993_dai.dev = codec->dev; - - ret = snd_soc_register_dai(&wm8993_dai); - if (ret != 0) - goto err_bias; - - ret = snd_soc_register_codec(codec); - - return 0; - -err_bias: - wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); -err: - wm8993_codec = NULL; - kfree(wm8993); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8993, &wm8993_dai, 1); + if (ret < 0) + kfree(wm8993); return ret; } -static int wm8993_i2c_remove(struct i2c_client *client) +static __devexit int wm8993_i2c_remove(struct i2c_client *client) { - struct wm8993_priv *wm8993 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&wm8993->codec); - snd_soc_unregister_dai(&wm8993_dai); - - wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); - kfree(wm8993); - + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -1695,30 +1630,34 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id); static struct i2c_driver wm8993_i2c_driver = { .driver = { - .name = "WM8993", + .name = "wm8993-codec", .owner = THIS_MODULE, }, - .probe = wm8993_i2c_probe, - .remove = wm8993_i2c_remove, + .probe = wm8993_i2c_probe, + .remove = __devexit_p(wm8993_i2c_remove), .id_table = wm8993_i2c_id, }; - +#endif static int __init wm8993_modinit(void) { - int ret; - + int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8993_i2c_driver); - if (ret != 0) - pr_err("WM8993: Unable to register I2C driver: %d\n", ret); - + if (ret != 0) { + pr_err("WM8993: Unable to register I2C driver: %d\n", + ret); + } +#endif return ret; } module_init(wm8993_modinit); static void __exit wm8993_exit(void) { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8993_i2c_driver); +#endif } module_exit(wm8993_exit); diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h index 30e71ca88dad..2184617b9611 100644 --- a/sound/soc/codecs/wm8993.h +++ b/sound/soc/codecs/wm8993.h @@ -1,9 +1,6 @@ #ifndef WM8993_H #define WM8993_H -extern struct snd_soc_dai wm8993_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8993; - #define WM8993_SYSCLK_MCLK 1 #define WM8993_SYSCLK_FLL 2 diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index a87046a96f2a..7823f92413f3 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -36,9 +36,6 @@ #include "wm8994.h" #include "wm_hubs.h" -static struct snd_soc_codec *wm8994_codec; -struct snd_soc_codec_device soc_codec_dev_wm8994; - struct fll_config { int src; int in; @@ -71,7 +68,9 @@ struct wm8994_micdet { /* codec private data */ struct wm8994_priv { struct wm_hubs_data hubs; - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; + struct snd_soc_codec *codec; u16 reg_cache[WM8994_REG_CACHE_SIZE + 1]; int sysclk[2]; int sysclk_rate[2]; @@ -1901,8 +1900,6 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, return snd_soc_put_volsw(kcontrol, ucontrol); } - - static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); @@ -1941,7 +1938,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); struct wm8994_pdata *pdata = wm8994->pdata; int drc = wm8994_get_drc(kcontrol->id.name); int value = ucontrol->value.integer.value[0]; @@ -2044,7 +2041,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); struct wm8994_pdata *pdata = wm8994->pdata; int block = wm8994_get_retune_mobile_block(kcontrol->id.name); int value = ucontrol->value.integer.value[0]; @@ -2066,7 +2063,7 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec); int block = wm8994_get_retune_mobile_block(kcontrol->id.name); ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; @@ -2880,10 +2877,9 @@ static int wm8994_get_fll_config(struct fll_div *fll, return 0; } -static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, +static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, unsigned int freq_in, unsigned int freq_out) { - struct snd_soc_codec *codec = dai->codec; struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); int reg_offset, ret; struct fll_div fll; @@ -2994,8 +2990,15 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, return 0; } + static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; +static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, + unsigned int freq_in, unsigned int freq_out) +{ + return _wm8994_set_fll(dai->codec, id, src, freq_in, freq_out); +} + static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { @@ -3507,10 +3510,9 @@ static struct snd_soc_dai_ops wm8994_aif3_dai_ops = { .set_tristate = wm8994_set_tristate, }; -struct snd_soc_dai wm8994_dai[] = { +static struct snd_soc_dai_driver wm8994_dai[] = { { - .name = "WM8994 AIF1", - .id = 1, + .name = "wm8994-aif1", .playback = { .stream_name = "AIF1 Playback", .channels_min = 2, @@ -3528,8 +3530,7 @@ struct snd_soc_dai wm8994_dai[] = { .ops = &wm8994_aif1_dai_ops, }, { - .name = "WM8994 AIF2", - .id = 2, + .name = "wm8994-aif2", .playback = { .stream_name = "AIF2 Playback", .channels_min = 2, @@ -3547,8 +3548,7 @@ struct snd_soc_dai wm8994_dai[] = { .ops = &wm8994_aif2_dai_ops, }, { - .name = "WM8994 AIF3", - .id = 3, + .name = "wm8994-aif3", .playback = { .stream_name = "AIF3 Playback", .channels_min = 2, @@ -3566,20 +3566,17 @@ struct snd_soc_dai wm8994_dai[] = { .ops = &wm8994_aif3_dai_ops, } }; -EXPORT_SYMBOL_GPL(wm8994_dai); #ifdef CONFIG_PM -static int wm8994_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); int i, ret; for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], sizeof(struct fll_config)); - ret = wm8994_set_fll(&codec->dai[0], i + 1, 0, 0, 0); + ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0); if (ret < 0) dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", i + 1, ret); @@ -3590,10 +3587,8 @@ static int wm8994_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int wm8994_resume(struct platform_device *pdev) +static int wm8994_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache; int i, ret; @@ -3622,7 +3617,7 @@ static int wm8994_resume(struct platform_device *pdev) if (!wm8994->fll_suspend[i].out) continue; - ret = wm8994_set_fll(&codec->dai[0], i + 1, + ret = _wm8994_set_fll(codec, i + 1, wm8994->fll_suspend[i].src, wm8994->fll_suspend[i].in, wm8994->fll_suspend[i].out); @@ -3640,7 +3635,7 @@ static int wm8994_resume(struct platform_device *pdev) static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) { - struct snd_soc_codec *codec = &wm8994->codec; + struct snd_soc_codec *codec = wm8994->codec; struct wm8994_pdata *pdata = wm8994->pdata; struct snd_kcontrol_new controls[] = { SOC_ENUM_EXT("AIF1.1 EQ Mode", @@ -3698,16 +3693,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; - ret = snd_soc_add_controls(&wm8994->codec, controls, + ret = snd_soc_add_controls(wm8994->codec, controls, ARRAY_SIZE(controls)); if (ret != 0) - dev_err(wm8994->codec.dev, + dev_err(wm8994->codec->dev, "Failed to add ReTune Mobile controls: %d\n", ret); } static void wm8994_handle_pdata(struct wm8994_priv *wm8994) { - struct snd_soc_codec *codec = &wm8994->codec; + struct snd_soc_codec *codec = wm8994->codec; struct wm8994_pdata *pdata = wm8994->pdata; int ret, i; @@ -3739,7 +3734,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) wm8994->drc_texts = kmalloc(sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); if (!wm8994->drc_texts) { - dev_err(wm8994->codec.dev, + dev_err(wm8994->codec->dev, "Failed to allocate %d DRC config texts\n", pdata->num_drc_cfgs); return; @@ -3751,10 +3746,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) wm8994->drc_enum.max = pdata->num_drc_cfgs; wm8994->drc_enum.texts = wm8994->drc_texts; - ret = snd_soc_add_controls(&wm8994->codec, controls, + ret = snd_soc_add_controls(wm8994->codec, controls, ARRAY_SIZE(controls)); if (ret != 0) - dev_err(wm8994->codec.dev, + dev_err(wm8994->codec->dev, "Failed to add DRC mode controls: %d\n", ret); for (i = 0; i < WM8994_NUM_DRC; i++) @@ -3767,62 +3762,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) if (pdata->num_retune_mobile_cfgs) wm8994_handle_retune_mobile_pdata(wm8994); else - snd_soc_add_controls(&wm8994->codec, wm8994_eq_controls, + snd_soc_add_controls(wm8994->codec, wm8994_eq_controls, ARRAY_SIZE(wm8994_eq_controls)); } -static int wm8994_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8994_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8994_codec; - codec = wm8994_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - return ret; - } - - wm8994_handle_pdata(snd_soc_codec_get_drvdata(codec)); - - wm_hubs_add_analogue_controls(codec); - snd_soc_add_controls(codec, wm8994_snd_controls, - ARRAY_SIZE(wm8994_snd_controls)); - snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets, - ARRAY_SIZE(wm8994_dapm_widgets)); - wm_hubs_add_analogue_routes(codec, 0, 0); - snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); - - return 0; -} - -static int wm8994_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8994 = { - .probe = wm8994_probe, - .remove = wm8994_remove, - .suspend = wm8994_suspend, - .resume = wm8994_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994); - /** * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ * @@ -3881,7 +3824,7 @@ EXPORT_SYMBOL_GPL(wm8994_mic_detect); static irqreturn_t wm8994_mic_irq(int irq, void *data) { struct wm8994_priv *priv = data; - struct snd_soc_codec *codec = &priv->codec; + struct snd_soc_codec *codec = priv->codec; int reg; int report; @@ -3913,47 +3856,20 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) return IRQ_HANDLED; } -static int wm8994_codec_probe(struct platform_device *pdev) +static int wm8994_codec_probe(struct snd_soc_codec *codec) { - int ret; struct wm8994_priv *wm8994; - struct snd_soc_codec *codec; - int i; - u16 rev; + int ret, i, rev; - if (wm8994_codec) { - dev_err(&pdev->dev, "Another WM8994 is registered\n"); - return -EINVAL; - } + codec->control_data = dev_get_drvdata(codec->dev->parent); wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); - if (!wm8994) { - dev_err(&pdev->dev, "Failed to allocate private data\n"); + if (wm8994 == NULL) return -ENOMEM; - } - - codec = &wm8994->codec; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - snd_soc_codec_set_drvdata(codec, wm8994); - codec->control_data = dev_get_drvdata(pdev->dev.parent); - codec->name = "WM8994"; - codec->owner = THIS_MODULE; - codec->read = wm8994_read; - codec->write = wm8994_write; - codec->readable_register = wm8994_readable; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8994_set_bias_level; - codec->dai = &wm8994_dai[0]; - codec->num_dai = 3; - codec->reg_cache_size = WM8994_MAX_REGISTER; - codec->reg_cache = &wm8994->reg_cache; - codec->dev = &pdev->dev; - - wm8994->pdata = pdev->dev.parent->platform_data; + + wm8994->pdata = dev_get_platdata(codec->dev->parent); + wm8994->codec = codec; /* Fill the cache with physical values we inherited; don't reset */ ret = wm8994_bulk_read(codec->control_data, 0, @@ -3989,25 +3905,25 @@ static int wm8994_codec_probe(struct platform_device *pdev) ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994_mic_irq, "Mic 1 detect", wm8994); if (ret != 0) - dev_warn(&pdev->dev, + dev_warn(codec->dev, "Failed to request Mic1 detect IRQ: %d\n", ret); ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994_mic_irq, "Mic 1 short", wm8994); if (ret != 0) - dev_warn(&pdev->dev, + dev_warn(codec->dev, "Failed to request Mic1 short IRQ: %d\n", ret); ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994_mic_irq, "Mic 2 detect", wm8994); if (ret != 0) - dev_warn(&pdev->dev, + dev_warn(codec->dev, "Failed to request Mic2 detect IRQ: %d\n", ret); ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994_mic_irq, "Mic 2 short", wm8994); if (ret != 0) - dev_warn(&pdev->dev, + dev_warn(codec->dev, "Failed to request Mic2 short IRQ: %d\n", ret); /* Remember if AIFnLRCLK is configured as a GPIO. This should be @@ -4038,13 +3954,8 @@ static int wm8994_codec_probe(struct platform_device *pdev) wm8994->lrclk_shared[1] = 0; } - for (i = 0; i < ARRAY_SIZE(wm8994_dai); i++) - wm8994_dai[i].dev = codec->dev; - wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm8994_codec = codec; - /* Latch volume updates (right only; we always do left then right). */ snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); @@ -4081,24 +3992,18 @@ static int wm8994_codec_probe(struct platform_device *pdev) wm8994_update_class_w(codec); - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_irq; - } - - ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); - goto err_codec; - } + wm8994_handle_pdata(wm8994); - platform_set_drvdata(pdev, wm8994); + wm_hubs_add_analogue_controls(codec); + snd_soc_add_controls(codec, wm8994_snd_controls, + ARRAY_SIZE(wm8994_snd_controls)); + snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets, + ARRAY_SIZE(wm8994_dapm_widgets)); + wm_hubs_add_analogue_routes(codec, 0, 0); + snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); return 0; -err_codec: - snd_soc_unregister_codec(codec); err_irq: wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); @@ -4109,31 +4014,50 @@ err: return ret; } -static int __devexit wm8994_codec_remove(struct platform_device *pdev) +static int wm8994_codec_remove(struct snd_soc_codec *codec) { - struct wm8994_priv *wm8994 = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = &wm8994->codec; + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); - snd_soc_unregister_codec(&wm8994->codec); + wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); kfree(wm8994); - wm8994_codec = NULL; return 0; } +static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { + .probe = wm8994_codec_probe, + .remove = wm8994_codec_remove, + .suspend = wm8994_suspend, + .resume = wm8994_resume, + .read = wm8994_read, + .write = wm8994_write, + .set_bias_level = wm8994_set_bias_level, +}; + +static int __devinit wm8994_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994, + wm8994_dai, ARRAY_SIZE(wm8994_dai)); +} + +static int __devexit wm8994_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + static struct platform_driver wm8994_codec_driver = { .driver = { .name = "wm8994-codec", .owner = THIS_MODULE, }, - .probe = wm8994_codec_probe, - .remove = __devexit_p(wm8994_codec_remove), + .probe = wm8994_probe, + .remove = __devexit_p(wm8994_remove), }; static __init int wm8994_init(void) diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 2e0ca67a8df7..d8dce260c430 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -11,9 +11,6 @@ #include -extern struct snd_soc_codec_device soc_codec_dev_wm8994; -extern struct snd_soc_dai wm8994_dai[]; - /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ #define WM8994_SYSCLK_MCLK1 1 #define WM8994_SYSCLK_MCLK2 2 diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 76b37ff6c264..00249d5b6793 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -156,7 +156,8 @@ static struct { }; struct wm9081_priv { - struct snd_soc_codec codec; + enum snd_soc_control_type control_type; + void *control_data; u16 reg_cache[WM9081_MAX_REGISTER + 1]; int sysclk_source; int mclk_rate; @@ -1212,8 +1213,8 @@ static struct snd_soc_dai_ops wm9081_dai_ops = { /* We report two channels because the CODEC processes a stereo signal, even * though it is only capable of handling a mono output. */ -struct snd_soc_dai wm9081_dai = { - .name = "WM9081", +static struct snd_soc_dai_driver wm9081_dai = { + .name = "wm9081-hifi", .playback = { .stream_name = "HiFi Playback", .channels_min = 1, @@ -1223,34 +1224,42 @@ struct snd_soc_dai wm9081_dai = { }, .ops = &wm9081_dai_ops, }; -EXPORT_SYMBOL_GPL(wm9081_dai); - -static struct snd_soc_codec *wm9081_codec; - -static int wm9081_probe(struct platform_device *pdev) +static int wm9081_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct wm9081_priv *wm9081; - int ret = 0; + struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); + int ret; + u16 reg; - if (wm9081_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; + codec->control_data = wm9081->control_data; + ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type); + if (ret != 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; } - socdev->card->codec = wm9081_codec; - codec = wm9081_codec; - wm9081 = snd_soc_codec_get_drvdata(codec); + reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET); + if (reg != 0x9081) { + dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg); + ret = -EINVAL; + return ret; + } - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + ret = wm9081_reset(codec); if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; + dev_err(codec->dev, "Failed to issue reset\n"); + return ret; } + wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + /* Enable zero cross by default */ + reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT); + snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC); + reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA); + snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, + reg | WM9081_SPKPGAZC); + snd_soc_add_controls(codec, wm9081_snd_controls, ARRAY_SIZE(wm9081_snd_controls)); if (!wm9081->retune) { @@ -1265,40 +1274,28 @@ static int wm9081_probe(struct platform_device *pdev) snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); return ret; - -pcm_err: - return ret; } -static int wm9081_remove(struct platform_device *pdev) +static int wm9081_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - + wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } #ifdef CONFIG_PM -static int wm9081_suspend(struct platform_device *pdev, pm_message_t state) +static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm9081_resume(struct platform_device *pdev) +static int wm9081_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; u16 *reg_cache = codec->reg_cache; int i; - for (i = 0; i < codec->reg_cache_size; i++) { + for (i = 0; i < codec->driver->reg_cache_size; i++) { if (i == WM9081_SOFTWARE_RESET) continue; @@ -1314,133 +1311,43 @@ static int wm9081_resume(struct platform_device *pdev) #define wm9081_resume NULL #endif -struct snd_soc_codec_device soc_codec_dev_wm9081 = { +static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { .probe = wm9081_probe, .remove = wm9081_remove, .suspend = wm9081_suspend, .resume = wm9081_resume, + .set_bias_level = wm9081_set_bias_level, + .reg_cache_size = sizeof(wm9081_reg_defaults), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm9081_reg_defaults, + .volatile_register = wm9081_volatile_register, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081); - -static int wm9081_register(struct wm9081_priv *wm9081, - enum snd_soc_control_type control) -{ - struct snd_soc_codec *codec = &wm9081->codec; - int ret; - u16 reg; - - if (wm9081_codec) { - dev_err(codec->dev, "Another WM9081 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm9081); - codec->name = "WM9081"; - codec->owner = THIS_MODULE; - codec->dai = &wm9081_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache); - codec->reg_cache = &wm9081->reg_cache; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm9081_set_bias_level; - codec->volatile_register = wm9081_volatile_register; - - memcpy(codec->reg_cache, wm9081_reg_defaults, - sizeof(wm9081_reg_defaults)); - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET); - if (reg != 0x9081) { - dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg); - ret = -EINVAL; - goto err; - } - - ret = wm9081_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err; - } - - wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Enable zero cross by default */ - reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT); - snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC); - reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA); - snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, - reg | WM9081_SPKPGAZC); - - wm9081_dai.dev = codec->dev; - - wm9081_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&wm9081_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm9081); - return ret; -} - -static void wm9081_unregister(struct wm9081_priv *wm9081) -{ - wm9081_set_bias_level(&wm9081->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm9081_dai); - snd_soc_unregister_codec(&wm9081->codec); - kfree(wm9081); - wm9081_codec = NULL; -} +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm9081_priv *wm9081; - struct snd_soc_codec *codec; + int ret; wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL); if (wm9081 == NULL) return -ENOMEM; - codec = &wm9081->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - wm9081->retune = i2c->dev.platform_data; - i2c_set_clientdata(i2c, wm9081); - codec->control_data = i2c; - - codec->dev = &i2c->dev; + wm9081->control_data = i2c; - return wm9081_register(wm9081, SND_SOC_I2C); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm9081, &wm9081_dai, 1); + if (ret < 0) + kfree(wm9081); + return ret; } static __devexit int wm9081_i2c_remove(struct i2c_client *client) { - struct wm9081_priv *wm9081 = i2c_get_clientdata(client); - wm9081_unregister(wm9081); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } @@ -1452,31 +1359,34 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id); static struct i2c_driver wm9081_i2c_driver = { .driver = { - .name = "wm9081", + .name = "wm9081-codec", .owner = THIS_MODULE, }, .probe = wm9081_i2c_probe, .remove = __devexit_p(wm9081_i2c_remove), .id_table = wm9081_i2c_id, }; +#endif static int __init wm9081_modinit(void) { - int ret; - + int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm9081_i2c_driver); if (ret != 0) { printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n", ret); } - +#endif return ret; } module_init(wm9081_modinit); static void __exit wm9081_exit(void) { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm9081_i2c_driver); +#endif } module_exit(wm9081_exit); diff --git a/sound/soc/codecs/wm9081.h b/sound/soc/codecs/wm9081.h index 42d3bc757021..871cccb066dc 100644 --- a/sound/soc/codecs/wm9081.h +++ b/sound/soc/codecs/wm9081.h @@ -15,9 +15,6 @@ #include -extern struct snd_soc_dai wm9081_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm9081; - /* * SYSCLK sources */ diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 1592250daec0..7a1825418ee4 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -34,8 +34,6 @@ #include "wm9090.h" -static struct snd_soc_codec *wm9090_codec; - static const u16 wm9090_reg_defaults[] = { 0x9093, /* R0 - Software Reset */ 0x0006, /* R1 - Power Management (1) */ @@ -142,15 +140,10 @@ static const u16 wm9090_reg_defaults[] = { /* This struct is used to save the context */ struct wm9090_priv { - /* We're not really registering as a CODEC since ASoC core - * does not yet support multiple CODECs but having the CODEC - * structure means we can reuse some of the ASoC core - * features. - */ - struct snd_soc_codec codec; struct mutex mutex; u16 reg_cache[WM9090_MAX_REGISTER + 1]; struct wm9090_platform_data pdata; + void *control_data; }; static int wm9090_volatile(unsigned int reg) @@ -523,7 +516,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Restore the register cache */ - for (i = 1; i < codec->reg_cache_size; i++) { + for (i = 1; i < codec->driver->reg_cache_size; i++) { if (reg_cache[i] == wm9090_reg_defaults[i]) continue; if (wm9090_volatile(i)) @@ -556,51 +549,67 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, return 0; } -static int wm9090_probe(struct platform_device *pdev) +static int wm9090_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; + struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); + int ret; - if (wm9090_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; + codec->control_data = wm9090->control_data; + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); + if (ret != 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; } - socdev->card->codec = wm9090_codec; - codec = wm9090_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; + ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET); + if (ret < 0) + return ret; + if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) { + dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret); + return -EINVAL; } + ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0); + if (ret < 0) + return ret; + + /* Configure some defaults; they will be written out when we + * bring the bias up. + */ + wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU + | WM9090_IN1A_ZC; + wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU + | WM9090_IN1B_ZC; + wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU + | WM9090_IN2A_ZC; + wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU + | WM9090_IN2B_ZC; + wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= + WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; + wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= + WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; + wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= + WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; + + wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; + + wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + wm9090_add_controls(codec); return 0; - -pcm_err: - return ret; } #ifdef CONFIG_PM -static int wm9090_suspend(struct platform_device *pdev, pm_message_t state) +static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm9090_resume(struct platform_device *pdev) +static int wm9090_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; @@ -610,29 +619,29 @@ static int wm9090_resume(struct platform_device *pdev) #define wm9090_resume NULL #endif -static int wm9090_remove(struct platform_device *pdev) +static int wm9090_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); + wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -struct snd_soc_codec_device soc_codec_dev_wm9090 = { +static struct snd_soc_codec_driver soc_codec_dev_wm9090 = { .probe = wm9090_probe, .remove = wm9090_remove, .suspend = wm9090_suspend, .resume = wm9090_resume, + .set_bias_level = wm9090_set_bias_level, + .reg_cache_size = (WM9090_MAX_REGISTER + 1), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm9090_reg_defaults, + .volatile_register = wm9090_volatile, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm9090); static int wm9090_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm9090_priv *wm9090; - struct snd_soc_codec *codec; int ret; wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL); @@ -640,102 +649,28 @@ static int wm9090_i2c_probe(struct i2c_client *i2c, dev_err(&i2c->dev, "Can not allocate memory\n"); return -ENOMEM; } - codec = &wm9090->codec; if (i2c->dev.platform_data) memcpy(&wm9090->pdata, i2c->dev.platform_data, sizeof(wm9090->pdata)); - wm9090_codec = codec; - i2c_set_clientdata(i2c, wm9090); + wm9090->control_data = i2c; + mutex_init(&wm9090->mutex); - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->control_data = i2c; - snd_soc_codec_set_drvdata(codec, wm9090); - codec->dev = &i2c->dev; - codec->name = "WM9090"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm9090_set_bias_level, - codec->reg_cache_size = WM9090_MAX_REGISTER + 1; - codec->reg_cache = &wm9090->reg_cache; - codec->volatile_register = wm9090_volatile; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - memcpy(&wm9090->reg_cache, wm9090_reg_defaults, - sizeof(wm9090->reg_cache)); - - ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET); - if (ret < 0) - goto err; - if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) { - dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", ret); - ret = -EINVAL; - goto err; - } - - ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0); + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm9090, NULL, 0); if (ret < 0) - goto err; - - /* Configure some defaults; they will be written out when we - * bring the bias up. - */ - wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU - | WM9090_IN1A_ZC; - wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU - | WM9090_IN1B_ZC; - wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU - | WM9090_IN2A_ZC; - wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU - | WM9090_IN2B_ZC; - wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= - WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; - wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= - WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; - wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= - WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; - - wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; - - wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); - goto err_bias; - } - - return 0; - -err_bias: - wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); -err: - kfree(wm9090); - i2c_set_clientdata(i2c, NULL); - wm9090_codec = NULL; - + kfree(wm9090); return ret; } static int wm9090_i2c_remove(struct i2c_client *i2c) { struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c); - struct snd_soc_codec *codec = &wm9090->codec; - snd_soc_unregister_codec(codec); - wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); + snd_soc_unregister_codec(&i2c->dev); kfree(wm9090); - wm9090_codec = NULL; return 0; } @@ -748,7 +683,7 @@ MODULE_DEVICE_TABLE(i2c, wm9090_id); static struct i2c_driver wm9090_i2c_driver = { .driver = { - .name = "wm9090", + .name = "wm9090-codec", .owner = THIS_MODULE, }, .probe = wm9090_i2c_probe, diff --git a/sound/soc/codecs/wm9090.h b/sound/soc/codecs/wm9090.h index b08eab932a5b..29b9d9fc70b4 100644 --- a/sound/soc/codecs/wm9090.h +++ b/sound/soc/codecs/wm9090.h @@ -23,8 +23,6 @@ #ifndef __WM9090_H #define __WM9090_H -extern struct snd_soc_codec_device soc_codec_dev_wm9090; - /* * Register values. */ diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 8793341849d1..e4d8f5339c51 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -248,8 +248,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; int reg; u16 vra; @@ -273,9 +272,9 @@ static struct snd_soc_dai_ops wm9705_dai_ops = { .prepare = ac97_prepare, }; -struct snd_soc_dai wm9705_dai[] = { +static struct snd_soc_dai_driver wm9705_dai[] = { { - .name = "AC97 HiFi", + .name = "wm9705-hifi", .ac97_control = 1, .playback = { .stream_name = "HiFi Playback", @@ -294,7 +293,7 @@ struct snd_soc_dai wm9705_dai[] = { .ops = &wm9705_dai_ops, }, { - .name = "AC97 Aux", + .name = "wm9705-aux", .playback = { .stream_name = "Aux Playback", .channels_min = 1, @@ -304,7 +303,6 @@ struct snd_soc_dai wm9705_dai[] = { }, } }; -EXPORT_SYMBOL_GPL(wm9705_dai); static int wm9705_reset(struct snd_soc_codec *codec) { @@ -318,20 +316,15 @@ static int wm9705_reset(struct snd_soc_codec *codec) } #ifdef CONFIG_PM -static int wm9705_soc_suspend(struct platform_device *pdev, pm_message_t msg) +static int wm9705_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff); return 0; } -static int wm9705_soc_resume(struct platform_device *pdev) +static int wm9705_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i, ret; u16 *cache = codec->reg_cache; @@ -352,49 +345,18 @@ static int wm9705_soc_resume(struct platform_device *pdev) #define wm9705_soc_resume NULL #endif -static int wm9705_soc_probe(struct platform_device *pdev) +static int wm9705_soc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; int ret = 0; printk(KERN_INFO "WM9705 SoC Audio Codec\n"); - socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), - GFP_KERNEL); - if (socdev->card->codec == NULL) - return -ENOMEM; - codec = socdev->card->codec; - mutex_init(&codec->mutex); - - codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL); - if (codec->reg_cache == NULL) { - ret = -ENOMEM; - goto cache_err; - } - codec->reg_cache_size = sizeof(wm9705_reg); - codec->reg_cache_step = 2; - - codec->name = "WM9705"; - codec->owner = THIS_MODULE; - codec->dai = wm9705_dai; - codec->num_dai = ARRAY_SIZE(wm9705_dai); - codec->write = ac97_write; - codec->read = ac97_read; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); - goto codec_err; + return ret; } - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) - goto pcm_err; - ret = wm9705_reset(codec); if (ret) goto reset_err; @@ -406,40 +368,62 @@ static int wm9705_soc_probe(struct platform_device *pdev) return 0; reset_err: - snd_soc_free_pcms(socdev); -pcm_err: snd_soc_free_ac97_codec(codec); -codec_err: - kfree(codec->reg_cache); -cache_err: - kfree(socdev->card->codec); - socdev->card->codec = NULL; return ret; } -static int wm9705_soc_remove(struct platform_device *pdev) +static int wm9705_soc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec == NULL) - return 0; - - snd_soc_dapm_free(socdev); - snd_soc_free_pcms(socdev); snd_soc_free_ac97_codec(codec); - kfree(codec->reg_cache); - kfree(codec); return 0; } -struct snd_soc_codec_device soc_codec_dev_wm9705 = { +static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { .probe = wm9705_soc_probe, .remove = wm9705_soc_remove, .suspend = wm9705_soc_suspend, .resume = wm9705_soc_resume, + .read = ac97_read, + .write = ac97_write, + .reg_cache_size = sizeof(wm9705_reg), + .reg_word_size = sizeof(u16), + .reg_cache_step = 2, + .reg_cache_default = wm9705_reg, +}; + +static __devinit int wm9705_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai)); +} + +static int __devexit wm9705_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static struct platform_driver wm9705_codec_driver = { + .driver = { + .name = "wm9705-codec", + .owner = THIS_MODULE, + }, + + .probe = wm9705_probe, + .remove = __devexit_p(wm9705_remove), }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705); + +static int __init wm9705_init(void) +{ + return platform_driver_register(&wm9705_codec_driver); +} +module_init(wm9705_init); + +static void __exit wm9705_exit(void) +{ + platform_driver_unregister(&wm9705_codec_driver); +} +module_exit(wm9705_exit); MODULE_DESCRIPTION("ASoC WM9705 driver"); MODULE_AUTHOR("Ian Molton"); diff --git a/sound/soc/codecs/wm9705.h b/sound/soc/codecs/wm9705.h index d380f110f9e2..23ea9ce47359 100644 --- a/sound/soc/codecs/wm9705.h +++ b/sound/soc/codecs/wm9705.h @@ -8,7 +8,4 @@ #define WM9705_DAI_AC97_HIFI 0 #define WM9705_DAI_AC97_AUX 1 -extern struct snd_soc_dai wm9705_dai[2]; -extern struct snd_soc_codec_device soc_codec_dev_wm9705; - #endif diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 28790a2ffe8d..f8f37ae30910 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -478,8 +478,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec =rtd->codec; int reg; u16 vra; @@ -499,8 +498,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u16 vra, xsle; vra = ac97_read(codec, AC97_EXTENDED_STATUS); @@ -526,9 +524,9 @@ static struct snd_soc_dai_ops wm9712_dai_ops_aux = { .prepare = ac97_aux_prepare, }; -struct snd_soc_dai wm9712_dai[] = { +struct snd_soc_dai_driver wm9712_dai[] = { { - .name = "AC97 HiFi", + .name = "wm9712-hifi", .ac97_control = 1, .playback = { .stream_name = "HiFi Playback", @@ -545,7 +543,7 @@ struct snd_soc_dai wm9712_dai[] = { .ops = &wm9712_dai_ops_hifi, }, { - .name = "AC97 Aux", + .name = "wm9712-aux", .playback = { .stream_name = "Aux Playback", .channels_min = 1, @@ -555,7 +553,6 @@ struct snd_soc_dai wm9712_dai[] = { .ops = &wm9712_dai_ops_aux, } }; -EXPORT_SYMBOL_GPL(wm9712_dai); static int wm9712_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) @@ -597,20 +594,15 @@ err: return -EIO; } -static int wm9712_soc_suspend(struct platform_device *pdev, +static int wm9712_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm9712_soc_resume(struct platform_device *pdev) +static int wm9712_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; int i, ret; u16 *cache = codec->reg_cache; @@ -635,51 +627,18 @@ static int wm9712_soc_resume(struct platform_device *pdev) return ret; } -static int wm9712_soc_probe(struct platform_device *pdev) +static int wm9712_soc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; int ret = 0; printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); - socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), - GFP_KERNEL); - if (socdev->card->codec == NULL) - return -ENOMEM; - codec = socdev->card->codec; - mutex_init(&codec->mutex); - - codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL); - - if (codec->reg_cache == NULL) { - ret = -ENOMEM; - goto cache_err; - } - codec->reg_cache_size = sizeof(wm9712_reg); - codec->reg_cache_step = 2; - - codec->name = "WM9712"; - codec->owner = THIS_MODULE; - codec->dai = wm9712_dai; - codec->num_dai = ARRAY_SIZE(wm9712_dai); - codec->write = ac97_write; - codec->read = ac97_read; - codec->set_bias_level = wm9712_set_bias_level; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); - goto codec_err; + return ret; } - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) - goto pcm_err; - ret = wm9712_reset(codec, 0); if (ret < 0) { printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); @@ -697,42 +656,63 @@ static int wm9712_soc_probe(struct platform_device *pdev) return 0; reset_err: - snd_soc_free_pcms(socdev); -pcm_err: snd_soc_free_ac97_codec(codec); - -codec_err: - kfree(codec->reg_cache); - -cache_err: - kfree(socdev->card->codec); - socdev->card->codec = NULL; return ret; } -static int wm9712_soc_remove(struct platform_device *pdev) +static int wm9712_soc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec == NULL) - return 0; - - snd_soc_dapm_free(socdev); - snd_soc_free_pcms(socdev); snd_soc_free_ac97_codec(codec); - kfree(codec->reg_cache); - kfree(codec); return 0; } -struct snd_soc_codec_device soc_codec_dev_wm9712 = { +static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { .probe = wm9712_soc_probe, .remove = wm9712_soc_remove, .suspend = wm9712_soc_suspend, .resume = wm9712_soc_resume, + .read = ac97_read, + .write = ac97_write, + .set_bias_level = wm9712_set_bias_level, + .reg_cache_size = sizeof(wm9712_reg), + .reg_word_size = sizeof(u16), + .reg_cache_step = 2, + .reg_cache_default = wm9712_reg, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712); + +static __devinit int wm9712_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai)); +} + +static int __devexit wm9712_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static struct platform_driver wm9712_codec_driver = { + .driver = { + .name = "wm9712-codec", + .owner = THIS_MODULE, + }, + + .probe = wm9712_probe, + .remove = __devexit_p(wm9712_remove), +}; + +static int __init wm9712_init(void) +{ + return platform_driver_register(&wm9712_codec_driver); +} +module_init(wm9712_init); + +static void __exit wm9712_exit(void) +{ + platform_driver_unregister(&wm9712_codec_driver); +} +module_exit(wm9712_exit); MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver"); MODULE_AUTHOR("Liam Girdwood"); diff --git a/sound/soc/codecs/wm9712.h b/sound/soc/codecs/wm9712.h index d29e8a18ca6d..fb69c3aa4ed0 100644 --- a/sound/soc/codecs/wm9712.h +++ b/sound/soc/codecs/wm9712.h @@ -8,7 +8,4 @@ #define WM9712_DAI_AC97_HIFI 0 #define WM9712_DAI_AC97_AUX 1 -extern struct snd_soc_dai wm9712_dai[2]; -extern struct snd_soc_codec_device soc_codec_dev_wm9712; - #endif diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 34e0c91092fa..463917e762b5 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1057,9 +1057,9 @@ static struct snd_soc_dai_ops wm9713_dai_ops_voice = { .set_tristate = wm9713_set_dai_tristate, }; -struct snd_soc_dai wm9713_dai[] = { +static struct snd_soc_dai_driver wm9713_dai[] = { { - .name = "AC97 HiFi", + .name = "wm9713-hifi", .ac97_control = 1, .playback = { .stream_name = "HiFi Playback", @@ -1076,7 +1076,7 @@ struct snd_soc_dai wm9713_dai[] = { .ops = &wm9713_dai_ops_hifi, }, { - .name = "AC97 Aux", + .name = "wm9713-aux", .playback = { .stream_name = "Aux Playback", .channels_min = 1, @@ -1086,7 +1086,7 @@ struct snd_soc_dai wm9713_dai[] = { .ops = &wm9713_dai_ops_aux, }, { - .name = "WM9713 Voice", + .name = "wm9713-voice", .playback = { .stream_name = "Voice Playback", .channels_min = 1, @@ -1103,7 +1103,6 @@ struct snd_soc_dai wm9713_dai[] = { .symmetric_rates = 1, }, }; -EXPORT_SYMBOL_GPL(wm9713_dai); int wm9713_reset(struct snd_soc_codec *codec, int try_warm) { @@ -1152,11 +1151,9 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec, return 0; } -static int wm9713_soc_suspend(struct platform_device *pdev, +static int wm9713_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; u16 reg; /* Disable everything except touchpanel - that will be handled @@ -1171,10 +1168,8 @@ static int wm9713_soc_suspend(struct platform_device *pdev, return 0; } -static int wm9713_soc_resume(struct platform_device *pdev) +static int wm9713_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); int i, ret; u16 *cache = codec->reg_cache; @@ -1204,53 +1199,20 @@ static int wm9713_soc_resume(struct platform_device *pdev) return ret; } -static int wm9713_soc_probe(struct platform_device *pdev) +static int wm9713_soc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; + struct wm9713_priv *wm9713; int ret = 0, reg; - socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), - GFP_KERNEL); - if (socdev->card->codec == NULL) + wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL); + if (wm9713 == NULL) return -ENOMEM; - codec = socdev->card->codec; - mutex_init(&codec->mutex); - - codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL); - if (codec->reg_cache == NULL) { - ret = -ENOMEM; - goto cache_err; - } - codec->reg_cache_size = sizeof(wm9713_reg); - codec->reg_cache_step = 2; - - snd_soc_codec_set_drvdata(codec, kzalloc(sizeof(struct wm9713_priv), - GFP_KERNEL)); - if (snd_soc_codec_get_drvdata(codec) == NULL) { - ret = -ENOMEM; - goto priv_err; - } - - codec->name = "WM9713"; - codec->owner = THIS_MODULE; - codec->dai = wm9713_dai; - codec->num_dai = ARRAY_SIZE(wm9713_dai); - codec->write = ac97_write; - codec->read = ac97_read; - codec->set_bias_level = wm9713_set_bias_level; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); + snd_soc_codec_set_drvdata(codec, wm9713); ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) goto codec_err; - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) - goto pcm_err; - /* do a cold reset for the controller and then try * a warm reset followed by an optional cold reset for codec */ wm9713_reset(codec, 0); @@ -1273,46 +1235,67 @@ static int wm9713_soc_probe(struct platform_device *pdev) return 0; reset_err: - snd_soc_free_pcms(socdev); -pcm_err: snd_soc_free_ac97_codec(codec); - codec_err: - kfree(snd_soc_codec_get_drvdata(codec)); - -priv_err: - kfree(codec->reg_cache); - -cache_err: - kfree(socdev->card->codec); - socdev->card->codec = NULL; + kfree(wm9713); return ret; } -static int wm9713_soc_remove(struct platform_device *pdev) +static int wm9713_soc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec == NULL) - return 0; - - snd_soc_dapm_free(socdev); - snd_soc_free_pcms(socdev); + struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); snd_soc_free_ac97_codec(codec); - kfree(snd_soc_codec_get_drvdata(codec)); - kfree(codec->reg_cache); - kfree(codec); + kfree(wm9713); return 0; } -struct snd_soc_codec_device soc_codec_dev_wm9713 = { +static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { .probe = wm9713_soc_probe, .remove = wm9713_soc_remove, .suspend = wm9713_soc_suspend, .resume = wm9713_soc_resume, + .read = ac97_read, + .write = ac97_write, + .set_bias_level = wm9713_set_bias_level, + .reg_cache_size = sizeof(wm9713_reg), + .reg_word_size = sizeof(u16), + .reg_cache_step = 2, + .reg_cache_default = wm9713_reg, +}; + +static __devinit int wm9713_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); +} + +static int __devexit wm9713_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static struct platform_driver wm9713_codec_driver = { + .driver = { + .name = "wm9713-codec", + .owner = THIS_MODULE, + }, + + .probe = wm9713_probe, + .remove = __devexit_p(wm9713_remove), }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713); + +static int __init wm9713_init(void) +{ + return platform_driver_register(&wm9713_codec_driver); +} +module_init(wm9713_init); + +static void __exit wm9713_exit(void) +{ + platform_driver_unregister(&wm9713_codec_driver); +} +module_exit(wm9713_exit); MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver"); MODULE_AUTHOR("Liam Girdwood"); diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h index 63b8d81756e3..793da863a03d 100644 --- a/sound/soc/codecs/wm9713.h +++ b/sound/soc/codecs/wm9713.h @@ -45,9 +45,6 @@ #define WM9713_DAI_AC97_AUX 1 #define WM9713_DAI_PCM_VOICE 2 -extern struct snd_soc_codec_device soc_codec_dev_wm9713; -extern struct snd_soc_dai wm9713_dai[3]; - int wm9713_reset(struct snd_soc_codec *codec, int try_warm); #endif diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 97f74d6a33e6..2b07b17a6b2d 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -28,12 +28,9 @@ #include #include "../codecs/tlv320aic3x.h" -#include "../codecs/cq93vc.h" -#include "../codecs/spdif_transciever.h" #include "davinci-pcm.h" #include "davinci-i2s.h" #include "davinci-mcasp.h" -#include "davinci-vcif.h" #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) @@ -41,8 +38,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret = 0; unsigned sysclk; @@ -87,7 +84,7 @@ static int evm_spdif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; /* set cpu DAI configuration */ return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); @@ -132,8 +129,10 @@ static const struct snd_soc_dapm_route audio_map[] = { }; /* Logic for a aic3x as connected on a davinci-evm */ -static int evm_aic3x_init(struct snd_soc_codec *codec) +static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + /* Add davinci-evm specific widgets */ snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, ARRAY_SIZE(aic3x_dapm_widgets)); @@ -161,8 +160,10 @@ static int evm_aic3x_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link evm_dai = { .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai = &davinci_i2s_dai, - .codec_dai = &aic3x_dai, + .cpu_dai_name = "davinci-mcasp.0", + .codec_dai_name = "tlv320aic3x-hifi", + .codec_name = "tlv320aic3x-codec.0-001a", + .platform_name = "davinci-pcm-audio", .init = evm_aic3x_init, .ops = &evm_ops, }; @@ -171,40 +172,49 @@ static struct snd_soc_dai_link dm365_evm_dai = { #ifdef CONFIG_SND_DM365_AIC3X_CODEC .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai = &davinci_i2s_dai, - .codec_dai = &aic3x_dai, + .cpu_dai_name = "davinci-i2s", + .codec_dai_name = "tlv320aic3x-hifi", .init = evm_aic3x_init, + .codec_name = "tlv320aic3x-codec.0-001a", .ops = &evm_ops, #elif defined(CONFIG_SND_DM365_VOICE_CODEC) .name = "Voice Codec - CQ93VC", .stream_name = "CQ93", - .cpu_dai = &davinci_vcif_dai, - .codec_dai = &cq93vc_dai, + .cpu_dai_name = "davinci-vcif", + .codec_dai_name = "cq93vc-hifi", + .codec_name = "cq93vc-codec", #endif + .platform_name = "davinci-pcm-audio", }; static struct snd_soc_dai_link dm6467_evm_dai[] = { { .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI], - .codec_dai = &aic3x_dai, + .cpu_dai_name= "davinci-mcasp.0", + .codec_dai_name = "tlv320aic3x-hifi", + .platform_name ="davinci-pcm-audio", + .codec_name = "tlv320aic3x-codec.0-001a", .init = evm_aic3x_init, .ops = &evm_ops, }, { .name = "McASP", .stream_name = "spdif", - .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI], - .codec_dai = &dit_stub_dai, + .cpu_dai_name= "davinci-mcasp.1", + .codec_dai_name = "dit-hifi", + .codec_name = "spdif_dit", + .platform_name = "davinci-pcm-audio", .ops = &evm_spdif_ops, }, }; static struct snd_soc_dai_link da8xx_evm_dai = { .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI], - .codec_dai = &aic3x_dai, + .cpu_dai_name= "davinci-mcasp.0", + .codec_dai_name = "tlv320aic3x-hifi", + .codec_name = "tlv320aic3x-codec.0-001a", + .platform_name = "davinci-pcm-audio", .init = evm_aic3x_init, .ops = &evm_ops, }; @@ -212,7 +222,6 @@ static struct snd_soc_dai_link da8xx_evm_dai = { /* davinci dm6446, dm355 evm audio machine driver */ static struct snd_soc_card snd_soc_card_evm = { .name = "DaVinci EVM", - .platform = &davinci_soc_platform, .dai_link = &evm_dai, .num_links = 1, }; @@ -220,16 +229,13 @@ static struct snd_soc_card snd_soc_card_evm = { /* davinci dm365 evm audio machine driver */ static struct snd_soc_card dm365_snd_soc_card_evm = { .name = "DaVinci DM365 EVM", - .platform = &davinci_soc_platform, .dai_link = &dm365_evm_dai, .num_links = 1, }; - /* davinci dm6467 evm audio machine driver */ static struct snd_soc_card dm6467_snd_soc_card_evm = { .name = "DaVinci DM6467 EVM", - .platform = &davinci_soc_platform, .dai_link = dm6467_evm_dai, .num_links = ARRAY_SIZE(dm6467_evm_dai), }; @@ -237,82 +243,40 @@ static struct snd_soc_card dm6467_snd_soc_card_evm = { static struct snd_soc_card da830_snd_soc_card = { .name = "DA830/OMAP-L137 EVM", .dai_link = &da8xx_evm_dai, - .platform = &davinci_soc_platform, .num_links = 1, }; static struct snd_soc_card da850_snd_soc_card = { .name = "DA850/OMAP-L138 EVM", .dai_link = &da8xx_evm_dai, - .platform = &davinci_soc_platform, .num_links = 1, }; -static struct aic3x_setup_data aic3x_setup; - -/* evm audio subsystem */ -static struct snd_soc_device evm_snd_devdata = { - .card = &snd_soc_card_evm, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &aic3x_setup, -}; - -/* evm audio subsystem */ -static struct snd_soc_device dm365_evm_snd_devdata = { - .card = &dm365_snd_soc_card_evm, -#ifdef CONFIG_SND_DM365_AIC3X_CODEC - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &aic3x_setup, -#elif defined(CONFIG_SND_DM365_VOICE_CODEC) - .codec_dev = &soc_codec_dev_cq93vc, -#endif -}; - -/* evm audio subsystem */ -static struct snd_soc_device dm6467_evm_snd_devdata = { - .card = &dm6467_snd_soc_card_evm, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &aic3x_setup, -}; - -/* evm audio subsystem */ -static struct snd_soc_device da830_evm_snd_devdata = { - .card = &da830_snd_soc_card, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &aic3x_setup, -}; - -static struct snd_soc_device da850_evm_snd_devdata = { - .card = &da850_snd_soc_card, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &aic3x_setup, -}; - static struct platform_device *evm_snd_device; static int __init evm_init(void) { - struct snd_soc_device *evm_snd_dev_data; + struct snd_soc_card *evm_snd_dev_data; int index; int ret; if (machine_is_davinci_evm()) { - evm_snd_dev_data = &evm_snd_devdata; + evm_snd_dev_data = &snd_soc_card_evm; index = 0; } else if (machine_is_davinci_dm355_evm()) { - evm_snd_dev_data = &evm_snd_devdata; + evm_snd_dev_data = &snd_soc_card_evm; index = 1; } else if (machine_is_davinci_dm365_evm()) { - evm_snd_dev_data = &dm365_evm_snd_devdata; + evm_snd_dev_data = &dm365_snd_soc_card_evm; index = 0; } else if (machine_is_davinci_dm6467_evm()) { - evm_snd_dev_data = &dm6467_evm_snd_devdata; + evm_snd_dev_data = &dm6467_snd_soc_card_evm; index = 0; } else if (machine_is_davinci_da830_evm()) { - evm_snd_dev_data = &da830_evm_snd_devdata; + evm_snd_dev_data = &da830_snd_soc_card; index = 1; } else if (machine_is_davinci_da850_evm()) { - evm_snd_dev_data = &da850_evm_snd_devdata; + evm_snd_dev_data = &da850_snd_soc_card; index = 0; } else return -EINVAL; @@ -322,7 +286,6 @@ static int __init evm_init(void) return -ENOMEM; platform_set_drvdata(evm_snd_device, evm_snd_dev_data); - evm_snd_dev_data->dev = &evm_snd_device->dev; ret = platform_device_add(evm_snd_device); if (ret) platform_device_put(evm_snd_device); diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 9e8932abf158..9f8b6c556866 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -183,8 +183,7 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_platform *platform = socdev->card->platform; + struct snd_soc_platform *platform = rtd->platform; int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); u32 spcr; u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; @@ -205,8 +204,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, if (playback) { /* Stop the DMA to avoid data loss */ /* while the transmitter is out of reset to handle XSYNCERR */ - if (platform->pcm_ops->trigger) { - int ret = platform->pcm_ops->trigger(substream, + if (platform->driver->ops->trigger) { + int ret = platform->driver->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); if (ret < 0) printk(KERN_DEBUG "Playback DMA stop failed\n"); @@ -227,8 +226,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, toggle_clock(dev, playback); /* Restart the DMA */ - if (platform->pcm_ops->trigger) { - int ret = platform->pcm_ops->trigger(substream, + if (platform->driver->ops->trigger) { + int ret = platform->driver->ops->trigger(substream, SNDRV_PCM_TRIGGER_START); if (ret < 0) printk(KERN_DEBUG "Playback DMA start failed\n"); @@ -263,7 +262,7 @@ static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback) static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct davinci_mcbsp_dev *dev = cpu_dai->private_data; + struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); unsigned int pcr; unsigned int srgr; /* Attention srgr is updated by hw_params! */ @@ -404,7 +403,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) { - struct davinci_mcbsp_dev *dev = cpu_dai->private_data; + struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); if (div_id != DAVINCI_MCBSP_CLKGDV) return -ENODEV; @@ -417,7 +416,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = dai->private_data; + struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); struct davinci_pcm_dma_params *dma_params = &dev->dma_params[substream->stream]; struct snd_interval *i = NULL; @@ -427,6 +426,9 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, snd_pcm_format_t fmt; unsigned element_cnt = 1; + dai->capture_dma_data = dev->dma_params; + dai->playback_dma_data = dev->dma_params; + /* general line settings */ spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { @@ -569,7 +571,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, static int davinci_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = dai->private_data; + struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); davinci_mcbsp_stop(dev, playback); if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) { @@ -582,7 +584,7 @@ static int davinci_i2s_prepare(struct snd_pcm_substream *substream, static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = dai->private_data; + struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); int ret = 0; int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) @@ -608,7 +610,7 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = dai->private_data; + struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); davinci_mcbsp_stop(dev, playback); } @@ -625,9 +627,7 @@ static struct snd_soc_dai_ops davinci_i2s_dai_ops = { }; -struct snd_soc_dai davinci_i2s_dai = { - .name = "davinci-i2s", - .id = 0, +static struct snd_soc_dai_driver davinci_i2s_dai = { .playback = { .channels_min = 2, .channels_max = 2, @@ -641,7 +641,6 @@ struct snd_soc_dai davinci_i2s_dai = { .ops = &davinci_i2s_dai_ops, }; -EXPORT_SYMBOL_GPL(davinci_i2s_dai); static int davinci_i2s_probe(struct platform_device *pdev) { @@ -720,10 +719,9 @@ static int davinci_i2s_probe(struct platform_device *pdev) dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; dev->dev = &pdev->dev; - davinci_i2s_dai.private_data = dev; - davinci_i2s_dai.capture.dma_data = dev->dma_params; - davinci_i2s_dai.playback.dma_data = dev->dma_params; - ret = snd_soc_register_dai(&davinci_i2s_dai); + dev_set_drvdata(&pdev->dev, dev); + + ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai); if (ret != 0) goto err_free_mem; @@ -739,10 +737,10 @@ err_release_region: static int davinci_i2s_remove(struct platform_device *pdev) { - struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data; + struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); struct resource *mem; - snd_soc_unregister_dai(&davinci_i2s_dai); + snd_soc_unregister_dai(&pdev->dev); clk_disable(dev->clk); clk_put(dev->clk); dev->clk = NULL; @@ -757,7 +755,7 @@ static struct platform_driver davinci_mcbsp_driver = { .probe = davinci_i2s_probe, .remove = davinci_i2s_remove, .driver = { - .name = "davinci-asp", + .name = "davinci-i2s", .owner = THIS_MODULE, }, }; diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h index 0b1e77b8c279..48dac3e2521a 100644 --- a/sound/soc/davinci/davinci-i2s.h +++ b/sound/soc/davinci/davinci-i2s.h @@ -17,6 +17,4 @@ enum davinci_mcbsp_div { DAVINCI_MCBSP_CLKGDV, /* Sample rate generator divider */ }; -extern struct snd_soc_dai davinci_i2s_dai; - #endif diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index b24720894af6..c8e97dcbfff4 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -422,7 +422,7 @@ static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct davinci_audio_dev *dev = cpu_dai->private_data; + struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); void __iomem *base = dev->base; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -709,12 +709,15 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { - struct davinci_audio_dev *dev = cpu_dai->private_data; + struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); struct davinci_pcm_dma_params *dma_params = &dev->dma_params[substream->stream]; int word_length; u8 fifo_level; + cpu_dai->capture_dma_data = dev->dma_params; + cpu_dai->playback_dma_data = dev->dma_params; + davinci_hw_common_param(dev, substream->stream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) fifo_level = dev->txnumevt; @@ -761,8 +764,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct davinci_audio_dev *dev = rtd->dai->cpu_dai->private_data; + struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); int ret = 0; switch (cmd) { @@ -804,10 +806,9 @@ static struct snd_soc_dai_ops davinci_mcasp_dai_ops = { }; -struct snd_soc_dai davinci_mcasp_dai[] = { +static struct snd_soc_dai_driver davinci_mcasp_dai[] = { { - .name = "davinci-i2s", - .id = 0, + .name = "davinci-mcasp.0", .playback = { .channels_min = 2, .channels_max = 2, @@ -828,8 +829,7 @@ struct snd_soc_dai davinci_mcasp_dai[] = { }, { - .name = "davinci-dit", - .id = 1, + "davinci-mcasp.1", .playback = { .channels_min = 1, .channels_max = 384, @@ -840,7 +840,6 @@ struct snd_soc_dai davinci_mcasp_dai[] = { }, }; -EXPORT_SYMBOL_GPL(davinci_mcasp_dai); static int davinci_mcasp_probe(struct platform_device *pdev) { @@ -917,11 +916,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev) } dma_data->channel = res->start; - davinci_mcasp_dai[pdata->op_mode].private_data = dev; - davinci_mcasp_dai[pdata->op_mode].capture.dma_data = dev->dma_params; - davinci_mcasp_dai[pdata->op_mode].playback.dma_data = dev->dma_params; - davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev; - ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]); + dev_set_drvdata(&pdev->dev, dev); + ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]); if (ret != 0) goto err_release_region; @@ -937,12 +933,10 @@ err_release_data: static int davinci_mcasp_remove(struct platform_device *pdev) { - struct snd_platform_data *pdata = pdev->dev.platform_data; - struct davinci_audio_dev *dev; + struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); struct resource *mem; - snd_soc_unregister_dai(&davinci_mcasp_dai[pdata->op_mode]); - dev = davinci_mcasp_dai[pdata->op_mode].private_data; + snd_soc_unregister_dai(&pdev->dev); clk_disable(dev->clk); clk_put(dev->clk); dev->clk = NULL; diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index e755b5121ec7..4681acc63606 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h @@ -22,8 +22,6 @@ #include #include "davinci-pcm.h" -extern struct snd_soc_dai davinci_mcasp_dai[]; - #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 #define DAVINCI_MCASP_I2S_DAI 0 #define DAVINCI_MCASP_DIT_DAI 1 diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index a7124116d2e0..9d35b8c1a624 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -653,7 +653,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream) struct davinci_pcm_dma_params *pa; struct davinci_pcm_dma_params *params; - pa = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + pa = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (!pa) return -ENODEV; params = &pa[substream->stream]; @@ -821,7 +821,7 @@ static int davinci_pcm_new(struct snd_card *card, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = 0xffffffff; - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = davinci_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK, pcm_hardware_playback.buffer_bytes_max); @@ -829,7 +829,7 @@ static int davinci_pcm_new(struct snd_card *card, return ret; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { ret = davinci_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE, pcm_hardware_capture.buffer_bytes_max); @@ -840,25 +840,44 @@ static int davinci_pcm_new(struct snd_card *card, return 0; } -struct snd_soc_platform davinci_soc_platform = { - .name = "davinci-audio", - .pcm_ops = &davinci_pcm_ops, +static struct snd_soc_platform_driver davinci_soc_platform = { + .ops = &davinci_pcm_ops, .pcm_new = davinci_pcm_new, .pcm_free = davinci_pcm_free, }; -EXPORT_SYMBOL_GPL(davinci_soc_platform); -static int __init davinci_soc_platform_init(void) +static int __devinit davinci_soc_platform_probe(struct platform_device *pdev) { - return snd_soc_register_platform(&davinci_soc_platform); + return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform); } -module_init(davinci_soc_platform_init); -static void __exit davinci_soc_platform_exit(void) +static int __devexit davinci_soc_platform_remove(struct platform_device *pdev) { - snd_soc_unregister_platform(&davinci_soc_platform); + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver davinci_pcm_driver = { + .driver = { + .name = "davinci-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = davinci_soc_platform_probe, + .remove = __devexit_p(davinci_soc_platform_remove), +}; + +static int __init snd_davinci_pcm_init(void) +{ + return platform_driver_register(&davinci_pcm_driver); +} +module_init(snd_davinci_pcm_init); + +static void __exit snd_davinci_pcm_exit(void) +{ + platform_driver_unregister(&davinci_pcm_driver); } -module_exit(davinci_soc_platform_exit); +module_exit(snd_davinci_pcm_exit); MODULE_AUTHOR("Vladimir Barinov"); MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index b799a02333d8..c0d6c9be4b4d 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -28,7 +28,4 @@ struct davinci_pcm_dma_params { unsigned int fifo_level; }; - -extern struct snd_soc_platform davinci_soc_platform; - #endif diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index 40eccfe9e358..997c54f3693c 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c @@ -29,7 +29,6 @@ #include #endif -#include #include #include "../codecs/pcm3008.h" @@ -48,7 +47,7 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int fs; int ret = 0; @@ -85,15 +84,16 @@ static struct snd_soc_ops sffsdr_ops = { static struct snd_soc_dai_link sffsdr_dai = { .name = "PCM3008", /* Codec name */ .stream_name = "PCM3008 HiFi", - .cpu_dai = &davinci_i2s_dai, - .codec_dai = &pcm3008_dai, + .cpu_dai_name = "davinci-asp.0", + .codec_dai_name = "pcm3008-hifi", + .codec_name = "pcm3008-codec", + .platform_name = "davinci-pcm-audio", .ops = &sffsdr_ops, }; /* davinci-sffsdr audio machine driver */ static struct snd_soc_card snd_soc_sffsdr = { .name = "DaVinci SFFSDR", - .platform = &davinci_soc_platform, .dai_link = &sffsdr_dai, .num_links = 1, }; @@ -106,11 +106,12 @@ static struct pcm3008_setup_data sffsdr_pcm3008_setup = { .pdda_pin = GPIO(38), }; -/* sffsdr audio subsystem */ -static struct snd_soc_device sffsdr_snd_devdata = { - .card = &snd_soc_sffsdr, - .codec_dev = &soc_codec_dev_pcm3008, - .codec_data = &sffsdr_pcm3008_setup, +struct platform_device pcm3008_codec = { + .name = "pcm3008-codec", + .id = 0, + .dev = { + .platform_data = &sffsdr_pcm3008_setup, + }, }; static struct resource sffsdr_snd_resources[] = { @@ -135,14 +136,15 @@ static int __init sffsdr_init(void) if (!machine_is_sffsdr()) return -EINVAL; + platform_device_register(&pcm3008_codec); + sffsdr_snd_device = platform_device_alloc("soc-audio", 0); if (!sffsdr_snd_device) { printk(KERN_ERR "platform device allocation failed\n"); return -ENOMEM; } - platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata); - sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev; + platform_set_drvdata(sffsdr_snd_device, &snd_soc_sffsdr); platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data, sizeof(sffsdr_snd_data)); @@ -168,6 +170,7 @@ error: static void __exit sffsdr_exit(void) { platform_device_unregister(sffsdr_snd_device); + platform_device_unregister(&pcm3008_codec); } module_init(sffsdr_init); diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index 48678533da7a..ea232f6a2c21 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c @@ -36,7 +36,6 @@ #include "davinci-pcm.h" #include "davinci-i2s.h" -#include "davinci-vcif.h" #define MOD_REG_BIT(val, mask, set) do { \ if (set) { \ @@ -55,7 +54,7 @@ static void davinci_vcif_start(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct davinci_vcif_dev *davinci_vcif_dev = - rtd->dai->cpu_dai->private_data; + snd_soc_dai_get_drvdata(rtd->cpu_dai); struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; u32 w; @@ -74,7 +73,7 @@ static void davinci_vcif_stop(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct davinci_vcif_dev *davinci_vcif_dev = - rtd->dai->cpu_dai->private_data; + snd_soc_dai_get_drvdata(rtd->cpu_dai); struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; u32 w; @@ -92,12 +91,15 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct davinci_vcif_dev *davinci_vcif_dev = dai->private_data; + struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(dai); struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; struct davinci_pcm_dma_params *dma_params = &davinci_vcif_dev->dma_params[substream->stream]; u32 w; + dai->capture_dma_data = davinci_vcif_dev->dma_params; + dai->playback_dma_data = davinci_vcif_dev->dma_params; + /* Restart the codec before setup */ davinci_vcif_stop(substream); davinci_vcif_start(substream); @@ -179,8 +181,7 @@ static struct snd_soc_dai_ops davinci_vcif_dai_ops = { .hw_params = davinci_vcif_hw_params, }; -struct snd_soc_dai davinci_vcif_dai = { - .name = "davinci-vcif", +static struct snd_soc_dai_driver davinci_vcif_dai = { .playback = { .channels_min = 1, .channels_max = 2, @@ -194,7 +195,6 @@ struct snd_soc_dai davinci_vcif_dai = { .ops = &davinci_vcif_dai_ops, }; -EXPORT_SYMBOL_GPL(davinci_vcif_dai); static int davinci_vcif_probe(struct platform_device *pdev) { @@ -222,12 +222,9 @@ static int davinci_vcif_probe(struct platform_device *pdev) davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr = davinci_vc->davinci_vcif.dma_rx_addr; - davinci_vcif_dai.dev = &pdev->dev; - davinci_vcif_dai.capture.dma_data = davinci_vcif_dev->dma_params; - davinci_vcif_dai.playback.dma_data = davinci_vcif_dev->dma_params; - davinci_vcif_dai.private_data = davinci_vcif_dev; + dev_set_drvdata(&pdev->dev, davinci_vcif_dev); - ret = snd_soc_register_dai(&davinci_vcif_dai); + ret = snd_soc_register_dai(&pdev->dev, &davinci_vcif_dai); if (ret != 0) { dev_err(&pdev->dev, "could not register dai\n"); goto fail; @@ -243,7 +240,7 @@ fail: static int davinci_vcif_remove(struct platform_device *pdev) { - snd_soc_unregister_dai(&davinci_vcif_dai); + snd_soc_unregister_dai(&pdev->dev); return 0; } @@ -252,7 +249,7 @@ static struct platform_driver davinci_vcif_driver = { .probe = davinci_vcif_probe, .remove = davinci_vcif_remove, .driver = { - .name = "davinci_vcif", + .name = "davinci-vcif", .owner = THIS_MODULE, }, }; diff --git a/sound/soc/davinci/davinci-vcif.h b/sound/soc/davinci/davinci-vcif.h deleted file mode 100644 index 571c9948724f..000000000000 --- a/sound/soc/davinci/davinci-vcif.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * ALSA SoC Voice Codec Interface for TI DAVINCI processor - * - * Copyright (C) 2010 Texas Instruments. - * - * Author: Miguel Aguilar - * - * 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 - */ - -#ifndef _DAVINCI_VCIF_H -#define _DAVINCI_VCIF_H - -extern struct snd_soc_dai davinci_vcif_dai; - -#endif diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c index 00b946632184..4f4873359613 100644 --- a/sound/soc/ep93xx/ep93xx-i2s.c +++ b/sound/soc/ep93xx/ep93xx-i2s.c @@ -31,7 +31,6 @@ #include #include "ep93xx-pcm.h" -#include "ep93xx-i2s.h" #define EP93XX_I2S_TXCLKCFG 0x00 #define EP93XX_I2S_RXCLKCFG 0x04 @@ -145,8 +144,8 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; snd_soc_dai_set_dma_data(cpu_dai, substream, &info->dma_params[substream->stream]); @@ -156,8 +155,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); ep93xx_i2s_disable(info, substream->stream); } @@ -165,7 +163,7 @@ static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct ep93xx_i2s_info *info = cpu_dai->private_data; + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); unsigned int clk_cfg, lin_ctrl; clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); @@ -242,9 +240,7 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct ep93xx_i2s_info *info = cpu_dai->private_data; + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); unsigned word_len, div, sdiv, lrdiv; int found = 0, err; @@ -302,7 +298,7 @@ out: static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct ep93xx_i2s_info *info = cpu_dai->private_data; + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); if (dir == SND_SOC_CLOCK_IN || clk_id != 0) return -EINVAL; @@ -313,7 +309,7 @@ static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, #ifdef CONFIG_PM static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) { - struct ep93xx_i2s_info *info = dai->private_data; + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); if (!dai->active) return; @@ -324,7 +320,7 @@ static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) static int ep93xx_i2s_resume(struct snd_soc_dai *dai) { - struct ep93xx_i2s_info *info = dai->private_data; + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); if (!dai->active) return; @@ -349,9 +345,7 @@ static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE) -struct snd_soc_dai ep93xx_i2s_dai = { - .name = "ep93xx-i2s", - .id = 0, +static struct snd_soc_dai_driver ep93xx_i2s_dai = { .symmetric_rates= 1, .suspend = ep93xx_i2s_suspend, .resume = ep93xx_i2s_resume, @@ -369,7 +363,6 @@ struct snd_soc_dai ep93xx_i2s_dai = { }, .ops = &ep93xx_i2s_dai_ops, }; -EXPORT_SYMBOL_GPL(ep93xx_i2s_dai); static int ep93xx_i2s_probe(struct platform_device *pdev) { @@ -383,8 +376,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev) goto fail; } - ep93xx_i2s_dai.dev = &pdev->dev; - ep93xx_i2s_dai.private_data = info; + dev_set_drvdata(&pdev->dev, info); info->dma_params = ep93xx_i2s_dma_params; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -424,7 +416,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev) goto fail_put_sclk; } - err = snd_soc_register_dai(&ep93xx_i2s_dai); + err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai); if (err) goto fail_put_lrclk; @@ -447,9 +439,9 @@ fail: static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) { - struct ep93xx_i2s_info *info = ep93xx_i2s_dai.private_data; + struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); - snd_soc_unregister_dai(&ep93xx_i2s_dai); + snd_soc_unregister_dai(&pdev->dev); clk_put(info->lrclk); clk_put(info->sclk); clk_put(info->mclk); diff --git a/sound/soc/ep93xx/ep93xx-i2s.h b/sound/soc/ep93xx/ep93xx-i2s.h deleted file mode 100644 index 3bd4ebfaa1de..000000000000 --- a/sound/soc/ep93xx/ep93xx-i2s.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * linux/sound/soc/ep93xx-i2s.h - * EP93xx I2S driver - * - * Copyright (C) 2010 Ryan Mallon - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef _EP93XX_SND_SOC_I2S_H -#define _EP93XX_SND_SOC_I2S_H - -extern struct snd_soc_dai ep93xx_i2s_dai; - -#endif /* _EP93XX_SND_SOC_I2S_H */ diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c index 4ba938400791..2f121ddbe4bb 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/ep93xx/ep93xx-pcm.c @@ -95,7 +95,7 @@ static void ep93xx_pcm_buffer_finished(void *cookie, static int ep93xx_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = soc_rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai; struct ep93xx_pcm_dma_params *dma_params; struct ep93xx_runtime_data *rtd; int ret; @@ -276,14 +276,14 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = 0xffffffff; - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = ep93xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) return ret; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { ret = ep93xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) @@ -293,22 +293,41 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, return 0; } -struct snd_soc_platform ep93xx_soc_platform = { - .name = "ep93xx-audio", - .pcm_ops = &ep93xx_pcm_ops, +static struct snd_soc_platform_driver ep93xx_soc_platform = { + .ops = &ep93xx_pcm_ops, .pcm_new = &ep93xx_pcm_new, .pcm_free = &ep93xx_pcm_free_dma_buffers, }; -EXPORT_SYMBOL_GPL(ep93xx_soc_platform); + +static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev) +{ + return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform); +} + +static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver ep93xx_pcm_driver = { + .driver = { + .name = "ep93xx-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = ep93xx_soc_platform_probe, + .remove = __devexit_p(ep93xx_soc_platform_remove), +}; static int __init ep93xx_soc_platform_init(void) { - return snd_soc_register_platform(&ep93xx_soc_platform); + return platform_driver_register(&ep93xx_pcm_driver); } static void __exit ep93xx_soc_platform_exit(void) { - snd_soc_unregister_platform(&ep93xx_soc_platform); + platform_driver_unregister(&ep93xx_pcm_driver); } module_init(ep93xx_soc_platform_init); diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/ep93xx/ep93xx-pcm.h index 4ffdd3f62fe9..111e1121ecb8 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.h +++ b/sound/soc/ep93xx/ep93xx-pcm.h @@ -17,6 +17,4 @@ struct ep93xx_pcm_dma_params { int dma_port; }; -extern struct snd_soc_platform ep93xx_soc_platform; - #endif /* _EP93XX_SND_SOC_PCM_H */ diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c index 64955340ff75..28ab5ff772ac 100644 --- a/sound/soc/ep93xx/snappercl15.c +++ b/sound/soc/ep93xx/snappercl15.c @@ -22,7 +22,6 @@ #include "../codecs/tlv320aic23.h" #include "ep93xx-pcm.h" -#include "ep93xx-i2s.h" #define CODEC_CLOCK 5644800 @@ -30,8 +29,8 @@ static int snappercl15_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int err; err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | @@ -77,8 +76,10 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MICIN", NULL, "Mic Jack"}, }; -static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec) +static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, ARRAY_SIZE(tlv320aic23_dapm_widgets)); @@ -89,24 +90,20 @@ static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link snappercl15_dai = { .name = "tlv320aic23", .stream_name = "AIC23", - .cpu_dai = &ep93xx_i2s_dai, - .codec_dai = &tlv320aic23_dai, + .cpu_dai_name = "ep93xx-i2s", + .codec_dai_name = "tlv320aic23-hifi", + .codec_name = "tlv320aic23-codec.0-001a", + .platform_name = "ep93xx-pcm-audio", .init = snappercl15_tlv320aic23_init, .ops = &snappercl15_ops, }; static struct snd_soc_card snd_soc_snappercl15 = { .name = "Snapper CL15", - .platform = &ep93xx_soc_platform, .dai_link = &snappercl15_dai, .num_links = 1, }; -static struct snd_soc_device snappercl15_snd_devdata = { - .card = &snd_soc_snappercl15, - .codec_dev = &soc_codec_dev_tlv320aic23, -}; - static struct platform_device *snappercl15_snd_device; static int __init snappercl15_init(void) @@ -126,8 +123,7 @@ static int __init snappercl15_init(void) if (!snappercl15_snd_device) return -ENOMEM; - platform_set_drvdata(snappercl15_snd_device, &snappercl15_snd_devdata); - snappercl15_snd_devdata.dev = &snappercl15_snd_device->dev; + platform_set_drvdata(snappercl15_snd_device, &snd_soc_snappercl15); ret = platform_device_add(snappercl15_snd_device); if (ret) platform_device_put(snappercl15_snd_device); diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 8cb65ccad35f..981868700388 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,6 +1,3 @@ -config SND_SOC_OF_SIMPLE - tristate - config SND_MPC52xx_DMA tristate diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index a83a73967ec6..7e472a53fcd3 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -1,6 +1,3 @@ -# Simple machine driver that extracts configuration from the OF device tree -obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o - # MPC8610 HPCD Machine Support snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c index 1a5b8e0d6a34..53251e6b5bd5 100644 --- a/sound/soc/fsl/efika-audio-fabric.c +++ b/sound/soc/fsl/efika-audio-fabric.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "mpc5200_dma.h" #include "mpc5200_psc_ac97.h" @@ -32,21 +31,24 @@ #define DRV_NAME "efika-audio-fabric" -static struct snd_soc_device device; static struct snd_soc_card card; static struct snd_soc_dai_link efika_fabric_dai[] = { { .name = "AC97", .stream_name = "AC97 Analog", - .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_ANALOG], - .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL], + .codec_dai_name = "stac9766-hifi-analog", + .cpu_dai_name = "mpc5200-psc-ac97.0", + .platform_name = "mpc5200-pcm-audio", + .codec_name = "stac9766-codec", }, { .name = "AC97", .stream_name = "AC97 IEC958", - .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_DIGITAL], - .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF], + .codec_dai_name = "stac9766-hifi-IEC958", + .cpu_dai_name = "mpc5200-psc-ac97.1", + .platform_name = "mpc5200-pcm-audio", + .codec_name = "stac9766-codec", }, }; @@ -58,13 +60,10 @@ static __init int efika_fabric_init(void) if (!of_machine_is_compatible("bplan,efika")) return -ENODEV; - card.platform = &mpc5200_audio_dma_platform; card.name = "Efika"; card.dai_link = efika_fabric_dai; card.num_links = ARRAY_SIZE(efika_fabric_dai); - device.card = &card; - device.codec_dev = &soc_codec_dev_stac9766; pdev = platform_device_alloc("soc-audio", 1); if (!pdev) { @@ -72,8 +71,7 @@ static __init int efika_fabric_init(void) return -ENODEV; } - platform_set_drvdata(pdev, &device); - device.dev = &pdev->dev; + platform_set_drvdata(pdev, &card); rc = platform_device_add(pdev); if (rc) { diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 410c7496a18d..d09e1941b1fa 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -3,10 +3,11 @@ * * Author: Timur Tabi * - * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed - * under the terms of the GNU General Public License version 2. This - * program is licensed "as is" without any warranty of any kind, whether - * express or implied. + * Copyright 2007-2010 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. * * This driver implements ASoC support for the Elo DMA controller, which is * the DMA controller on Freescale 83xx, 85xx, and 86xx SOCs. In ALSA terms, @@ -20,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -29,6 +32,7 @@ #include #include "fsl_dma.h" +#include "fsl_ssi.h" /* For the offset of stx0 and srx0 */ /* * The formats that the DMA controller supports, which is anything @@ -52,26 +56,16 @@ #define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ SNDRV_PCM_RATE_CONTINUOUS) -/* DMA global data. This structure is used by fsl_dma_open() to determine - * which DMA channels to assign to a substream. Unfortunately, ASoC V1 does - * not allow the machine driver to provide this information to the PCM - * driver in advance, and there's no way to differentiate between the two - * DMA controllers. So for now, this driver only supports one SSI device - * using two DMA channels. We cannot support multiple DMA devices. - * - * ssi_stx_phys: bus address of SSI STX register - * ssi_srx_phys: bus address of SSI SRX register - * dma_channel: pointer to the DMA channel's registers - * irq: IRQ for this DMA channel - * assigned: set to 1 if that DMA channel is assigned to a substream - */ -static struct { +struct dma_object { + struct list_head list; + struct snd_soc_platform_driver dai; dma_addr_t ssi_stx_phys; dma_addr_t ssi_srx_phys; - struct ccsr_dma_channel __iomem *dma_channel[2]; - unsigned int irq[2]; - unsigned int assigned[2]; -} dma_global_data; + struct ccsr_dma_channel __iomem *channel; + unsigned int irq; + bool assigned; + char path[1]; +}; /* * The number of DMA links to use. Two is the bare minimum, but if you @@ -88,8 +82,6 @@ static struct { * structure. * * @link[]: array of link descriptors - * @controller_id: which DMA controller (0, 1, ...) - * @channel_id: which DMA channel on the controller (0, 1, 2, ...) * @dma_channel: pointer to the DMA channel's registers * @irq: IRQ for this DMA channel * @substream: pointer to the substream object, needed by the ISR @@ -104,8 +96,6 @@ static struct { */ struct fsl_dma_private { struct fsl_dma_link_descriptor link[NUM_DMA_LINKS]; - unsigned int controller_id; - unsigned int channel_id; struct ccsr_dma_channel __iomem *dma_channel; unsigned int irq; struct snd_pcm_substream *substream; @@ -212,6 +202,9 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private) static irqreturn_t fsl_dma_isr(int irq, void *dev_id) { struct fsl_dma_private *dma_private = dev_id; + struct snd_pcm_substream *substream = dma_private->substream; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; irqreturn_t ret = IRQ_NONE; u32 sr, sr2 = 0; @@ -222,11 +215,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) sr = in_be32(&dma_channel->sr); if (sr & CCSR_DMA_SR_TE) { - dev_err(dma_private->substream->pcm->card->dev, - "DMA transmit error (controller=%u channel=%u irq=%u\n", - dma_private->controller_id, - dma_private->channel_id, irq); - fsl_dma_abort_stream(dma_private->substream); + dev_err(dev, "dma transmit error\n"); + fsl_dma_abort_stream(substream); sr2 |= CCSR_DMA_SR_TE; ret = IRQ_HANDLED; } @@ -235,11 +225,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) ret = IRQ_HANDLED; if (sr & CCSR_DMA_SR_PE) { - dev_err(dma_private->substream->pcm->card->dev, - "DMA%u programming error (channel=%u irq=%u)\n", - dma_private->controller_id, - dma_private->channel_id, irq); - fsl_dma_abort_stream(dma_private->substream); + dev_err(dev, "dma programming error\n"); + fsl_dma_abort_stream(substream); sr2 |= CCSR_DMA_SR_PE; ret = IRQ_HANDLED; } @@ -253,8 +240,6 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) ret = IRQ_HANDLED; if (sr & CCSR_DMA_SR_EOSI) { - struct snd_pcm_substream *substream = dma_private->substream; - /* Tell ALSA we completed a period. */ snd_pcm_period_elapsed(substream); @@ -305,10 +290,8 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, fsl_dma_hardware.buffer_bytes_max, &pcm->streams[0].substream->dma_buffer); if (ret) { - dev_err(card->dev, - "Can't allocate playback DMA buffer (size=%u)\n", - fsl_dma_hardware.buffer_bytes_max); - return -ENOMEM; + dev_err(card->dev, "can't allocate playback dma buffer\n"); + return ret; } ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, @@ -316,10 +299,8 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, &pcm->streams[1].substream->dma_buffer); if (ret) { snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); - dev_err(card->dev, - "Can't allocate capture DMA buffer (size=%u)\n", - fsl_dma_hardware.buffer_bytes_max); - return -ENOMEM; + dev_err(card->dev, "can't allocate capture dma buffer\n"); + return ret; } return 0; @@ -390,6 +371,10 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, static int fsl_dma_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; + struct dma_object *dma = + container_of(rtd->platform->driver, struct dma_object, dai); struct fsl_dma_private *dma_private; struct ccsr_dma_channel __iomem *dma_channel; dma_addr_t ld_buf_phys; @@ -407,52 +392,44 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) { - dev_err(substream->pcm->card->dev, "invalid buffer size\n"); + dev_err(dev, "invalid buffer size\n"); return ret; } channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; - if (dma_global_data.assigned[channel]) { - dev_err(substream->pcm->card->dev, - "DMA channel already assigned\n"); + if (dma->assigned) { + dev_err(dev, "dma channel already assigned\n"); return -EBUSY; } - dma_private = dma_alloc_coherent(substream->pcm->card->dev, - sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL); + dma_private = dma_alloc_coherent(dev, sizeof(struct fsl_dma_private), + &ld_buf_phys, GFP_KERNEL); if (!dma_private) { - dev_err(substream->pcm->card->dev, - "can't allocate DMA private data\n"); + dev_err(dev, "can't allocate dma private data\n"); return -ENOMEM; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dma_private->ssi_sxx_phys = dma_global_data.ssi_stx_phys; + dma_private->ssi_sxx_phys = dma->ssi_stx_phys; else - dma_private->ssi_sxx_phys = dma_global_data.ssi_srx_phys; + dma_private->ssi_sxx_phys = dma->ssi_srx_phys; - dma_private->dma_channel = dma_global_data.dma_channel[channel]; - dma_private->irq = dma_global_data.irq[channel]; + dma_private->dma_channel = dma->channel; + dma_private->irq = dma->irq; dma_private->substream = substream; dma_private->ld_buf_phys = ld_buf_phys; dma_private->dma_buf_phys = substream->dma_buffer.addr; - /* We only support one DMA controller for now */ - dma_private->controller_id = 0; - dma_private->channel_id = channel; - ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private); if (ret) { - dev_err(substream->pcm->card->dev, - "can't register ISR for IRQ %u (ret=%i)\n", + dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n", dma_private->irq, ret); - dma_free_coherent(substream->pcm->card->dev, - sizeof(struct fsl_dma_private), + dma_free_coherent(dev, sizeof(struct fsl_dma_private), dma_private, dma_private->ld_buf_phys); return ret; } - dma_global_data.assigned[channel] = 1; + dma->assigned = 1; snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware); @@ -546,6 +523,8 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_dma_private *dma_private = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; /* Number of bits per sample */ unsigned int sample_size = @@ -606,8 +585,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, break; default: /* We should never get here */ - dev_err(substream->pcm->card->dev, - "unsupported sample size %u\n", sample_size); + dev_err(dev, "unsupported sample size %u\n", sample_size); return -EINVAL; } @@ -689,6 +667,8 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_dma_private *dma_private = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; dma_addr_t position; snd_pcm_uframes_t frames; @@ -710,8 +690,7 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream) if ((position < dma_private->dma_buf_phys) || (position > dma_private->dma_buf_end)) { - dev_err(substream->pcm->card->dev, - "dma pointer is out of range, halting stream\n"); + dev_err(dev, "dma pointer is out of range, halting stream\n"); return SNDRV_PCM_POS_XRUN; } @@ -772,26 +751,28 @@ static int fsl_dma_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_dma_private *dma_private = runtime->private_data; - int dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; + struct dma_object *dma = + container_of(rtd->platform->driver, struct dma_object, dai); if (dma_private) { if (dma_private->irq) free_irq(dma_private->irq, dma_private); if (dma_private->ld_buf_phys) { - dma_unmap_single(substream->pcm->card->dev, - dma_private->ld_buf_phys, - sizeof(dma_private->link), DMA_TO_DEVICE); + dma_unmap_single(dev, dma_private->ld_buf_phys, + sizeof(dma_private->link), + DMA_TO_DEVICE); } /* Deallocate the fsl_dma_private structure */ - dma_free_coherent(substream->pcm->card->dev, - sizeof(struct fsl_dma_private), - dma_private, dma_private->ld_buf_phys); + dma_free_coherent(dev, sizeof(struct fsl_dma_private), + dma_private, dma_private->ld_buf_phys); substream->runtime->private_data = NULL; } - dma_global_data.assigned[dir] = 0; + dma->assigned = 0; return 0; } @@ -814,6 +795,40 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm) } } +/* List of DMA nodes that we've probed */ +static LIST_HEAD(dma_list); + +/** + * find_ssi_node -- returns the SSI node that points to his DMA channel node + * + * Although this DMA driver attempts to operate independently of the other + * devices, it still needs to determine some information about the SSI device + * that it's working with. Unfortunately, the device tree does not contain + * a pointer from the DMA channel node to the SSI node -- the pointer goes the + * other way. So we need to scan the device tree for SSI nodes until we find + * the one that points to the given DMA channel node. It's ugly, but at least + * it's contained in this one function. + */ +static struct device_node *find_ssi_node(struct device_node *dma_channel_np) +{ + struct device_node *ssi_np, *np; + + for_each_compatible_node(ssi_np, NULL, "fsl,mpc8610-ssi") { + /* Check each DMA phandle to see if it points to us. We + * assume that device_node pointers are a valid comparison. + */ + np = of_parse_phandle(ssi_np, "fsl,playback-dma", 0); + if (np == dma_channel_np) + return ssi_np; + + np = of_parse_phandle(ssi_np, "fsl,capture-dma", 0); + if (np == dma_channel_np) + return ssi_np; + } + + return NULL; +} + static struct snd_pcm_ops fsl_dma_ops = { .open = fsl_dma_open, .close = fsl_dma_close, @@ -823,59 +838,112 @@ static struct snd_pcm_ops fsl_dma_ops = { .pointer = fsl_dma_pointer, }; -struct snd_soc_platform fsl_soc_platform = { - .name = "fsl-dma", - .pcm_ops = &fsl_dma_ops, - .pcm_new = fsl_dma_new, - .pcm_free = fsl_dma_free_dma_buffers, -}; -EXPORT_SYMBOL_GPL(fsl_soc_platform); +static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, + const struct of_device_id *match) + { + struct dma_object *dma; + struct device_node *np = of_dev->dev.of_node; + struct device_node *ssi_np; + struct resource res; + int ret; -/** - * fsl_dma_configure: store the DMA parameters from the fabric driver. - * - * This function is called by the ASoC fabric driver to give us the DMA and - * SSI channel information. - * - * Unfortunately, ASoC V1 does make it possible to determine the DMA/SSI - * data when a substream is created, so for now we need to store this data - * into a global variable. This means that we can only support one DMA - * controller, and hence only one SSI. - */ -int fsl_dma_configure(struct fsl_dma_info *dma_info) + /* Find the SSI node that points to us. */ + ssi_np = find_ssi_node(np); + if (!ssi_np) { + dev_err(&of_dev->dev, "cannot find parent SSI node\n"); + return -ENODEV; + } + + ret = of_address_to_resource(ssi_np, 0, &res); + of_node_put(ssi_np); + if (ret) { + dev_err(&of_dev->dev, "could not determine device resources\n"); + return ret; + } + + dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL); + if (!dma) { + dev_err(&of_dev->dev, "could not allocate dma object\n"); + return -ENOMEM; + } + + strcpy(dma->path, np->full_name); + dma->dai.ops = &fsl_dma_ops; + dma->dai.pcm_new = fsl_dma_new; + dma->dai.pcm_free = fsl_dma_free_dma_buffers; + + /* Store the SSI-specific information that we need */ + dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0); + dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0); + + ret = snd_soc_register_platform(&of_dev->dev, &dma->dai); + if (ret) { + dev_err(&of_dev->dev, "could not register platform\n"); + kfree(dma); + return ret; + } + + dma->channel = of_iomap(np, 0); + dma->irq = irq_of_parse_and_map(np, 0); + list_add(&dma->list, &dma_list); + + return 0; +} + +static int __devexit fsl_soc_dma_remove(struct of_device *of_dev) { - static int initialized; + struct list_head *n, *ptr; + struct dma_object *dma; - /* We only support one DMA controller for now */ - if (initialized) - return 0; + list_for_each_safe(ptr, n, &dma_list) { + dma = list_entry(ptr, struct dma_object, list); + list_del_init(ptr); + + snd_soc_unregister_platform(&of_dev->dev); + iounmap(dma->channel); + irq_dispose_mapping(dma->irq); + kfree(dma); + } - dma_global_data.ssi_stx_phys = dma_info->ssi_stx_phys; - dma_global_data.ssi_srx_phys = dma_info->ssi_srx_phys; - dma_global_data.dma_channel[0] = dma_info->dma_channel[0]; - dma_global_data.dma_channel[1] = dma_info->dma_channel[1]; - dma_global_data.irq[0] = dma_info->dma_irq[0]; - dma_global_data.irq[1] = dma_info->dma_irq[1]; - dma_global_data.assigned[0] = 0; - dma_global_data.assigned[1] = 0; - - initialized = 1; - return 1; + return 0; } -EXPORT_SYMBOL_GPL(fsl_dma_configure); -static int __init fsl_soc_platform_init(void) +static const struct of_device_id fsl_soc_dma_ids[] = { + { .compatible = "fsl,ssi-dma-channel", }, + {} +}; +MODULE_DEVICE_TABLE(of, fsl_soc_dma_ids); + +static struct of_platform_driver fsl_soc_dma_driver = { + .driver = { + .name = "fsl-pcm-audio", + .owner = THIS_MODULE, + .of_match_table = fsl_soc_dma_ids, + }, + .probe = fsl_soc_dma_probe, + .remove = __devexit_p(fsl_soc_dma_remove), +}; + +static int __init fsl_soc_dma_init(void) { - return snd_soc_register_platform(&fsl_soc_platform); + pr_info("Freescale Elo DMA ASoC PCM Driver\n"); + + return of_register_platform_driver(&fsl_soc_dma_driver); } -module_init(fsl_soc_platform_init); -static void __exit fsl_soc_platform_exit(void) +static void __exit fsl_soc_dma_exit(void) { - snd_soc_unregister_platform(&fsl_soc_platform); + of_unregister_platform_driver(&fsl_soc_dma_driver); } -module_exit(fsl_soc_platform_exit); + +/* We want the DMA driver to be initialized before the SSI driver, so that + * when the SSI driver calls fsl_soc_dma_dai_from_node(), the DMA driver + * will already have been probed. The easiest way to do that is to make the + * __init function called via arch_initcall(). + */ +module_init(fsl_soc_dma_init); +module_exit(fsl_soc_dma_exit); MODULE_AUTHOR("Timur Tabi "); -MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module"); -MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/fsl_dma.h b/sound/soc/fsl/fsl_dma.h index 385d4a42603c..78fee97e8036 100644 --- a/sound/soc/fsl/fsl_dma.h +++ b/sound/soc/fsl/fsl_dma.h @@ -126,24 +126,4 @@ struct fsl_dma_link_descriptor { u8 res[4]; /* Reserved */ } __attribute__ ((aligned(32), packed)); -/* DMA information needed to create a snd_soc_dai object - * - * ssi_stx_phys: bus address of SSI STX register to use - * ssi_srx_phys: bus address of SSI SRX register to use - * dma[0]: points to the DMA channel to use for playback - * dma[1]: points to the DMA channel to use for capture - * dma_irq[0]: IRQ of the DMA channel to use for playback - * dma_irq[1]: IRQ of the DMA channel to use for capture - */ -struct fsl_dma_info { - dma_addr_t ssi_stx_phys; - dma_addr_t ssi_srx_phys; - struct ccsr_dma_channel __iomem *dma_channel[2]; - unsigned int dma_irq[2]; -}; - -extern struct snd_soc_platform fsl_soc_platform; - -int fsl_dma_configure(struct fsl_dma_info *dma_info); - #endif diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 762c1b8e8e4e..64f65910a7d7 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -3,10 +3,11 @@ * * Author: Timur Tabi * - * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed - * under the terms of the GNU General Public License version 2. This - * program is licensed "as is" without any warranty of any kind, whether - * express or implied. + * Copyright 2007-2010 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. */ #include @@ -15,6 +16,7 @@ #include #include #include +#include #include #include @@ -71,33 +73,31 @@ /** * fsl_ssi_private: per-SSI private data * - * @name: short name for this device ("SSI0", "SSI1", etc) * @ssi: pointer to the SSI's registers * @ssi_phys: physical address of the SSI registers * @irq: IRQ of this SSI * @first_stream: pointer to the stream that was opened first * @second_stream: pointer to second stream - * @dev: struct device pointer * @playback: the number of playback streams opened * @capture: the number of capture streams opened * @asynchronous: 0=synchronous mode, 1=asynchronous mode * @cpu_dai: the CPU DAI for this device * @dev_attr: the sysfs device attribute structure * @stats: SSI statistics + * @name: name for this device */ struct fsl_ssi_private { - char name[8]; struct ccsr_ssi __iomem *ssi; dma_addr_t ssi_phys; unsigned int irq; struct snd_pcm_substream *first_stream; struct snd_pcm_substream *second_stream; - struct device *dev; unsigned int playback; unsigned int capture; int asynchronous; - struct snd_soc_dai cpu_dai; + struct snd_soc_dai_driver cpu_dai_drv; struct device_attribute dev_attr; + struct platform_device *pdev; struct { unsigned int rfrc; @@ -122,6 +122,8 @@ struct fsl_ssi_private { unsigned int tfe1; unsigned int tfe0; } stats; + + char name[1]; }; /** @@ -280,7 +282,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; + struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); /* * If this is the first stream opened, then request the IRQ @@ -290,6 +292,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, struct ccsr_ssi __iomem *ssi = ssi_private->ssi; int ret; + /* The 'name' should not have any slashes in it. */ ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, ssi_private); if (ret < 0) { @@ -422,7 +425,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) { - struct fsl_ssi_private *ssi_private = cpu_dai->private_data; + struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); if (substream == ssi_private->first_stream) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi; @@ -458,7 +461,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; + struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); struct ccsr_ssi __iomem *ssi = ssi_private->ssi; switch (cmd) { @@ -497,7 +500,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; + struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ssi_private->playback--; @@ -523,56 +526,15 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, } } -/** - * fsl_ssi_set_sysclk: set the clock frequency and direction - * - * This function is called by the machine driver to tell us what the clock - * frequency and direction are. - * - * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN), - * and we don't care about the frequency. Return an error if the direction - * is not SND_SOC_CLOCK_IN. - * - * @clk_id: reserved, should be zero - * @freq: the frequency of the given clock ID, currently ignored - * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master) - */ -static int fsl_ssi_set_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, int dir) -{ - - return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; -} - -/** - * fsl_ssi_set_fmt: set the serial format. - * - * This function is called by the machine driver to tell us what serial - * format to use. - * - * Currently, we only support I2S mode. Return an error if the format is - * not SND_SOC_DAIFMT_I2S. - * - * @format: one of SND_SOC_DAIFMT_xxx - */ -static int fsl_ssi_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) -{ - return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; -} - -/** - * fsl_ssi_dai_template: template CPU DAI for the SSI - */ static struct snd_soc_dai_ops fsl_ssi_dai_ops = { .startup = fsl_ssi_startup, .hw_params = fsl_ssi_hw_params, .shutdown = fsl_ssi_shutdown, .trigger = fsl_ssi_trigger, - .set_sysclk = fsl_ssi_set_sysclk, - .set_fmt = fsl_ssi_set_fmt, }; -static struct snd_soc_dai fsl_ssi_dai_template = { +/* Template for the CPU dai driver structure */ +static struct snd_soc_dai_driver fsl_ssi_dai_template = { .playback = { /* The SSI does not support monaural audio. */ .channels_min = 2, @@ -640,95 +602,176 @@ static ssize_t fsl_sysfs_ssi_show(struct device *dev, } /** - * fsl_ssi_create_dai: create a snd_soc_dai structure - * - * This function is called by the machine driver to create a snd_soc_dai - * structure. The function creates an ssi_private object, which contains - * the snd_soc_dai. It also creates the sysfs statistics device. + * Make every character in a string lower-case */ -struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info) +static void make_lowercase(char *s) +{ + char *p = s; + char c; + + while ((c = *p)) { + if ((c >= 'A') && (c <= 'Z')) + *p = c + ('a' - 'A'); + p++; + } +} + +static int __devinit fsl_ssi_probe(struct of_device *of_dev, + const struct of_device_id *match) { - struct snd_soc_dai *fsl_ssi_dai; struct fsl_ssi_private *ssi_private; int ret = 0; struct device_attribute *dev_attr; + struct device_node *np = of_dev->dev.of_node; + const char *p, *sprop; + struct resource res; + char name[64]; - ssi_private = kzalloc(sizeof(struct fsl_ssi_private), GFP_KERNEL); + /* We are only interested in SSIs with a codec phandle in them, so let's + * make sure this SSI has one. + */ + if (!of_get_property(np, "codec-handle", NULL)) + return -ENODEV; + + /* We only support the SSI in "I2S Slave" mode */ + sprop = of_get_property(np, "fsl,mode", NULL); + if (!sprop || strcmp(sprop, "i2s-slave")) { + dev_notice(&of_dev->dev, "mode %s is unsupported\n", sprop); + return -ENODEV; + } + + /* The DAI name is the last part of the full name of the node. */ + p = strrchr(np->full_name, '/') + 1; + ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p), + GFP_KERNEL); if (!ssi_private) { - dev_err(ssi_info->dev, "could not allocate DAI object\n"); - return NULL; + dev_err(&of_dev->dev, "could not allocate DAI object\n"); + return -ENOMEM; } - memcpy(&ssi_private->cpu_dai, &fsl_ssi_dai_template, - sizeof(struct snd_soc_dai)); - fsl_ssi_dai = &ssi_private->cpu_dai; - dev_attr = &ssi_private->dev_attr; + strcpy(ssi_private->name, p); - sprintf(ssi_private->name, "ssi%u", (u8) ssi_info->id); - ssi_private->ssi = ssi_info->ssi; - ssi_private->ssi_phys = ssi_info->ssi_phys; - ssi_private->irq = ssi_info->irq; - ssi_private->dev = ssi_info->dev; - ssi_private->asynchronous = ssi_info->asynchronous; + /* Initialize this copy of the CPU DAI driver structure */ + memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, + sizeof(fsl_ssi_dai_template)); + ssi_private->cpu_dai_drv.name = ssi_private->name; + + /* Get the addresses and IRQ */ + ret = of_address_to_resource(np, 0, &res); + if (ret) { + dev_err(&of_dev->dev, "could not determine device resources\n"); + kfree(ssi_private); + return ret; + } + ssi_private->ssi = ioremap(res.start, 1 + res.end - res.start); + ssi_private->ssi_phys = res.start; + ssi_private->irq = irq_of_parse_and_map(np, 0); - dev_set_drvdata(ssi_private->dev, fsl_ssi_dai); + /* Are the RX and the TX clocks locked? */ + if (of_find_property(np, "fsl,ssi-asynchronous", NULL)) + ssi_private->asynchronous = 1; + else + ssi_private->cpu_dai_drv.symmetric_rates = 1; /* Initialize the the device_attribute structure */ - dev_attr->attr.name = "ssi-stats"; + dev_attr = &ssi_private->dev_attr; + dev_attr->attr.name = "statistics"; dev_attr->attr.mode = S_IRUGO; dev_attr->show = fsl_sysfs_ssi_show; - ret = device_create_file(ssi_private->dev, dev_attr); + ret = device_create_file(&of_dev->dev, dev_attr); if (ret) { - dev_err(ssi_info->dev, "could not create sysfs %s file\n", + dev_err(&of_dev->dev, "could not create sysfs %s file\n", ssi_private->dev_attr.attr.name); - kfree(fsl_ssi_dai); - return NULL; + kfree(ssi_private); + return ret; } - fsl_ssi_dai->private_data = ssi_private; - fsl_ssi_dai->name = ssi_private->name; - fsl_ssi_dai->id = ssi_info->id; - fsl_ssi_dai->dev = ssi_info->dev; - fsl_ssi_dai->symmetric_rates = 1; + /* Register with ASoC */ + dev_set_drvdata(&of_dev->dev, ssi_private); - ret = snd_soc_register_dai(fsl_ssi_dai); + ret = snd_soc_register_dai(&of_dev->dev, &ssi_private->cpu_dai_drv); if (ret != 0) { - dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret); - kfree(fsl_ssi_dai); - return NULL; + dev_err(&of_dev->dev, "failed to register DAI: %d\n", ret); + kfree(ssi_private); + return ret; + } + + /* Trigger the machine driver's probe function. The platform driver + * name of the machine driver is taken from the /model property of the + * device tree. We also pass the address of the CPU DAI driver + * structure. + */ + sprop = of_get_property(of_find_node_by_path("/"), "model", NULL); + /* Sometimes the model name has a "fsl," prefix, so we strip that. */ + p = strrchr(sprop, ','); + if (p) + sprop = p + 1; + snprintf(name, sizeof(name), "snd-soc-%s", sprop); + make_lowercase(name); + + ssi_private->pdev = + platform_device_register_data(&of_dev->dev, name, 0, NULL, 0); + if (IS_ERR(ssi_private->pdev)) { + ret = PTR_ERR(ssi_private->pdev); + dev_err(&of_dev->dev, "failed to register platform: %d\n", ret); + kfree(ssi_private); + return ret; } - return fsl_ssi_dai; + return 0; } -EXPORT_SYMBOL_GPL(fsl_ssi_create_dai); /** * fsl_ssi_destroy_dai: destroy the snd_soc_dai object * - * This function undoes the operations of fsl_ssi_create_dai() + * This function undoes the operations of fsl_ssi_probe() */ -void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai) +static int fsl_ssi_remove(struct of_device *of_dev) { - struct fsl_ssi_private *ssi_private = - container_of(fsl_ssi_dai, struct fsl_ssi_private, cpu_dai); + struct fsl_ssi_private *ssi_private = dev_get_drvdata(&of_dev->dev); - device_remove_file(ssi_private->dev, &ssi_private->dev_attr); - - snd_soc_unregister_dai(&ssi_private->cpu_dai); + platform_device_unregister(ssi_private->pdev); + snd_soc_unregister_dai(&of_dev->dev); + device_remove_file(&of_dev->dev, &ssi_private->dev_attr); kfree(ssi_private); + dev_set_drvdata(&of_dev->dev, NULL); + + return 0; } -EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai); + +static const struct of_device_id fsl_ssi_ids[] = { + { .compatible = "fsl,mpc8610-ssi", }, + {} +}; +MODULE_DEVICE_TABLE(of, fsl_ssi_ids); + +static struct of_platform_driver fsl_ssi_driver = { + .driver = { + .name = "fsl-ssi-dai", + .owner = THIS_MODULE, + .of_match_table = fsl_ssi_ids, + }, + .probe = fsl_ssi_probe, + .remove = fsl_ssi_remove, +}; static int __init fsl_ssi_init(void) { printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n"); - return 0; + return of_register_platform_driver(&fsl_ssi_driver); +} + +static void __exit fsl_ssi_exit(void) +{ + of_unregister_platform_driver(&fsl_ssi_driver); } + module_init(fsl_ssi_init); +module_exit(fsl_ssi_exit); MODULE_AUTHOR("Timur Tabi "); MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h index eade01feaab6..217300029b5b 100644 --- a/sound/soc/fsl/fsl_ssi.h +++ b/sound/soc/fsl/fsl_ssi.h @@ -196,31 +196,5 @@ struct ccsr_ssi { #define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT) #define CCSR_SSI_SOR_SYNRST 0x00000001 -/* Instantiation data for an SSI interface - * - * This structure contains all the information that the the SSI driver needs - * to instantiate an SSI interface with ALSA. The machine driver should - * create this structure, fill it in, call fsl_ssi_create_dai(), and then - * delete the structure. - * - * id: which SSI this is (0, 1, etc. ) - * ssi: pointer to the SSI's registers - * ssi_phys: physical address of the SSI registers - * irq: IRQ of this SSI - * dev: struct device, used to create the sysfs statistics file - * asynchronous: 0=synchronous mode, 1=asynchronous mode -*/ -struct fsl_ssi_info { - unsigned int id; - struct ccsr_ssi __iomem *ssi; - dma_addr_t ssi_phys; - unsigned int irq; - struct device *dev; - int asynchronous; -}; - -struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info); -void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai); - #endif diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 1d4e7164e80a..dce6b551cd78 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include @@ -107,7 +109,7 @@ static int psc_dma_hw_free(struct snd_pcm_substream *substream) static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); struct snd_pcm_runtime *runtime = substream->runtime; struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; @@ -212,7 +214,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); struct psc_dma_stream *s; int rc; @@ -239,7 +241,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream) static int psc_dma_close(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); struct psc_dma_stream *s; dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream); @@ -264,7 +266,7 @@ static snd_pcm_uframes_t psc_dma_pointer(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); struct psc_dma_stream *s; dma_addr_t count; @@ -302,11 +304,11 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { struct snd_soc_pcm_runtime *rtd = pcm->private_data; - struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); size_t size = psc_dma_hardware.buffer_bytes_max; int rc = 0; - dev_dbg(rtd->socdev->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n", + dev_dbg(rtd->platform->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n", card, dai, pcm); if (!card->dev->dma_mask) @@ -328,8 +330,8 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai, goto capture_alloc_err; } - if (rtd->socdev->card->codec->ac97) - rtd->socdev->card->codec->ac97->private_data = psc_dma; + if (rtd->codec->ac97) + rtd->codec->ac97->private_data = psc_dma; return 0; @@ -349,7 +351,7 @@ static void psc_dma_free(struct snd_pcm *pcm) struct snd_pcm_substream *substream; int stream; - dev_dbg(rtd->socdev->dev, "psc_dma_free(pcm=%p)\n", pcm); + dev_dbg(rtd->platform->dev, "psc_dma_free(pcm=%p)\n", pcm); for (stream = 0; stream < 2; stream++) { substream = pcm->streams[stream].substream; @@ -361,15 +363,14 @@ static void psc_dma_free(struct snd_pcm *pcm) } } -struct snd_soc_platform mpc5200_audio_dma_platform = { - .name = "mpc5200-psc-audio", - .pcm_ops = &psc_dma_ops, +static struct snd_soc_platform_driver mpc5200_audio_dma_platform = { + .ops = &psc_dma_ops, .pcm_new = &psc_dma_new, .pcm_free = &psc_dma_free, }; -EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform); -int mpc5200_audio_dma_create(struct of_device *op) +static int mpc5200_hpcd_probe(struct of_device *op, + const struct of_device_id *match) { phys_addr_t fifo; struct psc_dma *psc_dma; @@ -475,7 +476,7 @@ int mpc5200_audio_dma_create(struct of_device *op) dev_set_drvdata(&op->dev, psc_dma); /* Tell the ASoC OF helpers about it */ - return snd_soc_register_platform(&mpc5200_audio_dma_platform); + return snd_soc_register_platform(&op->dev, &mpc5200_audio_dma_platform); out_irq: free_irq(psc_dma->irq, psc_dma); free_irq(psc_dma->capture.irq, &psc_dma->capture); @@ -486,15 +487,14 @@ out_unmap: iounmap(regs); return ret; } -EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); -int mpc5200_audio_dma_destroy(struct of_device *op) +static int mpc5200_hpcd_remove(struct of_device *op) { struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n"); - snd_soc_unregister_platform(&mpc5200_audio_dma_platform); + snd_soc_unregister_platform(&op->dev); bcom_gen_bd_rx_release(psc_dma->capture.bcom_task); bcom_gen_bd_tx_release(psc_dma->playback.bcom_task); @@ -510,7 +510,35 @@ int mpc5200_audio_dma_destroy(struct of_device *op) return 0; } -EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy); + +static struct of_device_id mpc5200_hpcd_match[] = { + { + .compatible = "fsl,mpc5200-pcm", + }, + {} +}; +MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match); + +static struct of_platform_driver mpc5200_hpcd_of_driver = { + .owner = THIS_MODULE, + .name = "mpc5200-pcm-audio", + .match_table = mpc5200_hpcd_match, + .probe = mpc5200_hpcd_probe, + .remove = mpc5200_hpcd_remove, +}; + +static int __init mpc5200_hpcd_init(void) +{ + return of_register_platform_driver(&mpc5200_hpcd_of_driver); +} + +static void __exit mpc5200_hpcd_exit(void) +{ + of_unregister_platform_driver(&mpc5200_hpcd_of_driver); +} + +module_init(mpc5200_hpcd_init); +module_exit(mpc5200_hpcd_exit); MODULE_AUTHOR("Grant Likely "); MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index 22208b373fb9..7472531bc2a4 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h @@ -81,9 +81,4 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) return &psc_dma->playback; } -int mpc5200_audio_dma_create(struct of_device *op); -int mpc5200_audio_dma_destroy(struct of_device *op); - -extern struct snd_soc_platform mpc5200_audio_dma_platform; - #endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index e2ee220bfb7e..11706c128c08 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -129,7 +129,7 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { - struct psc_dma *psc_dma = cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" @@ -152,7 +152,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { - struct psc_dma *psc_dma = cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream); @@ -167,8 +167,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream, static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(dai); struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); switch (cmd) { @@ -193,10 +192,9 @@ static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd, return 0; } -static int psc_ac97_probe(struct platform_device *pdev, - struct snd_soc_dai *cpu_dai) +static int psc_ac97_probe(struct snd_soc_dai *cpu_dai) { - struct psc_dma *psc_dma = cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; /* Go */ @@ -223,9 +221,8 @@ static struct snd_soc_dai_ops psc_ac97_digital_ops = { .hw_params = psc_ac97_hw_digital_params, }; -struct snd_soc_dai psc_ac97_dai[] = { +static struct snd_soc_dai_driver psc_ac97_dai[] = { { - .name = "AC97", .ac97_control = 1, .probe = psc_ac97_probe, .playback = { @@ -243,7 +240,6 @@ struct snd_soc_dai psc_ac97_dai[] = { .ops = &psc_ac97_analog_ops, }, { - .name = "SPDIF", .ac97_control = 1, .playback = { .channels_min = 1, @@ -254,7 +250,6 @@ struct snd_soc_dai psc_ac97_dai[] = { }, .ops = &psc_ac97_digital_ops, } }; -EXPORT_SYMBOL_GPL(psc_ac97_dai); @@ -266,18 +261,11 @@ EXPORT_SYMBOL_GPL(psc_ac97_dai); static int __devinit psc_ac97_of_probe(struct of_device *op, const struct of_device_id *match) { - int rc, i; + int rc; struct snd_ac97 ac97; struct mpc52xx_psc __iomem *regs; - rc = mpc5200_audio_dma_create(op); - if (rc != 0) - return rc; - - for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++) - psc_ac97_dai[i].dev = &op->dev; - - rc = snd_soc_register_dais(psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); + rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); if (rc != 0) { dev_err(&op->dev, "Failed to register DAI\n"); return rc; @@ -287,9 +275,6 @@ static int __devinit psc_ac97_of_probe(struct of_device *op, regs = psc_dma->psc_regs; ac97.private_data = psc_dma; - for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++) - psc_ac97_dai[i].private_data = psc_dma; - psc_dma->imr = 0; out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); @@ -305,7 +290,8 @@ static int __devinit psc_ac97_of_probe(struct of_device *op, static int __devexit psc_ac97_of_remove(struct of_device *op) { - return mpc5200_audio_dma_destroy(op); + snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai)); + return 0; } /* Match table for of_platform binding */ diff --git a/sound/soc/fsl/mpc5200_psc_ac97.h b/sound/soc/fsl/mpc5200_psc_ac97.h index 4bc18c35c369..e881e784b270 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.h +++ b/sound/soc/fsl/mpc5200_psc_ac97.h @@ -7,8 +7,6 @@ #ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ #define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ -extern struct snd_soc_dai psc_ac97_dai[]; - #define MPC5200_AC97_NORMAL 0 #define MPC5200_AC97_SPDIF 1 diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 676841cbae98..5b9f2c73f031 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -40,7 +40,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); u32 mode; dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" @@ -88,7 +88,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream, static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct psc_dma *psc_dma = cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n", cpu_dai, dir); return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; @@ -107,7 +107,7 @@ static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, */ static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) { - struct psc_dma *psc_dma = cpu_dai->private_data; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n", cpu_dai, format); return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; @@ -129,8 +129,7 @@ static struct snd_soc_dai_ops psc_i2s_dai_ops = { .set_fmt = psc_i2s_set_fmt, }; -struct snd_soc_dai psc_i2s_dai[] = {{ - .name = "I2S", +static struct snd_soc_dai_driver psc_i2s_dai[] = {{ .playback = { .channels_min = 2, .channels_max = 2, @@ -145,7 +144,6 @@ struct snd_soc_dai psc_i2s_dai[] = {{ }, .ops = &psc_i2s_dai_ops, } }; -EXPORT_SYMBOL_GPL(psc_i2s_dai); /* --------------------------------------------------------------------- * OF platform bus binding code: @@ -159,11 +157,7 @@ static int __devinit psc_i2s_of_probe(struct of_device *op, struct psc_dma *psc_dma; struct mpc52xx_psc __iomem *regs; - rc = mpc5200_audio_dma_create(op); - if (rc != 0) - return rc; - - rc = snd_soc_register_dais(psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); + rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); if (rc != 0) { pr_err("Failed to register DAI\n"); return 0; @@ -207,7 +201,8 @@ static int __devinit psc_i2s_of_probe(struct of_device *op, static int __devexit psc_i2s_of_remove(struct of_device *op) { - return mpc5200_audio_dma_destroy(op); + snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai)); + return 0; } /* Match table for of_platform binding */ diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 6a2764ee8203..5ba823213abe 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -1,85 +1,96 @@ /** - * Freescale MPC8610HPCD ALSA SoC Fabric driver + * Freescale MPC8610HPCD ALSA SoC Machine driver * * Author: Timur Tabi * - * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed - * under the terms of the GNU General Public License version 2. This - * program is licensed "as is" without any warranty of any kind, whether - * express or implied. + * Copyright 2007-2010 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. */ -#include #include #include #include -#include #include #include -#include "../codecs/cs4270.h" #include "fsl_dma.h" #include "fsl_ssi.h" +/* There's only one global utilities register */ +static phys_addr_t guts_phys; + +#define DAI_NAME_SIZE 32 + /** - * mpc8610_hpcd_data: fabric-specific ASoC device data + * mpc8610_hpcd_data: machine-specific ASoC device data * * This structure contains data for a single sound platform device on an * MPC8610 HPCD. Some of the data is taken from the device tree. */ struct mpc8610_hpcd_data { - struct snd_soc_device sound_devdata; - struct snd_soc_dai_link dai; - struct snd_soc_card machine; + struct snd_soc_dai_link dai[2]; + struct snd_soc_card card; unsigned int dai_format; unsigned int codec_clk_direction; unsigned int cpu_clk_direction; unsigned int clk_frequency; - struct ccsr_guts __iomem *guts; - struct ccsr_ssi __iomem *ssi; - unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */ - unsigned int ssi_irq; - unsigned int dma_id; /* 0 = DMA1, 1 = DMA2, etc */ - unsigned int dma_irq[2]; - struct ccsr_dma_channel __iomem *dma[2]; + unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */ + unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */ unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/ + char codec_dai_name[DAI_NAME_SIZE]; + char codec_name[DAI_NAME_SIZE]; + char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */ }; /** - * mpc8610_hpcd_machine_probe: initalize the board + * mpc8610_hpcd_machine_probe: initialize the board * - * This function is called when platform_device_add() is called. It is used - * to initialize the board-specific hardware. + * This function is used to initialize the board-specific hardware. * * Here we program the DMACR and PMUXCR registers. */ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device) { + struct snd_soc_card *card = platform_get_drvdata(sound_device); struct mpc8610_hpcd_data *machine_data = - sound_device->dev.platform_data; + container_of(card, struct mpc8610_hpcd_data, card); + struct ccsr_guts __iomem *guts; - /* Program the signal routing between the SSI and the DMA */ - guts_set_dmacr(machine_data->guts, machine_data->dma_id, - machine_data->dma_channel_id[0], CCSR_GUTS_DMACR_DEV_SSI); - guts_set_dmacr(machine_data->guts, machine_data->dma_id, - machine_data->dma_channel_id[1], CCSR_GUTS_DMACR_DEV_SSI); + guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); + if (!guts) { + dev_err(card->dev, "could not map global utilities\n"); + return -ENOMEM; + } - guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, - machine_data->dma_channel_id[0], 0); - guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, - machine_data->dma_channel_id[1], 0); + /* Program the signal routing between the SSI and the DMA */ + guts_set_dmacr(guts, machine_data->dma_id[0], + machine_data->dma_channel_id[0], + CCSR_GUTS_DMACR_DEV_SSI); + guts_set_dmacr(guts, machine_data->dma_id[1], + machine_data->dma_channel_id[1], + CCSR_GUTS_DMACR_DEV_SSI); + + guts_set_pmuxcr_dma(guts, machine_data->dma_id[0], + machine_data->dma_channel_id[0], 0); + guts_set_pmuxcr_dma(guts, machine_data->dma_id[1], + machine_data->dma_channel_id[1], 0); switch (machine_data->ssi_id) { case 0: - clrsetbits_be32(&machine_data->guts->pmuxcr, + clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_SSI); break; case 1: - clrsetbits_be32(&machine_data->guts->pmuxcr, + clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_SSI); break; } + iounmap(guts); + return 0; } @@ -93,38 +104,15 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device) static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct mpc8610_hpcd_data *machine_data = - rtd->socdev->dev->platform_data; + container_of(rtd->card, struct mpc8610_hpcd_data, card); + struct device *dev = rtd->card->dev; int ret = 0; - /* Tell the CPU driver what the serial protocol is. */ - ret = snd_soc_dai_set_fmt(cpu_dai, machine_data->dai_format); - if (ret < 0) { - dev_err(substream->pcm->card->dev, - "could not set CPU driver audio format\n"); - return ret; - } - /* Tell the codec driver what the serial protocol is. */ - ret = snd_soc_dai_set_fmt(codec_dai, machine_data->dai_format); + ret = snd_soc_dai_set_fmt(rtd->codec_dai, machine_data->dai_format); if (ret < 0) { - dev_err(substream->pcm->card->dev, - "could not set codec driver audio format\n"); - return ret; - } - - /* - * Tell the CPU driver what the clock frequency is, and whether it's a - * slave or master. - */ - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, - machine_data->clk_frequency, - machine_data->cpu_clk_direction); - if (ret < 0) { - dev_err(substream->pcm->card->dev, - "could not set CPU driver clock parameters\n"); + dev_err(dev, "could not set codec driver audio format\n"); return ret; } @@ -132,12 +120,11 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) * Tell the codec driver what the MCLK frequency is, and whether it's * a slave or master. */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, - machine_data->clk_frequency, - machine_data->codec_clk_direction); + ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, + machine_data->clk_frequency, + machine_data->codec_clk_direction); if (ret < 0) { - dev_err(substream->pcm->card->dev, - "could not set codec driver clock params\n"); + dev_err(dev, "could not set codec driver clock params\n"); return ret; } @@ -150,116 +137,254 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) * This function is called to remove the sound device for one SSI. We * de-program the DMACR and PMUXCR register. */ -int mpc8610_hpcd_machine_remove(struct platform_device *sound_device) +static int mpc8610_hpcd_machine_remove(struct platform_device *sound_device) { + struct snd_soc_card *card = platform_get_drvdata(sound_device); struct mpc8610_hpcd_data *machine_data = - sound_device->dev.platform_data; + container_of(card, struct mpc8610_hpcd_data, card); + struct ccsr_guts __iomem *guts; + + guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); + if (!guts) { + dev_err(card->dev, "could not map global utilities\n"); + return -ENOMEM; + } /* Restore the signal routing */ - guts_set_dmacr(machine_data->guts, machine_data->dma_id, - machine_data->dma_channel_id[0], 0); - guts_set_dmacr(machine_data->guts, machine_data->dma_id, - machine_data->dma_channel_id[1], 0); + guts_set_dmacr(guts, machine_data->dma_id[0], + machine_data->dma_channel_id[0], 0); + guts_set_dmacr(guts, machine_data->dma_id[1], + machine_data->dma_channel_id[1], 0); switch (machine_data->ssi_id) { case 0: - clrsetbits_be32(&machine_data->guts->pmuxcr, + clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_LA); break; case 1: - clrsetbits_be32(&machine_data->guts->pmuxcr, + clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA); break; } + iounmap(guts); + return 0; } /** - * mpc8610_hpcd_ops: ASoC fabric driver operations + * mpc8610_hpcd_ops: ASoC machine driver operations */ static struct snd_soc_ops mpc8610_hpcd_ops = { .startup = mpc8610_hpcd_startup, }; /** - * mpc8610_hpcd_probe: OF probe function for the fabric driver + * get_node_by_phandle_name - get a node by its phandle name * - * This function gets called when an SSI node is found in the device tree. + * This function takes a node, the name of a property in that node, and a + * compatible string. Assuming the property is a phandle to another node, + * it returns that node, (optionally) if that node is compatible. * - * Although this is a fabric driver, the SSI node is the "master" node with - * respect to audio hardware connections. Therefore, we create a new ASoC - * device for each new SSI node that has a codec attached. + * If the property is not a phandle, or the node it points to is not compatible + * with the specific string, then NULL is returned. + */ +static struct device_node *get_node_by_phandle_name(struct device_node *np, + const char *name, + const char *compatible) +{ + const phandle *ph; + int len; + + ph = of_get_property(np, name, &len); + if (!ph || (len != sizeof(phandle))) + return NULL; + + np = of_find_node_by_phandle(*ph); + if (!np) + return NULL; + + if (compatible && !of_device_is_compatible(np, compatible)) { + of_node_put(np); + return NULL; + } + + return np; +} + +/** + * get_parent_cell_index -- return the cell-index of the parent of a node * - * FIXME: Currently, we only support one DMA controller, so if there are - * multiple SSI nodes with codecs, only the first will be supported. + * Return the value of the cell-index property of the parent of the given + * node. This is used for DMA channel nodes that need to know the DMA ID + * of the controller they are on. + */ +static int get_parent_cell_index(struct device_node *np) +{ + struct device_node *parent = of_get_parent(np); + const u32 *iprop; + + if (!parent) + return -1; + + iprop = of_get_property(parent, "cell-index", NULL); + of_node_put(parent); + + if (!iprop) + return -1; + + return *iprop; +} + +/** + * codec_node_dev_name - determine the dev_name for a codec node * - * FIXME: Even if we did support multiple DMA controllers, we have no - * mechanism for assigning DMA controllers and channels to the individual - * SSI devices. We also probably aren't compatible with the generic Elo DMA - * device driver. + * This function determines the dev_name for an I2C node. This is the name + * that would be returned by dev_name() if this device_node were part of a + * 'struct device' It's ugly and hackish, but it works. + * + * The dev_name for such devices include the bus number and I2C address. For + * example, "cs4270-codec.0-004f". */ -static int mpc8610_hpcd_probe(struct of_device *ofdev, - const struct of_device_id *match) +static int codec_node_dev_name(struct device_node *np, char *buf, size_t len) { - struct device_node *np = ofdev->dev.of_node; - struct device_node *codec_np = NULL; - struct device_node *guts_np = NULL; - struct device_node *dma_np = NULL; - struct device_node *dma_channel_np = NULL; - const phandle *codec_ph; - const char *sprop; const u32 *iprop; + int bus, addr; + char temp[DAI_NAME_SIZE]; + + of_modalias_node(np, temp, DAI_NAME_SIZE); + + iprop = of_get_property(np, "reg", NULL); + if (!iprop) + return -EINVAL; + + addr = *iprop; + + bus = get_parent_cell_index(np); + if (bus < 0) + return bus; + + snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr); + + return 0; +} + +static int get_dma_channel(struct device_node *ssi_np, + const char *compatible, + struct snd_soc_dai_link *dai, + unsigned int *dma_channel_id, + unsigned int *dma_id) +{ struct resource res; + struct device_node *dma_channel_np; + const u32 *iprop; + int ret; + + dma_channel_np = get_node_by_phandle_name(ssi_np, compatible, + "fsl,ssi-dma-channel"); + if (!dma_channel_np) + return -EINVAL; + + /* Determine the dev_name for the device_node. This code mimics the + * behavior of of_device_make_bus_id(). We need this because ASoC uses + * the dev_name() of the device to match the platform (DMA) device with + * the CPU (SSI) device. It's all ugly and hackish, but it works (for + * now). + * + * dai->platform name should already point to an allocated buffer. + */ + ret = of_address_to_resource(dma_channel_np, 0, &res); + if (ret) + return ret; + snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", + (unsigned long long) res.start, dma_channel_np->name); + + iprop = of_get_property(dma_channel_np, "cell-index", NULL); + if (!iprop) { + of_node_put(dma_channel_np); + return -EINVAL; + } + + *dma_channel_id = *iprop; + *dma_id = get_parent_cell_index(dma_channel_np); + of_node_put(dma_channel_np); + + return 0; +} + +/** + * mpc8610_hpcd_probe: platform probe function for the machine driver + * + * Although this is a machine driver, the SSI node is the "master" node with + * respect to audio hardware connections. Therefore, we create a new ASoC + * device for each new SSI node that has a codec attached. + */ +static int mpc8610_hpcd_probe(struct platform_device *pdev) +{ + struct device *dev = pdev->dev.parent; + /* of_dev is the OF device for the SSI node that probed us */ + struct of_device *of_dev = container_of(dev, struct of_device, dev); + struct device_node *np = of_dev->dev.of_node; + struct device_node *codec_np = NULL; struct platform_device *sound_device = NULL; struct mpc8610_hpcd_data *machine_data; - struct fsl_ssi_info ssi_info; - struct fsl_dma_info dma_info; int ret = -ENODEV; - unsigned int playback_dma_channel; - unsigned int capture_dma_channel; + const char *sprop; + const u32 *iprop; + + /* We are only interested in SSIs with a codec phandle in them, + * so let's make sure this SSI has one. The MPC8610 HPCD only + * knows about the CS4270 codec, so reject anything else. + */ + codec_np = get_node_by_phandle_name(np, "codec-handle", + "cirrus,cs4270"); + if (!codec_np) { + dev_err(dev, "invalid codec node\n"); + return -EINVAL; + } machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL); if (!machine_data) return -ENOMEM; - memset(&ssi_info, 0, sizeof(ssi_info)); - memset(&dma_info, 0, sizeof(dma_info)); + machine_data->dai[0].cpu_dai_name = dev_name(&of_dev->dev); + machine_data->dai[0].ops = &mpc8610_hpcd_ops; - ssi_info.dev = &ofdev->dev; - - /* - * We are only interested in SSIs with a codec phandle in them, so let's - * make sure this SSI has one. - */ - codec_ph = of_get_property(np, "codec-handle", NULL); - if (!codec_ph) + /* Determine the codec name, it will be used as the codec DAI name */ + ret = codec_node_dev_name(codec_np, machine_data->codec_name, + DAI_NAME_SIZE); + if (ret) { + dev_err(&pdev->dev, "invalid codec node %s\n", + codec_np->full_name); + ret = -EINVAL; goto error; + } + machine_data->dai[0].codec_name = machine_data->codec_name; - codec_np = of_find_node_by_phandle(*codec_ph); - if (!codec_np) - goto error; + /* The DAI name from the codec (snd_soc_dai_driver.name) */ + machine_data->dai[0].codec_dai_name = "cs4270-hifi"; - /* The MPC8610 HPCD only knows about the CS4270 codec, so reject - anything else. */ - if (!of_device_is_compatible(codec_np, "cirrus,cs4270")) - goto error; + /* We register two DAIs per SSI, one for playback and the other for + * capture. Currently, we only support codecs that have one DAI for + * both playback and capture. + */ + memcpy(&machine_data->dai[1], &machine_data->dai[0], + sizeof(struct snd_soc_dai_link)); /* Get the device ID */ iprop = of_get_property(np, "cell-index", NULL); if (!iprop) { - dev_err(&ofdev->dev, "cell-index property not found\n"); + dev_err(&pdev->dev, "cell-index property not found\n"); ret = -EINVAL; goto error; } machine_data->ssi_id = *iprop; - ssi_info.id = *iprop; /* Get the serial format and clock direction. */ sprop = of_get_property(np, "fsl,mode", NULL); if (!sprop) { - dev_err(&ofdev->dev, "fsl,mode property not found\n"); + dev_err(&pdev->dev, "fsl,mode property not found\n"); ret = -EINVAL; goto error; } @@ -269,15 +394,14 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev, machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; - /* - * In i2s-slave mode, the codec has its own clock source, so we + /* In i2s-slave mode, the codec has its own clock source, so we * need to get the frequency from the device tree and pass it to * the codec driver. */ iprop = of_get_property(codec_np, "clock-frequency", NULL); if (!iprop || !*iprop) { - dev_err(&ofdev->dev, "codec bus-frequency property " - "is missing or invalid\n"); + dev_err(&pdev->dev, "codec bus-frequency " + "property is missing or invalid\n"); ret = -EINVAL; goto error; } @@ -311,317 +435,153 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev, machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else { - dev_err(&ofdev->dev, - "unrecognized fsl,mode property \"%s\"\n", sprop); + dev_err(&pdev->dev, + "unrecognized fsl,mode property '%s'\n", sprop); ret = -EINVAL; goto error; } if (!machine_data->clk_frequency) { - dev_err(&ofdev->dev, "unknown clock frequency\n"); + dev_err(&pdev->dev, "unknown clock frequency\n"); ret = -EINVAL; goto error; } - /* Read the SSI information from the device tree */ - ret = of_address_to_resource(np, 0, &res); + /* Find the playback DMA channel to use. */ + machine_data->dai[0].platform_name = machine_data->platform_name[0]; + ret = get_dma_channel(np, "fsl,playback-dma", &machine_data->dai[0], + &machine_data->dma_channel_id[0], + &machine_data->dma_id[0]); if (ret) { - dev_err(&ofdev->dev, "could not obtain SSI address\n"); - goto error; - } - if (!res.start) { - dev_err(&ofdev->dev, "invalid SSI address\n"); - goto error; - } - ssi_info.ssi_phys = res.start; - - machine_data->ssi = ioremap(ssi_info.ssi_phys, sizeof(struct ccsr_ssi)); - if (!machine_data->ssi) { - dev_err(&ofdev->dev, "could not map SSI address %x\n", - ssi_info.ssi_phys); - ret = -EINVAL; - goto error; - } - ssi_info.ssi = machine_data->ssi; - - - /* Get the IRQ of the SSI */ - machine_data->ssi_irq = irq_of_parse_and_map(np, 0); - if (!machine_data->ssi_irq) { - dev_err(&ofdev->dev, "could not get SSI IRQ\n"); - ret = -EINVAL; - goto error; - } - ssi_info.irq = machine_data->ssi_irq; - - /* Do we want to use asynchronous mode? */ - ssi_info.asynchronous = - of_find_property(np, "fsl,ssi-asynchronous", NULL) ? 1 : 0; - if (ssi_info.asynchronous) - dev_info(&ofdev->dev, "using asynchronous mode\n"); - - /* Map the global utilities registers. */ - guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); - if (!guts_np) { - dev_err(&ofdev->dev, "could not obtain address of GUTS\n"); - ret = -EINVAL; - goto error; - } - machine_data->guts = of_iomap(guts_np, 0); - of_node_put(guts_np); - if (!machine_data->guts) { - dev_err(&ofdev->dev, "could not map GUTS\n"); - ret = -EINVAL; - goto error; - } - - /* Find the DMA channels to use. Both SSIs need to use the same DMA - * controller, so let's use DMA#1. - */ - for_each_compatible_node(dma_np, NULL, "fsl,mpc8610-dma") { - iprop = of_get_property(dma_np, "cell-index", NULL); - if (iprop && (*iprop == 0)) { - of_node_put(dma_np); - break; - } - } - if (!dma_np) { - dev_err(&ofdev->dev, "could not find DMA node\n"); - ret = -EINVAL; - goto error; - } - machine_data->dma_id = *iprop; - - /* SSI1 needs to use DMA Channels 0 and 1, and SSI2 needs to use DMA - * channels 2 and 3. This is just how the MPC8610 is wired - * internally. - */ - playback_dma_channel = (machine_data->ssi_id == 0) ? 0 : 2; - capture_dma_channel = (machine_data->ssi_id == 0) ? 1 : 3; - - /* - * Find the DMA channels to use. - */ - while ((dma_channel_np = of_get_next_child(dma_np, dma_channel_np))) { - iprop = of_get_property(dma_channel_np, "cell-index", NULL); - if (iprop && (*iprop == playback_dma_channel)) { - /* dma_channel[0] and dma_irq[0] are for playback */ - dma_info.dma_channel[0] = of_iomap(dma_channel_np, 0); - dma_info.dma_irq[0] = - irq_of_parse_and_map(dma_channel_np, 0); - machine_data->dma_channel_id[0] = *iprop; - continue; - } - if (iprop && (*iprop == capture_dma_channel)) { - /* dma_channel[1] and dma_irq[1] are for capture */ - dma_info.dma_channel[1] = of_iomap(dma_channel_np, 0); - dma_info.dma_irq[1] = - irq_of_parse_and_map(dma_channel_np, 0); - machine_data->dma_channel_id[1] = *iprop; - continue; - } - } - if (!dma_info.dma_channel[0] || !dma_info.dma_channel[1] || - !dma_info.dma_irq[0] || !dma_info.dma_irq[1]) { - dev_err(&ofdev->dev, "could not find DMA channels\n"); - ret = -EINVAL; + dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n"); goto error; } - dma_info.ssi_stx_phys = ssi_info.ssi_phys + - offsetof(struct ccsr_ssi, stx0); - dma_info.ssi_srx_phys = ssi_info.ssi_phys + - offsetof(struct ccsr_ssi, srx0); - - /* We have the DMA information, so tell the DMA driver what it is */ - if (!fsl_dma_configure(&dma_info)) { - dev_err(&ofdev->dev, "could not instantiate DMA device\n"); - ret = -EBUSY; + /* Find the capture DMA channel to use. */ + machine_data->dai[1].platform_name = machine_data->platform_name[1]; + ret = get_dma_channel(np, "fsl,capture-dma", &machine_data->dai[1], + &machine_data->dma_channel_id[1], + &machine_data->dma_id[1]); + if (ret) { + dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n"); goto error; } - /* - * Initialize our DAI data structure. We should probably get this - * information from the device tree. - */ - machine_data->dai.name = "CS4270"; - machine_data->dai.stream_name = "CS4270"; - - machine_data->dai.cpu_dai = fsl_ssi_create_dai(&ssi_info); - machine_data->dai.codec_dai = &cs4270_dai; /* The codec_dai we want */ - machine_data->dai.ops = &mpc8610_hpcd_ops; + /* Initialize our DAI data structure. */ + machine_data->dai[0].stream_name = "playback"; + machine_data->dai[1].stream_name = "capture"; + machine_data->dai[0].name = machine_data->dai[0].stream_name; + machine_data->dai[1].name = machine_data->dai[1].stream_name; - machine_data->machine.probe = mpc8610_hpcd_machine_probe; - machine_data->machine.remove = mpc8610_hpcd_machine_remove; - machine_data->machine.name = "MPC8610 HPCD"; - machine_data->machine.num_links = 1; - machine_data->machine.dai_link = &machine_data->dai; + machine_data->card.probe = mpc8610_hpcd_machine_probe; + machine_data->card.remove = mpc8610_hpcd_machine_remove; + machine_data->card.name = pdev->name; /* The platform driver name */ + machine_data->card.num_links = 2; + machine_data->card.dai_link = machine_data->dai; /* Allocate a new audio platform device structure */ sound_device = platform_device_alloc("soc-audio", -1); if (!sound_device) { - dev_err(&ofdev->dev, "platform device allocation failed\n"); + dev_err(&pdev->dev, "platform device alloc failed\n"); ret = -ENOMEM; goto error; } - machine_data->sound_devdata.card = &machine_data->machine; - machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270; - machine_data->machine.platform = &fsl_soc_platform; - - sound_device->dev.platform_data = machine_data; - + /* Associate the card data with the sound device */ + platform_set_drvdata(sound_device, &machine_data->card); - /* Set the platform device and ASoC device to point to each other */ - platform_set_drvdata(sound_device, &machine_data->sound_devdata); - - machine_data->sound_devdata.dev = &sound_device->dev; - - - /* Tell ASoC to probe us. This will call mpc8610_hpcd_machine.probe(), - if it exists. */ + /* Register with ASoC */ ret = platform_device_add(sound_device); - if (ret) { - dev_err(&ofdev->dev, "platform device add failed\n"); + dev_err(&pdev->dev, "platform device add failed\n"); goto error; } - dev_set_drvdata(&ofdev->dev, sound_device); + of_node_put(codec_np); return 0; error: of_node_put(codec_np); - of_node_put(guts_np); - of_node_put(dma_np); - of_node_put(dma_channel_np); if (sound_device) platform_device_unregister(sound_device); - if (machine_data->dai.cpu_dai) - fsl_ssi_destroy_dai(machine_data->dai.cpu_dai); - - if (ssi_info.ssi) - iounmap(ssi_info.ssi); - - if (ssi_info.irq) - irq_dispose_mapping(ssi_info.irq); - - if (dma_info.dma_channel[0]) - iounmap(dma_info.dma_channel[0]); - - if (dma_info.dma_channel[1]) - iounmap(dma_info.dma_channel[1]); - - if (dma_info.dma_irq[0]) - irq_dispose_mapping(dma_info.dma_irq[0]); - - if (dma_info.dma_irq[1]) - irq_dispose_mapping(dma_info.dma_irq[1]); - - if (machine_data->guts) - iounmap(machine_data->guts); - kfree(machine_data); return ret; } /** - * mpc8610_hpcd_remove: remove the OF device + * mpc8610_hpcd_remove: remove the platform device * - * This function is called when the OF device is removed. + * This function is called when the platform device is removed. */ -static int mpc8610_hpcd_remove(struct of_device *ofdev) +static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev) { - struct platform_device *sound_device = dev_get_drvdata(&ofdev->dev); + struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); + struct snd_soc_card *card = platform_get_drvdata(sound_device); struct mpc8610_hpcd_data *machine_data = - sound_device->dev.platform_data; + container_of(card, struct mpc8610_hpcd_data, card); platform_device_unregister(sound_device); - if (machine_data->dai.cpu_dai) - fsl_ssi_destroy_dai(machine_data->dai.cpu_dai); - - if (machine_data->ssi) - iounmap(machine_data->ssi); - - if (machine_data->dma[0]) - iounmap(machine_data->dma[0]); - - if (machine_data->dma[1]) - iounmap(machine_data->dma[1]); - - if (machine_data->dma_irq[0]) - irq_dispose_mapping(machine_data->dma_irq[0]); - - if (machine_data->dma_irq[1]) - irq_dispose_mapping(machine_data->dma_irq[1]); - - if (machine_data->guts) - iounmap(machine_data->guts); - kfree(machine_data); sound_device->dev.platform_data = NULL; - dev_set_drvdata(&ofdev->dev, NULL); + dev_set_drvdata(&pdev->dev, NULL); return 0; } -static struct of_device_id mpc8610_hpcd_match[] = { - { - .compatible = "fsl,mpc8610-ssi", - }, - {} -}; -MODULE_DEVICE_TABLE(of, mpc8610_hpcd_match); - -static struct of_platform_driver mpc8610_hpcd_of_driver = { +static struct platform_driver mpc8610_hpcd_driver = { + .probe = mpc8610_hpcd_probe, + .remove = __devexit_p(mpc8610_hpcd_remove), .driver = { - .name = "mpc8610_hpcd", + /* The name must match the 'model' property in the device tree, + * in lowercase letters. + */ + .name = "snd-soc-mpc8610hpcd", .owner = THIS_MODULE, - .of_match_table = mpc8610_hpcd_match, }, - .probe = mpc8610_hpcd_probe, - .remove = mpc8610_hpcd_remove, }; /** - * mpc8610_hpcd_init: fabric driver initialization. + * mpc8610_hpcd_init: machine driver initialization. * * This function is called when this module is loaded. */ static int __init mpc8610_hpcd_init(void) { - int ret; - - printk(KERN_INFO "Freescale MPC8610 HPCD ALSA SoC fabric driver\n"); + struct device_node *guts_np; + struct resource res; - ret = of_register_platform_driver(&mpc8610_hpcd_of_driver); + pr_info("Freescale MPC8610 HPCD ALSA SoC machine driver\n"); - if (ret) - printk(KERN_ERR - "mpc8610-hpcd: failed to register platform driver\n"); + /* Get the physical address of the global utilities registers */ + guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); + if (of_address_to_resource(guts_np, 0, &res)) { + pr_err("mpc8610-hpcd: missing/invalid global utilities node\n"); + return -EINVAL; + } + guts_phys = res.start; - return ret; + return platform_driver_register(&mpc8610_hpcd_driver); } /** - * mpc8610_hpcd_exit: fabric driver exit + * mpc8610_hpcd_exit: machine driver exit * * This function is called when this driver is unloaded. */ static void __exit mpc8610_hpcd_exit(void) { - of_unregister_platform_driver(&mpc8610_hpcd_of_driver); + platform_driver_unregister(&mpc8610_hpcd_driver); } module_init(mpc8610_hpcd_init); module_exit(mpc8610_hpcd_exit); MODULE_AUTHOR("Timur Tabi "); -MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC fabric driver"); -MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC machine driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 6644cba7cbf2..fe15bb26e484 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -32,21 +32,24 @@ #define DRV_NAME "pcm030-audio-fabric" -static struct snd_soc_device device; static struct snd_soc_card card; static struct snd_soc_dai_link pcm030_fabric_dai[] = { { .name = "AC97", .stream_name = "AC97 Analog", - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], - .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL], + .codec_dai_name = "wm9712-hifi", + .cpu_dai_name = "mpc5200-psc-ac97.0", + .platform_name = "mpc5200-pcm-audio", + .codec_name = "wm9712-codec", }, { .name = "AC97", .stream_name = "AC97 IEC958", - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], - .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF], + .codec_dai_name = "wm9712-aux", + .cpu_dai_name = "mpc5200-psc-ac97.1", + .platform_name = "mpc5200-pcm-audio", + ..codec_name = "wm9712-codec", }, }; @@ -58,22 +61,18 @@ static __init int pcm030_fabric_init(void) if (!of_machine_is_compatible("phytec,pcm030")) return -ENODEV; - card.platform = &mpc5200_audio_dma_platform; + card.name = "pcm030"; card.dai_link = pcm030_fabric_dai; card.num_links = ARRAY_SIZE(pcm030_fabric_dai); - device.card = &card; - device.codec_dev = &soc_codec_dev_wm9712; - pdev = platform_device_alloc("soc-audio", 1); if (!pdev) { pr_err("pcm030_fabric_init: platform_device_alloc() failed\n"); return -ENODEV; } - platform_set_drvdata(pdev, &device); - device.dev = &pdev->dev; + platform_set_drvdata(pdev, &card); rc = platform_device_add(pdev); if (rc) { diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c deleted file mode 100644 index 3bc13fd89096..000000000000 --- a/sound/soc/fsl/soc-of-simple.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * OF helpers for ALSA SoC Layer - * - * Copyright (C) 2008, Secret Lab Technologies Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Grant Likely "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("ALSA SoC OpenFirmware bindings"); - -static DEFINE_MUTEX(of_snd_soc_mutex); -static LIST_HEAD(of_snd_soc_device_list); -static int of_snd_soc_next_index; - -struct of_snd_soc_device { - int id; - struct list_head list; - struct snd_soc_device device; - struct snd_soc_card card; - struct snd_soc_dai_link dai_link; - struct platform_device *pdev; - struct device_node *platform_node; - struct device_node *codec_node; -}; - -static struct snd_soc_ops of_snd_soc_ops = { -}; - -static struct of_snd_soc_device * -of_snd_soc_get_device(struct device_node *codec_node) -{ - struct of_snd_soc_device *of_soc; - - list_for_each_entry(of_soc, &of_snd_soc_device_list, list) { - if (of_soc->codec_node == codec_node) - return of_soc; - } - - of_soc = kzalloc(sizeof(struct of_snd_soc_device), GFP_KERNEL); - if (!of_soc) - return NULL; - - /* Initialize the structure and add it to the global list */ - of_soc->codec_node = codec_node; - of_soc->id = of_snd_soc_next_index++; - of_soc->card.dai_link = &of_soc->dai_link; - of_soc->card.num_links = 1; - of_soc->device.card = &of_soc->card; - of_soc->dai_link.ops = &of_snd_soc_ops; - list_add(&of_soc->list, &of_snd_soc_device_list); - - return of_soc; -} - -static void of_snd_soc_register_device(struct of_snd_soc_device *of_soc) -{ - struct platform_device *pdev; - int rc; - - /* Only register the device if both the codec and platform have - * been registered */ - if ((!of_soc->device.codec_data) || (!of_soc->platform_node)) - return; - - pr_info("platform<-->codec match achieved; registering machine\n"); - - pdev = platform_device_alloc("soc-audio", of_soc->id); - if (!pdev) { - pr_err("of_soc: platform_device_alloc() failed\n"); - return; - } - - pdev->dev.platform_data = of_soc; - platform_set_drvdata(pdev, &of_soc->device); - of_soc->device.dev = &pdev->dev; - - /* The ASoC device is complete; register it */ - rc = platform_device_add(pdev); - if (rc) { - pr_err("of_soc: platform_device_add() failed\n"); - return; - } - -} - -int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev, - void *codec_data, struct snd_soc_dai *dai, - struct device_node *node) -{ - struct of_snd_soc_device *of_soc; - int rc = 0; - - pr_info("registering ASoC codec driver: %s\n", node->full_name); - - mutex_lock(&of_snd_soc_mutex); - of_soc = of_snd_soc_get_device(node); - if (!of_soc) { - rc = -ENOMEM; - goto out; - } - - /* Store the codec data */ - of_soc->device.codec_data = codec_data; - of_soc->device.codec_dev = codec_dev; - of_soc->dai_link.name = (char *)node->name; - of_soc->dai_link.stream_name = (char *)node->name; - of_soc->dai_link.codec_dai = dai; - - /* Now try to register the SoC device */ - of_snd_soc_register_device(of_soc); - - out: - mutex_unlock(&of_snd_soc_mutex); - return rc; -} -EXPORT_SYMBOL_GPL(of_snd_soc_register_codec); - -int of_snd_soc_register_platform(struct snd_soc_platform *platform, - struct device_node *node, - struct snd_soc_dai *cpu_dai) -{ - struct of_snd_soc_device *of_soc; - struct device_node *codec_node; - const phandle *handle; - int len, rc = 0; - - pr_info("registering ASoC platform driver: %s\n", node->full_name); - - handle = of_get_property(node, "codec-handle", &len); - if (!handle || len < sizeof(handle)) - return -ENODEV; - codec_node = of_find_node_by_phandle(*handle); - if (!codec_node) - return -ENODEV; - pr_info("looking for codec: %s\n", codec_node->full_name); - - mutex_lock(&of_snd_soc_mutex); - of_soc = of_snd_soc_get_device(codec_node); - if (!of_soc) { - rc = -ENOMEM; - goto out; - } - - of_soc->platform_node = node; - of_soc->dai_link.cpu_dai = cpu_dai; - of_soc->card.platform = platform; - of_soc->card.name = of_soc->dai_link.cpu_dai->name; - - /* Now try to register the SoC device */ - of_snd_soc_register_device(of_soc); - - out: - mutex_unlock(&of_snd_soc_mutex); - return rc; -} -EXPORT_SYMBOL_GPL(of_snd_soc_register_platform); diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 52dac5e3874c..66ba26393c10 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -8,12 +8,24 @@ menuconfig SND_IMX_SOC Say Y or M if you want to add support for codecs attached to the i.MX SSI interface. + if SND_IMX_SOC +config SND_MXC_SOC_SSI + tristate + +config SND_MXC_SOC_FIQ + tristate + +config SND_MXC_SOC_MX2 + tristate + config SND_MXC_SOC_WM1133_EV1 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL select SND_SOC_WM8350 + select SND_MXC_SOC_SSI + select SND_MXC_SOC_FIQ help Enable support for audio on the i.MX31ADS with the WM1133-EV1 PMIC board with WM8835x fitted. @@ -22,6 +34,8 @@ config SND_SOC_PHYCORE_AC97 tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" depends on MACH_PCM043 || MACH_PCA100 select SND_SOC_WM9712 + select SND_MXC_SOC_SSI + select SND_MXC_SOC_FIQ help Say Y if you want to add support for SoC audio on Phytec phyCORE and phyCARD boards in AC97 mode @@ -30,6 +44,8 @@ config SND_SOC_EUKREA_TLV320 tristate "Eukrea TLV320" depends on MACH_EUKREA_MBIMX27_BASEBOARD || MACH_EUKREA_MBIMXSD_BASEBOARD select SND_SOC_TLV320AIC23 + select SND_MXC_SOC_SSI + select SND_MXC_SOC_FIQ help Enable I2S based access to the TLV320AIC23B codec attached to the SSI interface diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index 7bc57baf2b0e..b67fc02a4ecc 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile @@ -1,11 +1,11 @@ # i.MX Platform Support -snd-soc-imx-objs := imx-ssi.o imx-pcm-fiq.o - -ifdef CONFIG_MACH_MX27 -snd-soc-imx-objs += imx-pcm-dma-mx2.o -endif +snd-soc-imx-objs := imx-ssi.o +snd-soc-imx-fiq-objs := imx-pcm-fiq.o +snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o +obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o +obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o # i.MX Machine Support snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c index f15dfbdc47ee..807f736ee294 100644 --- a/sound/soc/imx/eukrea-tlv320.c +++ b/sound/soc/imx/eukrea-tlv320.c @@ -79,22 +79,19 @@ static struct snd_soc_ops eukrea_tlv320_snd_ops = { static struct snd_soc_dai_link eukrea_tlv320_dai = { .name = "tlv320aic23", .stream_name = "TLV320AIC23", - .codec_dai = &tlv320aic23_dai, + .codec_dai = "tlv320aic23-hifi", + .platform_name = "imx-pcm-audio.0", + .codec_name = "tlv320aic23-codec.0-001a", + .cpu_dai = "imx-ssi-dai.0", .ops = &eukrea_tlv320_snd_ops, }; static struct snd_soc_card eukrea_tlv320 = { .name = "cpuimx-audio", - .platform = &imx_soc_platform, .dai_link = &eukrea_tlv320_dai, .num_links = 1, }; -static struct snd_soc_device eukrea_tlv320_snd_devdata = { - .card = &eukrea_tlv320, - .codec_dev = &soc_codec_dev_tlv320aic23, -}; - static struct platform_device *eukrea_tlv320_snd_device; static int __init eukrea_tlv320_init(void) @@ -110,10 +107,7 @@ static int __init eukrea_tlv320_init(void) if (!eukrea_tlv320_snd_device) return -ENOMEM; - eukrea_tlv320_dai.cpu_dai = &imx_ssi_pcm_dai[0]; - - platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320_snd_devdata); - eukrea_tlv320_snd_devdata.dev = &eukrea_tlv320_snd_device->dev; + platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320); ret = platform_device_add(eukrea_tlv320_snd_device); if (ret) { diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index 0a595da4811d..fd493ee1428e 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -103,7 +103,7 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream) struct imx_pcm_runtime_data *iprtd = runtime->private_data; int ret; - dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH); if (iprtd->dma < 0) { @@ -213,7 +213,7 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream) struct imx_pcm_runtime_data *iprtd = runtime->private_data; int err; - dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); iprtd->substream = substream; iprtd->buf = (unsigned int *)substream->dma_buffer.area; @@ -318,19 +318,42 @@ static struct snd_pcm_ops imx_pcm_ops = { .mmap = snd_imx_pcm_mmap, }; -static struct snd_soc_platform imx_soc_platform_dma = { - .name = "imx-audio", - .pcm_ops = &imx_pcm_ops, +static struct snd_soc_platform_driver imx_soc_platform_mx2 = { + .ops = &imx_pcm_ops, .pcm_new = imx_pcm_new, .pcm_free = imx_pcm_free, }; -struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev, - struct imx_ssi *ssi) +static int __devinit imx_soc_platform_probe(struct platform_device *pdev) { - ssi->dma_params_tx.burstsize = DMA_TXFIFO_BURST; - ssi->dma_params_rx.burstsize = DMA_RXFIFO_BURST; + return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2); +} + +static int __devexit imx_soc_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver imx_pcm_driver = { + .driver = { + .name = "imx-pcm-audio", + .owner = THIS_MODULE, + }, - return &imx_soc_platform_dma; + .probe = imx_soc_platform_probe, + .remove = __devexit_p(imx_soc_platform_remove), +}; + +static int __init snd_imx_pcm_init(void) +{ + return platform_driver_register(&imx_pcm_driver); +} +module_init(snd_imx_pcm_init); + +static void __exit snd_imx_pcm_exit(void) +{ + platform_driver_unregister(&imx_pcm_driver); } +module_exit(snd_imx_pcm_exit); diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c index b2bf27282cd2..413b78da248f 100644 --- a/sound/soc/imx/imx-pcm-fiq.c +++ b/sound/soc/imx/imx-pcm-fiq.c @@ -236,6 +236,8 @@ static struct snd_pcm_ops imx_pcm_ops = { .mmap = snd_imx_pcm_mmap, }; +static int ssi_irq = 0; + static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { @@ -245,7 +247,7 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, if (ret) return ret; - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { struct snd_pcm_substream *substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; struct snd_dma_buffer *buf = &substream->dma_buffer; @@ -253,7 +255,7 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, imx_ssi_fiq_tx_buffer = (unsigned long)buf->area; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { struct snd_pcm_substream *substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; struct snd_dma_buffer *buf = &substream->dma_buffer; @@ -267,24 +269,32 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, return 0; } -static struct snd_soc_platform imx_soc_platform_fiq = { - .pcm_ops = &imx_pcm_ops, +static void imx_pcm_fiq_free(struct snd_pcm *pcm) +{ + mxc_set_irq_fiq(ssi_irq, 0); + release_fiq(&fh); + imx_pcm_free(pcm); +} + +static struct snd_soc_platform_driver imx_soc_platform_fiq = { + .ops = &imx_pcm_ops, .pcm_new = imx_pcm_fiq_new, - .pcm_free = imx_pcm_free, + .pcm_free = imx_pcm_fiq_free, }; -struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, - struct imx_ssi *ssi) +static int __devinit imx_soc_platform_probe(struct platform_device *pdev) { - int ret = 0; + struct imx_ssi *ssi = platform_get_drvdata(pdev); + int ret; ret = claim_fiq(&fh); if (ret) { dev_err(&pdev->dev, "failed to claim fiq: %d", ret); - return ERR_PTR(ret); + return ret; } mxc_set_irq_fiq(ssi->irq, 1); + ssi_irq = ssi->irq; imx_pcm_fiq = ssi->irq; @@ -293,13 +303,43 @@ struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, ssi->dma_params_tx.burstsize = 4; ssi->dma_params_rx.burstsize = 6; - return &imx_soc_platform_fiq; + ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq); + if (ret) + goto failed_register; + + return 0; + +failed_register: + mxc_set_irq_fiq(ssi_irq, 0); + release_fiq(&fh); + + return ret; } -void imx_ssi_fiq_exit(struct platform_device *pdev, - struct imx_ssi *ssi) +static int __devexit imx_soc_platform_remove(struct platform_device *pdev) { - mxc_set_irq_fiq(ssi->irq, 0); - release_fiq(&fh); + snd_soc_unregister_platform(&pdev->dev); + return 0; } +static struct platform_driver imx_pcm_driver = { + .driver = { + .name = "imx-fiq-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = imx_soc_platform_probe, + .remove = __devexit_p(imx_soc_platform_remove), +}; + +static int __init snd_imx_pcm_init(void) +{ + return platform_driver_register(&imx_pcm_driver); +} +module_init(snd_imx_pcm_init); + +static void __exit snd_imx_pcm_exit(void) +{ + platform_driver_unregister(&imx_pcm_driver); +} +module_exit(snd_imx_pcm_exit); diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 50f51624c535..02a3e7c799d8 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -61,7 +61,7 @@ static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { - struct imx_ssi *ssi = cpu_dai->private_data; + struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); u32 sccr; sccr = readl(ssi->base + SSI_STCCR); @@ -86,7 +86,7 @@ static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, */ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct imx_ssi *ssi = cpu_dai->private_data; + struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); u32 strcr = 0, scr; scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET); @@ -164,7 +164,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct imx_ssi *ssi = cpu_dai->private_data; + struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); u32 scr; scr = readl(ssi->base + SSI_SCR); @@ -192,7 +192,7 @@ static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) { - struct imx_ssi *ssi = cpu_dai->private_data; + struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); u32 stccr, srccr; stccr = readl(ssi->base + SSI_STCCR); @@ -241,7 +241,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { - struct imx_ssi *ssi = cpu_dai->private_data; + struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); struct imx_pcm_dma_params *dma_data; u32 reg, sccr; @@ -279,9 +279,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream, static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct imx_ssi *ssi = cpu_dai->private_data; + struct imx_ssi *ssi = snd_soc_dai_get_drvdata(dai); unsigned int sier_bits, sier; unsigned int scr; @@ -350,22 +348,6 @@ static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { .trigger = imx_ssi_trigger, }; -static struct snd_soc_dai imx_ssi_dai = { - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &imx_ssi_pcm_dai_ops, -}; - int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) { @@ -381,6 +363,7 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, runtime->dma_bytes); return ret; } +EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap); static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) { @@ -412,14 +395,14 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, card->dev->dma_mask = &imx_pcm_dmamask; if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = imx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto out; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { ret = imx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) @@ -429,6 +412,7 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, out: return ret; } +EXPORT_SYMBOL_GPL(imx_pcm_new); void imx_pcm_free(struct snd_pcm *pcm) { @@ -450,14 +434,40 @@ void imx_pcm_free(struct snd_pcm *pcm) buf->area = NULL; } } +EXPORT_SYMBOL_GPL(imx_pcm_free); -struct snd_soc_platform imx_soc_platform = { - .name = "imx-audio", +static struct snd_soc_dai_driver imx_ssi_dai = { + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &imx_ssi_pcm_dai_ops, }; -EXPORT_SYMBOL_GPL(imx_soc_platform); -static struct snd_soc_dai imx_ac97_dai = { - .name = "AC97", +static int imx_ssi_dai_probe(struct snd_soc_dai *dai) +{ + struct imx_ssi *ssi = dev_get_drvdata(dai->dev); + uint32_t val; + + snd_soc_dai_set_drvdata(dai, ssi); + + val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | + SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); + writel(val, ssi->base + SSI_SFCSR); + + return 0; +} + +static struct snd_soc_dai_driver imx_ac97_dai = { + .probe = imx_ssi_dai_probe, .ac97_control = 1, .playback = { .stream_name = "AC97 Playback", @@ -577,25 +587,18 @@ struct snd_ac97_bus_ops soc_ac97_ops = { }; EXPORT_SYMBOL_GPL(soc_ac97_ops); -struct snd_soc_dai imx_ssi_pcm_dai[2]; -EXPORT_SYMBOL_GPL(imx_ssi_pcm_dai); - static int imx_ssi_probe(struct platform_device *pdev) { struct resource *res; struct imx_ssi *ssi; struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; - struct snd_soc_platform *platform; int ret = 0; - unsigned int val; - struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id]; - - if (dai->id >= ARRAY_SIZE(imx_ssi_pcm_dai)) - return -EINVAL; + struct snd_soc_dai_driver *dai; ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); if (!ssi) return -ENOMEM; + dev_set_drvdata(&pdev->dev, ssi); if (pdata) { ssi->ac97_reset = pdata->ac97_reset; @@ -640,9 +643,9 @@ static int imx_ssi_probe(struct platform_device *pdev) } ac97_ssi = ssi; setup_channel_to_ac97(ssi); - memcpy(dai, &imx_ac97_dai, sizeof(imx_ac97_dai)); + dai = &imx_ac97_dai; } else - memcpy(dai, &imx_ssi_dai, sizeof(imx_ssi_dai)); + dai = &imx_ssi_dai; writel(0x0, ssi->base + SSI_SIER); @@ -657,37 +660,36 @@ static int imx_ssi_probe(struct platform_device *pdev) if (res) ssi->dma_params_rx.dma = res->start; - dai->id = pdev->id; - dai->dev = &pdev->dev; - dai->name = kasprintf(GFP_KERNEL, "imx-ssi.%d", pdev->id); - dai->private_data = ssi; - if ((cpu_is_mx27() || cpu_is_mx21()) && !(ssi->flags & IMX_SSI_USE_AC97) && (ssi->flags & IMX_SSI_DMA)) { ssi->flags |= IMX_SSI_DMA; - platform = imx_ssi_dma_mx2_init(pdev, ssi); - } else - platform = imx_ssi_fiq_init(pdev, ssi); - - imx_soc_platform.pcm_ops = platform->pcm_ops; - imx_soc_platform.pcm_new = platform->pcm_new; - imx_soc_platform.pcm_free = platform->pcm_free; + } - val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | - SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); - writel(val, ssi->base + SSI_SFCSR); + platform_set_drvdata(pdev, ssi); - ret = snd_soc_register_dai(dai); + ret = snd_soc_register_dai(&pdev->dev, dai); if (ret) { dev_err(&pdev->dev, "register DAI failed\n"); goto failed_register; } - platform_set_drvdata(pdev, ssi); + ssi->soc_platform_pdev = platform_device_alloc("imx-fiq-pcm-audio", pdev->id); + if (!ssi->soc_platform_pdev) + goto failed_pdev_alloc; + platform_set_drvdata(ssi->soc_platform_pdev, ssi); + ret = platform_device_add(ssi->soc_platform_pdev); + if (ret) { + dev_err(&pdev->dev, "failed to add platform device\n"); + goto failed_pdev_add; + } return 0; +failed_pdev_add: + platform_device_put(ssi->soc_platform_pdev); +failed_pdev_alloc: + snd_soc_unregister_dai(&pdev->dev); failed_register: failed_ac97: iounmap(ssi->base); @@ -706,16 +708,15 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev) { struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct imx_ssi *ssi = platform_get_drvdata(pdev); - struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id]; - snd_soc_unregister_dai(dai); + platform_device_del(ssi->soc_platform_pdev); + platform_device_put(ssi->soc_platform_pdev); + + snd_soc_unregister_dai(&pdev->dev); if (ssi->flags & IMX_SSI_USE_AC97) ac97_ssi = NULL; - if (!(ssi->flags & IMX_SSI_DMA)) - imx_ssi_fiq_exit(pdev, ssi); - iounmap(ssi->base); release_mem_region(res->start, resource_size(res)); clk_disable(ssi->clk); @@ -730,34 +731,19 @@ static struct platform_driver imx_ssi_driver = { .remove = __devexit_p(imx_ssi_remove), .driver = { - .name = DRV_NAME, + .name = "imx-ssi-dai", .owner = THIS_MODULE, }, }; static int __init imx_ssi_init(void) { - int ret; - - ret = snd_soc_register_platform(&imx_soc_platform); - if (ret) { - pr_err("failed to register soc platform: %d\n", ret); - return ret; - } - - ret = platform_driver_register(&imx_ssi_driver); - if (ret) { - snd_soc_unregister_platform(&imx_soc_platform); - return ret; - } - - return 0; + return platform_driver_register(&imx_ssi_driver); } static void __exit imx_ssi_exit(void) { platform_driver_unregister(&imx_ssi_driver); - snd_soc_unregister_platform(&imx_soc_platform); } module_init(imx_ssi_init); diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h index 55f26ebcd8c2..53b780d9b2b0 100644 --- a/sound/soc/imx/imx-ssi.h +++ b/sound/soc/imx/imx-ssi.h @@ -183,9 +183,6 @@ #define IMX_SSI_RX_DIV_PSR 4 #define IMX_SSI_RX_DIV_PM 5 -extern struct snd_soc_dai imx_ssi_pcm_dai[2]; -extern struct snd_soc_platform imx_soc_platform; - #define DRV_NAME "imx-ssi" struct imx_pcm_dma_params { @@ -197,7 +194,7 @@ struct imx_pcm_dma_params { struct imx_ssi { struct platform_device *ac97_dev; - struct snd_soc_device imx_ac97; + struct snd_soc_dai *imx_ac97; struct clk *clk; void __iomem *base; int irq; @@ -213,6 +210,8 @@ struct imx_ssi { struct imx_pcm_dma_params dma_params_tx; int enabled; + + struct platform_device *soc_platform_pdev; }; struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c index a8307d55c70e..65f0f99ca6dd 100644 --- a/sound/soc/imx/phycore-ac97.c +++ b/sound/soc/imx/phycore-ac97.c @@ -32,23 +32,20 @@ static struct snd_soc_dai_link imx_phycore_dai_ac97[] = { { .name = "HiFi", .stream_name = "HiFi", - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], + .codec_dai_name = "wm9712-hifi", + .codec_name = "wm9712-codec", + .cpu_dai_name = "imx-ssi-dai.0", + .platform_name = "imx-fiq-pcm-audio.0", .ops = &imx_phycore_hifi_ops, }, }; static struct snd_soc_card imx_phycore = { .name = "PhyCORE-audio", - .platform = &imx_soc_platform, .dai_link = imx_phycore_dai_ac97, .num_links = ARRAY_SIZE(imx_phycore_dai_ac97), }; -static struct snd_soc_device imx_phycore_snd_devdata = { - .card = &imx_phycore, - .codec_dev = &soc_codec_dev_wm9712, -}; - static struct platform_device *imx_phycore_snd_device; static int __init imx_phycore_init(void) @@ -63,10 +60,12 @@ static int __init imx_phycore_init(void) if (!imx_phycore_snd_device) return -ENOMEM; - imx_phycore_dai_ac97[0].cpu_dai = &imx_ssi_pcm_dai[0]; + platform_set_drvdata(imx_phycore_snd_device, &imx_phycore); + ret = platform_device_add(imx_phycore_snd_device); - platform_set_drvdata(imx_phycore_snd_device, &imx_phycore_snd_devdata); - imx_phycore_snd_devdata.dev = &imx_phycore_snd_device->dev; + imx_phycore_snd_device = platform_device_alloc("wm9712-codec", -1); + if (!imx_phycore_snd_device) + return -ENOMEM; ret = platform_device_add(imx_phycore_snd_device); if (ret) { diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c index a6e7d9497639..74068636c1d8 100644 --- a/sound/soc/imx/wm1133-ev1.c +++ b/sound/soc/imx/wm1133-ev1.c @@ -82,8 +82,8 @@ static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int i, found = 0; snd_pcm_format_t format = params_format(params); unsigned int rate = params_rate(params); @@ -210,9 +210,9 @@ static struct snd_soc_jack_pin mic_jack_pins[] = { { .pin = "Mic2 Jack", .mask = SND_JACK_MICROPHONE }, }; -static int wm1133_ev1_init(struct snd_soc_codec *codec) +static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_card *card = codec->socdev->card; + struct snd_soc_codec *codec = rtd->codec; snd_soc_dapm_new_controls(codec, wm1133_ev1_widgets, ARRAY_SIZE(wm1133_ev1_widgets)); @@ -221,13 +221,13 @@ static int wm1133_ev1_init(struct snd_soc_codec *codec) ARRAY_SIZE(wm1133_ev1_map)); /* Headphone jack detection */ - snd_soc_jack_new(card, "Headphone", SND_JACK_HEADPHONE, &hp_jack); + snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack); snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), hp_jack_pins); wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE); /* Microphone jack detection */ - snd_soc_jack_new(card, "Microphone", + snd_soc_jack_new(codec, "Microphone", SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack); snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), mic_jack_pins); @@ -243,8 +243,10 @@ static int wm1133_ev1_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link wm1133_ev1_dai = { .name = "WM1133-EV1", .stream_name = "Audio", - .cpu_dai = &imx_ssi_pcm_dai[0], - .codec_dai = &wm8350_dai, + .cpu_dai_name = "imx-ssi-dai.0", + .codec_dai_name = "wm8350-hifi", + .platform_name = "imx-fiq-pcm-audio.0", + .codec_name = "wm8350-codec.0-0x1a", .init = wm1133_ev1_init, .ops = &wm1133_ev1_ops, .symmetric_rates = 1, @@ -252,16 +254,10 @@ static struct snd_soc_dai_link wm1133_ev1_dai = { static struct snd_soc_card wm1133_ev1 = { .name = "WM1133-EV1", - .platform = &imx_soc_platform, .dai_link = &wm1133_ev1_dai, .num_links = 1, }; -static struct snd_soc_device wm1133_ev1_snd_devdata = { - .card = &wm1133_ev1, - .codec_dev = &soc_codec_dev_wm8350, -}; - static struct platform_device *wm1133_ev1_snd_device; static int __init wm1133_ev1_audio_init(void) @@ -286,8 +282,7 @@ static int __init wm1133_ev1_audio_init(void) if (!wm1133_ev1_snd_device) return -ENOMEM; - platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1_snd_devdata); - wm1133_ev1_snd_devdata.dev = &wm1133_ev1_snd_device->dev; + platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1); ret = platform_device_add(wm1133_ev1_snd_device); if (ret) diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index eb518f0c5e01..f3cffd183401 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -106,15 +106,10 @@ static inline void jz4740_i2s_write(const struct jz4740_i2s *i2s, writel(value, i2s->base + reg); } -static inline struct jz4740_i2s *jz4740_dai_to_i2s(struct snd_soc_dai *dai) -{ - return dai->private_data; -} - static int jz4740_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); + struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); uint32_t conf, ctrl; if (dai->active) @@ -136,7 +131,7 @@ static int jz4740_i2s_startup(struct snd_pcm_substream *substream, static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); + struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); uint32_t conf; if (!dai->active) @@ -152,7 +147,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); + struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); uint32_t ctrl; uint32_t mask; @@ -186,7 +181,7 @@ static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); + struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); uint32_t format = 0; uint32_t conf; @@ -238,7 +233,7 @@ static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); + struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); enum jz4740_dma_width dma_width; struct jz4740_pcm_config *pcm_config; unsigned int sample_size; @@ -288,7 +283,7 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { - struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); + struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); struct clk *parent; int ret = 0; @@ -312,7 +307,7 @@ static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, static int jz4740_i2s_suspend(struct snd_soc_dai *dai) { - struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); + struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); uint32_t conf; if (dai->active) { @@ -330,7 +325,7 @@ static int jz4740_i2s_suspend(struct snd_soc_dai *dai) static int jz4740_i2s_resume(struct snd_soc_dai *dai) { - struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); + struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); uint32_t conf; clk_enable(i2s->clk_aic); @@ -346,11 +341,38 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai) return 0; } -static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai) +static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s) { - struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); + struct jz4740_dma_config *dma_config; + + /* Playback */ + dma_config = &i2s->pcm_config_playback.dma_config; + dma_config->src_width = JZ4740_DMA_WIDTH_32BIT, + dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; + dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT; + dma_config->flags = JZ4740_DMA_SRC_AUTOINC; + dma_config->mode = JZ4740_DMA_MODE_SINGLE; + i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; + + /* Capture */ + dma_config = &i2s->pcm_config_capture.dma_config; + dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT, + dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; + dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE; + dma_config->flags = JZ4740_DMA_DST_AUTOINC; + dma_config->mode = JZ4740_DMA_MODE_SINGLE; + i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; +} + +static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) +{ + struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); uint32_t conf; + clk_enable(i2s->clk_aic); + + jz4740_i2c_init_pcm_config(i2s); + conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | JZ_AIC_CONF_OVERFLOW_PLAY_LAST | @@ -363,6 +385,14 @@ static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *da return 0; } +static int jz4740_i2s_dai_remove(struct snd_soc_dai *dai) +{ + struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); + + clk_disable(i2s->clk_aic); + return 0; +} + static struct snd_soc_dai_ops jz4740_i2s_dai_ops = { .startup = jz4740_i2s_startup, .shutdown = jz4740_i2s_shutdown, @@ -375,9 +405,9 @@ static struct snd_soc_dai_ops jz4740_i2s_dai_ops = { #define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE) -struct snd_soc_dai jz4740_i2s_dai = { - .name = "jz4740-i2s", - .probe = jz4740_i2s_probe, +static struct snd_soc_dai_driver jz4740_i2s_dai = { + .probe = jz4740_i2s_dai_probe, + .remove = jz4740_i2s_dai_remove, .playback = { .channels_min = 1, .channels_max = 2, @@ -395,30 +425,6 @@ struct snd_soc_dai jz4740_i2s_dai = { .suspend = jz4740_i2s_suspend, .resume = jz4740_i2s_resume, }; -EXPORT_SYMBOL_GPL(jz4740_i2s_dai); - -static void __devinit jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s) -{ - struct jz4740_dma_config *dma_config; - - /* Playback */ - dma_config = &i2s->pcm_config_playback.dma_config; - dma_config->src_width = JZ4740_DMA_WIDTH_32BIT, - dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; - dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT; - dma_config->flags = JZ4740_DMA_SRC_AUTOINC; - dma_config->mode = JZ4740_DMA_MODE_SINGLE; - i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; - - /* Capture */ - dma_config = &i2s->pcm_config_capture.dma_config; - dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT, - dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; - dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE; - dma_config->flags = JZ4740_DMA_DST_AUTOINC; - dma_config->mode = JZ4740_DMA_MODE_SINGLE; - i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; -} static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev) { @@ -463,24 +469,17 @@ static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev) goto err_clk_put_aic; } - clk_enable(i2s->clk_aic); - - jz4740_i2c_init_pcm_config(i2s); - - jz4740_i2s_dai.private_data = i2s; - ret = snd_soc_register_dai(&jz4740_i2s_dai); + platform_set_drvdata(pdev, i2s); + ret = snd_soc_register_dai(&pdev->dev, &jz4740_i2s_dai); if (ret) { dev_err(&pdev->dev, "Failed to register DAI\n"); goto err_clk_put_i2s; } - platform_set_drvdata(pdev, i2s); - return 0; err_clk_put_i2s: - clk_disable(i2s->clk_aic); clk_put(i2s->clk_i2s); err_clk_put_aic: clk_put(i2s->clk_aic); @@ -498,9 +497,8 @@ static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev) { struct jz4740_i2s *i2s = platform_get_drvdata(pdev); - snd_soc_unregister_dai(&jz4740_i2s_dai); + snd_soc_unregister_dai(&pdev->dev); - clk_disable(i2s->clk_aic); clk_put(i2s->clk_i2s); clk_put(i2s->clk_aic); diff --git a/sound/soc/jz4740/jz4740-i2s.h b/sound/soc/jz4740/jz4740-i2s.h index da22ed88a589..5e49339d8b93 100644 --- a/sound/soc/jz4740/jz4740-i2s.h +++ b/sound/soc/jz4740/jz4740-i2s.h @@ -13,6 +13,4 @@ #define JZ4740_I2S_BIT_CLK 0 -extern struct snd_soc_dai jz4740_i2s_dai; - #endif diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c index ee68d850c8dd..fb1483f7c966 100644 --- a/sound/soc/jz4740/jz4740-pcm.c +++ b/sound/soc/jz4740/jz4740-pcm.c @@ -109,7 +109,7 @@ static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct jz4740_pcm_config *config; - config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + config = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (!config) return 0; @@ -310,14 +310,14 @@ int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = jz4740_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto err; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { ret = jz4740_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) @@ -328,22 +328,20 @@ err: return ret; } -struct snd_soc_platform jz4740_soc_platform = { - .name = "jz4740-pcm", - .pcm_ops = &jz4740_pcm_ops, +static struct snd_soc_platform_driver jz4740_soc_platform = { + .ops = &jz4740_pcm_ops, .pcm_new = jz4740_pcm_new, .pcm_free = jz4740_pcm_free, }; -EXPORT_SYMBOL_GPL(jz4740_soc_platform); static int __devinit jz4740_pcm_probe(struct platform_device *pdev) { - return snd_soc_register_platform(&jz4740_soc_platform); + return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform); } static int __devexit jz4740_pcm_remove(struct platform_device *pdev) { - snd_soc_unregister_platform(&jz4740_soc_platform); + snd_soc_unregister_platform(&pdev->dev); return 0; } @@ -351,7 +349,7 @@ static struct platform_driver jz4740_pcm_driver = { .probe = jz4740_pcm_probe, .remove = __devexit_p(jz4740_pcm_remove), .driver = { - .name = "jz4740-pcm", + .name = "jz4740-pcm-audio", .owner = THIS_MODULE, }, }; diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h index e3f221e2779c..1220cbb4382c 100644 --- a/sound/soc/jz4740/jz4740-pcm.h +++ b/sound/soc/jz4740/jz4740-pcm.h @@ -11,8 +11,6 @@ #include #include -/* platform data */ -extern struct snd_soc_platform jz4740_soc_platform; struct jz4740_pcm_config { struct jz4740_dma_config dma_config; diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c index f15f4918f15f..78dabebe8fd0 100644 --- a/sound/soc/jz4740/qi_lb60.c +++ b/sound/soc/jz4740/qi_lb60.c @@ -60,10 +60,11 @@ static const struct snd_soc_dapm_route qi_lb60_routes[] = { SND_SOC_DAIFMT_NB_NF | \ SND_SOC_DAIFMT_CBM_CFM) -static int qi_lb60_codec_init(struct snd_soc_codec *codec) +static int qi_lb60_codec_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; - struct snd_soc_dai *cpu_dai = codec->socdev->card->dai_link->cpu_dai; snd_soc_dapm_nc_pin(codec, "LIN"); snd_soc_dapm_nc_pin(codec, "RIN"); @@ -84,8 +85,10 @@ static int qi_lb60_codec_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link qi_lb60_dai = { .name = "jz4740", .stream_name = "jz4740", - .cpu_dai = &jz4740_i2s_dai, - .codec_dai = &jz4740_codec_dai, + .cpu_dai_name = "jz4740-i2s", + .platform_name = "jz4740-pmc-audio", + .codec_dai_name = "jz4740-hifi", + .codec_name = "jz4740-codec", .init = qi_lb60_codec_init, }; @@ -93,12 +96,6 @@ static struct snd_soc_card qi_lb60 = { .name = "QI LB60", .dai_link = &qi_lb60_dai, .num_links = 1, - .platform = &jz4740_soc_platform, -}; - -static struct snd_soc_device qi_lb60_snd_devdata = { - .card = &qi_lb60, - .codec_dev = &soc_codec_dev_jz4740_codec, }; static struct platform_device *qi_lb60_snd_device; @@ -129,8 +126,7 @@ static int __init qi_lb60_init(void) gpio_direction_output(QI_LB60_SND_GPIO, 0); gpio_direction_output(QI_LB60_AMP_GPIO, 0); - platform_set_drvdata(qi_lb60_snd_device, &qi_lb60_snd_devdata); - qi_lb60_snd_devdata.dev = &qi_lb60_snd_device->dev; + platform_set_drvdata(qi_lb60_snd_device, &qi_lb60); ret = platform_device_add(qi_lb60_snd_device); if (ret) { diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index a30205be3e2b..693049d42d24 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c @@ -18,7 +18,6 @@ #include #include #include -#include "kirkwood-dma.h" #include "kirkwood.h" #define KIRKWOOD_RATES \ @@ -123,9 +122,10 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) int err; struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; + struct snd_soc_platform *platform = soc_runtime->platform; + struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; struct kirkwood_dma_data *priv; - struct kirkwood_dma_priv *prdata = cpu_dai->private_data; + struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform); unsigned long addr; priv = snd_soc_dai_get_dma_data(cpu_dai, substream); @@ -151,7 +151,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) if (err < 0) return err; - if (soc_runtime->dai->cpu_dai->private_data == NULL) { + if (prdata == NULL) { prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL); if (prdata == NULL) return -ENOMEM; @@ -165,7 +165,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) return -EBUSY; } - soc_runtime->dai->cpu_dai->private_data = prdata; + snd_soc_platform_set_drvdata(platform, prdata); /* * Enable Error interrupts. We're only ack'ing them but @@ -191,8 +191,9 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) static int kirkwood_dma_close(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; - struct kirkwood_dma_priv *prdata = cpu_dai->private_data; + struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; + struct snd_soc_platform *platform = soc_runtime->platform; + struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform); struct kirkwood_dma_data *priv; priv = snd_soc_dai_get_dma_data(cpu_dai, substream); @@ -209,7 +210,7 @@ static int kirkwood_dma_close(struct snd_pcm_substream *substream) writel(0, priv->io + KIRKWOOD_ERR_MASK); free_irq(priv->irq, prdata); kfree(prdata); - soc_runtime->dai->cpu_dai->private_data = NULL; + snd_soc_platform_set_drvdata(platform, NULL); } return 0; @@ -236,7 +237,7 @@ static int kirkwood_dma_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; struct kirkwood_dma_data *priv; unsigned long size, count; @@ -265,7 +266,7 @@ static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; struct kirkwood_dma_data *priv; snd_pcm_uframes_t count; @@ -320,14 +321,14 @@ static int kirkwood_dma_new(struct snd_card *card, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = 0xffffffff; - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = kirkwood_dma_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) return ret; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { ret = kirkwood_dma_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) @@ -357,25 +358,44 @@ static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm) } } -struct snd_soc_platform kirkwood_soc_platform = { - .name = "kirkwood-dma", - .pcm_ops = &kirkwood_dma_ops, +static struct snd_soc_platform_driver kirkwood_soc_platform = { + .ops = &kirkwood_dma_ops, .pcm_new = kirkwood_dma_new, .pcm_free = kirkwood_dma_free_dma_buffers, }; -EXPORT_SYMBOL_GPL(kirkwood_soc_platform); -static int __init kirkwood_soc_platform_init(void) +static int __devinit kirkwood_soc_platform_probe(struct platform_device *pdev) { - return snd_soc_register_platform(&kirkwood_soc_platform); + return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform); } -module_init(kirkwood_soc_platform_init); -static void __exit kirkwood_soc_platform_exit(void) +static int __devexit kirkwood_soc_platform_remove(struct platform_device *pdev) { - snd_soc_unregister_platform(&kirkwood_soc_platform); + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver kirkwood_pcm_driver = { + .driver = { + .name = "kirkwood-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = kirkwood_soc_platform_probe, + .remove = __devexit_p(kirkwood_soc_platform_remove), +}; + +static int __init kirkwood_pcm_init(void) +{ + return platform_driver_register(&kirkwood_pcm_driver); +} +module_init(kirkwood_pcm_init); + +static void __exit kirkwood_pcm_exit(void) +{ + platform_driver_unregister(&kirkwood_pcm_driver); } -module_exit(kirkwood_soc_platform_exit); +module_exit(kirkwood_pcm_exit); MODULE_AUTHOR("Arnaud Patard "); MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module"); diff --git a/sound/soc/kirkwood/kirkwood-dma.h b/sound/soc/kirkwood/kirkwood-dma.h deleted file mode 100644 index ba4454cd34f1..000000000000 --- a/sound/soc/kirkwood/kirkwood-dma.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * kirkwood-dma.h - * - * (c) 2010 Arnaud Patard - * - * 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. - */ - -#ifndef _KIRKWOOD_DMA_H -#define _KIRKWOOD_DMA_H - -extern struct snd_soc_platform kirkwood_soc_platform; - -#endif diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 981ffc2a13c8..9b62cba4f590 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -20,7 +20,6 @@ #include #include #include -#include "kirkwood-i2s.h" #include "kirkwood.h" #define DRV_NAME "kirkwood-i2s" @@ -33,13 +32,10 @@ SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE) - -struct snd_soc_dai kirkwood_i2s_dai; -static struct kirkwood_dma_data *priv; - static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { + struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai); unsigned long mask; unsigned long value; @@ -101,10 +97,20 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate) } while (value == 0); } +static int kirkwood_i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); + + snd_soc_dai_set_dma_data(dai, substream, priv); + return 0; +} + static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { + struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); unsigned int i2s_reg, reg; unsigned long i2s_value, value; @@ -171,6 +177,7 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { + struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); unsigned long value; /* @@ -244,6 +251,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { + struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); unsigned long value; value = readl(priv->io + KIRKWOOD_RECCTL); @@ -323,9 +331,9 @@ static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd, return 0; } -static int kirkwood_i2s_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int kirkwood_i2s_probe(struct snd_soc_dai *dai) { + struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); unsigned long value; unsigned int reg_data; @@ -359,21 +367,20 @@ static int kirkwood_i2s_probe(struct platform_device *pdev, } -static void kirkwood_i2s_remove(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int kirkwood_i2s_remove(struct snd_soc_dai *dai) { + return 0; } static struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { + .startup = kirkwood_i2s_startup, .trigger = kirkwood_i2s_trigger, .hw_params = kirkwood_i2s_hw_params, .set_fmt = kirkwood_i2s_set_fmt, }; -struct snd_soc_dai kirkwood_i2s_dai = { - .name = DRV_NAME, - .id = 0, +static struct snd_soc_dai_driver kirkwood_i2s_dai = { .probe = kirkwood_i2s_probe, .remove = kirkwood_i2s_remove, .playback = { @@ -388,13 +395,13 @@ struct snd_soc_dai kirkwood_i2s_dai = { .formats = KIRKWOOD_I2S_FORMATS,}, .ops = &kirkwood_i2s_dai_ops, }; -EXPORT_SYMBOL_GPL(kirkwood_i2s_dai); static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev) { struct resource *mem; struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data; + struct kirkwood_dma_data *priv; int err; priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL); @@ -403,6 +410,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev) err = -ENOMEM; goto error; } + dev_set_drvdata(&pdev->dev, priv); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { @@ -441,10 +449,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev) priv->dram = data->dram; priv->burst = data->burst; - kirkwood_i2s_dai.capture.dma_data = priv; - kirkwood_i2s_dai.playback.dma_data = priv; - - return snd_soc_register_dai(&kirkwood_i2s_dai); + return snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai); err_ioremap: iounmap(priv->io); @@ -458,12 +463,13 @@ error: static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev) { - if (priv) { - iounmap(priv->io); - release_mem_region(priv->mem->start, SZ_16K); - kfree(priv); - } - snd_soc_unregister_dai(&kirkwood_i2s_dai); + struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); + + snd_soc_unregister_dai(&pdev->dev); + iounmap(priv->io); + release_mem_region(priv->mem->start, SZ_16K); + kfree(priv); + return 0; } diff --git a/sound/soc/kirkwood/kirkwood-i2s.h b/sound/soc/kirkwood/kirkwood-i2s.h deleted file mode 100644 index c5595c616d7a..000000000000 --- a/sound/soc/kirkwood/kirkwood-i2s.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * kirkwood-i2s.h - * - * (c) 2010 Arnaud Patard - * - * 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. - */ - -#ifndef _KIRKWOOD_I2S_H -#define _KIRKWOOD_I2S_H - -extern struct snd_soc_dai kirkwood_i2s_dai; - -#endif diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c index 0353d06bc41a..cc1a1e277edf 100644 --- a/sound/soc/kirkwood/kirkwood-openrd.c +++ b/sound/soc/kirkwood/kirkwood-openrd.c @@ -18,16 +18,14 @@ #include #include #include -#include "kirkwood-i2s.h" -#include "kirkwood-dma.h" #include "../codecs/cs42l51.h" static int openrd_client_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; unsigned int freq, fmt; @@ -66,8 +64,10 @@ static struct snd_soc_dai_link openrd_client_dai[] = { { .name = "CS42L51", .stream_name = "CS42L51 HiFi", - .cpu_dai = &kirkwood_i2s_dai, - .codec_dai = &cs42l51_dai, + .cpu_dai_name = "kirkwood-i2s", + .platform_name = "kirkwood-pcm-audio", + .codec_dai_name = "cs42l51_hifi", + .codec_name = "cs42l51-codec.0-004a", .ops = &openrd_client_ops, }, }; @@ -75,16 +75,10 @@ static struct snd_soc_dai_link openrd_client_dai[] = { static struct snd_soc_card openrd_client = { .name = "OpenRD Client", - .platform = &kirkwood_soc_platform, .dai_link = openrd_client_dai, .num_links = ARRAY_SIZE(openrd_client_dai), }; -static struct snd_soc_device openrd_client_snd_devdata = { - .card = &openrd_client, - .codec_dev = &soc_codec_device_cs42l51, -}; - static struct platform_device *openrd_client_snd_device; static int __init openrd_client_init(void) @@ -99,8 +93,7 @@ static int __init openrd_client_init(void) return -ENOMEM; platform_set_drvdata(openrd_client_snd_device, - &openrd_client_snd_devdata); - openrd_client_snd_devdata.dev = &openrd_client_snd_device->dev; + &openrd_client); ret = platform_device_add(openrd_client_snd_device); if (ret) { diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index caa7c901bc2e..02b64a17dec2 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c @@ -297,8 +297,7 @@ static struct snd_soc_dai_ops nuc900_ac97_dai_ops = { .trigger = nuc900_ac97_trigger, }; -struct snd_soc_dai nuc900_ac97_dai = { - .name = "nuc900-ac97", +static struct snd_soc_dai_driver nuc900_ac97_dai = { .probe = nuc900_ac97_probe, .remove = nuc900_ac97_remove, .ac97_control = 1, @@ -316,7 +315,6 @@ struct snd_soc_dai nuc900_ac97_dai = { }, .ops = &nuc900_ac97_dai_ops, } -EXPORT_SYMBOL_GPL(nuc900_ac97_dai); static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev) { @@ -365,9 +363,7 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev) nuc900_ac97_data = nuc900_audio; - nuc900_audio->dev = nuc900_ac97_dai.dev = &pdev->dev; - - ret = snd_soc_register_dai(&nuc900_ac97_dai); + ret = snd_soc_register_dai(&pdev->dev, &nuc900_ac97_dai); if (ret) goto out3; @@ -390,7 +386,7 @@ out0: static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev) { - snd_soc_unregister_dai(&nuc900_ac97_dai); + snd_soc_unregister_dai(&pdev->dev); clk_put(nuc900_ac97_data->clk); iounmap(nuc900_ac97_data->mmio); @@ -404,7 +400,7 @@ static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev) static struct platform_driver nuc900_ac97_driver = { .driver = { - .name = "nuc900-audio", + .name = "nuc900-ac97", .owner = THIS_MODULE, }, .probe = nuc900_ac97_drvprobe, diff --git a/sound/soc/nuc900/nuc900-audio.c b/sound/soc/nuc900/nuc900-audio.c index 72e6f518f7b2..161f5b667d7b 100644 --- a/sound/soc/nuc900/nuc900-audio.c +++ b/sound/soc/nuc900/nuc900-audio.c @@ -20,26 +20,21 @@ #include #include -#include "../codecs/ac97.h" #include "nuc900-audio.h" static struct snd_soc_dai_link nuc900evb_ac97_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &nuc900_ac97_dai, - .codec_dai = &ac97_dai, + .cpu_dai_name = "nuc900-ac97", + .codec_dai_name = "ac97-hifi", + .codec_name = "ac97-codec", + .platform_name = "nuc900-pcm-audio", }; static struct snd_soc_card nuc900evb_audio_machine = { .name = "NUC900EVB_AC97", .dai_link = &nuc900evb_ac97_dai, .num_links = 1, - .platform = &nuc900_soc_platform, -}; - -static struct snd_soc_device nuc900evb_ac97_devdata = { - .card = &nuc900evb_audio_machine, - .codec_dev = &soc_codec_dev_ac97, }; static struct platform_device *nuc900evb_asoc_dev; @@ -54,9 +49,8 @@ static int __init nuc900evb_audio_init(void) goto out; /* nuc900 board audio device */ - platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_ac97_devdata); + platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_audio_machine); - nuc900evb_ac97_devdata.dev = &nuc900evb_asoc_dev->dev; ret = platform_device_add(nuc900evb_asoc_dev); if (ret) { diff --git a/sound/soc/nuc900/nuc900-audio.h b/sound/soc/nuc900/nuc900-audio.h index 3038f519729f..aeed8ead2b2b 100644 --- a/sound/soc/nuc900/nuc900-audio.h +++ b/sound/soc/nuc900/nuc900-audio.h @@ -110,8 +110,4 @@ struct nuc900_audio { }; -extern struct nuc900_audio *nuc900_ac97_data; -extern struct snd_soc_dai nuc900_ac97_dai; -extern struct snd_soc_platform nuc900_soc_platform; - #endif /*end _NUC900_AUDIO_H */ diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c index e81e803b3a63..195d1ac94771 100644 --- a/sound/soc/nuc900/nuc900-pcm.c +++ b/sound/soc/nuc900/nuc900-pcm.c @@ -328,26 +328,44 @@ static int nuc900_dma_new(struct snd_card *card, return 0; } -struct snd_soc_platform nuc900_soc_platform = { - .name = "nuc900-dma", - .pcm_ops = &nuc900_dma_ops, +static struct snd_soc_platform_driver nuc900_soc_platform = { + .ops = &nuc900_dma_ops, .pcm_new = nuc900_dma_new, .pcm_free = nuc900_dma_free_dma_buffers, } -EXPORT_SYMBOL_GPL(nuc900_soc_platform); -static int __init nuc900_soc_platform_init(void) +static int __devinit nuc900_soc_platform_probe(struct platform_device *pdev) { - return snd_soc_register_platform(&nuc900_soc_platform); + return snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform); } -static void __exit nuc900_soc_platform_exit(void) +static int __devexit nuc900_soc_platform_remove(struct platform_device *pdev) { - snd_soc_unregister_platform(&nuc900_soc_platform); + snd_soc_unregister_platform(&pdev->dev); + return 0; } -module_init(nuc900_soc_platform_init); -module_exit(nuc900_soc_platform_exit); +static struct platform_driver nuc900_pcm_driver = { + .driver = { + .name = "nuc900-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = nuc900_soc_platform_probe, + .remove = __devexit_p(nuc900_soc_platform_remove), +}; + +static int __init nuc900_pcm_init(void) +{ + return platform_driver_register(&nuc900_pcm_driver); +} +module_init(nuc900_pcm_init); + +static void __exit nuc900_pcm_exit(void) +{ + platform_driver_unregister(&nuc900_pcm_driver); +} +module_exit(nuc900_pcm_exit); MODULE_AUTHOR("Wan ZongShun, "); MODULE_DESCRIPTION("nuc900 Audio DMA module"); diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index 135901b2ea11..68bd902ccd4e 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -40,8 +40,8 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set codec DAI configuration */ @@ -111,8 +111,10 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MICIN", NULL, "Mic In"}, }; -static int am3517evm_aic23_init(struct snd_soc_codec *codec) +static int am3517evm_aic23_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + /* Add am3517-evm specific widgets */ snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, ARRAY_SIZE(tlv320aic23_dapm_widgets)); @@ -134,8 +136,10 @@ static int am3517evm_aic23_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link am3517evm_dai = { .name = "TLV320AIC23", .stream_name = "AIC23", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &tlv320aic23_dai, + .cpu_dai_name ="omap-mcbsp-dai.0", + .codec_dai_name = "tlv320aic23-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "tlv320aic23-codec", .init = am3517evm_aic23_init, .ops = &am3517evm_ops, }; @@ -143,17 +147,10 @@ static struct snd_soc_dai_link am3517evm_dai = { /* Audio machine driver */ static struct snd_soc_card snd_soc_am3517evm = { .name = "am3517evm", - .platform = &omap_soc_platform, .dai_link = &am3517evm_dai, .num_links = 1, }; -/* Audio subsystem */ -static struct snd_soc_device am3517evm_snd_devdata = { - .card = &snd_soc_am3517evm, - .codec_dev = &soc_codec_dev_tlv320aic23, -}; - static struct platform_device *am3517evm_snd_device; static int __init am3517evm_soc_init(void) @@ -172,9 +169,7 @@ static int __init am3517evm_soc_init(void) return -ENOMEM; } - platform_set_drvdata(am3517evm_snd_device, &am3517evm_snd_devdata); - am3517evm_snd_devdata.dev = &am3517evm_snd_device->dev; - *(unsigned int *)am3517evm_dai.cpu_dai->private_data = 0; /* McBSP1 */ + platform_set_drvdata(am3517evm_snd_device, &snd_soc_am3517evm); ret = platform_device_add(am3517evm_snd_device); if (ret) diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index b0f618e44840..9d88efa06e3c 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -99,7 +99,7 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, int pin, changed = 0; /* Refuse any mode changes if we are not able to control the codec. */ - if (!codec->control_data) + if (!codec->hw_write) return -EUNATCH; if (ucontrol->value.enumerated.item[0] >= control->max) @@ -268,10 +268,32 @@ static void cx81801_timeout(unsigned long data) ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0); } +/* + * Used for passing a codec structure pointer + * from the board initialization code to the tty line discipline. + */ +static struct snd_soc_codec *cx20442_codec; + /* Line discipline .open() */ static int cx81801_open(struct tty_struct *tty) { - return v253_ops.open(tty); + int ret; + + if (!cx20442_codec) + return -ENODEV; + + /* + * Pass the codec structure pointer for use by other ldisc callbacks, + * both the card and the codec specific parts. + */ + tty->disc_data = cx20442_codec; + + ret = v253_ops.open(tty); + + if (ret < 0) + tty->disc_data = NULL; + + return ret; } /* Line discipline .close() */ @@ -281,11 +303,14 @@ static void cx81801_close(struct tty_struct *tty) del_timer_sync(&cx81801_timer); - v253_ops.close(tty); - /* Prevent the hook switch from further changing the DAPM pins */ INIT_LIST_HEAD(&ams_delta_hook_switch.pins); + if (!codec) + return; + + v253_ops.close(tty); + /* Revert back to default audio input/output constellation */ snd_soc_dapm_disable_pin(codec, "Mouthpiece"); snd_soc_dapm_enable_pin(codec, "Earpiece"); @@ -310,7 +335,10 @@ static void cx81801_receive(struct tty_struct *tty, const unsigned char *c; int apply, ret; - if (!codec->control_data) { + if (!codec) + return; + + if (!codec->hw_write) { /* First modem response, complete setup procedure */ /* Initialize timer used for config pulse generation */ @@ -323,7 +351,7 @@ static void cx81801_receive(struct tty_struct *tty, ARRAY_SIZE(ams_delta_hook_switch_pins), ams_delta_hook_switch_pins); if (ret) - dev_warn(codec->socdev->card->dev, + dev_warn(codec->dev, "Failed to link hook switch to DAPM pins, " "will continue with hook switch unlinked.\n"); @@ -383,7 +411,7 @@ static int ams_delta_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; /* Set cpu DAI configuration */ - return snd_soc_dai_set_fmt(rtd->dai->cpu_dai, + return snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); @@ -398,7 +426,7 @@ static struct snd_soc_ops ams_delta_ops = { static int ams_delta_set_bias_level(struct snd_soc_card *card, enum snd_soc_bias_level level) { - struct snd_soc_codec *codec = card->codec; + struct snd_soc_codec *codec = card->rtd->codec; switch (level) { case SND_SOC_BIAS_ON: @@ -461,18 +489,22 @@ static void ams_delta_shutdown(struct snd_pcm_substream *substream) * Card initialization */ -static int ams_delta_cx20442_init(struct snd_soc_codec *codec) +static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_dai *codec_dai = codec->dai; - struct snd_soc_card *card = codec->socdev->card; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_card *card = rtd->card; int ret; /* Codec is ready, now add/activate board specific controls */ + /* Store a pointer to the codec structure for tty ldisc use */ + cx20442_codec = codec; + /* Set up digital mute if not provided by the codec */ - if (!codec_dai->ops) { - codec_dai->ops = &ams_delta_dai_ops; - } else if (!codec_dai->ops->digital_mute) { - codec_dai->ops->digital_mute = ams_delta_digital_mute; + if (!codec_dai->driver->ops) { + codec_dai->driver->ops = &ams_delta_dai_ops; + } else if (!codec_dai->driver->ops->digital_mute) { + codec_dai->driver->ops->digital_mute = ams_delta_digital_mute; } else { ams_delta_ops.startup = ams_delta_startup; ams_delta_ops.shutdown = ams_delta_shutdown; @@ -483,7 +515,7 @@ static int ams_delta_cx20442_init(struct snd_soc_codec *codec) /* Add hook switch - can be used to control the codec from userspace * even if line discipline fails */ - ret = snd_soc_jack_new(card, "hook_switch", + ret = snd_soc_jack_new(rtd->codec, "hook_switch", SND_JACK_HEADSET, &ams_delta_hook_switch); if (ret) dev_warn(card->dev, @@ -551,27 +583,22 @@ static int ams_delta_cx20442_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link ams_delta_dai_link = { .name = "CX20442", .stream_name = "CX20442", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &cx20442_dai, + .cpu_dai_name ="omap-mcbsp-dai.0", + .codec_dai_name = "cx20442-hifi", .init = ams_delta_cx20442_init, + .platform_name = "omap-pcm-audio", + .codec_name = "cx20442-codec", .ops = &ams_delta_ops, }; /* Audio card driver */ static struct snd_soc_card ams_delta_audio_card = { .name = "AMS_DELTA", - .platform = &omap_soc_platform, .dai_link = &ams_delta_dai_link, .num_links = 1, .set_bias_level = ams_delta_set_bias_level, }; -/* Audio subsystem */ -static struct snd_soc_device ams_delta_snd_soc_device = { - .card = &ams_delta_audio_card, - .codec_dev = &cx20442_codec_dev, -}; - /* Module init/exit */ static struct platform_device *ams_delta_audio_platform_device; static struct platform_device *cx20442_platform_device; @@ -589,9 +616,7 @@ static int __init ams_delta_module_init(void) return -ENOMEM; platform_set_drvdata(ams_delta_audio_platform_device, - &ams_delta_snd_soc_device); - ams_delta_snd_soc_device.dev = &ams_delta_audio_platform_device->dev; - *(unsigned int *)ams_delta_dai_link.cpu_dai->private_data = OMAP_MCBSP1; + &ams_delta_audio_card); ret = platform_device_add(ams_delta_audio_platform_device); if (ret) @@ -601,8 +626,8 @@ static int __init ams_delta_module_init(void) * Codec platform device could be registered from elsewhere (board?), * but I do it here as it makes sense only if used with the card. */ - cx20442_platform_device = platform_device_register_simple("cx20442", - -1, NULL, 0); + cx20442_platform_device = + platform_device_register_simple("cx20442-codec", -1, NULL, 0); return 0; err: platform_device_put(ams_delta_audio_platform_device); @@ -612,19 +637,6 @@ module_init(ams_delta_module_init); static void __exit ams_delta_module_exit(void) { - struct snd_soc_codec *codec; - struct tty_struct *tty; - - if (ams_delta_audio_card.codec) { - codec = ams_delta_audio_card.codec; - - if (codec->control_data) { - tty = codec->control_data; - - tty_hangup(tty); - } - } - if (tty_unregister_ldisc(N_V253) != 0) dev_warn(&ams_delta_audio_platform_device->dev, "failed to unregister V253 line discipline\n"); diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c index 3583c429f9be..d296cfcc672e 100644 --- a/sound/soc/omap/igep0020.c +++ b/sound/soc/omap/igep0020.c @@ -33,14 +33,13 @@ #include "omap-mcbsp.h" #include "omap-pcm.h" -#include "../codecs/twl4030.h" static int igep2_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set codec DAI configuration */ @@ -82,25 +81,20 @@ static struct snd_soc_ops igep2_ops = { static struct snd_soc_dai_link igep2_dai = { .name = "TWL4030", .stream_name = "TWL4030", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], + .cpu_dai_name = "omap-mcbsp-dai.1", + .codec_dai_name = "twl4030-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", .ops = &igep2_ops, }; /* Audio machine driver */ static struct snd_soc_card snd_soc_card_igep2 = { .name = "igep2", - .platform = &omap_soc_platform, .dai_link = &igep2_dai, .num_links = 1, }; -/* Audio subsystem */ -static struct snd_soc_device igep2_snd_devdata = { - .card = &snd_soc_card_igep2, - .codec_dev = &soc_codec_dev_twl4030, -}; - static struct platform_device *igep2_snd_device; static int __init igep2_soc_init(void) @@ -119,9 +113,7 @@ static int __init igep2_soc_init(void) return -ENOMEM; } - platform_set_drvdata(igep2_snd_device, &igep2_snd_devdata); - igep2_snd_devdata.dev = &igep2_snd_device->dev; - *(unsigned int *)igep2_dai.cpu_dai->private_data = 1; /* McBSP2 */ + platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2); ret = platform_device_add(igep2_snd_device); if (ret) diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c index 90b8bf71c893..928f03707451 100644 --- a/sound/soc/omap/mcpdm.c +++ b/sound/soc/omap/mcpdm.c @@ -402,7 +402,7 @@ int omap_mcpdm_set_offset(int offset1, int offset2) return 0; } -static int __devinit omap_mcpdm_probe(struct platform_device *pdev) +int __devinit omap_mcpdm_probe(struct platform_device *pdev) { struct resource *res; int ret = 0; @@ -449,7 +449,7 @@ exit: return ret; } -static int __devexit omap_mcpdm_remove(struct platform_device *pdev) +int __devexit omap_mcpdm_remove(struct platform_device *pdev) { struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev); @@ -468,18 +468,3 @@ static int __devexit omap_mcpdm_remove(struct platform_device *pdev) return 0; } -static struct platform_driver omap_mcpdm_driver = { - .probe = omap_mcpdm_probe, - .remove = __devexit_p(omap_mcpdm_remove), - .driver = { - .name = "omap-mcpdm", - }, -}; - -static struct platform_device *omap_mcpdm_device; - -static int __init omap_mcpdm_init(void) -{ - return platform_driver_register(&omap_mcpdm_driver); -} -arch_initcall(omap_mcpdm_init); diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h index 7bb326ef0886..df3e16fb51f3 100644 --- a/sound/soc/omap/mcpdm.h +++ b/sound/soc/omap/mcpdm.h @@ -149,3 +149,5 @@ extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink); extern int omap_mcpdm_request(void); extern void omap_mcpdm_free(void); extern int omap_mcpdm_set_offset(int offset1, int offset2); +int __devinit omap_mcpdm_probe(struct platform_device *pdev); +int __devexit omap_mcpdm_remove(struct platform_device *pdev); diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 08e09d72790f..a3b6d897ad84 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -97,7 +97,7 @@ static int n810_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); @@ -115,8 +115,8 @@ static int n810_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int err; /* Set codec DAI configuration */ @@ -271,8 +271,9 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = { n810_get_input, n810_set_input), }; -static int n810_aic33_init(struct snd_soc_codec *codec) +static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int err; /* Not connected */ @@ -307,8 +308,10 @@ static int n810_aic33_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link n810_dai = { .name = "TLV320AIC33", .stream_name = "AIC33", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &aic3x_dai, + .cpu_dai_name = "omap-mcbsp-dai.1", + .platform_name = "omap-pcm-audio", + .codec_name = "tlv320aic3x-codec.2-0018", + .codec_dai_name = "tlv320aic3x-hifi", .init = n810_aic33_init, .ops = &n810_ops, }; @@ -316,33 +319,12 @@ static struct snd_soc_dai_link n810_dai = { /* Audio machine driver */ static struct snd_soc_card snd_soc_n810 = { .name = "N810", - .platform = &omap_soc_platform, .dai_link = &n810_dai, .num_links = 1, }; -/* Audio private data */ -static struct aic3x_setup_data n810_aic33_setup = { - .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, - .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, -}; - -/* Audio subsystem */ -static struct snd_soc_device n810_snd_devdata = { - .card = &snd_soc_n810, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &n810_aic33_setup, -}; - static struct platform_device *n810_snd_device; -/* temporary i2c device creation until this can be moved into the machine - * support file. -*/ -static struct i2c_board_info i2c_device[] = { - { I2C_BOARD_INFO("tlv320aic3x", 0x1b), } -}; - static int __init n810_soc_init(void) { int err; @@ -351,15 +333,11 @@ static int __init n810_soc_init(void) if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax())) return -ENODEV; - i2c_register_board_info(1, i2c_device, ARRAY_SIZE(i2c_device)); - n810_snd_device = platform_device_alloc("soc-audio", -1); if (!n810_snd_device) return -ENOMEM; - platform_set_drvdata(n810_snd_device, &n810_snd_devdata); - n810_snd_devdata.dev = &n810_snd_device->dev; - *(unsigned int *)n810_dai.cpu_dai->private_data = 1; /* McBSP2 */ + platform_set_drvdata(n810_snd_device, &snd_soc_n810); err = platform_device_add(n810_snd_device); if (err) goto err1; diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 86f213905e2c..7ba5690118f8 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -62,8 +62,6 @@ struct omap_mcbsp_data { int wlen; }; -#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id) - static struct omap_mcbsp_data mcbsp_data[NUM_LINKS]; /* @@ -153,13 +151,13 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {}; static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_pcm_dma_data *dma_data; int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); int words; - dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) @@ -203,11 +201,9 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params, } static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); int bus_id = mcbsp_data->bus_id; int err = 0; @@ -249,11 +245,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, } static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); if (!cpu_dai->active) { omap_mcbsp_free(mcbsp_data->bus_id); @@ -262,11 +256,9 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, } static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); switch (cmd) { @@ -295,8 +287,8 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay( struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); u16 fifo_use; snd_pcm_sframes_t delay; @@ -317,11 +309,9 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay( static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; struct omap_pcm_dma_data *dma_data; int dma, bus_id = mcbsp_data->bus_id; @@ -496,7 +486,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; unsigned int temp_fmt = fmt; @@ -596,7 +586,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) { - struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; if (div_id != OMAP_MCBSP_CLKGDV) @@ -699,7 +689,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int err = 0; @@ -733,7 +723,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, return err; } -static struct snd_soc_dai_ops omap_mcbsp_dai_ops = { +static struct snd_soc_dai_ops mcbsp_dai_ops = { .startup = omap_mcbsp_dai_startup, .shutdown = omap_mcbsp_dai_shutdown, .trigger = omap_mcbsp_dai_trigger, @@ -744,42 +734,31 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = { .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, }; -#define OMAP_MCBSP_DAI_BUILDER(link_id) \ -{ \ - .name = "omap-mcbsp-dai-"#link_id, \ - .id = (link_id), \ - .playback = { \ - .channels_min = 1, \ - .channels_max = 16, \ - .rates = OMAP_MCBSP_RATES, \ - .formats = SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S32_LE, \ - }, \ - .capture = { \ - .channels_min = 1, \ - .channels_max = 16, \ - .rates = OMAP_MCBSP_RATES, \ - .formats = SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S32_LE, \ - }, \ - .ops = &omap_mcbsp_dai_ops, \ - .private_data = &mcbsp_data[(link_id)].bus_id, \ +static int mcbsp_dai_probe(struct snd_soc_dai *dai) +{ + mcbsp_data[dai->id].bus_id = dai->id; + snd_soc_dai_set_drvdata(dai, &mcbsp_data[dai->id].bus_id); + return 0; } -struct snd_soc_dai omap_mcbsp_dai[] = { - OMAP_MCBSP_DAI_BUILDER(0), - OMAP_MCBSP_DAI_BUILDER(1), -#if NUM_LINKS >= 3 - OMAP_MCBSP_DAI_BUILDER(2), -#endif -#if NUM_LINKS == 5 - OMAP_MCBSP_DAI_BUILDER(3), - OMAP_MCBSP_DAI_BUILDER(4), -#endif +static struct snd_soc_dai_driver omap_mcbsp_dai = +{ + .probe = mcbsp_dai_probe, + .playback = { + .channels_min = 1, + .channels_max = 16, + .rates = OMAP_MCBSP_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 16, + .rates = OMAP_MCBSP_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mcbsp_dai_ops, }; -EXPORT_SYMBOL_GPL(omap_mcbsp_dai); - int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -910,16 +889,36 @@ int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id) } EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); +static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) +{ + return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai); +} + +static int __devexit asoc_mcbsp_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + return 0; +} + +static struct platform_driver asoc_mcbsp_driver = { + .driver = { + .name = "omap-mcbsp-dai", + .owner = THIS_MODULE, + }, + + .probe = asoc_mcbsp_probe, + .remove = __devexit_p(asoc_mcbsp_remove), +}; + static int __init snd_omap_mcbsp_init(void) { - return snd_soc_register_dais(omap_mcbsp_dai, - ARRAY_SIZE(omap_mcbsp_dai)); + return platform_driver_register(&asoc_mcbsp_driver); } module_init(snd_omap_mcbsp_init); static void __exit snd_omap_mcbsp_exit(void) { - snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai)); + platform_driver_unregister(&asoc_mcbsp_driver); } module_exit(snd_omap_mcbsp_exit); diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index 6c363e5f4387..ffdcc5abb7b9 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -55,8 +55,6 @@ enum omap_mcbsp_div { #define NUM_LINKS 5 #endif -extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; - int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id); #endif diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index b7f4f7e015f3..f161c2f5ed36 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -36,7 +36,6 @@ #include #include #include "mcpdm.h" -#include "omap-mcpdm.h" #include "omap-pcm.h" struct omap_mcpdm_data { @@ -89,11 +88,9 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; int err = 0; - if (!cpu_dai->active) + if (!dai->active) err = omap_mcpdm_request(); return err; @@ -102,19 +99,14 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - - if (!cpu_dai->active) + if (!dai->active) omap_mcpdm_free(); } static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; + struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai); int stream = substream->stream; int err = 0; @@ -143,14 +135,12 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; + struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai); struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; int stream = substream->stream; int channels, err, link_mask = 0; - snd_soc_dai_set_dma_data(cpu_dai, substream, + snd_soc_dai_set_dma_data(dai, substream, &omap_mcpdm_dai_dma_params[stream]); channels = params_channels(params); @@ -189,9 +179,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; + struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai); struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; int stream = substream->stream; int err; @@ -215,9 +203,14 @@ static struct snd_soc_dai_ops omap_mcpdm_dai_ops = { #define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) #define OMAP_MCPDM_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) -struct snd_soc_dai omap_mcpdm_dai = { - .name = "omap-mcpdm", - .id = -1, +static int omap_mcpdm_dai_probe(struct snd_soc_dai *dai) +{ + snd_soc_dai_set_drvdata(dai, &mcpdm_data); + return 0; +} + +static struct snd_soc_dai_driver omap_mcpdm_dai = { + .probe = omap_mcpdm_dai_probe, .playback = { .channels_min = 1, .channels_max = 4, @@ -231,19 +224,47 @@ struct snd_soc_dai omap_mcpdm_dai = { .formats = OMAP_MCPDM_FORMATS, }, .ops = &omap_mcpdm_dai_ops, - .private_data = &mcpdm_data, }; -EXPORT_SYMBOL_GPL(omap_mcpdm_dai); + +static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) +{ + int ret; + + ret = omap_mcpdm_probe(pdev); + if (ret < 0) + return ret; + ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); + if (ret < 0) + omap_mcpdm_remove(pdev); + return ret; +} + +static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + omap_mcpdm_remove(pdev); + return 0; +} + +static struct platform_driver asoc_mcpdm_driver = { + .driver = { + .name = "omap-mcpdm-dai", + .owner = THIS_MODULE, + }, + + .probe = asoc_mcpdm_probe, + .remove = __devexit_p(asoc_mcpdm_remove), +}; static int __init snd_omap_mcpdm_init(void) { - return snd_soc_register_dai(&omap_mcpdm_dai); + return platform_driver_register(&asoc_mcpdm_driver); } module_init(snd_omap_mcpdm_init); static void __exit snd_omap_mcpdm_exit(void) { - snd_soc_unregister_dai(&omap_mcpdm_dai); + platform_driver_unregister(&asoc_mcpdm_driver); } module_exit(snd_omap_mcpdm_exit); diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h deleted file mode 100644 index 73b80d559345..000000000000 --- a/sound/soc/omap/omap-mcpdm.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * omap-mcpdm.h - * - * Copyright (C) 2009 Texas Instruments - * - * Contact: Misael Lopez Cruz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __OMAP_MCPDM_H__ -#define __OMAP_MCPDM_H__ - -extern struct snd_soc_dai omap_mcpdm_dai; - -#endif /* End of __OMAP_MCPDM_H__ */ diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 1e521904ea64..8caeb8d305c3 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -101,9 +101,10 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct omap_runtime_data *prtd = runtime->private_data; struct omap_pcm_dma_data *dma_data; + int err = 0; - dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); /* return if this is a bufferless transfer e.g. * codec <--> BT codec or GSM modem -- lg FIXME */ @@ -374,14 +375,14 @@ static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(64); - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = omap_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto out; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { ret = omap_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) @@ -392,25 +393,45 @@ out: return ret; } -struct snd_soc_platform omap_soc_platform = { - .name = "omap-pcm-audio", - .pcm_ops = &omap_pcm_ops, +static struct snd_soc_platform_driver omap_soc_platform = { + .ops = &omap_pcm_ops, .pcm_new = omap_pcm_new, .pcm_free = omap_pcm_free_dma_buffers, }; -EXPORT_SYMBOL_GPL(omap_soc_platform); -static int __init omap_soc_platform_init(void) +static __devinit int omap_pcm_probe(struct platform_device *pdev) +{ + return snd_soc_register_platform(&pdev->dev, + &omap_soc_platform); +} + +static int __devexit omap_pcm_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver omap_pcm_driver = { + .driver = { + .name = "omap-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = omap_pcm_probe, + .remove = __devexit_p(omap_pcm_remove), +}; + +static int __init snd_omap_pcm_init(void) { - return snd_soc_register_platform(&omap_soc_platform); + return platform_driver_register(&omap_pcm_driver); } -module_init(omap_soc_platform_init); +module_init(snd_omap_pcm_init); -static void __exit omap_soc_platform_exit(void) +static void __exit snd_omap_pcm_exit(void) { - snd_soc_unregister_platform(&omap_soc_platform); + platform_driver_unregister(&omap_pcm_driver); } -module_exit(omap_soc_platform_exit); +module_exit(snd_omap_pcm_exit); MODULE_AUTHOR("Jarkko Nikula "); MODULE_DESCRIPTION("OMAP PCM DMA module"); diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index b19975d26907..fea0515331fb 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h @@ -35,6 +35,4 @@ struct omap_pcm_dma_data { int packet_size; /* packet size only in PACKET mode */ }; -extern struct snd_soc_platform omap_soc_platform; - #endif diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c index c7adea38274c..38cd1894623e 100644 --- a/sound/soc/omap/omap2evm.c +++ b/sound/soc/omap/omap2evm.c @@ -35,15 +35,13 @@ #include "omap-mcbsp.h" #include "omap-pcm.h" -#include "../codecs/twl4030.h" static int omap2evm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) + struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set codec DAI configuration */ @@ -85,25 +83,20 @@ static struct snd_soc_ops omap2evm_ops = { static struct snd_soc_dai_link omap2evm_dai = { .name = "TWL4030", .stream_name = "TWL4030", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], + .cpu_dai_name = "omap-mcbsp-dai.1", + .codec_dai_name = "twl4030-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", .ops = &omap2evm_ops, }; /* Audio machine driver */ static struct snd_soc_card snd_soc_omap2evm = { .name = "omap2evm", - .platform = &omap_soc_platform, .dai_link = &omap2evm_dai, .num_links = 1, }; -/* Audio subsystem */ -static struct snd_soc_device omap2evm_snd_devdata = { - .card = &snd_soc_omap2evm, - .codec_dev = &soc_codec_dev_twl4030, -}; - static struct platform_device *omap2evm_snd_device; static int __init omap2evm_soc_init(void) @@ -122,9 +115,7 @@ static int __init omap2evm_soc_init(void) return -ENOMEM; } - platform_set_drvdata(omap2evm_snd_device, &omap2evm_snd_devdata); - omap2evm_snd_devdata.dev = &omap2evm_snd_device->dev; - *(unsigned int *)omap2evm_dai.cpu_dai->private_data = 1; /* McBSP2 */ + platform_set_drvdata(omap2evm_snd_device, &snd_soc_omap2evm); ret = platform_device_add(omap2evm_snd_device); if (ret) diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c index 240e0975dd6a..7c11e1afe9e6 100644 --- a/sound/soc/omap/omap3beagle.c +++ b/sound/soc/omap/omap3beagle.c @@ -33,14 +33,13 @@ #include "omap-mcbsp.h" #include "omap-pcm.h" -#include "../codecs/twl4030.h" static int omap3beagle_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int fmt; int ret; @@ -92,25 +91,21 @@ static struct snd_soc_ops omap3beagle_ops = { static struct snd_soc_dai_link omap3beagle_dai = { .name = "TWL4030", .stream_name = "TWL4030", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], + .cpu_dai_name = "omap-mcbsp-dai.1", + .platform_name = "omap-pcm-audio", + .codec_dai_name = "twl4030-hifi", + .codec_name = "twl4030-codec", .ops = &omap3beagle_ops, }; /* Audio machine driver */ static struct snd_soc_card snd_soc_omap3beagle = { .name = "omap3beagle", - .platform = &omap_soc_platform, + .owner = THIS_MODULE, .dai_link = &omap3beagle_dai, .num_links = 1, }; -/* Audio subsystem */ -static struct snd_soc_device omap3beagle_snd_devdata = { - .card = &snd_soc_omap3beagle, - .codec_dev = &soc_codec_dev_twl4030, -}; - static struct platform_device *omap3beagle_snd_device; static int __init omap3beagle_soc_init(void) @@ -129,9 +124,7 @@ static int __init omap3beagle_soc_init(void) return -ENOMEM; } - platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata); - omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev; - *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */ + platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle); ret = platform_device_add(omap3beagle_snd_device); if (ret) diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c index dfcb344092e4..1ac5babef00d 100644 --- a/sound/soc/omap/omap3evm.c +++ b/sound/soc/omap/omap3evm.c @@ -31,14 +31,13 @@ #include "omap-mcbsp.h" #include "omap-pcm.h" -#include "../codecs/twl4030.h" static int omap3evm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set codec DAI configuration */ @@ -80,32 +79,20 @@ static struct snd_soc_ops omap3evm_ops = { static struct snd_soc_dai_link omap3evm_dai = { .name = "TWL4030", .stream_name = "TWL4030", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], + .cpu_dai_name = "omap-mcbsp-dai.1", + .codec_dai_name = "twl4030-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", .ops = &omap3evm_ops, }; /* Audio machine driver */ static struct snd_soc_card snd_soc_omap3evm = { .name = "omap3evm", - .platform = &omap_soc_platform, .dai_link = &omap3evm_dai, .num_links = 1, }; -/* twl4030 setup */ -static struct twl4030_setup_data twl4030_setup = { - .ramp_delay_value = 4, - .sysclk = 26000, -}; - -/* Audio subsystem */ -static struct snd_soc_device omap3evm_snd_devdata = { - .card = &snd_soc_omap3evm, - .codec_dev = &soc_codec_dev_twl4030, - .codec_data = &twl4030_setup, -}; - static struct platform_device *omap3evm_snd_device; static int __init omap3evm_soc_init(void) @@ -124,10 +111,7 @@ static int __init omap3evm_soc_init(void) return -ENOMEM; } - platform_set_drvdata(omap3evm_snd_device, &omap3evm_snd_devdata); - omap3evm_snd_devdata.dev = &omap3evm_snd_device->dev; - *(unsigned int *)omap3evm_dai.cpu_dai->private_data = 1; - + platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm); ret = platform_device_add(omap3evm_snd_device); if (ret) goto err1; diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index 9eecac135bbb..dbd9d96b5f92 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c @@ -31,10 +31,10 @@ #include #include +#include #include "omap-mcbsp.h" #include "omap-pcm.h" -#include "../codecs/twl4030.h" #define OMAP3_PANDORA_DAC_POWER_GPIO 118 #define OMAP3_PANDORA_AMP_POWER_GPIO 14 @@ -47,8 +47,8 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; int ret; @@ -167,8 +167,9 @@ static const struct snd_soc_dapm_route omap3pandora_in_map[] = { {"Mic Bias 2", NULL, "Mic (external)"}, }; -static int omap3pandora_out_init(struct snd_soc_codec *codec) +static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int ret; /* All TWL4030 output pins are floating */ @@ -194,8 +195,9 @@ static int omap3pandora_out_init(struct snd_soc_codec *codec) return snd_soc_dapm_sync(codec); } -static int omap3pandora_in_init(struct snd_soc_codec *codec) +static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int ret; /* Not comnnected */ @@ -224,15 +226,19 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { { .name = "PCM1773", .stream_name = "HiFi Out", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], + .cpu_dai_name = "omap-mcbsp-dai.1", + .codec_dai_name = "twl4030-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", .ops = &omap3pandora_ops, .init = omap3pandora_out_init, }, { .name = "TWL4030", .stream_name = "Line/Mic In", - .cpu_dai = &omap_mcbsp_dai[1], - .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], + .cpu_dai_name = "omap-mcbsp-dai.3", + .codec_dai_name = "twl4030-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", .ops = &omap3pandora_ops, .init = omap3pandora_in_init, } @@ -241,17 +247,10 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { /* SoC card */ static struct snd_soc_card snd_soc_card_omap3pandora = { .name = "omap3pandora", - .platform = &omap_soc_platform, .dai_link = omap3pandora_dai, .num_links = ARRAY_SIZE(omap3pandora_dai), }; -/* Audio subsystem */ -static struct snd_soc_device omap3pandora_snd_data = { - .card = &snd_soc_card_omap3pandora, - .codec_dev = &soc_codec_dev_twl4030, -}; - static struct platform_device *omap3pandora_snd_device; static int __init omap3pandora_soc_init(void) @@ -294,10 +293,7 @@ static int __init omap3pandora_soc_init(void) goto fail1; } - platform_set_drvdata(omap3pandora_snd_device, &omap3pandora_snd_data); - omap3pandora_snd_data.dev = &omap3pandora_snd_device->dev; - *(unsigned int *)omap_mcbsp_dai[0].private_data = 1; /* McBSP2 */ - *(unsigned int *)omap_mcbsp_dai[1].private_data = 3; /* McBSP4 */ + platform_set_drvdata(omap3pandora_snd_device, &snd_soc_card_omap3pandora); ret = platform_device_add(omap3pandora_snd_device); if (ret) { diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index 498ca2e03519..f0e662556428 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c @@ -55,8 +55,8 @@ static int osk_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int err; /* Set codec DAI configuration */ @@ -113,8 +113,9 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MICIN", NULL, "Mic Jack"}, }; -static int osk_tlv320aic23_init(struct snd_soc_codec *codec) +static int osk_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; /* Add osk5912 specific widgets */ snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, @@ -136,8 +137,10 @@ static int osk_tlv320aic23_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link osk_dai = { .name = "TLV320AIC23", .stream_name = "AIC23", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &tlv320aic23_dai, + .cpu_dai_name = "omap-mcbsp-dai.0", + .codec_dai_name = "tlv320aic23-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "tlv320aic23-codec", .init = osk_tlv320aic23_init, .ops = &osk_ops, }; @@ -145,17 +148,10 @@ static struct snd_soc_dai_link osk_dai = { /* Audio machine driver */ static struct snd_soc_card snd_soc_card_osk = { .name = "OSK5912", - .platform = &omap_soc_platform, .dai_link = &osk_dai, .num_links = 1, }; -/* Audio subsystem */ -static struct snd_soc_device osk_snd_devdata = { - .card = &snd_soc_card_osk, - .codec_dev = &soc_codec_dev_tlv320aic23, -}; - static struct platform_device *osk_snd_device; static int __init osk_soc_init(void) @@ -171,9 +167,7 @@ static int __init osk_soc_init(void) if (!osk_snd_device) return -ENOMEM; - platform_set_drvdata(osk_snd_device, &osk_snd_devdata); - osk_snd_devdata.dev = &osk_snd_device->dev; - *(unsigned int *)osk_dai.cpu_dai->private_data = 0; /* McBSP1 */ + platform_set_drvdata(osk_snd_device, &snd_soc_card_osk); err = platform_device_add(osk_snd_device); if (err) goto err1; diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c index c25f5276ad6f..e95a607937de 100644 --- a/sound/soc/omap/overo.c +++ b/sound/soc/omap/overo.c @@ -33,14 +33,13 @@ #include "omap-mcbsp.h" #include "omap-pcm.h" -#include "../codecs/twl4030.h" static int overo_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set codec DAI configuration */ @@ -82,25 +81,20 @@ static struct snd_soc_ops overo_ops = { static struct snd_soc_dai_link overo_dai = { .name = "TWL4030", .stream_name = "TWL4030", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], + .cpu_dai_name = "omap-mcbsp-dai.1", + .codec_dai_name = "twl4030-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", .ops = &overo_ops, }; /* Audio machine driver */ static struct snd_soc_card snd_soc_card_overo = { .name = "overo", - .platform = &omap_soc_platform, .dai_link = &overo_dai, .num_links = 1, }; -/* Audio subsystem */ -static struct snd_soc_device overo_snd_devdata = { - .card = &snd_soc_card_overo, - .codec_dev = &soc_codec_dev_twl4030, -}; - static struct platform_device *overo_snd_device; static int __init overo_soc_init(void) @@ -119,9 +113,7 @@ static int __init overo_soc_init(void) return -ENOMEM; } - platform_set_drvdata(overo_snd_device, &overo_snd_devdata); - overo_snd_devdata.dev = &overo_snd_device->dev; - *(unsigned int *)overo_dai.cpu_dai->private_data = 1; /* McBSP2 */ + platform_set_drvdata(overo_snd_device, &snd_soc_card_overo); ret = platform_device_add(overo_snd_device); if (ret) diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 88052d29617f..d1d8098923ce 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -76,7 +77,7 @@ static int rx51_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); @@ -89,8 +90,8 @@ static int rx51_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int err; /* Set codec DAI configuration */ @@ -240,9 +241,9 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = { rx51_get_jack, rx51_set_jack), }; -static int rx51_aic34_init(struct snd_soc_codec *codec) +static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_card *card = codec->socdev->card; + struct snd_soc_codec *codec = rtd->codec; int err; /* Set up NC codec pins */ @@ -266,7 +267,7 @@ static int rx51_aic34_init(struct snd_soc_codec *codec) snd_soc_dapm_sync(codec); /* AV jack detection */ - err = snd_soc_jack_new(card, "AV Jack", + err = snd_soc_jack_new(codec, "AV Jack", SND_JACK_VIDEOOUT, &rx51_av_jack); if (err) return err; @@ -282,32 +283,20 @@ static struct snd_soc_dai_link rx51_dai[] = { { .name = "TLV320AIC34", .stream_name = "AIC34", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &aic3x_dai, + .cpu_dai_name = "omap-mcbsp-dai.1", + .codec_dai_name = "tlv320aic3x-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "tlv320aic3x-codec.2-0018", .init = rx51_aic34_init, .ops = &rx51_ops, }, }; -/* Audio private data */ -static struct aic3x_setup_data rx51_aic34_setup = { - .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, - .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, -}; - /* Audio card */ static struct snd_soc_card rx51_sound_card = { .name = "RX-51", .dai_link = rx51_dai, .num_links = ARRAY_SIZE(rx51_dai), - .platform = &omap_soc_platform, -}; - -/* Audio subsystem */ -static struct snd_soc_device rx51_snd_devdata = { - .card = &rx51_sound_card, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &rx51_aic34_setup, }; static struct platform_device *rx51_snd_device; @@ -330,9 +319,7 @@ static int __init rx51_soc_init(void) goto err1; } - platform_set_drvdata(rx51_snd_device, &rx51_snd_devdata); - rx51_snd_devdata.dev = &rx51_snd_device->dev; - *(unsigned int *)rx51_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ + platform_set_drvdata(rx51_snd_device, &rx51_sound_card); err = platform_device_add(rx51_snd_device); if (err) diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index 3c85c0f92823..76ce77b91844 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c @@ -36,9 +36,11 @@ #include #include +/* Register descriptions for twl4030 codec part */ +#include + #include "omap-mcbsp.h" #include "omap-pcm.h" -#include "../codecs/twl4030.h" /* TWL4030 PMBR1 Register */ #define TWL4030_INTBR_PMBR1 0x0D @@ -51,8 +53,8 @@ static int sdp3430_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set codec DAI configuration */ @@ -94,8 +96,8 @@ static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set codec DAI configuration */ @@ -186,8 +188,9 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Headset Stereophone", NULL, "HSOR"}, }; -static int sdp3430_twl4030_init(struct snd_soc_codec *codec) +static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int ret; /* Add SDP3430 specific widgets */ @@ -225,7 +228,7 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec) return ret; /* Headset jack detection */ - ret = snd_soc_jack_new(&snd_soc_sdp3430, "Headset Jack", + ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, &hs_jack); if (ret) return ret; @@ -241,14 +244,15 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec) return ret; } -static int sdp3430_twl4030_voice_init(struct snd_soc_codec *codec) +static int sdp3430_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; unsigned short reg; /* Enable voice interface */ - reg = codec->read(codec, TWL4030_REG_VOICE_IF); + reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF); reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; - codec->write(codec, TWL4030_REG_VOICE_IF, reg); + codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg); return 0; } @@ -259,16 +263,20 @@ static struct snd_soc_dai_link sdp3430_dai[] = { { .name = "TWL4030 I2S", .stream_name = "TWL4030 Audio", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], + .cpu_dai_name = "omap-mcbsp-dai.1", + .codec_dai_name = "twl4030-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", .init = sdp3430_twl4030_init, .ops = &sdp3430_ops, }, { .name = "TWL4030 PCM", .stream_name = "TWL4030 Voice", - .cpu_dai = &omap_mcbsp_dai[1], - .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE], + .cpu_dai_name = "omap-mcbsp-dai.2", + .codec_dai_name = "twl4030-voice", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", .init = sdp3430_twl4030_voice_init, .ops = &sdp3430_voice_ops, }, @@ -277,25 +285,10 @@ static struct snd_soc_dai_link sdp3430_dai[] = { /* Audio machine driver */ static struct snd_soc_card snd_soc_sdp3430 = { .name = "SDP3430", - .platform = &omap_soc_platform, .dai_link = sdp3430_dai, .num_links = ARRAY_SIZE(sdp3430_dai), }; -/* twl4030 setup */ -static struct twl4030_setup_data twl4030_setup = { - .ramp_delay_value = 3, - .sysclk = 26000, - .hs_extmute = 1, -}; - -/* Audio subsystem */ -static struct snd_soc_device sdp3430_snd_devdata = { - .card = &snd_soc_sdp3430, - .codec_dev = &soc_codec_dev_twl4030, - .codec_data = &twl4030_setup, -}; - static struct platform_device *sdp3430_snd_device; static int __init sdp3430_soc_init(void) @@ -315,10 +308,7 @@ static int __init sdp3430_soc_init(void) return -ENOMEM; } - platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata); - sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev; - *(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ - *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ + platform_set_drvdata(sdp3430_snd_device, &snd_soc_sdp3430); /* Set TWL4030 GPIO6 as EXTMUTE signal */ twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c index 4ebbde6b565f..62f6a622d791 100644 --- a/sound/soc/omap/sdp4430.c +++ b/sound/soc/omap/sdp4430.c @@ -31,7 +31,6 @@ #include #include "mcpdm.h" -#include "omap-mcpdm.h" #include "omap-pcm.h" #include "../codecs/twl6040.h" @@ -41,7 +40,7 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; int clk_id, freq; int ret; @@ -60,6 +59,7 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream, printk(KERN_ERR "can't set codec system clock\n"); return ret; } + return ret; } static struct snd_soc_ops sdp4430_ops = { @@ -126,8 +126,9 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Earphone Spk", NULL, "EP"}, }; -static int sdp4430_twl6040_init(struct snd_soc_codec *codec) +static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int ret; /* Add SDP4430 specific controls */ @@ -164,8 +165,10 @@ static int sdp4430_twl6040_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link sdp4430_dai = { .name = "TWL6040", .stream_name = "TWL6040", - .cpu_dai = &omap_mcpdm_dai, - .codec_dai = &twl6040_dai, + .cpu_dai_name ="omap-mcpdm-dai", + .codec_dai_name = "twl6040-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl6040-codec", .init = sdp4430_twl6040_init, .ops = &sdp4430_ops, }; @@ -173,17 +176,10 @@ static struct snd_soc_dai_link sdp4430_dai = { /* Audio machine driver */ static struct snd_soc_card snd_soc_sdp4430 = { .name = "SDP4430", - .platform = &omap_soc_platform, .dai_link = &sdp4430_dai, .num_links = 1, }; -/* Audio subsystem */ -static struct snd_soc_device sdp4430_snd_devdata = { - .card = &snd_soc_sdp4430, - .codec_dev = &soc_codec_dev_twl6040, -}; - static struct platform_device *sdp4430_snd_device; static int __init sdp4430_soc_init(void) @@ -202,8 +198,7 @@ static int __init sdp4430_soc_init(void) return -ENOMEM; } - platform_set_drvdata(sdp4430_snd_device, &sdp4430_snd_devdata); - sdp4430_snd_devdata.dev = &sdp4430_snd_device->dev; + platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430); ret = platform_device_add(sdp4430_snd_device); if (ret) diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 50a94ee76ecc..338dc9552bd6 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c @@ -29,21 +29,23 @@ #include #include #include +#include #include +/* Register descriptions for twl4030 codec part */ +#include + #include "omap-mcbsp.h" #include "omap-pcm.h" -#include "../codecs/twl4030.h" #define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15) -#define ZOOM2_HEADSET_EXTMUTE_GPIO 153 static int zoom2_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set codec DAI configuration */ @@ -85,8 +87,8 @@ static int zoom2_hw_voice_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set codec DAI configuration */ @@ -157,8 +159,9 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Aux In", NULL, "AUXR"}, }; -static int zoom2_twl4030_init(struct snd_soc_codec *codec) +static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int ret; /* Add Zoom2 specific widgets */ @@ -192,14 +195,15 @@ static int zoom2_twl4030_init(struct snd_soc_codec *codec) return ret; } -static int zoom2_twl4030_voice_init(struct snd_soc_codec *codec) +static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; unsigned short reg; /* Enable voice interface */ - reg = codec->read(codec, TWL4030_REG_VOICE_IF); + reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF); reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; - codec->write(codec, TWL4030_REG_VOICE_IF, reg); + codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg); return 0; } @@ -209,16 +213,20 @@ static struct snd_soc_dai_link zoom2_dai[] = { { .name = "TWL4030 I2S", .stream_name = "TWL4030 Audio", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], + .cpu_dai_name = "omap-mcbsp-dai.1", + .codec_dai_name = "twl4030-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", .init = zoom2_twl4030_init, .ops = &zoom2_ops, }, { .name = "TWL4030 PCM", .stream_name = "TWL4030 Voice", - .cpu_dai = &omap_mcbsp_dai[1], - .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE], + .cpu_dai_name = "omap-mcbsp-dai.2", + .codec_dai_name = "twl4030-voice", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", .init = zoom2_twl4030_voice_init, .ops = &zoom2_voice_ops, }, @@ -227,32 +235,10 @@ static struct snd_soc_dai_link zoom2_dai[] = { /* Audio machine driver */ static struct snd_soc_card snd_soc_zoom2 = { .name = "Zoom2", - .platform = &omap_soc_platform, .dai_link = zoom2_dai, .num_links = ARRAY_SIZE(zoom2_dai), }; -/* EXTMUTE callback function */ -void zoom2_set_hs_extmute(int mute) -{ - gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute); -} - -/* twl4030 setup */ -static struct twl4030_setup_data twl4030_setup = { - .ramp_delay_value = 3, /* 161 ms */ - .sysclk = 26000, - .hs_extmute = 1, - .set_hs_extmute = zoom2_set_hs_extmute, -}; - -/* Audio subsystem */ -static struct snd_soc_device zoom2_snd_devdata = { - .card = &snd_soc_zoom2, - .codec_dev = &soc_codec_dev_twl4030, - .codec_data = &twl4030_setup, -}; - static struct platform_device *zoom2_snd_device; static int __init zoom2_soc_init(void) @@ -271,11 +257,7 @@ static int __init zoom2_soc_init(void) return -ENOMEM; } - platform_set_drvdata(zoom2_snd_device, &zoom2_snd_devdata); - zoom2_snd_devdata.dev = &zoom2_snd_device->dev; - *(unsigned int *)zoom2_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ - *(unsigned int *)zoom2_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ - + platform_set_drvdata(zoom2_snd_device, &snd_soc_zoom2); ret = platform_device_add(zoom2_snd_device); if (ret) goto err1; diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index fefe1a57f31a..11c6a495f970 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -99,7 +99,7 @@ static void corgi_ext_control(struct snd_soc_codec *codec) static int corgi_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ corgi_ext_control(codec); @@ -118,8 +118,8 @@ static int corgi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int clk = 0; int ret = 0; @@ -272,8 +272,9 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = { /* * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device */ -static int corgi_wm8731_init(struct snd_soc_codec *codec) +static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int err; snd_soc_dapm_nc_pin(codec, "LLINEIN"); @@ -300,8 +301,10 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link corgi_dai = { .name = "WM8731", .stream_name = "WM8731", - .cpu_dai = &pxa_i2s_dai, - .codec_dai = &wm8731_dai, + .cpu_dai_name = "pxa-is2-dai", + .codec_dai_name = "wm8731-hifi", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm8731-codec-0.001a", .init = corgi_wm8731_init, .ops = &corgi_ops, }; @@ -309,17 +312,10 @@ static struct snd_soc_dai_link corgi_dai = { /* corgi audio machine driver */ static struct snd_soc_card snd_soc_corgi = { .name = "Corgi", - .platform = &pxa2xx_soc_platform, .dai_link = &corgi_dai, .num_links = 1, }; -/* corgi audio subsystem */ -static struct snd_soc_device corgi_snd_devdata = { - .card = &snd_soc_corgi, - .codec_dev = &soc_codec_dev_wm8731, -}; - static struct platform_device *corgi_snd_device; static int __init corgi_init(void) @@ -334,8 +330,7 @@ static int __init corgi_init(void) if (!corgi_snd_device) return -ENOMEM; - platform_set_drvdata(corgi_snd_device, &corgi_snd_devdata); - corgi_snd_devdata.dev = &corgi_snd_device->dev; + platform_set_drvdata(corgi_snd_device, &snd_soc_corgi); ret = platform_device_add(corgi_snd_device); if (ret) diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 7cd2f89d7b10..f614607b2055 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -24,7 +24,6 @@ #include #include "../codecs/wm9705.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" @@ -90,8 +89,10 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Mic Amp", NULL, "Mic (Internal)"}, }; -static int e740_ac97_init(struct snd_soc_codec *codec) +static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + snd_soc_dapm_nc_pin(codec, "HPOUTL"); snd_soc_dapm_nc_pin(codec, "HPOUTR"); snd_soc_dapm_nc_pin(codec, "PHONE"); @@ -116,30 +117,28 @@ static struct snd_soc_dai_link e740_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], - .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], + .cpu_dai_name = "pxa-ac97.0", + .codec_dai_name = "wm9705-hifi", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm9705-codec", .init = e740_ac97_init, }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], - .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], + .cpu_dai_name = "pxa-ac97.1", + .codec_dai_name = "wm9705-aux", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm9705-codec", }, }; static struct snd_soc_card e740 = { .name = "Toshiba e740", - .platform = &pxa2xx_soc_platform, .dai_link = e740_dai, .num_links = ARRAY_SIZE(e740_dai), }; -static struct snd_soc_device e740_snd_devdata = { - .card = &e740, - .codec_dev = &soc_codec_dev_wm9705, -}; - static struct platform_device *e740_snd_device; static int __init e740_init(void) @@ -178,8 +177,7 @@ static int __init e740_init(void) goto free_apwr_gpio; } - platform_set_drvdata(e740_snd_device, &e740_snd_devdata); - e740_snd_devdata.dev = &e740_snd_device->dev; + platform_set_drvdata(e740_snd_device, &e740); ret = platform_device_add(e740_snd_device); if (!ret) diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index 8dceccc5e059..4c143803a75e 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c @@ -24,7 +24,6 @@ #include #include "../codecs/wm9705.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, @@ -72,8 +71,10 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MIC1", NULL, "Mic (Internal)"}, }; -static int e750_ac97_init(struct snd_soc_codec *codec) +static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + snd_soc_dapm_nc_pin(codec, "LOUT"); snd_soc_dapm_nc_pin(codec, "ROUT"); snd_soc_dapm_nc_pin(codec, "PHONE"); @@ -98,31 +99,29 @@ static struct snd_soc_dai_link e750_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], - .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], + .cpu_dai_name = "pxa-ac97.0", + .codec_dai_name = "wm9705-hifi", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm9705-codec", .init = e750_ac97_init, /* use ops to check startup state */ }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], - .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], + .cpu_dai_name = "pxa-ac97.1", + .codec_dai_name ="wm9705-aux", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm9705-codec", }, }; static struct snd_soc_card e750 = { .name = "Toshiba e750", - .platform = &pxa2xx_soc_platform, .dai_link = e750_dai, .num_links = ARRAY_SIZE(e750_dai), }; -static struct snd_soc_device e750_snd_devdata = { - .card = &e750, - .codec_dev = &soc_codec_dev_wm9705, -}; - static struct platform_device *e750_snd_device; static int __init e750_init(void) @@ -154,8 +153,7 @@ static int __init e750_init(void) goto free_spk_amp_gpio; } - platform_set_drvdata(e750_snd_device, &e750_snd_devdata); - e750_snd_devdata.dev = &e750_snd_device->dev; + platform_set_drvdata(e750_snd_device, &e750); ret = platform_device_add(e750_snd_device); if (!ret) diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index bc019cdce429..d42e5fe832c5 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -23,7 +23,6 @@ #include #include "../codecs/wm9712.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, @@ -73,8 +72,10 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MIC2", NULL, "Mic (Internal2)"}, }; -static int e800_ac97_init(struct snd_soc_codec *codec) +static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + snd_soc_dapm_new_controls(codec, e800_dapm_widgets, ARRAY_SIZE(e800_dapm_widgets)); @@ -88,30 +89,28 @@ static struct snd_soc_dai_link e800_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], + .cpu_dai_name = "pxa-ac97.0", + .codec_dai_name = "wm9712-hifi", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm9712-codec", .init = e800_ac97_init, }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], + .cpu_dai_name = "pxa-ac97.1", + .codec_dai_name ="wm9712-aux", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm9712-codec", }, }; static struct snd_soc_card e800 = { .name = "Toshiba e800", - .platform = &pxa2xx_soc_platform, .dai_link = e800_dai, .num_links = ARRAY_SIZE(e800_dai), }; -static struct snd_soc_device e800_snd_devdata = { - .card = &e800, - .codec_dev = &soc_codec_dev_wm9712, -}; - static struct platform_device *e800_snd_device; static int __init e800_init(void) @@ -141,8 +140,7 @@ static int __init e800_init(void) if (!e800_snd_device) return -ENOMEM; - platform_set_drvdata(e800_snd_device, &e800_snd_devdata); - e800_snd_devdata.dev = &e800_snd_device->dev; + platform_set_drvdata(e800_snd_device, &e800); ret = platform_device_add(e800_snd_device); if (!ret) diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c index f4756e4025fd..7046128b2a4c 100644 --- a/sound/soc/pxa/em-x270.c +++ b/sound/soc/pxa/em-x270.c @@ -39,29 +39,27 @@ static struct snd_soc_dai_link em_x270_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], + .cpu_dai_name = "pxa-ac97.0", + .codec_dai_name = "wm9712-hifi", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm9712-codec", }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], + .cpu_dai_name = "pxa-ac97.1", + .codec_dai_name ="wm9712-aux", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm9712-codec", }, }; static struct snd_soc_card em_x270 = { .name = "EM-X270", - .platform = &pxa2xx_soc_platform, .dai_link = em_x270_dai, .num_links = ARRAY_SIZE(em_x270_dai), }; -static struct snd_soc_device em_x270_snd_devdata = { - .card = &em_x270, - .codec_dev = &soc_codec_dev_wm9712, -}; - static struct platform_device *em_x270_snd_device; static int __init em_x270_init(void) @@ -76,8 +74,7 @@ static int __init em_x270_init(void) if (!em_x270_snd_device) return -ENOMEM; - platform_set_drvdata(em_x270_snd_device, &em_x270_snd_devdata); - em_x270_snd_devdata.dev = &em_x270_snd_device->dev; + platform_set_drvdata(em_x270_snd_device, &em_x270); ret = platform_device_add(em_x270_snd_device); if (ret) diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c index 405587a01160..03765fc5ac74 100644 --- a/sound/soc/pxa/imote2.c +++ b/sound/soc/pxa/imote2.c @@ -6,14 +6,13 @@ #include "../codecs/wm8940.h" #include "pxa2xx-i2s.h" -#include "pxa2xx-pcm.h" static int imote2_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int clk = 0; int ret; @@ -64,23 +63,19 @@ static struct snd_soc_ops imote2_asoc_ops = { static struct snd_soc_dai_link imote2_dai = { .name = "WM8940", .stream_name = "WM8940", - .cpu_dai = &pxa_i2s_dai, - .codec_dai = &wm8940_dai, + .cpu_dai_name = "pxa-i2s", + .codec_dai_name = "wm8940-hifi", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm8940-codec.0-0034", .ops = &imote2_asoc_ops, }; static struct snd_soc_card snd_soc_imote2 = { .name = "Imote2", - .platform = &pxa2xx_soc_platform, .dai_link = &imote2_dai, .num_links = 1, }; -static struct snd_soc_device imote2_snd_devdata = { - .card = &snd_soc_imote2, - .codec_dev = &soc_codec_dev_wm8940, -}; - static struct platform_device *imote2_snd_device; static int __init imote2_asoc_init(void) @@ -93,8 +88,7 @@ static int __init imote2_asoc_init(void) if (!imote2_snd_device) return -ENOMEM; - platform_set_drvdata(imote2_snd_device, &imote2_snd_devdata); - imote2_snd_devdata.dev = &imote2_snd_device->dev; + platform_set_drvdata(imote2_snd_device, &snd_soc_imote2); ret = platform_device_add(imote2_snd_device); if (ret) platform_device_put(imote2_snd_device); diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index 4c8d99a8d386..608bc3dd835f 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -32,7 +32,6 @@ #include #include #include "../codecs/uda1380.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-i2s.h" #include "pxa-ssp.h" @@ -71,7 +70,7 @@ static void magician_ext_control(struct snd_soc_codec *codec) static int magician_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ magician_ext_control(codec); @@ -86,8 +85,8 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int acps, acds, width, rate; unsigned int div4 = PXA_SSP_CLK_SCDB_4; int ret = 0; @@ -227,8 +226,8 @@ static int magician_capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret = 0; /* set codec DAI configuration */ @@ -393,8 +392,9 @@ static const struct snd_kcontrol_new uda1380_magician_controls[] = { /* * Logic for a uda1380 as connected on a HTC Magician */ -static int magician_uda1380_init(struct snd_soc_codec *codec) +static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int err; /* NC codec pins */ @@ -427,16 +427,20 @@ static struct snd_soc_dai_link magician_dai[] = { { .name = "uda1380", .stream_name = "UDA1380 Playback", - .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1], - .codec_dai = &uda1380_dai[UDA1380_DAI_PLAYBACK], + .cpu_dai_name = "pxa-ssp-dai.0", + .codec_dai_name = "uda1380-hifi-playback", + .platform_name = "pxa-pcm-audio", + .codec_name = "uda1380-codec.0-0018", .init = magician_uda1380_init, .ops = &magician_playback_ops, }, { .name = "uda1380", .stream_name = "UDA1380 Capture", - .cpu_dai = &pxa_i2s_dai, - .codec_dai = &uda1380_dai[UDA1380_DAI_CAPTURE], + .cpu_dai_name = "pxa-i2s", + .codec_dai_name = "uda1380-hifi-capture", + .platform_name = "pxa-pcm-audio", + .codec_name = "uda1380-codec.0-0018", .ops = &magician_capture_ops, } }; @@ -446,13 +450,7 @@ static struct snd_soc_card snd_soc_card_magician = { .name = "Magician", .dai_link = magician_dai, .num_links = ARRAY_SIZE(magician_dai), - .platform = &pxa2xx_soc_platform, -}; -/* magician audio subsystem */ -static struct snd_soc_device magician_snd_devdata = { - .card = &snd_soc_card_magician, - .codec_dev = &soc_codec_dev_uda1380, }; static struct platform_device *magician_snd_device; @@ -514,8 +512,7 @@ static int __init magician_init(void) goto err_pdev; } - platform_set_drvdata(magician_snd_device, &magician_snd_devdata); - magician_snd_devdata.dev = &magician_snd_device->dev; + platform_set_drvdata(magician_snd_device, &snd_soc_card_magician); ret = platform_device_add(magician_snd_device); if (ret) { platform_device_put(magician_snd_device); diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 19eda8bbfdaf..f284cc54bc80 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -54,7 +54,6 @@ #include #include -#include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" #include "../codecs/wm9713.h" @@ -128,8 +127,9 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Rear Speaker", NULL, "SPKR"}, }; -static int mioa701_wm9713_init(struct snd_soc_codec *codec) +static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; unsigned short reg; /* Add mioa701 specific widgets */ @@ -139,12 +139,12 @@ static int mioa701_wm9713_init(struct snd_soc_codec *codec) snd_soc_dapm_add_routes(codec, ARRAY_AND_SIZE(audio_map)); /* Prepare GPIO8 for rear speaker amplifier */ - reg = codec->read(codec, AC97_GPIO_CFG); - codec->write(codec, AC97_GPIO_CFG, reg | 0x0100); + reg = codec->driver->read(codec, AC97_GPIO_CFG); + codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100); /* Prepare MIC input */ - reg = codec->read(codec, AC97_3D_CONTROL); - codec->write(codec, AC97_3D_CONTROL, reg | 0xc000); + reg = codec->driver->read(codec, AC97_3D_CONTROL); + codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000); snd_soc_dapm_enable_pin(codec, "Front Speaker"); snd_soc_dapm_enable_pin(codec, "Rear Speaker"); @@ -162,32 +162,30 @@ static struct snd_soc_dai_link mioa701_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], - .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], + .cpu_dai_name = "pxa-ac97.0", + .codec_dai_name = "wm9713-hifi", + .codec_name = "wm9713-codec", .init = mioa701_wm9713_init, + .platform_name = "pxa-pcm-audio", .ops = &mioa701_ops, }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], - .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX], + .cpu_dai_name = "pxa-ac97.1", + .codec_dai_name ="wm9713-aux", + .codec_name = "wm9713-codec", + .platform_name = "pxa-pcm-audio", .ops = &mioa701_ops, }, }; static struct snd_soc_card mioa701 = { .name = "MioA701", - .platform = &pxa2xx_soc_platform, .dai_link = mioa701_dai, .num_links = ARRAY_SIZE(mioa701_dai), }; -static struct snd_soc_device mioa701_snd_devdata = { - .card = &mioa701, - .codec_dev = &soc_codec_dev_wm9713, -}; - static struct platform_device *mioa701_snd_device; static int mioa701_wm9713_probe(struct platform_device *pdev) @@ -205,8 +203,7 @@ static int mioa701_wm9713_probe(struct platform_device *pdev) if (!mioa701_snd_device) return -ENOMEM; - platform_set_drvdata(mioa701_snd_device, &mioa701_snd_devdata); - mioa701_snd_devdata.dev = &mioa701_snd_device->dev; + platform_set_drvdata(mioa701_snd_device, &mioa701); ret = platform_device_add(mioa701_snd_device); if (!ret) diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 1f96e3227be5..13f6d485d571 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c @@ -29,7 +29,6 @@ #include #include "../codecs/wm9712.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" static struct snd_soc_jack hs_jack; @@ -75,8 +74,9 @@ static const struct snd_soc_dapm_route audio_map[] = { static struct snd_soc_card palm27x_asoc; -static int palm27x_ac97_init(struct snd_soc_codec *codec) +static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int err; /* add palm27x specific widgets */ @@ -112,7 +112,7 @@ static int palm27x_ac97_init(struct snd_soc_codec *codec) return err; /* Jack detection API stuff */ - err = snd_soc_jack_new(&palm27x_asoc, "Headphone Jack", + err = snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, &hs_jack); if (err) return err; @@ -132,30 +132,28 @@ static struct snd_soc_dai_link palm27x_dai[] = { { .name = "AC97 HiFi", .stream_name = "AC97 HiFi", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], + .cpu_dai_name = "pxa-ac97.0", + .codec_dai_name = "wm9712-hifi", + .codec_name = "wm9712-codec", + .platform_name = "pxa-pcm-audio", .init = palm27x_ac97_init, }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], + .cpu_dai_name = "pxa-ac97.1", + .codec_dai_name = "wm9712-aux", + .codec_name = "wm9712-codec", + .platform_name = "pxa-pcm-audio", }, }; static struct snd_soc_card palm27x_asoc = { .name = "Palm/PXA27x", - .platform = &pxa2xx_soc_platform, .dai_link = palm27x_dai, .num_links = ARRAY_SIZE(palm27x_dai), }; -static struct snd_soc_device palm27x_snd_devdata = { - .card = &palm27x_asoc, - .codec_dev = &soc_codec_dev_wm9712, -}; - static struct platform_device *palm27x_snd_device; static int palm27x_asoc_probe(struct platform_device *pdev) @@ -178,8 +176,7 @@ static int palm27x_asoc_probe(struct platform_device *pdev) if (!palm27x_snd_device) return -ENOMEM; - platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata); - palm27x_snd_devdata.dev = &palm27x_snd_device->dev; + platform_set_drvdata(palm27x_snd_device, &palm27x_asoc); ret = platform_device_add(palm27x_snd_device); if (ret != 0) diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index c5f36e0eab58..3ba5a962ecb8 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -31,7 +31,6 @@ #include #include "../codecs/wm8731.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-i2s.h" #define POODLE_HP 1 @@ -76,7 +75,7 @@ static void poodle_ext_control(struct snd_soc_codec *codec) static int poodle_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ poodle_ext_control(codec); @@ -97,8 +96,8 @@ static int poodle_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int clk = 0; int ret = 0; @@ -237,8 +236,9 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = { /* * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device */ -static int poodle_wm8731_init(struct snd_soc_codec *codec) +static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int err; snd_soc_dapm_nc_pin(codec, "LLINEIN"); @@ -266,8 +266,10 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link poodle_dai = { .name = "WM8731", .stream_name = "WM8731", - .cpu_dai = &pxa_i2s_dai, - .codec_dai = &wm8731_dai, + .cpu_dai_name = "pxa-i2s", + .codec_dai_name = "wm8731-hifi" + .platform_name = "pxa-pcm-audio", + .codec_name = "wm8731-codec.0-001a", .init = poodle_wm8731_init, .ops = &poodle_ops, }; @@ -275,15 +277,9 @@ static struct snd_soc_dai_link poodle_dai = { /* poodle audio machine driver */ static struct snd_soc_card snd_soc_poodle = { .name = "Poodle", - .platform = &pxa2xx_soc_platform, .dai_link = &poodle_dai, .num_links = 1, -}; - -/* poodle audio subsystem */ -static struct snd_soc_device poodle_snd_devdata = { - .card = &snd_soc_poodle, - .codec_dev = &soc_codec_dev_wm8731, + .owner = THIS_MODULE, }; static struct platform_device *poodle_snd_device; @@ -307,8 +303,7 @@ static int __init poodle_init(void) if (!poodle_snd_device) return -ENOMEM; - platform_set_drvdata(poodle_snd_device, &poodle_snd_devdata); - poodle_snd_devdata.dev = &poodle_snd_device->dev; + platform_set_drvdata(poodle_snd_device, &snd_soc_poodle); ret = platform_device_add(poodle_snd_device); if (ret) diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index a1fd23e0e3d0..99d80e85621c 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -108,11 +108,9 @@ pxa_ssp_get_dma_params(struct ssp_device *ssp, int width4, int out) } static int pxa_ssp_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; int ret = 0; @@ -128,11 +126,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, } static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; if (!cpu_dai->active) { @@ -148,7 +144,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) { - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; if (!cpu_dai->active) @@ -166,7 +162,7 @@ static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai) { - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE; @@ -230,7 +226,7 @@ static u32 pxa_ssp_get_scr(struct ssp_device *ssp) static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; int val; @@ -287,7 +283,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) { - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; int val; @@ -338,7 +334,7 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; u32 ssacd = pxa_ssp_read_reg(ssp, SSACD) & ~0x70; @@ -407,7 +403,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; u32 sscr0; @@ -442,7 +438,7 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai, int tristate) { - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; u32 sscr1; @@ -464,7 +460,7 @@ static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai, static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; u32 sscr0; u32 sscr1; @@ -555,11 +551,9 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, */ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; int chn = params_channels(params); u32 sscr0; @@ -568,7 +562,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf; struct pxa2xx_pcm_dma_params *dma_data; - dma_data = snd_soc_dai_get_dma_data(dai, substream); + dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); /* generate correct DMA params */ kfree(dma_data); @@ -581,7 +575,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, ((chn == 2) && (ttsa != 1)) || (width == 32), substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - snd_soc_dai_set_dma_data(dai, substream, dma_data); + snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); /* we can only change the settings if the port is not in use */ if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) @@ -668,12 +662,10 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, } static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; int ret = 0; - struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; int val; @@ -729,8 +721,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, return ret; } -static int pxa_ssp_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int pxa_ssp_probe(struct snd_soc_dai *dai) { struct ssp_priv *priv; int ret; @@ -746,7 +737,7 @@ static int pxa_ssp_probe(struct platform_device *pdev, } priv->dai_fmt = (unsigned int) -1; - dai->private_data = priv; + snd_soc_dai_set_drvdata(dai, priv); return 0; @@ -755,11 +746,12 @@ err_priv: return ret; } -static void pxa_ssp_remove(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int pxa_ssp_remove(struct snd_soc_dai *dai) { - struct ssp_priv *priv = dai->private_data; + struct ssp_priv *priv = snd_soc_dai_get_drvdata(dai); + pxa_ssp_free(priv->ssp); + return 0; } #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ @@ -784,10 +776,7 @@ static struct snd_soc_dai_ops pxa_ssp_dai_ops = { .set_tristate = pxa_ssp_set_dai_tristate, }; -struct snd_soc_dai pxa_ssp_dai[] = { - { - .name = "pxa2xx-ssp1", - .id = 0, +static struct snd_soc_dai_driver pxa_ssp_dai = { .probe = pxa_ssp_probe, .remove = pxa_ssp_remove, .suspend = pxa_ssp_suspend, @@ -805,81 +794,38 @@ struct snd_soc_dai pxa_ssp_dai[] = { .formats = PXA_SSP_FORMATS, }, .ops = &pxa_ssp_dai_ops, +}; + +static __devinit int asoc_ssp_probe(struct platform_device *pdev) +{ + return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai); +} + +static int __devexit asoc_ssp_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + return 0; +} + +static struct platform_driver asoc_ssp_driver = { + .driver = { + .name = "pxa-ssp-dai", + .owner = THIS_MODULE, }, - { .name = "pxa2xx-ssp2", - .id = 1, - .probe = pxa_ssp_probe, - .remove = pxa_ssp_remove, - .suspend = pxa_ssp_suspend, - .resume = pxa_ssp_resume, - .playback = { - .channels_min = 1, - .channels_max = 8, - .rates = PXA_SSP_RATES, - .formats = PXA_SSP_FORMATS, - }, - .capture = { - .channels_min = 1, - .channels_max = 8, - .rates = PXA_SSP_RATES, - .formats = PXA_SSP_FORMATS, - }, - .ops = &pxa_ssp_dai_ops, - }, - { - .name = "pxa2xx-ssp3", - .id = 2, - .probe = pxa_ssp_probe, - .remove = pxa_ssp_remove, - .suspend = pxa_ssp_suspend, - .resume = pxa_ssp_resume, - .playback = { - .channels_min = 1, - .channels_max = 8, - .rates = PXA_SSP_RATES, - .formats = PXA_SSP_FORMATS, - }, - .capture = { - .channels_min = 1, - .channels_max = 8, - .rates = PXA_SSP_RATES, - .formats = PXA_SSP_FORMATS, - }, - .ops = &pxa_ssp_dai_ops, - }, - { - .name = "pxa2xx-ssp4", - .id = 3, - .probe = pxa_ssp_probe, - .remove = pxa_ssp_remove, - .suspend = pxa_ssp_suspend, - .resume = pxa_ssp_resume, - .playback = { - .channels_min = 1, - .channels_max = 8, - .rates = PXA_SSP_RATES, - .formats = PXA_SSP_FORMATS, - }, - .capture = { - .channels_min = 1, - .channels_max = 8, - .rates = PXA_SSP_RATES, - .formats = PXA_SSP_FORMATS, - }, - .ops = &pxa_ssp_dai_ops, - }, + + .probe = asoc_ssp_probe, + .remove = __devexit_p(asoc_ssp_remove), }; -EXPORT_SYMBOL_GPL(pxa_ssp_dai); static int __init pxa_ssp_init(void) { - return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); + return platform_driver_register(&asoc_ssp_driver); } module_init(pxa_ssp_init); static void __exit pxa_ssp_exit(void) { - snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); + platform_driver_unregister(&asoc_ssp_driver); } module_exit(pxa_ssp_exit); diff --git a/sound/soc/pxa/pxa-ssp.h b/sound/soc/pxa/pxa-ssp.h index 91deadd55675..bc79da221c0d 100644 --- a/sound/soc/pxa/pxa-ssp.h +++ b/sound/soc/pxa/pxa-ssp.h @@ -42,6 +42,4 @@ #define PXA_SSP_PLL_OUT 0 -extern struct snd_soc_dai pxa_ssp_dai[4]; - #endif diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index d314115e3dd7..9c2bafa112ad 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -104,24 +104,21 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai) #define pxa2xx_ac97_resume NULL #endif -static int pxa2xx_ac97_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int pxa2xx_ac97_probe(struct snd_soc_dai *dai) { return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev)); } -static void pxa2xx_ac97_remove(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int pxa2xx_ac97_remove(struct snd_soc_dai *dai) { pxa2xx_ac97_hw_remove(to_platform_device(dai->dev)); + return 0; } static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct pxa2xx_pcm_dma_params *dma_data; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -136,10 +133,8 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct pxa2xx_pcm_dma_params *dma_data; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -154,11 +149,8 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) return -ENODEV; else @@ -188,10 +180,9 @@ static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = { * There is only 1 physical AC97 interface for pxa2xx, but it * has extra fifo's that can be used for aux DACs and ADCs. */ -struct snd_soc_dai pxa_ac97_dai[] = { +static struct snd_soc_dai_driver pxa_ac97_dai[] = { { .name = "pxa2xx-ac97", - .id = 0, .ac97_control = 1, .probe = pxa2xx_ac97_probe, .remove = pxa2xx_ac97_remove, @@ -213,7 +204,6 @@ struct snd_soc_dai pxa_ac97_dai[] = { }, { .name = "pxa2xx-ac97-aux", - .id = 1, .ac97_control = 1, .playback = { .stream_name = "AC97 Aux Playback", @@ -231,7 +221,6 @@ struct snd_soc_dai pxa_ac97_dai[] = { }, { .name = "pxa2xx-ac97-mic", - .id = 2, .ac97_control = 1, .capture = { .stream_name = "AC97 Mic Capture", @@ -243,36 +232,26 @@ struct snd_soc_dai pxa_ac97_dai[] = { }, }; -EXPORT_SYMBOL_GPL(pxa_ac97_dai); EXPORT_SYMBOL_GPL(soc_ac97_ops); -static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev) +static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev) { - int i; - pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data; - - if (pdev->id >= 0) { + if (pdev->id != -1) { dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); return -ENXIO; } - for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) { - pxa_ac97_dai[i].dev = &pdev->dev; - if (pdata && pdata->codec_pdata[0]) - pxa_ac97_dai[i].ac97_pdata = pdata->codec_pdata[0]; - } - /* Punt most of the init to the SoC probe; we may need the machine * driver to do interesting things with the clocking to get us up * and running. */ - return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); + return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai, + ARRAY_SIZE(pxa_ac97_dai)); } static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev) { - snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); - + snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai)); return 0; } diff --git a/sound/soc/pxa/pxa2xx-ac97.h b/sound/soc/pxa/pxa2xx-ac97.h index e390de8edcd4..eda891e6f31b 100644 --- a/sound/soc/pxa/pxa2xx-ac97.h +++ b/sound/soc/pxa/pxa2xx-ac97.h @@ -14,8 +14,6 @@ #define PXA2XX_DAI_AC97_AUX 1 #define PXA2XX_DAI_AC97_MIC 2 -extern struct snd_soc_dai pxa_ac97_dai[3]; - /* platform data */ extern struct snd_ac97_bus_ops pxa2xx_ac97_ops; diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index c1a5275721e4..3b473b200a8f 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -80,6 +80,7 @@ struct pxa_i2s_port { }; static struct pxa_i2s_port pxa_i2s; static struct clk *clk_i2s; +static int clk_ena = 0; static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { .name = "I2S PCM Stereo out", @@ -101,7 +102,7 @@ static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; if (IS_ERR(clk_i2s)) return PTR_ERR(clk_i2s); @@ -162,13 +163,11 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct pxa2xx_pcm_dma_params *dma_data; BUG_ON(IS_ERR(clk_i2s)); clk_enable(clk_i2s); - dai->private_data = dai; + clk_ena = 1; pxa_i2s_wait(); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -176,7 +175,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, else dma_data = &pxa2xx_i2s_pcm_stereo_in; - snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); + snd_soc_dai_set_dma_data(dai, substream, dma_data); /* is port used by another stream */ if (!(SACR0 & SACR0_ENB)) { @@ -259,9 +258,9 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream, if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) { SACR0 &= ~SACR0_ENB; pxa_i2s_wait(); - if (dai->private_data != NULL) { + if (clk_ena) { clk_disable(clk_i2s); - dai->private_data = NULL; + clk_ena = 0; } } } @@ -300,6 +299,35 @@ static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) #define pxa2xx_i2s_resume NULL #endif +static int pxa2xx_i2s_probe(struct snd_soc_dai *dai) +{ + clk_i2s = clk_get(dai->dev, "I2SCLK"); + if (IS_ERR(clk_i2s)) + return PTR_ERR(clk_i2s); + + /* + * PXA Developer's Manual: + * If SACR0[ENB] is toggled in the middle of a normal operation, + * the SACR0[RST] bit must also be set and cleared to reset all + * I2S controller registers. + */ + SACR0 = SACR0_RST; + SACR0 = 0; + /* Make sure RPL and REC are disabled */ + SACR1 = SACR1_DRPL | SACR1_DREC; + /* Along with FIFO servicing */ + SAIMR &= ~(SAIMR_RFS | SAIMR_TFS); + + return 0; +} + +static int pxa2xx_i2s_remove(struct snd_soc_dai *dai) +{ + clk_put(clk_i2s); + clk_i2s = ERR_PTR(-ENOENT); + return 0; +} + #define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) @@ -313,9 +341,9 @@ static struct snd_soc_dai_ops pxa_i2s_dai_ops = { .set_sysclk = pxa2xx_i2s_set_dai_sysclk, }; -struct snd_soc_dai pxa_i2s_dai = { - .name = "pxa2xx-i2s", - .id = 0, +static struct snd_soc_dai_driver pxa_i2s_dai = { + .probe = pxa2xx_i2s_probe, + .remove = pxa2xx_i2s_remove, .suspend = pxa2xx_i2s_suspend, .resume = pxa2xx_i2s_resume, .playback = { @@ -332,49 +360,20 @@ struct snd_soc_dai pxa_i2s_dai = { .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(pxa_i2s_dai); - -static int pxa2xx_i2s_probe(struct platform_device *dev) +static int pxa2xx_i2s_drv_probe(struct platform_device *pdev) { - int ret; - - clk_i2s = clk_get(&dev->dev, "I2SCLK"); - if (IS_ERR(clk_i2s)) - return PTR_ERR(clk_i2s); - - pxa_i2s_dai.dev = &dev->dev; - pxa_i2s_dai.private_data = NULL; - ret = snd_soc_register_dai(&pxa_i2s_dai); - if (ret != 0) - clk_put(clk_i2s); - - /* - * PXA Developer's Manual: - * If SACR0[ENB] is toggled in the middle of a normal operation, - * the SACR0[RST] bit must also be set and cleared to reset all - * I2S controller registers. - */ - SACR0 = SACR0_RST; - SACR0 = 0; - /* Make sure RPL and REC are disabled */ - SACR1 = SACR1_DRPL | SACR1_DREC; - /* Along with FIFO servicing */ - SAIMR &= ~(SAIMR_RFS | SAIMR_TFS); - - return ret; + return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai); } -static int __devexit pxa2xx_i2s_remove(struct platform_device *dev) +static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev) { - snd_soc_unregister_dai(&pxa_i2s_dai); - clk_put(clk_i2s); - clk_i2s = ERR_PTR(-ENOENT); + snd_soc_unregister_dai(&pdev->dev); return 0; } static struct platform_driver pxa2xx_i2s_driver = { - .probe = pxa2xx_i2s_probe, - .remove = __devexit_p(pxa2xx_i2s_remove), + .probe = pxa2xx_i2s_drv_probe, + .remove = __devexit_p(pxa2xx_i2s_drv_remove), .driver = { .name = "pxa2xx-i2s", diff --git a/sound/soc/pxa/pxa2xx-i2s.h b/sound/soc/pxa/pxa2xx-i2s.h index e2def441153e..070f3c6059fe 100644 --- a/sound/soc/pxa/pxa2xx-i2s.h +++ b/sound/soc/pxa/pxa2xx-i2s.h @@ -15,6 +15,4 @@ /* I2S clock */ #define PXA2XX_I2S_SYSCLK 0 -extern struct snd_soc_dai pxa_i2s_dai; - #endif diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index adc7e6f15f93..5127044acfec 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c @@ -28,7 +28,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, struct pxa2xx_pcm_dma_params *dma; int ret; - dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); /* return if this is a bufferless transfer e.g. * codec <--> BT codec or GSM modem -- lg FIXME */ @@ -95,14 +95,14 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto out; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) @@ -112,25 +112,44 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, return ret; } -struct snd_soc_platform pxa2xx_soc_platform = { - .name = "pxa2xx-audio", - .pcm_ops = &pxa2xx_pcm_ops, +static struct snd_soc_platform_driver pxa2xx_soc_platform = { + .ops = &pxa2xx_pcm_ops, .pcm_new = pxa2xx_soc_pcm_new, .pcm_free = pxa2xx_pcm_free_dma_buffers, }; -EXPORT_SYMBOL_GPL(pxa2xx_soc_platform); -static int __init pxa2xx_soc_platform_init(void) +static int __devinit pxa2xx_soc_platform_probe(struct platform_device *pdev) { - return snd_soc_register_platform(&pxa2xx_soc_platform); + return snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform); } -module_init(pxa2xx_soc_platform_init); -static void __exit pxa2xx_soc_platform_exit(void) +static int __devexit pxa2xx_soc_platform_remove(struct platform_device *pdev) { - snd_soc_unregister_platform(&pxa2xx_soc_platform); + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver pxa_pcm_driver = { + .driver = { + .name = "pxa-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = pxa2xx_soc_platform_probe, + .remove = __devexit_p(pxa2xx_soc_platform_remove), +}; + +static int __init snd_pxa_pcm_init(void) +{ + return platform_driver_register(&pxa_pcm_driver); +} +module_init(snd_pxa_pcm_init); + +static void __exit snd_pxa_pcm_exit(void) +{ + platform_driver_unregister(&pxa_pcm_driver); } -module_exit(pxa2xx_soc_platform_exit); +module_exit(snd_pxa_pcm_exit); MODULE_AUTHOR("Nicolas Pitre"); MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); diff --git a/sound/soc/pxa/pxa2xx-pcm.h b/sound/soc/pxa/pxa2xx-pcm.h deleted file mode 100644 index 60c3b20aeeb4..000000000000 --- a/sound/soc/pxa/pxa2xx-pcm.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip - * - * Author: Nicolas Pitre - * Created: Nov 30, 2004 - * Copyright: MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _PXA2XX_PCM_H -#define _PXA2XX_PCM_H - -/* platform data */ -extern struct snd_soc_platform pxa2xx_soc_platform; - -#endif diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c index 7e3f41696c41..2cda82bc5d2e 100644 --- a/sound/soc/pxa/raumfeld.c +++ b/sound/soc/pxa/raumfeld.c @@ -26,9 +26,6 @@ #include -#include "../codecs/cs4270.h" -#include "../codecs/ak4104.h" -#include "pxa2xx-pcm.h" #include "pxa-ssp.h" #define GPIO_SPDIF_RESET (38) @@ -71,7 +68,7 @@ static void raumfeld_enable_audio(bool en) static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; /* set freq to 0 to enable all possible codec sample rates */ return snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0); @@ -80,7 +77,7 @@ static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream) static void raumfeld_cs4270_shutdown(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; /* set freq to 0 to enable all possible codec sample rates */ snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0); @@ -90,8 +87,8 @@ static int raumfeld_cs4270_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int fmt, clk = 0; int ret = 0; @@ -167,32 +164,14 @@ static int raumfeld_line_resume(struct platform_device *pdev) return 0; } -static struct snd_soc_dai_link raumfeld_line_dai = { - .name = "CS4270", - .stream_name = "CS4270", - .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1], - .codec_dai = &cs4270_dai, - .ops = &raumfeld_cs4270_ops, -}; - -static struct snd_soc_card snd_soc_line_raumfeld = { - .name = "Raumfeld analog", - .platform = &pxa2xx_soc_platform, - .dai_link = &raumfeld_line_dai, - .suspend_post = raumfeld_line_suspend, - .resume_pre = raumfeld_line_resume, - .num_links = 1, -}; - - /* AK4104 */ static int raumfeld_ak4104_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int fmt, ret = 0, clk = 0; switch (params_rate(params)) { @@ -247,34 +226,35 @@ static struct snd_soc_ops raumfeld_ak4104_ops = { .hw_params = raumfeld_ak4104_hw_params, }; -static struct snd_soc_dai_link raumfeld_spdif_dai = { +static struct snd_soc_dai_link raumfeld_dai[] = { +{ .name = "ak4104", .stream_name = "Playback", - .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP2], - .codec_dai = &ak4104_dai, + .cpu_dai_name = "pxa-ssp-dai.1", + .codec_dai_name = "ak4104-hifi", + .platform_name = "pxa-pcm-audio", .ops = &raumfeld_ak4104_ops, -}; - -static struct snd_soc_card snd_soc_spdif_raumfeld = { - .name = "Raumfeld S/PDIF", - .platform = &pxa2xx_soc_platform, - .dai_link = &raumfeld_spdif_dai, - .num_links = 1 -}; - -/* raumfeld_audio audio subsystem */ -static struct snd_soc_device raumfeld_line_devdata = { - .card = &snd_soc_line_raumfeld, - .codec_dev = &soc_codec_device_cs4270, -}; + .codec_name = "ak4104-codec.0", +}, +{ + .name = "CS4270", + .stream_name = "CS4270", + .cpu_dai_name = "pxa-ssp-dai.0", + .platform_name = "pxa-pcm-audio", + .codec_dai_name = "cs4270-hifi", + .codec_name = "cs4270-codec.0-0048", + .ops = &raumfeld_cs4270_ops, +},}; -static struct snd_soc_device raumfeld_spdif_devdata = { - .card = &snd_soc_spdif_raumfeld, - .codec_dev = &soc_codec_device_ak4104, +static struct snd_soc_card snd_soc_raumfeld = { + .name = "Raumfeld", + .dai_link = raumfeld_dai, + .suspend_post = raumfeld_line_suspend, + .resume_pre = raumfeld_line_resume, + .num_links = ARRAY_SIZE(raumfeld_dai), }; -static struct platform_device *raumfeld_audio_line_device; -static struct platform_device *raumfeld_audio_spdif_device; +static struct platform_device *raumfeld_audio_device; static int __init raumfeld_audio_init(void) { @@ -292,38 +272,19 @@ static int __init raumfeld_audio_init(void) set_max9485_clk(MAX9485_MCLK_FREQ_122880); - /* LINE */ - raumfeld_audio_line_device = platform_device_alloc("soc-audio", 0); - if (!raumfeld_audio_line_device) + /* Register LINE and SPDIF */ + raumfeld_audio_device = platform_device_alloc("soc-audio", 0); + if (!raumfeld_audio_device) return -ENOMEM; - platform_set_drvdata(raumfeld_audio_line_device, - &raumfeld_line_devdata); - raumfeld_line_devdata.dev = &raumfeld_audio_line_device->dev; - ret = platform_device_add(raumfeld_audio_line_device); - if (ret) - platform_device_put(raumfeld_audio_line_device); + platform_set_drvdata(raumfeld_audio_device, + &snd_soc_raumfeld); + ret = platform_device_add(raumfeld_audio_device); /* no S/PDIF on Speakers */ if (machine_is_raumfeld_speaker()) return ret; - /* S/PDIF */ - raumfeld_audio_spdif_device = platform_device_alloc("soc-audio", 1); - if (!raumfeld_audio_spdif_device) { - platform_device_put(raumfeld_audio_line_device); - return -ENOMEM; - } - - platform_set_drvdata(raumfeld_audio_spdif_device, - &raumfeld_spdif_devdata); - raumfeld_spdif_devdata.dev = &raumfeld_audio_spdif_device->dev; - ret = platform_device_add(raumfeld_audio_spdif_device); - if (ret) { - platform_device_put(raumfeld_audio_line_device); - platform_device_put(raumfeld_audio_spdif_device); - } - raumfeld_enable_audio(true); return ret; @@ -333,10 +294,7 @@ static void __exit raumfeld_audio_exit(void) { raumfeld_enable_audio(false); - platform_device_unregister(raumfeld_audio_line_device); - - if (machine_is_raumfeld_connector()) - platform_device_unregister(raumfeld_audio_spdif_device); + platform_device_unregister(raumfeld_audio_device); i2c_unregister_device(max9486_client); diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 1941a357e8c4..f470f360f4dd 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -28,7 +28,6 @@ #include #include #include "../codecs/wm8750.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-i2s.h" #define SPITZ_HP 0 @@ -107,7 +106,7 @@ static void spitz_ext_control(struct snd_soc_codec *codec) static int spitz_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ spitz_ext_control(codec); @@ -118,8 +117,8 @@ static int spitz_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int clk = 0; int ret = 0; @@ -274,8 +273,9 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = { /* * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device */ -static int spitz_wm8750_init(struct snd_soc_codec *codec) +static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int err; /* NC codec pins */ @@ -308,8 +308,10 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link spitz_dai = { .name = "wm8750", .stream_name = "WM8750", - .cpu_dai = &pxa_i2s_dai, - .codec_dai = &wm8750_dai, + .cpu_dai_name = "pxa-is2", + .codec_dai_name = "wm8750-hifi", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm8750-codec.0-001a", .init = spitz_wm8750_init, .ops = &spitz_ops, }; @@ -317,49 +319,10 @@ static struct snd_soc_dai_link spitz_dai = { /* spitz audio machine driver */ static struct snd_soc_card snd_soc_spitz = { .name = "Spitz", - .platform = &pxa2xx_soc_platform, .dai_link = &spitz_dai, .num_links = 1, }; -/* spitz audio subsystem */ -static struct snd_soc_device spitz_snd_devdata = { - .card = &snd_soc_spitz, - .codec_dev = &soc_codec_dev_wm8750, -}; - -/* - * FIXME: This is a temporary bodge to avoid cross-tree merge issues. - * New drivers should register the wm8750 I2C device in the machine - * setup code (under arch/arm for ARM systems). - */ -static int wm8750_i2c_register(void) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = 0x1b; - strlcpy(info.type, "wm8750", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(0); - if (!adapter) { - printk(KERN_ERR "can't get i2c adapter 0\n"); - return -ENODEV; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - printk(KERN_ERR "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - return -ENODEV; - } - - return 0; -} - static struct platform_device *spitz_snd_device; static int __init spitz_init(void) @@ -369,16 +332,11 @@ static int __init spitz_init(void) if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita())) return -ENODEV; - ret = wm8750_i2c_setup(); - if (ret != 0) - return ret; - spitz_snd_device = platform_device_alloc("soc-audio", -1); if (!spitz_snd_device) return -ENOMEM; - platform_set_drvdata(spitz_snd_device, &spitz_snd_devdata); - spitz_snd_devdata.dev = &spitz_snd_device->dev; + platform_set_drvdata(spitz_snd_device, &snd_soc_spitz); ret = platform_device_add(spitz_snd_device); if (ret) diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index dbbd3e9d1637..a3bfb2e8b70f 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -33,7 +33,6 @@ #include #include "../codecs/wm9712.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" static struct snd_soc_card tosa; @@ -80,7 +79,7 @@ static void tosa_ext_control(struct snd_soc_codec *codec) static int tosa_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->socdev->card->codec; + struct snd_soc_codec *codec = rtd->card->codec; /* check the jack status at stream startup */ tosa_ext_control(codec); @@ -184,8 +183,9 @@ static const struct snd_kcontrol_new tosa_controls[] = { tosa_set_spk), }; -static int tosa_ac97_init(struct snd_soc_codec *codec) +static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int err; snd_soc_dapm_nc_pin(codec, "OUT3"); @@ -212,16 +212,20 @@ static struct snd_soc_dai_link tosa_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], + .cpu_dai_name = "pxa-ac97.0", + .codec_dai_name = "wm9712-hifi", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm9712-codec", .init = tosa_ac97_init, .ops = &tosa_ops, }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], + .cpu_dai_name = "pxa-ac97.1", + .codec_dai_name = "wm9712-aux", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm9712-codec", .ops = &tosa_ops, }, }; @@ -248,18 +252,12 @@ static int tosa_remove(struct platform_device *dev) static struct snd_soc_card tosa = { .name = "Tosa", - .platform = &pxa2xx_soc_platform, .dai_link = tosa_dai, .num_links = ARRAY_SIZE(tosa_dai), .probe = tosa_probe, .remove = tosa_remove, }; -static struct snd_soc_device tosa_snd_devdata = { - .card = &tosa, - .codec_dev = &soc_codec_dev_wm9712, -}; - static struct platform_device *tosa_snd_device; static int __init tosa_init(void) @@ -275,8 +273,7 @@ static int __init tosa_init(void) goto err_alloc; } - platform_set_drvdata(tosa_snd_device, &tosa_snd_devdata); - tosa_snd_devdata.dev = &tosa_snd_device->dev; + platform_set_drvdata(tosa_snd_device, &tosa); ret = platform_device_add(tosa_snd_device); if (!ret) diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index 4e4d2fa8ddc5..704f74b56ab6 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c @@ -30,7 +30,6 @@ #include #include "../codecs/wm8750.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-i2s.h" static struct snd_soc_card snd_soc_z2; @@ -39,8 +38,8 @@ static int z2_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int clk = 0; int ret = 0; @@ -138,8 +137,9 @@ static const struct snd_soc_dapm_route audio_map[] = { /* * Logic for a wm8750 as connected on a Z2 Device */ -static int z2_wm8750_init(struct snd_soc_codec *codec) +static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int ret; /* NC codec pins */ @@ -160,7 +160,7 @@ static int z2_wm8750_init(struct snd_soc_codec *codec) goto err; /* Jack detection API stuff */ - ret = snd_soc_jack_new(&snd_soc_z2, "Headset Jack", SND_JACK_HEADSET, + ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, &hs_jack); if (ret) goto err; @@ -189,8 +189,10 @@ static struct snd_soc_ops z2_ops = { static struct snd_soc_dai_link z2_dai = { .name = "wm8750", .stream_name = "WM8750", - .cpu_dai = &pxa_i2s_dai, - .codec_dai = &wm8750_dai, + .cpu_dai_name = "pxa-i2s", + .codec_dai_name = "wm8750-hifi", + .platform_name = "pxa-pcm-audio", + .codec_name = "wm8750-codec.0-001a", .init = z2_wm8750_init, .ops = &z2_ops, }; @@ -198,17 +200,10 @@ static struct snd_soc_dai_link z2_dai = { /* z2 audio machine driver */ static struct snd_soc_card snd_soc_z2 = { .name = "Z2", - .platform = &pxa2xx_soc_platform, .dai_link = &z2_dai, .num_links = 1, }; -/* z2 audio subsystem */ -static struct snd_soc_device z2_snd_devdata = { - .card = &snd_soc_z2, - .codec_dev = &soc_codec_dev_wm8750, -}; - static struct platform_device *z2_snd_device; static int __init z2_init(void) @@ -222,8 +217,7 @@ static int __init z2_init(void) if (!z2_snd_device) return -ENOMEM; - platform_set_drvdata(z2_snd_device, &z2_snd_devdata); - z2_snd_devdata.dev = &z2_snd_device->dev; + platform_set_drvdata(z2_snd_device, &snd_soc_z2); ret = platform_device_add(z2_snd_device); if (ret) diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index dd678ae24398..d27e05af7759 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -23,7 +23,6 @@ #include #include "../codecs/wm9713.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" #include "pxa-ssp.h" @@ -71,10 +70,12 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Multiactor", NULL, "SPKR" }, }; -static int zylonite_wm9713_init(struct snd_soc_codec *codec) +static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + if (clk_pout) - snd_soc_dai_set_pll(&codec->dai[0], 0, 0, + snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, clk_get_rate(pout), 0); snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, @@ -94,8 +95,8 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int pll_out = 0; unsigned int wm9713_div = 0; int ret = 0; @@ -163,21 +164,27 @@ static struct snd_soc_dai_link zylonite_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], - .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], + .codec_name = "wm9713-codec", + .platform_name = "pxa-pcm-audio", + .cpu_dai_name = "pxa-ac97.0", + .codec_name = "wm9713-hifi", .init = zylonite_wm9713_init, }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], - .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX], + .codec_name = "wm9713-codec", + .platform_name = "pxa-pcm-audio", + .cpu_dai_name = "pxa-ac97.1", + .codec_name = "wm9713-aux", }, { .name = "WM9713 Voice", .stream_name = "WM9713 Voice", - .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP3], - .codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE], + .codec_name = "wm9713-codec", + .platform_name = "pxa-pcm-audio", + .cpu_dai_name = "pxa-ssp-dai.2", + .codec_name = "wm9713-voice", .ops = &zylonite_voice_ops, }, }; @@ -248,14 +255,9 @@ static struct snd_soc_card zylonite = { .remove = &zylonite_remove, .suspend_post = &zylonite_suspend_post, .resume_pre = &zylonite_resume_pre, - .platform = &pxa2xx_soc_platform, .dai_link = zylonite_dai, .num_links = ARRAY_SIZE(zylonite_dai), -}; - -static struct snd_soc_device zylonite_snd_ac97_devdata = { - .card = &zylonite, - .codec_dev = &soc_codec_dev_wm9713, + .owner = THIS_MODULE, }; static struct platform_device *zylonite_snd_ac97_device; @@ -268,9 +270,7 @@ static int __init zylonite_init(void) if (!zylonite_snd_ac97_device) return -ENOMEM; - platform_set_drvdata(zylonite_snd_ac97_device, - &zylonite_snd_ac97_devdata); - zylonite_snd_ac97_devdata.dev = &zylonite_snd_ac97_device->dev; + platform_set_drvdata(zylonite_snd_ac97_device, &zylonite); ret = platform_device_add(zylonite_snd_ac97_device); if (ret != 0) diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c index 8c108b121c10..49605cd83947 100644 --- a/sound/soc/s3c24xx/jive_wm8750.c +++ b/sound/soc/s3c24xx/jive_wm8750.c @@ -49,8 +49,8 @@ static int jive_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct s3c_i2sv2_rate_calc div; unsigned int clk = 0; int ret = 0; @@ -108,8 +108,9 @@ static struct snd_soc_ops jive_ops = { .hw_params = jive_hw_params, }; -static int jive_wm8750_init(struct snd_soc_codec *codec) +static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int err; /* These endpoints are not being used. */ @@ -138,8 +139,10 @@ static int jive_wm8750_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link jive_dai = { .name = "wm8750", .stream_name = "WM8750", - .cpu_dai = &s3c2412_i2s_dai, - .codec_dai = &wm8750_dai, + .cpu_dai_name = "s3c2412-i2s", + .codec_dai_name = "wm8750-hifi", + .platform_name = "s3c24xx-pcm-audio", + .codec_name = "wm8750-codec.0-0x1a", .init = jive_wm8750_init, .ops = &jive_ops, }; @@ -147,17 +150,10 @@ static struct snd_soc_dai_link jive_dai = { /* jive audio machine driver */ static struct snd_soc_card snd_soc_machine_jive = { .name = "Jive", - .platform = &s3c24xx_soc_platform, .dai_link = &jive_dai, .num_links = 1, }; -/* jive audio subsystem */ -static struct snd_soc_device jive_snd_devdata = { - .card = &snd_soc_machine_jive, - .codec_dev = &soc_codec_dev_wm8750, -}; - static struct platform_device *jive_snd_device; static int __init jive_init(void) @@ -173,8 +169,7 @@ static int __init jive_init(void) if (!jive_snd_device) return -ENOMEM; - platform_set_drvdata(jive_snd_device, &jive_snd_devdata); - jive_snd_devdata.dev = &jive_snd_device->dev; + platform_set_drvdata(jive_snd_device, &snd_soc_machine_jive); ret = platform_device_add(jive_snd_device); if (ret) diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c index ffa954fe6931..abe64abe8c84 100644 --- a/sound/soc/s3c24xx/ln2440sbc_alc650.c +++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c @@ -23,7 +23,6 @@ #include #include -#include "../codecs/ac97.h" #include "s3c-dma.h" #include "s3c-ac97.h" @@ -33,23 +32,19 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], - .codec_dai = &ac97_dai, + .cpu_dai_name = "s3c-ac97", + .codec_dai_name = "ac97-hifi", + .codec_name = "ac97-codec", + .platform_name = "s3c24xx-pcm-audio", }, }; static struct snd_soc_card ln2440sbc = { .name = "LN2440SBC", - .platform = &s3c24xx_soc_platform, .dai_link = ln2440sbc_dai, .num_links = ARRAY_SIZE(ln2440sbc_dai), }; -static struct snd_soc_device ln2440sbc_snd_ac97_devdata = { - .card = &ln2440sbc, - .codec_dev = &soc_codec_dev_ac97, -}; - static struct platform_device *ln2440sbc_snd_ac97_device; static int __init ln2440sbc_init(void) @@ -60,9 +55,7 @@ static int __init ln2440sbc_init(void) if (!ln2440sbc_snd_ac97_device) return -ENOMEM; - platform_set_drvdata(ln2440sbc_snd_ac97_device, - &ln2440sbc_snd_ac97_devdata); - ln2440sbc_snd_ac97_devdata.dev = &ln2440sbc_snd_ac97_device->dev; + platform_set_drvdata(ln2440sbc_snd_ac97_device, &ln2440sbc); ret = platform_device_add(ln2440sbc_snd_ac97_device); if (ret) diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c index 209c25994c7e..c457bfd8297c 100644 --- a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c @@ -41,8 +41,8 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int pll_out = 0, bclk = 0; int ret = 0; unsigned long iis_clkrate; @@ -130,7 +130,7 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream, static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; /* disable the PLL */ return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); @@ -149,7 +149,7 @@ static int neo1973_gta02_voice_hw_params( struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; unsigned int pcmdiv = 0; int ret = 0; unsigned long iis_clkrate; @@ -194,7 +194,7 @@ static int neo1973_gta02_voice_hw_params( static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; /* disable the PLL */ return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); @@ -262,7 +262,7 @@ static int lm4853_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value)); + gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event)); return 0; } @@ -330,8 +330,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = { * This is an example machine initialisation for a wm8753 connected to a * neo1973 GTA02. */ -static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) +static int neo1973_gta02_wm8753_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int err; /* set up NC codec pins */ @@ -378,9 +379,8 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) /* * BT Codec DAI */ -static struct snd_soc_dai bt_dai = { - .name = "Bluetooth", - .id = 0, +static struct snd_soc_dai_driver bt_dai = { + .name = "bluetooth-dai", .playback = { .channels_min = 1, .channels_max = 1, @@ -397,32 +397,30 @@ static struct snd_soc_dai_link neo1973_gta02_dai[] = { { /* Hifi Playback - for similatious use with voice below */ .name = "WM8753", .stream_name = "WM8753 HiFi", - .cpu_dai = &s3c24xx_i2s_dai, - .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], + .cpu_dai_name = "s3c24xx-i2s", + .codec_dai_name = "wm8753-hifi", .init = neo1973_gta02_wm8753_init, + .platform_name = "s3c24xx-pcm-audio", + .codec_name = "wm8753-codec.0-0x1a", .ops = &neo1973_gta02_hifi_ops, }, { /* Voice via BT */ .name = "Bluetooth", .stream_name = "Voice", - .cpu_dai = &bt_dai, - .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], + .cpu_dai_name = "bluetooth-dai", + .codec_dai_name = "wm8753-voice", .ops = &neo1973_gta02_voice_ops, + .codec_name = "wm8753-codec.0-0x1a", + .platform_name = "s3c24xx-pcm-audio", }, }; static struct snd_soc_card neo1973_gta02 = { .name = "neo1973-gta02", - .platform = &s3c24xx_soc_platform, .dai_link = neo1973_gta02_dai, .num_links = ARRAY_SIZE(neo1973_gta02_dai), }; -static struct snd_soc_device neo1973_gta02_snd_devdata = { - .card = &neo1973_gta02, - .codec_dev = &soc_codec_dev_wm8753, -}; - static struct platform_device *neo1973_gta02_snd_device; static int __init neo1973_gta02_init(void) @@ -435,18 +433,18 @@ static int __init neo1973_gta02_init(void) return -ENODEV; } - /* register bluetooth DAI here */ - ret = snd_soc_register_dai(&bt_dai); - if (ret) - return ret; - neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1); if (!neo1973_gta02_snd_device) return -ENOMEM; - platform_set_drvdata(neo1973_gta02_snd_device, - &neo1973_gta02_snd_devdata); - neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev; + /* register bluetooth DAI here */ + ret = snd_soc_register_dai(&neo1973_gta02_snd_device->dev, -1, &bt_dai); + if (ret) { + platform_device_put(neo1973_gta02_snd_device); + return ret; + } + + platform_set_drvdata(neo1973_gta02_snd_device, &neo1973_gta02); ret = platform_device_add(neo1973_gta02_snd_device); if (ret) { @@ -461,7 +459,7 @@ static int __init neo1973_gta02_init(void) goto err_unregister_device; } - ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1); + ret = gpio_direction_output(GTA02_GPIO_HP_IN, 1); if (ret) { pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN); goto err_free_gpio_hp_in; @@ -493,7 +491,7 @@ module_init(neo1973_gta02_init); static void __exit neo1973_gta02_exit(void) { - snd_soc_unregister_dai(&bt_dai); + snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev, -1); platform_device_unregister(neo1973_gta02_snd_device); gpio_free(GTA02_GPIO_HP_IN); gpio_free(GTA02_GPIO_AMP_SHUT); diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c index 0cb4f86f6d1e..d7a39a0fe99b 100644 --- a/sound/soc/s3c24xx/neo1973_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_wm8753.c @@ -57,8 +57,8 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int pll_out = 0, bclk = 0; int ret = 0; unsigned long iis_clkrate; @@ -147,7 +147,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; pr_debug("Entered %s\n", __func__); @@ -167,7 +167,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; unsigned int pcmdiv = 0; int ret = 0; unsigned long iis_clkrate; @@ -213,7 +213,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; pr_debug("Entered %s\n", __func__); @@ -499,8 +499,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_controls[] = { * neo1973 II. It is missing logic to detect hp/mic insertions and logic * to re-route the audio in such an event. */ -static int neo1973_wm8753_init(struct snd_soc_codec *codec) +static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; int err; pr_debug("Entered %s\n", __func__); @@ -538,8 +539,7 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec) * BT Codec DAI */ static struct snd_soc_dai bt_dai = { - .name = "Bluetooth", - .id = 0, + .name = "bluetooth-dai", .playback = { .channels_min = 1, .channels_max = 1, @@ -556,32 +556,30 @@ static struct snd_soc_dai_link neo1973_dai[] = { { /* Hifi Playback - for similatious use with voice below */ .name = "WM8753", .stream_name = "WM8753 HiFi", - .cpu_dai = &s3c24xx_i2s_dai, - .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], + .platform_name = "s3c24xx-pcm-audio", + .cpu_dai_name = "s3c24xx-i2s", + .codec_dai_name = "wm8753-hifi", + .codec_name = "wm8753-codec.0-0x1a", .init = neo1973_wm8753_init, .ops = &neo1973_hifi_ops, }, { /* Voice via BT */ .name = "Bluetooth", .stream_name = "Voice", - .cpu_dai = &bt_dai, - .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], + .platform_name = "s3c24xx-pcm-audio", + .cpu_dai_name = "bluetooth-dai", + .codec_dai_name = "wm8753-voice", + .codec_name = "wm8753-codec.0-0x1a", .ops = &neo1973_voice_ops, }, }; static struct snd_soc_card neo1973 = { .name = "neo1973", - .platform = &s3c24xx_soc_platform, .dai_link = neo1973_dai, .num_links = ARRAY_SIZE(neo1973_dai), }; -static struct snd_soc_device neo1973_snd_devdata = { - .card = &neo1973, - .codec_dev = &soc_codec_dev_wm8753, -}; - static int lm4857_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -673,8 +671,7 @@ static int __init neo1973_init(void) if (!neo1973_snd_device) return -ENOMEM; - platform_set_drvdata(neo1973_snd_device, &neo1973_snd_devdata); - neo1973_snd_devdata.dev = &neo1973_snd_device->dev; + platform_set_drvdata(neo1973_snd_device, &neo1973); ret = platform_device_add(neo1973_snd_device); if (ret) { diff --git a/sound/soc/s3c24xx/s3c-ac97.c b/sound/soc/s3c24xx/s3c-ac97.c index 31f6d45b6384..86f4a9b4a869 100644 --- a/sound/soc/s3c24xx/s3c-ac97.c +++ b/sound/soc/s3c24xx/s3c-ac97.c @@ -222,7 +222,7 @@ static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct s3c_dma_params *dma_data; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -241,7 +241,7 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, u32 ac_glbctrl; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct s3c_dma_params *dma_data = - snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) @@ -277,7 +277,7 @@ static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) return -ENODEV; @@ -293,7 +293,7 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, u32 ac_glbctrl; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct s3c_dma_params *dma_data = - snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; @@ -328,10 +328,9 @@ static struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = { .trigger = s3c_ac97_mic_trigger, }; -struct snd_soc_dai s3c_ac97_dai[] = { +static struct snd_soc_dai_driver s3c_ac97_dai[] = { [S3C_AC97_DAI_PCM] = { .name = "s3c-ac97", - .id = S3C_AC97_DAI_PCM, .ac97_control = 1, .playback = { .stream_name = "AC97 Playback", @@ -349,7 +348,6 @@ struct snd_soc_dai s3c_ac97_dai[] = { }, [S3C_AC97_DAI_MIC] = { .name = "s3c-ac97-mic", - .id = S3C_AC97_DAI_MIC, .ac97_control = 1, .capture = { .stream_name = "AC97 Mic Capture", @@ -360,7 +358,6 @@ struct snd_soc_dai s3c_ac97_dai[] = { .ops = &s3c_ac97_mic_dai_ops, }, }; -EXPORT_SYMBOL_GPL(s3c_ac97_dai); static __devinit int s3c_ac97_probe(struct platform_device *pdev) { @@ -449,10 +446,8 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev) goto err4; } - s3c_ac97_dai[S3C_AC97_DAI_PCM].dev = &pdev->dev; - s3c_ac97_dai[S3C_AC97_DAI_MIC].dev = &pdev->dev; - - ret = snd_soc_register_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); + ret = snd_soc_register_dais(&pdev->dev, s3c_ac97_dai, + ARRAY_SIZE(s3c_ac97_dai)); if (ret) goto err5; @@ -476,7 +471,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev) { struct resource *mem_res, *irq_res; - snd_soc_unregister_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); + snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai)); irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (irq_res) diff --git a/sound/soc/s3c24xx/s3c-ac97.h b/sound/soc/s3c24xx/s3c-ac97.h index 278198379def..5dcedd07fdbb 100644 --- a/sound/soc/s3c24xx/s3c-ac97.h +++ b/sound/soc/s3c24xx/s3c-ac97.h @@ -18,6 +18,4 @@ #define S3C_AC97_DAI_PCM 0 #define S3C_AC97_DAI_MIC 1 -extern struct snd_soc_dai s3c_ac97_dai[]; - #endif /* __S3C_AC97_H_ */ diff --git a/sound/soc/s3c24xx/s3c-dma.c b/sound/soc/s3c24xx/s3c-dma.c index 1b61c23ff300..9f91b2d51454 100644 --- a/sound/soc/s3c24xx/s3c-dma.c +++ b/sound/soc/s3c24xx/s3c-dma.c @@ -147,7 +147,7 @@ static int s3c_dma_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; unsigned long totbytes = params_buffer_bytes(params); struct s3c_dma_params *dma = - snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); int ret = 0; @@ -441,14 +441,14 @@ static int s3c_dma_new(struct snd_card *card, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = 0xffffffff; - if (dai->playback.channels_min) { + if (dai->driver->playback.channels_min) { ret = s3c_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto out; } - if (dai->capture.channels_min) { + if (dai->driver->capture.channels_min) { ret = s3c_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) @@ -458,25 +458,44 @@ static int s3c_dma_new(struct snd_card *card, return ret; } -struct snd_soc_platform s3c24xx_soc_platform = { - .name = "s3c24xx-audio", - .pcm_ops = &s3c_dma_ops, +static struct snd_soc_platform_driver s3c24xx_soc_platform = { + .ops = &s3c_dma_ops, .pcm_new = s3c_dma_new, .pcm_free = s3c_dma_free_dma_buffers, }; -EXPORT_SYMBOL_GPL(s3c24xx_soc_platform); -static int __init s3c24xx_soc_platform_init(void) +static int __devinit s3c24xx_soc_platform_probe(struct platform_device *pdev) { - return snd_soc_register_platform(&s3c24xx_soc_platform); + return snd_soc_register_platform(&pdev->dev, &s3c24xx_soc_platform); } -module_init(s3c24xx_soc_platform_init); -static void __exit s3c24xx_soc_platform_exit(void) +static int __devexit s3c24xx_soc_platform_remove(struct platform_device *pdev) { - snd_soc_unregister_platform(&s3c24xx_soc_platform); + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver s3c24xx_pcm_driver = { + .driver = { + .name = "s3c24xx-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = s3c24xx_soc_platform_probe, + .remove = __devexit_p(s3c24xx_soc_platform_remove), +}; + +static int __init snd_s3c24xx_pcm_init(void) +{ + return platform_driver_register(&s3c24xx_pcm_driver); +} +module_init(snd_s3c24xx_pcm_init); + +static void __exit snd_s3c24xx_pcm_exit(void) +{ + platform_driver_unregister(&s3c24xx_pcm_driver); } -module_exit(s3c24xx_soc_platform_exit); +module_exit(snd_s3c24xx_pcm_exit); MODULE_AUTHOR("Ben Dooks, "); MODULE_DESCRIPTION("Samsung S3C Audio DMA module"); diff --git a/sound/soc/s3c24xx/s3c-dma.h b/sound/soc/s3c24xx/s3c-dma.h index 69bb6bf6fc1c..748c07d7c075 100644 --- a/sound/soc/s3c24xx/s3c-dma.h +++ b/sound/soc/s3c24xx/s3c-dma.h @@ -25,7 +25,6 @@ struct s3c_dma_params { #define S3C24XX_DAI_I2S 0 /* platform data */ -extern struct snd_soc_platform s3c24xx_soc_platform; extern struct snd_ac97_bus_ops s3c24xx_ac97_ops; #endif diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c index 64376b2aac73..f4fbc0e61733 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.c +++ b/sound/soc/s3c24xx/s3c-i2s-v2.c @@ -49,7 +49,7 @@ static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) { - return cpu_dai->private_data; + return snd_soc_dai_get_drvdata(cpu_dai); } #define bit_set(v, b) (((v) & (b)) ? 1 : 0) @@ -307,11 +307,9 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai, static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, - struct snd_soc_dai *socdai) + struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai_link *dai = rtd->dai; - struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai); + struct s3c_i2sv2_info *i2s = to_info(dai); struct s3c_dma_params *dma_data; u32 iismod; @@ -322,7 +320,7 @@ static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream, else dma_data = i2s->dma_capture; - snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); + snd_soc_dai_set_dma_data(dai, substream, dma_data); /* Working copies of register */ iismod = readl(i2s->regs + S3C2412_IISMOD); @@ -396,12 +394,12 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct s3c_i2sv2_info *i2s = to_info(rtd->dai->cpu_dai); + struct s3c_i2sv2_info *i2s = to_info(rtd->cpu_dai); int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); unsigned long irqs; int ret = 0; struct s3c_dma_params *dma_data = - snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); pr_debug("Entered %s\n", __func__); @@ -640,36 +638,17 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, } EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate); -int s3c_i2sv2_probe(struct platform_device *pdev, - struct snd_soc_dai *dai, +int s3c_i2sv2_probe(struct snd_soc_dai *dai, struct s3c_i2sv2_info *i2s, unsigned long base) { - struct device *dev = &pdev->dev; + struct device *dev = dai->dev; unsigned int iismod; i2s->dev = dev; /* record our i2s structure for later use in the callbacks */ - dai->private_data = i2s; - - if (!base) { - struct resource *res = platform_get_resource(pdev, - IORESOURCE_MEM, - 0); - if (!res) { - dev_err(dev, "Unable to get register resource\n"); - return -ENXIO; - } - - if (!request_mem_region(res->start, resource_size(res), - "s3c64xx-i2s-v4")) { - dev_err(dev, "Unable to request register region\n"); - return -EBUSY; - } - - base = res->start; - } + snd_soc_dai_set_drvdata(dai, i2s); i2s->regs = ioremap(base, 0x100); if (i2s->regs == NULL) { @@ -752,9 +731,10 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai) #define s3c2412_i2s_resume NULL #endif -int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) +int s3c_i2sv2_register_dai(struct device *dev, int id, + struct snd_soc_dai_driver *drv) { - struct snd_soc_dai_ops *ops = dai->ops; + struct snd_soc_dai_ops *ops = drv->ops; ops->trigger = s3c2412_i2s_trigger; if (!ops->hw_params) @@ -767,10 +747,10 @@ int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) if (!ops->delay) ops->delay = s3c2412_i2s_delay; - dai->suspend = s3c2412_i2s_suspend; - dai->resume = s3c2412_i2s_resume; + drv->suspend = s3c2412_i2s_suspend; + drv->resume = s3c2412_i2s_resume; - return snd_soc_register_dai(dai); + return snd_soc_register_dai(dev, id, drv); } EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h index 766f43a13d8b..d45830151484 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.h +++ b/sound/soc/s3c24xx/s3c-i2s-v2.h @@ -66,6 +66,8 @@ struct s3c_i2sv2_info { u32 suspend_iismod; u32 suspend_iiscon; u32 suspend_iispsr; + + unsigned long base; }; extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai); @@ -81,23 +83,24 @@ extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, /** * s3c_i2sv2_probe - probe for i2s device helper - * @pdev: The platform device supplied to the original probe. * @dai: The ASoC DAI structure supplied to the original probe. * @i2s: Our local i2s structure to fill in. * @base: The base address for the registers. */ -extern int s3c_i2sv2_probe(struct platform_device *pdev, - struct snd_soc_dai *dai, +extern int s3c_i2sv2_probe(struct snd_soc_dai *dai, struct s3c_i2sv2_info *i2s, unsigned long base); /** * s3c_i2sv2_register_dai - register dai with soc core - * @dai: The snd_soc_dai structure to register + * @dev: DAI device + * @id: DAI ID + * @drv: The driver structure to register * * Fill in any missing fields and then register the given dai with the * soc core. */ -extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai); +extern int s3c_i2sv2_register_dai(struct device *dev, int id, + struct snd_soc_dai_driver *drv); #endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ diff --git a/sound/soc/s3c24xx/s3c-pcm.c b/sound/soc/s3c24xx/s3c-pcm.c index 326f0a9e7e30..653ffa270915 100644 --- a/sound/soc/s3c24xx/s3c-pcm.c +++ b/sound/soc/s3c24xx/s3c-pcm.c @@ -64,11 +64,6 @@ static struct s3c_dma_params s3c_pcm_stereo_in[] = { static struct s3c_pcm_info s3c_pcm[2]; -static inline struct s3c_pcm_info *to_info(struct snd_soc_dai *cpu_dai) -{ - return cpu_dai->private_data; -} - static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on) { void __iomem *regs = pcm->regs; @@ -132,7 +127,7 @@ static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct s3c_pcm_info *pcm = to_info(rtd->dai->cpu_dai); + struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai); unsigned long flags; dev_dbg(pcm->dev, "Entered %s\n", __func__); @@ -176,8 +171,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *socdai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai_link *dai = rtd->dai; - struct s3c_pcm_info *pcm = to_info(dai->cpu_dai); + struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai); struct s3c_dma_params *dma_data; void __iomem *regs = pcm->regs; struct clk *clk; @@ -192,7 +186,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, else dma_data = pcm->dma_capture; - snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); + snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); /* Strictly check for sample size */ switch (params_format(params)) { @@ -242,7 +236,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct s3c_pcm_info *pcm = to_info(cpu_dai); + struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai); void __iomem *regs = pcm->regs; unsigned long flags; int ret = 0; @@ -313,7 +307,7 @@ exit: static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) { - struct s3c_pcm_info *pcm = to_info(cpu_dai); + struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai); switch (div_id) { case S3C_PCM_SCLK_PER_FS: @@ -330,7 +324,7 @@ static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai, static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct s3c_pcm_info *pcm = to_info(cpu_dai); + struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai); void __iomem *regs = pcm->regs; u32 clkctl = readl(regs + S3C_PCM_CLKCTL); @@ -366,10 +360,9 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = { #define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000 -#define S3C_PCM_DECLARE(n) \ +#define S3C_PCM_DAI_DECLARE \ { \ - .name = "samsung-pcm", \ - .id = (n), \ + .name = "samsung-dai", \ .symmetric_rates = 1, \ .ops = &s3c_pcm_dai_ops, \ .playback = { \ @@ -386,16 +379,15 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = { }, \ } -struct snd_soc_dai s3c_pcm_dai[] = { - S3C_PCM_DECLARE(0), - S3C_PCM_DECLARE(1), +struct snd_soc_dai_driver s3c_pcm_dai[] = { + S3C_PCM_DAI_DECLARE, + S3C_PCM_DAI_DECLARE, }; EXPORT_SYMBOL_GPL(s3c_pcm_dai); static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) { struct s3c_pcm_info *pcm; - struct snd_soc_dai *dai; struct resource *mem_res, *dmatx_res, *dmarx_res; struct s3c_audio_pdata *pcm_pdata; int ret; @@ -437,9 +429,6 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) spin_lock_init(&pcm->lock); - dai = &s3c_pcm_dai[pdev->id]; - dai->dev = &pdev->dev; - /* Default is 128fs */ pcm->sclk_per_fs = 128; @@ -452,7 +441,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) clk_enable(pcm->cclk); /* record our pcm structure for later use in the callbacks */ - dai->private_data = pcm; + dev_set_drvdata(&pdev->dev, pcm); if (!request_mem_region(mem_res->start, resource_size(mem_res), "samsung-pcm")) { @@ -476,7 +465,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) } clk_enable(pcm->pclk); - ret = snd_soc_register_dai(dai); + ret = snd_soc_register_dai(&pdev->dev, s3c_pcm_dai); if (ret != 0) { dev_err(&pdev->dev, "failed to get pcm_clock\n"); goto err5; @@ -514,6 +503,8 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev) struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; struct resource *mem_res; + snd_soc_unregister_dai(&pdev->dev); + iounmap(pcm->regs); mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -531,7 +522,7 @@ static struct platform_driver s3c_pcm_driver = { .probe = s3c_pcm_dev_probe, .remove = s3c_pcm_dev_remove, .driver = { - .name = "samsung-pcm", + .name = "samsung-pcm-audio", .owner = THIS_MODULE, }, }; diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c index 709adef9d043..acd00962ac36 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.c +++ b/sound/soc/s3c24xx/s3c2412-i2s.c @@ -65,26 +65,20 @@ static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { static struct s3c_i2sv2_info s3c2412_i2s; -static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) -{ - return cpu_dai->private_data; -} - -static int s3c2412_i2s_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int s3c2412_i2s_probe(struct snd_soc_dai *dai) { int ret; pr_debug("Entered %s\n", __func__); - ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS); + ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); if (ret) return ret; s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; - s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk"); + s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk"); if (s3c2412_i2s.iis_cclk == NULL) { pr_err("failed to get i2sclk clock\n"); iounmap(s3c2412_i2s.regs); @@ -108,11 +102,20 @@ static int s3c2412_i2s_probe(struct platform_device *pdev, return 0; } +static int s3c2412_i2s_remove(struct snd_soc_dai *dai) +{ + clk_disable(s3c2412_i2s.iis_cclk); + clk_put(s3c2412_i2s.iis_cclk); + iounmap(s3c2412_i2s.regs); + + return 0; +} + static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { - struct s3c_i2sv2_info *i2s = to_info(cpu_dai); + struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); struct s3c_dma_params *dma_data; u32 iismod; @@ -152,10 +155,9 @@ static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = { .hw_params = s3c2412_i2s_hw_params, }; -struct snd_soc_dai s3c2412_i2s_dai = { - .name = "s3c2412-i2s", - .id = 0, +static struct snd_soc_dai_driver s3c2412_i2s_dai = { .probe = s3c2412_i2s_probe, + .remove = s3c2412_i2s_remove, .playback = { .channels_min = 2, .channels_max = 2, @@ -170,17 +172,36 @@ struct snd_soc_dai s3c2412_i2s_dai = { }, .ops = &s3c2412_i2s_dai_ops, }; -EXPORT_SYMBOL_GPL(s3c2412_i2s_dai); + +static __devinit int s3c2412_iis_dev_probe(struct platform_device *pdev) +{ + return snd_soc_register_dai(&pdev->dev, &s3c2412_i2s_dai); +} + +static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + return 0; +} + +static struct platform_driver s3c2412_iis_driver = { + .probe = s3c2412_iis_dev_probe, + .remove = s3c2412_iis_dev_remove, + .driver = { + .name = "s3c2412-iis", + .owner = THIS_MODULE, + }, +}; static int __init s3c2412_i2s_init(void) { - return s3c_i2sv2_register_dai(&s3c2412_i2s_dai); + return platform_driver_register(&s3c2412_iis_driver); } module_init(s3c2412_i2s_init); static void __exit s3c2412_i2s_exit(void) { - snd_soc_unregister_dai(&s3c2412_i2s_dai); + platform_driver_unregister(&s3c2412_iis_driver); } module_exit(s3c2412_i2s_exit); diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h index 0b5686b4d5c3..01a0471ac65c 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.h +++ b/sound/soc/s3c24xx/s3c2412-i2s.h @@ -24,6 +24,4 @@ #define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK #define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS -extern struct snd_soc_dai s3c2412_i2s_dai; - #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */ diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c index c3ac890a3986..1d0bade10d3d 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c @@ -252,7 +252,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, else dma_data = &s3c24xx_i2s_pcm_stereo_in; - snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_data); + snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); /* Working copies of register */ iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); @@ -280,9 +280,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; struct s3c_dma_params *dma_data = - snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + snd_soc_dai_get_dma_data(dai, substream); pr_debug("Entered %s\n", __func__); @@ -387,8 +386,7 @@ u32 s3c24xx_i2s_get_clockrate(void) } EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); -static int s3c24xx_i2s_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) { pr_debug("Entered %s\n", __func__); @@ -396,7 +394,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev, if (s3c24xx_i2s.regs == NULL) return -ENXIO; - s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis"); + s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis"); if (s3c24xx_i2s.iis_clk == NULL) { pr_err("failed to get iis_clock\n"); iounmap(s3c24xx_i2s.regs); @@ -465,9 +463,7 @@ static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = { .set_sysclk = s3c24xx_i2s_set_sysclk, }; -struct snd_soc_dai s3c24xx_i2s_dai = { - .name = "s3c24xx-i2s", - .id = 0, +static struct snd_soc_dai_driver s3c24xx_i2s_dai = { .probe = s3c24xx_i2s_probe, .suspend = s3c24xx_i2s_suspend, .resume = s3c24xx_i2s_resume, @@ -483,17 +479,36 @@ struct snd_soc_dai s3c24xx_i2s_dai = { .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, .ops = &s3c24xx_i2s_dai_ops, }; -EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); + +static __devinit int s3c24xx_iis_dev_probe(struct platform_device *pdev) +{ + return snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai); +} + +static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + return 0; +} + +static struct platform_driver s3c24xx_iis_driver = { + .probe = s3c24xx_iis_dev_probe, + .remove = s3c24xx_iis_dev_remove, + .driver = { + .name = "s3c24xx-iis", + .owner = THIS_MODULE, + }, +}; static int __init s3c24xx_i2s_init(void) { - return snd_soc_register_dai(&s3c24xx_i2s_dai); + return platform_driver_register(&s3c24xx_iis_driver); } module_init(s3c24xx_i2s_init); static void __exit s3c24xx_i2s_exit(void) { - snd_soc_unregister_dai(&s3c24xx_i2s_dai); + platform_driver_unregister(&s3c24xx_iis_driver); } module_exit(s3c24xx_i2s_exit); diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.h b/sound/soc/s3c24xx/s3c24xx-i2s.h index 726d91cf4e1c..f9ca04edacb7 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.h +++ b/sound/soc/s3c24xx/s3c24xx-i2s.h @@ -32,6 +32,4 @@ u32 s3c24xx_i2s_get_clockrate(void); -extern struct snd_soc_dai s3c24xx_i2s_dai; - #endif /*S3C24XXI2S_H_*/ diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c index 4984754f3298..c4c111442010 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec.c @@ -139,8 +139,10 @@ static const struct snd_kcontrol_new amp_unmute_controls[] = { speaker_unmute_get, speaker_unmute_put), }; -void simtec_audio_init(struct snd_soc_codec *codec) +void simtec_audio_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + if (pdata->amp_gpio > 0) { pr_debug("%s: adding amp routes\n", __func__); @@ -170,8 +172,8 @@ static int simtec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set the CODEC as the bus clock master, I2S */ @@ -319,12 +321,12 @@ EXPORT_SYMBOL_GPL(simtec_audio_pmops); #endif int __devinit simtec_audio_core_probe(struct platform_device *pdev, - struct snd_soc_device *socdev) + struct snd_soc_card *card) { struct platform_device *snd_dev; int ret; - socdev->card->dai_link->ops = &simtec_snd_ops; + card->dai_link->ops = &simtec_snd_ops; pdata = pdev->dev.platform_data; if (!pdata) { @@ -353,8 +355,7 @@ int __devinit simtec_audio_core_probe(struct platform_device *pdev, goto err_gpio; } - platform_set_drvdata(snd_dev, socdev); - socdev->dev = &snd_dev->dev; + platform_set_drvdata(snd_dev, card); ret = platform_device_add(snd_dev); if (ret) { diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.h b/sound/soc/s3c24xx/s3c24xx_simtec.h index e18faee30cce..e63d5ff9c41f 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.h +++ b/sound/soc/s3c24xx/s3c24xx_simtec.h @@ -7,10 +7,10 @@ * published by the Free Software Foundation. */ -extern void simtec_audio_init(struct snd_soc_codec *codec); +extern void simtec_audio_init(struct snd_soc_pcm_runtime *rtd); extern int simtec_audio_core_probe(struct platform_device *pdev, - struct snd_soc_device *socdev); + struct snd_soc_card *card); extern int simtec_audio_remove(struct platform_device *pdev); diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c index bdf8951af8e3..f88453735ae2 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c @@ -73,8 +73,10 @@ static const struct snd_soc_dapm_route base_map[] = { * Attach our controls and configure the necessary codec * mappings for our sound card instance. */ -static int simtec_hermes_init(struct snd_soc_codec *codec) +static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + snd_soc_dapm_new_controls(codec, dapm_widgets, ARRAY_SIZE(dapm_widgets)); @@ -85,42 +87,33 @@ static int simtec_hermes_init(struct snd_soc_codec *codec) snd_soc_dapm_enable_pin(codec, "Line Out"); snd_soc_dapm_enable_pin(codec, "Mic Jack"); - simtec_audio_init(codec); + simtec_audio_init(rtd); snd_soc_dapm_sync(codec); return 0; } -static struct aic3x_setup_data codec_setup = { -}; - static struct snd_soc_dai_link simtec_dai_aic33 = { .name = "tlv320aic33", .stream_name = "TLV320AIC33", - .cpu_dai = &s3c24xx_i2s_dai, - .codec_dai = &aic3x_dai, + .codec_name = "tlv320aic3x-codec.0-0x1a", + .cpu_dai_name = "s3c24xx-i2s", + .codec_dai_name = "tlv320aic3x-hifi", + .platform_name = "s3c24xx-pcm-audio", .init = simtec_hermes_init, }; /* simtec audio machine driver */ static struct snd_soc_card snd_soc_machine_simtec_aic33 = { .name = "Simtec-Hermes", - .platform = &s3c24xx_soc_platform, .dai_link = &simtec_dai_aic33, .num_links = 1, }; -/* simtec audio subsystem */ -static struct snd_soc_device simtec_snd_devdata_aic33 = { - .card = &snd_soc_machine_simtec_aic33, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &codec_setup, -}; - static int __devinit simtec_audio_hermes_probe(struct platform_device *pd) { dev_info(&pd->dev, "probing....\n"); - return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic33); + return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33); } static struct platform_driver simtec_audio_hermes_platdrv = { diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c index 185c0acb5ce6..c0967593510d 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c @@ -62,8 +62,10 @@ static const struct snd_soc_dapm_route base_map[] = { * Attach our controls and configure the necessary codec * mappings for our sound card instance. */ -static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) +static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + snd_soc_dapm_new_controls(codec, dapm_widgets, ARRAY_SIZE(dapm_widgets)); @@ -74,7 +76,7 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) snd_soc_dapm_enable_pin(codec, "Line Out"); snd_soc_dapm_enable_pin(codec, "Mic Jack"); - simtec_audio_init(codec); + simtec_audio_init(rtd); snd_soc_dapm_sync(codec); return 0; @@ -83,28 +85,23 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link simtec_dai_aic23 = { .name = "tlv320aic23", .stream_name = "TLV320AIC23", - .cpu_dai = &s3c24xx_i2s_dai, - .codec_dai = &tlv320aic23_dai, + .codec_name = "tlv320aic3x-codec.0-0x1a", + .cpu_dai_name = "s3c24xx-i2s", + .codec_dai_name = "tlv320aic3x-hifi", + .platform_name = "s3c24xx-pcm-audio", .init = simtec_tlv320aic23_init, }; /* simtec audio machine driver */ static struct snd_soc_card snd_soc_machine_simtec_aic23 = { .name = "Simtec", - .platform = &s3c24xx_soc_platform, .dai_link = &simtec_dai_aic23, .num_links = 1, }; -/* simtec audio subsystem */ -static struct snd_soc_device simtec_snd_devdata_aic23 = { - .card = &snd_soc_machine_simtec_aic23, - .codec_dev = &soc_codec_dev_tlv320aic23, -}; - static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd) { - return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic23); + return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23); } static struct platform_driver simtec_audio_tlv320aic23_platdrv = { diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c index 052d59659c29..bd48ffbde880 100644 --- a/sound/soc/s3c24xx/s3c24xx_uda134x.c +++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c @@ -133,8 +133,8 @@ static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int clk = 0; int ret = 0; int clk_source, fs_mode; @@ -227,14 +227,15 @@ static struct snd_soc_ops s3c24xx_uda134x_ops = { static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { .name = "UDA134X", .stream_name = "UDA134X", - .codec_dai = &uda134x_dai, - .cpu_dai = &s3c24xx_i2s_dai, + .codec_name = "uda134x-hifi", + .codec_dai_name = "uda134x-hifi", + .cpu_dai_name = "s3c24xx-i2s", .ops = &s3c24xx_uda134x_ops, + .platform_name = "s3c24xx-pcm-audio", }; static struct snd_soc_card snd_soc_s3c24xx_uda134x = { .name = "S3C24XX_UDA134X", - .platform = &s3c24xx_soc_platform, .dai_link = &s3c24xx_uda134x_dai_link, .num_links = 1, }; @@ -256,6 +257,7 @@ static void setmode(int v) gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0); } +/* FIXME - This must be codec platform data but in which board file ?? */ static struct uda134x_platform_data s3c24xx_uda134x = { .l3 = { .setdat = setdat, @@ -270,12 +272,6 @@ static struct uda134x_platform_data s3c24xx_uda134x = { }, }; -static struct snd_soc_device s3c24xx_uda134x_snd_devdata = { - .card = &snd_soc_s3c24xx_uda134x, - .codec_dev = &soc_codec_dev_uda134x, - .codec_data = &s3c24xx_uda134x, -}; - static int s3c24xx_uda134x_setup_pin(int pin, char *fun) { if (gpio_request(pin, "s3c24xx_uda134x") < 0) { @@ -325,8 +321,7 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev) } platform_set_drvdata(s3c24xx_uda134x_snd_device, - &s3c24xx_uda134x_snd_devdata); - s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev; + &snd_soc_s3c24xx_uda134x); ret = platform_device_add(s3c24xx_uda134x_snd_device); if (ret) { printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); diff --git a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c index 06db130030a1..7cab4fcf1f12 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c @@ -16,9 +16,7 @@ #include #include -#include -#include -#include +#include #include #include @@ -39,34 +37,23 @@ static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_out; static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in; static struct s3c_i2sv2_info s3c64xx_i2sv4; -struct snd_soc_dai s3c64xx_i2s_v4_dai; -EXPORT_SYMBOL_GPL(s3c64xx_i2s_v4_dai); - -static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) +static int s3c64xx_i2sv4_probe(struct snd_soc_dai *dai) { - return cpu_dai->private_data; -} + struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4; + int ret = 0; -static int s3c64xx_i2sv4_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) -{ - /* configure GPIO for i2s port */ - s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0); - s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1); - s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2); - s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK); - s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK); - s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK); - s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI); + snd_soc_dai_set_drvdata(dai, i2s); - return 0; + ret = s3c_i2sv2_probe(dai, i2s, i2s->base); + + return ret; } static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { - struct s3c_i2sv2_info *i2s = to_info(cpu_dai); + struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); struct s3c_dma_params *dma_data; u32 iismod; @@ -104,51 +91,79 @@ static struct snd_soc_dai_ops s3c64xx_i2sv4_dai_ops = { .hw_params = s3c_i2sv4_hw_params, }; +static struct snd_soc_dai_driver s3c64xx_i2s_v4_dai = { + .symmetric_rates = 1, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C64XX_I2S_RATES, + .formats = S3C64XX_I2S_FMTS, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C64XX_I2S_RATES, + .formats = S3C64XX_I2S_FMTS, + }, + .probe = s3c64xx_i2sv4_probe, + .ops = &s3c64xx_i2sv4_dai_ops, +}; + static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) { + struct s3c_audio_pdata *i2s_pdata; struct s3c_i2sv2_info *i2s; - struct snd_soc_dai *dai; + struct resource *res; int ret; i2s = &s3c64xx_i2sv4; - dai = &s3c64xx_i2s_v4_dai; - - if (dai->dev) { - dev_dbg(dai->dev, "%s: \ - I2Sv4 instance already registered!\n", __func__); - return -EBUSY; - } - - dai->dev = &pdev->dev; - dai->name = "s3c64xx-i2s-v4"; - dai->id = 0; - dai->symmetric_rates = 1; - dai->playback.channels_min = 2; - dai->playback.channels_max = 2; - dai->playback.rates = S3C64XX_I2S_RATES; - dai->playback.formats = S3C64XX_I2S_FMTS; - dai->capture.channels_min = 2; - dai->capture.channels_max = 2; - dai->capture.rates = S3C64XX_I2S_RATES; - dai->capture.formats = S3C64XX_I2S_FMTS; - dai->probe = s3c64xx_i2sv4_probe; - dai->ops = &s3c64xx_i2sv4_dai_ops; i2s->feature |= S3C_FEATURE_CDCLKCON; i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in; i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out; - i2s->dma_capture->channel = DMACH_HSI_I2SV40_RX; - i2s->dma_capture->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISRXD; - i2s->dma_playback->channel = DMACH_HSI_I2SV40_TX; - i2s->dma_playback->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISTXD; + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!res) { + dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n"); + return -ENXIO; + } + i2s->dma_playback->channel = res->start; + + res = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (!res) { + dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n"); + return -ENXIO; + } + i2s->dma_capture->channel = res->start; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Unable to get I2S SFR address\n"); + return -ENXIO; + } + + if (!request_mem_region(res->start, resource_size(res), + "s3c64xx-i2s-v4")) { + dev_err(&pdev->dev, "Unable to request SFR region\n"); + return -EBUSY; + } + i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD; + i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD; i2s->dma_capture->client = &s3c64xx_dma_client_in; i2s->dma_capture->dma_size = 4; i2s->dma_playback->client = &s3c64xx_dma_client_out; i2s->dma_playback->dma_size = 4; + i2s->base = res->start; + + i2s_pdata = pdev->dev.platform_data; + if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { + dev_err(&pdev->dev, "Unable to configure gpio\n"); + return -EINVAL; + } + i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); if (IS_ERR(i2s->iis_cclk)) { dev_err(&pdev->dev, "failed to get audio-bus\n"); @@ -158,19 +173,13 @@ static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) clk_enable(i2s->iis_cclk); - ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); - if (ret) - goto err_clk; - - ret = s3c_i2sv2_register_dai(dai); + ret = s3c_i2sv2_register_dai(&pdev->dev, pdev->id, &s3c64xx_i2s_v4_dai); if (ret != 0) goto err_i2sv2; return 0; err_i2sv2: - /* Not implemented for I2Sv2 core yet */ -err_clk: clk_put(i2s->iis_cclk); err: return ret; @@ -178,7 +187,7 @@ err: static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev) { - dev_err(&pdev->dev, "Device removal not yet supported\n"); + snd_soc_unregister_dai(&pdev->dev); return 0; } diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index 1d85cb85a7d2..a1d0b2566416 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c @@ -12,15 +12,15 @@ * published by the Free Software Foundation. */ +#include #include #include #include +#include #include -#include -#include -#include +#include #include #include @@ -46,45 +46,107 @@ static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_out[MAX_I2SV3]; static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3]; static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3]; -struct snd_soc_dai s3c64xx_i2s_dai[MAX_I2SV3]; -EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); - -static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) +struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai) { - return cpu_dai->private_data; + struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai); + u32 iismod = readl(i2s->regs + S3C2412_IISMOD); + + if (iismod & S3C2412_IISMOD_IMS_SYSMUX) + return i2s->iis_cclk; + else + return i2s->iis_pclk; } +EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock); -static int s3c64xx_i2s_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int s3c64xx_i2s_probe(struct snd_soc_dai *dai) { - /* configure GPIO for i2s port */ - switch (dai->id) { - case 0: - s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); - s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); - s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK); - s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI); - s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0); - break; - case 1: - s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK); - s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK); - s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK); - s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI); - s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0); + struct s3c_i2sv2_info *i2s; + int ret; + + if (dai->id >= MAX_I2SV3) { + dev_err(dai->dev, "id %d out of range\n", dai->id); + return -EINVAL; + } + + i2s = &s3c64xx_i2s[dai->id]; + snd_soc_dai_set_drvdata(dai, i2s); + + i2s->iis_cclk = clk_get(dai->dev, "audio-bus"); + if (IS_ERR(i2s->iis_cclk)) { + dev_err(dai->dev, "failed to get audio-bus\n"); + ret = PTR_ERR(i2s->iis_cclk); + goto err; } + clk_enable(i2s->iis_cclk); + + ret = s3c_i2sv2_probe(dai, i2s, i2s->base); + if (ret) + goto err_clk; + return 0; + +err_clk: + clk_disable(i2s->iis_cclk); + clk_put(i2s->iis_cclk); +err: + kfree(i2s); + return ret; } +static int s3c64xx_i2s_remove(struct snd_soc_dai *dai) +{ + struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai); + + clk_disable(i2s->iis_cclk); + clk_put(i2s->iis_cclk); + kfree(i2s); + return 0; +} static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops; +static struct snd_soc_dai_driver s3c64xx_i2s_dai[MAX_I2SV3] = { +{ + .name = "s3c64xx-i2s-0", + .probe = s3c64xx_i2s_probe, + .remove = s3c64xx_i2s_remove, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C64XX_I2S_RATES, + .formats = S3C64XX_I2S_FMTS,}, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C64XX_I2S_RATES, + .formats = S3C64XX_I2S_FMTS,}, + .ops = &s3c64xx_i2s_dai_ops, + .symmetric_rates = 1, +}, { + .name = "s3c64xx-i2s-1", + .probe = s3c64xx_i2s_probe, + .remove = s3c64xx_i2s_remove, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C64XX_I2S_RATES, + .formats = S3C64XX_I2S_FMTS,}, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C64XX_I2S_RATES, + .formats = S3C64XX_I2S_FMTS,}, + .ops = &s3c64xx_i2s_dai_ops, + .symmetric_rates = 1, +},}; + static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) { + struct s3c_audio_pdata *i2s_pdata; struct s3c_i2sv2_info *i2s; - struct snd_soc_dai *dai; - int ret; + struct resource *res; + int i, ret; if (pdev->id >= MAX_I2SV3) { dev_err(&pdev->dev, "id %d out of range\n", pdev->id); @@ -92,74 +154,63 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) } i2s = &s3c64xx_i2s[pdev->id]; - dai = &s3c64xx_i2s_dai[pdev->id]; - dai->dev = &pdev->dev; - dai->name = "s3c64xx-i2s"; - dai->id = pdev->id; - dai->symmetric_rates = 1; - dai->playback.channels_min = 2; - dai->playback.channels_max = 2; - dai->playback.rates = S3C64XX_I2S_RATES; - dai->playback.formats = S3C64XX_I2S_FMTS; - dai->capture.channels_min = 2; - dai->capture.channels_max = 2; - dai->capture.rates = S3C64XX_I2S_RATES; - dai->capture.formats = S3C64XX_I2S_FMTS; - dai->probe = s3c64xx_i2s_probe; - dai->ops = &s3c64xx_i2s_dai_ops; - - i2s->feature |= S3C_FEATURE_CDCLKCON; i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; - if (pdev->id == 0) { - i2s->dma_capture->channel = DMACH_I2S0_IN; - i2s->dma_capture->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISRXD; - i2s->dma_playback->channel = DMACH_I2S0_OUT; - i2s->dma_playback->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISTXD; - } else { - i2s->dma_capture->channel = DMACH_I2S1_IN; - i2s->dma_capture->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISRXD; - i2s->dma_playback->channel = DMACH_I2S1_OUT; - i2s->dma_playback->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISTXD; + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!res) { + dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n"); + return -ENXIO; + } + i2s->dma_playback->channel = res->start; + + res = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (!res) { + dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n"); + return -ENXIO; + } + i2s->dma_capture->channel = res->start; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Unable to get I2S SFR address\n"); + return -ENXIO; } + if (!request_mem_region(res->start, resource_size(res), + "s3c64xx-i2s")) { + dev_err(&pdev->dev, "Unable to request SFR region\n"); + return -EBUSY; + } + i2s->base = res->start; + + i2s_pdata = pdev->dev.platform_data; + if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { + dev_err(&pdev->dev, "Unable to configure gpio\n"); + return -EINVAL; + } + i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD; + i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD; + i2s->dma_capture->client = &s3c64xx_dma_client_in; i2s->dma_capture->dma_size = 4; i2s->dma_playback->client = &s3c64xx_dma_client_out; i2s->dma_playback->dma_size = 4; - i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); - if (IS_ERR(i2s->iis_cclk)) { - dev_err(&pdev->dev, "failed to get audio-bus\n"); - ret = PTR_ERR(i2s->iis_cclk); - goto err; + for (i = 0; i < ARRAY_SIZE(s3c64xx_i2s_dai); i++) { + ret = s3c_i2sv2_register_dai(&pdev->dev, i, + &s3c64xx_i2s_dai[i]); + if (ret != 0) + return ret; } - clk_enable(i2s->iis_cclk); - - ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); - if (ret) - goto err_clk; - - ret = s3c_i2sv2_register_dai(dai); - if (ret != 0) - goto err_i2sv2; - return 0; - -err_i2sv2: - /* Not implemented for I2Sv2 core yet */ -err_clk: - clk_put(i2s->iis_cclk); -err: - return ret; } static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev) { - dev_err(&pdev->dev, "Device removal not yet supported\n"); + snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c64xx_i2s_dai)); return 0; } diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h index 7a40f43d1d51..19bd444bf8a6 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.h +++ b/sound/soc/s3c24xx/s3c64xx-i2s.h @@ -36,7 +36,5 @@ struct clk; (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S24_LE) -extern struct snd_soc_dai s3c64xx_i2s_dai[]; -extern struct snd_soc_dai s3c64xx_i2s_v4_dai; #endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ diff --git a/sound/soc/s3c24xx/smartq_wm8987.c b/sound/soc/s3c24xx/smartq_wm8987.c index b480348140b0..dd20ca7f4681 100644 --- a/sound/soc/s3c24xx/smartq_wm8987.c +++ b/sound/soc/s3c24xx/smartq_wm8987.c @@ -211,8 +211,10 @@ static struct snd_soc_dai_link smartq_dai[] = { { .name = "wm8987", .stream_name = "SmartQ Hi-Fi", - .cpu_dai = &s3c64xx_i2s_dai[0], - .codec_dai = &wm8750_dai, + .cpu_dai_name = "s3c64xx-i2s.0", + .codec_dai_name = "wm8750-hifi", + .platform_name = "s3c24xx-pcm-audio", + .codec_name = "wm8750-codec.0-0x1a", .init = smartq_wm8987_init, .ops = &smartq_hifi_ops, }, @@ -220,16 +222,10 @@ static struct snd_soc_dai_link smartq_dai[] = { static struct snd_soc_card snd_soc_smartq = { .name = "SmartQ", - .platform = &s3c24xx_soc_platform, .dai_link = smartq_dai, .num_links = ARRAY_SIZE(smartq_dai), }; -static struct snd_soc_device smartq_snd_devdata = { - .card = &snd_soc_smartq, - .codec_dev = &soc_codec_dev_wm8750, -}; - static struct platform_device *smartq_snd_device; static int __init smartq_init(void) @@ -245,8 +241,7 @@ static int __init smartq_init(void) if (!smartq_snd_device) return -ENOMEM; - platform_set_drvdata(smartq_snd_device, &smartq_snd_devdata); - smartq_snd_devdata.dev = &smartq_snd_device->dev; + platform_set_drvdata(smartq_snd_device, &snd_soc_smartq); ret = platform_device_add(smartq_snd_device); if (ret) { diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c index 362258835e8d..66f9e222220b 100644 --- a/sound/soc/s3c24xx/smdk2443_wm9710.c +++ b/sound/soc/s3c24xx/smdk2443_wm9710.c @@ -19,7 +19,6 @@ #include #include -#include "../codecs/ac97.h" #include "s3c-dma.h" #include "s3c-ac97.h" @@ -29,23 +28,19 @@ static struct snd_soc_dai_link smdk2443_dai[] = { { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], - .codec_dai = &ac97_dai, + .cpu_dai_name = "s3c-ac97-dai", + .codec_dai_name = "ac97-hifi", + .codec_name = "ac97-codec", + .platform_name = "s3c24xx-pcm-audio", }, }; static struct snd_soc_card smdk2443 = { .name = "SMDK2443", - .platform = &s3c24xx_soc_platform, .dai_link = smdk2443_dai, .num_links = ARRAY_SIZE(smdk2443_dai), }; -static struct snd_soc_device smdk2443_snd_ac97_devdata = { - .card = &smdk2443, - .codec_dev = &soc_codec_dev_ac97, -}; - static struct platform_device *smdk2443_snd_ac97_device; static int __init smdk2443_init(void) @@ -56,9 +51,7 @@ static int __init smdk2443_init(void) if (!smdk2443_snd_ac97_device) return -ENOMEM; - platform_set_drvdata(smdk2443_snd_ac97_device, - &smdk2443_snd_ac97_devdata); - smdk2443_snd_ac97_devdata.dev = &smdk2443_snd_ac97_device->dev; + platform_set_drvdata(smdk2443_snd_ac97_device, &smdk2443); ret = platform_device_add(smdk2443_snd_ac97_device); if (ret) diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c index 07e8e51d10d6..634acfc41608 100644 --- a/sound/soc/s3c24xx/smdk64xx_wm8580.c +++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c @@ -29,8 +29,8 @@ static int smdk64xx_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; unsigned int pll_out; int bfs, rfs, ret; @@ -174,8 +174,10 @@ static const struct snd_soc_dapm_route audio_map_rx[] = { {"Rear-L/R", NULL, "VOUT3R"}, }; -static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec) +static int smdk64xx_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + /* Add smdk64xx specific Capture widgets */ snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt, ARRAY_SIZE(wm8580_dapm_widgets_cpt)); @@ -194,8 +196,10 @@ static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec) return 0; } -static int smdk64xx_wm8580_init_paifrx(struct snd_soc_codec *codec) +static int smdk64xx_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + /* Add smdk64xx specific Playback widgets */ snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk, ARRAY_SIZE(wm8580_dapm_widgets_pbk)); @@ -213,16 +217,20 @@ static struct snd_soc_dai_link smdk64xx_dai[] = { { /* Primary Playback i/f */ .name = "WM8580 PAIF RX", .stream_name = "Playback", - .cpu_dai = &s3c64xx_i2s_v4_dai, - .codec_dai = &wm8580_dai[WM8580_DAI_PAIFRX], + .cpu_dai_name = "s3c64xx-iis-v4", + .codec_dai_name = "wm8580-hifi-playback", + .platform_name = "s3c24xx-pcm-audio", + .codec_name = "wm8580-codec.0-001b", .init = smdk64xx_wm8580_init_paifrx, .ops = &smdk64xx_ops, }, { /* Primary Capture i/f */ .name = "WM8580 PAIF TX", .stream_name = "Capture", - .cpu_dai = &s3c64xx_i2s_v4_dai, - .codec_dai = &wm8580_dai[WM8580_DAI_PAIFTX], + .cpu_dai_name = "s3c64xx-iis-v4", + .codec_dai_name = "wm8580-hifi-capture", + .platform_name = "s3c24xx-pcm-audio", + .codec_name = "wm8580-codec.0-001b", .init = smdk64xx_wm8580_init_paiftx, .ops = &smdk64xx_ops, }, @@ -230,16 +238,10 @@ static struct snd_soc_dai_link smdk64xx_dai[] = { static struct snd_soc_card smdk64xx = { .name = "smdk64xx", - .platform = &s3c24xx_soc_platform, .dai_link = smdk64xx_dai, .num_links = ARRAY_SIZE(smdk64xx_dai), }; -static struct snd_soc_device smdk64xx_snd_devdata = { - .card = &smdk64xx, - .codec_dev = &soc_codec_dev_wm8580, -}; - static struct platform_device *smdk64xx_snd_device; static int __init smdk64xx_audio_init(void) @@ -250,8 +252,7 @@ static int __init smdk64xx_audio_init(void) if (!smdk64xx_snd_device) return -ENOMEM; - platform_set_drvdata(smdk64xx_snd_device, &smdk64xx_snd_devdata); - smdk64xx_snd_devdata.dev = &smdk64xx_snd_device->dev; + platform_set_drvdata(smdk64xx_snd_device, &smdk64xx); ret = platform_device_add(smdk64xx_snd_device); if (ret) diff --git a/sound/soc/s3c24xx/smdk_wm9713.c b/sound/soc/s3c24xx/smdk_wm9713.c index 5527b9e88c98..90108a7a0a8e 100644 --- a/sound/soc/s3c24xx/smdk_wm9713.c +++ b/sound/soc/s3c24xx/smdk_wm9713.c @@ -46,40 +46,50 @@ static struct snd_soc_card smdk; static struct snd_soc_dai_link smdk_dai = { .name = "AC97", .stream_name = "AC97 PCM", - .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], - .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], + .platform_name = "s3c24xx-pcm-audio", + .cpu_dai_name = "s3c-ac97-dai", + .codec_dai_name = "wm9713-hifi", + .codec_name = "wm9713-codec", }; static struct snd_soc_card smdk = { .name = "SMDK", - .platform = &s3c24xx_soc_platform, .dai_link = &smdk_dai, .num_links = 1, }; -static struct snd_soc_device smdk_snd_ac97_devdata = { - .card = &smdk, - .codec_dev = &soc_codec_dev_wm9713, -}; - +static struct platform_device *smdk_snd_wm9713_device; static struct platform_device *smdk_snd_ac97_device; static int __init smdk_init(void) { int ret; - smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1); - if (!smdk_snd_ac97_device) + smdk_snd_wm9713_device = platform_device_alloc("wm9713-codec", -1); + if (!smdk_snd_wm9713_device) return -ENOMEM; - platform_set_drvdata(smdk_snd_ac97_device, - &smdk_snd_ac97_devdata); - smdk_snd_ac97_devdata.dev = &smdk_snd_ac97_device->dev; + ret = platform_device_add(smdk_snd_wm9713_device); + if (ret) + goto err; + + smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1); + if (!smdk_snd_ac97_device) { + ret = -ENOMEM; + goto err; + } + + platform_set_drvdata(smdk_snd_ac97_device, &smdk); ret = platform_device_add(smdk_snd_ac97_device); - if (ret) + if (ret) { platform_device_put(smdk_snd_ac97_device); + goto err; + } + return 0; +err: + platform_device_put(smdk_snd_wm9713_device); return ret; } diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c index 59e3fa7bcb05..8778faa174a6 100644 --- a/sound/soc/s6000/s6000-i2s.c +++ b/sound/soc/s6000/s6000-i2s.c @@ -140,7 +140,7 @@ static void s6000_i2s_stop_channel(struct s6000_i2s_dev *dev, int channel) static void s6000_i2s_start(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data; + struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); int channel; channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? @@ -152,7 +152,7 @@ static void s6000_i2s_start(struct snd_pcm_substream *substream) static void s6000_i2s_stop(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data; + struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); int channel; channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? @@ -194,7 +194,7 @@ static unsigned int s6000_i2s_int_sources(struct s6000_i2s_dev *dev) static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai) { - struct s6000_i2s_dev *dev = cpu_dai->private_data; + struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); unsigned int errors; unsigned int ret; @@ -232,7 +232,7 @@ static void s6000_i2s_wait_disabled(struct s6000_i2s_dev *dev) static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct s6000_i2s_dev *dev = cpu_dai->private_data; + struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); u32 w; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -273,7 +273,7 @@ static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) { - struct s6000_i2s_dev *dev = dai->private_data; + struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2) return -EINVAL; @@ -287,7 +287,7 @@ static int s6000_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct s6000_i2s_dev *dev = dai->private_data; + struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); int interf; u32 w = 0; @@ -326,15 +326,17 @@ static int s6000_i2s_hw_params(struct snd_pcm_substream *substream, return 0; } -static int s6000_i2s_dai_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int s6000_i2s_dai_probe(struct snd_soc_dai *dai) { - struct s6000_i2s_dev *dev = dai->private_data; - struct s6000_snd_platform_data *pdata = pdev->dev.platform_data; + struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); + struct s6000_snd_platform_data *pdata = dai->dev->platform_data; if (!pdata) return -EINVAL; + dai->capture_dma_data = &dev->dma_params; + dai->playback_dma_data = &dev->dma_params; + dev->wide = pdata->wide; dev->channel_in = pdata->channel_in; dev->channel_out = pdata->channel_out; @@ -352,10 +354,10 @@ static int s6000_i2s_dai_probe(struct platform_device *pdev, dev->channel_in = 0; dev->channel_out = 1; - dai->capture.channels_min = 2 * dev->lines_in; - dai->capture.channels_max = dai->capture.channels_min; - dai->playback.channels_min = 2 * dev->lines_out; - dai->playback.channels_max = dai->playback.channels_min; + dai->driver->capture.channels_min = 2 * dev->lines_in; + dai->driver->capture.channels_max = dai->driver->capture.channels_min; + dai->driver->playback.channels_min = 2 * dev->lines_out; + dai->driver->playback.channels_max = dai->driver->playback.channels_min; for (i = 0; i < dev->lines_out; i++) s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT); @@ -372,10 +374,10 @@ static int s6000_i2s_dai_probe(struct platform_device *pdev, if (dev->lines_in > 1 || dev->lines_out > 1) return -EINVAL; - dai->capture.channels_min = 2 * dev->lines_in; - dai->capture.channels_max = 8 * dev->lines_in; - dai->playback.channels_min = 2 * dev->lines_out; - dai->playback.channels_max = 8 * dev->lines_out; + dai->driver->capture.channels_min = 2 * dev->lines_in; + dai->driver->capture.channels_max = 8 * dev->lines_in; + dai->driver->playback.channels_min = 2 * dev->lines_out; + dai->driver->playback.channels_max = 8 * dev->lines_out; if (dev->lines_in) cfg[dev->channel_in] = S6_I2S_IN; @@ -413,9 +415,7 @@ static struct snd_soc_dai_ops s6000_i2s_dai_ops = { .hw_params = s6000_i2s_hw_params, }; -struct snd_soc_dai s6000_i2s_dai = { - .name = "s6000-i2s", - .id = 0, +static struct snd_soc_dai_driver s6000_i2s_dai = { .probe = s6000_i2s_dai_probe, .playback = { .channels_min = 2, @@ -435,7 +435,6 @@ struct snd_soc_dai s6000_i2s_dai = { }, .ops = &s6000_i2s_dai_ops, } -EXPORT_SYMBOL_GPL(s6000_i2s_dai); static int __devinit s6000_i2s_probe(struct platform_device *pdev) { @@ -513,11 +512,7 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_release_dma2; } - - s6000_i2s_dai.dev = &pdev->dev; - s6000_i2s_dai.private_data = dev; - s6000_i2s_dai.capture.dma_data = &dev->dma_params; - s6000_i2s_dai.playback.dma_data = &dev->dma_params; + dev_set_drvdata(&pdev->dev, dev); dev->sifbase = sifmem->start; dev->scbbase = mmio; @@ -548,7 +543,7 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev) S6_I2S_INT_UNDERRUN | S6_I2S_INT_OVERRUN); - ret = snd_soc_register_dai(&s6000_i2s_dai); + ret = snd_soc_register_dai(&pdev->dev, &s6000_i2s_dai); if (ret) goto err_release_dev; @@ -573,17 +568,16 @@ err_release_none: static void __devexit s6000_i2s_remove(struct platform_device *pdev) { - struct s6000_i2s_dev *dev = s6000_i2s_dai.private_data; + struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev); struct resource *region; void __iomem *mmio = dev->scbbase; - snd_soc_unregister_dai(&s6000_i2s_dai); + snd_soc_unregister_dai(&pdev->dev); s6000_i2s_stop_channel(dev, 0); s6000_i2s_stop_channel(dev, 1); s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0); - s6000_i2s_dai.private_data = 0; kfree(dev); region = platform_get_resource(pdev, IORESOURCE_DMA, 0); diff --git a/sound/soc/s6000/s6000-i2s.h b/sound/soc/s6000/s6000-i2s.h index 2375fdfe6dba..86aa1921c89e 100644 --- a/sound/soc/s6000/s6000-i2s.h +++ b/sound/soc/s6000/s6000-i2s.h @@ -12,8 +12,6 @@ #ifndef _S6000_I2S_H #define _S6000_I2S_H -extern struct snd_soc_dai s6000_i2s_dai; - struct s6000_snd_platform_data { int lines_in; int lines_out; diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c index 9c7f7f00cebb..271fd222bf19 100644 --- a/sound/soc/s6000/s6000-pcm.c +++ b/sound/soc/s6000/s6000-pcm.c @@ -65,7 +65,7 @@ static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream) dma_addr_t dma_pos; dma_addr_t src, dst; - par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); period_size = snd_pcm_lib_period_bytes(substream); dma_offset = prtd->period * period_size; @@ -103,23 +103,25 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) { struct snd_pcm *pcm = data; struct snd_soc_pcm_runtime *runtime = pcm->private_data; - struct s6000_pcm_dma_params *params = - snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); struct s6000_runtime_data *prtd; unsigned int has_xrun; int i, ret = IRQ_NONE; - u32 channel[2] = { - [SNDRV_PCM_STREAM_PLAYBACK] = params->dma_out, - [SNDRV_PCM_STREAM_CAPTURE] = params->dma_in - }; - - has_xrun = params->check_xrun(runtime->dai->cpu_dai); - for (i = 0; i < ARRAY_SIZE(channel); ++i) { + for (i = 0; i < 2; ++i) { struct snd_pcm_substream *substream = pcm->streams[i].substream; + struct s6000_pcm_dma_params *params = + snd_soc_dai_get_dma_data(runtime->cpu_dai, substream); + u32 channel; unsigned int pending; - if (!channel[i]) + if (substream == SNDRV_PCM_STREAM_PLAYBACK) + channel = params->dma_out; + else + channel = params->dma_in; + + has_xrun = params->check_xrun(runtime->cpu_dai); + + if (!channel) continue; if (unlikely(has_xrun & (1 << i)) && @@ -130,8 +132,8 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) ret = IRQ_HANDLED; } - pending = s6dmac_int_sources(DMA_MASK_DMAC(channel[i]), - DMA_INDEX_CHNL(channel[i])); + pending = s6dmac_int_sources(DMA_MASK_DMAC(channel), + DMA_INDEX_CHNL(channel)); if (pending & 1) { ret = IRQ_HANDLED; @@ -139,10 +141,10 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) snd_pcm_running(substream))) { snd_pcm_period_elapsed(substream); dev_dbg(pcm->dev, "period elapsed %x %x\n", - s6dmac_cur_src(DMA_MASK_DMAC(channel[i]), - DMA_INDEX_CHNL(channel[i])), - s6dmac_cur_dst(DMA_MASK_DMAC(channel[i]), - DMA_INDEX_CHNL(channel[i]))); + s6dmac_cur_src(DMA_MASK_DMAC(channel), + DMA_INDEX_CHNL(channel)), + s6dmac_cur_dst(DMA_MASK_DMAC(channel), + DMA_INDEX_CHNL(channel))); prtd = substream->runtime->private_data; spin_lock(&prtd->lock); s6000_pcm_enqueue_dma(substream); @@ -154,16 +156,16 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) if (pending & (1 << 3)) printk(KERN_WARNING "s6000-pcm: DMA %x Underflow\n", - channel[i]); + channel); if (pending & (1 << 4)) printk(KERN_WARNING "s6000-pcm: DMA %x Overflow\n", - channel[i]); + channel); if (pending & 0x1e0) printk(KERN_WARNING "s6000-pcm: DMA %x Master Error " "(mask %x)\n", - channel[i], pending >> 5); + channel, pending >> 5); } } @@ -180,7 +182,7 @@ static int s6000_pcm_start(struct snd_pcm_substream *substream) int srcinc; u32 dma; - par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); spin_lock_irqsave(&prtd->lock, flags); @@ -221,7 +223,7 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream) unsigned long flags; u32 channel; - par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) channel = par->dma_out; @@ -246,7 +248,7 @@ static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct s6000_pcm_dma_params *par; int ret; - par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); ret = par->trigger(substream, cmd, 0); if (ret < 0) @@ -291,7 +293,7 @@ static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream) unsigned int offset; dma_addr_t count; - par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); spin_lock_irqsave(&prtd->lock, flags); @@ -321,7 +323,7 @@ static int s6000_pcm_open(struct snd_pcm_substream *substream) struct s6000_runtime_data *prtd; int ret; - par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware); ret = snd_pcm_hw_constraint_step(runtime, 0, @@ -385,7 +387,7 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream, return ret; } - par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); if (par->same_rate) { spin_lock(&par->lock); @@ -407,7 +409,7 @@ static int s6000_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct s6000_pcm_dma_params *par = - snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); spin_lock(&par->lock); par->in_use &= ~(1 << substream->stream); @@ -433,7 +435,7 @@ static void s6000_pcm_free(struct snd_pcm *pcm) { struct snd_soc_pcm_runtime *runtime = pcm->private_data; struct s6000_pcm_dma_params *params = - snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + snd_soc_dai_get_dma_data(runtime->cpu_dai, pcm->streams[0].substream); free_irq(params->irq, pcm); snd_pcm_lib_preallocate_free_for_all(pcm); @@ -448,7 +450,8 @@ static int s6000_pcm_new(struct snd_card *card, struct s6000_pcm_dma_params *params; int res; - params = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + params = snd_soc_dai_get_dma_data(runtime->cpu_dai, + pcm->streams[0].substream); if (!card->dev->dma_mask) card->dev->dma_mask = &s6000_pcm_dmamask; @@ -490,25 +493,44 @@ static int s6000_pcm_new(struct snd_card *card, return 0; } -struct snd_soc_platform s6000_soc_platform = { - .name = "s6000-audio", - .pcm_ops = &s6000_pcm_ops, +static struct snd_soc_platform_driver s6000_soc_platform = { + .ops = &s6000_pcm_ops, .pcm_new = s6000_pcm_new, .pcm_free = s6000_pcm_free, }; -EXPORT_SYMBOL_GPL(s6000_soc_platform); -static int __init s6000_pcm_init(void) +static int __devinit s6000_soc_platform_probe(struct platform_device *pdev) +{ + return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform); +} + +static int __devexit s6000_soc_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver s6000_pcm_driver = { + .driver = { + .name = "s6000-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = s6000_soc_platform_probe, + .remove = __devexit_p(s6000_soc_platform_remove), +}; + +static int __init snd_s6000_pcm_init(void) { - return snd_soc_register_platform(&s6000_soc_platform); + return platform_driver_register(&s6000_pcm_driver); } -module_init(s6000_pcm_init); +module_init(snd_s6000_pcm_init); -static void __exit s6000_pcm_exit(void) +static void __exit snd_s6000_pcm_exit(void) { - snd_soc_unregister_platform(&s6000_soc_platform); + platform_driver_unregister(&s6000_pcm_driver); } -module_exit(s6000_pcm_exit); +module_exit(snd_s6000_pcm_exit); MODULE_AUTHOR("Daniel Gloeckner"); MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module"); diff --git a/sound/soc/s6000/s6000-pcm.h b/sound/soc/s6000/s6000-pcm.h index 96f23f6f52bf..09d9b883e58b 100644 --- a/sound/soc/s6000/s6000-pcm.h +++ b/sound/soc/s6000/s6000-pcm.h @@ -30,6 +30,4 @@ struct s6000_pcm_dma_params { int rate; }; -extern struct snd_soc_platform s6000_soc_platform; - #endif diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c index c1b40ac22c05..96c05e137538 100644 --- a/sound/soc/s6000/s6105-ipcam.c +++ b/sound/soc/s6000/s6105-ipcam.c @@ -32,8 +32,8 @@ static int s6105_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret = 0; /* set codec DAI configuration */ @@ -134,8 +134,10 @@ static const struct snd_kcontrol_new audio_out_mux = { }; /* Logic for a aic3x as connected on the s6105 ip camera ref design */ -static int s6105_aic3x_init(struct snd_soc_codec *codec) +static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + /* Add s6105 specific widgets */ snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, ARRAY_SIZE(aic3x_dapm_widgets)); @@ -165,7 +167,7 @@ static int s6105_aic3x_init(struct snd_soc_codec *codec) snd_soc_dapm_sync(codec); - snd_ctl_add(codec->card, snd_ctl_new1(&audio_out_mux, codec)); + snd_ctl_add(codec->snd_card, snd_ctl_new1(&audio_out_mux, codec)); return 0; } @@ -174,8 +176,10 @@ static int s6105_aic3x_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link s6105_dai = { .name = "TLV320AIC31", .stream_name = "AIC31", - .cpu_dai = &s6000_i2s_dai, - .codec_dai = &aic3x_dai, + .cpu_dai_name = "s6000-i2s", + .codec_dai_name = "tlv320aic3x-hifi", + .platform_name = "s6000-pcm-audio", + .codec_name = "tlv320aic3x-codec.0-001a", .init = s6105_aic3x_init, .ops = &s6105_ops, }; @@ -183,22 +187,10 @@ static struct snd_soc_dai_link s6105_dai = { /* s6105 audio machine driver */ static struct snd_soc_card snd_soc_card_s6105 = { .name = "Stretch IP Camera", - .platform = &s6000_soc_platform, .dai_link = &s6105_dai, .num_links = 1, }; -/* s6105 audio private data */ -static struct aic3x_setup_data s6105_aic3x_setup = { -}; - -/* s6105 audio subsystem */ -static struct snd_soc_device s6105_snd_devdata = { - .card = &snd_soc_card_s6105, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &s6105_aic3x_setup, -}; - static struct s6000_snd_platform_data __initdata s6105_snd_data = { .wide = 0, .channel_in = 0, @@ -227,8 +219,7 @@ static int __init s6105_init(void) if (!s6105_snd_device) return -ENOMEM; - platform_set_drvdata(s6105_snd_device, &s6105_snd_devdata); - s6105_snd_devdata.dev = &s6105_snd_device->dev; + platform_set_drvdata(s6105_snd_device, &snd_soc_card_s6105); platform_device_add_data(s6105_snd_device, &s6105_snd_data, sizeof(s6105_snd_data)); diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index 0d8bdf07729c..c326d29992fe 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c @@ -137,7 +137,7 @@ static void camelot_rxdma(void *data) static int camelot_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; + struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; int ret, dmairq; @@ -150,7 +150,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream) ret = dmabrg_request_irq(dmairq, camelot_rxdma, cam); if (unlikely(ret)) { pr_debug("audio unit %d irqs already taken!\n", - rtd->dai->cpu_dai->id); + rtd->cpu_dai->id); return -EBUSY; } (void)dmabrg_request_irq(dmairq + 1,camelot_rxdma, cam); @@ -159,7 +159,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream) ret = dmabrg_request_irq(dmairq, camelot_txdma, cam); if (unlikely(ret)) { pr_debug("audio unit %d irqs already taken!\n", - rtd->dai->cpu_dai->id); + rtd->cpu_dai->id); return -EBUSY; } (void)dmabrg_request_irq(dmairq + 1, camelot_txdma, cam); @@ -170,7 +170,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream) static int camelot_pcm_close(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; + struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; int dmairq; @@ -191,7 +191,7 @@ static int camelot_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; + struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; int ret; @@ -219,7 +219,7 @@ static int camelot_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; + struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; pr_debug("PCM data: addr 0x%08ulx len %d\n", (u32)runtime->dma_addr, runtime->dma_bytes); @@ -266,7 +266,7 @@ static inline void dmabrg_rec_dma_stop(struct camelot_pcm *cam) static int camelot_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; + struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; switch (cmd) { @@ -293,7 +293,7 @@ static snd_pcm_uframes_t camelot_pos(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; + struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; unsigned long pos; @@ -342,25 +342,44 @@ static int camelot_pcm_new(struct snd_card *card, return 0; } -struct snd_soc_platform sh7760_soc_platform = { - .name = "sh7760-pcm", +static struct snd_soc_platform sh7760_soc_platform = { .pcm_ops = &camelot_pcm_ops, .pcm_new = camelot_pcm_new, .pcm_free = camelot_pcm_free, }; -EXPORT_SYMBOL_GPL(sh7760_soc_platform); -static int __init sh7760_soc_platform_init(void) +static int __devinit sh7760_soc_platform_probe(struct platform_device *pdev) { - return snd_soc_register_platform(&sh7760_soc_platform); + return snd_soc_register_platform(&pdev->dev, &sh7760_soc_platform); } -module_init(sh7760_soc_platform_init); -static void __exit sh7760_soc_platform_exit(void) +static int __devexit sh7760_soc_platform_remove(struct platform_device *pdev) { - snd_soc_unregister_platform(&sh7760_soc_platform); + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver sh7760_pcm_driver = { + .driver = { + .name = "sh7760-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = sh7760_soc_platform_probe, + .remove = __devexit_p(sh7760_soc_platform_remove), +}; + +static int __init snd_sh7760_pcm_init(void) +{ + return platform_driver_register(&sh7760_pcm_driver); +} +module_init(snd_sh7760_pcm_init); + +static void __exit snd_sh7760_pcm_exit(void) +{ + platform_driver_unregister(&sh7760_pcm_driver); } -module_exit(sh7760_soc_platform_exit); +module_exit(snd_sh7760_pcm_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver"); diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c index dad575a22622..9e107a9c4010 100644 --- a/sound/soc/sh/fsi-ak4642.c +++ b/sound/soc/sh/fsi-ak4642.c @@ -11,17 +11,17 @@ #include #include -#include <../sound/soc/codecs/ak4642.h> -static int fsi_ak4642_dai_init(struct snd_soc_codec *codec) +static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_dai *dai = rtd->codec_dai; int ret; - ret = snd_soc_dai_set_fmt(&ak4642_dai, SND_SOC_DAIFMT_CBM_CFM); + ret = snd_soc_dai_set_fmt(dai, SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) return ret; - ret = snd_soc_dai_set_sysclk(&ak4642_dai, 0, 11289600, 0); + ret = snd_soc_dai_set_sysclk(dai, 0, 11289600, 0); return ret; } @@ -29,24 +29,20 @@ static int fsi_ak4642_dai_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link fsi_dai_link = { .name = "AK4642", .stream_name = "AK4642", - .cpu_dai = &fsi_soc_dai[FSI_PORT_A], - .codec_dai = &ak4642_dai, + .cpu_dai_name = "fsia-dai", /* fsi A */ + .codec_dai_name = "ak4642-hifi", + .platform_name = "fsi-pcm-audio", + .codec_name = "ak4642-codec.0-0012", .init = fsi_ak4642_dai_init, .ops = NULL, }; static struct snd_soc_card fsi_soc_card = { .name = "FSI", - .platform = &fsi_soc_platform, .dai_link = &fsi_dai_link, .num_links = 1, }; -static struct snd_soc_device fsi_snd_devdata = { - .card = &fsi_soc_card, - .codec_dev = &soc_codec_dev_ak4642, -}; - static struct platform_device *fsi_snd_device; static int __init fsi_ak4642_init(void) @@ -57,9 +53,7 @@ static int __init fsi_ak4642_init(void) if (!fsi_snd_device) goto out; - platform_set_drvdata(fsi_snd_device, - &fsi_snd_devdata); - fsi_snd_devdata.dev = &fsi_snd_device->dev; + platform_set_drvdata(fsi_snd_device, &fsi_soc_card); ret = platform_device_add(fsi_snd_device); if (ret) diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c index 121bbb07bb03..4f9298f45215 100644 --- a/sound/soc/sh/fsi-da7210.c +++ b/sound/soc/sh/fsi-da7210.c @@ -12,11 +12,12 @@ #include #include -#include "../codecs/da7210.h" -static int fsi_da7210_init(struct snd_soc_codec *codec) +static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd) { - return snd_soc_dai_set_fmt(&da7210_dai, + struct snd_soc_dai *dai = rtd->codec_dai; + + return snd_soc_dai_set_fmt(dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); } @@ -24,23 +25,19 @@ static int fsi_da7210_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link fsi_da7210_dai = { .name = "DA7210", .stream_name = "DA7210", - .cpu_dai = &fsi_soc_dai[FSI_PORT_B], - .codec_dai = &da7210_dai, + .cpu_dai_name = "fsib-dai", /* FSI B */ + .codec_dai_name = "da7210-hifi", + .platform_name = "fsi-pcm-audio", + .codec_name = "da7210-codec.0-001a", .init = fsi_da7210_init, }; static struct snd_soc_card fsi_soc_card = { .name = "FSI", - .platform = &fsi_soc_platform, .dai_link = &fsi_da7210_dai, .num_links = 1, }; -static struct snd_soc_device fsi_da7210_snd_devdata = { - .card = &fsi_soc_card, - .codec_dev = &soc_codec_dev_da7210, -}; - static struct platform_device *fsi_da7210_snd_device; static int __init fsi_da7210_sound_init(void) @@ -51,8 +48,7 @@ static int __init fsi_da7210_sound_init(void) if (!fsi_da7210_snd_device) return -ENOMEM; - platform_set_drvdata(fsi_da7210_snd_device, &fsi_da7210_snd_devdata); - fsi_da7210_snd_devdata.dev = &fsi_da7210_snd_device->dev; + platform_set_drvdata(fsi_da7210_snd_device, &fsi_soc_card); ret = platform_device_add(fsi_da7210_snd_device); if (ret) platform_device_put(fsi_da7210_snd_device); diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 58c6bec642de..abc6d8309609 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -271,16 +271,19 @@ static int fsi_is_port_a(struct fsi_priv *fsi) static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai_link *machine = rtd->dai; - return machine->cpu_dai; + return rtd->cpu_dai; } static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) { struct snd_soc_dai *dai = fsi_get_dai(substream); + struct fsi_master *master = snd_soc_dai_get_drvdata(dai); - return dai->private_data; + if (dai->id == 0) + return &master->fsia; + else + return &master->fsib; } static u32 fsi_get_info_flags(struct fsi_priv *fsi) @@ -1025,10 +1028,9 @@ static int fsi_pcm_new(struct snd_card *card, ************************************************************************/ -struct snd_soc_dai fsi_soc_dai[] = { +static struct snd_soc_dai_driver fsi_soc_dai[] = { { - .name = "FSIA", - .id = 0, + .name = "fsia-dai", .playback = { .rates = FSI_RATES, .formats = FSI_FMTS, @@ -1044,8 +1046,7 @@ struct snd_soc_dai fsi_soc_dai[] = { .ops = &fsi_dai_ops, }, { - .name = "FSIB", - .id = 1, + .name = "fsib-dai", .playback = { .rates = FSI_RATES, .formats = FSI_FMTS, @@ -1061,15 +1062,12 @@ struct snd_soc_dai fsi_soc_dai[] = { .ops = &fsi_dai_ops, }, }; -EXPORT_SYMBOL_GPL(fsi_soc_dai); -struct snd_soc_platform fsi_soc_platform = { - .name = "fsi-pcm", - .pcm_ops = &fsi_pcm_ops, +static struct snd_soc_platform_driver fsi_soc_platform = { + .ops = &fsi_pcm_ops, .pcm_new = fsi_pcm_new, .pcm_free = fsi_pcm_free, }; -EXPORT_SYMBOL_GPL(fsi_soc_platform); /************************************************************************ @@ -1132,11 +1130,7 @@ static int fsi_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_resume(&pdev->dev); - - fsi_soc_dai[0].dev = &pdev->dev; - fsi_soc_dai[0].private_data = &master->fsia; - fsi_soc_dai[1].dev = &pdev->dev; - fsi_soc_dai[1].private_data = &master->fsib; + dev_set_drvdata(&pdev->dev, master); fsi_soft_all_reset(master); @@ -1147,13 +1141,13 @@ static int fsi_probe(struct platform_device *pdev) goto exit_iounmap; } - ret = snd_soc_register_platform(&fsi_soc_platform); + ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform); if (ret < 0) { dev_err(&pdev->dev, "cannot snd soc register\n"); goto exit_free_irq; } - return snd_soc_register_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); + return snd_soc_register_dais(&pdev->dev, fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); exit_free_irq: free_irq(irq, master); @@ -1171,10 +1165,10 @@ static int fsi_remove(struct platform_device *pdev) { struct fsi_master *master; - master = fsi_get_master(fsi_soc_dai[0].private_data); + master = dev_get_drvdata(&pdev->dev); - snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); - snd_soc_unregister_platform(&fsi_soc_platform); + snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai)); + snd_soc_unregister_platform(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -1183,11 +1177,6 @@ static int fsi_remove(struct platform_device *pdev) iounmap(master->base); kfree(master); - fsi_soc_dai[0].dev = NULL; - fsi_soc_dai[0].private_data = NULL; - fsi_soc_dai[1].dev = NULL; - fsi_soc_dai[1].private_data = NULL; - return 0; } @@ -1233,7 +1222,7 @@ static struct platform_device_id fsi_id_table[] = { static struct platform_driver fsi_driver = { .driver = { - .name = "sh_fsi", + .name = "fsi-pcm-audio", .pm = &fsi_pm_ops, }, .probe = fsi_probe, diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index 41db75af3c69..c87e3ff28a0a 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c @@ -239,8 +239,7 @@ static int hac_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id]; + struct hac_priv *hac = &hac_cpu_data[dai->id]; int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; switch (params->msbits) { @@ -271,10 +270,9 @@ static struct snd_soc_dai_ops hac_dai_ops = { .hw_params = hac_hw_params, }; -struct snd_soc_dai sh4_hac_dai[] = { +static struct snd_soc_dai_driver sh4_hac_dai[] = { { - .name = "HAC0", - .id = 0, + .name = "hac-dai.0", .ac97_control = 1, .playback = { .rates = AC97_RATES, @@ -292,8 +290,7 @@ struct snd_soc_dai sh4_hac_dai[] = { }, #ifdef CONFIG_CPU_SUBTYPE_SH7760 { - .name = "HAC1", - .ac97_control = 1, + .name = "hac-dai.1", .id = 1, .playback = { .rates = AC97_RATES, @@ -312,19 +309,40 @@ struct snd_soc_dai sh4_hac_dai[] = { }, #endif }; -EXPORT_SYMBOL_GPL(sh4_hac_dai); -static int __init sh4_hac_init(void) +static int __devinit hac_soc_platform_probe(struct platform_device *pdev) +{ + return snd_soc_register_dais(&pdev->dev, sh4_hac_dai, + ARRAY_SIZE(sh4_hac_dai)); +} + +static int __devexit hac_soc_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_hac_dai)); + return 0; +} + +static struct platform_driver hac_pcm_driver = { + .driver = { + .name = "hac-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = hac_soc_platform_probe, + .remove = __devexit_p(hac_soc_platform_remove), +}; + +static int __init sh4_hac_pcm_init(void) { - return snd_soc_register_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); + return platform_driver_register(&hac_pcm_driver); } -module_init(sh4_hac_init); +module_init(sh4_hac_pcm_init); -static void __exit sh4_hac_exit(void) +static void __exit sh4_hac_pcm_exit(void) { - snd_soc_unregister_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); + platform_driver_unregister(&hac_pcm_driver); } -module_exit(sh4_hac_exit); +module_exit(sh4_hac_pcm_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver"); diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index b823a5c9b9bc..866d78fb8398 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c @@ -50,7 +50,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret; unsigned int rate = params_rate(params); @@ -68,7 +68,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - ret = snd_soc_dai_set_fmt(rtd->dai->cpu_dai, SND_SOC_DAIFMT_NB_IF | + ret = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; @@ -81,7 +81,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream, clk_set_rate(&siumckb_clk, codec_freq); dev_dbg(codec_dai->dev, "%s: configure %luHz\n", __func__, codec_freq); - ret = snd_soc_dai_set_sysclk(rtd->dai->cpu_dai, SIU_CLKB_EXT, + ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, SIU_CLKB_EXT, codec_freq / 2, SND_SOC_CLOCK_IN); if (!ret) @@ -93,7 +93,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream, static int migor_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; if (use_count) { use_count--; @@ -136,8 +136,10 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Mic Bias", NULL, "External Microphone" }, }; -static int migor_dai_init(struct snd_soc_codec *codec) +static int migor_dai_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + snd_soc_dapm_new_controls(codec, migor_dapm_widgets, ARRAY_SIZE(migor_dapm_widgets)); @@ -150,8 +152,10 @@ static int migor_dai_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link migor_dai = { .name = "wm8978", .stream_name = "WM8978", - .cpu_dai = &siu_i2s_dai, - .codec_dai = &wm8978_dai, + .cpu_dai_name = "siu-i2s-dai", + .codec_dai_name = "wm8978-hifi", + .platform_name = "siu-pcm-audio", + .codec_name = "wm8978-codec.0-001a", .ops = &migor_dai_ops, .init = migor_dai_init, }; @@ -159,17 +163,10 @@ static struct snd_soc_dai_link migor_dai = { /* migor audio machine driver */ static struct snd_soc_card snd_soc_migor = { .name = "Migo-R", - .platform = &siu_platform, .dai_link = &migor_dai, .num_links = 1, }; -/* migor audio subsystem */ -static struct snd_soc_device migor_snd_devdata = { - .card = &snd_soc_migor, - .codec_dev = &soc_codec_dev_wm8978, -}; - static struct platform_device *migor_snd_device; static int __init migor_init(void) @@ -187,9 +184,7 @@ static int __init migor_init(void) goto epdevalloc; } - platform_set_drvdata(migor_snd_device, &migor_snd_devdata); - - migor_snd_devdata.dev = &migor_snd_device->dev; + platform_set_drvdata(migor_snd_device, &snd_soc_migor); ret = platform_device_add(migor_snd_device); if (ret) diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c index ce7f95b59de3..b897f7b96d89 100644 --- a/sound/soc/sh/sh7760-ac97.c +++ b/sound/soc/sh/sh7760-ac97.c @@ -15,41 +15,35 @@ #include #include -#include "../codecs/ac97.h" - #define IPSEL 0xFE400034 /* platform specific structs can be declared here */ -extern struct snd_soc_dai sh4_hac_dai[2]; -extern struct snd_soc_platform sh7760_soc_platform; +extern struct snd_soc_dai_driver sh4_hac_dai[2]; +extern struct snd_soc_platform_driver sh7760_soc_platform; -static int machine_init(struct snd_soc_codec *codec) +static int machine_init(struct snd_soc_pcm_runtime *rtd) { - snd_soc_dapm_sync(codec); + snd_soc_dapm_sync(rtd->codec); return 0; } static struct snd_soc_dai_link sh7760_ac97_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &sh4_hac_dai[0], /* HAC0 */ - .codec_dai = &ac97_dai, + .cpu_dai_name = "hac-dai.0", /* HAC0 */ + .codec_dai_name = "ac97-hifi", + .platform_name = "sh7760-pcm-audio", + .codec_name = "ac97-codec", .init = machine_init, .ops = NULL, }; static struct snd_soc_card sh7760_ac97_soc_machine = { .name = "SH7760 AC97", - .platform = &sh7760_soc_platform, .dai_link = &sh7760_ac97_dai, .num_links = 1, }; -static struct snd_soc_device sh7760_ac97_snd_devdata = { - .card = &sh7760_ac97_soc_machine, - .codec_dev = &soc_codec_dev_ac97, -}; - static struct platform_device *sh7760_ac97_snd_device; static int __init sh7760_ac97_init(void) @@ -67,8 +61,7 @@ static int __init sh7760_ac97_init(void) goto out; platform_set_drvdata(sh7760_ac97_snd_device, - &sh7760_ac97_snd_devdata); - sh7760_ac97_snd_devdata.dev = &sh7760_ac97_snd_device->dev; + &sh7760_ac97_soc_machine); ret = platform_device_add(sh7760_ac97_snd_device); if (ret) diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h index 492b1cae24cc..aa239ff7310d 100644 --- a/sound/soc/sh/siu.h +++ b/sound/soc/sh/siu.h @@ -181,8 +181,9 @@ static inline u32 siu_read32(u32 __iomem *addr) #define SIU_BRGBSEL (0x108 / sizeof(u32)) #define SIU_BRRB (0x10c / sizeof(u32)) -extern struct snd_soc_platform siu_platform; -extern struct snd_soc_dai siu_i2s_dai; +extern struct snd_soc_platform_driver siu_platform; +extern struct snd_soc_dai_driver siu_i2s_dai; +extern struct siu_info *siu_i2s_data; int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card); void siu_free_port(struct siu_port *port_info); diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c index eeed5edd722b..827940a8e248 100644 --- a/sound/soc/sh/siu_dai.c +++ b/sound/soc/sh/siu_dai.c @@ -71,6 +71,9 @@ struct port_flag { struct format_flag capture; }; +struct siu_info *siu_i2s_data = NULL; +EXPORT_SYMBOL_GPL(siu_i2s_data); + static struct port_flag siu_flags[SIU_PORT_NUM] = { [SIU_PORT_A] = { .playback = { @@ -104,13 +107,13 @@ static struct port_flag siu_flags[SIU_PORT_NUM] = { static void siu_dai_start(struct siu_port *port_info) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; dev_dbg(port_info->pcm->card->dev, "%s\n", __func__); /* Turn on SIU clock */ - pm_runtime_get_sync(siu_i2s_dai.dev); + pm_runtime_get_sync(port_info->pcm->card->dev); /* Issue software reset to siu */ siu_write32(base + SIU_SRCTL, 0); @@ -148,21 +151,21 @@ static void siu_dai_start(struct siu_port *port_info) siu_write32(base + SIU_SBDVCB, port_info->capture.volume); } -static void siu_dai_stop(void) +static void siu_dai_stop(struct siu_port *port_info) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; /* SIU software reset */ siu_write32(base + SIU_SRCTL, 0); /* Turn off SIU clock */ - pm_runtime_put_sync(siu_i2s_dai.dev); + pm_runtime_put_sync(port_info->pcm->card->dev); } static void siu_dai_spbAselect(struct siu_port *port_info) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; struct siu_firmware *fw = &info->fw; u32 *ydef = fw->yram0; u32 idx; @@ -187,7 +190,7 @@ static void siu_dai_spbAselect(struct siu_port *port_info) static void siu_dai_spbBselect(struct siu_port *port_info) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; struct siu_firmware *fw = &info->fw; u32 *ydef = fw->yram0; u32 idx; @@ -207,7 +210,7 @@ static void siu_dai_spbBselect(struct siu_port *port_info) static void siu_dai_open(struct siu_stream *siu_stream) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; u32 srctl, ifctl; @@ -238,7 +241,7 @@ static void siu_dai_open(struct siu_stream *siu_stream) */ static void siu_dai_pcmdatapack(struct siu_stream *siu_stream) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; u32 dpak; @@ -258,7 +261,7 @@ static void siu_dai_pcmdatapack(struct siu_stream *siu_stream) static int siu_dai_spbstart(struct siu_port *port_info) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; struct siu_firmware *fw = &info->fw; u32 *ydef = fw->yram0; @@ -323,7 +326,7 @@ static int siu_dai_spbstart(struct siu_port *port_info) static void siu_dai_spbstop(struct siu_port *port_info) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; siu_write32(base + SIU_SBACTIV, 0); @@ -402,7 +405,7 @@ static int siu_dai_put_volume(struct snd_kcontrol *kctrl, { struct siu_port *port_info = snd_kcontrol_chip(kctrl); struct device *dev = port_info->pcm->card->dev; - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; u32 new_vol; u32 cur_vol; @@ -510,7 +513,7 @@ void siu_free_port(struct siu_port *port_info) static int siu_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = snd_soc_dai_get_drvdata(dai); struct snd_pcm_runtime *rt = substream->runtime; struct siu_port *port_info = siu_port_info(substream); int ret; @@ -532,7 +535,7 @@ static int siu_dai_startup(struct snd_pcm_substream *substream, static void siu_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = snd_soc_dai_get_drvdata(dai); struct siu_port *port_info = siu_port_info(substream); dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__, @@ -548,7 +551,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream, /* during stmread or stmwrite ? */ BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg); siu_dai_spbstop(port_info); - siu_dai_stop(); + siu_dai_stop(port_info); } } @@ -556,7 +559,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream, static int siu_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = snd_soc_dai_get_drvdata(dai); struct snd_pcm_runtime *rt = substream->runtime; struct siu_port *port_info = siu_port_info(substream); struct siu_stream *siu_stream; @@ -605,7 +608,7 @@ fail: static int siu_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = snd_soc_dai_get_drvdata(dai); u32 __iomem *base = info->reg; u32 ifctl; @@ -671,11 +674,11 @@ static int siu_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, return -EINVAL; } - siu_clk = clk_get(siu_i2s_dai.dev, siu_name); + siu_clk = clk_get(dai->dev, siu_name); if (IS_ERR(siu_clk)) return PTR_ERR(siu_clk); - parent_clk = clk_get(siu_i2s_dai.dev, parent_name); + parent_clk = clk_get(dai->dev, parent_name); if (!IS_ERR(parent_clk)) { ret = clk_set_parent(siu_clk, parent_clk); if (!ret) @@ -696,9 +699,8 @@ static struct snd_soc_dai_ops siu_dai_ops = { .set_fmt = siu_dai_set_fmt, }; -struct snd_soc_dai siu_i2s_dai = { - .name = "sh-siu", - .id = 0, +static struct snd_soc_dai_driver siu_i2s_dai = { + .name = "sui-i2s-dai", .playback = { .channels_min = 2, .channels_max = 2, @@ -713,7 +715,6 @@ struct snd_soc_dai siu_i2s_dai = { }, .ops = &siu_dai_ops, }; -EXPORT_SYMBOL_GPL(siu_i2s_dai); static int __devinit siu_probe(struct platform_device *pdev) { @@ -725,6 +726,7 @@ static int __devinit siu_probe(struct platform_device *pdev) info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; + siu_i2s_data = info; ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev); if (ret) @@ -767,14 +769,14 @@ static int __devinit siu_probe(struct platform_device *pdev) if (!info->reg) goto emapreg; - siu_i2s_dai.dev = &pdev->dev; - siu_i2s_dai.private_data = info; + dev_set_drvdata(&pdev->dev, info); - ret = snd_soc_register_dais(&siu_i2s_dai, 1); + /* register using ARRAY version so we can keep dai name */ + ret = snd_soc_register_dais(&pdev->dev, &siu_i2s_dai, 1); if (ret < 0) goto edaiinit; - ret = snd_soc_register_platform(&siu_platform); + ret = snd_soc_register_platform(&pdev->dev, &siu_platform); if (ret < 0) goto esocregp; @@ -783,7 +785,7 @@ static int __devinit siu_probe(struct platform_device *pdev) return ret; esocregp: - snd_soc_unregister_dais(&siu_i2s_dai, 1); + snd_soc_unregister_dai(&pdev->dev); edaiinit: iounmap(info->reg); emapreg: @@ -804,13 +806,13 @@ ereqfw: static int __devexit siu_remove(struct platform_device *pdev) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = dev_get_drvdata(&pdev->dev); struct resource *res; pm_runtime_disable(&pdev->dev); - snd_soc_unregister_platform(&siu_platform); - snd_soc_unregister_dais(&siu_i2s_dai, 1); + snd_soc_unregister_platform(&pdev->dev); + snd_soc_unregister_dai(&pdev->dev); iounmap(info->reg); iounmap(info->yram); @@ -826,7 +828,7 @@ static int __devexit siu_remove(struct platform_device *pdev) static struct platform_driver siu_driver = { .driver = { - .name = "sh_siu", + .name = "siu-pcm-audio", }, .probe = siu_probe, .remove = __devexit_p(siu_remove), diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 36170be15aa7..440476993325 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -48,7 +48,7 @@ struct siu_port *siu_ports[SIU_PORT_NUM]; /* transfersize is number of u32 dma transfers per period */ static int siu_pcm_stmwrite_stop(struct siu_port *port_info) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; struct siu_stream *siu_stream = &port_info->playback; u32 stfifo; @@ -114,7 +114,7 @@ static void siu_dma_tx_complete(void *arg) static int siu_pcm_wr_set(struct siu_port *port_info, dma_addr_t buff, u32 size) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; struct siu_stream *siu_stream = &port_info->playback; struct snd_pcm_substream *substream = siu_stream->substream; @@ -161,7 +161,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info, static int siu_pcm_rd_set(struct siu_port *port_info, dma_addr_t buff, size_t size) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; struct siu_stream *siu_stream = &port_info->capture; struct snd_pcm_substream *substream = siu_stream->substream; @@ -270,7 +270,7 @@ static int siu_pcm_stmread_start(struct siu_port *port_info) static int siu_pcm_stmread_stop(struct siu_port *port_info) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; struct siu_stream *siu_stream = &port_info->capture; struct device *dev = siu_stream->substream->pcm->card->dev; @@ -294,7 +294,7 @@ static int siu_pcm_stmread_stop(struct siu_port *port_info) static int siu_pcm_hw_params(struct snd_pcm_substream *ss, struct snd_pcm_hw_params *hw_params) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; struct device *dev = ss->pcm->card->dev; int ret; @@ -309,7 +309,7 @@ static int siu_pcm_hw_params(struct snd_pcm_substream *ss, static int siu_pcm_hw_free(struct snd_pcm_substream *ss) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; struct siu_port *port_info = siu_port_info(ss); struct device *dev = ss->pcm->card->dev; struct siu_stream *siu_stream; @@ -340,11 +340,12 @@ static bool filter(struct dma_chan *chan, void *slave) static int siu_pcm_open(struct snd_pcm_substream *ss) { /* Playback / Capture */ - struct siu_info *info = siu_i2s_dai.private_data; + struct snd_soc_pcm_runtime *rtd = ss->private_data; + struct siu_platform *pdata = snd_soc_platform_get_drvdata(rtd->platform); + struct siu_info *info = siu_i2s_data; struct siu_port *port_info = siu_port_info(ss); struct siu_stream *siu_stream; u32 port = info->port_id; - struct siu_platform *pdata = siu_i2s_dai.dev->platform_data; struct device *dev = ss->pcm->card->dev; dma_cap_mask_t mask; struct sh_dmae_slave *param; @@ -381,7 +382,7 @@ static int siu_pcm_open(struct snd_pcm_substream *ss) static int siu_pcm_close(struct snd_pcm_substream *ss) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; struct device *dev = ss->pcm->card->dev; struct siu_port *port_info = siu_port_info(ss); struct siu_stream *siu_stream; @@ -403,7 +404,7 @@ static int siu_pcm_close(struct snd_pcm_substream *ss) static int siu_pcm_prepare(struct snd_pcm_substream *ss) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; struct siu_port *port_info = siu_port_info(ss); struct device *dev = ss->pcm->card->dev; struct snd_pcm_runtime *rt = ss->runtime; @@ -449,7 +450,7 @@ static int siu_pcm_prepare(struct snd_pcm_substream *ss) static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd) { - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; struct device *dev = ss->pcm->card->dev; struct siu_port *port_info = siu_port_info(ss); int ret; @@ -492,7 +493,7 @@ static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd) static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss) { struct device *dev = ss->pcm->card->dev; - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; u32 __iomem *base = info->reg; struct siu_port *port_info = siu_port_info(ss); struct snd_pcm_runtime *rt = ss->runtime; @@ -528,7 +529,7 @@ static int siu_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { /* card->dev == socdev->dev, see snd_soc_new_pcms() */ - struct siu_info *info = siu_i2s_dai.private_data; + struct siu_info *info = siu_i2s_data; struct platform_device *pdev = to_platform_device(card->dev); int ret; int i; @@ -605,9 +606,8 @@ static struct snd_pcm_ops siu_pcm_ops = { .pointer = siu_pcm_pointer_dma, }; -struct snd_soc_platform siu_platform = { - .name = "siu-audio", - .pcm_ops = &siu_pcm_ops, +struct snd_soc_platform_driver siu_platform = { + .ops = &siu_pcm_ops, .pcm_new = siu_pcm_new, .pcm_free = siu_pcm_free, }; diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c index b378096cadb1..40bbdf1591dc 100644 --- a/sound/soc/sh/ssi.c +++ b/sound/soc/sh/ssi.c @@ -92,8 +92,7 @@ struct ssi_priv { static int ssi_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; + struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; if (ssi->inuse) { pr_debug("ssi: already in use!\n"); return -EBUSY; @@ -105,8 +104,7 @@ static int ssi_startup(struct snd_pcm_substream *substream, static void ssi_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; + struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; ssi->inuse = 0; } @@ -114,8 +112,7 @@ static void ssi_shutdown(struct snd_pcm_substream *substream, static int ssi_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; + struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -135,8 +132,7 @@ static int ssi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; + struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; unsigned long ssicr = SSIREG(SSICR); unsigned int bits, channels, swl, recv, i; @@ -346,10 +342,9 @@ static struct snd_soc_dai_ops ssi_dai_ops = { .set_fmt = ssi_set_fmt, }; -struct snd_soc_dai sh4_ssi_dai[] = { +struct snd_soc_dai_driver sh4_ssi_dai[] = { { - .name = "SSI0", - .id = 0, + .name = "ssi-dai.0", .playback = { .rates = SSI_RATES, .formats = SSI_FMTS, @@ -366,8 +361,7 @@ struct snd_soc_dai sh4_ssi_dai[] = { }, #ifdef CONFIG_CPU_SUBTYPE_SH7760 { - .name = "SSI1", - .id = 1, + .name = "ssi-dai.1", .playback = { .rates = SSI_RATES, .formats = SSI_FMTS, @@ -384,19 +378,40 @@ struct snd_soc_dai sh4_ssi_dai[] = { }, #endif }; -EXPORT_SYMBOL_GPL(sh4_ssi_dai); -static int __init sh4_ssi_init(void) +static int __devinit sh4_soc_dai_probe(struct platform_device *pdev) +{ + return snd_soc_register_dais(&pdev->dev, sh4_ssi_dai, + ARRAY_SIZE(sh4_ssi_dai)); +} + +static int __devexit sh4_soc_dai_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai)); + return 0; +} + +static struct platform_driver sh4_ssi_driver = { + .driver = { + .name = "sh4-ssi-dai", + .owner = THIS_MODULE, + }, + + .probe = sh4_soc_dai_probe, + .remove = __devexit_p(sh4_soc_dai_remove), +}; + +static int __init snd_sh4_ssi_init(void) { - return snd_soc_register_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); + return platform_driver_register(&sh4_ssi_driver); } -module_init(sh4_ssi_init); +module_init(snd_sh4_ssi_init); -static void __exit sh4_ssi_exit(void) +static void __exit snd_sh4_ssi_exit(void) { - snd_soc_unregister_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); + platform_driver_unregister(&sh4_ssi_driver); } -module_exit(sh4_ssi_exit); +module_exit(snd_sh4_ssi_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver"); diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 472af38188c1..83cd8ed944bf 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -19,7 +19,7 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -1; return cache[reg]; } @@ -31,12 +31,12 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, u8 data[2]; int ret; - BUG_ON(codec->volatile_register); + BUG_ON(codec->driver->volatile_register); data[0] = (reg << 4) | ((value >> 8) & 0x000f); data[1] = value & 0x00ff; - if (reg < codec->reg_cache_size) + if (reg < codec->driver->reg_cache_size) cache[reg] = value; if (codec->cache_only) { @@ -89,7 +89,7 @@ static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -1; return cache[reg]; } @@ -101,12 +101,12 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, u8 data[2]; int ret; - BUG_ON(codec->volatile_register); + BUG_ON(codec->driver->volatile_register); data[0] = (reg << 1) | ((value >> 8) & 0x0001); data[1] = value & 0x00ff; - if (reg < codec->reg_cache_size) + if (reg < codec->driver->reg_cache_size) cache[reg] = value; if (codec->cache_only) { @@ -161,13 +161,13 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, u8 *cache = codec->reg_cache; u8 data[2]; - BUG_ON(codec->volatile_register); + BUG_ON(codec->driver->volatile_register); reg &= 0xff; data[0] = reg; data[1] = value & 0xff; - if (reg < codec->reg_cache_size) + if (reg < codec->driver->reg_cache_size) cache[reg] = value; if (codec->cache_only) { @@ -188,7 +188,7 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec, { u8 *cache = codec->reg_cache; reg &= 0xff; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -1; return cache[reg]; } @@ -224,7 +224,7 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, { u16 *cache = codec->reg_cache; - if (reg >= codec->reg_cache_size || + if (reg >= codec->driver->reg_cache_size || snd_soc_codec_volatile_register(codec, reg)) { if (codec->cache_only) return -EINVAL; @@ -343,7 +343,7 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, u16 *cache = codec->reg_cache; reg &= 0xff; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -1; return cache[reg]; } @@ -355,14 +355,14 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, u8 data[3]; int ret; - BUG_ON(codec->volatile_register); + BUG_ON(codec->driver->volatile_register); data[0] = (reg >> 8) & 0xff; data[1] = reg & 0xff; data[2] = value; reg &= 0xff; - if (reg < codec->reg_cache_size) + if (reg < codec->driver->reg_cache_size) cache[reg] = value; if (codec->cache_only) { @@ -451,7 +451,7 @@ static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec, { u16 *cache = codec->reg_cache; - if (reg >= codec->reg_cache_size || + if (reg >= codec->driver->reg_cache_size || snd_soc_codec_volatile_register(codec, reg)) { if (codec->cache_only) return -EINVAL; @@ -474,7 +474,7 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, data[2] = (value >> 8) & 0xff; data[3] = value & 0xff; - if (reg < codec->reg_cache_size) + if (reg < codec->driver->reg_cache_size) cache[reg] = value; if (codec->cache_only) { @@ -571,8 +571,8 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, return -EINVAL; } - codec->write = io_types[i].write; - codec->read = io_types[i].read; + codec->driver->write = io_types[i].write; + codec->driver->read = io_types[i].read; switch (control) { case SND_SOC_CUSTOM: diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 5299932db0b6..a004876a39a9 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3,6 +3,8 @@ * * Copyright 2005 Wolfson Microelectronics PLC. * Copyright 2005 Openedhand Ltd. + * Copyright (C) 2010 Slimlogic Ltd. + * Copyright (C) 2010 Texas Instruments Inc. * * Author: Liam Girdwood * with code, comments and ideas from :- @@ -37,6 +39,8 @@ #include #include +#define NAME_SIZE 32 + static DEFINE_MUTEX(pcm_mutex); static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); @@ -52,6 +56,7 @@ static LIST_HEAD(codec_list); static int snd_soc_register_card(struct snd_soc_card *card); static int snd_soc_unregister_card(struct snd_soc_card *card); +static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); /* * This is a timeout to do a DAPM powerdown after a stream is closed(). @@ -86,30 +91,30 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) { int ret, i, step = 1, count = 0; - if (!codec->reg_cache_size) + if (!codec->driver->reg_cache_size) return 0; - if (codec->reg_cache_step) - step = codec->reg_cache_step; + if (codec->driver->reg_cache_step) + step = codec->driver->reg_cache_step; count += sprintf(buf, "%s registers\n", codec->name); - for (i = 0; i < codec->reg_cache_size; i += step) { - if (codec->readable_register && !codec->readable_register(i)) + for (i = 0; i < codec->driver->reg_cache_size; i += step) { + if (codec->driver->readable_register && !codec->driver->readable_register(i)) continue; count += sprintf(buf + count, "%2x: ", i); if (count >= PAGE_SIZE - 1) break; - if (codec->display_register) { - count += codec->display_register(codec, buf + count, + if (codec->driver->display_register) { + count += codec->driver->display_register(codec, buf + count, PAGE_SIZE - count, i); } else { /* If the read fails it's almost certainly due to * the register being volatile and the device being * powered off. */ - ret = codec->read(codec, i); + ret = codec->driver->read(codec, i); if (ret >= 0) count += snprintf(buf + count, PAGE_SIZE - count, @@ -137,8 +142,10 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) static ssize_t codec_reg_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct snd_soc_device *devdata = dev_get_drvdata(dev); - return soc_codec_reg_show(devdata->card->codec, buf); + struct snd_soc_pcm_runtime *rtd = + container_of(dev, struct snd_soc_pcm_runtime, dev); + + return soc_codec_reg_show(rtd->codec, buf); } static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); @@ -146,20 +153,20 @@ static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); static ssize_t pmdown_time_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct snd_soc_device *socdev = dev_get_drvdata(dev); - struct snd_soc_card *card = socdev->card; + struct snd_soc_pcm_runtime *rtd = + container_of(dev, struct snd_soc_pcm_runtime, dev); - return sprintf(buf, "%ld\n", card->pmdown_time); + return sprintf(buf, "%ld\n", rtd->pmdown_time); } static ssize_t pmdown_time_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct snd_soc_device *socdev = dev_get_drvdata(dev); - struct snd_soc_card *card = socdev->card; + struct snd_soc_pcm_runtime *rtd = + container_of(dev, struct snd_soc_pcm_runtime, dev); - strict_strtol(buf, 10, &card->pmdown_time); + strict_strtol(buf, 10, &rtd->pmdown_time); return count; } @@ -203,19 +210,19 @@ static ssize_t codec_reg_write_file(struct file *file, return -EFAULT; buf[buf_size] = 0; - if (codec->reg_cache_step) - step = codec->reg_cache_step; + if (codec->driver->reg_cache_step) + step = codec->driver->reg_cache_step; while (*start == ' ') start++; reg = simple_strtoul(start, &start, 16); - if ((reg >= codec->reg_cache_size) || (reg % step)) + if ((reg >= codec->driver->reg_cache_size) || (reg % step)) return -EINVAL; while (*start == ' ') start++; if (strict_strtoul(start, 16, &value)) return -EINVAL; - codec->write(codec, reg, value); + codec->driver->write(codec, reg, value); return buf_size; } @@ -305,7 +312,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) codec->ac97->dev.release = soc_ac97_device_release; dev_set_name(&codec->ac97->dev, "%d-%d:%s", - codec->card->number, 0, codec->name); + codec->card->snd_card->number, 0, codec->name); err = device_register(&codec->ac97->dev); if (err < 0) { snd_printk(KERN_ERR "Can't register ac97 bus\n"); @@ -319,24 +326,21 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_card *card = socdev->card; - struct snd_soc_dai_link *machine = rtd->dai; - struct snd_soc_dai *cpu_dai = machine->cpu_dai; - struct snd_soc_dai *codec_dai = machine->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret; - if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates || - machine->symmetric_rates) { - dev_dbg(card->dev, "Symmetry forces %dHz rate\n", - machine->rate); + if (codec_dai->driver->symmetric_rates || cpu_dai->driver->symmetric_rates || + rtd->dai_link->symmetric_rates) { + dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", + rtd->rate); ret = snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_RATE, - machine->rate, - machine->rate); + rtd->rate, + rtd->rate); if (ret < 0) { - dev_err(card->dev, + dev_err(&rtd->dev, "Unable to apply rate symmetry constraint: %d\n", ret); return ret; } @@ -353,20 +357,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) static int soc_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_card *card = socdev->card; struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_dai_link *machine = rtd->dai; - struct snd_soc_platform *platform = card->platform; - struct snd_soc_dai *cpu_dai = machine->cpu_dai; - struct snd_soc_dai *codec_dai = machine->codec_dai; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; + struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; int ret = 0; mutex_lock(&pcm_mutex); /* startup the audio subsystem */ - if (cpu_dai->ops->startup) { - ret = cpu_dai->ops->startup(substream, cpu_dai); + if (cpu_dai->driver->ops->startup) { + ret = cpu_dai->driver->ops->startup(substream, cpu_dai); if (ret < 0) { printk(KERN_ERR "asoc: can't open interface %s\n", cpu_dai->name); @@ -374,16 +377,16 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) } } - if (platform->pcm_ops->open) { - ret = platform->pcm_ops->open(substream); + if (platform->driver->ops->open) { + ret = platform->driver->ops->open(substream); if (ret < 0) { printk(KERN_ERR "asoc: can't open platform %s\n", platform->name); goto platform_err; } } - if (codec_dai->ops->startup) { - ret = codec_dai->ops->startup(substream, codec_dai); + if (codec_dai->driver->ops->startup) { + ret = codec_dai->driver->ops->startup(substream, codec_dai); if (ret < 0) { printk(KERN_ERR "asoc: can't open codec %s\n", codec_dai->name); @@ -391,10 +394,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) } } - if (machine->ops && machine->ops->startup) { - ret = machine->ops->startup(substream); + if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { + ret = rtd->dai_link->ops->startup(substream); if (ret < 0) { - printk(KERN_ERR "asoc: %s startup failed\n", machine->name); + printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name); goto machine_err; } } @@ -402,50 +405,50 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) /* Check that the codec and cpu DAI's are compatible */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { runtime->hw.rate_min = - max(codec_dai->playback.rate_min, - cpu_dai->playback.rate_min); + max(codec_dai_drv->playback.rate_min, + cpu_dai_drv->playback.rate_min); runtime->hw.rate_max = - min(codec_dai->playback.rate_max, - cpu_dai->playback.rate_max); + min(codec_dai_drv->playback.rate_max, + cpu_dai_drv->playback.rate_max); runtime->hw.channels_min = - max(codec_dai->playback.channels_min, - cpu_dai->playback.channels_min); + max(codec_dai_drv->playback.channels_min, + cpu_dai_drv->playback.channels_min); runtime->hw.channels_max = - min(codec_dai->playback.channels_max, - cpu_dai->playback.channels_max); + min(codec_dai_drv->playback.channels_max, + cpu_dai_drv->playback.channels_max); runtime->hw.formats = - codec_dai->playback.formats & cpu_dai->playback.formats; + codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats; runtime->hw.rates = - codec_dai->playback.rates & cpu_dai->playback.rates; - if (codec_dai->playback.rates + codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates; + if (codec_dai_drv->playback.rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) - runtime->hw.rates |= cpu_dai->playback.rates; - if (cpu_dai->playback.rates + runtime->hw.rates |= cpu_dai_drv->playback.rates; + if (cpu_dai_drv->playback.rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) - runtime->hw.rates |= codec_dai->playback.rates; + runtime->hw.rates |= codec_dai_drv->playback.rates; } else { runtime->hw.rate_min = - max(codec_dai->capture.rate_min, - cpu_dai->capture.rate_min); + max(codec_dai_drv->capture.rate_min, + cpu_dai_drv->capture.rate_min); runtime->hw.rate_max = - min(codec_dai->capture.rate_max, - cpu_dai->capture.rate_max); + min(codec_dai_drv->capture.rate_max, + cpu_dai_drv->capture.rate_max); runtime->hw.channels_min = - max(codec_dai->capture.channels_min, - cpu_dai->capture.channels_min); + max(codec_dai_drv->capture.channels_min, + cpu_dai_drv->capture.channels_min); runtime->hw.channels_max = - min(codec_dai->capture.channels_max, - cpu_dai->capture.channels_max); + min(codec_dai_drv->capture.channels_max, + cpu_dai_drv->capture.channels_max); runtime->hw.formats = - codec_dai->capture.formats & cpu_dai->capture.formats; + codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats; runtime->hw.rates = - codec_dai->capture.rates & cpu_dai->capture.rates; - if (codec_dai->capture.rates + codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates; + if (codec_dai_drv->capture.rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) - runtime->hw.rates |= cpu_dai->capture.rates; - if (cpu_dai->capture.rates + runtime->hw.rates |= cpu_dai_drv->capture.rates; + if (cpu_dai_drv->capture.rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) - runtime->hw.rates |= codec_dai->capture.rates; + runtime->hw.rates |= codec_dai_drv->capture.rates; } snd_pcm_limit_hw_rates(runtime); @@ -461,7 +464,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) } if (!runtime->hw.channels_min || !runtime->hw.channels_max) { printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", - codec_dai->name, cpu_dai->name); + codec_dai->name, cpu_dai->name); goto config_err; } @@ -472,7 +475,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) goto config_err; } - pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); + pr_debug("asoc: %s <-> %s info:\n", + codec_dai->name, cpu_dai->name); pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, runtime->hw.channels_max); @@ -480,33 +484,33 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) runtime->hw.rate_max); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - cpu_dai->playback.active++; - codec_dai->playback.active++; + cpu_dai->playback_active++; + codec_dai->playback_active++; } else { - cpu_dai->capture.active++; - codec_dai->capture.active++; + cpu_dai->capture_active++; + codec_dai->capture_active++; } cpu_dai->active++; codec_dai->active++; - card->codec->active++; + rtd->codec->active++; mutex_unlock(&pcm_mutex); return 0; config_err: - if (machine->ops && machine->ops->shutdown) - machine->ops->shutdown(substream); + if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) + rtd->dai_link->ops->shutdown(substream); machine_err: - if (codec_dai->ops->shutdown) - codec_dai->ops->shutdown(substream, codec_dai); + if (codec_dai->driver->ops->shutdown) + codec_dai->driver->ops->shutdown(substream, codec_dai); codec_dai_err: - if (platform->pcm_ops->close) - platform->pcm_ops->close(substream); + if (platform->driver->ops->close) + platform->driver->ops->close(substream); platform_err: - if (cpu_dai->ops->shutdown) - cpu_dai->ops->shutdown(substream, cpu_dai); + if (cpu_dai->driver->ops->shutdown) + cpu_dai->driver->ops->shutdown(substream, cpu_dai); out: mutex_unlock(&pcm_mutex); return ret; @@ -519,29 +523,25 @@ out: */ static void close_delayed_work(struct work_struct *work) { - struct snd_soc_card *card = container_of(work, struct snd_soc_card, - delayed_work.work); - struct snd_soc_codec *codec = card->codec; - struct snd_soc_dai *codec_dai; - int i; + struct snd_soc_pcm_runtime *rtd = + container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); + struct snd_soc_dai *codec_dai = rtd->codec_dai; mutex_lock(&pcm_mutex); - for (i = 0; i < codec->num_dai; i++) { - codec_dai = &codec->dai[i]; - - pr_debug("pop wq checking: %s status: %s waiting: %s\n", - codec_dai->playback.stream_name, - codec_dai->playback.active ? "active" : "inactive", - codec_dai->pop_wait ? "yes" : "no"); - - /* are we waiting on this codec DAI stream */ - if (codec_dai->pop_wait == 1) { - codec_dai->pop_wait = 0; - snd_soc_dapm_stream_event(codec, - codec_dai->playback.stream_name, - SND_SOC_DAPM_STREAM_STOP); - } + + pr_debug("pop wq checking: %s status: %s waiting: %s\n", + codec_dai->driver->playback.stream_name, + codec_dai->playback_active ? "active" : "inactive", + codec_dai->pop_wait ? "yes" : "no"); + + /* are we waiting on this codec DAI stream */ + if (codec_dai->pop_wait == 1) { + codec_dai->pop_wait = 0; + snd_soc_dapm_stream_event(rtd, + codec_dai->driver->playback.stream_name, + SND_SOC_DAPM_STREAM_STOP); } + mutex_unlock(&pcm_mutex); } @@ -553,22 +553,19 @@ static void close_delayed_work(struct work_struct *work) static int soc_codec_close(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_card *card = socdev->card; - struct snd_soc_dai_link *machine = rtd->dai; - struct snd_soc_platform *platform = card->platform; - struct snd_soc_dai *cpu_dai = machine->cpu_dai; - struct snd_soc_dai *codec_dai = machine->codec_dai; - struct snd_soc_codec *codec = card->codec; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_codec *codec = rtd->codec; mutex_lock(&pcm_mutex); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - cpu_dai->playback.active--; - codec_dai->playback.active--; + cpu_dai->playback_active--; + codec_dai->playback_active--; } else { - cpu_dai->capture.active--; - codec_dai->capture.active--; + cpu_dai->capture_active--; + codec_dai->capture_active--; } cpu_dai->active--; @@ -581,27 +578,28 @@ static int soc_codec_close(struct snd_pcm_substream *substream) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) snd_soc_dai_digital_mute(codec_dai, 1); - if (cpu_dai->ops->shutdown) - cpu_dai->ops->shutdown(substream, cpu_dai); + if (cpu_dai->driver->ops->shutdown) + cpu_dai->driver->ops->shutdown(substream, cpu_dai); - if (codec_dai->ops->shutdown) - codec_dai->ops->shutdown(substream, codec_dai); + if (codec_dai->driver->ops->shutdown) + codec_dai->driver->ops->shutdown(substream, codec_dai); - if (machine->ops && machine->ops->shutdown) - machine->ops->shutdown(substream); + if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) + rtd->dai_link->ops->shutdown(substream); - if (platform->pcm_ops->close) - platform->pcm_ops->close(substream); + if (platform->driver->ops->close) + platform->driver->ops->close(substream); + cpu_dai->runtime = NULL; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /* start delayed pop wq here for playback streams */ codec_dai->pop_wait = 1; - schedule_delayed_work(&card->delayed_work, - msecs_to_jiffies(card->pmdown_time)); + schedule_delayed_work(&rtd->delayed_work, + msecs_to_jiffies(rtd->pmdown_time)); } else { /* capture streams can be powered down now */ - snd_soc_dapm_stream_event(codec, - codec_dai->capture.stream_name, + snd_soc_dapm_stream_event(rtd, + codec_dai->driver->capture.stream_name, SND_SOC_DAPM_STREAM_STOP); } @@ -617,43 +615,39 @@ static int soc_codec_close(struct snd_pcm_substream *substream) static int soc_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_card *card = socdev->card; - struct snd_soc_dai_link *machine = rtd->dai; - struct snd_soc_platform *platform = card->platform; - struct snd_soc_dai *cpu_dai = machine->cpu_dai; - struct snd_soc_dai *codec_dai = machine->codec_dai; - struct snd_soc_codec *codec = card->codec; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret = 0; mutex_lock(&pcm_mutex); - if (machine->ops && machine->ops->prepare) { - ret = machine->ops->prepare(substream); + if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { + ret = rtd->dai_link->ops->prepare(substream); if (ret < 0) { printk(KERN_ERR "asoc: machine prepare error\n"); goto out; } } - if (platform->pcm_ops->prepare) { - ret = platform->pcm_ops->prepare(substream); + if (platform->driver->ops->prepare) { + ret = platform->driver->ops->prepare(substream); if (ret < 0) { printk(KERN_ERR "asoc: platform prepare error\n"); goto out; } } - if (codec_dai->ops->prepare) { - ret = codec_dai->ops->prepare(substream, codec_dai); + if (codec_dai->driver->ops->prepare) { + ret = codec_dai->driver->ops->prepare(substream, codec_dai); if (ret < 0) { printk(KERN_ERR "asoc: codec DAI prepare error\n"); goto out; } } - if (cpu_dai->ops->prepare) { - ret = cpu_dai->ops->prepare(substream, cpu_dai); + if (cpu_dai->driver->ops->prepare) { + ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); if (ret < 0) { printk(KERN_ERR "asoc: cpu DAI prepare error\n"); goto out; @@ -664,16 +658,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && codec_dai->pop_wait) { codec_dai->pop_wait = 0; - cancel_delayed_work(&card->delayed_work); + cancel_delayed_work(&rtd->delayed_work); } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - snd_soc_dapm_stream_event(codec, - codec_dai->playback.stream_name, + snd_soc_dapm_stream_event(rtd, + codec_dai->driver->playback.stream_name, SND_SOC_DAPM_STREAM_START); else - snd_soc_dapm_stream_event(codec, - codec_dai->capture.stream_name, + snd_soc_dapm_stream_event(rtd, + codec_dai->driver->capture.stream_name, SND_SOC_DAPM_STREAM_START); snd_soc_dai_digital_mute(codec_dai, 0); @@ -692,26 +686,23 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_dai_link *machine = rtd->dai; - struct snd_soc_card *card = socdev->card; - struct snd_soc_platform *platform = card->platform; - struct snd_soc_dai *cpu_dai = machine->cpu_dai; - struct snd_soc_dai *codec_dai = machine->codec_dai; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret = 0; mutex_lock(&pcm_mutex); - if (machine->ops && machine->ops->hw_params) { - ret = machine->ops->hw_params(substream, params); + if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { + ret = rtd->dai_link->ops->hw_params(substream, params); if (ret < 0) { printk(KERN_ERR "asoc: machine hw_params failed\n"); goto out; } } - if (codec_dai->ops->hw_params) { - ret = codec_dai->ops->hw_params(substream, params, codec_dai); + if (codec_dai->driver->ops->hw_params) { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); if (ret < 0) { printk(KERN_ERR "asoc: can't set codec %s hw params\n", codec_dai->name); @@ -719,8 +710,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, } } - if (cpu_dai->ops->hw_params) { - ret = cpu_dai->ops->hw_params(substream, params, cpu_dai); + if (cpu_dai->driver->ops->hw_params) { + ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai); if (ret < 0) { printk(KERN_ERR "asoc: interface %s hw params failed\n", cpu_dai->name); @@ -728,8 +719,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, } } - if (platform->pcm_ops->hw_params) { - ret = platform->pcm_ops->hw_params(substream, params); + if (platform->driver->ops->hw_params) { + ret = platform->driver->ops->hw_params(substream, params); if (ret < 0) { printk(KERN_ERR "asoc: platform %s hw params failed\n", platform->name); @@ -737,23 +728,23 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, } } - machine->rate = params_rate(params); + rtd->rate = params_rate(params); out: mutex_unlock(&pcm_mutex); return ret; platform_err: - if (cpu_dai->ops->hw_free) - cpu_dai->ops->hw_free(substream, cpu_dai); + if (cpu_dai->driver->ops->hw_free) + cpu_dai->driver->ops->hw_free(substream, cpu_dai); interface_err: - if (codec_dai->ops->hw_free) - codec_dai->ops->hw_free(substream, codec_dai); + if (codec_dai->driver->ops->hw_free) + codec_dai->driver->ops->hw_free(substream, codec_dai); codec_err: - if (machine->ops && machine->ops->hw_free) - machine->ops->hw_free(substream); + if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) + rtd->dai_link->ops->hw_free(substream); mutex_unlock(&pcm_mutex); return ret; @@ -765,13 +756,10 @@ codec_err: static int soc_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_dai_link *machine = rtd->dai; - struct snd_soc_card *card = socdev->card; - struct snd_soc_platform *platform = card->platform; - struct snd_soc_dai *cpu_dai = machine->cpu_dai; - struct snd_soc_dai *codec_dai = machine->codec_dai; - struct snd_soc_codec *codec = card->codec; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_codec *codec = rtd->codec; mutex_lock(&pcm_mutex); @@ -780,19 +768,19 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) snd_soc_dai_digital_mute(codec_dai, 1); /* free any machine hw params */ - if (machine->ops && machine->ops->hw_free) - machine->ops->hw_free(substream); + if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) + rtd->dai_link->ops->hw_free(substream); /* free any DMA resources */ - if (platform->pcm_ops->hw_free) - platform->pcm_ops->hw_free(substream); + if (platform->driver->ops->hw_free) + platform->driver->ops->hw_free(substream); /* now free hw params for the DAI's */ - if (codec_dai->ops->hw_free) - codec_dai->ops->hw_free(substream, codec_dai); + if (codec_dai->driver->ops->hw_free) + codec_dai->driver->ops->hw_free(substream, codec_dai); - if (cpu_dai->ops->hw_free) - cpu_dai->ops->hw_free(substream, cpu_dai); + if (cpu_dai->driver->ops->hw_free) + cpu_dai->driver->ops->hw_free(substream, cpu_dai); mutex_unlock(&pcm_mutex); return 0; @@ -801,28 +789,25 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_card *card= socdev->card; - struct snd_soc_dai_link *machine = rtd->dai; - struct snd_soc_platform *platform = card->platform; - struct snd_soc_dai *cpu_dai = machine->cpu_dai; - struct snd_soc_dai *codec_dai = machine->codec_dai; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret; - if (codec_dai->ops->trigger) { - ret = codec_dai->ops->trigger(substream, cmd, codec_dai); + if (codec_dai->driver->ops->trigger) { + ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai); if (ret < 0) return ret; } - if (platform->pcm_ops->trigger) { - ret = platform->pcm_ops->trigger(substream, cmd); + if (platform->driver->ops->trigger) { + ret = platform->driver->ops->trigger(substream, cmd); if (ret < 0) return ret; } - if (cpu_dai->ops->trigger) { - ret = cpu_dai->ops->trigger(substream, cmd, cpu_dai); + if (cpu_dai->driver->ops->trigger) { + ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai); if (ret < 0) return ret; } @@ -837,27 +822,24 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_card *card = socdev->card; - struct snd_soc_platform *platform = card->platform; - struct snd_soc_dai_link *machine = rtd->dai; - struct snd_soc_dai *cpu_dai = machine->cpu_dai; - struct snd_soc_dai *codec_dai = machine->codec_dai; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t offset = 0; snd_pcm_sframes_t delay = 0; - if (platform->pcm_ops->pointer) - offset = platform->pcm_ops->pointer(substream); + if (platform->driver->ops->pointer) + offset = platform->driver->ops->pointer(substream); - if (cpu_dai->ops->delay) - delay += cpu_dai->ops->delay(substream, cpu_dai); + if (cpu_dai->driver->ops->delay) + delay += cpu_dai->driver->ops->delay(substream, cpu_dai); - if (codec_dai->ops->delay) - delay += codec_dai->ops->delay(substream, codec_dai); + if (codec_dai->driver->ops->delay) + delay += codec_dai->driver->ops->delay(substream, codec_dai); - if (platform->delay) - delay += platform->delay(substream, codec_dai); + if (platform->driver->delay) + delay += platform->driver->delay(substream, codec_dai); runtime->delay = delay; @@ -880,104 +862,111 @@ static struct snd_pcm_ops soc_pcm_ops = { static int soc_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_card *card = socdev->card; - struct snd_soc_platform *platform = card->platform; - struct snd_soc_codec_device *codec_dev = socdev->codec_dev; - struct snd_soc_codec *codec = card->codec; + struct snd_soc_card *card = platform_get_drvdata(pdev); int i; /* If the initialization of this soc device failed, there is no codec * associated with it. Just bail out in this case. */ - if (!codec) + if (list_empty(&card->codec_dev_list)) return 0; /* Due to the resume being scheduled into a workqueue we could * suspend before that's finished - wait for it to complete. */ - snd_power_lock(codec->card); - snd_power_wait(codec->card, SNDRV_CTL_POWER_D0); - snd_power_unlock(codec->card); + snd_power_lock(card->snd_card); + snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0); + snd_power_unlock(card->snd_card); /* we're going to block userspace touching us until resume completes */ - snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot); + snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); /* mute any active DAC's */ - for (i = 0; i < card->num_links; i++) { - struct snd_soc_dai *dai = card->dai_link[i].codec_dai; + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai *dai = card->rtd[i].codec_dai; + struct snd_soc_dai_driver *drv = dai->driver; - if (card->dai_link[i].ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend) continue; - if (dai->ops->digital_mute && dai->playback.active) - dai->ops->digital_mute(dai, 1); + if (drv->ops->digital_mute && dai->playback_active) + drv->ops->digital_mute(dai, 1); } /* suspend all pcms */ - for (i = 0; i < card->num_links; i++) { - if (card->dai_link[i].ignore_suspend) + for (i = 0; i < card->num_rtd; i++) { + if (card->rtd[i].dai_link->ignore_suspend) continue; - snd_pcm_suspend_all(card->dai_link[i].pcm); + snd_pcm_suspend_all(card->rtd[i].pcm); } if (card->suspend_pre) card->suspend_pre(pdev, PMSG_SUSPEND); - for (i = 0; i < card->num_links; i++) { - struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; + struct snd_soc_platform *platform = card->rtd[i].platform; - if (card->dai_link[i].ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend) continue; - if (cpu_dai->suspend && !cpu_dai->ac97_control) - cpu_dai->suspend(cpu_dai); - if (platform->suspend) - platform->suspend(&card->dai_link[i]); + if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control) + cpu_dai->driver->suspend(cpu_dai); + if (platform->driver->suspend && !platform->suspended) { + platform->driver->suspend(cpu_dai); + platform->suspended = 1; + } } /* close any waiting streams and save state */ - run_delayed_work(&card->delayed_work); - codec->suspend_bias_level = codec->bias_level; + for (i = 0; i < card->num_rtd; i++) { + run_delayed_work(&card->rtd[i].delayed_work); + card->rtd[i].codec->suspend_bias_level = card->rtd[i].codec->bias_level; + } - for (i = 0; i < codec->num_dai; i++) { - char *stream = codec->dai[i].playback.stream_name; + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver; - if (card->dai_link[i].ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend) continue; - if (stream != NULL) - snd_soc_dapm_stream_event(codec, stream, + if (driver->playback.stream_name != NULL) + snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name, SND_SOC_DAPM_STREAM_SUSPEND); - stream = codec->dai[i].capture.stream_name; - if (stream != NULL) - snd_soc_dapm_stream_event(codec, stream, + + if (driver->capture.stream_name != NULL) + snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name, SND_SOC_DAPM_STREAM_SUSPEND); } - /* If there are paths active then the CODEC will be held with - * bias _ON and should not be suspended. */ - if (codec_dev->suspend) { - switch (codec->bias_level) { - case SND_SOC_BIAS_STANDBY: - case SND_SOC_BIAS_OFF: - codec_dev->suspend(pdev, PMSG_SUSPEND); - break; - default: - dev_dbg(socdev->dev, "CODEC is on over suspend\n"); - break; + /* suspend all CODECs */ + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_codec *codec = card->rtd[i].codec; + /* If there are paths active then the CODEC will be held with + * bias _ON and should not be suspended. */ + if (!codec->suspended && codec->driver->suspend) { + switch (codec->bias_level) { + case SND_SOC_BIAS_STANDBY: + case SND_SOC_BIAS_OFF: + codec->driver->suspend(codec, PMSG_SUSPEND); + codec->suspended = 1; + break; + default: + dev_dbg(codec->dev, "CODEC is on over suspend\n"); + break; + } } } - for (i = 0; i < card->num_links; i++) { - struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; - if (card->dai_link[i].ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend) continue; - if (cpu_dai->suspend && cpu_dai->ac97_control) - cpu_dai->suspend(cpu_dai); + if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control) + cpu_dai->driver->suspend(cpu_dai); } if (card->suspend_post) @@ -991,127 +980,127 @@ static int soc_suspend(struct device *dev) */ static void soc_resume_deferred(struct work_struct *work) { - struct snd_soc_card *card = container_of(work, - struct snd_soc_card, - deferred_resume_work); - struct snd_soc_device *socdev = card->socdev; - struct snd_soc_platform *platform = card->platform; - struct snd_soc_codec_device *codec_dev = socdev->codec_dev; - struct snd_soc_codec *codec = card->codec; - struct platform_device *pdev = to_platform_device(socdev->dev); + struct snd_soc_card *card = + container_of(work, struct snd_soc_card, deferred_resume_work); + struct platform_device *pdev = to_platform_device(card->dev); int i; /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, * so userspace apps are blocked from touching us */ - dev_dbg(socdev->dev, "starting resume work\n"); + dev_dbg(card->dev, "starting resume work\n"); /* Bring us up into D2 so that DAPM starts enabling things */ - snd_power_change_state(codec->card, SNDRV_CTL_POWER_D2); + snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2); if (card->resume_pre) card->resume_pre(pdev); - for (i = 0; i < card->num_links; i++) { - struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; + /* resume AC97 DAIs */ + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; - if (card->dai_link[i].ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend) continue; - if (cpu_dai->resume && cpu_dai->ac97_control) - cpu_dai->resume(cpu_dai); - } - - /* If the CODEC was idle over suspend then it will have been - * left with bias OFF or STANDBY and suspended so we must now - * resume. Otherwise the suspend was suppressed. - */ - if (codec_dev->resume) { - switch (codec->bias_level) { - case SND_SOC_BIAS_STANDBY: - case SND_SOC_BIAS_OFF: - codec_dev->resume(pdev); - break; - default: - dev_dbg(socdev->dev, "CODEC was on over suspend\n"); - break; + if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control) + cpu_dai->driver->resume(cpu_dai); + } + + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_codec *codec = card->rtd[i].codec; + /* If the CODEC was idle over suspend then it will have been + * left with bias OFF or STANDBY and suspended so we must now + * resume. Otherwise the suspend was suppressed. + */ + if (codec->driver->resume && codec->suspended) { + switch (codec->bias_level) { + case SND_SOC_BIAS_STANDBY: + case SND_SOC_BIAS_OFF: + codec->driver->resume(codec); + codec->suspended = 0; + break; + default: + dev_dbg(codec->dev, "CODEC was on over suspend\n"); + break; + } } } - for (i = 0; i < codec->num_dai; i++) { - char *stream = codec->dai[i].playback.stream_name; + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver; - if (card->dai_link[i].ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend) continue; - if (stream != NULL) - snd_soc_dapm_stream_event(codec, stream, + if (driver->playback.stream_name != NULL) + snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name, SND_SOC_DAPM_STREAM_RESUME); - stream = codec->dai[i].capture.stream_name; - if (stream != NULL) - snd_soc_dapm_stream_event(codec, stream, + + if (driver->capture.stream_name != NULL) + snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name, SND_SOC_DAPM_STREAM_RESUME); } /* unmute any active DACs */ - for (i = 0; i < card->num_links; i++) { - struct snd_soc_dai *dai = card->dai_link[i].codec_dai; + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai *dai = card->rtd[i].codec_dai; + struct snd_soc_dai_driver *drv = dai->driver; - if (card->dai_link[i].ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend) continue; - if (dai->ops->digital_mute && dai->playback.active) - dai->ops->digital_mute(dai, 0); + if (drv->ops->digital_mute && dai->playback_active) + drv->ops->digital_mute(dai, 0); } - for (i = 0; i < card->num_links; i++) { - struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; + struct snd_soc_platform *platform = card->rtd[i].platform; - if (card->dai_link[i].ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend) continue; - if (cpu_dai->resume && !cpu_dai->ac97_control) - cpu_dai->resume(cpu_dai); - if (platform->resume) - platform->resume(&card->dai_link[i]); + if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control) + cpu_dai->driver->resume(cpu_dai); + if (platform->driver->resume && platform->suspended) { + platform->driver->resume(cpu_dai); + platform->suspended = 0; + } } if (card->resume_post) card->resume_post(pdev); - dev_dbg(socdev->dev, "resume work completed\n"); + dev_dbg(card->dev, "resume work completed\n"); /* userspace can access us now we are back as we were before */ - snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0); + snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); } /* powers up audio subsystem after a suspend */ static int soc_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_card *card = socdev->card; - struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai; - - /* If the initialization of this soc device failed, there is no codec - * associated with it. Just bail out in this case. - */ - if (!card->codec) - return 0; + struct snd_soc_card *card = platform_get_drvdata(pdev); + int i; /* AC97 devices might have other drivers hanging off them so * need to resume immediately. Other drivers don't have that * problem and may take a substantial amount of time to resume * due to I/O costs and anti-pop so handle them out of line. */ - if (cpu_dai->ac97_control) { - dev_dbg(socdev->dev, "Resuming AC97 immediately\n"); - soc_resume_deferred(&card->deferred_resume_work); - } else { - dev_dbg(socdev->dev, "Scheduling resume work\n"); - if (!schedule_work(&card->deferred_resume_work)) - dev_err(socdev->dev, "resume work item may be lost\n"); + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; + if (cpu_dai->driver->ac97_control) { + dev_dbg(dev, "Resuming AC97 immediately\n"); + soc_resume_deferred(&card->deferred_resume_work); + } else { + dev_dbg(dev, "Scheduling resume work\n"); + if (!schedule_work(&card->deferred_resume_work)) + dev_err(dev, "resume work item may be lost\n"); + } } return 0; @@ -1124,198 +1113,429 @@ static int soc_resume(struct device *dev) static struct snd_soc_dai_ops null_dai_ops = { }; -static void snd_soc_instantiate_card(struct snd_soc_card *card) +static int soc_bind_dai_link(struct snd_soc_card *card, int num) { - struct platform_device *pdev = container_of(card->dev, - struct platform_device, - dev); - struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev; + struct snd_soc_dai_link *dai_link = &card->dai_link[num]; + struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; struct snd_soc_codec *codec; struct snd_soc_platform *platform; - struct snd_soc_dai *dai; - int i, found, ret, ac97; + struct snd_soc_dai *codec_dai, *cpu_dai; - if (card->instantiated) - return; + if (rtd->complete) + return 1; + dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num); - found = 0; - list_for_each_entry(platform, &platform_list, list) - if (card->platform == platform) { - found = 1; - break; + /* do we already have the CPU DAI for this link ? */ + if (rtd->cpu_dai) { + goto find_codec; + } + /* no, then find CPU DAI from registered DAIs*/ + list_for_each_entry(cpu_dai, &dai_list, list) { + if (!strcmp(cpu_dai->name, dai_link->cpu_dai_name)) { + + if (!try_module_get(cpu_dai->dev->driver->owner)) + return -ENODEV; + + rtd->cpu_dai = cpu_dai; + goto find_codec; } - if (!found) { - dev_dbg(card->dev, "Platform %s not registered\n", - card->platform->name); - return; } + dev_dbg(card->dev, "CPU DAI %s not registered\n", + dai_link->cpu_dai_name); - ac97 = 0; - for (i = 0; i < card->num_links; i++) { - found = 0; - list_for_each_entry(dai, &dai_list, list) - if (card->dai_link[i].cpu_dai == dai) { - found = 1; - break; +find_codec: + /* do we already have the CODEC for this link ? */ + if (rtd->codec) { + goto find_platform; + } + + /* no, then find CODEC from registered CODECs*/ + list_for_each_entry(codec, &codec_list, list) { + if (!strcmp(codec->name, dai_link->codec_name)) { + rtd->codec = codec; + + if (!try_module_get(codec->dev->driver->owner)) + return -ENODEV; + + /* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/ + list_for_each_entry(codec_dai, &dai_list, list) { + if (codec->dev == codec_dai->dev && + !strcmp(codec_dai->name, dai_link->codec_dai_name)) { + rtd->codec_dai = codec_dai; + goto find_platform; + } } - if (!found) { - dev_dbg(card->dev, "DAI %s not registered\n", - card->dai_link[i].cpu_dai->name); - return; + dev_dbg(card->dev, "CODEC DAI %s not registered\n", + dai_link->codec_dai_name); + + goto find_platform; } + } + dev_dbg(card->dev, "CODEC %s not registered\n", + dai_link->codec_name); - if (card->dai_link[i].cpu_dai->ac97_control) - ac97 = 1; +find_platform: + /* do we already have the CODEC DAI for this link ? */ + if (rtd->platform) { + goto out; } + /* no, then find CPU DAI from registered DAIs*/ + list_for_each_entry(platform, &platform_list, list) { + if (!strcmp(platform->name, dai_link->platform_name)) { - for (i = 0; i < card->num_links; i++) { - if (!card->dai_link[i].codec_dai->ops) - card->dai_link[i].codec_dai->ops = &null_dai_ops; + if (!try_module_get(platform->dev->driver->owner)) + return -ENODEV; + + rtd->platform = platform; + goto out; + } } - /* If we have AC97 in the system then don't wait for the - * codec. This will need revisiting if we have to handle - * systems with mixed AC97 and non-AC97 parts. Only check for - * DAIs currently; we can't do this per link since some AC97 - * codecs have non-AC97 DAIs. - */ - if (!ac97) - for (i = 0; i < card->num_links; i++) { - found = 0; - list_for_each_entry(dai, &dai_list, list) - if (card->dai_link[i].codec_dai == dai) { - found = 1; - break; - } - if (!found) { - dev_dbg(card->dev, "DAI %s not registered\n", - card->dai_link[i].codec_dai->name); - return; - } + dev_dbg(card->dev, "platform %s not registered\n", + dai_link->platform_name); + return 0; + +out: + /* mark rtd as complete if we found all 4 of our client devices */ + if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) { + rtd->complete = 1; + card->num_rtd++; + } + return 1; +} + +static void soc_remove_dai_link(struct snd_soc_card *card, int num) +{ + struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; + int err; + + /* unregister the rtd device */ + if (rtd->dev_registered) { + device_remove_file(&rtd->dev, &dev_attr_pmdown_time); + device_unregister(&rtd->dev); + rtd->dev_registered = 0; + } + + /* remove the CODEC DAI */ + if (codec_dai && codec_dai->probed) { + if (codec_dai->driver->remove) { + err = codec_dai->driver->remove(codec_dai); + if (err < 0) + printk(KERN_ERR "asoc: failed to remove %s\n", codec_dai->name); } + codec_dai->probed = 0; + list_del(&codec_dai->card_list); + } - /* Note that we do not current check for codec components */ + /* remove the platform */ + if (platform && platform->probed) { + if (platform->driver->remove) { + err = platform->driver->remove(platform); + if (err < 0) + printk(KERN_ERR "asoc: failed to remove %s\n", platform->name); + } + platform->probed = 0; + list_del(&platform->card_list); + module_put(platform->dev->driver->owner); + } - dev_dbg(card->dev, "All components present, instantiating\n"); + /* remove the CODEC */ + if (codec && codec->probed) { + if (codec->driver->remove) { + err = codec->driver->remove(codec); + if (err < 0) + printk(KERN_ERR "asoc: failed to remove %s\n", codec->name); + } - /* Found everything, bring it up */ - card->pmdown_time = pmdown_time; + /* Make sure all DAPM widgets are freed */ + snd_soc_dapm_free(codec); - if (card->probe) { - ret = card->probe(pdev); - if (ret < 0) - return; + soc_cleanup_codec_debugfs(codec); + device_remove_file(&rtd->dev, &dev_attr_codec_reg); + codec->probed = 0; + list_del(&codec->card_list); + module_put(codec->dev->driver->owner); } - for (i = 0; i < card->num_links; i++) { - struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; - if (cpu_dai->probe) { - ret = cpu_dai->probe(pdev, cpu_dai); - if (ret < 0) - goto cpu_dai_err; + /* remove the cpu_dai */ + if (cpu_dai && cpu_dai->probed) { + if (cpu_dai->driver->remove) { + err = cpu_dai->driver->remove(cpu_dai); + if (err < 0) + printk(KERN_ERR "asoc: failed to remove %s\n", cpu_dai->name); } + cpu_dai->probed = 0; + list_del(&cpu_dai->card_list); + module_put(cpu_dai->dev->driver->owner); } +} - if (codec_dev->probe) { - ret = codec_dev->probe(pdev); - if (ret < 0) - goto cpu_dai_err; +static void rtd_release(struct device *dev) {} + +static int soc_probe_dai_link(struct snd_soc_card *card, int num) +{ + struct snd_soc_dai_link *dai_link = &card->dai_link[num]; + struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; + int ret; + + dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num); + + /* config components */ + codec_dai->codec = codec; + codec->card = card; + cpu_dai->platform = platform; + rtd->card = card; + rtd->dev.parent = card->dev; + codec_dai->card = card; + cpu_dai->card = card; + + /* set default power off timeout */ + rtd->pmdown_time = pmdown_time; + + /* probe the cpu_dai */ + if (!cpu_dai->probed) { + if (cpu_dai->driver->probe) { + ret = cpu_dai->driver->probe(cpu_dai); + if (ret < 0) { + printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n", + cpu_dai->name); + return ret; + } + } + cpu_dai->probed = 1; + /* mark cpu_dai as probed and add to card cpu_dai list */ + list_add(&cpu_dai->card_list, &card->dai_dev_list); } - codec = card->codec; - if (platform->probe) { - ret = platform->probe(pdev); - if (ret < 0) - goto platform_err; + /* probe the CODEC */ + if (!codec->probed) { + if (codec->driver->probe) { + ret = codec->driver->probe(codec); + if (ret < 0) { + printk(KERN_ERR "asoc: failed to probe CODEC %s\n", + codec->name); + return ret; + } + } + /* mark codec as probed and add to card codec list */ + codec->probed = 1; + list_add(&codec->card_list, &card->codec_dev_list); } - /* DAPM stream work */ - INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work); -#ifdef CONFIG_PM - /* deferred resume work */ - INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); -#endif + /* probe the platform */ + if (!platform->probed) { + if (platform->driver->probe) { + ret = platform->driver->probe(platform); + if (ret < 0) { + printk(KERN_ERR "asoc: failed to probe platform %s\n", + platform->name); + return ret; + } + } + /* mark platform as probed and add to card platform list */ + platform->probed = 1; + list_add(&platform->card_list, &card->platform_dev_list); + } - for (i = 0; i < card->num_links; i++) { - if (card->dai_link[i].init) { - ret = card->dai_link[i].init(codec); + /* probe the CODEC DAI */ + if (!codec_dai->probed) { + if (codec_dai->driver->probe) { + ret = codec_dai->driver->probe(codec_dai); if (ret < 0) { - printk(KERN_ERR "asoc: failed to init %s\n", - card->dai_link[i].stream_name); - continue; + printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n", + codec_dai->name); + return ret; } } - if (card->dai_link[i].codec_dai->ac97_control) - ac97 = 1; + + /* mark cpu_dai as probed and add to card cpu_dai list */ + codec_dai->probed = 1; + list_add(&codec_dai->card_list, &card->dai_dev_list); } - snprintf(codec->card->shortname, sizeof(codec->card->shortname), - "%s", card->name); - snprintf(codec->card->longname, sizeof(codec->card->longname), - "%s (%s)", card->name, codec->name); + /* DAPM dai link stream work */ + INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); + + /* now that all clients have probed, initialise the DAI link */ + if (dai_link->init) { + ret = dai_link->init(rtd); + if (ret < 0) { + printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name); + return ret; + } + } /* Make sure all DAPM widgets are instantiated */ snd_soc_dapm_new_widgets(codec); + snd_soc_dapm_sync(codec); - ret = snd_card_register(codec->card); + /* register the rtd device */ + rtd->dev.init_name = rtd->dai_link->stream_name; + rtd->dev.release = rtd_release; + rtd->dev.init_name = dai_link->name; + ret = device_register(&rtd->dev); if (ret < 0) { - printk(KERN_ERR "asoc: failed to register soundcard for %s\n", - codec->name); - goto card_err; + printk(KERN_ERR "asoc: failed to register DAI runtime device %d\n", ret); + return ret; } - mutex_lock(&codec->mutex); + rtd->dev_registered = 1; + ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time); + if (ret < 0) + printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); + + /* add DAPM sysfs entries for this codec */ + ret = snd_soc_dapm_sys_add(&rtd->dev); + if (ret < 0) + printk(KERN_WARNING "asoc: failed to add codec dapm sysfs entries\n"); + + /* add codec sysfs entries */ + ret = device_create_file(&rtd->dev, &dev_attr_codec_reg); + if (ret < 0) + printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); + + soc_init_codec_debugfs(codec); + + /* create the pcm */ + ret = soc_new_pcm(rtd, num); + if (ret < 0) { + printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_name); + return ret; + } + + /* add platform data for AC97 devices */ + if (rtd->codec_dai->driver->ac97_control) + snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata); + + return 0; +} + #ifdef CONFIG_SND_SOC_AC97_BUS +static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + /* Only instantiate AC97 if not already done by the adaptor * for the generic AC97 subsystem. */ - if (ac97 && strcmp(codec->name, "AC97") != 0) { - ret = soc_ac97_dev_register(codec); + if (rtd->codec_dai->driver->ac97_control && !rtd->codec->ac97_registered) { + + ret = soc_ac97_dev_register(rtd->codec); if (ret < 0) { printk(KERN_ERR "asoc: AC97 device register failed\n"); - snd_card_free(codec->card); - mutex_unlock(&codec->mutex); - goto card_err; + return ret; } + + rtd->codec->ac97_registered = 1; } + return 0; +} + +static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec) +{ + if (codec->ac97_registered) { + soc_ac97_dev_unregister(codec); + codec->ac97_registered = 0; + } +} #endif - ret = snd_soc_dapm_sys_add(card->socdev->dev); - if (ret < 0) - printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n"); +static void snd_soc_instantiate_card(struct snd_soc_card *card) +{ + struct platform_device *pdev = to_platform_device(card->dev); + int ret, i; - ret = device_create_file(card->socdev->dev, &dev_attr_pmdown_time); - if (ret < 0) - printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); + mutex_lock(&card->mutex); - ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg); - if (ret < 0) - printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); + if (card->instantiated) { + mutex_unlock(&card->mutex); + return; + } - soc_init_codec_debugfs(codec); - mutex_unlock(&codec->mutex); + /* bind DAIs */ + for (i = 0; i < card->num_links; i++) + soc_bind_dai_link(card, i); - card->instantiated = 1; + /* bind completed ? */ + if (card->num_rtd != card->num_links) { + mutex_unlock(&card->mutex); + return; + } - return; + /* card bind complete so register a sound card */ + ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + card->owner, 0, &card->snd_card); + if (ret < 0) { + printk(KERN_ERR "asoc: can't create sound card for card %s\n", + card->name); + mutex_unlock(&card->mutex); + return; + } + card->snd_card->dev = card->dev; + +#ifdef CONFIG_PM + /* deferred resume work */ + INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); +#endif -card_err: - if (platform->remove) - platform->remove(pdev); + /* initialise the sound card only once */ + if (card->probe) { + ret = card->probe(pdev); + if (ret < 0) + goto card_probe_error; + } -platform_err: - if (codec_dev->remove) - codec_dev->remove(pdev); + for (i = 0; i < card->num_links; i++) { + ret = soc_probe_dai_link(card, i); + if (ret < 0) { + printk(KERN_ERR "asoc: failed to instanciate card %s\n", card->name); + goto probe_dai_err; + } + } -cpu_dai_err: - for (i--; i >= 0; i--) { - struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; - if (cpu_dai->remove) - cpu_dai->remove(pdev, cpu_dai); + snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), + "%s", card->name); + snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), + "%s", card->name); + + ret = snd_card_register(card->snd_card); + if (ret < 0) { + printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name); + goto probe_dai_err; } +#ifdef CONFIG_SND_SOC_AC97_BUS + /* register any AC97 codecs */ + for (i = 0; i < card->num_rtd; i++) { + ret = soc_register_ac97_dai_link(&card->rtd[i]); + if (ret < 0) { + printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name); + goto probe_dai_err; + } + } +#endif + + card->instantiated = 1; + mutex_unlock(&card->mutex); + return; + +probe_dai_err: + for (i = 0; i < card->num_links; i++) + soc_remove_dai_link(card, i); + +card_probe_error: if (card->remove) card->remove(pdev); + + snd_card_free(card->snd_card); + + mutex_unlock(&card->mutex); } /* @@ -1332,15 +1552,15 @@ static void snd_soc_instantiate_cards(void) /* probes a new socdev */ static int soc_probe(struct platform_device *pdev) { + struct snd_soc_card *card = platform_get_drvdata(pdev); int ret = 0; - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_card *card = socdev->card; - - /* Bodge while we push things out of socdev */ - card->socdev = socdev; /* Bodge while we unpick instantiation */ card->dev = &pdev->dev; + INIT_LIST_HEAD(&card->dai_dev_list); + INIT_LIST_HEAD(&card->codec_dev_list); + INIT_LIST_HEAD(&card->platform_dev_list); + ret = snd_soc_register_card(card); if (ret != 0) { dev_err(&pdev->dev, "Failed to register card\n"); @@ -1353,50 +1573,49 @@ static int soc_probe(struct platform_device *pdev) /* removes a socdev */ static int soc_remove(struct platform_device *pdev) { + struct snd_soc_card *card = platform_get_drvdata(pdev); int i; - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_card *card = socdev->card; - struct snd_soc_platform *platform = card->platform; - struct snd_soc_codec_device *codec_dev = socdev->codec_dev; - if (card->instantiated) { - run_delayed_work(&card->delayed_work); + if (card->instantiated) { - if (platform->remove) - platform->remove(pdev); - - if (codec_dev->remove) - codec_dev->remove(pdev); - - for (i = 0; i < card->num_links; i++) { - struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; - if (cpu_dai->remove) - cpu_dai->remove(pdev, cpu_dai); + /* make sure any delayed work runs */ + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; + run_delayed_work(&rtd->delayed_work); } + /* remove and free each DAI */ + for (i = 0; i < card->num_rtd; i++) + soc_remove_dai_link(card, i); + + /* remove the card */ if (card->remove) card->remove(pdev); - } + kfree(card->rtd); + snd_card_free(card->snd_card); + } snd_soc_unregister_card(card); - return 0; } static int soc_poweroff(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_card *card = socdev->card; + struct snd_soc_card *card = platform_get_drvdata(pdev); + int i; if (!card->instantiated) return 0; /* Flush out pmdown_time work - we actually do want to run it * now, we're shutting down so no imminent restart. */ - run_delayed_work(&card->delayed_work); + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; + run_delayed_work(&rtd->delayed_work); + } - snd_soc_dapm_shutdown(socdev); + snd_soc_dapm_shutdown(card); return 0; } @@ -1419,53 +1638,42 @@ static struct platform_driver soc_driver = { }; /* create a new pcm */ -static int soc_new_pcm(struct snd_soc_device *socdev, - struct snd_soc_dai_link *dai_link, int num) -{ - struct snd_soc_card *card = socdev->card; - struct snd_soc_codec *codec = card->codec; - struct snd_soc_platform *platform = card->platform; - struct snd_soc_dai *codec_dai = dai_link->codec_dai; - struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; - struct snd_soc_pcm_runtime *rtd; +static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_pcm *pcm; char new_name[64]; int ret = 0, playback = 0, capture = 0; - rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL); - if (rtd == NULL) - return -ENOMEM; - - rtd->dai = dai_link; - rtd->socdev = socdev; - codec_dai->codec = card->codec; - /* check client and interface hw capabilities */ snprintf(new_name, sizeof(new_name), "%s %s-%d", - dai_link->stream_name, codec_dai->name, num); + rtd->dai_link->stream_name, codec_dai->name, num); - if (codec_dai->playback.channels_min) + if (codec_dai->driver->playback.channels_min) playback = 1; - if (codec_dai->capture.channels_min) + if (codec_dai->driver->capture.channels_min) capture = 1; - ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback, - capture, &pcm); + dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name); + ret = snd_pcm_new(rtd->card->snd_card, new_name, + num, playback, capture, &pcm); if (ret < 0) { - printk(KERN_ERR "asoc: can't create pcm for codec %s\n", - codec->name); - kfree(rtd); + printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name); return ret; } - dai_link->pcm = pcm; + rtd->pcm = pcm; pcm->private_data = rtd; - soc_pcm_ops.mmap = platform->pcm_ops->mmap; - soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; - soc_pcm_ops.copy = platform->pcm_ops->copy; - soc_pcm_ops.silence = platform->pcm_ops->silence; - soc_pcm_ops.ack = platform->pcm_ops->ack; - soc_pcm_ops.page = platform->pcm_ops->page; + soc_pcm_ops.mmap = platform->driver->ops->mmap; + soc_pcm_ops.pointer = platform->driver->ops->pointer; + soc_pcm_ops.ioctl = platform->driver->ops->ioctl; + soc_pcm_ops.copy = platform->driver->ops->copy; + soc_pcm_ops.silence = platform->driver->ops->silence; + soc_pcm_ops.ack = platform->driver->ops->ack; + soc_pcm_ops.page = platform->driver->ops->page; if (playback) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); @@ -1473,14 +1681,13 @@ static int soc_new_pcm(struct snd_soc_device *socdev, if (capture) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); - ret = platform->pcm_new(codec->card, codec_dai, pcm); + ret = platform->driver->pcm_new(rtd->card->snd_card, codec_dai, pcm); if (ret < 0) { printk(KERN_ERR "asoc: platform pcm constructor failed\n"); - kfree(rtd); return ret; } - pcm->private_free = platform->pcm_free; + pcm->private_free = platform->driver->pcm_free; printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, cpu_dai->name); return ret; @@ -1496,8 +1703,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev, */ int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg) { - if (codec->volatile_register) - return codec->volatile_register(reg); + if (codec->driver->volatile_register) + return codec->driver->volatile_register(reg); else return 0; } @@ -1532,7 +1739,6 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, codec->ac97->bus->ops = ops; codec->ac97->num = num; - codec->dev = &codec->ac97->dev; mutex_unlock(&codec->mutex); return 0; } @@ -1547,6 +1753,9 @@ EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) { mutex_lock(&codec->mutex); +#ifdef CONFIG_SND_SOC_AC97_BUS + soc_unregister_ac97_dai_link(codec); +#endif kfree(codec->ac97->bus); kfree(codec->ac97); codec->ac97 = NULL; @@ -1632,95 +1841,6 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg, } EXPORT_SYMBOL_GPL(snd_soc_test_bits); -/** - * snd_soc_new_pcms - create new sound card and pcms - * @socdev: the SoC audio device - * @idx: ALSA card index - * @xid: card identification - * - * Create a new sound card based upon the codec and interface pcms. - * - * Returns 0 for success, else error. - */ -int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) -{ - struct snd_soc_card *card = socdev->card; - struct snd_soc_codec *codec = card->codec; - int ret, i; - - mutex_lock(&codec->mutex); - - /* register a sound card */ - ret = snd_card_create(idx, xid, codec->owner, 0, &codec->card); - if (ret < 0) { - printk(KERN_ERR "asoc: can't create sound card for codec %s\n", - codec->name); - mutex_unlock(&codec->mutex); - return ret; - } - - codec->socdev = socdev; - codec->card->dev = socdev->dev; - codec->card->private_data = codec; - strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); - - /* create the pcms */ - for (i = 0; i < card->num_links; i++) { - ret = soc_new_pcm(socdev, &card->dai_link[i], i); - if (ret < 0) { - printk(KERN_ERR "asoc: can't create pcm %s\n", - card->dai_link[i].stream_name); - mutex_unlock(&codec->mutex); - return ret; - } - /* Check for codec->ac97 to handle the ac97.c fun */ - if (card->dai_link[i].codec_dai->ac97_control && codec->ac97) { - snd_ac97_dev_add_pdata(codec->ac97, - card->dai_link[i].cpu_dai->ac97_pdata); - } - } - - mutex_unlock(&codec->mutex); - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_new_pcms); - -/** - * snd_soc_free_pcms - free sound card and pcms - * @socdev: the SoC audio device - * - * Frees sound card and pcms associated with the socdev. - * Also unregister the codec if it is an AC97 device. - */ -void snd_soc_free_pcms(struct snd_soc_device *socdev) -{ - struct snd_soc_codec *codec = socdev->card->codec; -#ifdef CONFIG_SND_SOC_AC97_BUS - struct snd_soc_dai *codec_dai; - int i; -#endif - - mutex_lock(&codec->mutex); - soc_cleanup_codec_debugfs(codec); -#ifdef CONFIG_SND_SOC_AC97_BUS - for (i = 0; i < codec->num_dai; i++) { - codec_dai = &codec->dai[i]; - if (codec_dai->ac97_control && codec->ac97 && - strcmp(codec->name, "AC97") != 0) { - soc_ac97_dev_unregister(codec); - goto free_card; - } - } -free_card: -#endif - - if (codec->card) - snd_card_free(codec->card); - device_remove_file(socdev->dev, &dev_attr_codec_reg); - mutex_unlock(&codec->mutex); -} -EXPORT_SYMBOL_GPL(snd_soc_free_pcms); - /** * snd_soc_set_runtime_hwparams - set the runtime hardware parameters * @substream: the pcm substream @@ -1782,7 +1902,7 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew); int snd_soc_add_controls(struct snd_soc_codec *codec, const struct snd_kcontrol_new *controls, int num_controls) { - struct snd_card *card = codec->card; + struct snd_card *card = codec->card->snd_card; int err, i; for (i = 0; i < num_controls; i++) { @@ -2337,7 +2457,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); int snd_soc_limit_volume(struct snd_soc_codec *codec, const char *name, int max) { - struct snd_card *card = codec->card; + struct snd_card *card = codec->card->snd_card; struct snd_kcontrol *kctl; struct soc_mixer_control *mc; int found = 0; @@ -2469,8 +2589,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx); int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { - if (dai->ops && dai->ops->set_sysclk) - return dai->ops->set_sysclk(dai, clk_id, freq, dir); + if (dai->driver && dai->driver->ops->set_sysclk) + return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); else return -EINVAL; } @@ -2489,8 +2609,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) { - if (dai->ops && dai->ops->set_clkdiv) - return dai->ops->set_clkdiv(dai, div_id, div); + if (dai->driver && dai->driver->ops->set_clkdiv) + return dai->driver->ops->set_clkdiv(dai, div_id, div); else return -EINVAL; } @@ -2509,8 +2629,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { - if (dai->ops && dai->ops->set_pll) - return dai->ops->set_pll(dai, pll_id, source, + if (dai->driver && dai->driver->ops->set_pll) + return dai->driver->ops->set_pll(dai, pll_id, source, freq_in, freq_out); else return -EINVAL; @@ -2526,8 +2646,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); */ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - if (dai->ops && dai->ops->set_fmt) - return dai->ops->set_fmt(dai, fmt); + if (dai->driver && dai->driver->ops->set_fmt) + return dai->driver->ops->set_fmt(dai, fmt); else return -EINVAL; } @@ -2547,8 +2667,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { - if (dai->ops && dai->ops->set_tdm_slot) - return dai->ops->set_tdm_slot(dai, tx_mask, rx_mask, + if (dai->driver && dai->driver->ops->set_tdm_slot) + return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); else return -EINVAL; @@ -2571,8 +2691,8 @@ int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_num, unsigned int *tx_slot, unsigned int rx_num, unsigned int *rx_slot) { - if (dai->ops && dai->ops->set_channel_map) - return dai->ops->set_channel_map(dai, tx_num, tx_slot, + if (dai->driver && dai->driver->ops->set_channel_map) + return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, rx_num, rx_slot); else return -EINVAL; @@ -2588,8 +2708,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); */ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) { - if (dai->ops && dai->ops->set_tristate) - return dai->ops->set_tristate(dai, tristate); + if (dai->driver && dai->driver->ops->set_tristate) + return dai->driver->ops->set_tristate(dai, tristate); else return -EINVAL; } @@ -2604,8 +2724,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); */ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) { - if (dai->ops && dai->ops->digital_mute) - return dai->ops->digital_mute(dai, mute); + if (dai->driver && dai->driver->ops->digital_mute) + return dai->driver->ops->digital_mute(dai, mute); else return -EINVAL; } @@ -2622,11 +2742,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); */ static int snd_soc_register_card(struct snd_soc_card *card) { + int i; + if (!card->name || !card->dev) return -EINVAL; + card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * card->num_links, + GFP_KERNEL); + if (card->rtd == NULL) + return -ENOMEM; + + for (i = 0; i < card->num_links; i++) + card->rtd[i].dai_link = &card->dai_link[i]; + INIT_LIST_HEAD(&card->list); card->instantiated = 0; + mutex_init(&card->mutex); mutex_lock(&client_mutex); list_add(&card->list, &card_list); @@ -2652,30 +2783,97 @@ static int snd_soc_unregister_card(struct snd_soc_card *card) mutex_lock(&client_mutex); list_del(&card->list); mutex_unlock(&client_mutex); - dev_dbg(card->dev, "Unregistered card '%s'\n", card->name); return 0; } +/* + * Simplify DAI link configuration by removing ".-1" from device names + * and sanitizing names. + */ +static inline char *fmt_single_name(struct device *dev, int *id) +{ + char *found, name[NAME_SIZE]; + int id1, id2; + + if (dev_name(dev) == NULL) + return NULL; + + strncpy(name, dev_name(dev), NAME_SIZE); + + /* are we a "%s.%d" name (platform and SPI components) */ + found = strstr(name, dev->driver->name); + if (found) { + /* get ID */ + if (sscanf(&found[strlen(dev->driver->name)], ".%d", id) == 1) { + + /* discard ID from name if ID == -1 */ + if (*id == -1) + found[strlen(dev->driver->name)] = '\0'; + } + + } else { + /* I2C component devices are named "bus-addr" */ + if (sscanf(name, "%x-%x", &id1, &id2) == 2) { + char tmp[NAME_SIZE]; + + /* create unique ID number from I2C addr and bus */ + *id = ((id1 && 0xffff) << 16) + id2; + + /* sanitize component name for DAI link creation */ + snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, name); + strncpy(name, tmp, NAME_SIZE); + } else + *id = 0; + } + + return kstrdup(name, GFP_KERNEL); +} + +/* + * Simplify DAI link naming for single devices with multiple DAIs by removing + * any ".-1" and using the DAI name (instead of device name). + */ +static inline char *fmt_multiple_name(struct device *dev, + struct snd_soc_dai_driver *dai_drv) +{ + if (dai_drv->name == NULL) { + printk(KERN_ERR "asoc: error - multiple DAI %s registered with no name\n", + dev_name(dev)); + return NULL; + } + + return kstrdup(dai_drv->name, GFP_KERNEL); +} + /** * snd_soc_register_dai - Register a DAI with the ASoC core * * @dai: DAI to register */ -int snd_soc_register_dai(struct snd_soc_dai *dai) +int snd_soc_register_dai(struct device *dev, + struct snd_soc_dai_driver *dai_drv) { - if (!dai->name) - return -EINVAL; + struct snd_soc_dai *dai; + + dev_dbg(dev, "dai register %s\n", dev_name(dev)); - /* The device should become mandatory over time */ - if (!dai->dev) - printk(KERN_WARNING "No device for DAI %s\n", dai->name); + dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); + if (dai == NULL) + return -ENOMEM; - if (!dai->ops) - dai->ops = &null_dai_ops; + /* create DAI component name */ + dai->name = fmt_single_name(dev, &dai->id); + if (dai->name == NULL) { + kfree(dai); + return -ENOMEM; + } - INIT_LIST_HEAD(&dai->list); + dai->dev = dev; + dai->driver = dai_drv; + if (!dai->driver->ops) + dai->driver->ops = &null_dai_ops; mutex_lock(&client_mutex); list_add(&dai->list, &dai_list); @@ -2693,13 +2891,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dai); * * @dai: DAI to unregister */ -void snd_soc_unregister_dai(struct snd_soc_dai *dai) +void snd_soc_unregister_dai(struct device *dev) { + struct snd_soc_dai *dai; + + list_for_each_entry(dai, &dai_list, list) { + if (dev == dai->dev) + goto found; + } + return; + +found: mutex_lock(&client_mutex); list_del(&dai->list); mutex_unlock(&client_mutex); pr_debug("Unregistered DAI '%s'\n", dai->name); + kfree(dai->name); + kfree(dai); } EXPORT_SYMBOL_GPL(snd_soc_unregister_dai); @@ -2709,21 +2918,47 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai); * @dai: Array of DAIs to register * @count: Number of DAIs */ -int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count) +int snd_soc_register_dais(struct device *dev, + struct snd_soc_dai_driver *dai_drv, size_t count) { - int i, ret; + struct snd_soc_dai *dai; + int i, ret = 0; + + dev_dbg(dev, "dai register %s #%d\n", dev_name(dev), count); for (i = 0; i < count; i++) { - ret = snd_soc_register_dai(&dai[i]); - if (ret != 0) + + dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); + if (dai == NULL) + return -ENOMEM; + + /* create DAI component name */ + dai->name = fmt_multiple_name(dev, &dai_drv[i]); + if (dai->name == NULL) { + kfree(dai); + ret = -EINVAL; goto err; + } + + dai->dev = dev; + dai->id = i; + dai->driver = &dai_drv[i]; + if (!dai->driver->ops) + dai->driver->ops = &null_dai_ops; + + mutex_lock(&client_mutex); + list_add(&dai->list, &dai_list); + mutex_unlock(&client_mutex); + + pr_debug("Registered DAI '%s'\n", dai->name); } + snd_soc_instantiate_cards(); return 0; err: for (i--; i >= 0; i--) - snd_soc_unregister_dai(&dai[i]); + snd_soc_unregister_dai(dev); return ret; } @@ -2735,12 +2970,12 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dais); * @dai: Array of DAIs to unregister * @count: Number of DAIs */ -void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count) +void snd_soc_unregister_dais(struct device *dev, size_t count) { int i; for (i = 0; i < count; i++) - snd_soc_unregister_dai(&dai[i]); + snd_soc_unregister_dai(dev); } EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); @@ -2749,12 +2984,26 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); * * @platform: platform to register */ -int snd_soc_register_platform(struct snd_soc_platform *platform) +int snd_soc_register_platform(struct device *dev, + struct snd_soc_platform_driver *platform_drv) { - if (!platform->name) - return -EINVAL; + struct snd_soc_platform *platform; + + dev_dbg(dev, "platform register %s\n", dev_name(dev)); + + platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL); + if (platform == NULL) + return -ENOMEM; + + /* create platform component name */ + platform->name = fmt_single_name(dev, &platform->id); + if (platform->name == NULL) { + kfree(platform); + return -ENOMEM; + } - INIT_LIST_HEAD(&platform->list); + platform->dev = dev; + platform->driver = platform_drv; mutex_lock(&client_mutex); list_add(&platform->list, &platform_list); @@ -2772,13 +3021,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform); * * @platform: platform to unregister */ -void snd_soc_unregister_platform(struct snd_soc_platform *platform) +void snd_soc_unregister_platform(struct device *dev) { + struct snd_soc_platform *platform; + + list_for_each_entry(platform, &platform_list, list) { + if (dev == platform->dev) + goto found; + } + return; + +found: mutex_lock(&client_mutex); list_del(&platform->list); mutex_unlock(&client_mutex); pr_debug("Unregistered platform '%s'\n", platform->name); + kfree(platform->name); + kfree(platform); } EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); @@ -2820,32 +3080,78 @@ static void fixup_codec_formats(struct snd_soc_pcm_stream *stream) * * @codec: codec to register */ -int snd_soc_register_codec(struct snd_soc_codec *codec) +int snd_soc_register_codec(struct device *dev, + struct snd_soc_codec_driver *codec_drv, + struct snd_soc_dai_driver *dai_drv, int num_dai) { - int i; + struct snd_soc_codec *codec; + int ret, i; - if (!codec->name) - return -EINVAL; + dev_dbg(dev, "codec register %s\n", dev_name(dev)); + + codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (codec == NULL) + return -ENOMEM; - /* The device should become mandatory over time */ - if (!codec->dev) - printk(KERN_WARNING "No device for codec %s\n", codec->name); + /* create CODEC component name */ + codec->name = fmt_single_name(dev, &codec->id); + if (codec->name == NULL) { + kfree(codec); + return -ENOMEM; + } + + /* allocate CODEC register cache */ + if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { - INIT_LIST_HEAD(&codec->list); + if (codec_drv->reg_cache_default) + codec->reg_cache = kmemdup(codec_drv->reg_cache_default, + codec_drv->reg_cache_size * codec_drv->reg_word_size, GFP_KERNEL); + else + codec->reg_cache = kzalloc(codec_drv->reg_cache_size * + codec_drv->reg_word_size, GFP_KERNEL); - for (i = 0; i < codec->num_dai; i++) { - fixup_codec_formats(&codec->dai[i].playback); - fixup_codec_formats(&codec->dai[i].capture); + if (codec->reg_cache == NULL) { + kfree(codec->name); + kfree(codec); + return -ENOMEM; + } } + codec->dev = dev; + codec->driver = codec_drv; + codec->bias_level = SND_SOC_BIAS_OFF; + codec->num_dai = num_dai; + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + for (i = 0; i < num_dai; i++) { + fixup_codec_formats(&dai_drv[i].playback); + fixup_codec_formats(&dai_drv[i].capture); + } + + /* register DAIs */ + ret = snd_soc_register_dais(dev, dai_drv, num_dai); + if (ret < 0) + goto error; + mutex_lock(&client_mutex); list_add(&codec->list, &codec_list); snd_soc_instantiate_cards(); mutex_unlock(&client_mutex); pr_debug("Registered codec '%s'\n", codec->name); - return 0; + +error: + for (i--; i >= 0; i--) + snd_soc_unregister_dai(dev); + + if (codec->reg_cache) + kfree(codec->reg_cache); + kfree(codec->name); + kfree(codec); + return ret; } EXPORT_SYMBOL_GPL(snd_soc_register_codec); @@ -2854,13 +3160,30 @@ EXPORT_SYMBOL_GPL(snd_soc_register_codec); * * @codec: codec to unregister */ -void snd_soc_unregister_codec(struct snd_soc_codec *codec) +void snd_soc_unregister_codec(struct device *dev) { + struct snd_soc_codec *codec; + int i; + + list_for_each_entry(codec, &codec_list, list) { + if (dev == codec->dev) + goto found; + } + return; + +found: + for (i = 0; i < codec->num_dai; i++) + snd_soc_unregister_dai(dev); + mutex_lock(&client_mutex); list_del(&codec->list); mutex_unlock(&client_mutex); pr_debug("Unregistered codec '%s'\n", codec->name); + + if (codec->reg_cache) + kfree(codec->reg_cache); + kfree(codec); } EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 03cb7c05ebec..035cab85cb66 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -112,43 +112,41 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( /** * snd_soc_dapm_set_bias_level - set the bias level for the system - * @socdev: audio device + * @card: audio device * @level: level to configure * * Configure the bias (power) levels for the SoC audio device. * * Returns 0 for success else error. */ -static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, - enum snd_soc_bias_level level) +static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card, + struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - struct snd_soc_card *card = socdev->card; - struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; switch (level) { case SND_SOC_BIAS_ON: - dev_dbg(socdev->dev, "Setting full bias\n"); + dev_dbg(codec->dev, "Setting full bias\n"); break; case SND_SOC_BIAS_PREPARE: - dev_dbg(socdev->dev, "Setting bias prepare\n"); + dev_dbg(codec->dev, "Setting bias prepare\n"); break; case SND_SOC_BIAS_STANDBY: - dev_dbg(socdev->dev, "Setting standby bias\n"); + dev_dbg(codec->dev, "Setting standby bias\n"); break; case SND_SOC_BIAS_OFF: - dev_dbg(socdev->dev, "Setting bias off\n"); + dev_dbg(codec->dev, "Setting bias off\n"); break; default: - dev_err(socdev->dev, "Setting invalid bias %d\n", level); + dev_err(codec->dev, "Setting invalid bias %d\n", level); return -EINVAL; } - if (card->set_bias_level) + if (card && card->set_bias_level) ret = card->set_bias_level(card, level); if (ret == 0) { - if (codec->set_bias_level) - ret = codec->set_bias_level(codec, level); + if (codec->driver->set_bias_level) + ret = codec->driver->set_bias_level(codec, level); else codec->bias_level = level; } @@ -370,7 +368,7 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, path->long_name); - ret = snd_ctl_add(codec->card, path->kcontrol); + ret = snd_ctl_add(codec->card->snd_card, path->kcontrol); if (ret < 0) { printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n", path->long_name, @@ -398,7 +396,7 @@ static int dapm_new_mux(struct snd_soc_codec *codec, } kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); - ret = snd_ctl_add(codec->card, kcontrol); + ret = snd_ctl_add(codec->card->snd_card, kcontrol); if (ret < 0) goto err; @@ -437,9 +435,9 @@ static inline void dapm_clear_walk(struct snd_soc_codec *codec) */ static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) { - struct snd_soc_codec *codec = widget->codec; + int level = snd_power_get_state(widget->codec->card->snd_card); - switch (snd_power_get_state(codec->card)) { + switch (level) { case SNDRV_CTL_POWER_D3hot: case SNDRV_CTL_POWER_D3cold: if (widget->ignore_suspend) @@ -893,7 +891,7 @@ static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list, */ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) { - struct snd_soc_device *socdev = codec->socdev; + struct snd_soc_card *card = codec->card; struct snd_soc_dapm_widget *w; LIST_HEAD(up_list); LIST_HEAD(down_list); @@ -966,7 +964,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) } if (sys_power && codec->bias_level == SND_SOC_BIAS_OFF) { - ret = snd_soc_dapm_set_bias_level(socdev, + ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_STANDBY); if (ret != 0) pr_err("Failed to turn on bias: %d\n", ret); @@ -975,8 +973,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) /* If we're changing to all on or all off then prepare */ if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) || (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) { - ret = snd_soc_dapm_set_bias_level(socdev, - SND_SOC_BIAS_PREPARE); + ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_PREPARE); if (ret != 0) pr_err("Failed to prepare bias: %d\n", ret); } @@ -989,8 +986,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) /* If we just powered the last thing off drop to standby bias */ if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) { - ret = snd_soc_dapm_set_bias_level(socdev, - SND_SOC_BIAS_STANDBY); + ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_STANDBY); if (ret != 0) pr_err("Failed to apply standby bias: %d\n", ret); } @@ -998,15 +994,14 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) /* If we're in standby and can support bias off then do that */ if (codec->bias_level == SND_SOC_BIAS_STANDBY && codec->idle_bias_off) { - ret = snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF); + ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF); if (ret != 0) pr_err("Failed to turn off bias: %d\n", ret); } /* If we just powered up then move to active bias */ if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) { - ret = snd_soc_dapm_set_bias_level(socdev, - SND_SOC_BIAS_ON); + ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_ON); if (ret != 0) pr_err("Failed to apply active bias: %d\n", ret); } @@ -1188,8 +1183,9 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, static ssize_t dapm_widget_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct snd_soc_device *devdata = dev_get_drvdata(dev); - struct snd_soc_codec *codec = devdata->card->codec; + struct snd_soc_pcm_runtime *rtd = + container_of(dev, struct snd_soc_pcm_runtime, dev); + struct snd_soc_codec *codec =rtd->codec; struct snd_soc_dapm_widget *w; int count = 0; char *state = "not set"; @@ -1998,9 +1994,10 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); * * Returns 0 for success else error. */ -int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, - char *stream, int event) +int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, + const char *stream, int event) { + struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_widget *w; if (stream == NULL) @@ -2168,25 +2165,19 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); /** * snd_soc_dapm_free - free dapm resources - * @socdev: SoC device + * @card: SoC device * * Free all dapm widgets and resources. */ -void snd_soc_dapm_free(struct snd_soc_device *socdev) +void snd_soc_dapm_free(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = socdev->card->codec; - - snd_soc_dapm_sys_remove(socdev->dev); + snd_soc_dapm_sys_remove(codec->dev); dapm_free_widgets(codec); } EXPORT_SYMBOL_GPL(snd_soc_dapm_free); -/* - * snd_soc_dapm_shutdown - callback for system shutdown - */ -void snd_soc_dapm_shutdown(struct snd_soc_device *socdev) +static void soc_dapm_shutdown_codec(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_dapm_widget *w; LIST_HEAD(down_list); int powerdown = 0; @@ -2203,12 +2194,23 @@ void snd_soc_dapm_shutdown(struct snd_soc_device *socdev) * standby. */ if (powerdown) { - snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE); + snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_PREPARE); dapm_seq_run(codec, &down_list, 0, dapm_down_seq); - snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY); + snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_STANDBY); } +} + +/* + * snd_soc_dapm_shutdown - callback for system shutdown + */ +void snd_soc_dapm_shutdown(struct snd_soc_card *card) +{ + struct snd_soc_codec *codec; + + list_for_each_entry(codec, &card->codec_dev_list, list) + soc_dapm_shutdown_codec(codec); - snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF); + snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF); } /* Module information */ diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 29159e1781d0..8862770aa221 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -32,14 +32,14 @@ * Returns zero if successful, or a negative error code on failure. * On success jack will be initialised. */ -int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, +int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type, struct snd_soc_jack *jack) { - jack->card = card; + jack->codec = codec; INIT_LIST_HEAD(&jack->pins); BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); - return snd_jack_new(card->codec->card, id, type, &jack->jack); + return snd_jack_new(codec->card->snd_card, id, type, &jack->jack); } EXPORT_SYMBOL_GPL(snd_soc_jack_new); @@ -67,7 +67,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) if (!jack) return; - codec = jack->card->codec; + codec = jack->codec; mutex_lock(&codec->mutex); @@ -268,7 +268,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, ret = request_irq(gpio_to_irq(gpios[i].gpio), gpio_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - jack->card->dev->driver->name, + jack->codec->dev->driver->name, &gpios[i]); if (ret) goto err; diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index 0ec20b68e8cb..743d07b82c06 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c @@ -36,13 +36,11 @@ static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq); -/* REVISIT: How to find txx9aclc_soc_device from snd_ac97? */ -static struct txx9aclc_soc_device *txx9aclc_soc_dev; +/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */ +static struct txx9aclc_plat_drvdata *txx9aclc_drvdata; -static int txx9aclc_regready(struct txx9aclc_soc_device *dev) +static int txx9aclc_regready(struct txx9aclc_plat_drvdata *drvdata) { - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); - return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY; } @@ -50,8 +48,7 @@ static int txx9aclc_regready(struct txx9aclc_soc_device *dev) static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { - struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); + struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; void __iomem *base = drvdata->base; u32 dat; @@ -61,15 +58,15 @@ static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97, dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ; __raw_writel(dat, base + ACREGACC); __raw_writel(ACINT_REGACCRDY, base + ACINTEN); - if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) { + if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) { __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); - dev_err(dev->soc_dev.dev, "ac97 read timeout (reg %#x)\n", reg); + printk(KERN_ERR "ac97 read timeout (reg %#x)\n", reg); dat = 0xffff; goto done; } dat = __raw_readl(base + ACREGACC); if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) { - dev_err(dev->soc_dev.dev, "reg mismatch %x with %x\n", + printk(KERN_ERR "reg mismatch %x with %x\n", dat, reg); dat = 0xffff; goto done; @@ -84,16 +81,15 @@ done: static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { - struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); + struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; void __iomem *base = drvdata->base; __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) | (val << ACREGACC_DAT_SHIFT), base + ACREGACC); __raw_writel(ACINT_REGACCRDY, base + ACINTEN); - if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) { - dev_err(dev->soc_dev.dev, + if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) { + printk(KERN_ERR "ac97 write timeout (reg %#x)\n", reg); } __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); @@ -101,8 +97,7 @@ static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97) { - struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); + struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; void __iomem *base = drvdata->base; u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY; @@ -141,31 +136,23 @@ static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static int txx9aclc_ac97_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int txx9aclc_ac97_probe(struct snd_soc_dai *dai) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct txx9aclc_soc_device *dev = - container_of(socdev, struct txx9aclc_soc_device, soc_dev); - - dev->aclc_pdev = to_platform_device(dai->dev); - txx9aclc_soc_dev = dev; + txx9aclc_drvdata = snd_soc_dai_get_drvdata(dai); return 0; } -static void txx9aclc_ac97_remove(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int txx9aclc_ac97_remove(struct snd_soc_dai *dai) { - struct platform_device *aclc_pdev = to_platform_device(dai->dev); - struct txx9aclc_plat_drvdata *drvdata = platform_get_drvdata(aclc_pdev); + struct txx9aclc_plat_drvdata *drvdata = snd_soc_dai_get_drvdata(dai); /* disable AC-link */ __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS); - txx9aclc_soc_dev = NULL; + txx9aclc_drvdata = NULL; + return 0; } -struct snd_soc_dai txx9aclc_ac97_dai = { - .name = "txx9aclc_ac97", +static struct snd_soc_dai_driver txx9aclc_ac97_dai = { .ac97_control = 1, .probe = txx9aclc_ac97_probe, .remove = txx9aclc_ac97_remove, @@ -182,7 +169,6 @@ struct snd_soc_dai txx9aclc_ac97_dai = { .channels_max = 2, }, }; -EXPORT_SYMBOL_GPL(txx9aclc_ac97_dai); static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev) { @@ -219,13 +205,12 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev) if (err < 0) return err; - txx9aclc_ac97_dai.dev = &pdev->dev; - return snd_soc_register_dai(&txx9aclc_ac97_dai); + return snd_soc_register_dai(&pdev->dev, &txx9aclc_ac97_dai); } static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev) { - snd_soc_unregister_dai(&txx9aclc_ac97_dai); + snd_soc_unregister_dai(&pdev->dev); return 0; } diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c index 95b17f731aec..6770e7166be4 100644 --- a/sound/soc/txx9/txx9aclc-generic.c +++ b/sound/soc/txx9/txx9aclc-generic.c @@ -19,54 +19,44 @@ #include #include #include -#include "../codecs/ac97.h" #include "txx9aclc.h" static struct snd_soc_dai_link txx9aclc_generic_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai = &txx9aclc_ac97_dai, - .codec_dai = &ac97_dai, + .cpu_dai_name = "txx9aclc-ac97", + .codec_dai_name = "ac97-hifi", + .platform_name = "txx9aclc-pcm-audio", + .codec_name = "ac97-codec", }; static struct snd_soc_card txx9aclc_generic_card = { .name = "Generic TXx9 ACLC Audio", - .platform = &txx9aclc_soc_platform, .dai_link = &txx9aclc_generic_dai, .num_links = 1, }; -static struct txx9aclc_soc_device txx9aclc_generic_soc_device = { - .soc_dev = { - .card = &txx9aclc_generic_card, - .codec_dev = &soc_codec_dev_ac97, - }, -}; +static struct platform_device *soc_pdev; static int __init txx9aclc_generic_probe(struct platform_device *pdev) { - struct txx9aclc_soc_device *dev = &txx9aclc_generic_soc_device; - struct platform_device *soc_pdev; int ret; soc_pdev = platform_device_alloc("soc-audio", -1); if (!soc_pdev) return -ENOMEM; - platform_set_drvdata(soc_pdev, &dev->soc_dev); - dev->soc_dev.dev = &soc_pdev->dev; + platform_set_drvdata(soc_pdev, &txx9aclc_generic_card); ret = platform_device_add(soc_pdev); if (ret) { platform_device_put(soc_pdev); return ret; } - platform_set_drvdata(pdev, soc_pdev); + return 0; } static int __exit txx9aclc_generic_remove(struct platform_device *pdev) { - struct platform_device *soc_pdev = platform_get_drvdata(pdev); - platform_device_unregister(soc_pdev); return 0; } diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index 0e3452303ea6..f4aa4e03c888 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c @@ -22,6 +22,16 @@ #include #include "txx9aclc.h" +static struct txx9aclc_soc_device { + struct txx9aclc_dmadata dmadata[2]; +} txx9aclc_soc_device; + +/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */ +static struct txx9aclc_plat_drvdata *txx9aclc_drvdata; + +static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, + struct txx9aclc_dmadata *dmadata); + static const struct snd_pcm_hardware txx9aclc_pcm_hardware = { /* * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID @@ -46,7 +56,6 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); - struct snd_soc_device *socdev = rtd->socdev; struct snd_pcm_runtime *runtime = substream->runtime; struct txx9aclc_dmadata *dmadata = runtime->private_data; int ret; @@ -55,13 +64,13 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - dev_dbg(socdev->dev, + dev_dbg(rtd->platform->dev, "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd " "runtime->min_align %ld\n", (unsigned long)runtime->dma_area, (unsigned long)runtime->dma_addr, runtime->dma_bytes, runtime->min_align); - dev_dbg(socdev->dev, + dev_dbg(rtd->platform->dev, "periods %d period_bytes %d stream %d\n", params_periods(params), params_period_bytes(params), substream->stream); @@ -152,11 +161,7 @@ static void txx9aclc_dma_tasklet(unsigned long data) spin_lock_irqsave(&dmadata->dma_lock, flags); if (dmadata->frag_count < 0) { - struct txx9aclc_soc_device *dev = - container_of(dmadata, struct txx9aclc_soc_device, - dmadata[substream->stream]); - struct txx9aclc_plat_drvdata *drvdata = - txx9aclc_get_plat_drvdata(dev); + struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; void __iomem *base = drvdata->base; spin_unlock_irqrestore(&dmadata->dma_lock, flags); @@ -202,10 +207,7 @@ static void txx9aclc_dma_tasklet(unsigned long data) static int txx9aclc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct txx9aclc_soc_device *dev = - container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev); - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); + struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata; void __iomem *base = drvdata->base; unsigned long flags; int ret = 0; @@ -244,9 +246,7 @@ txx9aclc_pcm_pointer(struct snd_pcm_substream *substream) static int txx9aclc_pcm_open(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct txx9aclc_soc_device *dev = - container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev); + struct txx9aclc_soc_device *dev = &txx9aclc_soc_device; struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream]; int ret; @@ -291,8 +291,38 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm) static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { + struct platform_device *pdev = to_platform_device(dai->platform->dev); + struct txx9aclc_soc_device *dev; + struct resource *r; + int i; + int ret; + + /* at this point onwards the AC97 component has probed and this will be valid */ + dev = snd_soc_dai_get_drvdata(dai); + + dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK; + dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE; + for (i = 0; i < 2; i++) { + r = platform_get_resource(pdev, IORESOURCE_DMA, i); + if (!r) { + ret = -EBUSY; + goto exit; + } + dev->dmadata[i].dma_res = r; + ret = txx9aclc_dma_init(dev, &dev->dmadata[i]); + if (ret) + goto exit; + } return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, card->dev, 64 * 1024, 4 * 1024 * 1024); + +exit: + for (i = 0; i < 2; i++) { + if (dev->dmadata[i].dma_chan) + dma_release_channel(dev->dmadata[i].dma_chan); + dev->dmadata[i].dma_chan = NULL; + } + return ret; } static bool filter(struct dma_chan *chan, void *param) @@ -314,7 +344,7 @@ static bool filter(struct dma_chan *chan, void *param) static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, struct txx9aclc_dmadata *dmadata) { - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); + struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata; struct txx9dmac_slave *ds = &dmadata->dma_slave; dma_cap_mask_t mask; @@ -334,7 +364,7 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, dma_cap_set(DMA_SLAVE, mask); dmadata->dma_chan = dma_request_channel(mask, filter, dmadata); if (!dmadata->dma_chan) { - dev_err(dev->soc_dev.dev, + printk(KERN_ERR "DMA channel for %s is not available\n", dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture"); @@ -345,45 +375,16 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, return 0; } -static int txx9aclc_pcm_probe(struct platform_device *pdev) +static int txx9aclc_pcm_probe(struct snd_soc_platform *platform) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct txx9aclc_soc_device *dev = - container_of(socdev, struct txx9aclc_soc_device, soc_dev); - struct resource *r; - int i; - int ret; - - dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK; - dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE; - for (i = 0; i < 2; i++) { - r = platform_get_resource(dev->aclc_pdev, IORESOURCE_DMA, i); - if (!r) { - ret = -EBUSY; - goto exit; - } - dev->dmadata[i].dma_res = r; - ret = txx9aclc_dma_init(dev, &dev->dmadata[i]); - if (ret) - goto exit; - } + snd_soc_platform_set_drvdata(platform, &txx9aclc_soc_device); return 0; - -exit: - for (i = 0; i < 2; i++) { - if (dev->dmadata[i].dma_chan) - dma_release_channel(dev->dmadata[i].dma_chan); - dev->dmadata[i].dma_chan = NULL; - } - return ret; } -static int txx9aclc_pcm_remove(struct platform_device *pdev) +static int txx9aclc_pcm_remove(struct snd_soc_platform *platform) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct txx9aclc_soc_device *dev = - container_of(socdev, struct txx9aclc_soc_device, soc_dev); - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); + struct txx9aclc_soc_device *dev = snd_soc_platform_get_drvdata(platform); + struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; void __iomem *base = drvdata->base; int i; @@ -406,28 +407,46 @@ static int txx9aclc_pcm_remove(struct platform_device *pdev) return 0; } -struct snd_soc_platform txx9aclc_soc_platform = { - .name = "txx9aclc-audio", +static struct snd_soc_platform_driver txx9aclc_soc_platform = { .probe = txx9aclc_pcm_probe, .remove = txx9aclc_pcm_remove, - .pcm_ops = &txx9aclc_pcm_ops, + .ops = &txx9aclc_pcm_ops, .pcm_new = txx9aclc_pcm_new, .pcm_free = txx9aclc_pcm_free_dma_buffers, }; -EXPORT_SYMBOL_GPL(txx9aclc_soc_platform); -static int __init txx9aclc_soc_platform_init(void) +static int __devinit txx9aclc_soc_platform_probe(struct platform_device *pdev) { - return snd_soc_register_platform(&txx9aclc_soc_platform); + return snd_soc_register_platform(&pdev->dev, &txx9aclc_soc_platform); } -static void __exit txx9aclc_soc_platform_exit(void) +static int __devexit txx9aclc_soc_platform_remove(struct platform_device *pdev) { - snd_soc_unregister_platform(&txx9aclc_soc_platform); + snd_soc_unregister_platform(&pdev->dev); + return 0; } -module_init(txx9aclc_soc_platform_init); -module_exit(txx9aclc_soc_platform_exit); +static struct platform_driver txx9aclc_pcm_driver = { + .driver = { + .name = "txx9aclc-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = txx9aclc_soc_platform_probe, + .remove = __devexit_p(txx9aclc_soc_platform_remove), +}; + +static int __init snd_txx9aclc_pcm_init(void) +{ + return platform_driver_register(&txx9aclc_pcm_driver); +} +module_init(snd_txx9aclc_pcm_init); + +static void __exit snd_txx9aclc_pcm_exit(void) +{ + platform_driver_unregister(&txx9aclc_pcm_driver); +} +module_exit(snd_txx9aclc_pcm_exit); MODULE_AUTHOR("Atsushi Nemoto "); MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver"); diff --git a/sound/soc/txx9/txx9aclc.h b/sound/soc/txx9/txx9aclc.h index 6769aab41b33..9c2de84fec3b 100644 --- a/sound/soc/txx9/txx9aclc.h +++ b/sound/soc/txx9/txx9aclc.h @@ -65,19 +65,10 @@ struct txx9aclc_plat_drvdata { u64 physbase; }; -struct txx9aclc_soc_device { - struct snd_soc_device soc_dev; - struct platform_device *aclc_pdev; /* for ioresources, drvdata */ - struct txx9aclc_dmadata dmadata[2]; -}; - static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata( - struct txx9aclc_soc_device *sdev) + struct snd_soc_dai *dai) { - return platform_get_drvdata(sdev->aclc_pdev); + return dev_get_drvdata(dai->dev); } -extern struct snd_soc_platform txx9aclc_soc_platform; -extern struct snd_soc_dai txx9aclc_ac97_dai; - #endif /* __TXX9ACLC_H */ -- cgit v1.2.3-59-g8ed1b From 3782a528974c9607bde03ec265bbebd2dc300ea1 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 21 Jul 2010 08:06:56 +0900 Subject: ASoC: multi-component - Add Aquila sound driver This patch add sound support for the Aquila board based on S5PC110. The Aquila board is based on Samsung SoC(S5PC110) and include WM8994 codec over I2S to support sound. This uses the I2Sv4 driver compatible with I2Sv5 to run sound. The kind of jack is below states : * SND_JACK_HEADPHONE * SND_JACK_HEADSET * SND_JACK_MECHANICAL : When TV-OUT cable is inserted on Aquila board, the TV-OUT cable isn't connected to television. * SND_JACK_AVOUT : When TV-OUT cable is inserted on Aquila board, the TV-OUT cable is connected to television. Signed-off-by: Chanwoo Choi Signed-off-by: Joonyoung Shim Signed-off-by: Kyungmin Park Acked-by: Mark Brown Signed-off-by: Liam Girdwood ASoC: multi-component: SAMSUNG: Fix wrong field name on Aquila board This patch modify the wrong field name on Aquila board. Signed-off-by: Chanwoo Choi Signed-off-by: Kyungmin Park Signed-off-by: Liam Girdwood --- sound/soc/s3c24xx/Kconfig | 9 ++ sound/soc/s3c24xx/Makefile | 2 + sound/soc/s3c24xx/aquila_wm8994.c | 295 ++++++++++++++++++++++++++++++++++++++ sound/soc/s3c24xx/s3c-i2s-v2.c | 2 +- 4 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 sound/soc/s3c24xx/aquila_wm8994.c diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index 213963ac3c28..c09b4021afe9 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig @@ -131,3 +131,12 @@ config SND_S3C64XX_SOC_SMARTQ depends on SND_S3C24XX_SOC && MACH_SMARTQ select SND_S3C64XX_SOC_I2S select SND_SOC_WM8750 + +config SND_S5PC110_SOC_AQUILA_WM8994 + tristate "SoC I2S Audio support for AQUILA - WM8994" + depends on SND_S3C24XX_SOC && MACH_AQUILA + select SND_S3C64XX_SOC_I2S_V4 + select SND_SOC_WM8994 + help + Say Y if you want to add support for SoC audio on aquila + with the WM8994. diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 50172c385d90..02dd12c714f6 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile @@ -30,6 +30,7 @@ snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o snd-soc-smdk-wm9713-objs := smdk_wm9713.o snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o +snd-soc-aquila-wm8994-objs := aquila_wm8994.o obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o @@ -43,3 +44,4 @@ obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv32 obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o +obj-$(CONFIG_SND_S5PC110_SOC_AQUILA_WM8994) += snd-soc-aquila-wm8994.o diff --git a/sound/soc/s3c24xx/aquila_wm8994.c b/sound/soc/s3c24xx/aquila_wm8994.c new file mode 100644 index 000000000000..235d1973f7d0 --- /dev/null +++ b/sound/soc/s3c24xx/aquila_wm8994.c @@ -0,0 +1,295 @@ +/* + * aquila_wm8994.c + * + * Copyright (C) 2010 Samsung Electronics Co.Ltd + * Author: Chanwoo Choi + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "../codecs/wm8994.h" +#include "s3c-dma.h" +#include "s3c64xx-i2s.h" + +static struct snd_soc_card aquila; +static struct platform_device *aquila_snd_device; + +/* 3.5 pie jack */ +static struct snd_soc_jack jack; + +/* 3.5 pie jack detection DAPM pins */ +static struct snd_soc_jack_pin jack_pins[] = { + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, { + .pin = "Headset Stereophone", + .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL | + SND_JACK_AVOUT, + }, +}; + +/* 3.5 pie jack detection gpios */ +static struct snd_soc_jack_gpio jack_gpios[] = { + { + .gpio = S5PV210_GPH0(6), + .name = "DET_3.5", + .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL | + SND_JACK_AVOUT, + .debounce_time = 200, + }, +}; + +static const struct snd_soc_dapm_widget aquila_dapm_widgets[] = { + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_SPK("Ext Rcv", NULL), + SND_SOC_DAPM_HP("Headset Stereophone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Main Mic", NULL), + SND_SOC_DAPM_MIC("2nd Mic", NULL), + SND_SOC_DAPM_LINE("Radio In", NULL), +}; + +static const struct snd_soc_dapm_route aquila_dapm_routes[] = { + {"Ext Spk", NULL, "SPKOUTLP"}, + {"Ext Spk", NULL, "SPKOUTLN"}, + + {"Ext Rcv", NULL, "HPOUT2N"}, + {"Ext Rcv", NULL, "HPOUT2P"}, + + {"Headset Stereophone", NULL, "HPOUT1L"}, + {"Headset Stereophone", NULL, "HPOUT1R"}, + + {"IN1RN", NULL, "Headset Mic"}, + {"IN1RP", NULL, "Headset Mic"}, + + {"IN1RN", NULL, "2nd Mic"}, + {"IN1RP", NULL, "2nd Mic"}, + + {"IN1LN", NULL, "Main Mic"}, + {"IN1LP", NULL, "Main Mic"}, + + {"IN2LN", NULL, "Radio In"}, + {"IN2RN", NULL, "Radio In"}, +}; + +static int aquila_wm8994_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + int ret; + + /* add aquila specific widgets */ + snd_soc_dapm_new_controls(codec, aquila_dapm_widgets, + ARRAY_SIZE(aquila_dapm_widgets)); + + /* set up aquila specific audio routes */ + snd_soc_dapm_add_routes(codec, aquila_dapm_routes, + ARRAY_SIZE(aquila_dapm_routes)); + + /* set endpoints to not connected */ + snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN"); + snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP"); + snd_soc_dapm_nc_pin(codec, "LINEOUT1N"); + snd_soc_dapm_nc_pin(codec, "LINEOUT1P"); + snd_soc_dapm_nc_pin(codec, "LINEOUT2N"); + snd_soc_dapm_nc_pin(codec, "LINEOUT2P"); + snd_soc_dapm_nc_pin(codec, "SPKOUTRN"); + snd_soc_dapm_nc_pin(codec, "SPKOUTRP"); + + snd_soc_dapm_sync(codec); + + /* Headset jack detection */ + ret = snd_soc_jack_new(&aquila, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, + &jack); + if (ret) + return ret; + + ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); + if (ret) + return ret; + + ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); + if (ret) + return ret; + + return 0; +} + +static int aquila_hifi_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 24000000; + int ret = 0; + + /* set the cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + + /* set the cpu system clock */ + ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK, + 0, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + + /* set the codec FLL */ + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out, + params_rate(params) * 256); + if (ret < 0) + return ret; + + /* set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, + params_rate(params) * 256, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static struct snd_soc_ops aquila_hifi_ops = { + .hw_params = aquila_hifi_hw_params, +}; + +static int aquila_voice_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + unsigned int pll_out = 24000000; + int ret = 0; + + if (params_rate(params) != 8000) + return -EINVAL; + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | + SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + + /* set the codec FLL */ + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out, + params_rate(params) * 256); + if (ret < 0) + return ret; + + /* set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, + params_rate(params) * 256, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static struct snd_soc_dai_driver voice_dai = { + .name = "aquila-voice-dai", + .playback = { + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, +}; + +static struct snd_soc_ops aquila_voice_ops = { + .hw_params = aquila_voice_hw_params, +}; + +static struct snd_soc_dai_link aquila_dai[] = { +{ + .name = "WM8994", + .stream_name = "WM8994 HiFi", + .cpu_dai_name = "s3c64xx-i2s-v4", + .codec_dai_name = "wm8994-hifi", + .platform_name = "s3c24xx-pcm-audio", + .codec_name = "wm8994-codec.0-0x1a", + .init = aquila_wm8994_init, + .ops = &aquila_hifi_ops, +}, { + .name = "WM8994 Voice", + .stream_name = "Voice", + .cpu_dai_name = "aquila-voice-dai", + .codec_dai_name = "wm8994-voice", + .platform_name = "s3c24xx-pcm-audio", + .codec_name = "wm8994-codec.0-0x1a", + .ops = &aquila_voice_ops, +}, +}; + +static struct snd_soc_card aquila = { + .name = "aquila", + .dai_link = aquila_dai, + .num_links = ARRAY_SIZE(aquila_dai), +}; + +static int __init aquila_init(void) +{ + int ret; + + if (!machine_is_aquila()) + return -ENODEV; + + aquila_snd_device = platform_device_alloc("soc-audio", -1); + if (!aquila_snd_device) + return -ENOMEM; + + /* register voice DAI here */ + ret = snd_soc_register_dai(&aquila_snd_device->dev, &voice_dai); + if (ret) + return ret; + + platform_set_drvdata(aquila_snd_device, &aquila); + ret = platform_device_add(aquila_snd_device); + + if (ret) + platform_device_put(aquila_snd_device); + + return ret; +} + +static void __exit aquila_exit(void) +{ + platform_device_unregister(aquila_snd_device); +} + +module_init(aquila_init); +module_exit(aquila_exit); + +/* Module information */ +MODULE_DESCRIPTION("ALSA SoC WM8994 Aquila(S5PC110)"); +MODULE_AUTHOR("Chanwoo Choi "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c index f4fbc0e61733..b3866d5b19e9 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.c +++ b/sound/soc/s3c24xx/s3c-i2s-v2.c @@ -750,7 +750,7 @@ int s3c_i2sv2_register_dai(struct device *dev, int id, drv->suspend = s3c2412_i2s_suspend; drv->resume = s3c2412_i2s_resume; - return snd_soc_register_dai(dev, id, drv); + return snd_soc_register_dai(dev, drv); } EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); -- cgit v1.2.3-59-g8ed1b From f51582fd8d9b1196d58cd94c2b4b759cc1baf57a Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 22 Jul 2010 15:16:10 +0900 Subject: ASoC: multi-component - Add Goni sound driver This patch add sound support for the Goni board based on S5PV210. The Goni board is based on Samsung SoC(S5PV210) and include WM8994 codec over I2S to support sound. The kind of jack is below states : * SND_JACK_HEADPHONE * SND_JACK_HEADSET * SND_JACK_MECHANICAL : When TV-OUT cable is inserted on Goni board, the TV-OUT cable isn't connected to television. * SND_JACK_AVOUT : When TV-OUT cable is inserted on Goni board, the TV-OUT cable is connected to television. Signed-off-by: Chanwoo Choi Signed-off-by: Joonyoung Shim Signed-off-by: Kyungmin Park Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/s3c24xx/Kconfig | 9 ++ sound/soc/s3c24xx/Makefile | 2 + sound/soc/s3c24xx/goni_wm8994.c | 298 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 309 insertions(+) create mode 100644 sound/soc/s3c24xx/goni_wm8994.c diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index c09b4021afe9..1cdc37bd58f4 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig @@ -140,3 +140,12 @@ config SND_S5PC110_SOC_AQUILA_WM8994 help Say Y if you want to add support for SoC audio on aquila with the WM8994. + +config SND_S5PV210_SOC_GONI_WM8994 + tristate "SoC I2S Audio support for GONI - WM8994" + depends on SND_S3C24XX_SOC && MACH_GONI + select SND_S3C64XX_SOC_I2S_V4 + select SND_SOC_WM8994 + help + Say Y if you want to add support for SoC audio on goni + with the WM8994. diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 02dd12c714f6..47ed6d70b90b 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile @@ -31,6 +31,7 @@ snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o snd-soc-smdk-wm9713-objs := smdk_wm9713.o snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o snd-soc-aquila-wm8994-objs := aquila_wm8994.o +snd-soc-goni-wm8994-objs := goni_wm8994.o obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o @@ -45,3 +46,4 @@ obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o obj-$(CONFIG_SND_S5PC110_SOC_AQUILA_WM8994) += snd-soc-aquila-wm8994.o +obj-$(CONFIG_SND_S5PV210_SOC_GONI_WM8994) += snd-soc-goni-wm8994.o diff --git a/sound/soc/s3c24xx/goni_wm8994.c b/sound/soc/s3c24xx/goni_wm8994.c new file mode 100644 index 000000000000..694f702cc8e2 --- /dev/null +++ b/sound/soc/s3c24xx/goni_wm8994.c @@ -0,0 +1,298 @@ +/* + * goni_wm8994.c + * + * Copyright (C) 2010 Samsung Electronics Co.Ltd + * Author: Chanwoo Choi + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "../codecs/wm8994.h" +#include "s3c-dma.h" +#include "s3c64xx-i2s.h" + +static struct snd_soc_card goni; +static struct platform_device *goni_snd_device; + +/* 3.5 pie jack */ +static struct snd_soc_jack jack; + +/* 3.5 pie jack detection DAPM pins */ +static struct snd_soc_jack_pin jack_pins[] = { + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, { + .pin = "Headset Stereophone", + .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL | + SND_JACK_AVOUT, + }, +}; + +/* 3.5 pie jack detection gpios */ +static struct snd_soc_jack_gpio jack_gpios[] = { + { + .gpio = S5PV210_GPH0(6), + .name = "DET_3.5", + .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL | + SND_JACK_AVOUT, + .debounce_time = 200, + }, +}; + +static const struct snd_soc_dapm_widget goni_dapm_widgets[] = { + SND_SOC_DAPM_SPK("Ext Left Spk", NULL), + SND_SOC_DAPM_SPK("Ext Right Spk", NULL), + SND_SOC_DAPM_SPK("Ext Rcv", NULL), + SND_SOC_DAPM_HP("Headset Stereophone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Main Mic", NULL), + SND_SOC_DAPM_MIC("2nd Mic", NULL), + SND_SOC_DAPM_LINE("Radio In", NULL), +}; + +static const struct snd_soc_dapm_route goni_dapm_routes[] = { + {"Ext Left Spk", NULL, "SPKOUTLP"}, + {"Ext Left Spk", NULL, "SPKOUTLN"}, + + {"Ext Right Spk", NULL, "SPKOUTRP"}, + {"Ext Right Spk", NULL, "SPKOUTRN"}, + + {"Ext Rcv", NULL, "HPOUT2N"}, + {"Ext Rcv", NULL, "HPOUT2P"}, + + {"Headset Stereophone", NULL, "HPOUT1L"}, + {"Headset Stereophone", NULL, "HPOUT1R"}, + + {"IN1RN", NULL, "Headset Mic"}, + {"IN1RP", NULL, "Headset Mic"}, + + {"IN1RN", NULL, "2nd Mic"}, + {"IN1RP", NULL, "2nd Mic"}, + + {"IN1LN", NULL, "Main Mic"}, + {"IN1LP", NULL, "Main Mic"}, + + {"IN2LN", NULL, "Radio In"}, + {"IN2RN", NULL, "Radio In"}, +}; + +static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + int ret; + + /* add goni specific widgets */ + snd_soc_dapm_new_controls(codec, goni_dapm_widgets, + ARRAY_SIZE(goni_dapm_widgets)); + + /* set up goni specific audio routes */ + snd_soc_dapm_add_routes(codec, goni_dapm_routes, + ARRAY_SIZE(goni_dapm_routes)); + + /* set endpoints to not connected */ + snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN"); + snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP"); + snd_soc_dapm_nc_pin(codec, "LINEOUT1N"); + snd_soc_dapm_nc_pin(codec, "LINEOUT1P"); + snd_soc_dapm_nc_pin(codec, "LINEOUT2N"); + snd_soc_dapm_nc_pin(codec, "LINEOUT2P"); + + snd_soc_dapm_sync(codec); + + /* Headset jack detection */ + ret = snd_soc_jack_new(&goni, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, + &jack); + if (ret) + return ret; + + ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); + if (ret) + return ret; + + ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); + if (ret) + return ret; + + return 0; +} + +static int goni_hifi_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 24000000; + int ret = 0; + + /* set the cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + + /* set the cpu system clock */ + ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK, + 0, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + + /* set the codec FLL */ + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out, + params_rate(params) * 256); + if (ret < 0) + return ret; + + /* set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, + params_rate(params) * 256, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static struct snd_soc_ops goni_hifi_ops = { + .hw_params = goni_hifi_hw_params, +}; + +static int goni_voice_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + unsigned int pll_out = 24000000; + int ret = 0; + + if (params_rate(params) != 8000) + return -EINVAL; + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | + SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + + /* set the codec FLL */ + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out, + params_rate(params) * 256); + if (ret < 0) + return ret; + + /* set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, + params_rate(params) * 256, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static struct snd_soc_dai_driver voice_dai = { + .name = "goni-voice-dai", + .id = 0, + .playback = { + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, +}; + +static struct snd_soc_ops goni_voice_ops = { + .hw_params = goni_voice_hw_params, +}; + +static struct snd_soc_dai_link goni_dai[] = { +{ + .name = "WM8994", + .stream_name = "WM8994 HiFi", + .cpu_dai_name = "s3c64xx-i2s-v4", + .codec_dai_name = "wm8994-hifi", + .platform_name = "s3c24xx-pcm-audio", + .codec_name = "wm8994-codec.0-0x1a", + .init = goni_wm8994_init, + .ops = &goni_hifi_ops, +}, { + .name = "WM8994 Voice", + .stream_name = "Voice", + .cpu_dai_name = "goni-voice-dai", + .codec_dai_name = "wm8994-voice", + .platform_name = "s3c24xx-pcm-audio", + .codec_name = "wm8994-codec.0-0x1a", + .ops = &goni_voice_ops, +}, +}; + +static struct snd_soc_card goni = { + .name = "goni", + .dai_link = goni_dai, + .num_links = ARRAY_SIZE(goni_dai), +}; + +static int __init goni_init(void) +{ + int ret; + + if (!machine_is_goni()) + return -ENODEV; + + goni_snd_device = platform_device_alloc("soc-audio", -1); + if (!goni_snd_device) + return -ENOMEM; + + /* register voice DAI here */ + ret = snd_soc_register_dai(&goni_snd_device->dev, &voice_dai); + if (ret) + return ret; + + platform_set_drvdata(goni_snd_device, &goni); + ret = platform_device_add(goni_snd_device); + + if (ret) + platform_device_put(goni_snd_device); + + return ret; +} + +static void __exit goni_exit(void) +{ + platform_device_unregister(goni_snd_device); +} + +module_init(goni_init); +module_exit(goni_exit); + +/* Module information */ +MODULE_DESCRIPTION("ALSA SoC WM8994 GONI(S5PV210)"); +MODULE_AUTHOR("Chanwoo Choi "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 6e6f66226f0092a39526f8d6f02ebb447d995be2 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 22 Jul 2010 11:33:30 -0500 Subject: powerpc: rename immap_86xx.h to fsl_guts.h, and add 85xx support The immap_86xx.h header file only defines one data structure: the "global utilities" register set found on Freescale PowerPC SOCs. Rename this file to fsl_guts.h to reflect its true purpose, and extend it to cover the "GUTS" register set on 85xx chips. Signed-off-by: Timur Tabi Acked-by: Mark Brown Acked-by: Kumar Gala Signed-off-by: Liam Girdwood --- arch/powerpc/include/asm/fsl_guts.h | 197 ++++++++++++++++++++++++++++++++++ arch/powerpc/include/asm/immap_86xx.h | 156 --------------------------- sound/soc/fsl/fsl_ssi.c | 2 - sound/soc/fsl/mpc8610_hpcd.c | 10 +- 4 files changed, 202 insertions(+), 163 deletions(-) create mode 100644 arch/powerpc/include/asm/fsl_guts.h delete mode 100644 arch/powerpc/include/asm/immap_86xx.h diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h new file mode 100644 index 000000000000..bebd12463ec9 --- /dev/null +++ b/arch/powerpc/include/asm/fsl_guts.h @@ -0,0 +1,197 @@ +/** + * Freecale 85xx and 86xx Global Utilties register set + * + * Authors: Jeff Brown + * Timur Tabi + * + * Copyright 2004,2007 Freescale Semiconductor, Inc + * + * 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. + */ + +#ifndef __ASM_POWERPC_FSL_GUTS_H__ +#define __ASM_POWERPC_FSL_GUTS_H__ +#ifdef __KERNEL__ + +/* + * These #ifdefs are safe because it's not possible to build a kernel that + * runs on e500 and e600 cores. + */ + +#if !defined(CONFIG_PPC_85xx) && !defined(CONFIG_PPC_86xx) +#error Only 85xx and 86xx SOCs are supported +#endif + +/** + * Global Utility Registers. + * + * Not all registers defined in this structure are available on all chips, so + * you are expected to know whether a given register actually exists on your + * chip before you access it. + * + * Also, some registers are similar on different chips but have slightly + * different names. In these cases, one name is chosen to avoid extraneous + * #ifdefs. + */ +#ifdef CONFIG_PPC_85xx +struct ccsr_guts_85xx { +#else +struct ccsr_guts_86xx { +#endif + __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ + __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ + __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ + __be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */ + __be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */ + __be32 pordevsr2; /* 0x.0014 - POR device status register 2 */ + u8 res018[0x20 - 0x18]; + __be32 porcir; /* 0x.0020 - POR Configuration Information Register */ + u8 res024[0x30 - 0x24]; + __be32 gpiocr; /* 0x.0030 - GPIO Control Register */ + u8 res034[0x40 - 0x34]; + __be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */ + u8 res044[0x50 - 0x44]; + __be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */ + u8 res054[0x60 - 0x54]; + __be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */ + __be32 pmuxcr2; /* 0x.0064 - Alternate function signal multiplex control 2 */ + __be32 dmuxcr; /* 0x.0068 - DMA Mux Control Register */ + u8 res06c[0x70 - 0x6c]; + __be32 devdisr; /* 0x.0070 - Device Disable Control */ + __be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */ + u8 res078[0x7c - 0x78]; + __be32 pmjcr; /* 0x.007c - 4 Power Management Jog Control Register */ + __be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */ + __be32 pmrccr; /* 0x.0084 - Power Management Reset Counter Configuration Register */ + __be32 pmpdccr; /* 0x.0088 - Power Management Power Down Counter Configuration Register */ + __be32 pmcdr; /* 0x.008c - 4Power management clock disable register */ + __be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */ + __be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */ + __be32 ectrstcr; /* 0x.0098 - Exception reset control register */ + __be32 autorstsr; /* 0x.009c - Automatic reset status register */ + __be32 pvr; /* 0x.00a0 - Processor Version Register */ + __be32 svr; /* 0x.00a4 - System Version Register */ + u8 res0a8[0xb0 - 0xa8]; + __be32 rstcr; /* 0x.00b0 - Reset Control Register */ + u8 res0b4[0xc0 - 0xb4]; +#ifdef CONFIG_PPC_85xx + __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register */ +#else + __be32 elbcvselcr; /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */ +#endif + u8 res0c4[0x224 - 0xc4]; + __be32 iodelay1; /* 0x.0224 - IO delay control register 1 */ + __be32 iodelay2; /* 0x.0228 - IO delay control register 2 */ + u8 res22c[0x800 - 0x22c]; + __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */ + u8 res804[0x900 - 0x804]; + __be32 ircr; /* 0x.0900 - Infrared Control Register */ + u8 res904[0x908 - 0x904]; + __be32 dmacr; /* 0x.0908 - DMA Control Register */ + u8 res90c[0x914 - 0x90c]; + __be32 elbccr; /* 0x.0914 - eLBC Control Register */ + u8 res918[0xb20 - 0x918]; + __be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */ + __be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */ + __be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */ + u8 resb2c[0xe00 - 0xb2c]; + __be32 clkocr; /* 0x.0e00 - Clock Out Select Register */ + u8 rese04[0xe10 - 0xe04]; + __be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */ + u8 rese14[0xe20 - 0xe14]; + __be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */ + __be32 cpfor; /* 0x.0e24 - L2 charge pump fuse override register */ + u8 rese28[0xf04 - 0xe28]; + __be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */ + __be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */ + u8 resf0c[0xf2c - 0xf0c]; + __be32 itcr; /* 0x.0f2c - Internal transaction control register */ + u8 resf30[0xf40 - 0xf30]; + __be32 srds2cr0; /* 0x.0f40 - SerDes2 Control Register 0 */ + __be32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */ +} __attribute__ ((packed)); + +#ifdef CONFIG_PPC_86xx + +#define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */ +#define CCSR_GUTS_DMACR_DEV_IR 1 /* DMA controller/channel set to IR */ + +/* + * Set the DMACR register in the GUTS + * + * The DMACR register determines the source of initiated transfers for each + * channel on each DMA controller. Rather than have a bunch of repetitive + * macros for the bit patterns, we just have a function that calculates + * them. + * + * guts: Pointer to GUTS structure + * co: The DMA controller (0 or 1) + * ch: The channel on the DMA controller (0, 1, 2, or 3) + * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx) + */ +static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts, + unsigned int co, unsigned int ch, unsigned int device) +{ + unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); + + clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift); +} + +#define CCSR_GUTS_PMUXCR_LDPSEL 0x00010000 +#define CCSR_GUTS_PMUXCR_SSI1_MASK 0x0000C000 /* Bitmask for SSI1 */ +#define CCSR_GUTS_PMUXCR_SSI1_LA 0x00000000 /* Latched address */ +#define CCSR_GUTS_PMUXCR_SSI1_HI 0x00004000 /* High impedance */ +#define CCSR_GUTS_PMUXCR_SSI1_SSI 0x00008000 /* Used for SSI1 */ +#define CCSR_GUTS_PMUXCR_SSI2_MASK 0x00003000 /* Bitmask for SSI2 */ +#define CCSR_GUTS_PMUXCR_SSI2_LA 0x00000000 /* Latched address */ +#define CCSR_GUTS_PMUXCR_SSI2_HI 0x00001000 /* High impedance */ +#define CCSR_GUTS_PMUXCR_SSI2_SSI 0x00002000 /* Used for SSI2 */ +#define CCSR_GUTS_PMUXCR_LA_22_25_LA 0x00000000 /* Latched Address */ +#define CCSR_GUTS_PMUXCR_LA_22_25_HI 0x00000400 /* High impedance */ +#define CCSR_GUTS_PMUXCR_DBGDRV 0x00000200 /* Signals not driven */ +#define CCSR_GUTS_PMUXCR_DMA2_0 0x00000008 +#define CCSR_GUTS_PMUXCR_DMA2_3 0x00000004 +#define CCSR_GUTS_PMUXCR_DMA1_0 0x00000002 +#define CCSR_GUTS_PMUXCR_DMA1_3 0x00000001 + +/* + * Set the DMA external control bits in the GUTS + * + * The DMA external control bits in the PMUXCR are only meaningful for + * channels 0 and 3. Any other channels are ignored. + * + * guts: Pointer to GUTS structure + * co: The DMA controller (0 or 1) + * ch: The channel on the DMA controller (0, 1, 2, or 3) + * value: the new value for the bit (0 or 1) + */ +static inline void guts_set_pmuxcr_dma(struct ccsr_guts_86xx __iomem *guts, + unsigned int co, unsigned int ch, unsigned int value) +{ + if ((ch == 0) || (ch == 3)) { + unsigned int shift = 2 * (co + 1) - (ch & 1) - 1; + + clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift); + } +} + +#define CCSR_GUTS_CLKDVDR_PXCKEN 0x80000000 +#define CCSR_GUTS_CLKDVDR_SSICKEN 0x20000000 +#define CCSR_GUTS_CLKDVDR_PXCKINV 0x10000000 +#define CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT 25 +#define CCSR_GUTS_CLKDVDR_PXCKDLY_MASK 0x06000000 +#define CCSR_GUTS_CLKDVDR_PXCKDLY(x) \ + (((x) & 3) << CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT) +#define CCSR_GUTS_CLKDVDR_PXCLK_SHIFT 16 +#define CCSR_GUTS_CLKDVDR_PXCLK_MASK 0x001F0000 +#define CCSR_GUTS_CLKDVDR_PXCLK(x) (((x) & 31) << CCSR_GUTS_CLKDVDR_PXCLK_SHIFT) +#define CCSR_GUTS_CLKDVDR_SSICLK_MASK 0x000000FF +#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK) + +#endif + +#endif +#endif diff --git a/arch/powerpc/include/asm/immap_86xx.h b/arch/powerpc/include/asm/immap_86xx.h deleted file mode 100644 index 0f165e59c326..000000000000 --- a/arch/powerpc/include/asm/immap_86xx.h +++ /dev/null @@ -1,156 +0,0 @@ -/** - * MPC86xx Internal Memory Map - * - * Authors: Jeff Brown - * Timur Tabi - * - * Copyright 2004,2007 Freescale Semiconductor, Inc - * - * 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 header file defines structures for various 86xx SOC devices that are - * used by multiple source files. - */ - -#ifndef __ASM_POWERPC_IMMAP_86XX_H__ -#define __ASM_POWERPC_IMMAP_86XX_H__ -#ifdef __KERNEL__ - -/* Global Utility Registers */ -struct ccsr_guts { - __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ - __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ - __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ - __be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */ - __be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */ - u8 res1[0x20 - 0x14]; - __be32 porcir; /* 0x.0020 - POR Configuration Information Register */ - u8 res2[0x30 - 0x24]; - __be32 gpiocr; /* 0x.0030 - GPIO Control Register */ - u8 res3[0x40 - 0x34]; - __be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */ - u8 res4[0x50 - 0x44]; - __be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */ - u8 res5[0x60 - 0x54]; - __be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */ - u8 res6[0x70 - 0x64]; - __be32 devdisr; /* 0x.0070 - Device Disable Control */ - __be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */ - u8 res7[0x80 - 0x78]; - __be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */ - u8 res8[0x90 - 0x84]; - __be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */ - __be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */ - u8 res9[0xA0 - 0x98]; - __be32 pvr; /* 0x.00a0 - Processor Version Register */ - __be32 svr; /* 0x.00a4 - System Version Register */ - u8 res10[0xB0 - 0xA8]; - __be32 rstcr; /* 0x.00b0 - Reset Control Register */ - u8 res11[0xC0 - 0xB4]; - __be32 elbcvselcr; /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */ - u8 res12[0x800 - 0xC4]; - __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */ - u8 res13[0x900 - 0x804]; - __be32 ircr; /* 0x.0900 - Infrared Control Register */ - u8 res14[0x908 - 0x904]; - __be32 dmacr; /* 0x.0908 - DMA Control Register */ - u8 res15[0x914 - 0x90C]; - __be32 elbccr; /* 0x.0914 - eLBC Control Register */ - u8 res16[0xB20 - 0x918]; - __be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */ - __be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */ - __be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */ - u8 res17[0xE00 - 0xB2C]; - __be32 clkocr; /* 0x.0e00 - Clock Out Select Register */ - u8 res18[0xE10 - 0xE04]; - __be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */ - u8 res19[0xE20 - 0xE14]; - __be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */ - u8 res20[0xF04 - 0xE24]; - __be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */ - __be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */ - u8 res21[0xF40 - 0xF0C]; - __be32 srds2cr0; /* 0x.0f40 - SerDes1 Control Register 0 */ - __be32 srds2cr1; /* 0x.0f44 - SerDes1 Control Register 0 */ -} __attribute__ ((packed)); - -#define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */ -#define CCSR_GUTS_DMACR_DEV_IR 1 /* DMA controller/channel set to IR */ - -/* - * Set the DMACR register in the GUTS - * - * The DMACR register determines the source of initiated transfers for each - * channel on each DMA controller. Rather than have a bunch of repetitive - * macros for the bit patterns, we just have a function that calculates - * them. - * - * guts: Pointer to GUTS structure - * co: The DMA controller (0 or 1) - * ch: The channel on the DMA controller (0, 1, 2, or 3) - * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx) - */ -static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts, - unsigned int co, unsigned int ch, unsigned int device) -{ - unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); - - clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift); -} - -#define CCSR_GUTS_PMUXCR_LDPSEL 0x00010000 -#define CCSR_GUTS_PMUXCR_SSI1_MASK 0x0000C000 /* Bitmask for SSI1 */ -#define CCSR_GUTS_PMUXCR_SSI1_LA 0x00000000 /* Latched address */ -#define CCSR_GUTS_PMUXCR_SSI1_HI 0x00004000 /* High impedance */ -#define CCSR_GUTS_PMUXCR_SSI1_SSI 0x00008000 /* Used for SSI1 */ -#define CCSR_GUTS_PMUXCR_SSI2_MASK 0x00003000 /* Bitmask for SSI2 */ -#define CCSR_GUTS_PMUXCR_SSI2_LA 0x00000000 /* Latched address */ -#define CCSR_GUTS_PMUXCR_SSI2_HI 0x00001000 /* High impedance */ -#define CCSR_GUTS_PMUXCR_SSI2_SSI 0x00002000 /* Used for SSI2 */ -#define CCSR_GUTS_PMUXCR_LA_22_25_LA 0x00000000 /* Latched Address */ -#define CCSR_GUTS_PMUXCR_LA_22_25_HI 0x00000400 /* High impedance */ -#define CCSR_GUTS_PMUXCR_DBGDRV 0x00000200 /* Signals not driven */ -#define CCSR_GUTS_PMUXCR_DMA2_0 0x00000008 -#define CCSR_GUTS_PMUXCR_DMA2_3 0x00000004 -#define CCSR_GUTS_PMUXCR_DMA1_0 0x00000002 -#define CCSR_GUTS_PMUXCR_DMA1_3 0x00000001 - -/* - * Set the DMA external control bits in the GUTS - * - * The DMA external control bits in the PMUXCR are only meaningful for - * channels 0 and 3. Any other channels are ignored. - * - * guts: Pointer to GUTS structure - * co: The DMA controller (0 or 1) - * ch: The channel on the DMA controller (0, 1, 2, or 3) - * value: the new value for the bit (0 or 1) - */ -static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, - unsigned int co, unsigned int ch, unsigned int value) -{ - if ((ch == 0) || (ch == 3)) { - unsigned int shift = 2 * (co + 1) - (ch & 1) - 1; - - clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift); - } -} - -#define CCSR_GUTS_CLKDVDR_PXCKEN 0x80000000 -#define CCSR_GUTS_CLKDVDR_SSICKEN 0x20000000 -#define CCSR_GUTS_CLKDVDR_PXCKINV 0x10000000 -#define CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT 25 -#define CCSR_GUTS_CLKDVDR_PXCKDLY_MASK 0x06000000 -#define CCSR_GUTS_CLKDVDR_PXCKDLY(x) \ - (((x) & 3) << CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT) -#define CCSR_GUTS_CLKDVDR_PXCLK_SHIFT 16 -#define CCSR_GUTS_CLKDVDR_PXCLK_MASK 0x001F0000 -#define CCSR_GUTS_CLKDVDR_PXCLK(x) (((x) & 31) << CCSR_GUTS_CLKDVDR_PXCLK_SHIFT) -#define CCSR_GUTS_CLKDVDR_SSICLK_MASK 0x000000FF -#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK) - -#endif /* __ASM_POWERPC_IMMAP_86XX_H__ */ -#endif /* __KERNEL__ */ diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 64f65910a7d7..51b089f9751c 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -24,8 +24,6 @@ #include #include -#include - #include "fsl_ssi.h" /** diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 5ba823213abe..38339c158ed9 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "fsl_dma.h" #include "fsl_ssi.h" @@ -57,9 +57,9 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device) struct snd_soc_card *card = platform_get_drvdata(sound_device); struct mpc8610_hpcd_data *machine_data = container_of(card, struct mpc8610_hpcd_data, card); - struct ccsr_guts __iomem *guts; + struct ccsr_guts_86xx __iomem *guts; - guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); + guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx)); if (!guts) { dev_err(card->dev, "could not map global utilities\n"); return -ENOMEM; @@ -142,9 +142,9 @@ static int mpc8610_hpcd_machine_remove(struct platform_device *sound_device) struct snd_soc_card *card = platform_get_drvdata(sound_device); struct mpc8610_hpcd_data *machine_data = container_of(card, struct mpc8610_hpcd_data, card); - struct ccsr_guts __iomem *guts; + struct ccsr_guts_86xx __iomem *guts; - guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); + guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx)); if (!guts) { dev_err(card->dev, "could not map global utilities\n"); return -ENOMEM; -- cgit v1.2.3-59-g8ed1b From 1a3c5a491af6756dbba6ee166a9dee72bb414ba8 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 2 Aug 2010 12:44:36 -0500 Subject: asoc/multi-component: fsl: add support for 36-bit physical addresses Update the DMA driver used by the Freescale MPC8610 HPCD audio driver to support 36-bit physical addresses, for both DMA buffers and the SSI registers. The DMA driver calls snd_dma_alloc_pages() to allocate the DMA buffers for playback and capture. This function is just a front-end for dma_alloc_coherent(). Currently, dma_alloc_coherent() only allocates buffers in low memory (it ignores GFP_HIGHMEM), so we never actually get a DMA buffer with a real 36-bit physical address. Signed-off-by: Timur Tabi Signed-off-by: Liam Girdwood --- sound/soc/fsl/fsl_dma.c | 77 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index d09e1941b1fa..4450f9d845c6 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -175,13 +175,23 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private) struct fsl_dma_link_descriptor *link = &dma_private->link[dma_private->current_link]; - /* Update our link descriptors to point to the next period */ - if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - link->source_addr = - cpu_to_be32(dma_private->dma_buf_next); - else - link->dest_addr = - cpu_to_be32(dma_private->dma_buf_next); + /* Update our link descriptors to point to the next period. On a 36-bit + * system, we also need to update the ESAD bits. We also set (keep) the + * snoop bits. See the comments in fsl_dma_hw_params() about snooping. + */ + if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + link->source_addr = cpu_to_be32(dma_private->dma_buf_next); +#ifdef CONFIG_PHYS_64BIT + link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | + upper_32_bits(dma_private->dma_buf_next)); +#endif + } else { + link->dest_addr = cpu_to_be32(dma_private->dma_buf_next); +#ifdef CONFIG_PHYS_64BIT + link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | + upper_32_bits(dma_private->dma_buf_next)); +#endif + } /* Update our variables for next time */ dma_private->dma_buf_next += dma_private->period_size; @@ -273,11 +283,19 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) * This function is called when the codec driver calls snd_soc_new_pcms(), * once for each .dai_link in the machine driver's snd_soc_card * structure. + * + * snd_dma_alloc_pages() is just a front-end to dma_alloc_coherent(), which + * (currently) always allocates the DMA buffer in lowmem, even if GFP_HIGHMEM + * is specified. Therefore, any DMA buffers we allocate will always be in low + * memory, but we support for 36-bit physical addresses anyway. + * + * Regardless of where the memory is actually allocated, since the device can + * technically DMA to any 36-bit address, we do need to set the DMA mask to 36. */ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { - static u64 fsl_dma_dmamask = DMA_BIT_MASK(32); + static u64 fsl_dma_dmamask = DMA_BIT_MASK(36); int ret; if (!card->dev->dma_mask) @@ -609,12 +627,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, link->count = cpu_to_be32(period_size); - /* Even though the DMA controller supports 36-bit addressing, - * for simplicity we allow only 32-bit addresses for the audio - * buffer itself. This was enforced in fsl_dma_new() with the - * DMA mask. - * - * The snoop bit tells the DMA controller whether it should tell + /* The snoop bit tells the DMA controller whether it should tell * the ECM to snoop during a read or write to an address. For * audio, we use DMA to transfer data between memory and an I/O * device (the SSI's STX0 or SRX0 register). Snooping is only @@ -629,20 +642,24 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, * flush out the data for the previous period. So if you * increased period_bytes_min to a large enough size, you might * get more performance by not snooping, and you'll still be - * okay. + * okay. You'll need to update fsl_dma_update_pointers() also. */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { link->source_addr = cpu_to_be32(temp_addr); - link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); + link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | + upper_32_bits(temp_addr)); link->dest_addr = cpu_to_be32(ssi_sxx_phys); - link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); + link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP | + upper_32_bits(ssi_sxx_phys)); } else { link->source_addr = cpu_to_be32(ssi_sxx_phys); - link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); + link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP | + upper_32_bits(ssi_sxx_phys)); link->dest_addr = cpu_to_be32(temp_addr); - link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); + link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | + upper_32_bits(temp_addr)); } temp_addr += period_size; @@ -673,10 +690,23 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream) dma_addr_t position; snd_pcm_uframes_t frames; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + /* Obtain the current DMA pointer, but don't read the ESAD bits if we + * only have 32-bit DMA addresses. This function is typically called + * in interrupt context, so we need to optimize it. + */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { position = in_be32(&dma_channel->sar); - else +#ifdef CONFIG_PHYS_64BIT + position |= (u64)(in_be32(&dma_channel->satr) & + CCSR_DMA_ATR_ESAD_MASK) << 32; +#endif + } else { position = in_be32(&dma_channel->dar); +#ifdef CONFIG_PHYS_64BIT + position |= (u64)(in_be32(&dma_channel->datr) & + CCSR_DMA_ATR_ESAD_MASK) << 32; +#endif + } /* * When capture is started, the SSI immediately starts to fill its FIFO. @@ -936,11 +966,6 @@ static void __exit fsl_soc_dma_exit(void) of_unregister_platform_driver(&fsl_soc_dma_driver); } -/* We want the DMA driver to be initialized before the SSI driver, so that - * when the SSI driver calls fsl_soc_dma_dai_from_node(), the DMA driver - * will already have been probed. The easiest way to do that is to make the - * __init function called via arch_initcall(). - */ module_init(fsl_soc_dma_init); module_exit(fsl_soc_dma_exit); -- cgit v1.2.3-59-g8ed1b From 87a0632b29410bab5c1783d7eb979c8d942d4209 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 3 Aug 2010 17:55:28 -0500 Subject: asoc/multi-component: fsl: fix exit and error paths in DMA and SSI drivers The error handling code in the OF probe function of the SSI driver is not freeing all resources correctly. Since the machine driver no longer calls the DMA driver to provide information about the SSI, we don't need to keep a list of DMA objects any more. In addition, the fsl_soc_dma_remove() function is incorrectly removing *all* DMA objects when it should only remove one. Signed-off-by: Timur Tabi Signed-off-by: Liam Girdwood --- sound/soc/fsl/fsl_dma.c | 23 +++++++---------------- sound/soc/fsl/fsl_ssi.c | 29 ++++++++++++++++------------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 4450f9d845c6..57774cb91ae3 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -57,7 +57,6 @@ SNDRV_PCM_RATE_CONTINUOUS) struct dma_object { - struct list_head list; struct snd_soc_platform_driver dai; dma_addr_t ssi_stx_phys; dma_addr_t ssi_srx_phys; @@ -825,9 +824,6 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm) } } -/* List of DMA nodes that we've probed */ -static LIST_HEAD(dma_list); - /** * find_ssi_node -- returns the SSI node that points to his DMA channel node * @@ -915,25 +911,20 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, dma->channel = of_iomap(np, 0); dma->irq = irq_of_parse_and_map(np, 0); - list_add(&dma->list, &dma_list); + + dev_set_drvdata(&of_dev->dev, dma); return 0; } static int __devexit fsl_soc_dma_remove(struct of_device *of_dev) { - struct list_head *n, *ptr; - struct dma_object *dma; + struct dma_object *dma = dev_get_drvdata(&of_dev->dev); - list_for_each_safe(ptr, n, &dma_list) { - dma = list_entry(ptr, struct dma_object, list); - list_del_init(ptr); - - snd_soc_unregister_platform(&of_dev->dev); - iounmap(dma->channel); - irq_dispose_mapping(dma->irq); - kfree(dma); - } + snd_soc_unregister_platform(&of_dev->dev); + iounmap(dma->channel); + irq_dispose_mapping(dma->irq); + kfree(dma); return 0; } diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 51b089f9751c..00e3e625b52a 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -619,7 +619,7 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev, { struct fsl_ssi_private *ssi_private; int ret = 0; - struct device_attribute *dev_attr; + struct device_attribute *dev_attr = NULL; struct device_node *np = of_dev->dev.of_node; const char *p, *sprop; struct resource res; @@ -681,18 +681,16 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev, if (ret) { dev_err(&of_dev->dev, "could not create sysfs %s file\n", ssi_private->dev_attr.attr.name); - kfree(ssi_private); - return ret; + goto error; } /* Register with ASoC */ dev_set_drvdata(&of_dev->dev, ssi_private); ret = snd_soc_register_dai(&of_dev->dev, &ssi_private->cpu_dai_drv); - if (ret != 0) { + if (ret) { dev_err(&of_dev->dev, "failed to register DAI: %d\n", ret); - kfree(ssi_private); - return ret; + goto error; } /* Trigger the machine driver's probe function. The platform driver @@ -713,18 +711,23 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev, if (IS_ERR(ssi_private->pdev)) { ret = PTR_ERR(ssi_private->pdev); dev_err(&of_dev->dev, "failed to register platform: %d\n", ret); - kfree(ssi_private); - return ret; + goto error; } return 0; + +error: + snd_soc_unregister_dai(&of_dev->dev); + dev_set_drvdata(&of_dev->dev, NULL); + if (dev_attr) + device_remove_file(&of_dev->dev, dev_attr); + irq_dispose_mapping(ssi_private->irq); + iounmap(ssi_private->ssi); + kfree(ssi_private); + + return ret; } -/** - * fsl_ssi_destroy_dai: destroy the snd_soc_dai object - * - * This function undoes the operations of fsl_ssi_probe() - */ static int fsl_ssi_remove(struct of_device *of_dev) { struct fsl_ssi_private *ssi_private = dev_get_drvdata(&of_dev->dev); -- cgit v1.2.3-59-g8ed1b From ff71334a46844d0ae6ff0055c549790bcd27bb10 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Wed, 4 Aug 2010 17:51:08 -0500 Subject: asoc/multi-component: fsl: add support for disabled SSI nodes Add support for adding "status = disabled" to an SSI node to incidate that it is not wired on the board. This replaces the not-so-intuitive previous method of omitting a codec-handle property. Signed-off-by: Timur Tabi Acked-by: Kumar Gala Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- arch/powerpc/boot/dts/mpc8610_hpcd.dts | 1 + sound/soc/fsl/fsl_ssi.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts index 9535ce68caae..83c3218cb4da 100644 --- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts +++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts @@ -286,6 +286,7 @@ ssi@16100 { compatible = "fsl,mpc8610-ssi"; + status = "disabled"; cell-index = <1>; reg = <0x16100 0x100>; interrupt-parent = <&mpic>; diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 00e3e625b52a..7939c337ed9d 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -625,12 +625,19 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev, struct resource res; char name[64]; - /* We are only interested in SSIs with a codec phandle in them, so let's - * make sure this SSI has one. + /* SSIs that are not connected on the board should have a + * status = "disabled" + * property in their device tree nodes. */ - if (!of_get_property(np, "codec-handle", NULL)) + if (!of_device_is_available(np)) return -ENODEV; + /* Check for a codec-handle property. */ + if (!of_get_property(np, "codec-handle", NULL)) { + dev_err(&of_dev->dev, "missing codec-handle property\n"); + return -ENODEV; + } + /* We only support the SSI in "I2S Slave" mode */ sprop = of_get_property(np, "fsl,mode", NULL); if (!sprop || strcmp(sprop, "i2s-slave")) { -- cgit v1.2.3-59-g8ed1b From 26e277d7151abcef8efa1e6f1f0d1420d4ed17c6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Aug 2010 10:57:04 +0100 Subject: ASoC: Remove version display from WM8510 driver Signed-off-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/wm8510.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index dbfa05d2cb92..1c623de4a4cd 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -29,8 +29,6 @@ #include "wm8510.h" -#define WM8510_VERSION "0.6" - /* * wm8510 register cache * We can't read the WM8510 register space when we are @@ -563,8 +561,6 @@ static int wm8510_probe(struct snd_soc_codec *codec) struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); int ret; - pr_info("WM8510 Audio Codec %s", WM8510_VERSION); - codec->control_data = wm8510->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type); if (ret < 0) { -- cgit v1.2.3-59-g8ed1b From af3751a0bfe4d461e0567961dc06448f2128e26f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Aug 2010 11:04:14 +0100 Subject: ASoC: Remove unneeded control_data management from Wolfson drivers Now soc-cache.c can figure out the I2C and SPI control data from the device for the CODEC we don't need to manually assign it in drivers. Signed-off-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/wm8510.c | 4 ---- sound/soc/codecs/wm8523.c | 3 --- sound/soc/codecs/wm8580.c | 3 --- sound/soc/codecs/wm8711.c | 4 ---- sound/soc/codecs/wm8728.c | 4 ---- sound/soc/codecs/wm8731.c | 4 ---- sound/soc/codecs/wm8741.c | 3 --- sound/soc/codecs/wm8750.c | 4 ---- sound/soc/codecs/wm8753.c | 6 +----- sound/soc/codecs/wm8776.c | 4 ---- sound/soc/codecs/wm8900.c | 4 ---- sound/soc/codecs/wm8903.c | 3 --- sound/soc/codecs/wm8955.c | 3 --- sound/soc/codecs/wm8961.c | 3 --- sound/soc/codecs/wm8971.c | 3 --- sound/soc/codecs/wm8974.c | 3 --- sound/soc/codecs/wm8988.c | 4 ---- sound/soc/codecs/wm8990.c | 4 ---- sound/soc/codecs/wm8993.c | 3 --- 19 files changed, 1 insertion(+), 68 deletions(-) diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 1c623de4a4cd..d00da2001a12 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -60,7 +60,6 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { /* codec private data */ struct wm8510_priv { enum snd_soc_control_type control_type; - void *control_data; }; static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; @@ -561,7 +560,6 @@ static int wm8510_probe(struct snd_soc_codec *codec) struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = wm8510->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type); if (ret < 0) { printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); @@ -611,7 +609,6 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi) if (wm8510 == NULL) return -ENOMEM; - wm8510->control_data = spi; wm8510->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8510); @@ -651,7 +648,6 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8510); - wm8510->control_data = i2c; wm8510->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 58d411b6faaf..712ef7c76f90 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -41,7 +41,6 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { /* codec private data */ struct wm8523_priv { enum snd_soc_control_type control_type; - void *control_data; u16 reg_cache[WM8523_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; unsigned int sysclk; @@ -419,7 +418,6 @@ static int wm8523_probe(struct snd_soc_codec *codec) int ret, i; codec->hw_write = (hw_write_t)i2c_master_send; - codec->control_data = wm8523->control_data; wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; wm8523->rate_constraint.count = ARRAY_SIZE(wm8523->rate_constraint_list); @@ -528,7 +526,6 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8523); - wm8523->control_data = i2c; wm8523->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index cae58941a32f..39ad46c41e8a 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -200,7 +200,6 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { /* codec private data */ struct wm8580_priv { enum snd_soc_control_type control_type; - void *control_data; struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; u16 reg_cache[WM8580_MAX_REGISTER + 1]; struct pll_state a; @@ -778,7 +777,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); int ret = 0,i; - codec->control_data = wm8580->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -858,7 +856,6 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8580); - wm8580->control_data = i2c; wm8580->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 8d942b3b111f..f8d9c60e7fad 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -34,7 +34,6 @@ /* codec private data */ struct wm8711_priv { enum snd_soc_control_type bus_type; - void *control_data; u16 reg_cache[WM8711_CACHEREGNUM]; unsigned int sysclk; }; @@ -378,7 +377,6 @@ static int wm8711_probe(struct snd_soc_codec *codec) struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); int ret, reg; - codec->control_data = wm8711->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -436,7 +434,6 @@ static int __devinit wm8711_spi_probe(struct spi_device *spi) return -ENOMEM; spi_set_drvdata(spi, wm8711); - wm8711->control_data = spi; wm8711->bus_type = SND_SOC_SPI; ret = snd_soc_register_codec(&spi->dev, @@ -476,7 +473,6 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client, return -ENOMEM; i2c_set_clientdata(client, wm8711); - wm8711->control_data = client; wm8711->bus_type = SND_SOC_I2C; ret = snd_soc_register_codec(&client->dev, diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index ae2292444783..5e5a1625194c 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -45,7 +45,6 @@ static const u16 wm8728_reg_defaults[] = { /* codec private data */ struct wm8728_priv { enum snd_soc_control_type control_type; - void *control_data; }; static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); @@ -244,7 +243,6 @@ static int wm8728_probe(struct snd_soc_codec *codec) struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = wm8728->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type); if (ret < 0) { printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", @@ -289,7 +287,6 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi) if (wm8728 == NULL) return -ENOMEM; - wm8728->control_data = spi; wm8728->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8728); @@ -330,7 +327,6 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8728); - wm8728->control_data = i2c; wm8728->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 7da360ee1fee..19844fc8cb1d 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -43,7 +43,6 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { /* codec private data */ struct wm8731_priv { enum snd_soc_control_type control_type; - void *control_data; struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; u16 reg_cache[WM8731_CACHEREGNUM]; unsigned int sysclk; @@ -463,7 +462,6 @@ static int wm8731_probe(struct snd_soc_codec *codec) int ret = 0, i; codec->bias_level = SND_SOC_BIAS_OFF, - codec->control_data = wm8731->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type); if (ret < 0) { @@ -557,7 +555,6 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi) if (wm8731 == NULL) return -ENOMEM; - wm8731->control_data = spi; wm8731->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8731); @@ -598,7 +595,6 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8731); - wm8731->control_data = i2c; wm8731->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 0c6d59e4d226..782fe539662b 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -41,7 +41,6 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { /* codec private data */ struct wm8741_priv { enum snd_soc_control_type control_type; - void *control_data; u16 reg_cache[WM8741_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; @@ -347,7 +346,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); int ret = 0; - codec->control_data = wm8741->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -415,7 +413,6 @@ static int wm8741_i2c_probe(struct i2c_client *i2c, } i2c_set_clientdata(i2c, wm8741); - wm8741->control_data = i2c; wm8741->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 89863a5bc830..92d4b2aef93b 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -53,7 +53,6 @@ static const u16 wm8750_reg[] = { struct wm8750_priv { unsigned int sysclk; enum snd_soc_control_type control_type; - void *control_data; u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; }; @@ -697,7 +696,6 @@ static int wm8750_probe(struct snd_soc_codec *codec) struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); int reg, ret; - codec->control_data = wm8750->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type); if (ret < 0) { printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); @@ -764,7 +762,6 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi) if (wm8750 == NULL) return -ENOMEM; - wm8750->control_data = spi; wm8750->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8750); @@ -805,7 +802,6 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8750); - wm8750->control_data = i2c; wm8750->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 976e408b3616..484423248c26 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -86,7 +86,6 @@ static const u16 wm8753_reg[] = { /* codec private data */ struct wm8753_priv { enum snd_soc_control_type control_type; - void *control_data; unsigned int sysclk; unsigned int pcmclk; u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; @@ -1551,8 +1550,7 @@ static int wm8753_probe(struct snd_soc_codec *codec) struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); int ret = 0, reg; - codec->bias_level = SND_SOC_BIAS_OFF, - codec->control_data = wm8753->control_data; + codec->bias_level = SND_SOC_BIAS_OFF; INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type); @@ -1637,7 +1635,6 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi) if (wm8753 == NULL) return -ENOMEM; - wm8753->control_data = spi; wm8753->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8753); @@ -1678,7 +1675,6 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8753); - wm8753->control_data = i2c; wm8753->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 51a2d265d40e..053030679c1a 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -34,7 +34,6 @@ /* codec private data */ struct wm8776_priv { enum snd_soc_control_type control_type; - void *control_data; u16 reg_cache[WM8776_CACHEREGNUM]; int sysclk[2]; }; @@ -415,7 +414,6 @@ static int wm8776_probe(struct snd_soc_codec *codec) struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); int ret = 0; - codec->control_data = wm8776->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -472,7 +470,6 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi) if (wm8776 == NULL) return -ENOMEM; - wm8776->control_data = spi; wm8776->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8776); @@ -513,7 +510,6 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8776); - wm8776->control_data = i2c; wm8776->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 33c3b57f3f66..1378aab5ca75 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -140,7 +140,6 @@ struct wm8900_priv { enum snd_soc_control_type control_type; - void *control_data; u16 reg_cache[WM8900_MAXREG]; u32 fll_in; /* FLL input frequency */ @@ -1189,7 +1188,6 @@ static int wm8900_probe(struct snd_soc_codec *codec) struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); int ret = 0, reg; - codec->control_data = wm8900->control_data; ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -1273,7 +1271,6 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi) if (wm8900 == NULL) return -ENOMEM; - wm8900->control_data = spi; wm8900->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8900); @@ -1314,7 +1311,6 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8900); - wm8900->control_data = i2c; wm8900->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index f5d73ed72cbd..622b60238a82 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -217,7 +217,6 @@ struct wm8903_priv { u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)]; int sysclk; - struct i2c_client *control_data; int irq; /* Reference counts */ @@ -1639,7 +1638,6 @@ static int wm8903_probe(struct snd_soc_codec *codec) u16 val; init_completion(&wm8903->wseq); - codec->control_data = wm8903->control_data; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret != 0) { @@ -1779,7 +1777,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8903); - wm8903->control_data = i2c; wm8903->irq = i2c->irq; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index a5a9f8ef5771..f89ad6c9a80b 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -41,7 +41,6 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { /* codec private data */ struct wm8955_priv { enum snd_soc_control_type control_type; - void *control_data; u16 reg_cache[WM8955_MAX_REGISTER + 1]; @@ -904,7 +903,6 @@ static int wm8955_probe(struct snd_soc_codec *codec) struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); int ret, i; - codec->control_data = wm8955->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -1004,7 +1002,6 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8955); - wm8955->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8955, &wm8955_dai, 1); diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 5ebe2c04e5cf..fa36a62972f8 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -289,7 +289,6 @@ static u16 wm8961_reg_defaults[] = { struct wm8961_priv { enum snd_soc_control_type control_type; - void *control_data; int sysclk; u16 reg_cache[WM8961_MAX_REGISTER]; }; @@ -964,7 +963,6 @@ static int wm8961_probe(struct snd_soc_codec *codec) int ret = 0; u16 reg; - codec->control_data = wm8961->control_data; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -1096,7 +1094,6 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8961); - wm8961->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8961, &wm8961_dai, 1); diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index ad2692afbb31..1d460735c4d3 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -39,7 +39,6 @@ static struct workqueue_struct *wm8971_workq = NULL; /* codec private data */ struct wm8971_priv { enum snd_soc_control_type control_type; - void *control_data; unsigned int sysclk; }; @@ -642,7 +641,6 @@ static int wm8971_probe(struct snd_soc_codec *codec) pr_info("WM8971 Audio Codec %s", WM8971_VERSION); - codec->control_data = wm8971->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type); if (ret < 0) { printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); @@ -725,7 +723,6 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8971); - wm8971->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8971, &wm8971_dai, 1); diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 52f631c62e29..e61728b7339f 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -52,7 +52,6 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { struct wm8974_priv { enum snd_soc_control_type control_type; - void *control_data; u16 reg_cache[WM8974_CACHEREGNUM]; }; @@ -611,7 +610,6 @@ static int wm8974_probe(struct snd_soc_codec *codec) struct wm8974_priv *wm8974 = snd_soc_codec_get_drvdata(codec); int ret = 0; - codec->control_data = wm8974->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -662,7 +660,6 @@ static __devinit int wm8974_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8974); - wm8974->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8974, &wm8974_dai, 1); diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index ecbffcea71db..d070a58e4f8e 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -53,7 +53,6 @@ static const u16 wm8988_reg[] = { struct wm8988_priv { unsigned int sysclk; enum snd_soc_control_type control_type; - void *control_data; struct snd_pcm_hw_constraint_list *sysclk_constraints; u16 reg_cache[WM8988_NUM_REG]; }; @@ -763,7 +762,6 @@ static int wm8988_probe(struct snd_soc_codec *codec) int ret = 0; u16 reg; - codec->control_data = wm8988->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -826,7 +824,6 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi) if (wm8988 == NULL) return -ENOMEM; - wm8988->control_data = spi; wm8988->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8988); @@ -867,7 +864,6 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8988); - wm8988->control_data = i2c; wm8988->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index b25243382966..0ffecbd1e33b 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -33,7 +33,6 @@ /* codec private data */ struct wm8990_priv { enum snd_soc_control_type control_type; - void *control_data; unsigned int sysclk; unsigned int pcmclk; }; @@ -1343,11 +1342,9 @@ static int wm8990_resume(struct snd_soc_codec *codec) */ static int wm8990_probe(struct snd_soc_codec *codec) { - struct wm8990_priv *wm8990 = snd_soc_codec_get_drvdata(codec); int ret; u16 reg; - codec->control_data = wm8990->control_data; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret < 0) { printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); @@ -1410,7 +1407,6 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8990); - wm8990->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8990, &wm8990_dai, 1); diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 1d9e1837a2df..a3fd6b935804 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -230,7 +230,6 @@ struct wm8993_priv { struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; struct wm8993_platform_data pdata; enum snd_soc_control_type control_type; - void *control_data; int master; int sysclk_source; int tdm_slots; @@ -1425,7 +1424,6 @@ static int wm8993_probe(struct snd_soc_codec *codec) struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); int ret, i, val; - codec->control_data = wm8993->control_data; wm8993->hubs_data.hp_startup_mode = 1; wm8993->hubs_data.dcs_codes = -2; @@ -1606,7 +1604,6 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8993); - wm8993->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8993, &wm8993_dai, 1); -- cgit v1.2.3-59-g8ed1b From 38445af3bc0658615fd9a724fbcb67148eac2cd3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Aug 2010 10:57:05 +0100 Subject: ASoC: Remove version display from WM8971 driver Signed-off-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/wm8971.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 1d460735c4d3..63f6dbf5d070 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -30,8 +30,6 @@ #include "wm8971.h" -#define WM8971_VERSION "0.9" - #define WM8971_REG_COUNT 43 static struct workqueue_struct *wm8971_workq = NULL; @@ -639,8 +637,6 @@ static int wm8971_probe(struct snd_soc_codec *codec) int ret = 0; u16 reg; - pr_info("WM8971 Audio Codec %s", WM8971_VERSION); - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type); if (ret < 0) { printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); -- cgit v1.2.3-59-g8ed1b From 960d0697919aef453273e3a0ccc87daf52d808ac Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Aug 2010 11:02:19 +0100 Subject: ASoC: Add MODULE_ALIAS to Samsung DAI drivers Signed-off-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/s3c24xx/s3c-ac97.c | 1 + sound/soc/s3c24xx/s3c-dma.c | 1 + sound/soc/s3c24xx/s3c-pcm.c | 1 + sound/soc/s3c24xx/s3c2412-i2s.c | 1 + sound/soc/s3c24xx/s3c24xx-i2s.c | 1 + sound/soc/s3c24xx/s3c64xx-i2s-v4.c | 1 + sound/soc/s3c24xx/s3c64xx-i2s.c | 1 + 7 files changed, 7 insertions(+) diff --git a/sound/soc/s3c24xx/s3c-ac97.c b/sound/soc/s3c24xx/s3c-ac97.c index 86f4a9b4a869..26f4ed90a0ee 100644 --- a/sound/soc/s3c24xx/s3c-ac97.c +++ b/sound/soc/s3c24xx/s3c-ac97.c @@ -513,3 +513,4 @@ module_exit(s3c_ac97_exit); MODULE_AUTHOR("Jaswinder Singh, "); MODULE_DESCRIPTION("AC97 driver for the Samsung SoC"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c-ac97"); diff --git a/sound/soc/s3c24xx/s3c-dma.c b/sound/soc/s3c24xx/s3c-dma.c index 9f91b2d51454..54bff83c98b4 100644 --- a/sound/soc/s3c24xx/s3c-dma.c +++ b/sound/soc/s3c24xx/s3c-dma.c @@ -500,3 +500,4 @@ module_exit(snd_s3c24xx_pcm_exit); MODULE_AUTHOR("Ben Dooks, "); MODULE_DESCRIPTION("Samsung S3C Audio DMA module"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c24xx-pcm-audio"); diff --git a/sound/soc/s3c24xx/s3c-pcm.c b/sound/soc/s3c24xx/s3c-pcm.c index 653ffa270915..6174e26e433e 100644 --- a/sound/soc/s3c24xx/s3c-pcm.c +++ b/sound/soc/s3c24xx/s3c-pcm.c @@ -543,3 +543,4 @@ module_exit(s3c_pcm_exit); MODULE_AUTHOR("Jaswinder Singh, "); MODULE_DESCRIPTION("S3C PCM Controller Driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:samsung-pcm-audio"); diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c index acd00962ac36..4a861cfa52c5 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.c +++ b/sound/soc/s3c24xx/s3c2412-i2s.c @@ -209,3 +209,4 @@ module_exit(s3c2412_i2s_exit); MODULE_AUTHOR("Ben Dooks, "); MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c2412-iis"); diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c index 1d0bade10d3d..e060daaa458f 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c @@ -516,3 +516,4 @@ module_exit(s3c24xx_i2s_exit); MODULE_AUTHOR("Ben Dooks, "); MODULE_DESCRIPTION("s3c24xx I2S SoC Interface"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c24xx-iis"); diff --git a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c index 7cab4fcf1f12..a13415a85a45 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c @@ -216,3 +216,4 @@ module_exit(s3c64xx_i2sv4_exit); MODULE_AUTHOR("Jaswinder Singh, "); MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c64xx-iis-v4"); diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index a1d0b2566416..ae7acb6c4f1d 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c @@ -239,3 +239,4 @@ module_exit(s3c64xx_i2s_exit); MODULE_AUTHOR("Ben Dooks, "); MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c64xx-iis"); -- cgit v1.2.3-59-g8ed1b From a6d14342dc46f0ef94cccf323fd9481de84b458f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Aug 2010 10:59:15 +0100 Subject: ASoC: Automatically determine control_data for soc-cache users Since the provision of a struct device for the CODEC is now mandatory we can use container_of() to locate the struct i2c_client and struct spi_device for relevant devices, removing the need to manually set it in each driver. A further patch will automate selection of the control type based on the bus_type of the struct device, further reducing the amount of driver code required. Signed-off-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/soc-cache.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 83cd8ed944bf..b856177ea281 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -584,11 +584,19 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, #endif if (io_types[i].i2c_read) codec->hw_read = io_types[i].i2c_read; + + codec->control_data = container_of(codec->dev, + struct i2c_client, + dev); break; case SND_SOC_SPI: if (io_types[i].spi_write) codec->hw_write = io_types[i].spi_write; + + codec->control_data = container_of(codec->dev, + struct spi_device, + dev); break; } -- cgit v1.2.3-59-g8ed1b From 5dcba5d6741d4533e0ef696507f93f2a4c738efb Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 12 Aug 2010 09:29:52 +0300 Subject: ASoC: multi-component: TWL4030: Restore registers on removal Add back the register restore call, when the codec driver is removed. This does not affect normal operation, but it is usefull when debugging audio through the twl4030 class codecs. Signed-off-by: Peter Ujfalusi Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/twl4030.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 898430f44f9d..c7ee1a4c9d99 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -2258,6 +2258,8 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec) static int twl4030_soc_remove(struct snd_soc_codec *codec) { + /* Reset registers to their chip default before leaving */ + twl4030_reset_registers(codec); twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -- cgit v1.2.3-59-g8ed1b From 54d8d0aeb96e677c129918b391b9e74d48e65294 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Aug 2010 15:02:11 +0100 Subject: ASoC: Update WM8962 to build with multi-component No notable changes, currently build tested only. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 168 +++++++++++++--------------------------------- sound/soc/codecs/wm8962.h | 3 - 2 files changed, 47 insertions(+), 124 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index ea8940e80263..58ba2d3ca533 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -34,9 +34,6 @@ #include "wm8962.h" -static struct snd_soc_codec *wm8962_codec; -struct snd_soc_codec_device soc_codec_dev_wm8962; - #define WM8962_NUM_SUPPLIES 8 static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = { "DCVDD", @@ -51,7 +48,8 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = { /* codec private data */ struct wm8962_priv { - struct snd_soc_codec codec; + struct snd_soc_codec *codec; + u16 reg_cache[WM8962_MAX_REGISTER + 1]; int sysclk; @@ -85,7 +83,7 @@ static int wm8962_regulator_event_##n(struct notifier_block *nb, \ struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \ disable_nb[n]); \ if (event & REGULATOR_EVENT_DISABLE) { \ - wm8962->codec.cache_sync = 1; \ + wm8962->codec->cache_sync = 1; \ } \ return 0; \ } @@ -107,7 +105,7 @@ static int wm8962_volatile_register(unsigned int reg) return 0; } -static int wm8962_readable(unsigned int reg) +static int wm8962_readable_register(unsigned int reg) { if (wm8962_reg_access[reg].read) return 1; @@ -150,7 +148,8 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 *reg_cache = codec->reg_cache; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = wm8962->reg_cache; int ret; /* Apply the update (if any) */ @@ -178,7 +177,8 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 *reg_cache = codec->reg_cache; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = wm8962->reg_cache; int ret; /* Apply the update (if any) */ @@ -486,7 +486,8 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - u16 *reg_cache = codec->reg_cache; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = wm8962->reg_cache; int reg; switch (w->shift) { @@ -1071,8 +1072,7 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); int rate = params_rate(params); int i; @@ -1441,8 +1441,8 @@ static struct snd_soc_dai_ops wm8962_dai_ops = { .digital_mute = wm8962_mute, }; -struct snd_soc_dai wm8962_dai = { - .name = "WM8962", +static struct snd_soc_dai_driver wm8962_dai = { + .name = "wm8962", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -1460,52 +1460,10 @@ struct snd_soc_dai wm8962_dai = { .ops = &wm8962_dai_ops, .symmetric_rates = 1, }; -EXPORT_SYMBOL_GPL(wm8962_dai); - -static int wm8962_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8962_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8962_codec; - codec = wm8962_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - wm8962_add_widgets(codec); - - return ret; - -pcm_err: - return ret; -} - -static int wm8962_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} #ifdef CONFIG_PM -static int wm8962_resume(struct platform_device *pdev) +static int wm8962_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache; int i; @@ -1529,13 +1487,6 @@ static int wm8962_resume(struct platform_device *pdev) #define wm8962_resume NULL #endif -struct snd_soc_codec_device soc_codec_dev_wm8962 = { - .probe = wm8962_probe, - .remove = wm8962_remove, - .resume = wm8962_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8962); - #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) static int beep_rates[] = { 500, 1000, 2000, 4000, @@ -1545,7 +1496,7 @@ static void wm8962_beep_work(struct work_struct *work) { struct wm8962_priv *wm8962 = container_of(work, struct wm8962_priv, beep_work); - struct snd_soc_codec *codec = &wm8962->codec; + struct snd_soc_codec *codec = wm8962->codec; int i; int reg = 0; int best = 0; @@ -1676,40 +1627,19 @@ static void wm8962_free_beep(struct snd_soc_codec *codec) } #endif -static int wm8962_register(struct wm8962_priv *wm8962, - enum snd_soc_control_type control) +static int wm8962_probe(struct snd_soc_codec *codec) { int ret; - struct snd_soc_codec *codec = &wm8962->codec; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); int i; - if (wm8962_codec) { - dev_err(codec->dev, "Another WM8962 is registered\n"); - return -EINVAL; - } + wm8962->codec = codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - snd_soc_codec_set_drvdata(codec, wm8962); - codec->name = "WM8962"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8962_set_bias_level; - codec->dai = &wm8962_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8962_MAX_REGISTER; - codec->reg_cache = &wm8962->reg_cache; - codec->volatile_register = wm8962_volatile_register; codec->cache_sync = 1; codec->idle_bias_off = 1; - codec->readable_register = wm8962_readable; - memcpy(codec->reg_cache, wm8962_reg, sizeof(wm8962_reg)); - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, control); + ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); goto err; @@ -1814,22 +1744,9 @@ static int wm8962_register(struct wm8962_priv *wm8962, wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU; - wm8962_dai.dev = codec->dev; - - wm8962_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - return ret; - } - - ret = snd_soc_register_dai(&wm8962_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - return ret; - } + snd_soc_add_controls(codec, wm8962_snd_controls, + ARRAY_SIZE(wm8962_snd_controls)); + wm8962_add_widgets(codec); wm8962_init_beep(codec); @@ -1844,48 +1761,57 @@ err: return ret; } -static void wm8962_unregister(struct wm8962_priv *wm8962) +static int wm8962_remove(struct snd_soc_codec *codec) { + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); int i; - wm8962_free_beep(&wm8962->codec); - wm8962_set_bias_level(&wm8962->codec, SND_SOC_BIAS_OFF); + wm8962_free_beep(codec); for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) regulator_unregister_notifier(wm8962->supplies[i].consumer, &wm8962->disable_nb[i]); regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); - snd_soc_unregister_dai(&wm8962_dai); - snd_soc_unregister_codec(&wm8962->codec); - kfree(wm8962); - wm8962_codec = NULL; + + return 0; } +static struct snd_soc_codec_driver soc_codec_dev_wm8962 = { + .probe = wm8962_probe, + .remove = wm8962_remove, + .resume = wm8962_resume, + .set_bias_level = wm8962_set_bias_level, + .reg_cache_size = WM8962_MAX_REGISTER, + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8962_reg, + .volatile_register = wm8962_volatile_register, + .readable_register = wm8962_readable_register, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8962_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8962_priv *wm8962; - struct snd_soc_codec *codec; + int ret; wm8962 = kzalloc(sizeof(struct wm8962_priv), GFP_KERNEL); if (wm8962 == NULL) return -ENOMEM; - codec = &wm8962->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - i2c_set_clientdata(i2c, wm8962); - codec->control_data = i2c; - codec->dev = &i2c->dev; + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8962, &wm8962_dai, 1); + if (ret < 0) + kfree(wm8962); - return wm8962_register(wm8962, SND_SOC_I2C); + return ret; } static __devexit int wm8962_i2c_remove(struct i2c_client *client) { - struct wm8962_priv *wm8962 = i2c_get_clientdata(client); - wm8962_unregister(wm8962); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); return 0; } diff --git a/sound/soc/codecs/wm8962.h b/sound/soc/codecs/wm8962.h index bc0b1876174c..6145399acb16 100644 --- a/sound/soc/codecs/wm8962.h +++ b/sound/soc/codecs/wm8962.h @@ -15,9 +15,6 @@ #include -extern struct snd_soc_dai wm8962_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8962; - #define WM8962_SYSCLK_MCLK 1 #define WM8962_SYSCLK_FLL 2 #define WM8962_SYSCLK_PLL3 3 -- cgit v1.2.3-59-g8ed1b From 48bd3472d6512c74257706f7c38ad10a7117bac7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Aug 2010 15:02:36 +0100 Subject: ASoC: Staticise WM8727 codec driver structure Nothing should be referencing this any more. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8727.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c index 6a40080ba701..748808285119 100644 --- a/sound/soc/codecs/wm8727.c +++ b/sound/soc/codecs/wm8727.c @@ -43,7 +43,7 @@ static struct snd_soc_dai_driver wm8727_dai = { }, }; -struct snd_soc_codec_driver soc_codec_dev_wm8727; +static struct snd_soc_codec_driver soc_codec_dev_wm8727; static __devinit int wm8727_probe(struct platform_device *pdev) { -- cgit v1.2.3-59-g8ed1b From 381ac990db3f4fdfbe91e3a636cab03edf293b9c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Aug 2010 15:09:55 +0100 Subject: ASoC: Remove unused driver data from WM8961 probe Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8961.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index fa36a62972f8..bfc6578ed060 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -959,7 +959,6 @@ static struct snd_soc_dai_driver wm8961_dai = { static int wm8961_probe(struct snd_soc_codec *codec) { - struct wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec); int ret = 0; u16 reg; -- cgit v1.2.3-59-g8ed1b From 495311927ffbe3604e915aeafdf03325e9925b9d Mon Sep 17 00:00:00 2001 From: René Herman Date: Wed, 11 Aug 2010 13:08:06 +0200 Subject: ALSA: ISA: New Aztech Sound Galaxy driver This is a new driver for Aztech Sound Galaxy ISA soundcards based on the AZT1605 and AZT2316 chipsets. It's constructed as two seperate drivers for either chipset generated from the same source file, with (very) minimal ifdeffery. The drivers check the SB DSP version to decide if they are being loaded for the right chip. AZT1605 returns 2.1 by default and AZT2316 3.1. This isn't full-proof as the DSP version can actually be set through software but it's close enough -- as far as I've been able to see, the DSP version can not be stored in the EEPROM and the cards will therefore startup with the defaults. This distinction could (with the same success rate) also be used to decide which chip we're looking at at runtime meaning a single, merged driver is also an option but I feel it's actually nicer this way. A merged driver would have to postpone translating the passed in resource values to the card configuration until it knew which one it was looking at and would need to postpone erring out on mpu_irq=10 for azt1605 and mpu_irq=3 for azt2316. The drivers have been tested on various cards. For snd-azt1605: FCC-ID I38-MMSN811: Aztech Sound Galaxy Nova 16 Extra FCC-ID I38-MMSN822: Aztech Sound Galaxy Pro 16 II and for snd-azt2316: FCC-ID I38-MMSN824: Aztech Sound Galaxy Pro 16 AB FCC-ID I38-MMSN826: Trust Sound Expert DeLuxe Wave 32 (05201) FCC-ID I38-MMSN830: Trust Sound Expert DeLuxe 16+ (05202) FCC-ID I38-MMSN837: Packard Bell ISA Soundcard 030069 FCC-ID I38-MMSN846: Trust Sound Expert DeLuxe 16-3D (06300) FCC-ID I38-MMSN847: Trust Sound Expert DeLuxe Wave 32-3D (06301) FCC-ID I38-MMSN852: Aztech Sound Galaxy Waverider Pro 32-3D 826 and 846 were also marketed directly by Aztech and then known as: FCC-ID I38-MMSN826: Aztech Sound Galaxy Waverider 32+ FCC-ID I38-MMSN846: Aztech Sound Galaxy Nova 16 Extra II-3D Together, these cover the AZT1605 and AT2316A, AZT2316R and AZT2316-S chipsets. All cards work fully -- full-duplex PCM, MIDI and FM. Full duplex is a little flaky on some. I38-MSN811 tends to not work in full-duplex but sometimes does with the highest success rate being achieved when you first start the capture and then a playback instead of the other way around (it's a CS4231-KL codec). The cards with an AD1845XP codec (my I38-MMSN826 and one of my I38-MMSN830s) are also somewhat duplex-challenged. Sometimes full-duplex works, sometimes not and this varies from try to try. This seems likely to be a timing problem somewhere inside wss-lib. I38-MMSN826 has an additional "ICS2115 WaveFront" wavetable synth onboard that isn't supported yet. The wavetable synths on I38-MMSN847 and I38-MMSN852 are wired directly to the standard MPU-401 UART and the AUX1 input on the codec and work without problem. CD-ROM audio on the cards is routed to the codec "Line" input, Line-In to its Aux input, and FM/Wavetable to its AUX1 input. I did not rename the controls due to the capture source enumeration: I see that capture-source overrides are hardcoded in wss-lib and this is just too ugly to live. Versus the old snd-sgalaxy driver these drivers add support for the models without a configuration EEPROM (which are common), full-duplex, MPU-401 UART and OPL3. In the future they might grow support for that ICS2115 WaveFront synth on 826 and an hwdep interface to write to the EEPROM on the models that have one. Signed-off-by: Rene Herman Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 68 +++ sound/isa/Kconfig | 26 + sound/isa/Makefile | 2 +- sound/isa/galaxy/Makefile | 10 + sound/isa/galaxy/azt1605.c | 91 ++++ sound/isa/galaxy/azt2316.c | 111 ++++ sound/isa/galaxy/galaxy.c | 652 ++++++++++++++++++++++++ 7 files changed, 959 insertions(+), 1 deletion(-) create mode 100644 sound/isa/galaxy/Makefile create mode 100644 sound/isa/galaxy/azt1605.c create mode 100644 sound/isa/galaxy/azt2316.c create mode 100644 sound/isa/galaxy/galaxy.c diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 7f4dcebda9c6..e25555c02166 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -300,6 +300,74 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. control correctly. If you have problems regarding this, try another ALSA compliant mixer (alsamixer works). + Module snd-azt1605 + ------------------ + + Module for Aztech Sound Galaxy soundcards based on the Aztech AZT1605 + chipset. + + port - port # for BASE (0x220,0x240,0x260,0x280) + wss_port - port # for WSS (0x530,0x604,0xe80,0xf40) + irq - IRQ # for WSS (7,9,10,11) + dma1 - DMA # for WSS playback (0,1,3) + dma2 - DMA # for WSS capture (0,1), -1 = disabled (default) + mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default) + mpu_irq - IRQ # for MPU-401 UART (3,5,7,9), -1 = disabled (default) + fm_port - port # for OPL3 (0x388), -1 = disabled (default) + + This module supports multiple cards. It does not support autoprobe: port, + wss_port, irq and dma1 have to be specified. The other values are + optional. + + "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240) + or the value stored in the card's EEPROM for cards that have an EEPROM and + their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can + be choosen freely from the options enumerated above. + + If dma2 is specified and different from dma1, the card will operate in + full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to + enable capture since only channels 0 and 1 are available for capture. + + Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0 + mpu_port=0x330 mpu_irq=9 fm_port=0x388". + + Whatever IRQ and DMA channels you pick, be sure to reserve them for + legacy ISA in your BIOS. + + Module snd-azt2316 + ------------------ + + Module for Aztech Sound Galaxy soundcards based on the Aztech AZT2316 + chipset. + + port - port # for BASE (0x220,0x240,0x260,0x280) + wss_port - port # for WSS (0x530,0x604,0xe80,0xf40) + irq - IRQ # for WSS (7,9,10,11) + dma1 - DMA # for WSS playback (0,1,3) + dma2 - DMA # for WSS capture (0,1), -1 = disabled (default) + mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default) + mpu_irq - IRQ # for MPU-401 UART (5,7,9,10), -1 = disabled (default) + fm_port - port # for OPL3 (0x388), -1 = disabled (default) + + This module supports multiple cards. It does not support autoprobe: port, + wss_port, irq and dma1 have to be specified. The other values are + optional. + + "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240) + or the value stored in the card's EEPROM for cards that have an EEPROM and + their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can + be choosen freely from the options enumerated above. + + If dma2 is specified and different from dma1, the card will operate in + full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to + enable capture since only channels 0 and 1 are available for capture. + + Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0 + mpu_port=0x330 mpu_irq=9 fm_port=0x388". + + Whatever IRQ and DMA channels you pick, be sure to reserve them for + legacy ISA in your BIOS. + Module snd-aw2 -------------- diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index c6990c680796..f9aa13d8dacc 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -77,6 +77,32 @@ config SND_ALS100 To compile this driver as a module, choose M here: the module will be called snd-als100. +config SND_AZT1605 + tristate "Aztech AZT1605 Driver" + depends on SND + select SND_WSS_LIB + select SND_MPU401_UART + select SND_OPL3_LIB + help + Say Y here to include support for Aztech Sound Galaxy cards + based on the AZT1605 chipset. + + To compile this driver as a module, choose M here: the module + will be called snd-azt1605. + +config SND_AZT2316 + tristate "Aztech AZT2316 Driver" + depends on SND + select SND_WSS_LIB + select SND_MPU401_UART + select SND_OPL3_LIB + help + Say Y here to include support for Aztech Sound Galaxy cards + based on the AZT2316 chipset. + + To compile this driver as a module, choose M here: the module + will be called snd-azt2316. + config SND_AZT2320 tristate "Aztech Systems AZT2320" depends on PNP diff --git a/sound/isa/Makefile b/sound/isa/Makefile index c73d30c4f462..d2bd8f536dd8 100644 --- a/sound/isa/Makefile +++ b/sound/isa/Makefile @@ -24,5 +24,5 @@ obj-$(CONFIG_SND_SC6000) += snd-sc6000.o obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o -obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ msnd/ opti9xx/ \ +obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ galaxy/ gus/ msnd/ opti9xx/ \ sb/ wavefront/ wss/ diff --git a/sound/isa/galaxy/Makefile b/sound/isa/galaxy/Makefile new file mode 100644 index 000000000000..e307066d4315 --- /dev/null +++ b/sound/isa/galaxy/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for ALSA +# Copyright (c) 2001 by Jaroslav Kysela +# + +snd-azt1605-objs := azt1605.o +snd-azt2316-objs := azt2316.o + +obj-$(CONFIG_SND_AZT1605) += snd-azt1605.o +obj-$(CONFIG_SND_AZT2316) += snd-azt2316.o diff --git a/sound/isa/galaxy/azt1605.c b/sound/isa/galaxy/azt1605.c new file mode 100644 index 000000000000..9a97643cb713 --- /dev/null +++ b/sound/isa/galaxy/azt1605.c @@ -0,0 +1,91 @@ +/* + * Aztech AZT1605 Driver + * Copyright (C) 2007,2010 Rene Herman + * + * 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, see . + * + */ + +#define AZT1605 + +#define CRD_NAME "Aztech AZT1605" +#define DRV_NAME "AZT1605" +#define DEV_NAME "azt1605" + +#define GALAXY_DSP_MAJOR 2 +#define GALAXY_DSP_MINOR 1 + +#define GALAXY_CONFIG_SIZE 3 + +/* + * 24-bit config register + */ + +#define GALAXY_CONFIG_SBA_220 (0 << 0) +#define GALAXY_CONFIG_SBA_240 (1 << 0) +#define GALAXY_CONFIG_SBA_260 (2 << 0) +#define GALAXY_CONFIG_SBA_280 (3 << 0) +#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280 + +#define GALAXY_CONFIG_MPUA_300 (0 << 2) +#define GALAXY_CONFIG_MPUA_330 (1 << 2) + +#define GALAXY_CONFIG_MPU_ENABLE (1 << 3) + +#define GALAXY_CONFIG_GAME_ENABLE (1 << 4) + +#define GALAXY_CONFIG_CD_PANASONIC (1 << 5) +#define GALAXY_CONFIG_CD_MITSUMI (1 << 6) +#define GALAXY_CONFIG_CD_MASK (\ + GALAXY_CONFIG_CD_PANASONIC | GALAXY_CONFIG_CD_MITSUMI) + +#define GALAXY_CONFIG_UNUSED (1 << 7) +#define GALAXY_CONFIG_UNUSED_MASK GALAXY_CONFIG_UNUSED + +#define GALAXY_CONFIG_SBIRQ_2 (1 << 8) +#define GALAXY_CONFIG_SBIRQ_3 (1 << 9) +#define GALAXY_CONFIG_SBIRQ_5 (1 << 10) +#define GALAXY_CONFIG_SBIRQ_7 (1 << 11) + +#define GALAXY_CONFIG_MPUIRQ_2 (1 << 12) +#define GALAXY_CONFIG_MPUIRQ_3 (1 << 13) +#define GALAXY_CONFIG_MPUIRQ_5 (1 << 14) +#define GALAXY_CONFIG_MPUIRQ_7 (1 << 15) + +#define GALAXY_CONFIG_WSSA_530 (0 << 16) +#define GALAXY_CONFIG_WSSA_604 (1 << 16) +#define GALAXY_CONFIG_WSSA_E80 (2 << 16) +#define GALAXY_CONFIG_WSSA_F40 (3 << 16) + +#define GALAXY_CONFIG_WSS_ENABLE (1 << 18) + +#define GALAXY_CONFIG_CDIRQ_11 (1 << 19) +#define GALAXY_CONFIG_CDIRQ_12 (1 << 20) +#define GALAXY_CONFIG_CDIRQ_15 (1 << 21) +#define GALAXY_CONFIG_CDIRQ_MASK (\ + GALAXY_CONFIG_CDIRQ_11 | GALAXY_CONFIG_CDIRQ_12 |\ + GALAXY_CONFIG_CDIRQ_15) + +#define GALAXY_CONFIG_CDDMA_DISABLE (0 << 22) +#define GALAXY_CONFIG_CDDMA_0 (1 << 22) +#define GALAXY_CONFIG_CDDMA_1 (2 << 22) +#define GALAXY_CONFIG_CDDMA_3 (3 << 22) +#define GALAXY_CONFIG_CDDMA_MASK GALAXY_CONFIG_CDDMA_3 + +#define GALAXY_CONFIG_MASK (\ + GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CD_MASK |\ + GALAXY_CONFIG_UNUSED_MASK | GALAXY_CONFIG_CDIRQ_MASK |\ + GALAXY_CONFIG_CDDMA_MASK) + +#include "galaxy.c" diff --git a/sound/isa/galaxy/azt2316.c b/sound/isa/galaxy/azt2316.c new file mode 100644 index 000000000000..189441141df6 --- /dev/null +++ b/sound/isa/galaxy/azt2316.c @@ -0,0 +1,111 @@ +/* + * Aztech AZT2316 Driver + * Copyright (C) 2007,2010 Rene Herman + * + * 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, see . + * + */ + +#define AZT2316 + +#define CRD_NAME "Aztech AZT2316" +#define DRV_NAME "AZT2316" +#define DEV_NAME "azt2316" + +#define GALAXY_DSP_MAJOR 3 +#define GALAXY_DSP_MINOR 1 + +#define GALAXY_CONFIG_SIZE 4 + +/* + * 32-bit config register + */ + +#define GALAXY_CONFIG_SBA_220 (0 << 0) +#define GALAXY_CONFIG_SBA_240 (1 << 0) +#define GALAXY_CONFIG_SBA_260 (2 << 0) +#define GALAXY_CONFIG_SBA_280 (3 << 0) +#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280 + +#define GALAXY_CONFIG_SBIRQ_2 (1 << 2) +#define GALAXY_CONFIG_SBIRQ_5 (1 << 3) +#define GALAXY_CONFIG_SBIRQ_7 (1 << 4) +#define GALAXY_CONFIG_SBIRQ_10 (1 << 5) + +#define GALAXY_CONFIG_SBDMA_DISABLE (0 << 6) +#define GALAXY_CONFIG_SBDMA_0 (1 << 6) +#define GALAXY_CONFIG_SBDMA_1 (2 << 6) +#define GALAXY_CONFIG_SBDMA_3 (3 << 6) + +#define GALAXY_CONFIG_WSSA_530 (0 << 8) +#define GALAXY_CONFIG_WSSA_604 (1 << 8) +#define GALAXY_CONFIG_WSSA_E80 (2 << 8) +#define GALAXY_CONFIG_WSSA_F40 (3 << 8) + +#define GALAXY_CONFIG_WSS_ENABLE (1 << 10) + +#define GALAXY_CONFIG_GAME_ENABLE (1 << 11) + +#define GALAXY_CONFIG_MPUA_300 (0 << 12) +#define GALAXY_CONFIG_MPUA_330 (1 << 12) + +#define GALAXY_CONFIG_MPU_ENABLE (1 << 13) + +#define GALAXY_CONFIG_CDA_310 (0 << 14) +#define GALAXY_CONFIG_CDA_320 (1 << 14) +#define GALAXY_CONFIG_CDA_340 (2 << 14) +#define GALAXY_CONFIG_CDA_350 (3 << 14) +#define GALAXY_CONFIG_CDA_MASK GALAXY_CONFIG_CDA_350 + +#define GALAXY_CONFIG_CD_DISABLE (0 << 16) +#define GALAXY_CONFIG_CD_PANASONIC (1 << 16) +#define GALAXY_CONFIG_CD_SONY (2 << 16) +#define GALAXY_CONFIG_CD_MITSUMI (3 << 16) +#define GALAXY_CONFIG_CD_AZTECH (4 << 16) +#define GALAXY_CONFIG_CD_UNUSED_5 (5 << 16) +#define GALAXY_CONFIG_CD_UNUSED_6 (6 << 16) +#define GALAXY_CONFIG_CD_UNUSED_7 (7 << 16) +#define GALAXY_CONFIG_CD_MASK GALAXY_CONFIG_CD_UNUSED_7 + +#define GALAXY_CONFIG_CDDMA8_DISABLE (0 << 20) +#define GALAXY_CONFIG_CDDMA8_0 (1 << 20) +#define GALAXY_CONFIG_CDDMA8_1 (2 << 20) +#define GALAXY_CONFIG_CDDMA8_3 (3 << 20) +#define GALAXY_CONFIG_CDDMA8_MASK GALAXY_CONFIG_CDDMA8_3 + +#define GALAXY_CONFIG_CDDMA16_DISABLE (0 << 22) +#define GALAXY_CONFIG_CDDMA16_5 (1 << 22) +#define GALAXY_CONFIG_CDDMA16_6 (2 << 22) +#define GALAXY_CONFIG_CDDMA16_7 (3 << 22) +#define GALAXY_CONFIG_CDDMA16_MASK GALAXY_CONFIG_CDDMA16_7 + +#define GALAXY_CONFIG_MPUIRQ_2 (1 << 24) +#define GALAXY_CONFIG_MPUIRQ_5 (1 << 25) +#define GALAXY_CONFIG_MPUIRQ_7 (1 << 26) +#define GALAXY_CONFIG_MPUIRQ_10 (1 << 27) + +#define GALAXY_CONFIG_CDIRQ_5 (1 << 28) +#define GALAXY_CONFIG_CDIRQ_11 (1 << 29) +#define GALAXY_CONFIG_CDIRQ_12 (1 << 30) +#define GALAXY_CONFIG_CDIRQ_15 (1 << 31) +#define GALAXY_CONFIG_CDIRQ_MASK (\ + GALAXY_CONFIG_CDIRQ_5 | GALAXY_CONFIG_CDIRQ_11 |\ + GALAXY_CONFIG_CDIRQ_12 | GALAXY_CONFIG_CDIRQ_15) + +#define GALAXY_CONFIG_MASK (\ + GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CDA_MASK |\ + GALAXY_CONFIG_CD_MASK | GALAXY_CONFIG_CDDMA16_MASK |\ + GALAXY_CONFIG_CDDMA8_MASK | GALAXY_CONFIG_CDIRQ_MASK) + +#include "galaxy.c" diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c new file mode 100644 index 000000000000..ee54df082b9c --- /dev/null +++ b/sound/isa/galaxy/galaxy.c @@ -0,0 +1,652 @@ +/* + * Aztech AZT1605/AZT2316 Driver + * Copyright (C) 2007,2010 Rene Herman + * + * 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, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION(CRD_NAME); +MODULE_AUTHOR("Rene Herman"); +MODULE_LICENSE("GPL"); + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; + +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); +module_param_array(id, charp, NULL, 0444); +MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); + +static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; +static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; +static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; +static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; +static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; +static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; +static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; +static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; + +module_param_array(port, long, NULL, 0444); +MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); +module_param_array(wss_port, long, NULL, 0444); +MODULE_PARM_DESC(wss_port, "WSS port # for " CRD_NAME " driver."); +module_param_array(mpu_port, long, NULL, 0444); +MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); +module_param_array(fm_port, long, NULL, 0444); +MODULE_PARM_DESC(fm_port, "FM port # for " CRD_NAME " driver."); +module_param_array(irq, int, NULL, 0444); +MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); +module_param_array(mpu_irq, int, NULL, 0444); +MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); +module_param_array(dma1, int, NULL, 0444); +MODULE_PARM_DESC(dma1, "Playback DMA # for " CRD_NAME " driver."); +module_param_array(dma2, int, NULL, 0444); +MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver."); + +/* + * Generic SB DSP support routines + */ + +#define DSP_PORT_RESET 0x6 +#define DSP_PORT_READ 0xa +#define DSP_PORT_COMMAND 0xc +#define DSP_PORT_STATUS 0xc +#define DSP_PORT_DATA_AVAIL 0xe + +#define DSP_SIGNATURE 0xaa + +#define DSP_COMMAND_GET_VERSION 0xe1 + +static int __devinit dsp_get_byte(void __iomem *port, u8 *val) +{ + int loops = 1000; + + while (!(ioread8(port + DSP_PORT_DATA_AVAIL) & 0x80)) { + if (!loops--) + return -EIO; + cpu_relax(); + } + *val = ioread8(port + DSP_PORT_READ); + return 0; +} + +static int __devinit dsp_reset(void __iomem *port) +{ + u8 val; + + iowrite8(1, port + DSP_PORT_RESET); + udelay(10); + iowrite8(0, port + DSP_PORT_RESET); + + if (dsp_get_byte(port, &val) < 0 || val != DSP_SIGNATURE) + return -ENODEV; + + return 0; +} + +static int __devinit dsp_command(void __iomem *port, u8 cmd) +{ + int loops = 1000; + + while (ioread8(port + DSP_PORT_STATUS) & 0x80) { + if (!loops--) + return -EIO; + cpu_relax(); + } + iowrite8(cmd, port + DSP_PORT_COMMAND); + return 0; +} + +static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor) +{ + int err; + + err = dsp_command(port, DSP_COMMAND_GET_VERSION); + if (err < 0) + return err; + + err = dsp_get_byte(port, major); + if (err < 0) + return err; + + err = dsp_get_byte(port, minor); + if (err < 0) + return err; + + return 0; +} + +/* + * Generic WSS support routines + */ + +#define WSS_CONFIG_DMA_0 (1 << 0) +#define WSS_CONFIG_DMA_1 (2 << 0) +#define WSS_CONFIG_DMA_3 (3 << 0) +#define WSS_CONFIG_DUPLEX (1 << 2) +#define WSS_CONFIG_IRQ_7 (1 << 3) +#define WSS_CONFIG_IRQ_9 (2 << 3) +#define WSS_CONFIG_IRQ_10 (3 << 3) +#define WSS_CONFIG_IRQ_11 (4 << 3) + +#define WSS_PORT_CONFIG 0 +#define WSS_PORT_SIGNATURE 3 + +#define WSS_SIGNATURE 4 + +static int __devinit wss_detect(void __iomem *wss_port) +{ + if ((ioread8(wss_port + WSS_PORT_SIGNATURE) & 0x3f) != WSS_SIGNATURE) + return -ENODEV; + + return 0; +} + +static void wss_set_config(void __iomem *wss_port, u8 wss_config) +{ + iowrite8(wss_config, wss_port + WSS_PORT_CONFIG); +} + +/* + * Aztech Sound Galaxy specifics + */ + +#define GALAXY_PORT_CONFIG 1024 +#define CONFIG_PORT_SET 4 + +#define DSP_COMMAND_GALAXY_8 8 +#define GALAXY_COMMAND_GET_TYPE 5 + +#define DSP_COMMAND_GALAXY_9 9 +#define GALAXY_COMMAND_WSSMODE 0 +#define GALAXY_COMMAND_SB8MODE 1 + +#define GALAXY_MODE_WSS GALAXY_COMMAND_WSSMODE +#define GALAXY_MODE_SB8 GALAXY_COMMAND_SB8MODE + +struct snd_galaxy { + void __iomem *port; + void __iomem *config_port; + void __iomem *wss_port; + u32 config; + struct resource *res_port; + struct resource *res_config_port; + struct resource *res_wss_port; +}; + +static u32 config[SNDRV_CARDS]; +static u8 wss_config[SNDRV_CARDS]; + +static int __devinit snd_galaxy_match(struct device *dev, unsigned int n) +{ + if (!enable[n]) + return 0; + + switch (port[n]) { + case SNDRV_AUTO_PORT: + dev_err(dev, "please specify port\n"); + return 0; + case 0x220: + config[n] |= GALAXY_CONFIG_SBA_220; + break; + case 0x240: + config[n] |= GALAXY_CONFIG_SBA_240; + break; + case 0x260: + config[n] |= GALAXY_CONFIG_SBA_260; + break; + case 0x280: + config[n] |= GALAXY_CONFIG_SBA_280; + break; + default: + dev_err(dev, "invalid port %#lx\n", port[n]); + return 0; + } + + switch (wss_port[n]) { + case SNDRV_AUTO_PORT: + dev_err(dev, "please specify wss_port\n"); + return 0; + case 0x530: + config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_530; + break; + case 0x604: + config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_604; + break; + case 0xe80: + config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_E80; + break; + case 0xf40: + config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_F40; + break; + default: + dev_err(dev, "invalid WSS port %#lx\n", wss_port[n]); + return 0; + } + + switch (irq[n]) { + case SNDRV_AUTO_IRQ: + dev_err(dev, "please specify irq\n"); + return 0; + case 7: + wss_config[n] |= WSS_CONFIG_IRQ_7; + break; + case 2: + irq[n] = 9; + case 9: + wss_config[n] |= WSS_CONFIG_IRQ_9; + break; + case 10: + wss_config[n] |= WSS_CONFIG_IRQ_10; + break; + case 11: + wss_config[n] |= WSS_CONFIG_IRQ_11; + break; + default: + dev_err(dev, "invalid IRQ %d\n", irq[n]); + return 0; + } + + switch (dma1[n]) { + case SNDRV_AUTO_DMA: + dev_err(dev, "please specify dma1\n"); + return 0; + case 0: + wss_config[n] |= WSS_CONFIG_DMA_0; + break; + case 1: + wss_config[n] |= WSS_CONFIG_DMA_1; + break; + case 3: + wss_config[n] |= WSS_CONFIG_DMA_3; + break; + default: + dev_err(dev, "invalid playback DMA %d\n", dma1[n]); + return 0; + } + + if (dma2[n] == SNDRV_AUTO_DMA || dma2[n] == dma1[n]) { + dma2[n] = -1; + goto mpu; + } + + wss_config[n] |= WSS_CONFIG_DUPLEX; + switch (dma2[n]) { + case 0: + break; + case 1: + if (dma1[n] == 0) + break; + default: + dev_err(dev, "invalid capture DMA %d\n", dma2[n]); + return 0; + } + +mpu: + switch (mpu_port[n]) { + case SNDRV_AUTO_PORT: + dev_warn(dev, "mpu_port not specified; not using MPU-401\n"); + mpu_port[n] = -1; + goto fm; + case 0x300: + config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_300; + break; + case 0x330: + config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_330; + break; + default: + dev_err(dev, "invalid MPU port %#lx\n", mpu_port[n]); + return 0; + } + + switch (mpu_irq[n]) { + case SNDRV_AUTO_IRQ: + dev_warn(dev, "mpu_irq not specified: using polling mode\n"); + mpu_irq[n] = -1; + break; + case 2: + mpu_irq[n] = 9; + case 9: + config[n] |= GALAXY_CONFIG_MPUIRQ_2; + break; +#ifdef AZT1605 + case 3: + config[n] |= GALAXY_CONFIG_MPUIRQ_3; + break; +#endif + case 5: + config[n] |= GALAXY_CONFIG_MPUIRQ_5; + break; + case 7: + config[n] |= GALAXY_CONFIG_MPUIRQ_7; + break; +#ifdef AZT2316 + case 10: + config[n] |= GALAXY_CONFIG_MPUIRQ_10; + break; +#endif + default: + dev_err(dev, "invalid MPU IRQ %d\n", mpu_irq[n]); + return 0; + } + + if (mpu_irq[n] == irq[n]) { + dev_err(dev, "cannot share IRQ between WSS and MPU-401\n"); + return 0; + } + +fm: + switch (fm_port[n]) { + case SNDRV_AUTO_PORT: + dev_warn(dev, "fm_port not specified: not using OPL3\n"); + fm_port[n] = -1; + break; + case 0x388: + break; + default: + dev_err(dev, "illegal FM port %#lx\n", fm_port[n]); + return 0; + } + + config[n] |= GALAXY_CONFIG_GAME_ENABLE; + return 1; +} + +static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type) +{ + u8 major; + u8 minor; + int err; + + err = dsp_reset(galaxy->port); + if (err < 0) + return err; + + err = dsp_get_version(galaxy->port, &major, &minor); + if (err < 0) + return err; + + if (major != GALAXY_DSP_MAJOR || minor != GALAXY_DSP_MINOR) + return -ENODEV; + + err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_8); + if (err < 0) + return err; + + err = dsp_command(galaxy->port, GALAXY_COMMAND_GET_TYPE); + if (err < 0) + return err; + + err = dsp_get_byte(galaxy->port, type); + if (err < 0) + return err; + + return 0; +} + +static int __devinit galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode) +{ + int err; + + err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_9); + if (err < 0) + return err; + + err = dsp_command(galaxy->port, mode); + if (err < 0) + return err; + +#ifdef AZT1605 + /* + * Needed for MPU IRQ on AZT1605, but AZT2316 loses WSS again + */ + err = dsp_reset(galaxy->port); + if (err < 0) + return err; +#endif + + return 0; +} + +static void galaxy_set_config(struct snd_galaxy *galaxy, u32 config) +{ + u8 tmp = ioread8(galaxy->config_port + CONFIG_PORT_SET); + int i; + + iowrite8(tmp | 0x80, galaxy->config_port + CONFIG_PORT_SET); + for (i = 0; i < GALAXY_CONFIG_SIZE; i++) { + iowrite8(config, galaxy->config_port + i); + config >>= 8; + } + iowrite8(tmp & 0x7f, galaxy->config_port + CONFIG_PORT_SET); + msleep(10); +} + +static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config) +{ + int i; + + for (i = GALAXY_CONFIG_SIZE; i; i--) { + u8 tmp = ioread8(galaxy->config_port + i - 1); + galaxy->config = (galaxy->config << 8) | tmp; + } + config |= galaxy->config & GALAXY_CONFIG_MASK; + galaxy_set_config(galaxy, config); +} + +static int __devinit galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config) +{ + int err; + + err = wss_detect(galaxy->wss_port); + if (err < 0) + return err; + + wss_set_config(galaxy->wss_port, wss_config); + + err = galaxy_set_mode(galaxy, GALAXY_MODE_WSS); + if (err < 0) + return err; + + return 0; +} + +static void snd_galaxy_free(struct snd_card *card) +{ + struct snd_galaxy *galaxy = card->private_data; + + if (galaxy->wss_port) { + wss_set_config(galaxy->wss_port, 0); + ioport_unmap(galaxy->wss_port); + release_and_free_resource(galaxy->res_wss_port); + } + if (galaxy->config_port) { + galaxy_set_config(galaxy, galaxy->config); + ioport_unmap(galaxy->config_port); + release_and_free_resource(galaxy->res_config_port); + } + if (galaxy->port) { + ioport_unmap(galaxy->port); + release_and_free_resource(galaxy->res_port); + } +} + +static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n) +{ + struct snd_galaxy *galaxy; + struct snd_wss *chip; + struct snd_card *card; + u8 type; + int err; + + err = snd_card_create(index[n], id[n], THIS_MODULE, sizeof *galaxy, + &card); + if (err < 0) + return err; + + snd_card_set_dev(card, dev); + + card->private_free = snd_galaxy_free; + galaxy = card->private_data; + + galaxy->res_port = request_region(port[n], 16, DRV_NAME); + if (!galaxy->res_port) { + dev_err(dev, "could not grab ports %#lx-%#lx\n", port[n], + port[n] + 15); + err = -EBUSY; + goto error; + } + galaxy->port = ioport_map(port[n], 16); + + err = galaxy_init(galaxy, &type); + if (err < 0) { + dev_err(dev, "did not find a Sound Galaxy at %#lx\n", port[n]); + goto error; + } + dev_info(dev, "Sound Galaxy (type %d) found at %#lx\n", type, port[n]); + + galaxy->res_config_port = request_region(port[n] + GALAXY_PORT_CONFIG, + 16, DRV_NAME); + if (!galaxy->res_config_port) { + dev_err(dev, "could not grab ports %#lx-%#lx\n", + port[n] + GALAXY_PORT_CONFIG, + port[n] + GALAXY_PORT_CONFIG + 15); + err = -EBUSY; + goto error; + } + galaxy->config_port = ioport_map(port[n] + GALAXY_PORT_CONFIG, 16); + + galaxy_config(galaxy, config[n]); + + galaxy->res_wss_port = request_region(wss_port[n], 4, DRV_NAME); + if (!galaxy->res_wss_port) { + dev_err(dev, "could not grab ports %#lx-%#lx\n", wss_port[n], + wss_port[n] + 3); + err = -EBUSY; + goto error; + } + galaxy->wss_port = ioport_map(wss_port[n], 4); + + err = galaxy_wss_config(galaxy, wss_config[n]); + if (err < 0) { + dev_err(dev, "could not configure WSS\n"); + goto error; + } + + strcpy(card->driver, DRV_NAME); + strcpy(card->shortname, DRV_NAME); + sprintf(card->longname, "%s at %#lx/%#lx, irq %d, dma %d/%d", + card->shortname, port[n], wss_port[n], irq[n], dma1[n], + dma2[n]); + + err = snd_wss_create(card, wss_port[n] + 4, -1, irq[n], dma1[n], + dma2[n], WSS_HW_DETECT, 0, &chip); + if (err < 0) + goto error; + + err = snd_wss_pcm(chip, 0, NULL); + if (err < 0) + goto error; + + err = snd_wss_mixer(chip); + if (err < 0) + goto error; + + err = snd_wss_timer(chip, 0, NULL); + if (err < 0) + goto error; + + if (mpu_port[n] >= 0) { + err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, + mpu_port[n], 0, mpu_irq[n], + IRQF_DISABLED, NULL); + if (err < 0) + goto error; + } + + if (fm_port[n] >= 0) { + struct snd_opl3 *opl3; + + err = snd_opl3_create(card, fm_port[n], fm_port[n] + 2, + OPL3_HW_AUTO, 0, &opl3); + if (err < 0) { + dev_err(dev, "no OPL device at %#lx\n", fm_port[n]); + goto error; + } + err = snd_opl3_timer_new(opl3, 1, 2); + if (err < 0) + goto error; + + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) + goto error; + } + + err = snd_card_register(card); + if (err < 0) + goto error; + + dev_set_drvdata(dev, card); + return 0; + +error: + snd_card_free(card); + return err; +} + +static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n) +{ + snd_card_free(dev_get_drvdata(dev)); + dev_set_drvdata(dev, NULL); + return 0; +} + +static struct isa_driver snd_galaxy_driver = { + .match = snd_galaxy_match, + .probe = snd_galaxy_probe, + .remove = __devexit_p(snd_galaxy_remove), + + .driver = { + .name = DEV_NAME + } +}; + +static int __init alsa_card_galaxy_init(void) +{ + return isa_register_driver(&snd_galaxy_driver, SNDRV_CARDS); +} + +static void __exit alsa_card_galaxy_exit(void) +{ + isa_unregister_driver(&snd_galaxy_driver); +} + +module_init(alsa_card_galaxy_init); +module_exit(alsa_card_galaxy_exit); -- cgit v1.2.3-59-g8ed1b From cbaa9f60d5d5c3af10f94e0d49789d5b82341a4a Mon Sep 17 00:00:00 2001 From: René Herman Date: Fri, 13 Aug 2010 10:43:48 +0200 Subject: ALSA: ISA: Remove snd-sgalaxy Its hardware is handled more fully by the new azt1605/azt2316 drivers. Signed-off-by: Rene Herman Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 14 - sound/isa/Kconfig | 10 - sound/isa/Makefile | 2 - sound/isa/sgalaxy.c | 369 ------------------------ 4 files changed, 395 deletions(-) delete mode 100644 sound/isa/sgalaxy.c diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index e25555c02166..d0eb696d32e8 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1709,20 +1709,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. This card is also known as Audio Excel DSP 16 or Zoltrix AV302. - Module snd-sgalaxy - ------------------ - - Module for Aztech Sound Galaxy sound card. - - sbport - Port # for SB16 interface (0x220,0x240) - wssport - Port # for WSS interface (0x530,0xe80,0xf40,0x604) - irq - IRQ # (7,9,10,11) - dma1 - DMA # - - This module supports multiple cards. - - The power-management is supported. - Module snd-sscape ----------------- diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index f9aa13d8dacc..52064cfa91f3 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -377,16 +377,6 @@ config SND_SB16_CSP coprocessor can do variable tasks like various compression and decompression algorithms. -config SND_SGALAXY - tristate "Aztech Sound Galaxy" - select SND_WSS_LIB - help - Say Y here to include support for Aztech Sound Galaxy - soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-sgalaxy. - config SND_SSCAPE tristate "Ensoniq SoundScape driver" select SND_MPU401_UART diff --git a/sound/isa/Makefile b/sound/isa/Makefile index d2bd8f536dd8..8d781e419e2e 100644 --- a/sound/isa/Makefile +++ b/sound/isa/Makefile @@ -10,7 +10,6 @@ snd-cmi8330-objs := cmi8330.o snd-es18xx-objs := es18xx.o snd-opl3sa2-objs := opl3sa2.o snd-sc6000-objs := sc6000.o -snd-sgalaxy-objs := sgalaxy.o snd-sscape-objs := sscape.o # Toplevel Module Dependency @@ -21,7 +20,6 @@ obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o obj-$(CONFIG_SND_SC6000) += snd-sc6000.o -obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ galaxy/ gus/ msnd/ opti9xx/ \ diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c deleted file mode 100644 index 6fe27b9d9440..000000000000 --- a/sound/isa/sgalaxy.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Driver for Aztech Sound Galaxy cards - * Copyright (c) by Christopher Butler -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include - -MODULE_AUTHOR("Christopher Butler "); -MODULE_DESCRIPTION("Aztech Sound Galaxy"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Aztech Systems,Sound Galaxy}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240 */ -static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530,0xe80,0xf40,0x604 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 7,9,10,11 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Sound Galaxy soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Sound Galaxy soundcard."); -module_param_array(sbport, long, NULL, 0444); -MODULE_PARM_DESC(sbport, "Port # for Sound Galaxy SB driver."); -module_param_array(wssport, long, NULL, 0444); -MODULE_PARM_DESC(wssport, "Port # for Sound Galaxy WSS driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver."); - -#define SGALAXY_AUXC_LEFT 18 -#define SGALAXY_AUXC_RIGHT 19 - -#define PFX "sgalaxy: " - -/* - - */ - -#define AD1848P1( port, x ) ( port + c_d_c_AD1848##x ) - -/* from lowlevel/sb/sb.c - to avoid having to allocate a struct snd_sb for the */ -/* short time we actually need it.. */ - -static int snd_sgalaxy_sbdsp_reset(unsigned long port) -{ - int i; - - outb(1, SBP1(port, RESET)); - udelay(10); - outb(0, SBP1(port, RESET)); - udelay(30); - for (i = 0; i < 1000 && !(inb(SBP1(port, DATA_AVAIL)) & 0x80); i++); - if (inb(SBP1(port, READ)) != 0xaa) { - snd_printd("sb_reset: failed at 0x%lx!!!\n", port); - return -ENODEV; - } - return 0; -} - -static int __devinit snd_sgalaxy_sbdsp_command(unsigned long port, - unsigned char val) -{ - int i; - - for (i = 10000; i; i--) - if ((inb(SBP1(port, STATUS)) & 0x80) == 0) { - outb(val, SBP1(port, COMMAND)); - return 1; - } - - return 0; -} - -static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id) -{ - return IRQ_NONE; -} - -static int __devinit snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma) -{ - static int interrupt_bits[] = {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, - 0x10, 0x18, 0x20, -1, -1, -1, -1}; - static int dma_bits[] = {1, 2, 0, 3}; - int tmp, tmp1; - - if ((tmp = inb(port + 3)) == 0xff) - { - snd_printdd("I/O address dead (0x%lx)\n", port); - return 0; - } -#if 0 - snd_printdd("WSS signature = 0x%x\n", tmp); -#endif - - if ((tmp & 0x3f) != 0x04 && - (tmp & 0x3f) != 0x0f && - (tmp & 0x3f) != 0x00) { - snd_printdd("No WSS signature detected on port 0x%lx\n", - port + 3); - return 0; - } - -#if 0 - snd_printdd(PFX "setting up IRQ/DMA for WSS\n"); -#endif - - /* initialize IRQ for WSS codec */ - tmp = interrupt_bits[irq % 16]; - if (tmp < 0) - return -EINVAL; - - if (request_irq(irq, snd_sgalaxy_dummy_interrupt, IRQF_DISABLED, "sgalaxy", NULL)) { - snd_printk(KERN_ERR "sgalaxy: can't grab irq %d\n", irq); - return -EIO; - } - - outb(tmp | 0x40, port); - tmp1 = dma_bits[dma % 4]; - outb(tmp | tmp1, port); - - free_irq(irq, NULL); - - return 0; -} - -static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma) -{ -#if 0 - snd_printdd(PFX "switching to WSS mode\n"); -#endif - - /* switch to WSS mode */ - snd_sgalaxy_sbdsp_reset(sbport[dev]); - - snd_sgalaxy_sbdsp_command(sbport[dev], 9); - snd_sgalaxy_sbdsp_command(sbport[dev], 0); - - udelay(400); - return snd_sgalaxy_setup_wss(wssport[dev], irq, dma); -} - -static struct snd_kcontrol_new snd_sgalaxy_controls[] = { -WSS_DOUBLE("Aux Playback Switch", 0, - SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1), -WSS_DOUBLE("Aux Playback Volume", 0, - SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0) -}; - -static int __devinit snd_sgalaxy_mixer(struct snd_wss *chip) -{ - struct snd_card *card = chip->card; - struct snd_ctl_elem_id id1, id2; - unsigned int idx; - int err; - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - /* reassign AUX0 to LINE */ - strcpy(id1.name, "Aux Playback Switch"); - strcpy(id2.name, "Line Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "Line Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - /* reassign AUX1 to FM */ - strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; - strcpy(id2.name, "FM Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "FM Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - /* build AUX2 input */ - for (idx = 0; idx < ARRAY_SIZE(snd_sgalaxy_controls); idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_sgalaxy_controls[idx], chip)); - if (err < 0) - return err; - } - return 0; -} - -static int __devinit snd_sgalaxy_match(struct device *devptr, unsigned int dev) -{ - if (!enable[dev]) - return 0; - if (sbport[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify SB port\n"); - return 0; - } - if (wssport[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify WSS port\n"); - return 0; - } - return 1; -} - -static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) -{ - static int possible_irqs[] = {7, 9, 10, 11, -1}; - static int possible_dmas[] = {1, 3, 0, -1}; - int err, xirq, xdma1; - struct snd_card *card; - struct snd_wss *chip; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - xirq = irq[dev]; - if (xirq == SNDRV_AUTO_IRQ) { - if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - err = -EBUSY; - goto _err; - } - } - xdma1 = dma1[dev]; - if (xdma1 == SNDRV_AUTO_DMA) { - if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA\n"); - err = -EBUSY; - goto _err; - } - } - - if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) - goto _err; - - err = snd_wss_create(card, wssport[dev] + 4, -1, - xirq, xdma1, -1, - WSS_HW_DETECT, 0, &chip); - if (err < 0) - goto _err; - card->private_data = chip; - - err = snd_wss_pcm(chip, 0, NULL); - if (err < 0) { - snd_printdd(PFX "error creating new WSS PCM device\n"); - goto _err; - } - err = snd_wss_mixer(chip); - if (err < 0) { - snd_printdd(PFX "error creating new WSS mixer\n"); - goto _err; - } - if ((err = snd_sgalaxy_mixer(chip)) < 0) { - snd_printdd(PFX "the mixer rewrite failed\n"); - goto _err; - } - - strcpy(card->driver, "Sound Galaxy"); - strcpy(card->shortname, "Sound Galaxy"); - sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d", - wssport[dev], xirq, xdma1); - - snd_card_set_dev(card, devptr); - - if ((err = snd_card_register(card)) < 0) - goto _err; - - dev_set_drvdata(devptr, card); - return 0; - - _err: - snd_card_free(card); - return err; -} - -static int __devexit snd_sgalaxy_remove(struct device *devptr, unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n, - pm_message_t state) -{ - struct snd_card *card = dev_get_drvdata(pdev); - struct snd_wss *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->suspend(chip); - return 0; -} - -static int snd_sgalaxy_resume(struct device *pdev, unsigned int n) -{ - struct snd_card *card = dev_get_drvdata(pdev); - struct snd_wss *chip = card->private_data; - - chip->resume(chip); - snd_wss_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]); - snd_wss_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -#define DEV_NAME "sgalaxy" - -static struct isa_driver snd_sgalaxy_driver = { - .match = snd_sgalaxy_match, - .probe = snd_sgalaxy_probe, - .remove = __devexit_p(snd_sgalaxy_remove), -#ifdef CONFIG_PM - .suspend = snd_sgalaxy_suspend, - .resume = snd_sgalaxy_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - -static int __init alsa_card_sgalaxy_init(void) -{ - return isa_register_driver(&snd_sgalaxy_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_sgalaxy_exit(void) -{ - isa_unregister_driver(&snd_sgalaxy_driver); -} - -module_init(alsa_card_sgalaxy_init) -module_exit(alsa_card_sgalaxy_exit) -- cgit v1.2.3-59-g8ed1b From 48fc267ee6f34f67db42a49f386fdd367cac6f8a Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Fri, 13 Aug 2010 10:10:46 -0400 Subject: MAINTAINERS: Add maintainer entries for padata/pcrypt Signed-off-by: Steffen Klassert Signed-off-by: Herbert Xu --- MAINTAINERS | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 11e34d5272b8..2dfc90c0243c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4315,6 +4315,15 @@ L: linux-i2c@vger.kernel.org S: Maintained F: drivers/i2c/busses/i2c-pasemi.c +PADATA PARALLEL EXECUTION MECHANISM +M: Steffen Klassert +L: linux-kernel@vger.kernel.org +L: linux-crypto@vger.kernel.org +S: Maintained +F: kernel/padata.c +F: include/linux/padata.h +F: Documentation/padata.txt + PANASONIC LAPTOP ACPI EXTRAS DRIVER M: Harald Welte L: platform-driver-x86@vger.kernel.org @@ -4435,6 +4444,13 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/pcnet32.c +PCRYPT PARALLEL CRYPTO ENGINE +M: Steffen Klassert +L: linux-crypto@vger.kernel.org +S: Maintained +F: crypto/pcrypt.c +F: include/crypto/pcrypt.h + PER-TASK DELAY ACCOUNTING M: Balbir Singh S: Maintained -- cgit v1.2.3-59-g8ed1b From 4f4e8f69895c8696a4bcc751817d4b186023ac44 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 13 Aug 2010 12:42:07 -0700 Subject: ALSA: usb: USB3 SuperSpeed sound support This is V2 of the patch, after feedback from Clemens and Daniel. This patch adds SuperSpeed support to the USB drivers under sound/. It adds tests for USB_SPEED_SUPER to the appropriate places that check for the USB speed. This patch has been tested with our SS USB3 device emulating a set of Yamaha speakers and a Logitech microphone, but with the descriptors modified to add USB3 support. It has also been tested with the real speakers and microphone, to make sure that USB2 devices still work. Signed-off-by: Paul Zimmerman Cc: Clemens Ladisch Cc: Daniel Mack Cc: Greg Kroah-Hartman Signed-off-by: Takashi Iwai --- sound/usb/card.c | 31 +++++++++++++++++++++++-------- sound/usb/helper.c | 17 +++++++++++------ sound/usb/midi.c | 9 ++++++++- sound/usb/pcm.c | 4 ++-- sound/usb/proc.c | 2 +- sound/usb/urb.c | 2 +- 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 9feb00c831a0..498a2d8fa4bb 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -299,9 +299,13 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, *rchip = NULL; - if (snd_usb_get_speed(dev) != USB_SPEED_LOW && - snd_usb_get_speed(dev) != USB_SPEED_FULL && - snd_usb_get_speed(dev) != USB_SPEED_HIGH) { + switch (snd_usb_get_speed(dev)) { + case USB_SPEED_LOW: + case USB_SPEED_FULL: + case USB_SPEED_HIGH: + case USB_SPEED_SUPER: + break; + default: snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev)); return -ENXIO; } @@ -377,11 +381,22 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, if (len < sizeof(card->longname)) usb_make_path(dev, card->longname + len, sizeof(card->longname) - len); - strlcat(card->longname, - snd_usb_get_speed(dev) == USB_SPEED_LOW ? ", low speed" : - snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" : - ", high speed", - sizeof(card->longname)); + switch (snd_usb_get_speed(dev)) { + case USB_SPEED_LOW: + strlcat(card->longname, ", low speed", sizeof(card->longname)); + break; + case USB_SPEED_FULL: + strlcat(card->longname, ", full speed", sizeof(card->longname)); + break; + case USB_SPEED_HIGH: + strlcat(card->longname, ", high speed", sizeof(card->longname)); + break; + case USB_SPEED_SUPER: + strlcat(card->longname, ", super speed", sizeof(card->longname)); + break; + default: + break; + } snd_usb_audio_create_proc(chip); diff --git a/sound/usb/helper.c b/sound/usb/helper.c index d48d6f8f6ac9..f280c1903c25 100644 --- a/sound/usb/helper.c +++ b/sound/usb/helper.c @@ -103,11 +103,16 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, struct usb_host_interface *alts) { - if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH && - get_endpoint(alts, 0)->bInterval >= 1 && - get_endpoint(alts, 0)->bInterval <= 4) - return get_endpoint(alts, 0)->bInterval - 1; - else - return 0; + switch (snd_usb_get_speed(chip->dev)) { + case USB_SPEED_HIGH: + case USB_SPEED_SUPER: + if (get_endpoint(alts, 0)->bInterval >= 1 && + get_endpoint(alts, 0)->bInterval <= 4) + return get_endpoint(alts, 0)->bInterval - 1; + break; + default: + break; + } + return 0; } diff --git a/sound/usb/midi.c b/sound/usb/midi.c index b9c2bc65f51a..156cd0716c42 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -834,7 +834,14 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep, if (!ep->ports[0].active) return; - count = snd_usb_get_speed(ep->umidi->dev) == USB_SPEED_HIGH ? 1 : 2; + switch (snd_usb_get_speed(ep->umidi->dev)) { + case USB_SPEED_HIGH: + case USB_SPEED_SUPER: + count = 1; + break; + default: + count = 2; + } count = snd_rawmidi_transmit(ep->ports[0].substream, urb->transfer_buffer, count); diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 456829882f40..ebd09acd186e 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -467,7 +467,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, return 0; } /* check whether the period time is >= the data packet interval */ - if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) { + if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { ptime = 125 * (1 << fp->datainterval); if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); @@ -735,7 +735,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre } param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; - if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH) + if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) /* full speed devices have fixed data packet interval */ ptmin = 1000; if (ptmin == 1000) diff --git a/sound/usb/proc.c b/sound/usb/proc.c index f5e3f356b95f..3c650ab3c91d 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -107,7 +107,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s } snd_iprintf(buffer, "\n"); } - if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) + if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) snd_iprintf(buffer, " Data packet interval: %d us\n", 125 * (1 << fp->datainterval)); // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); diff --git a/sound/usb/urb.c b/sound/usb/urb.c index de607d4411ac..8deeaad10f10 100644 --- a/sound/usb/urb.c +++ b/sound/usb/urb.c @@ -244,7 +244,7 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs, else subs->curpacksize = maxsize; - if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) + if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) packs_per_ms = 8 >> subs->datainterval; else packs_per_ms = 1; -- cgit v1.2.3-59-g8ed1b From 13cb61f8c261ca6a218f83f4ee9c3bd5cfc223a5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Aug 2010 15:44:04 +0100 Subject: ASoC: Set up debugfs only once per CODEC Since the debugfs directory is current per CODEC we should only init it when the CODEC is initialised, otherwise we end up with errors being generated when an attempt is made to add duplicate debugfs entries. Since most of this stuff is actually for the card we should refactor but this can come later. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a004876a39a9..ac0fa228c7b3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1323,6 +1323,9 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) return ret; } } + + soc_init_codec_debugfs(codec); + /* mark codec as probed and add to card codec list */ codec->probed = 1; list_add(&codec->card_list, &card->codec_dev_list); @@ -1400,8 +1403,6 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) if (ret < 0) printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); - soc_init_codec_debugfs(codec); - /* create the pcm */ ret = soc_new_pcm(rtd, num); if (ret < 0) { -- cgit v1.2.3-59-g8ed1b From 6ba6c9c3414b95c3ed50d529fb0efa744ed45761 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Aug 2010 15:49:52 +0100 Subject: ASoC: Remove redundant device name from debugfs directory Since the core now includes deduplication in the name of CODEC devices there's no need to add extra for the debugfs directory name. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-core.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ac0fa228c7b3..cea0fe488623 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -234,16 +234,7 @@ static const struct file_operations codec_reg_fops = { static void soc_init_codec_debugfs(struct snd_soc_codec *codec) { - char codec_root[128]; - - if (codec->dev) - snprintf(codec_root, sizeof(codec_root), - "%s.%s", codec->name, dev_name(codec->dev)); - else - snprintf(codec_root, sizeof(codec_root), - "%s", codec->name); - - codec->debugfs_codec_root = debugfs_create_dir(codec_root, + codec->debugfs_codec_root = debugfs_create_dir(codec->name , debugfs_root); if (!codec->debugfs_codec_root) { printk(KERN_WARNING -- cgit v1.2.3-59-g8ed1b From 10e2f11326e0a263f0336686454be67efb2b56dc Mon Sep 17 00:00:00 2001 From: Ian Lartey Date: Fri, 13 Aug 2010 17:02:13 +0100 Subject: ASoC: multi-component: Fix reference to moved header file, which was unused anyway. Removed #include of pxa2xx-pcm.h Signed-off-by: Ian Lartey Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-i2s.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 3b473b200a8f..d1b2ca69fd30 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -27,7 +27,6 @@ #include #include -#include "pxa2xx-pcm.h" #include "pxa2xx-i2s.h" /* -- cgit v1.2.3-59-g8ed1b From dd99a4524bd9f82358e9a20a44c5e784baa4e702 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Fri, 13 Aug 2010 21:55:27 +0800 Subject: ASoC: fix pxa2xx-pcm.h path Since pxa2xx-pcm.h is removed from sound/soc/pxa, we need to update the path in related files. Signed-off-by: Haojian Zhuang Tested-by: Ian Lartey Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 2 +- sound/soc/pxa/pxa2xx-pcm.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 99d80e85621c..c4f480d67a50 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -35,7 +35,7 @@ #include #include -#include "pxa2xx-pcm.h" +#include "../../arm/pxa2xx-pcm.h" #include "pxa-ssp.h" /* diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index 5127044acfec..02fb66416ddc 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c @@ -16,7 +16,6 @@ #include #include -#include "pxa2xx-pcm.h" #include "../../arm/pxa2xx-pcm.h" static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, -- cgit v1.2.3-59-g8ed1b From f5d1e5ed58dc0178e1678db63156772999379d49 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Fri, 13 Aug 2010 21:55:35 +0800 Subject: ASoC: update setting for pxa ssp slave mode SCFR bit is required to be always set if pxa ssp is in slave mode. This bit indicates clock input to SSPSCLK is only active during data transfers. Signed-off-by: Haojian Zhuang Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index c4f480d67a50..8dfbcda956ff 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -462,9 +462,7 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, { struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); struct ssp_device *ssp = priv->ssp; - u32 sscr0; - u32 sscr1; - u32 sspsp; + u32 sscr0, sscr1, sspsp, scfr; /* check if we need to change anything at all */ if (priv->dai_fmt == fmt) @@ -479,16 +477,16 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* reset port settings */ sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & - (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); + ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7); sspsp = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: - sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR; + sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR | SSCR1_SCFR; break; case SND_SOC_DAIFMT_CBM_CFS: - sscr1 |= SSCR1_SCLKDIR; + sscr1 |= SSCR1_SCLKDIR | SSCR1_SCFR; break; case SND_SOC_DAIFMT_CBS_CFS: break; @@ -534,6 +532,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, pxa_ssp_write_reg(ssp, SSCR1, sscr1); pxa_ssp_write_reg(ssp, SSPSP, sspsp); + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBM_CFS: + scfr = pxa_ssp_read_reg(ssp, SSCR1) | SSCR1_SCFR; + pxa_ssp_write_reg(ssp, SSCR1, scfr); + + while (pxa_ssp_read_reg(ssp, SSSR) & SSSR_BSY) + cpu_relax(); + break; + } + dump_registers(ssp); /* Since we are configuring the timings for the format by hand @@ -583,10 +592,8 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, /* clear selected SSP bits */ sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS); - pxa_ssp_write_reg(ssp, SSCR0, sscr0); /* bit size */ - sscr0 = pxa_ssp_read_reg(ssp, SSCR0); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: #ifdef CONFIG_PXA3xx -- cgit v1.2.3-59-g8ed1b From eaae183f4b3f25522cd13ebf30162c1cb863b1f1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Aug 2010 19:26:28 +0100 Subject: ASoC: Add a bit of resource unwinding in the S3C IISv4 driver There's much more needed but this'll get us started. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/s3c24xx/s3c64xx-i2s-v4.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c index a13415a85a45..a9628472ebfe 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c @@ -187,7 +187,18 @@ err: static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev) { + struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4; + struct resource *res; + snd_soc_unregister_dai(&pdev->dev); + clk_put(i2s->iis_cclk); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) + release_mem_region(res->start, resource_size(res)); + else + dev_warn(&pdev->dev, "Unable to get I2S SFR address\n"); + return 0; } -- cgit v1.2.3-59-g8ed1b From e231cab0a4b5844ae13a9584433ca3b9b204629e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Aug 2010 17:57:28 +0100 Subject: ASoC: Convert WM8580 hw_params to use snd_soc_update_bits() All the cool kids are using snd_soc_update_bits() these days. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8580.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index b1a80e5ff8b5..4f414199d76d 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -485,9 +485,8 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->driver->id); + u16 paifb = 0; - paifb &= ~WM8580_AIF_LENGTH_MASK; /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: @@ -505,7 +504,8 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - snd_soc_write(codec, WM8580_PAIF3 + dai->driver->id, paifb); + snd_soc_update_bits(codec, WM8580_PAIF3 + dai->driver->id, + WM8580_AIF_LENGTH_MASK, paifb); return 0; } -- cgit v1.2.3-59-g8ed1b From 8ef339df25ed424e7430fd411a52840c6af368c6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Aug 2010 18:09:52 +0100 Subject: ASoC: Remove unused rate selection bitmasks from WM8580 In the case of the BCLK rate the defines are at best misleading anyway. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8580.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 4f414199d76d..9964f02f84e2 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -112,19 +112,7 @@ /* AIF control 1 (registers 9h-bh) */ #define WM8580_AIF_RATE_MASK 0x7 -#define WM8580_AIF_RATE_128 0x0 -#define WM8580_AIF_RATE_192 0x1 -#define WM8580_AIF_RATE_256 0x2 -#define WM8580_AIF_RATE_384 0x3 -#define WM8580_AIF_RATE_512 0x4 -#define WM8580_AIF_RATE_768 0x5 -#define WM8580_AIF_RATE_1152 0x6 - #define WM8580_AIF_BCLKSEL_MASK 0x18 -#define WM8580_AIF_BCLKSEL_64 0x00 -#define WM8580_AIF_BCLKSEL_128 0x08 -#define WM8580_AIF_BCLKSEL_256 0x10 -#define WM8580_AIF_BCLKSEL_SYSCLK 0x18 #define WM8580_AIF_MS 0x20 -- cgit v1.2.3-59-g8ed1b From c5607d8e7a4c30d2ff62b8eefe3f977d5c71d2fe Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Aug 2010 19:05:04 +0100 Subject: ASoC: Automatically calculate clock ratio for WM8580 Implement set_sysclk() and then rather than assuming 256fs use the supplied value to calculate and configure the clock ratio for the currently used sample rate. As a side effect we also end up implementing clock selection for the ADC path. In order to avoid confusion remove the existing set_clkdiv() based configuration of the clock source for the DAC and update the SMDK64xx driver (which is the only in-tree user of the CODEC). Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8580.c | 101 ++++++++++++++++++++++++++++-------- sound/soc/codecs/wm8580.h | 14 ++--- sound/soc/s3c24xx/smdk64xx_wm8580.c | 9 ++-- 3 files changed, 90 insertions(+), 34 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 9964f02f84e2..7942f917d31e 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -192,6 +192,7 @@ struct wm8580_priv { u16 reg_cache[WM8580_MAX_REGISTER + 1]; struct pll_state a; struct pll_state b; + int sysclk[2]; }; static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); @@ -464,6 +465,10 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, return 0; } +static const int wm8580_sysclk_ratios[] = { + 128, 192, 256, 384, 512, 768, 1152, +}; + /* * Set PCM DAI bit size and sample rate. */ @@ -473,7 +478,10 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; + struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); + u16 paifa = 0; u16 paifb = 0; + int i, ratio; /* bit size */ switch (params_format(params)) { @@ -492,6 +500,22 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + /* Look up the SYSCLK ratio; accept only exact matches */ + ratio = wm8580->sysclk[dai->id] / params_rate(params); + for (i = 0; i < ARRAY_SIZE(wm8580_sysclk_ratios); i++) + if (ratio == wm8580_sysclk_ratios[i]) + break; + if (i == ARRAY_SIZE(wm8580_sysclk_ratios)) { + dev_err(codec->dev, "Invalid clock ratio %d/%d\n", + wm8580->sysclk[dai->id], params_rate(params)); + return -EINVAL; + } + paifa |= i; + dev_dbg(codec->dev, "Running at %dfs with %dHz clock\n", + wm8580_sysclk_ratios[i], wm8580->sysclk[dai->driver->id]); + + snd_soc_update_bits(codec, WM8580_PAIF1 + dai->driver->id, + WM8580_AIF_RATE_MASK, paifa); snd_soc_update_bits(codec, WM8580_PAIF3 + dai->driver->id, WM8580_AIF_LENGTH_MASK, paifb); return 0; @@ -501,9 +525,11 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; + struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); unsigned int aifa; unsigned int aifb; int can_invert_lrclk; + int sysclk; aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->driver->id); aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->driver->id); @@ -572,6 +598,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } + sysclk = wm8580->sysclk[codec_dai->driver->id]; + snd_soc_write(codec, WM8580_PAIF1 + codec_dai->driver->id, aifa); snd_soc_write(codec, WM8580_PAIF3 + codec_dai->driver->id, aifb); @@ -611,28 +639,6 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, snd_soc_write(codec, WM8580_PLLB4, reg); break; - case WM8580_DAC_CLKSEL: - reg = snd_soc_read(codec, WM8580_CLKSEL); - reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK; - - switch (div) { - case WM8580_CLKSRC_MCLK: - break; - - case WM8580_CLKSRC_PLLA: - reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLA; - break; - - case WM8580_CLKSRC_PLLB: - reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLB; - break; - - default: - return -EINVAL; - } - snd_soc_write(codec, WM8580_CLKSEL, reg); - break; - case WM8580_CLKOUTSRC: reg = snd_soc_read(codec, WM8580_PLLB4); reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; @@ -666,6 +672,55 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, return 0; } +static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); + int sel, sel_mask, sel_shift; + + switch (dai->driver->id) { + case WM8580_DAI_PAIFTX: + sel_mask = 0x3; + sel_shift = 0; + break; + + case WM8580_DAI_PAIFRX: + sel_mask = 0xc; + sel_shift = 2; + break; + + default: + BUG_ON("Unknown DAI driver ID\n"); + return -EINVAL; + } + + switch (clk_id) { + case WM8580_CLKSRC_ADCMCLK: + if (dai->id != WM8580_DAI_PAIFTX) + return -EINVAL; + sel = 0 << sel_shift; + break; + case WM8580_CLKSRC_PLLA: + sel = 1 << sel_shift; + break; + case WM8580_CLKSRC_PLLB: + sel = 2 << sel_shift; + break; + case WM8580_CLKSRC_MCLK: + sel = 3 << sel_shift; + break; + default: + dev_err(codec->dev, "Unknown clock %d\n", clk_id); + return -EINVAL; + } + + /* We really should validate PLL settings but not yet */ + wm8580->sysclk[dai->id] = freq; + + return snd_soc_update_bits(codec, WM8580_CLKSEL, sel, sel_mask); +} + static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) { struct snd_soc_codec *codec = codec_dai->codec; @@ -719,6 +774,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) static struct snd_soc_dai_ops wm8580_dai_ops_playback = { + .set_sysclk = wm8580_set_sysclk, .hw_params = wm8580_paif_hw_params, .set_fmt = wm8580_set_paif_dai_fmt, .set_clkdiv = wm8580_set_dai_clkdiv, @@ -727,6 +783,7 @@ static struct snd_soc_dai_ops wm8580_dai_ops_playback = { }; static struct snd_soc_dai_ops wm8580_dai_ops_capture = { + .set_sysclk = wm8580_set_sysclk, .hw_params = wm8580_paif_hw_params, .set_fmt = wm8580_set_paif_dai_fmt, .set_clkdiv = wm8580_set_dai_clkdiv, diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h index 8328ef667593..1d34656d0dcb 100644 --- a/sound/soc/codecs/wm8580.h +++ b/sound/soc/codecs/wm8580.h @@ -19,14 +19,14 @@ #define WM8580_PLLB 2 #define WM8580_MCLK 1 -#define WM8580_DAC_CLKSEL 2 -#define WM8580_CLKOUTSRC 3 +#define WM8580_CLKOUTSRC 2 -#define WM8580_CLKSRC_MCLK 1 -#define WM8580_CLKSRC_PLLA 2 -#define WM8580_CLKSRC_PLLB 3 -#define WM8580_CLKSRC_OSC 4 -#define WM8580_CLKSRC_NONE 5 +#define WM8580_CLKSRC_MCLK 1 +#define WM8580_CLKSRC_PLLA 2 +#define WM8580_CLKSRC_PLLB 3 +#define WM8580_CLKSRC_OSC 4 +#define WM8580_CLKSRC_NONE 5 +#define WM8580_CLKSRC_ADCMCLK 6 #define WM8580_DAI_PAIFRX 0 #define WM8580_DAI_PAIFTX 1 diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c index 5c21e26da075..91367f7bfec3 100644 --- a/sound/soc/s3c24xx/smdk64xx_wm8580.c +++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c @@ -113,14 +113,13 @@ static int smdk64xx_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - /* Explicitly set WM8580-DAC to source from MCLK */ - ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_DAC_CLKSEL, - WM8580_CLKSRC_MCLK); + ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0, + SMDK64XX_WM8580_FREQ, pll_out); if (ret < 0) return ret; - ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0, - SMDK64XX_WM8580_FREQ, pll_out); + ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA, + pll_out, SND_SOC_CLOCK_IN); if (ret < 0) return ret; -- cgit v1.2.3-59-g8ed1b From ba2772edbe1f03a695029ca82844615fe41d28fc Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Aug 2010 19:36:56 +0100 Subject: ASoC: Implement BCLK rate selection for WM8580 Drive a minimal supported number of clocks required for the current bit format in master mode. In slave mode this setting has no effect. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8580.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 7942f917d31e..b6b2d6f8cba9 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -486,14 +486,18 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: + paifa |= 0x8; break; case SNDRV_PCM_FORMAT_S20_3LE: + paifa |= 0x10; paifb |= WM8580_AIF_LENGTH_20; break; case SNDRV_PCM_FORMAT_S24_LE: + paifa |= 0x10; paifb |= WM8580_AIF_LENGTH_24; break; case SNDRV_PCM_FORMAT_S32_LE: + paifa |= 0x10; paifb |= WM8580_AIF_LENGTH_24; break; default: @@ -515,7 +519,8 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, wm8580_sysclk_ratios[i], wm8580->sysclk[dai->driver->id]); snd_soc_update_bits(codec, WM8580_PAIF1 + dai->driver->id, - WM8580_AIF_RATE_MASK, paifa); + WM8580_AIF_RATE_MASK | WM8580_AIF_BCLKSEL_MASK, + paifa); snd_soc_update_bits(codec, WM8580_PAIF3 + dai->driver->id, WM8580_AIF_LENGTH_MASK, paifb); return 0; -- cgit v1.2.3-59-g8ed1b From dacfe9f277f765dcebc7b34588d3af4a687ea2f3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Aug 2010 20:01:32 +0100 Subject: ASoC: Fix inverted WM8580 capture mute control Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8580.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index b6b2d6f8cba9..834cf141ea2f 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -262,7 +262,7 @@ SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 0), SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 0), SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 0), -SOC_DOUBLE("Capture Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), +SOC_DOUBLE("Capture Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 1), SOC_SINGLE("Capture High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), }; -- cgit v1.2.3-59-g8ed1b From 6bfb6aa91f61f2a7c526a6353c8c50676ca528da Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Aug 2010 20:08:55 +0100 Subject: ASoC: Automatically manage WM8580 DAC OSR The DAC OSR should be selected based on the sample clock ratio. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8580.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 834cf141ea2f..d66db4bf11e4 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -94,6 +94,8 @@ #define WM8580_MAX_REGISTER 0x35 +#define WM8580_DACOSR 0x40 + /* PLLB4 (register 7h) */ #define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60 #define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20 @@ -481,7 +483,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); u16 paifa = 0; u16 paifb = 0; - int i, ratio; + int i, ratio, osr; /* bit size */ switch (params_format(params)) { @@ -518,6 +520,22 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, dev_dbg(codec->dev, "Running at %dfs with %dHz clock\n", wm8580_sysclk_ratios[i], wm8580->sysclk[dai->driver->id]); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (ratio) { + case 128: + case 192: + osr = WM8580_DACOSR; + dev_dbg(codec->dev, "Selecting 64x OSR\n"); + break; + default: + osr = 0; + dev_dbg(codec->dev, "Selecting 128x OSR\n"); + break; + } + + snd_soc_update_bits(codec, WM8580_PAIF3, WM8580_DACOSR, osr); + } + snd_soc_update_bits(codec, WM8580_PAIF1 + dai->driver->id, WM8580_AIF_RATE_MASK | WM8580_AIF_BCLKSEL_MASK, paifa); -- cgit v1.2.3-59-g8ed1b From e583d6b3c25d4ce3867b345782abd7d11a0d384c Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 14 Aug 2010 12:23:39 +0000 Subject: sh: fix recursive dependency in Kconfig When executing: make ARCH=sh defconfig kconfig segfaulted. kconfig should obviously not segfault. But this indicated a problem in the sh files which was tracked down to a recursive dependency. We select HAVE_HW_BREAKPOINT and in the following line we use the same symbol in an expression. Drop the conditional as it is of no use. Signed-off-by: Sam Ravnborg Cc: Michal Marek Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index b2b90ee39447..2284215981ed 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -46,7 +46,7 @@ config SUPERH32 select HAVE_ARCH_KGDB select HAVE_HW_BREAKPOINT select HAVE_MIXED_BREAKPOINTS_REGS - select PERF_EVENTS if HAVE_HW_BREAKPOINT + select PERF_EVENTS select ARCH_HIBERNATION_POSSIBLE if MMU config SUPERH64 -- cgit v1.2.3-59-g8ed1b From 3e497df14d3cb900377094f36eeb8c17cec6f795 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Aug 2010 13:51:18 +0900 Subject: sh: wire up fanotify/prlimit64 syscalls. Signed-off-by: Paul Mundt --- arch/sh/include/asm/unistd_32.h | 5 ++++- arch/sh/include/asm/unistd_64.h | 5 ++++- arch/sh/kernel/syscalls_32.S | 3 +++ arch/sh/kernel/syscalls_64.S | 3 +++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h index 0e7f0fc8f086..01183add5687 100644 --- a/arch/sh/include/asm/unistd_32.h +++ b/arch/sh/include/asm/unistd_32.h @@ -345,8 +345,11 @@ #define __NR_pwritev 334 #define __NR_rt_tgsigqueueinfo 335 #define __NR_perf_event_open 336 +#define __NR_fanotify_init 337 +#define __NR_fanotify_mark 338 +#define __NR_prlimit64 339 -#define NR_syscalls 337 +#define NR_syscalls 340 #ifdef __KERNEL__ diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h index 0580c33a1e04..09aa93f9eb70 100644 --- a/arch/sh/include/asm/unistd_64.h +++ b/arch/sh/include/asm/unistd_64.h @@ -387,10 +387,13 @@ #define __NR_perf_event_open 364 #define __NR_recvmmsg 365 #define __NR_accept4 366 +#define __NR_fanotify_init 367 +#define __NR_fanotify_mark 368 +#define __NR_prlimit64 369 #ifdef __KERNEL__ -#define NR_syscalls 367 +#define NR_syscalls 370 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index 19fd11dd9871..3c6d669740a7 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S @@ -353,3 +353,6 @@ ENTRY(sys_call_table) .long sys_pwritev .long sys_rt_tgsigqueueinfo /* 335 */ .long sys_perf_event_open + .long sys_fanotify_init + .long sys_fanotify_mark + .long sys_prlimit64 diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 2048a20d7c80..66585708ce90 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S @@ -393,3 +393,6 @@ sys_call_table: .long sys_perf_event_open .long sys_recvmmsg /* 365 */ .long sys_accept4 + .long sys_fanotify_init + .long sys_fanotify_mark + .long sys_prlimit64 -- cgit v1.2.3-59-g8ed1b From d5b7fb7bb8a014ee96cd39b410fc57a7dc239a91 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Aug 2010 14:52:06 +0900 Subject: sh: fix up fallout from syscall arg constification. sys_execve() now takes a const pointer, so reflect this change where the syscall is actually defined, too. Fixes up a build error due to prototype mismatch. Signed-off-by: Paul Mundt --- arch/sh/kernel/process_32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 052981972ae6..ee22a583d48c 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -296,7 +296,8 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, /* * sys_execve() executes a new program. */ -asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv, +asmlinkage int sys_execve(const char __user *ufilename, + char __user * __user *uargv, char __user * __user *uenvp, unsigned long r7, struct pt_regs __regs) { -- cgit v1.2.3-59-g8ed1b From a8dc49b51ace4ff80cb764c250338cb9b311fb14 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Aug 2010 14:53:01 +0900 Subject: sh: stub __flush_tlb_global() definition for nommu. This fixes up the nommu build with a stub definition for __flush_tlb_global(), now used by the reboot code. Signed-off-by: Paul Mundt --- arch/sh/mm/nommu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/sh/mm/nommu.c b/arch/sh/mm/nommu.c index 7694f50c9034..36312d254faf 100644 --- a/arch/sh/mm/nommu.c +++ b/arch/sh/mm/nommu.c @@ -67,6 +67,10 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) BUG(); } +void __flush_tlb_global(void) +{ +} + void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) { } -- cgit v1.2.3-59-g8ed1b From bbff2168c1088995753e889580c756971eca51e4 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 11 Aug 2010 18:34:09 +0200 Subject: paravirt: noreplace-paravirt is implemented for x86 and ia-64 kernel-parameters.txt lists 'noreplace-paravirt' parameter as being limited to X86-32, which is incorrect -- it's actually supported by x86-32, x86-64 and ia-64. Signed-off-by: Jiri Kosina Acked-by: Jeremy Fitzhardinge --- Documentation/kernel-parameters.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d529b1363e95..8ed3a7772da1 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1777,7 +1777,7 @@ and is between 256 and 4096 characters. It is defined in the file norandmaps Don't use address space randomization. Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space - noreplace-paravirt [X86-32,PV_OPS] Don't patch paravirt_ops + noreplace-paravirt [X86,IA-64,PV_OPS] Don't patch paravirt_ops noreplace-smp [X86-32,SMP] Don't replace SMP instructions with UP alternatives -- cgit v1.2.3-59-g8ed1b From 8aed62882129c4e7608deb6fe1a39b44a9aa4539 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Sat, 14 Aug 2010 09:43:21 -0700 Subject: vesafb: fix comment a typo Signed-off-by: Justin P. Mattock Signed-off-by: Jiri Kosina --- drivers/video/vesafb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 090aa1a9be6e..6a069d047914 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -253,7 +253,7 @@ static int __init vesafb_probe(struct platform_device *dev) size_vmode = vesafb_defined.yres * vesafb_fix.line_length; /* size_total -- all video memory we have. Used for mtrr - * entries, ressource allocation and bounds + * entries, resource allocation and bounds * checking. */ size_total = screen_info.lfb_size * 65536; if (vram_total) -- cgit v1.2.3-59-g8ed1b From c84e032e145775032fa9078b55e6333dd866603b Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Sat, 14 Aug 2010 09:43:22 -0700 Subject: include/video/vga.h: update web address. The below updates a broken web address to one(hopefully) thats the new correct address. Signed-off-by: Justin P. Mattock Signed-off-by: Jiri Kosina --- include/video/vga.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/video/vga.h b/include/video/vga.h index b49a5120ca2d..2b8691f7d256 100644 --- a/include/video/vga.h +++ b/include/video/vga.h @@ -5,7 +5,7 @@ * * Copyright history from vga16fb.c: * Copyright 1999 Ben Pfaff and Petr Vandrovec - * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm + * Based on VGA info at http://www.osdever.net/FreeVGA/home.htm * Based on VESA framebuffer (c) 1998 Gerd Knorr * * This file is subject to the terms and conditions of the GNU General -- cgit v1.2.3-59-g8ed1b From 652caa5b67b096b13c34f299db238e1daeab1f67 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Jul 2010 13:27:28 -0400 Subject: b43: update hw/fw version info in wiphy struct This makes the information available through ethtool... Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 20631ae2ddd7..294b68895822 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2280,6 +2280,7 @@ out: static int b43_upload_microcode(struct b43_wldev *dev) { + struct wiphy *wiphy = dev->wl->hw->wiphy; const size_t hdr_len = sizeof(struct b43_fw_header); const __be32 *data; unsigned int i, len; @@ -2405,6 +2406,10 @@ static int b43_upload_microcode(struct b43_wldev *dev) } } + snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u", + dev->fw.rev, dev->fw.patch); + wiphy->hw_version = dev->dev->id.coreid; + if (b43_is_old_txhdr_format(dev)) { /* We're over the deadline, but we keep support for old fw * until it turns out to be in major conflict with something new. */ -- cgit v1.2.3-59-g8ed1b From bcf3c7c5264f06cd2542e6bece94c65bf0ac482b Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Jul 2010 13:30:15 -0400 Subject: b43legacy: update hw/fw version info in wiphy struct This makes the information available through ethtool... Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1713f5f7a58b..67f18ecdb3bf 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -1623,6 +1623,7 @@ error: static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) { + struct wiphy *wiphy = dev->wl->hw->wiphy; const size_t hdr_len = sizeof(struct b43legacy_fw_header); const __be32 *data; unsigned int i; @@ -1732,6 +1733,10 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) dev->fw.rev = fwrev; dev->fw.patch = fwpatch; + snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u", + dev->fw.rev, dev->fw.patch); + wiphy->hw_version = dev->dev->id.coreid; + return 0; error: -- cgit v1.2.3-59-g8ed1b From 37269e805267ba68fe8c5d693ccf0ec5727155fa Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Jul 2010 13:44:44 -0400 Subject: p54: update fw version info in wiphy struct This makes the information available through ethtool... Signed-off-by: John W. Linville --- drivers/net/wireless/p54/fwio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index 47006bca4852..6f027ab4c775 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -123,10 +123,14 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) bootrec = (struct bootrec *)&bootrec->data[len]; } - if (fw_version) + if (fw_version) { wiphy_info(priv->hw->wiphy, "fw rev %s - softmac protocol %x.%x\n", fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); + snprintf(dev->wiphy->fw_version, sizeof(dev->wiphy->fw_version), + "%s - %x.%x", fw_version, + priv->fw_var >> 8, priv->fw_var & 0xff); + } if (priv->fw_var < 0x500) wiphy_info(priv->hw->wiphy, -- cgit v1.2.3-59-g8ed1b From dd358c9a45fc27f90e77992cf77117ab6e2fb467 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Jul 2010 13:50:39 -0400 Subject: rt2x00: update fw version info in wiphy struct This makes the information available through ethtool... Signed-off-by: John W. Linville Acked-by: Ivo van Doorn --- drivers/net/wireless/rt2x00/rt2x00firmware.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index b818a43c4672..f0e1eb72befc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -63,6 +63,9 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", fw->data[fw->size - 4], fw->data[fw->size - 3]); + snprintf(rt2x00dev->hw->wiphy->fw_version, + sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d", + fw->data[fw->size - 4], fw->data[fw->size - 3]); retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size); switch (retval) { -- cgit v1.2.3-59-g8ed1b From 68e887ef21dfd9adcf896ef92a9676bf9036a0aa Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Jul 2010 13:58:48 -0400 Subject: zd1211rw: update fw version info in wiphy struct This makes the information available through ethtool... Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_chip.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index b2af3c549bb3..87a95bcfee57 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -973,6 +973,7 @@ static void dump_fw_registers(struct zd_chip *chip) static int print_fw_version(struct zd_chip *chip) { + struct wiphy *wiphy = zd_chip_to_mac(chip)->hw->wiphy; int r; u16 version; @@ -982,6 +983,10 @@ static int print_fw_version(struct zd_chip *chip) return r; dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version); + + snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), + "%04hx", version); + return 0; } -- cgit v1.2.3-59-g8ed1b From 4e6cbfd09c66893e5134c9896e9af353c2322b66 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Jul 2010 16:14:13 -0400 Subject: mac80211: support use of NAPI for bottom-half processing This patch implement basic infrastructure to support use of NAPI by mac80211-based hardware drivers. Because mac80211 devices can support multiple netdevs, a dummy netdev is used for interfacing with the NAPI code in the core of the network stack. That structure is hidden from the hardware drivers, but the actual napi_struct is exposed in the ieee80211_hw structure so that the poll routines in drivers can retrieve that structure. Hardware drivers can also specify their own weight value for NAPI polling. Signed-off-by: John W. Linville --- include/net/mac80211.h | 24 ++++++++++++++++++++++++ net/mac80211/ieee80211_i.h | 5 +++++ net/mac80211/iface.c | 4 ++++ net/mac80211/main.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index b0787a1dea90..3f1e03b521ec 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1102,6 +1102,10 @@ enum ieee80211_hw_flags { * * @max_rates: maximum number of alternate rate retry stages * @max_rate_tries: maximum number of tries for each stage + * + * @napi_weight: weight used for NAPI polling. You must specify an + * appropriate value here if a napi_poll operation is provided + * by your driver. */ struct ieee80211_hw { struct ieee80211_conf conf; @@ -1113,6 +1117,7 @@ struct ieee80211_hw { int channel_change_time; int vif_data_size; int sta_data_size; + int napi_weight; u16 queues; u16 max_listen_interval; s8 max_signal; @@ -1687,6 +1692,8 @@ enum ieee80211_ampdu_mlme_action { * switch operation for CSAs received from the AP may implement this * callback. They must then call ieee80211_chswitch_done() to indicate * completion of the channel switch. + * + * @napi_poll: Poll Rx queue for incoming data frames. */ struct ieee80211_ops { int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); @@ -1752,6 +1759,7 @@ struct ieee80211_ops { void (*flush)(struct ieee80211_hw *hw, bool drop); void (*channel_switch)(struct ieee80211_hw *hw, struct ieee80211_channel_switch *ch_switch); + int (*napi_poll)(struct ieee80211_hw *hw, int budget); }; /** @@ -1897,6 +1905,22 @@ void ieee80211_free_hw(struct ieee80211_hw *hw); */ void ieee80211_restart_hw(struct ieee80211_hw *hw); +/** ieee80211_napi_schedule - schedule NAPI poll + * + * Use this function to schedule NAPI polling on a device. + * + * @hw: the hardware to start polling + */ +void ieee80211_napi_schedule(struct ieee80211_hw *hw); + +/** ieee80211_napi_complete - complete NAPI polling + * + * Use this function to finish NAPI polling on a device. + * + * @hw: the hardware to stop polling + */ +void ieee80211_napi_complete(struct ieee80211_hw *hw); + /** * ieee80211_rx - receive frame * diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 65e0ed6c2975..79d56454484a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -870,6 +870,11 @@ struct ieee80211_local { struct dentry *keys; } debugfs; #endif + + /* dummy netdev for use w/ NAPI */ + struct net_device napi_dev; + + struct napi_struct napi; }; static inline struct ieee80211_sub_if_data * diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ebbe264e2b0b..c1008a9d7bfb 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -187,6 +187,8 @@ static int ieee80211_open(struct net_device *dev) res = drv_start(local); if (res) goto err_del_bss; + if (local->ops->napi_poll) + napi_enable(&local->napi); /* we're brought up, everything changes */ hw_reconf_flags = ~0; ieee80211_led_radio(local, true); @@ -519,6 +521,8 @@ static int ieee80211_stop(struct net_device *dev) ieee80211_recalc_ps(local, -1); if (local->open_count == 0) { + if (local->ops->napi_poll) + napi_disable(&local->napi); ieee80211_clear_tx_pending(local); ieee80211_stop_device(local); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 798a91b100cc..1ed956c9cb8b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -390,6 +390,30 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, } #endif +static int ieee80211_napi_poll(struct napi_struct *napi, int budget) +{ + struct ieee80211_local *local = + container_of(napi, struct ieee80211_local, napi); + + return local->ops->napi_poll(&local->hw, budget); +} + +void ieee80211_napi_schedule(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + + napi_schedule(&local->napi); +} +EXPORT_SYMBOL(ieee80211_napi_schedule); + +void ieee80211_napi_complete(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + + napi_complete(&local->napi); +} +EXPORT_SYMBOL(ieee80211_napi_complete); + struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, const struct ieee80211_ops *ops) { @@ -494,6 +518,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, skb_queue_head_init(&local->skb_queue); skb_queue_head_init(&local->skb_queue_unreliable); + /* init dummy netdev for use w/ NAPI */ + init_dummy_netdev(&local->napi_dev); + return local_to_hw(local); } EXPORT_SYMBOL(ieee80211_alloc_hw); @@ -683,6 +710,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) goto fail_ifa; #endif + netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, + local->hw.napi_weight); + return 0; #ifdef CONFIG_INET -- cgit v1.2.3-59-g8ed1b From 030725d2c7c1fafec7ede618647bf30ed79601f0 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Jul 2010 16:14:14 -0400 Subject: rtl8180: use NAPI for bottom-half processing Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8180_dev.c | 128 ++++++++++++++++------------- 1 file changed, 69 insertions(+), 59 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index b50c39aaec05..02d0f71d0faa 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -99,19 +99,66 @@ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) } } -static void rtl8180_handle_rx(struct ieee80211_hw *dev) +static void rtl8180_handle_tx(struct ieee80211_hw *dev) { struct rtl8180_priv *priv = dev->priv; - unsigned int count = 32; + struct rtl8180_tx_ring *ring; + int prio; + + spin_lock(&priv->lock); + + for (prio = 3; prio >= 0; prio--) { + ring = &priv->tx_ring[prio]; + + while (skb_queue_len(&ring->queue)) { + struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb; + struct ieee80211_tx_info *info; + u32 flags = le32_to_cpu(entry->flags); + + if (flags & RTL818X_TX_DESC_FLAG_OWN) + break; + + ring->idx = (ring->idx + 1) % ring->entries; + skb = __skb_dequeue(&ring->queue); + pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), + skb->len, PCI_DMA_TODEVICE); + + info = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(info); + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && + (flags & RTL818X_TX_DESC_FLAG_TX_OK)) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.rates[0].count = (flags & 0xFF) + 1; + info->status.rates[1].idx = -1; + + ieee80211_tx_status(dev, skb); + if (ring->entries - skb_queue_len(&ring->queue) == 2) + ieee80211_wake_queue(dev, prio); + } + } + + spin_unlock(&priv->lock); +} + +static int rtl8180_poll(struct ieee80211_hw *dev, int budget) +{ + struct rtl8180_priv *priv = dev->priv; + unsigned int count = 0; u8 signal, agc, sq; - while (count--) { + /* handle pending Tx queue cleanup */ + rtl8180_handle_tx(dev); + + while (count++ < budget) { struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; u32 flags = le32_to_cpu(entry->flags); if (flags & RTL818X_RX_DESC_FLAG_OWN) - return; + break; if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | RTL818X_RX_DESC_FLAG_FOF | @@ -151,7 +198,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - ieee80211_rx_irqsafe(dev, skb); + ieee80211_rx(dev, skb); skb = new_skb; priv->rx_buf[priv->rx_idx] = skb; @@ -168,41 +215,16 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); priv->rx_idx = (priv->rx_idx + 1) % 32; } -} - -static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_tx_ring *ring = &priv->tx_ring[prio]; - - while (skb_queue_len(&ring->queue)) { - struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - u32 flags = le32_to_cpu(entry->flags); - - if (flags & RTL818X_TX_DESC_FLAG_OWN) - return; - - ring->idx = (ring->idx + 1) % ring->entries; - skb = __skb_dequeue(&ring->queue); - pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), - skb->len, PCI_DMA_TODEVICE); - - info = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(info); - - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && - (flags & RTL818X_TX_DESC_FLAG_TX_OK)) - info->flags |= IEEE80211_TX_STAT_ACK; - info->status.rates[0].count = (flags & 0xFF) + 1; - info->status.rates[1].idx = -1; + if (count < budget) { + /* disable polling */ + ieee80211_napi_complete(dev); - ieee80211_tx_status_irqsafe(dev, skb); - if (ring->entries - skb_queue_len(&ring->queue) == 2) - ieee80211_wake_queue(dev, prio); + /* enable interrupts */ + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); } + + return count; } static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) @@ -211,31 +233,17 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) struct rtl8180_priv *priv = dev->priv; u16 reg; - spin_lock(&priv->lock); reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); - if (unlikely(reg == 0xFFFF)) { - spin_unlock(&priv->lock); + if (unlikely(reg == 0xFFFF)) return IRQ_HANDLED; - } rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); - if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR)) - rtl8180_handle_tx(dev, 3); - - if (reg & (RTL818X_INT_TXH_OK | RTL818X_INT_TXH_ERR)) - rtl8180_handle_tx(dev, 2); - - if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR)) - rtl8180_handle_tx(dev, 1); - - if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR)) - rtl8180_handle_tx(dev, 0); - - if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR)) - rtl8180_handle_rx(dev); + /* disable interrupts */ + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); - spin_unlock(&priv->lock); + /* enable polling */ + ieee80211_napi_schedule(dev); return IRQ_HANDLED; } @@ -247,7 +255,6 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) struct rtl8180_priv *priv = dev->priv; struct rtl8180_tx_ring *ring; struct rtl8180_tx_desc *entry; - unsigned long flags; unsigned int idx, prio; dma_addr_t mapping; u32 tx_flags; @@ -294,7 +301,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) plcp_len |= 1 << 15; } - spin_lock_irqsave(&priv->lock, flags); + spin_lock(&priv->lock); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) @@ -318,7 +325,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) if (ring->entries - skb_queue_len(&ring->queue) < 2) ieee80211_stop_queue(dev, prio); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock(&priv->lock); rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); @@ -861,6 +868,7 @@ static const struct ieee80211_ops rtl8180_ops = { .prepare_multicast = rtl8180_prepare_multicast, .configure_filter = rtl8180_configure_filter, .get_tsf = rtl8180_get_tsf, + .napi_poll = rtl8180_poll, }; static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) @@ -992,6 +1000,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, dev->queues = 1; dev->max_signal = 65; + dev->napi_weight = 64; + reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); reg &= RTL818X_TX_CONF_HWVER_MASK; switch (reg) { -- cgit v1.2.3-59-g8ed1b From 0f956e7107fe5069767323a1bf2a522f5f37cc2c Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Jul 2010 21:50:29 -0400 Subject: rtl8180: use RTL818X_MSR_ADHOC for IBSS connection Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8180_dev.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 02d0f71d0faa..9544eb1a23dc 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -790,6 +790,7 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, struct rtl8180_priv *priv = dev->priv; struct rtl8180_vif *vif_priv; int i; + u8 reg; vif_priv = (struct rtl8180_vif *)&vif->drv_priv; @@ -798,12 +799,14 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, rtl818x_iowrite8(priv, &priv->map->BSSID[i], info->bssid[i]); - if (is_valid_ether_addr(info->bssid)) - rtl818x_iowrite8(priv, &priv->map->MSR, - RTL818X_MSR_INFRA); - else - rtl818x_iowrite8(priv, &priv->map->MSR, - RTL818X_MSR_NO_LINK); + if (is_valid_ether_addr(info->bssid)) { + if (vif->type == NL80211_IFTYPE_ADHOC) + reg = RTL818X_MSR_ADHOC; + else + reg = RTL818X_MSR_INFRA; + } else + reg = RTL818X_MSR_NO_LINK; + rtl818x_iowrite8(priv, &priv->map->MSR, reg); } if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) -- cgit v1.2.3-59-g8ed1b From 31a5cddaaed9c04ef653e3c2900cfb5a646fe686 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Jul 2010 21:52:59 -0400 Subject: rtl8187: consolidate MSR writes in rtl8187_bss_info_changed Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187_dev.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 5738a55c1b06..0801c1d7c8d4 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1176,13 +1176,12 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, else reg = 0; - if (is_valid_ether_addr(info->bssid)) { + if (is_valid_ether_addr(info->bssid)) reg |= RTL818X_MSR_INFRA; - rtl818x_iowrite8(priv, &priv->map->MSR, reg); - } else { + else reg |= RTL818X_MSR_NO_LINK; - rtl818x_iowrite8(priv, &priv->map->MSR, reg); - } + + rtl818x_iowrite8(priv, &priv->map->MSR, reg); mutex_unlock(&priv->conf_mutex); } -- cgit v1.2.3-59-g8ed1b From c61029c77fb68d7a182c0ae010f0f9dcae4e196c Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 5 Aug 2010 14:26:24 -0400 Subject: wireless: upcase alpha2 values in queue_regulatory_request This provides a little more flexibility for human users, and it allows us to use isalpha rather than the custom is_alpha_upper. Signed-off-by: John W. Linville --- net/wireless/reg.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f180db0de66c..b0d9a08447c9 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -181,14 +182,6 @@ static bool is_alpha2_set(const char *alpha2) return false; } -static bool is_alpha_upper(char letter) -{ - /* ASCII A - Z */ - if (letter >= 65 && letter <= 90) - return true; - return false; -} - static bool is_unknown_alpha2(const char *alpha2) { if (!alpha2) @@ -220,7 +213,7 @@ static bool is_an_alpha2(const char *alpha2) { if (!alpha2) return false; - if (is_alpha_upper(alpha2[0]) && is_alpha_upper(alpha2[1])) + if (isalpha(alpha2[0]) && isalpha(alpha2[1])) return true; return false; } @@ -1399,6 +1392,11 @@ static DECLARE_WORK(reg_work, reg_todo); static void queue_regulatory_request(struct regulatory_request *request) { + if (isalpha(request->alpha2[0])) + request->alpha2[0] = toupper(request->alpha2[0]); + if (isalpha(request->alpha2[1])) + request->alpha2[1] = toupper(request->alpha2[1]); + spin_lock(®_requests_lock); list_add_tail(&request->list, ®_requests_list); spin_unlock(®_requests_lock); -- cgit v1.2.3-59-g8ed1b From 1a7123cdd9f49cf1c908fb2c16d26f279c88d8c9 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 5 Aug 2010 14:39:31 -0400 Subject: iwlwifi: disable aspm by default Some iwlwifi devices inexplicably disconnect themselves from the PCI-E bus causing the predictable failures. This seems to disappear if ASPM is disabled. Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 35337b1e7cac..49a7a9889c55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -3968,6 +3969,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /************************** * 2. Initializing PCI bus **************************/ + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | + PCIE_LINK_STATE_CLKPM); + if (pci_enable_device(pdev)) { err = -ENODEV; goto out_ieee80211_free_hw; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d24eb47d3705..bc08242db2ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -3963,6 +3964,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /*************************** * 2. Initializing PCI bus * *************************/ + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | + PCIE_LINK_STATE_CLKPM); + if (pci_enable_device(pdev)) { err = -ENODEV; goto out_ieee80211_free_hw; -- cgit v1.2.3-59-g8ed1b From aa0d52c5e7f352ce9725c8940fe2458f2c04e049 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 10 Aug 2010 13:08:11 -0400 Subject: ipw2100: avoid warning from pointer cast in call to IPW_DEBUG_TX drivers/net/wireless/ipw2x00/ipw2100.c: In function 'ipw2100_tx_send_commands': drivers/net/wireless/ipw2x00/ipw2100.c:3063: warning: cast to pointer from integer of different size This changes the cast and the conversion to match other usage of the same value in calls to IPW_DEBUG_TX. Reported-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index a146240f7ddb..e4ed479c36f5 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -3064,9 +3064,9 @@ static void ipw2100_tx_send_commands(struct ipw2100_priv *priv) packet = list_entry(element, struct ipw2100_tx_packet, list); - IPW_DEBUG_TX("using TBD at virt=%p, phys=%p\n", + IPW_DEBUG_TX("using TBD at virt=%p, phys=%04X\n", &txq->drv[txq->next], - (void *)(txq->nic + txq->next * + (u32) (txq->nic + txq->next * sizeof(struct ipw2100_bd))); packet->index = txq->next; -- cgit v1.2.3-59-g8ed1b From 13eb670c104e15e06d38f3a210cfaf467a9c66de Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 10 Aug 2010 13:22:24 -0400 Subject: iwm3200wifi: remove comparison to WIFI_IF_NTFY_MAX in iwm_ntf_wifi_if_wrapper drivers/net/wireless/iwmc3200wifi/rx.c: In function 'iwm_ntf_wifi_if_wrapper': drivers/net/wireless/iwmc3200wifi/rx.c:1198: warning: comparison is always true due to limited range of data type This is, of course, because the value of WIFI_IF_NTFY_MAX is 0xff and hdr->oid is a u8. This is obviously an attempt to verify the range on an input value, but since it has no effect it can simply be removed. Signed-off-by: John W. Linville Acked-by: Samuel Ortiz --- drivers/net/wireless/iwmc3200wifi/rx.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index c02fcedea9fa..a944893ae3ca 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -1195,11 +1195,8 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " "oid is 0x%x\n", hdr->oid); - if (hdr->oid <= WIFI_IF_NTFY_MAX) { - set_bit(hdr->oid, &iwm->wifi_ntfy[0]); - wake_up_interruptible(&iwm->wifi_ntfy_queue); - } else - return -EINVAL; + set_bit(hdr->oid, &iwm->wifi_ntfy[0]); + wake_up_interruptible(&iwm->wifi_ntfy_queue); switch (hdr->oid) { case UMAC_WIFI_IF_CMD_SET_PROFILE: -- cgit v1.2.3-59-g8ed1b From 84c164a34ffe67908a932a2d641ec1a80c2d5435 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 6 Aug 2010 15:31:45 -0400 Subject: b43: move hwrng registration driver to wireless core initialization ...and unregistration to core shutdown. Previously, the driver remained registered even when the hardware was shutdown. That causes the driver to return -ENODEV if the b43 device is IFF_DOWN. This change causes the driver to disappear in that case, allowing /dev/hwrng to still function if another hwrng device is available. Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 294b68895822..a3e2f2bfe3a7 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4255,6 +4255,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED); if (!dev || b43_status(dev) != B43_STAT_INITIALIZED) return; + + /* Unregister HW RNG driver */ + b43_rng_exit(dev->wl); + b43_set_status(dev, B43_STAT_UNINIT); /* Stop the microcode PSM. */ @@ -4384,6 +4388,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev) b43_set_status(dev, B43_STAT_INITIALIZED); + /* Register HW RNG driver */ + b43_rng_init(dev->wl); + out: return err; @@ -4989,7 +4996,6 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id) if (err) goto err_one_core_detach; b43_leds_register(wl->current_dev); - b43_rng_init(wl); } out: @@ -5025,7 +5031,6 @@ static void b43_remove(struct ssb_device *dev) b43_one_core_detach(dev); if (list_empty(&wl->devlist)) { - b43_rng_exit(wl); b43_leds_unregister(wl); /* Last core on the chip unregistered. * We can destroy common struct b43_wl. -- cgit v1.2.3-59-g8ed1b From c25edef8dcdd9c193a8457e0cdf53197fd4523e8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 16 Aug 2010 19:26:41 +0100 Subject: ASoC: Fix WM8580 CLKSEL mask selection The RX and TX directions were inverted. Reported-by: Seungwhan Youn Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8580.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index af4517ed2964..42a6699662ee 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -703,12 +703,12 @@ static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id, int sel, sel_mask, sel_shift; switch (dai->driver->id) { - case WM8580_DAI_PAIFTX: + case WM8580_DAI_PAIFRX: sel_mask = 0x3; sel_shift = 0; break; - case WM8580_DAI_PAIFRX: + case WM8580_DAI_PAIFTX: sel_mask = 0xc; sel_shift = 2; break; -- cgit v1.2.3-59-g8ed1b From f538281c2b0b0e58a8059ba2accfe91f941d4f8a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 16 Aug 2010 19:27:05 +0100 Subject: ASoC: Fix argument ordering for snd_soc_update_bits() in WM8580 Reported-by: Seungwhan Youn Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8580.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 42a6699662ee..910c62a3f594 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -741,7 +741,7 @@ static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id, /* We really should validate PLL settings but not yet */ wm8580->sysclk[dai->id] = freq; - return snd_soc_update_bits(codec, WM8580_CLKSEL, sel, sel_mask); + return snd_soc_update_bits(codec, WM8580_CLKSEL, sel_mask, sel); } static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) -- cgit v1.2.3-59-g8ed1b From 4d7ede7f5ad58c5316335b9018ddef58bd687def Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 26 May 2010 13:33:31 -0400 Subject: rt2x00: do not shortcut rt2x00lib_config_antenna This function was exiting early if the existing diversity settings were unchanged. Unfortunately, in some cases the antenna configuration is not initialized at all. https://bugzilla.kernel.org/show_bug.cgi?id=14751 Signed-off-by: John W. Linville Acked-by: Ivo van Doorn Cc: Gertjan van Wingerde --- drivers/net/wireless/rt2x00/rt2x00config.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 953dc4f2c6af..fb23af40008b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -126,11 +126,6 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, * ANTENNA_SW_DIVERSITY state to the driver. * If that happens, fallback to hardware defaults, * or our own default. - * If diversity handling is active for a particular antenna, - * we shouldn't overwrite that antenna. - * The calls to rt2x00lib_config_antenna_check() - * might have caused that we restore back to the already - * active setting. If that has happened we can quit. */ if (!(ant->flags & ANTENNA_RX_DIVERSITY)) config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); @@ -142,9 +137,6 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, else config.tx = active->tx; - if (config.rx == active->rx && config.tx == active->tx) - return; - /* * Antenna setup changes require the RX to be disabled, * else the changes will be ignored by the device. -- cgit v1.2.3-59-g8ed1b From ffd2778bb984afe3cc264e22a125c06587020aa3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 29 Jul 2010 17:36:43 +0200 Subject: mac80211: fix driver offchannel notification when the channel does not change When running in client mode and associating to an AP, the channel change is usually performed with the offchannel flag still set. However after the assoc is complete, the following channel change event is suppressed because the run time channel is already set to the operating channel. Fix this by sending channel change notifications to the driver even if only the offchannel flag changes. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 1ed956c9cb8b..18b8df922c60 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -99,11 +99,13 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) int ret = 0; int power; enum nl80211_channel_type channel_type; + u32 offchannel_flag; might_sleep(); scan_chan = local->scan_channel; + offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; if (scan_chan) { chan = scan_chan; channel_type = NL80211_CHAN_NO_HT; @@ -117,8 +119,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) channel_type = local->_oper_channel_type; local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; } + offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; - if (chan != local->hw.conf.channel || + if (offchannel_flag || chan != local->hw.conf.channel || channel_type != local->hw.conf.channel_type) { local->hw.conf.channel = chan; local->hw.conf.channel_type = channel_type; -- cgit v1.2.3-59-g8ed1b From 1e51b2ff0a33797476932a68d36136921e4e1b05 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 29 Jul 2010 22:56:22 -0400 Subject: ath9k: add fastcc to debug print for channel change This helps us debug channel changes better. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3caa32316e7b..2ab3df22fbb5 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -226,9 +226,10 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, caldata = &aphy->caldata; ath_print(common, ATH_DBG_CONFIG, - "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", + "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", sc->sc_ah->curchan->channel, - channel->center_freq, conf_is_ht40(conf)); + channel->center_freq, conf_is_ht40(conf), + fastcc); spin_lock_bh(&sc->sc_resetlock); -- cgit v1.2.3-59-g8ed1b From 4083858c8b309068024ba43672d831999d69ba3f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 29 Jul 2010 23:12:53 -0700 Subject: libertas: better scan response debugging Make it a bit easier to debug scan results in the future. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cfg.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 51a96f5a342d..8bf88fa43690 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -524,20 +524,31 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, pos = scanresp->bssdesc_and_tlvbuffer; + lbs_deb_hex(LBS_DEB_SCAN, "SCAN_RSP", scanresp->bssdesc_and_tlvbuffer, + scanresp->bssdescriptsize); + tsfdesc = pos + bsssize; tsfsize = 4 + 8 * scanresp->nr_sets; + lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TSF", (u8 *) tsfdesc, tsfsize); /* Validity check: we expect a Marvell-Local TLV */ i = get_unaligned_le16(tsfdesc); tsfdesc += 2; - if (i != TLV_TYPE_TSFTIMESTAMP) + if (i != TLV_TYPE_TSFTIMESTAMP) { + lbs_deb_scan("scan response: invalid TSF Timestamp %d\n", i); goto done; + } + /* Validity check: the TLV holds TSF values with 8 bytes each, so * the size in the TLV must match the nr_sets value */ i = get_unaligned_le16(tsfdesc); tsfdesc += 2; - if (i / 8 != scanresp->nr_sets) + if (i / 8 != scanresp->nr_sets) { + lbs_deb_scan("scan response: invalid number of TSF timestamp " + "sets (expected %d got %d)\n", scanresp->nr_sets, + i / 8); goto done; + } for (i = 0; i < scanresp->nr_sets; i++) { const u8 *bssid; @@ -579,8 +590,11 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, id = *pos++; elen = *pos++; left -= 2; - if (elen > left || elen == 0) + if (elen > left || elen == 0) { + lbs_deb_scan("scan response: invalid IE fmt\n"); goto done; + } + if (id == WLAN_EID_DS_PARAMS) chan_no = *pos; if (id == WLAN_EID_SSID) { @@ -611,7 +625,9 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, capa, intvl, ie, ielen, LBS_SCAN_RSSI_TO_MBM(rssi), GFP_KERNEL); - } + } else + lbs_deb_scan("scan response: missing BSS channel IE\n"); + tsfdesc += 8; } ret = 0; -- cgit v1.2.3-59-g8ed1b From 86df5f7284ffdea9923153764691e490abf36081 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 29 Jul 2010 23:14:33 -0700 Subject: libertas: better association request debugging Bring back the comment about FW v5 status codes from the pre-cfg80211 driver, and let through status codes that aren't remapped by the firmware. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cfg.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 8bf88fa43690..08487a848e05 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -1117,7 +1117,7 @@ static int lbs_associate(struct lbs_private *priv, lbs_deb_hex(LBS_DEB_ASSOC, "Common Rates", tmp, pos - tmp); /* add auth type TLV */ - if (priv->fwrelease >= 0x09000000) + if (MRVL_FW_MAJOR_REV(priv->fwrelease) >= 9) pos += lbs_add_auth_type_tlv(pos, sme->auth_type); /* add WPA/WPA2 TLV */ @@ -1128,6 +1128,9 @@ static int lbs_associate(struct lbs_private *priv, (u16)(pos - (u8 *) &cmd->iebuf); cmd->hdr.size = cpu_to_le16(len); + lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_CMD", (u8 *) cmd, + le16_to_cpu(cmd->hdr.size)); + /* store for later use */ memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN); @@ -1135,14 +1138,28 @@ static int lbs_associate(struct lbs_private *priv, if (ret) goto done; - /* generate connect message to cfg80211 */ resp = (void *) cmd; /* recast for easier field access */ status = le16_to_cpu(resp->statuscode); - /* Convert statis code of old firmware */ - if (priv->fwrelease < 0x09000000) + /* Older FW versions map the IEEE 802.11 Status Code in the association + * response to the following values returned in resp->statuscode: + * + * IEEE Status Code Marvell Status Code + * 0 -> 0x0000 ASSOC_RESULT_SUCCESS + * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * others -> 0x0003 ASSOC_RESULT_REFUSED + * + * Other response codes: + * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) + * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for + * association response from the AP) + */ + if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) { switch (status) { case 0: break; @@ -1164,11 +1181,16 @@ static int lbs_associate(struct lbs_private *priv, break; default: lbs_deb_assoc("association failure %d\n", status); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; + /* v5 OLPC firmware does return the AP status code if + * it's not one of the values above. Let that through. + */ + break; + } } - lbs_deb_assoc("status %d, capability 0x%04x\n", status, - le16_to_cpu(resp->capability)); + lbs_deb_assoc("status %d, statuscode 0x%04x, capability 0x%04x, " + "aid 0x%04x\n", status, le16_to_cpu(resp->statuscode), + le16_to_cpu(resp->capability), le16_to_cpu(resp->aid)); resp_ie_len = le16_to_cpu(resp->hdr.size) - sizeof(resp->hdr) @@ -1188,7 +1210,6 @@ static int lbs_associate(struct lbs_private *priv, netif_tx_wake_all_queues(priv->dev); } - done: lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); return ret; -- cgit v1.2.3-59-g8ed1b From fc88518916793af8ad6a02e05ff254d95c36d875 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Jul 2010 13:23:12 +0200 Subject: mac80211: don't check rates on PLCP error frames Frames that failed PLCP error checks are most likely microwave transmissions (well, maybe not ...) and don't have a proper rate detected, so ignore it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/rx.c | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fa0f37e4afe4..225e8ee682e3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2615,28 +2615,37 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) if (WARN_ON(!local->started)) goto drop; - if (status->flag & RX_FLAG_HT) { + if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { /* - * rate_idx is MCS index, which can be [0-76] as documented on: - * - * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n - * - * Anything else would be some sort of driver or hardware error. - * The driver should catch hardware errors. + * Validate the rate, unless a PLCP error means that + * we probably can't have a valid rate here anyway. */ - if (WARN((status->rate_idx < 0 || - status->rate_idx > 76), - "Rate marked as an HT rate but passed " - "status->rate_idx is not " - "an MCS index [0-76]: %d (0x%02x)\n", - status->rate_idx, - status->rate_idx)) - goto drop; - } else { - if (WARN_ON(status->rate_idx < 0 || - status->rate_idx >= sband->n_bitrates)) - goto drop; - rate = &sband->bitrates[status->rate_idx]; + + if (status->flag & RX_FLAG_HT) { + /* + * rate_idx is MCS index, which can be [0-76] + * as documented on: + * + * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n + * + * Anything else would be some sort of driver or + * hardware error. The driver should catch hardware + * errors. + */ + if (WARN((status->rate_idx < 0 || + status->rate_idx > 76), + "Rate marked as an HT rate but passed " + "status->rate_idx is not " + "an MCS index [0-76]: %d (0x%02x)\n", + status->rate_idx, + status->rate_idx)) + goto drop; + } else { + if (WARN_ON(status->rate_idx < 0 || + status->rate_idx >= sband->n_bitrates)) + goto drop; + rate = &sband->bitrates[status->rate_idx]; + } } /* -- cgit v1.2.3-59-g8ed1b From c240879f3488ae0904a7ba5bdaaa54638b2d8852 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 30 Jul 2010 16:41:08 +0200 Subject: iwlwifi: make scan workqueue functions static We do not need export iwl_bg.*scan.*() functions just for initialize workqueue in other module. Making that functions static helps with iwl-scan.c code review a bit. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.h | 4 ---- drivers/net/wireless/iwlwifi/iwl-scan.c | 12 ++++-------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 ++---- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4a71dfb10a15..a8fa31f360ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -530,7 +530,6 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_scan_request *req); -void iwl_bg_start_internal_scan(struct work_struct *work); void iwl_internal_short_hw_scan(struct iwl_priv *priv); int iwl_force_reset(struct iwl_priv *priv, int mode, bool external); u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, @@ -542,9 +541,6 @@ u16 iwl_get_active_dwell_time(struct iwl_priv *priv, u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, enum ieee80211_band band, struct ieee80211_vif *vif); -void iwl_bg_scan_check(struct work_struct *data); -void iwl_bg_abort_scan(struct work_struct *work); -void iwl_bg_scan_completed(struct work_struct *work); void iwl_setup_scan_deferred_work(struct iwl_priv *priv); /* For faster active scanning, scan will move to the next channel if fewer than diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index a4b3663a262f..ac510840519c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -378,7 +378,7 @@ void iwl_internal_short_hw_scan(struct iwl_priv *priv) queue_work(priv->workqueue, &priv->start_internal_scan); } -void iwl_bg_start_internal_scan(struct work_struct *work) +static void iwl_bg_start_internal_scan(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, start_internal_scan); @@ -418,9 +418,8 @@ void iwl_bg_start_internal_scan(struct work_struct *work) unlock: mutex_unlock(&priv->mutex); } -EXPORT_SYMBOL(iwl_bg_start_internal_scan); -void iwl_bg_scan_check(struct work_struct *data) +static void iwl_bg_scan_check(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, scan_check.work); @@ -439,7 +438,6 @@ void iwl_bg_scan_check(struct work_struct *data) } mutex_unlock(&priv->mutex); } -EXPORT_SYMBOL(iwl_bg_scan_check); /** * iwl_fill_probe_req - fill in all required fields and IE for probe request @@ -489,7 +487,7 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, } EXPORT_SYMBOL(iwl_fill_probe_req); -void iwl_bg_abort_scan(struct work_struct *work) +static void iwl_bg_abort_scan(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); @@ -504,9 +502,8 @@ void iwl_bg_abort_scan(struct work_struct *work) iwl_send_scan_abort(priv); mutex_unlock(&priv->mutex); } -EXPORT_SYMBOL(iwl_bg_abort_scan); -void iwl_bg_scan_completed(struct work_struct *work) +static void iwl_bg_scan_completed(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, scan_completed); @@ -555,7 +552,6 @@ void iwl_bg_scan_completed(struct work_struct *work) if (!internal) ieee80211_scan_completed(priv->hw, false); } -EXPORT_SYMBOL(iwl_bg_scan_completed); void iwl_setup_scan_deferred_work(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index bb955d2013e3..de6d592af748 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3737,10 +3737,8 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll); - INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); - INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); - INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); - INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); + + iwl_setup_scan_deferred_work(priv); iwl3945_hw_setup_deferred_work(priv); -- cgit v1.2.3-59-g8ed1b From a1699b75a1db31a1da2f0fc610ee696d02a19280 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Jul 2010 16:46:07 +0200 Subject: mac80211: unify scan and work mutexes Having both scan and work mutexes is not just a bit too fine grained, it also creates issues when there's code that needs both since they then need to be acquired in the right order, which can be hard to do. Therefore, use just a single mutex for both. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 4 ++-- net/mac80211/main.c | 4 ++-- net/mac80211/mlme.c | 8 ++++---- net/mac80211/scan.c | 30 +++++++++++++++--------------- net/mac80211/work.c | 35 +++++++++++++++-------------------- 5 files changed, 38 insertions(+), 43 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 79d56454484a..fb4363e148f2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -634,7 +634,6 @@ struct ieee80211_local { /* * work stuff, potentially off-channel (in the future) */ - struct mutex work_mtx; struct list_head work_list; struct timer_list work_timer; struct work_struct work_work; @@ -746,9 +745,10 @@ struct ieee80211_local { */ struct mutex key_mtx; + /* mutex for scan and work locking */ + struct mutex mtx; /* Scanning and BSS list */ - struct mutex scan_mtx; unsigned long scanning; struct cfg80211_ssid scan_ssid; struct cfg80211_scan_request *int_scan_req; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 18b8df922c60..06b9608a2130 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -482,7 +482,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, __hw_addr_init(&local->mc_list); mutex_init(&local->iflist_mtx); - mutex_init(&local->scan_mtx); + mutex_init(&local->mtx); mutex_init(&local->key_mtx); spin_lock_init(&local->filter_lock); @@ -791,7 +791,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) struct ieee80211_local *local = hw_to_local(hw); mutex_destroy(&local->iflist_mtx); - mutex_destroy(&local->scan_mtx); + mutex_destroy(&local->mtx); wiphy_free(local->hw.wiphy); } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b6c163ac22da..17e9257a61d8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1751,7 +1751,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct ieee80211_work *wk; - mutex_lock(&local->work_mtx); + mutex_lock(&local->mtx); list_for_each_entry(wk, &local->work_list, list) { if (wk->sdata != sdata) continue; @@ -1783,7 +1783,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, free_work(wk); break; } - mutex_unlock(&local->work_mtx); + mutex_unlock(&local->mtx); cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); } @@ -2275,7 +2275,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, mutex_unlock(&ifmgd->mtx); - mutex_lock(&local->work_mtx); + mutex_lock(&local->mtx); list_for_each_entry(wk, &local->work_list, list) { if (wk->sdata != sdata) continue; @@ -2294,7 +2294,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, free_work(wk); break; } - mutex_unlock(&local->work_mtx); + mutex_unlock(&local->mtx); /* * If somebody requests authentication and we haven't diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 872d7b6ef6b3..f31f549733b1 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -255,7 +255,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) trace_api_scan_completed(local, aborted); - mutex_lock(&local->scan_mtx); + mutex_lock(&local->mtx); /* * It's ok to abort a not-yet-running scan (that @@ -267,7 +267,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) aborted = true; if (WARN_ON(!local->scan_req)) { - mutex_unlock(&local->scan_mtx); + mutex_unlock(&local->mtx); return; } @@ -275,7 +275,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); - mutex_unlock(&local->scan_mtx); + mutex_unlock(&local->mtx); return; } @@ -291,7 +291,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) local->scan_channel = NULL; /* we only have to protect scan_req and hw/sw scan */ - mutex_unlock(&local->scan_mtx); + mutex_unlock(&local->mtx); ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); if (was_hw_scan) @@ -639,15 +639,15 @@ void ieee80211_scan_work(struct work_struct *work) struct ieee80211_sub_if_data *sdata = local->scan_sdata; unsigned long next_delay = 0; - mutex_lock(&local->scan_mtx); + mutex_lock(&local->mtx); if (!sdata || !local->scan_req) { - mutex_unlock(&local->scan_mtx); + mutex_unlock(&local->mtx); return; } if (local->hw_scan_req) { int rc = drv_hw_scan(local, sdata, local->hw_scan_req); - mutex_unlock(&local->scan_mtx); + mutex_unlock(&local->mtx); if (rc) ieee80211_scan_completed(&local->hw, true); return; @@ -661,14 +661,14 @@ void ieee80211_scan_work(struct work_struct *work) local->scan_sdata = NULL; rc = __ieee80211_start_scan(sdata, req); - mutex_unlock(&local->scan_mtx); + mutex_unlock(&local->mtx); if (rc) ieee80211_scan_completed(&local->hw, true); return; } - mutex_unlock(&local->scan_mtx); + mutex_unlock(&local->mtx); /* * Avoid re-scheduling when the sdata is going away. @@ -711,9 +711,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, { int res; - mutex_lock(&sdata->local->scan_mtx); + mutex_lock(&sdata->local->mtx); res = __ieee80211_start_scan(sdata, req); - mutex_unlock(&sdata->local->scan_mtx); + mutex_unlock(&sdata->local->mtx); return res; } @@ -726,7 +726,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, int ret = -EBUSY; enum ieee80211_band band; - mutex_lock(&local->scan_mtx); + mutex_lock(&local->mtx); /* busy scanning */ if (local->scan_req) @@ -761,7 +761,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); unlock: - mutex_unlock(&local->scan_mtx); + mutex_unlock(&local->mtx); return ret; } @@ -775,10 +775,10 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) * Only call this function when a scan can't be * queued -- mostly at suspend under RTNL. */ - mutex_lock(&local->scan_mtx); + mutex_lock(&local->mtx); abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || (!local->scanning && local->scan_req); - mutex_unlock(&local->scan_mtx); + mutex_unlock(&local->mtx); if (abortscan) ieee80211_scan_completed(&local->hw, true); diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 81d4ad64184a..b98af64f5862 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -43,7 +43,7 @@ enum work_action { /* utils */ static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) { - WARN_ON(!mutex_is_locked(&local->work_mtx)); + lockdep_assert_held(&local->mtx); } /* @@ -757,7 +757,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, mgmt = (struct ieee80211_mgmt *) skb->data; fc = le16_to_cpu(mgmt->frame_control); - mutex_lock(&local->work_mtx); + mutex_lock(&local->mtx); list_for_each_entry(wk, &local->work_list, list) { const u8 *bssid = NULL; @@ -833,7 +833,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, WARN(1, "unexpected: %d", rma); } - mutex_unlock(&local->work_mtx); + mutex_unlock(&local->mtx); if (rma != WORK_ACT_DONE) goto out; @@ -845,9 +845,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, case WORK_DONE_REQUEUE: synchronize_rcu(); wk->started = false; /* restart */ - mutex_lock(&local->work_mtx); + mutex_lock(&local->mtx); list_add_tail(&wk->list, &local->work_list); - mutex_unlock(&local->work_mtx); + mutex_unlock(&local->mtx); } out: @@ -890,7 +890,7 @@ static void ieee80211_work_work(struct work_struct *work) ieee80211_recalc_idle(local); - mutex_lock(&local->work_mtx); + mutex_lock(&local->mtx); list_for_each_entry_safe(wk, tmp, &local->work_list, list) { bool started = wk->started; @@ -995,17 +995,13 @@ static void ieee80211_work_work(struct work_struct *work) run_again(local, jiffies + HZ/2); } - mutex_lock(&local->scan_mtx); - if (list_empty(&local->work_list) && local->scan_req && !local->scanning) ieee80211_queue_delayed_work(&local->hw, &local->scan_work, round_jiffies_relative(0)); - mutex_unlock(&local->scan_mtx); - - mutex_unlock(&local->work_mtx); + mutex_unlock(&local->mtx); ieee80211_recalc_idle(local); @@ -1035,16 +1031,15 @@ void ieee80211_add_work(struct ieee80211_work *wk) wk->started = false; local = wk->sdata->local; - mutex_lock(&local->work_mtx); + mutex_lock(&local->mtx); list_add_tail(&wk->list, &local->work_list); - mutex_unlock(&local->work_mtx); + mutex_unlock(&local->mtx); ieee80211_queue_work(&local->hw, &local->work_work); } void ieee80211_work_init(struct ieee80211_local *local) { - mutex_init(&local->work_mtx); INIT_LIST_HEAD(&local->work_list); setup_timer(&local->work_timer, ieee80211_work_timer, (unsigned long)local); @@ -1057,7 +1052,7 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) struct ieee80211_local *local = sdata->local; struct ieee80211_work *wk; - mutex_lock(&local->work_mtx); + mutex_lock(&local->mtx); list_for_each_entry(wk, &local->work_list, list) { if (wk->sdata != sdata) continue; @@ -1065,19 +1060,19 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) wk->started = true; wk->timeout = jiffies; } - mutex_unlock(&local->work_mtx); + mutex_unlock(&local->mtx); /* run cleanups etc. */ ieee80211_work_work(&local->work_work); - mutex_lock(&local->work_mtx); + mutex_lock(&local->mtx); list_for_each_entry(wk, &local->work_list, list) { if (wk->sdata != sdata) continue; WARN_ON(1); break; } - mutex_unlock(&local->work_mtx); + mutex_unlock(&local->mtx); } ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, @@ -1163,7 +1158,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, struct ieee80211_work *wk, *tmp; bool found = false; - mutex_lock(&local->work_mtx); + mutex_lock(&local->mtx); list_for_each_entry_safe(wk, tmp, &local->work_list, list) { if ((unsigned long) wk == cookie) { wk->timeout = jiffies; @@ -1171,7 +1166,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, break; } } - mutex_unlock(&local->work_mtx); + mutex_unlock(&local->mtx); if (!found) return -ENOENT; -- cgit v1.2.3-59-g8ed1b From 422f8d19d68d0530dfd37be97bac431ca7435e69 Mon Sep 17 00:00:00 2001 From: Thomas Klute Date: Sat, 31 Jul 2010 12:01:44 +0200 Subject: libertas_tf: if_usb.c: Whitespace cleanup Signed-off-by: Thomas Klute Signed-off-by: John W. Linville --- drivers/net/wireless/libertas_tf/if_usb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index b172f5d87a3b..f93260b67fcf 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -54,7 +54,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp); /** * if_usb_wrike_bulk_callback - call back to handle URB status * - * @param urb pointer to urb structure + * @param urb pointer to urb structure */ static void if_usb_write_bulk_callback(struct urb *urb) { @@ -187,7 +187,7 @@ static int if_usb_probe(struct usb_interface *intf, lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out); lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n", - cardp->ep_out_size); + cardp->ep_out_size); } } if (!cardp->ep_out_size || !cardp->ep_in_size) { @@ -367,7 +367,7 @@ EXPORT_SYMBOL_GPL(if_usb_reset_device); /** * usb_tx_block - transfer data to the device * - * @priv pointer to struct lbtf_private + * @priv pointer to struct lbtf_private * @payload pointer to payload data * @nb data length * @data non-zero for data, zero for commands @@ -689,7 +689,7 @@ static void if_usb_receive(struct urb *urb) } default: lbtf_deb_usbd(&cardp->udev->dev, - "libertastf: unknown command type 0x%X\n", recvtype); + "libertastf: unknown command type 0x%X\n", recvtype); kfree_skb(skb); break; } -- cgit v1.2.3-59-g8ed1b From 139455c3912bfed4bd42824d59c82113cc667f91 Mon Sep 17 00:00:00 2001 From: Thomas Klute Date: Sat, 31 Jul 2010 12:01:45 +0200 Subject: libertas_tf: if_usb.c: Some more formatting fixes Split some long lines to make checkpatch.pl happy. ;-) Signed-off-by: Thomas Klute Signed-off-by: John W. Linville --- drivers/net/wireless/libertas_tf/if_usb.c | 49 +++++++++++++++++++------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index f93260b67fcf..1cf01acef5f0 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -178,14 +178,17 @@ static int if_usb_probe(struct usb_interface *intf, le16_to_cpu(endpoint->wMaxPacketSize); cardp->ep_in = usb_endpoint_num(endpoint); - lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in); - lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size); + lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", + cardp->ep_in); + lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", + cardp->ep_in_size); } else if (usb_endpoint_is_bulk_out(endpoint)) { cardp->ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize); cardp->ep_out = usb_endpoint_num(endpoint); - lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out); + lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", + cardp->ep_out); lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n", cardp->ep_out_size); } @@ -318,10 +321,12 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) { lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n"); - lbtf_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n", - cardp->fwseqnum, cardp->totalbytes); + lbtf_deb_usb2(&cardp->udev->dev, + "seqnum = %d totalbytes = %d\n", + cardp->fwseqnum, cardp->totalbytes); } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { - lbtf_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n"); + lbtf_deb_usb2(&cardp->udev->dev, + "Host has finished FW downloading\n"); lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n"); /* Host has finished FW downloading @@ -400,7 +405,8 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, urb->transfer_flags |= URB_ZERO_PACKET; if (usb_submit_urb(urb, GFP_ATOMIC)) { - lbtf_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret); + lbtf_deb_usbd(&cardp->udev->dev, + "usb_submit_urb failed: %d\n", ret); goto tx_ret; } @@ -438,10 +444,12 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; - lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); + lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", + cardp->rx_urb); ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC); if (ret) { - lbtf_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret); + lbtf_deb_usbd(&cardp->udev->dev, + "Submit Rx URB failed: %d\n", ret); kfree_skb(skb); cardp->rx_skb = NULL; lbtf_deb_leave(LBTF_DEB_USB); @@ -522,14 +530,14 @@ static void if_usb_receive_fwload(struct urb *urb) } } else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) { pr_info("boot cmd response cmd_tag error (%d)\n", - bcmdresp.cmd); + bcmdresp.cmd); } else if (bcmdresp.result != BOOT_CMD_RESP_OK) { pr_info("boot cmd response result error (%d)\n", - bcmdresp.result); + bcmdresp.result); } else { cardp->bootcmdresp = 1; lbtf_deb_usbd(&cardp->udev->dev, - "Received valid boot command response\n"); + "Received valid boot command response\n"); } kfree_skb(skb); @@ -541,19 +549,23 @@ static void if_usb_receive_fwload(struct urb *urb) syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader), GFP_ATOMIC); if (!syncfwheader) { - lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); + lbtf_deb_usbd(&cardp->udev->dev, + "Failure to allocate syncfwheader\n"); kfree_skb(skb); lbtf_deb_leave(LBTF_DEB_USB); return; } if (!syncfwheader->cmd) { - lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); - lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", - le32_to_cpu(syncfwheader->seqnum)); + lbtf_deb_usb2(&cardp->udev->dev, + "FW received Blk with correct CRC\n"); + lbtf_deb_usb2(&cardp->udev->dev, + "FW received Blk seqnum = %d\n", + le32_to_cpu(syncfwheader->seqnum)); cardp->CRC_OK = 1; } else { - lbtf_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n"); + lbtf_deb_usbd(&cardp->udev->dev, + "FW received Blk with CRC error\n"); cardp->CRC_OK = 0; } @@ -666,7 +678,8 @@ static void if_usb_receive(struct urb *urb) { /* Event cause handling */ u32 event_cause = le32_to_cpu(pkt[1]); - lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event_cause); + lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", + event_cause); /* Icky undocumented magic special case */ if (event_cause & 0xffff0000) { -- cgit v1.2.3-59-g8ed1b From 3867fe0477a1e23df3d05131320d7b0075a9bed0 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 31 Jul 2010 08:34:05 -0700 Subject: iwlwifi: make iwl_hw_detect static to _agn iwl_hw_detect() only used by _agn, make it static Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 8 -------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d3de5096a620..8d4a2b569f05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3883,6 +3883,13 @@ static struct ieee80211_ops iwl_hw_ops = { .flush = iwl_mac_flush, }; +static void iwl_hw_detect(struct iwl_priv *priv) +{ + priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); + priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG); + pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id); +} + static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2c03c6e20a72..db8f15f3df46 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -183,14 +183,6 @@ out: } EXPORT_SYMBOL(iwl_alloc_all); -void iwl_hw_detect(struct iwl_priv *priv) -{ - priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); - priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG); - pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id); -} -EXPORT_SYMBOL(iwl_hw_detect); - /* * QoS support */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a8fa31f360ea..ac16f582d6d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -347,7 +347,6 @@ struct iwl_cfg { struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, struct ieee80211_ops *hw_ops); -void iwl_hw_detect(struct iwl_priv *priv); void iwl_activate_qos(struct iwl_priv *priv); int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); -- cgit v1.2.3-59-g8ed1b From 49ded76bd52f1341671f767a2f5121cb4eb8cf6e Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 31 Jul 2010 08:34:06 -0700 Subject: iwlagn: log pci revision id Log the information after reading the PCI_REVISION_ID from pci config space, Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8d4a2b569f05..5c1ea0b2c6a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3888,6 +3888,7 @@ static void iwl_hw_detect(struct iwl_priv *priv) priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG); pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id); + IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id); } static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -- cgit v1.2.3-59-g8ed1b From 07d4f1ad2c21273f0f89a3d2202d22fcaf901439 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 31 Jul 2010 08:34:08 -0700 Subject: iwlwifi: make iwl_set_hw_params static to _agn iwl_set_hw_params() only used by _agn, make it static Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 18 ++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 19 ------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5c1ea0b2c6a2..8684f2639716 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3891,6 +3891,24 @@ static void iwl_hw_detect(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id); } +static int iwl_set_hw_params(struct iwl_priv *priv) +{ + priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; + priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; + if (priv->cfg->mod_params->amsdu_size_8K) + priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); + else + priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); + + priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; + + if (priv->cfg->mod_params->disable_11n) + priv->cfg->sku &= ~IWL_SKU_N; + + /* Device-specific setup */ + return priv->cfg->ops->lib->set_hw_params(priv); +} + static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index db8f15f3df46..78882f9ab459 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1365,25 +1365,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw, } EXPORT_SYMBOL(iwl_configure_filter); -int iwl_set_hw_params(struct iwl_priv *priv) -{ - priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; - priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; - if (priv->cfg->mod_params->amsdu_size_8K) - priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); - else - priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); - - priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; - - if (priv->cfg->mod_params->disable_11n) - priv->cfg->sku &= ~IWL_SKU_N; - - /* Device-specific setup */ - return priv->cfg->ops->lib->set_hw_params(priv); -} -EXPORT_SYMBOL(iwl_set_hw_params); - int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) { int ret = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index ac16f582d6d3..cca7428c238f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -374,7 +374,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv); void iwl_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, u64 multicast); -int iwl_set_hw_params(struct iwl_priv *priv); void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, -- cgit v1.2.3-59-g8ed1b From a85d7cca1204f2dba86d2f61693f0fe8c48f0fa5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 31 Jul 2010 08:34:10 -0700 Subject: iwlwifi: track IBSS manager status Only the IBSS manager, ie. the station that sent the IBSS beacon last, should be replying to probe responses. This requires implementing the mac80211 tx_last_beacon callback, which we can do thanks to the ucode beacon notification. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 ++++- drivers/net/wireless/iwlwifi/iwl-commands.h | 5 +++++ drivers/net/wireless/iwlwifi/iwl-core.c | 8 ++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 3 +++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 ++++- 6 files changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8684f2639716..43e078b87378 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -764,10 +764,10 @@ static void iwl_bg_ucode_trace(unsigned long data) static void iwl_rx_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl4965_beacon_notif *beacon = (struct iwl4965_beacon_notif *)pkt->u.raw; +#ifdef CONFIG_IWLWIFI_DEBUG u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " @@ -779,6 +779,8 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, le32_to_cpu(beacon->low_tsf), rate); #endif + priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); + if ((priv->iw_mode == NL80211_IFTYPE_AP) && (!test_bit(STATUS_EXIT_PENDING, &priv->status))) queue_work(priv->workqueue, &priv->beacon_update); @@ -3881,6 +3883,7 @@ static struct ieee80211_ops iwl_hw_ops = { .sta_remove = iwl_mac_sta_remove, .channel_switch = iwl_mac_channel_switch, .flush = iwl_mac_flush, + .tx_last_beacon = iwl_mac_tx_last_beacon, }; static void iwl_hw_detect(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 60725a5c1b69..9435fd934d5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2919,6 +2919,11 @@ struct iwl_scancomplete_notification { * *****************************************************************************/ +enum iwl_ibss_manager { + IWL_NOT_IBSS_MANAGER = 0, + IWL_IBSS_MANAGER = 1, +}; + /* * BEACON_NOTIFICATION = 0x90 (notification only, not a command) */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 78882f9ab459..ccdf3c02bb3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1666,6 +1666,14 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, } EXPORT_SYMBOL(iwl_mac_conf_tx); +int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw) +{ + struct iwl_priv *priv = hw->priv; + + return priv->ibss_manager == IWL_IBSS_MANAGER; +} +EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon); + static void iwl_ht_conf(struct iwl_priv *priv, struct ieee80211_vif *vif) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index cca7428c238f..7f1aaf206078 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -350,6 +350,7 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, void iwl_activate_qos(struct iwl_priv *priv); int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); +int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); int iwl_check_rxon_cmd(struct iwl_priv *priv); int iwl_full_rxon_required(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f35bcad56e36..599635547021 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1109,6 +1109,9 @@ struct iwl_priv { u32 ucode_beacon_time; int missed_beacon_threshold; + /* track IBSS manager (last beacon) status */ + u32 ibss_manager; + /* storing the jiffies when the plcp error rate is received */ unsigned long plcp_jiffies; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index de6d592af748..b14eaf91c7c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -814,9 +814,9 @@ static void iwl3945_bg_beacon_update(struct work_struct *work) static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); +#ifdef CONFIG_IWLWIFI_DEBUG u8 rate = beacon->beacon_notify_hdr.rate; IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " @@ -828,6 +828,8 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, le32_to_cpu(beacon->low_tsf), rate); #endif + priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); + if ((priv->iw_mode == NL80211_IFTYPE_AP) && (!test_bit(STATUS_EXIT_PENDING, &priv->status))) queue_work(priv->workqueue, &priv->beacon_update); @@ -3803,6 +3805,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .hw_scan = iwl_mac_hw_scan, .sta_add = iwl3945_mac_sta_add, .sta_remove = iwl_mac_sta_remove, + .tx_last_beacon = iwl_mac_tx_last_beacon, }; static int iwl3945_init_drv(struct iwl_priv *priv) -- cgit v1.2.3-59-g8ed1b From 1ac62ba7c985109868a18d959986425148481f47 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 1 Aug 2010 17:37:03 +0100 Subject: mac80211: Don't squash error codes in key setup functions ieee80211_add_key() currently returns -ENOMEM in case of any error, including a missing crypto algorithm. Change ieee80211_key_alloc() and ieee80211_aes_{key_setup_encrypt,cmac_key_setup}() to encode errors with ERR_PTR() rather than returning NULL, and change ieee80211_add_key() accordingly. Compile-tested only. Reported-by: Marcin Owsiany Signed-off-by: Ben Hutchings Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/aes_ccm.c | 6 ++---- net/mac80211/aes_cmac.c | 6 ++---- net/mac80211/cfg.c | 4 ++-- net/mac80211/key.c | 14 ++++++++------ 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index a87cb3ba2df6..d2b03e0851ef 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c @@ -138,10 +138,8 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]) struct crypto_cipher *tfm; tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - return NULL; - - crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN); + if (!IS_ERR(tfm)) + crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN); return tfm; } diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index 3d097b3d7b62..b4d66cca76d6 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c @@ -119,10 +119,8 @@ struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]) struct crypto_cipher *tfm; tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - return NULL; - - crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); + if (!IS_ERR(tfm)) + crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); return tfm; } diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 29ac8e1a509e..19c6146010b7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -150,8 +150,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key, params->seq_len, params->seq); - if (!key) - return -ENOMEM; + if (IS_ERR(key)) + return PTR_ERR(key); mutex_lock(&sdata->local->sta_mtx); diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 1b9d87ed143a..d6dbc8ea4ead 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -234,13 +234,13 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, size_t seq_len, const u8 *seq) { struct ieee80211_key *key; - int i, j; + int i, j, err; BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); if (!key) - return NULL; + return ERR_PTR(-ENOMEM); /* * Default to software encryption; we'll later upload the @@ -296,9 +296,10 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, * it does not need to be initialized for every packet. */ key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); - if (!key->u.ccmp.tfm) { + if (IS_ERR(key->u.ccmp.tfm)) { + err = PTR_ERR(key->u.ccmp.tfm); kfree(key); - return NULL; + key = ERR_PTR(err); } } @@ -309,9 +310,10 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, */ key->u.aes_cmac.tfm = ieee80211_aes_cmac_key_setup(key_data); - if (!key->u.aes_cmac.tfm) { + if (IS_ERR(key->u.aes_cmac.tfm)) { + err = PTR_ERR(key->u.aes_cmac.tfm); kfree(key); - return NULL; + key = ERR_PTR(err); } } -- cgit v1.2.3-59-g8ed1b From 6252fcb9f802a992c697edf105e30271a4ae3246 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 2 Aug 2010 15:53:12 +0200 Subject: ath9k: add a separate debug level for stuck beacons Stuck beacons are a useful indicator for debugging various PHY issues such as calibration. Putting them on the same debug level as the other beacon stuff makes it hard to spot them in huge amounts of spam. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 6 +++--- drivers/net/wireless/ath/debug.h | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 4d4b22d52dfd..102f1234f794 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -359,11 +359,11 @@ void ath_beacon_tasklet(unsigned long data) sc->beacon.bmisscnt++; if (sc->beacon.bmisscnt < BSTUCK_THRESH) { - ath_print(common, ATH_DBG_BEACON, + ath_print(common, ATH_DBG_BSTUCK, "missed %u consecutive beacons\n", sc->beacon.bmisscnt); } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { - ath_print(common, ATH_DBG_BEACON, + ath_print(common, ATH_DBG_BSTUCK, "beacon is officially stuck\n"); sc->sc_flags |= SC_OP_TSF_RESET; ath_reset(sc, false); @@ -373,7 +373,7 @@ void ath_beacon_tasklet(unsigned long data) } if (sc->beacon.bmisscnt != 0) { - ath_print(common, ATH_DBG_BEACON, + ath_print(common, ATH_DBG_BSTUCK, "resume beacon xmit after %u misses\n", sc->beacon.bmisscnt); sc->beacon.bmisscnt = 0; diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h index 873bf526e11f..fd3a020682dc 100644 --- a/drivers/net/wireless/ath/debug.h +++ b/drivers/net/wireless/ath/debug.h @@ -36,6 +36,7 @@ * @ATH_DBG_PS: power save processing * @ATH_DBG_HWTIMER: hardware timer handling * @ATH_DBG_BTCOEX: bluetooth coexistance + * @ATH_DBG_BSTUCK: stuck beacons * @ATH_DBG_ANY: enable all debugging * * The debug level is used to control the amount and type of debugging output @@ -60,6 +61,7 @@ enum ATH_DEBUG { ATH_DBG_HWTIMER = 0x00001000, ATH_DBG_BTCOEX = 0x00002000, ATH_DBG_WMI = 0x00004000, + ATH_DBG_BSTUCK = 0x00008000, ATH_DBG_ANY = 0xffffffff }; -- cgit v1.2.3-59-g8ed1b From 2292ca6d783d3c79b58591bb3ee795bf0144e5ff Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 2 Aug 2010 15:53:13 +0200 Subject: ath9k_hw: apply the noise floor validation to the median instead of single Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 51 +++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 45208690c0ec..ccb1b2eae85e 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -19,8 +19,7 @@ /* Common calibration code */ -/* We can tune this as we go by monitoring really low values */ -#define ATH9K_NF_TOO_LOW -60 +#define ATH9K_NF_TOO_HIGH -60 static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) { @@ -45,11 +44,35 @@ static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) return nfval; } -static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, +static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct ath_nf_limits *limit; + + if (!chan || IS_CHAN_2GHZ(chan)) + limit = &ah->nf_2g; + else + limit = &ah->nf_5g; + + return limit; +} + +static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + return ath9k_hw_get_nf_limits(ah, chan)->nominal; +} + + +static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, + struct ath9k_nfcal_hist *h, int16_t *nfarray) { + struct ath_nf_limits *limit; int i; + limit = ath9k_hw_get_nf_limits(ah, ah->curchan); + for (i = 0; i < NUM_NF_READINGS; i++) { h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; @@ -63,6 +86,9 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, h[i].privNF = ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); } + + if (h[i].privNF > limit->max) + h[i].privNF = limit->max; } } @@ -104,19 +130,6 @@ void ath9k_hw_reset_calibration(struct ath_hw *ah, ah->cal_samples = 0; } -static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ath_nf_limits *limit; - - if (!chan || IS_CHAN_2GHZ(chan)) - limit = &ah->nf_2g; - else - limit = &ah->nf_5g; - - return limit->nominal; -} - /* This is done for the currently configured channel */ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) { @@ -277,10 +290,10 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) "NF calibrated [%s] [chain %d] is %d\n", (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); - if (nf[i] > limit->max) { + if (nf[i] > ATH9K_NF_TOO_HIGH) { ath_print(common, ATH_DBG_CALIBRATE, "NF[%d] (%d) > MAX (%d), correcting to MAX", - i, nf[i], limit->max); + i, nf[i], ATH9K_NF_TOO_HIGH); nf[i] = limit->max; } else if (nf[i] < limit->min) { ath_print(common, ATH_DBG_CALIBRATE, @@ -326,7 +339,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) h = caldata->nfCalHist; caldata->nfcal_pending = false; - ath9k_hw_update_nfcal_hist_buffer(h, nfarray); + ath9k_hw_update_nfcal_hist_buffer(ah, h, nfarray); caldata->rawNoiseFloor = h[0].privNF; return true; } -- cgit v1.2.3-59-g8ed1b From 70cf15335eb35d562a4ec6d8860611c87f775cf2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 2 Aug 2010 15:53:14 +0200 Subject: ath9k: use AP beacon miss as a trigger for fast recalibration When beacons get stuck in AP mode, the most likely cause is interference. Such interference can often go on for a while, and too many consecutive beacon misses can lead to connected clients getting dropped. Since connected clients might not be subjected to the same interference if that happens to be very local, the AP should try to deal with it as good as it can. One way to do this is to trigger an NF calibration with automatic baseband update right after the beacon miss. In my tests with very strong interference, this allowed the AP to continue transmitting beacons after only 2-3 misses, which allows a normal client to stay connected. With some of the newer - really sensitive - chips, the maximum noise floor limit is very low, which can be problematic during very strong interference. To avoid an endless loop of stuck beacons -> nfcal -> periodic calibration -> stuck beacons, the beacon miss event also sets a flag, which allows the calibration code to bypass the chip specific maximum NF value. This flag is automatically cleared, as soon as the first NF median goes back below the limits for all chains. In my tests, this allowed an ath9k AP to survive very strong interference (measured NF: -68, or sometimes even higher) without losing connectivity to its clients. Even under these conditions, I was able to transmit several mbits/s through the interface. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 1 + drivers/net/wireless/ath/ath9k/calib.c | 66 +++++++++++++++++++++++++++++++-- drivers/net/wireless/ath/ath9k/calib.h | 1 + drivers/net/wireless/ath/ath9k/hw.h | 1 + 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 102f1234f794..081192e78a46 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -362,6 +362,7 @@ void ath_beacon_tasklet(unsigned long data) ath_print(common, ATH_DBG_BSTUCK, "missed %u consecutive beacons\n", sc->beacon.bmisscnt); + ath9k_hw_bstuck_nfcal(ah); } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { ath_print(common, ATH_DBG_BSTUCK, "beacon is officially stuck\n"); diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index ccb1b2eae85e..67ee5d735cc1 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -65,12 +65,16 @@ static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, - struct ath9k_nfcal_hist *h, + struct ath9k_hw_cal_data *cal, int16_t *nfarray) { + struct ath_common *common = ath9k_hw_common(ah); struct ath_nf_limits *limit; + struct ath9k_nfcal_hist *h; + bool high_nf_mid = false; int i; + h = cal->nfCalHist; limit = ath9k_hw_get_nf_limits(ah, ah->curchan); for (i = 0; i < NUM_NF_READINGS; i++) { @@ -87,9 +91,38 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); } - if (h[i].privNF > limit->max) - h[i].privNF = limit->max; + if (!h[i].privNF) + continue; + + if (h[i].privNF > limit->max) { + high_nf_mid = true; + + ath_print(common, ATH_DBG_CALIBRATE, + "NFmid[%d] (%d) > MAX (%d), %s\n", + i, h[i].privNF, limit->max, + (cal->nfcal_interference ? + "not corrected (due to interference)" : + "correcting to MAX")); + + /* + * Normally we limit the average noise floor by the + * hardware specific maximum here. However if we have + * encountered stuck beacons because of interference, + * we bypass this limit here in order to better deal + * with our environment. + */ + if (!cal->nfcal_interference) + h[i].privNF = limit->max; + } } + + /* + * If the noise floor seems normal for all chains, assume that + * there is no significant interference in the environment anymore. + * Re-enable the enforcement of the NF maximum again. + */ + if (!high_nf_mid) + cal->nfcal_interference = false; } static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, @@ -339,7 +372,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) h = caldata->nfCalHist; caldata->nfcal_pending = false; - ath9k_hw_update_nfcal_hist_buffer(ah, h, nfarray); + ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); caldata->rawNoiseFloor = h[0].privNF; return true; } @@ -374,3 +407,28 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) return ah->caldata->rawNoiseFloor; } EXPORT_SYMBOL(ath9k_hw_getchan_noise); + +void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) +{ + struct ath9k_hw_cal_data *caldata = ah->caldata; + + if (unlikely(!caldata)) + return; + + /* + * If beacons are stuck, the most likely cause is interference. + * Triggering a noise floor calibration at this point helps the + * hardware adapt to a noisy environment much faster. + * To ensure that we recover from stuck beacons quickly, let + * the baseband update the internal NF value itself, similar to + * what is being done after a full reset. + */ + if (!caldata->nfcal_pending) + ath9k_hw_start_nfcal(ah, true); + else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)) + ath9k_hw_getnf(ah, ah->curchan); + + caldata->nfcal_interference = true; +} +EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal); + diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 0a304b3eeeb6..5b053a6260b2 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -113,6 +113,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, struct ath9k_channel *chan); +void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); void ath9k_hw_reset_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 399f7c1283cd..1601dd439890 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -355,6 +355,7 @@ struct ath9k_hw_cal_data { int16_t rawNoiseFloor; bool paprd_done; bool nfcal_pending; + bool nfcal_interference; u16 small_signal_gain[AR9300_MAX_CHAINS]; u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; -- cgit v1.2.3-59-g8ed1b From 6044474ed86484b899d46e040ade3872e83fc9f7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 2 Aug 2010 15:53:15 +0200 Subject: ath9k: shorten the calibration interval during strong interference When the noise floor limits are being bypassed because of strong interference, sensitivity is also reduced. In order to recover from this as quickly as possible, trigger a long periodic calibration every second instead of every 30 seconds, until the NF median is within limits again. This is especially important if the interference lasts for a while, since it takes multiple clean NF calibrations to bring the median back to normal. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 07f26ee7a723..def0cd308fdd 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -423,6 +423,7 @@ int ath_beaconq_config(struct ath_softc *sc); #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ #define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */ #define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */ +#define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */ #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2ab3df22fbb5..a3b0ea90439d 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -396,7 +396,12 @@ void ath_ani_calibrate(unsigned long data) bool shortcal = false; bool aniflag = false; unsigned int timestamp = jiffies_to_msecs(jiffies); - u32 cal_interval, short_cal_interval; + u32 cal_interval, short_cal_interval, long_cal_interval; + + if (ah->caldata && ah->caldata->nfcal_interference) + long_cal_interval = ATH_LONG_CALINTERVAL_INT; + else + long_cal_interval = ATH_LONG_CALINTERVAL; short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; @@ -408,7 +413,7 @@ void ath_ani_calibrate(unsigned long data) ath9k_ps_wakeup(sc); /* Long calibration runs independently of short calibration. */ - if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { + if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { longcal = true; ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); common->ani.longcal_timer = timestamp; -- cgit v1.2.3-59-g8ed1b From aa0c86364f925c6f12195072562b18c5609ff082 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 5 Aug 2010 01:36:04 +0200 Subject: mac80211: put rx handlers into separate functions This patch takes the reorder logic from the RX path and moves it into separate routines to make the expired frame release accessible. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/rx.c | 214 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 128 insertions(+), 86 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 225e8ee682e3..8301b4a980a2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -583,6 +583,57 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, */ #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) +static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, + struct tid_ampdu_rx *tid_agg_rx, + struct sk_buff_head *frames) +{ + int index; + + /* release the buffer until next missing frame */ + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % + tid_agg_rx->buf_size; + if (!tid_agg_rx->reorder_buf[index] && + tid_agg_rx->stored_mpdu_num > 1) { + /* + * No buffers ready to be released, but check whether any + * frames in the reorder buffer have timed out. + */ + int j; + int skipped = 1; + for (j = (index + 1) % tid_agg_rx->buf_size; j != index; + j = (j + 1) % tid_agg_rx->buf_size) { + if (!tid_agg_rx->reorder_buf[j]) { + skipped++; + continue; + } + if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + + HT_RX_REORDER_BUF_TIMEOUT)) + break; + +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_DEBUG "%s: release an RX reorder " + "frame due to timeout on earlier " + "frames\n", + wiphy_name(hw->wiphy)); +#endif + ieee80211_release_reorder_frame(hw, tid_agg_rx, + j, frames); + + /* + * Increment the head seq# also for the skipped slots. + */ + tid_agg_rx->head_seq_num = + (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; + skipped = 0; + } + } else while (tid_agg_rx->reorder_buf[index]) { + ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % + tid_agg_rx->buf_size; + } +} + /* * As this function belongs to the RX path it must be under * rcu_read_lock protection. It returns false if the frame @@ -643,49 +694,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, tid_agg_rx->reorder_buf[index] = skb; tid_agg_rx->reorder_time[index] = jiffies; tid_agg_rx->stored_mpdu_num++; - /* release the buffer until next missing frame */ - index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % - tid_agg_rx->buf_size; - if (!tid_agg_rx->reorder_buf[index] && - tid_agg_rx->stored_mpdu_num > 1) { - /* - * No buffers ready to be released, but check whether any - * frames in the reorder buffer have timed out. - */ - int j; - int skipped = 1; - for (j = (index + 1) % tid_agg_rx->buf_size; j != index; - j = (j + 1) % tid_agg_rx->buf_size) { - if (!tid_agg_rx->reorder_buf[j]) { - skipped++; - continue; - } - if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + - HT_RX_REORDER_BUF_TIMEOUT)) - break; - -#ifdef CONFIG_MAC80211_HT_DEBUG - if (net_ratelimit()) - printk(KERN_DEBUG "%s: release an RX reorder " - "frame due to timeout on earlier " - "frames\n", - wiphy_name(hw->wiphy)); -#endif - ieee80211_release_reorder_frame(hw, tid_agg_rx, - j, frames); - - /* - * Increment the head seq# also for the skipped slots. - */ - tid_agg_rx->head_seq_num = - (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; - skipped = 0; - } - } else while (tid_agg_rx->reorder_buf[index]) { - ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); - index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % - tid_agg_rx->buf_size; - } + ieee80211_sta_reorder_release(hw, tid_agg_rx, frames); return true; } @@ -2267,19 +2276,46 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, dev_kfree_skb(skb); } - -static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, - struct ieee80211_rx_data *rx, - struct sk_buff *skb, - struct ieee80211_rate *rate) +static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, + ieee80211_rx_result res) { - struct sk_buff_head reorder_release; - ieee80211_rx_result res = RX_DROP_MONITOR; + switch (res) { + case RX_DROP_MONITOR: + I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); + if (rx->sta) + rx->sta->rx_dropped++; + /* fall through */ + case RX_CONTINUE: { + struct ieee80211_rate *rate = NULL; + struct ieee80211_supported_band *sband; + struct ieee80211_rx_status *status; + + status = IEEE80211_SKB_RXCB((rx->skb)); + + sband = rx->local->hw.wiphy->bands[status->band]; + if (!(status->flag & RX_FLAG_HT)) + rate = &sband->bitrates[status->rate_idx]; - __skb_queue_head_init(&reorder_release); + ieee80211_rx_cooked_monitor(rx, rate); + break; + } + case RX_DROP_UNUSABLE: + I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); + if (rx->sta) + rx->sta->rx_dropped++; + dev_kfree_skb(rx->skb); + break; + case RX_QUEUED: + I802_DEBUG_INC(rx->sdata->local->rx_handlers_queued); + break; + } +} - rx->skb = skb; - rx->sdata = sdata; +static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, + struct sk_buff_head *frames) +{ + ieee80211_rx_result res = RX_DROP_MONITOR; + struct sk_buff *skb; #define CALL_RXH(rxh) \ do { \ @@ -2288,17 +2324,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, goto rxh_next; \ } while (0); - /* - * NB: the rxh_next label works even if we jump - * to it from here because then the list will - * be empty, which is a trivial check - */ - CALL_RXH(ieee80211_rx_h_passive_scan) - CALL_RXH(ieee80211_rx_h_check) - - ieee80211_rx_reorder_ampdu(rx, &reorder_release); - - while ((skb = __skb_dequeue(&reorder_release))) { + while ((skb = __skb_dequeue(frames))) { /* * all the other fields are valid across frames * that belong to an aMPDU since they are on the @@ -2316,42 +2342,58 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, CALL_RXH(ieee80211_rx_h_remove_qos_control) CALL_RXH(ieee80211_rx_h_amsdu) #ifdef CONFIG_MAC80211_MESH - if (ieee80211_vif_is_mesh(&sdata->vif)) + if (ieee80211_vif_is_mesh(&rx->sdata->vif)) CALL_RXH(ieee80211_rx_h_mesh_fwding); #endif CALL_RXH(ieee80211_rx_h_data) /* special treatment -- needs the queue */ - res = ieee80211_rx_h_ctrl(rx, &reorder_release); + res = ieee80211_rx_h_ctrl(rx, frames); if (res != RX_CONTINUE) goto rxh_next; CALL_RXH(ieee80211_rx_h_action) CALL_RXH(ieee80211_rx_h_mgmt) + rxh_next: + ieee80211_rx_handlers_result(rx, res); + #undef CALL_RXH + } +} + +static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, + struct ieee80211_rx_data *rx, + struct sk_buff *skb, + struct ieee80211_rate *rate) +{ + struct sk_buff_head reorder_release; + ieee80211_rx_result res = RX_DROP_MONITOR; + + __skb_queue_head_init(&reorder_release); + + rx->skb = skb; + rx->sdata = sdata; + +#define CALL_RXH(rxh) \ + do { \ + res = rxh(rx); \ + if (res != RX_CONTINUE) \ + goto rxh_next; \ + } while (0); + + CALL_RXH(ieee80211_rx_h_passive_scan) + CALL_RXH(ieee80211_rx_h_check) + + ieee80211_rx_reorder_ampdu(rx, &reorder_release); + + ieee80211_rx_handlers(rx, &reorder_release); + return; rxh_next: - switch (res) { - case RX_DROP_MONITOR: - I802_DEBUG_INC(sdata->local->rx_handlers_drop); - if (rx->sta) - rx->sta->rx_dropped++; - /* fall through */ - case RX_CONTINUE: - ieee80211_rx_cooked_monitor(rx, rate); - break; - case RX_DROP_UNUSABLE: - I802_DEBUG_INC(sdata->local->rx_handlers_drop); - if (rx->sta) - rx->sta->rx_dropped++; - dev_kfree_skb(rx->skb); - break; - case RX_QUEUED: - I802_DEBUG_INC(sdata->local->rx_handlers_queued); - break; - } - } + ieee80211_rx_handlers_result(rx, res); + +#undef CALL_RXH } /* main receive path */ -- cgit v1.2.3-59-g8ed1b From 071d9ac253ff51154beb7e33967168e30bc96053 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 5 Aug 2010 01:36:36 +0200 Subject: mac80211: remove unused rate function parameter This patch removes a few stale parameters and variables which survived the last, large rx-path reorganization: "mac80211: correctly place aMPDU RX reorder code" Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/rx.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 8301b4a980a2..d5b91b6eb120 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -538,20 +538,12 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, int index, struct sk_buff_head *frames) { - struct ieee80211_supported_band *sband; - struct ieee80211_rate *rate = NULL; struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; - struct ieee80211_rx_status *status; if (!skb) goto no_frame; - status = IEEE80211_SKB_RXCB(skb); - - /* release the reordered frames to stack */ - sband = hw->wiphy->bands[status->band]; - if (!(status->flag & RX_FLAG_HT)) - rate = &sband->bitrates[status->rate_idx]; + /* release the frame from the reorder ring buffer */ tid_agg_rx->stored_mpdu_num--; tid_agg_rx->reorder_buf[index] = NULL; __skb_queue_tail(frames, skb); @@ -2364,8 +2356,7 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, struct ieee80211_rx_data *rx, - struct sk_buff *skb, - struct ieee80211_rate *rate) + struct sk_buff *skb) { struct sk_buff_head reorder_release; ieee80211_rx_result res = RX_DROP_MONITOR; @@ -2489,8 +2480,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, * be called with rcu_read_lock protection. */ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct ieee80211_rate *rate) + struct sk_buff *skb) { struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_local *local = hw_to_local(hw); @@ -2598,7 +2588,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, prev->name); goto next; } - ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); + ieee80211_invoke_rx_handlers(prev, &rx, skb_new); next: prev = sdata; } @@ -2614,7 +2604,7 @@ next: } } if (prev) - ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); + ieee80211_invoke_rx_handlers(prev, &rx, skb); else dev_kfree_skb(skb); } @@ -2709,7 +2699,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) return; } - __ieee80211_rx_handle_packet(hw, skb, rate); + __ieee80211_rx_handle_packet(hw, skb); rcu_read_unlock(); -- cgit v1.2.3-59-g8ed1b From 2bff8ebf32a7c5ec9e5f5eeffef94a8cb622f5f0 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 5 Aug 2010 01:36:41 +0200 Subject: mac80211: AMPDU rx reorder timeout timer This patch introduces a new timer, which will release queued-up MPDUs from the reorder buffer, whenever they've waited for more than HT_RX_REORDER_BUF_TIMEOUT (which is at around 100 ms). The advantage of having a dedicated timer, instead of relying on a constant stream of freshly arriving aMPDUs to release the old ones, is particularly observable when even a small fraction of MPDUs are forever lost at low network speeds. Previously under these circumstances frames would become stuck in the reorder buffer and the network stack of both HT peers throttled back, instead of revving up and gunning the pipes. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/agg-rx.c | 22 +++++++++++++++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/rx.c | 70 +++++++++++++++++++++++++++++++++++++++++----- net/mac80211/sta_info.h | 16 +++++++---- 4 files changed, 97 insertions(+), 12 deletions(-) diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 965b272499fd..58eab9e8e4ee 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -86,6 +86,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, tid, 0, reason); del_timer_sync(&tid_rx->session_timer); + del_timer_sync(&tid_rx->reorder_timer); call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); } @@ -120,6 +121,20 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); } +static void sta_rx_agg_reorder_timer_expired(unsigned long data) +{ + u8 *ptid = (u8 *)data; + u8 *timer_to_id = ptid - *ptid; + struct sta_info *sta = container_of(timer_to_id, struct sta_info, + timer_to_tid[0]); + + rcu_read_lock(); + spin_lock(&sta->lock); + ieee80211_release_reorder_timeout(sta, *ptid); + spin_unlock(&sta->lock); + rcu_read_unlock(); +} + static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, u8 dialog_token, u16 status, u16 policy, u16 buf_size, u16 timeout) @@ -251,11 +266,18 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, goto end; } + spin_lock_init(&tid_agg_rx->reorder_lock); + /* rx timer */ tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; init_timer(&tid_agg_rx->session_timer); + /* rx reorder timer */ + tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired; + tid_agg_rx->reorder_timer.data = (unsigned long)&sta->timer_to_tid[tid]; + init_timer(&tid_agg_rx->reorder_timer); + /* prepare reordering buffer */ tid_agg_rx->reorder_buf = kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index fb4363e148f2..b44e03a02da9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1136,6 +1136,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); void ieee80211_ba_session_work(struct work_struct *work); void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid); +void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid); /* Spectrum management */ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d5b91b6eb120..f24a0a1cff1a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -572,6 +572,8 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, * frames that have not yet been received are assumed to be lost and the skb * can be released for processing. This may also release other skb's from the * reorder buffer if there are no additional gaps between the frames. + * + * Callers must hold tid_agg_rx->reorder_lock. */ #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) @@ -579,7 +581,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, struct tid_ampdu_rx *tid_agg_rx, struct sk_buff_head *frames) { - int index; + int index, j; /* release the buffer until next missing frame */ index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % @@ -590,7 +592,6 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, * No buffers ready to be released, but check whether any * frames in the reorder buffer have timed out. */ - int j; int skipped = 1; for (j = (index + 1) % tid_agg_rx->buf_size; j != index; j = (j + 1) % tid_agg_rx->buf_size) { @@ -600,7 +601,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, } if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + HT_RX_REORDER_BUF_TIMEOUT)) - break; + goto set_release_timer; #ifdef CONFIG_MAC80211_HT_DEBUG if (net_ratelimit()) @@ -624,6 +625,25 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; } + + if (tid_agg_rx->stored_mpdu_num) { + j = index = seq_sub(tid_agg_rx->head_seq_num, + tid_agg_rx->ssn) % tid_agg_rx->buf_size; + + for (; j != (index - 1) % tid_agg_rx->buf_size; + j = (j + 1) % tid_agg_rx->buf_size) { + if (tid_agg_rx->reorder_buf[j]) + break; + } + + set_release_timer: + + mod_timer(&tid_agg_rx->reorder_timer, + tid_agg_rx->reorder_time[j] + + HT_RX_REORDER_BUF_TIMEOUT); + } else { + del_timer(&tid_agg_rx->reorder_timer); + } } /* @@ -641,14 +661,16 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; u16 head_seq_num, buf_size; int index; + bool ret = true; buf_size = tid_agg_rx->buf_size; head_seq_num = tid_agg_rx->head_seq_num; + spin_lock(&tid_agg_rx->reorder_lock); /* frame with out of date sequence number */ if (seq_less(mpdu_seq_num, head_seq_num)) { dev_kfree_skb(skb); - return true; + goto out; } /* @@ -669,7 +691,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, /* check if we already stored this frame */ if (tid_agg_rx->reorder_buf[index]) { dev_kfree_skb(skb); - return true; + goto out; } /* @@ -679,7 +701,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, if (mpdu_seq_num == tid_agg_rx->head_seq_num && tid_agg_rx->stored_mpdu_num == 0) { tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); - return false; + ret = false; + goto out; } /* put the frame in the reordering buffer */ @@ -688,7 +711,9 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, tid_agg_rx->stored_mpdu_num++; ieee80211_sta_reorder_release(hw, tid_agg_rx, frames); - return true; + out: + spin_unlock(&tid_agg_rx->reorder_lock); + return ret; } /* @@ -2387,6 +2412,37 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, #undef CALL_RXH } +/* + * This function makes calls into the RX path. Therefore the + * caller must hold the sta_info->lock and everything has to + * be under rcu_read_lock protection as well. + */ +void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) +{ + struct sk_buff_head frames; + struct ieee80211_rx_data rx = { }; + + __skb_queue_head_init(&frames); + + /* construct rx struct */ + rx.sta = sta; + rx.sdata = sta->sdata; + rx.local = sta->local; + rx.queue = tid; + rx.flags |= IEEE80211_RX_RA_MATCH; + + if (unlikely(test_bit(SCAN_HW_SCANNING, &sta->local->scanning) || + test_bit(SCAN_OFF_CHANNEL, &sta->local->scanning))) + rx.flags |= IEEE80211_RX_IN_SCAN; + + spin_lock(&sta->ampdu_mlme.tid_rx[tid]->reorder_lock); + ieee80211_sta_reorder_release(&sta->local->hw, + sta->ampdu_mlme.tid_rx[tid], &frames); + spin_unlock(&sta->ampdu_mlme.tid_rx[tid]->reorder_lock); + + ieee80211_rx_handlers(&rx, &frames); +} + /* main receive path */ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 54262e72376d..810c5ce98316 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -103,6 +103,7 @@ struct tid_ampdu_tx { * @reorder_buf: buffer to reorder incoming aggregated MPDUs * @reorder_time: jiffies when skb was added * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) + * @reorder_timer: releases expired frames from the reorder buffer. * @head_seq_num: head sequence number in reordering buffer. * @stored_mpdu_num: number of MPDUs in reordering buffer * @ssn: Starting Sequence Number expected to be aggregated. @@ -110,20 +111,25 @@ struct tid_ampdu_tx { * @timeout: reset timer value (in TUs). * @dialog_token: dialog token for aggregation session * @rcu_head: RCU head used for freeing this struct + * @reorder_lock: serializes access to reorder buffer, see below. * * This structure is protected by RCU and the per-station * spinlock. Assignments to the array holding it must hold - * the spinlock, only the RX path can access it under RCU - * lock-free. The RX path, since it is single-threaded, - * can even modify the structure without locking since the - * only other modifications to it are done when the struct - * can not yet or no longer be found by the RX path. + * the spinlock. + * + * The @reorder_lock is used to protect the variables and + * arrays such as @reorder_buf, @reorder_time, @head_seq_num, + * @stored_mpdu_num and @reorder_time from being corrupted by + * concurrent access of the RX path and the expired frame + * release timer. */ struct tid_ampdu_rx { struct rcu_head rcu_head; + spinlock_t reorder_lock; struct sk_buff **reorder_buf; unsigned long *reorder_time; struct timer_list session_timer; + struct timer_list reorder_timer; u16 head_seq_num; u16 stored_mpdu_num; u16 ssn; -- cgit v1.2.3-59-g8ed1b From 3f3b6a8d90b6e762e2bb83e6a9e86d9534b56cdc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Aug 2010 10:20:27 +0200 Subject: cfg80211: deauth doesn't always imply disconnect When an AP sends a deauth frame, or we send one to an AP, that only means we lost our connection if we were actually connected to that AP. Check this to avoid sending spurious "disconnected" events and breaking "iw ... link" reporting. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/mlme.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index d1a3fb99fdf2..ee0af32ed59e 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -149,7 +149,7 @@ void __cfg80211_send_deauth(struct net_device *dev, struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; int i; - bool found = false; + bool found = false, was_current = false; ASSERT_WDEV_LOCK(wdev); @@ -159,6 +159,7 @@ void __cfg80211_send_deauth(struct net_device *dev, cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; found = true; + was_current = true; } else for (i = 0; i < MAX_AUTH_BSSES; i++) { if (wdev->auth_bsses[i] && memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { @@ -183,7 +184,7 @@ void __cfg80211_send_deauth(struct net_device *dev, nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); - if (wdev->sme_state == CFG80211_SME_CONNECTED) { + if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { u16 reason_code; bool from_ap; -- cgit v1.2.3-59-g8ed1b From 1fdaa46e9f26ccbab5e0eb8c4d4f8e1fbf32c7df Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Thu, 5 Aug 2010 15:51:35 +0200 Subject: net: mac80211: Fix a typo. "userpace" -> "userspace" Signed-off-by: Andrea Gelmini Signed-off-by: John W. Linville --- net/mac80211/rc80211_pid_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c index 47438b4a9af5..135f36fd4d5d 100644 --- a/net/mac80211/rc80211_pid_debugfs.c +++ b/net/mac80211/rc80211_pid_debugfs.c @@ -162,7 +162,7 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf, file_info->next_entry = (file_info->next_entry + 1) % RC_PID_EVENT_RING_SIZE; - /* Print information about the event. Note that userpace needs to + /* Print information about the event. Note that userspace needs to * provide large enough buffers. */ length = length < RC_PID_PRINT_BUF_SIZE ? length : RC_PID_PRINT_BUF_SIZE; -- cgit v1.2.3-59-g8ed1b From 7da7cc1d42d8ce02cca16df8c021e6d657f1f8fd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Aug 2010 17:02:38 +0200 Subject: mac80211: per interface idle notification Sometimes we don't just need to know whether or not the device is idle, but also per interface. This adds that reporting capability to mac80211. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 6 ++++++ net/mac80211/ibss.c | 8 +++++-- net/mac80211/ieee80211_i.h | 3 +++ net/mac80211/iface.c | 53 +++++++++++++++++++++++++++++++++++++++------- net/mac80211/mlme.c | 17 +++++++++++++-- net/mac80211/scan.c | 2 ++ net/mac80211/work.c | 8 +++---- 7 files changed, 81 insertions(+), 16 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3f1e03b521ec..3a3c26f647b7 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -149,6 +149,7 @@ struct ieee80211_low_level_stats { * @BSS_CHANGED_ARP_FILTER: Hardware ARP filter address list or state changed. * @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note * that it is only ever disabled for station mode. + * @BSS_CHANGED_IDLE: Idle changed for this BSS/interface. */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -165,6 +166,7 @@ enum ieee80211_bss_change { BSS_CHANGED_IBSS = 1<<11, BSS_CHANGED_ARP_FILTER = 1<<12, BSS_CHANGED_QOS = 1<<13, + BSS_CHANGED_IDLE = 1<<14, /* when adding here, make sure to change ieee80211_reconfig */ }; @@ -223,6 +225,9 @@ enum ieee80211_bss_change { * hardware must not perform any ARP filtering. Note, that the filter will * be enabled also in promiscuous mode. * @qos: This is a QoS-enabled BSS. + * @idle: This interface is idle. There's also a global idle flag in the + * hardware config which may be more appropriate depending on what + * your driver/device needs to do. */ struct ieee80211_bss_conf { const u8 *bssid; @@ -247,6 +252,7 @@ struct ieee80211_bss_conf { u8 arp_addr_cnt; bool arp_filter_enabled; bool qos; + bool idle; }; /** diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index c691780725a7..32af97108425 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -920,12 +920,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); sdata->u.ibss.ssid_len = params->ssid_len; + mutex_unlock(&sdata->u.ibss.mtx); + + mutex_lock(&sdata->local->mtx); ieee80211_recalc_idle(sdata->local); + mutex_unlock(&sdata->local->mtx); ieee80211_queue_work(&sdata->local->hw, &sdata->work); - mutex_unlock(&sdata->u.ibss.mtx); - return 0; } @@ -980,7 +982,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) mutex_unlock(&sdata->u.ibss.mtx); + mutex_lock(&local->mtx); ieee80211_recalc_idle(sdata->local); + mutex_unlock(&local->mtx); return 0; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b44e03a02da9..98e783c6a363 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -497,6 +497,9 @@ struct ieee80211_sub_if_data { */ bool ht_opmode_valid; + /* to detect idle changes */ + bool old_idle; + /* Fragment table for host-based reassembly */ struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; unsigned int fragment_next; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index c1008a9d7bfb..9459aeee0ddc 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -309,7 +309,9 @@ static int ieee80211_open(struct net_device *dev) if (sdata->flags & IEEE80211_SDATA_PROMISC) atomic_inc(&local->iff_promiscs); + mutex_lock(&local->mtx); hw_reconf_flags |= __ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); local->open_count++; if (hw_reconf_flags) { @@ -516,7 +518,9 @@ static int ieee80211_stop(struct net_device *dev) sdata->bss = NULL; + mutex_lock(&local->mtx); hw_reconf_flags |= __ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); ieee80211_recalc_ps(local, -1); @@ -1199,28 +1203,61 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; int count = 0; + bool working = false, scanning = false; + struct ieee80211_work *wk; - if (!list_empty(&local->work_list)) - return ieee80211_idle_off(local, "working"); - - if (local->scanning) - return ieee80211_idle_off(local, "scanning"); +#ifdef CONFIG_PROVE_LOCKING + WARN_ON(debug_locks && !lockdep_rtnl_is_held() && + !lockdep_is_held(&local->iflist_mtx)); +#endif + lockdep_assert_held(&local->mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!ieee80211_sdata_running(sdata)) + if (!ieee80211_sdata_running(sdata)) { + sdata->vif.bss_conf.idle = true; continue; + } + + sdata->old_idle = sdata->vif.bss_conf.idle; + /* do not count disabled managed interfaces */ if (sdata->vif.type == NL80211_IFTYPE_STATION && - !sdata->u.mgd.associated) + !sdata->u.mgd.associated) { + sdata->vif.bss_conf.idle = true; continue; + } /* do not count unused IBSS interfaces */ if (sdata->vif.type == NL80211_IFTYPE_ADHOC && - !sdata->u.ibss.ssid_len) + !sdata->u.ibss.ssid_len) { + sdata->vif.bss_conf.idle = true; continue; + } /* count everything else */ count++; } + list_for_each_entry(wk, &local->work_list, list) { + working = true; + wk->sdata->vif.bss_conf.idle = false; + } + + if (local->scan_sdata) { + scanning = true; + local->scan_sdata->vif.bss_conf.idle = false; + } + + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->old_idle == sdata->vif.bss_conf.idle) + continue; + if (!ieee80211_sdata_running(sdata)) + continue; + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); + } + + if (working) + return ieee80211_idle_off(local, "working"); + if (scanning) + return ieee80211_idle_off(local, "scanning"); if (!count) return ieee80211_idle_on(local); else diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 17e9257a61d8..82e7cec5179c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1103,8 +1103,11 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); ieee80211_set_disassoc(sdata, true); - ieee80211_recalc_idle(local); mutex_unlock(&ifmgd->mtx); + + mutex_lock(&local->mtx); + ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); /* * must be outside lock due to cfg80211, * but that's not a problem. @@ -1173,7 +1176,9 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, sdata->name, bssid, reason_code); ieee80211_set_disassoc(sdata, true); + mutex_lock(&sdata->local->mtx); ieee80211_recalc_idle(sdata->local); + mutex_unlock(&sdata->local->mtx); return RX_MGMT_CFG80211_DEAUTH; } @@ -1203,7 +1208,9 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, sdata->name, mgmt->sa, reason_code); ieee80211_set_disassoc(sdata, true); + mutex_lock(&sdata->local->mtx); ieee80211_recalc_idle(sdata->local); + mutex_unlock(&sdata->local->mtx); return RX_MGMT_CFG80211_DISASSOC; } @@ -1840,8 +1847,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) " after %dms, disconnecting.\n", bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); ieee80211_set_disassoc(sdata, true); - ieee80211_recalc_idle(local); mutex_unlock(&ifmgd->mtx); + mutex_lock(&local->mtx); + ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); /* * must be outside lock due to cfg80211, * but that's not a problem. @@ -2319,7 +2328,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, if (assoc_bss) sta_info_destroy_addr(sdata, bssid); + mutex_lock(&sdata->local->mtx); ieee80211_recalc_idle(sdata->local); + mutex_unlock(&sdata->local->mtx); return 0; } @@ -2357,7 +2368,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, cookie, !req->local_state_change); sta_info_destroy_addr(sdata, bssid); + mutex_lock(&sdata->local->mtx); ieee80211_recalc_idle(sdata->local); + mutex_unlock(&sdata->local->mtx); return 0; } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f31f549733b1..31f233f7f51a 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -304,7 +304,9 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ieee80211_offchannel_return(local, true); done: + mutex_lock(&local->mtx); ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); ieee80211_mlme_notify_scan_completed(local); ieee80211_ibss_notify_scan_completed(local); ieee80211_mesh_notify_scan_completed(local); diff --git a/net/mac80211/work.c b/net/mac80211/work.c index b98af64f5862..ae344d1ba056 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -888,10 +888,10 @@ static void ieee80211_work_work(struct work_struct *work) while ((skb = skb_dequeue(&local->work_skb_queue))) ieee80211_work_rx_queued_mgmt(local, skb); - ieee80211_recalc_idle(local); - mutex_lock(&local->mtx); + ieee80211_recalc_idle(local); + list_for_each_entry_safe(wk, tmp, &local->work_list, list) { bool started = wk->started; @@ -1001,10 +1001,10 @@ static void ieee80211_work_work(struct work_struct *work) &local->scan_work, round_jiffies_relative(0)); - mutex_unlock(&local->mtx); - ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); + list_for_each_entry_safe(wk, tmp, &free_work, list) { wk->done(wk, NULL); list_del(&wk->list); -- cgit v1.2.3-59-g8ed1b From d1f5b7a34aa5ff703c4966ea2652d4212ac75940 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Aug 2010 17:05:55 +0200 Subject: mac80211: allow drivers to request SM PS mode change Sometimes drivers have more information than the stack about how their antennas/chains are used, and may require that the SM PS mode be changed. This could happen, for example, when detecting that the user disconnected an antenna. Thus this patch introduces API to allow drivers to request SM PS mode changes. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 12 ++++++++++++ net/mac80211/ht.c | 28 ++++++++++++++++++++++++++++ net/mac80211/ieee80211_i.h | 6 +++++- net/mac80211/mlme.c | 3 +++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3a3c26f647b7..871ed1de736a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2548,6 +2548,18 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, */ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success); +/** + * ieee80211_request_smps - request SM PS transition + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @mode: new SM PS mode + * + * This allows the driver to request an SM PS transition in managed + * mode. This is useful when the driver has more information than + * the stack about possible interference, for example by bluetooth. + */ +void ieee80211_request_smps(struct ieee80211_vif *vif, + enum ieee80211_smps_mode smps_mode); + /* Rate control API */ /** diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 9d101fb33861..11f74f5f7b2f 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -265,3 +265,31 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, return 0; } + +void ieee80211_request_smps_work(struct work_struct *work) +{ + struct ieee80211_sub_if_data *sdata = + container_of(work, struct ieee80211_sub_if_data, + u.mgd.request_smps_work); + + mutex_lock(&sdata->u.mgd.mtx); + __ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode); + mutex_unlock(&sdata->u.mgd.mtx); +} + +void ieee80211_request_smps(struct ieee80211_vif *vif, + enum ieee80211_smps_mode smps_mode) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + + if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) + return; + + if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF)) + smps_mode = IEEE80211_SMPS_AUTOMATIC; + + ieee80211_queue_work(&sdata->local->hw, + &sdata->u.mgd.request_smps_work); +} +/* this might change ... don't want non-open drivers using it */ +EXPORT_SYMBOL_GPL(ieee80211_request_smps); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 98e783c6a363..1bf05bfd149d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -343,7 +343,10 @@ struct ieee80211_if_managed { unsigned long timers_running; /* used for quiesce/restart */ bool powersave; /* powersave requested for this iface */ enum ieee80211_smps_mode req_smps, /* requested smps mode */ - ap_smps; /* smps mode AP thinks we're in */ + ap_smps, /* smps mode AP thinks we're in */ + driver_smps_mode; /* smps mode request */ + + struct work_struct request_smps_work; unsigned int flags; @@ -1113,6 +1116,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, enum ieee80211_smps_mode smps, const u8 *da, const u8 *bssid); +void ieee80211_request_smps_work(struct work_struct *work); void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, u16 initiator, u16 reason); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 82e7cec5179c..38996a44aa8e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1926,6 +1926,8 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) * time -- the code here is properly synchronised. */ + cancel_work_sync(&ifmgd->request_smps_work); + cancel_work_sync(&ifmgd->beacon_connection_loss_work); if (del_timer_sync(&ifmgd->timer)) set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); @@ -1961,6 +1963,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); INIT_WORK(&ifmgd->beacon_connection_loss_work, ieee80211_beacon_connection_loss_work); + INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work); setup_timer(&ifmgd->timer, ieee80211_sta_timer, (unsigned long) sdata); setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, -- cgit v1.2.3-59-g8ed1b From 04600794958f1833f5571c6cde40f260ab557f55 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Aug 2010 17:45:15 +0200 Subject: cfg80211: support sysfs namespaces Enable using network namespaces with wireless devices even when sysfs is enabled using the same infrastructure that was built for netdevs. Signed-off-by: Johannes Berg Acked-by: "Eric W. Biederman" Signed-off-by: John W. Linville --- include/linux/netdevice.h | 2 ++ net/core/net-sysfs.c | 3 ++- net/wireless/core.c | 7 ++++++- net/wireless/sysfs.c | 9 +++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 46c36ffe20ee..a4b14fd81c6a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2171,6 +2171,8 @@ extern void dev_seq_stop(struct seq_file *seq, void *v); extern int netdev_class_create_file(struct class_attribute *class_attr); extern void netdev_class_remove_file(struct class_attribute *class_attr); +extern struct kobj_ns_type_operations net_ns_type_operations; + extern char *netdev_drivername(const struct net_device *dev, char *buffer, int len); extern void linkwatch_run_queue(void); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index af4dfbadf2a0..7d748542d97e 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -789,12 +789,13 @@ static const void *net_netlink_ns(struct sock *sk) return sock_net(sk); } -static struct kobj_ns_type_operations net_ns_type_operations = { +struct kobj_ns_type_operations net_ns_type_operations = { .type = KOBJ_NS_TYPE_NET, .current_ns = net_current_ns, .netlink_ns = net_netlink_ns, .initial_ns = net_initial_ns, }; +EXPORT_SYMBOL_GPL(net_ns_type_operations); static void net_kobj_ns_exit(struct net *net) { diff --git a/net/wireless/core.c b/net/wireless/core.c index 541e2fff5e9c..c70909c3eae4 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -253,11 +253,16 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, WARN_ON(err); wdev->netdev->features |= NETIF_F_NETNS_LOCAL; } + + return err; } wiphy_net_set(&rdev->wiphy, net); - return err; + err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev)); + WARN_ON(err); + + return 0; } static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 9f2cef3e0ca0..74a9e3cce452 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c @@ -110,6 +110,13 @@ static int wiphy_resume(struct device *dev) return ret; } +static const void *wiphy_namespace(struct device *d) +{ + struct wiphy *wiphy = container_of(d, struct wiphy, dev); + + return wiphy_net(wiphy); +} + struct class ieee80211_class = { .name = "ieee80211", .owner = THIS_MODULE, @@ -120,6 +127,8 @@ struct class ieee80211_class = { #endif .suspend = wiphy_suspend, .resume = wiphy_resume, + .ns_type = &net_ns_type_operations, + .namespace = wiphy_namespace, }; int wiphy_sysfs_init(void) -- cgit v1.2.3-59-g8ed1b From 2674f82d3eef97df98fd5dbd4224ce1ce4800a3b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 22:23:54 +0200 Subject: drivers/net/wireless/libertas: Adjust confusing if indentation At the point of the patched code, err has already been tested, so it is only worthwhile to test it again in the if branches where it is changed. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_spi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index fe3f08028eb3..3965c6cf504a 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -800,14 +800,16 @@ static int lbs_spi_thread(void *data) goto err; } - if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) + if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) { err = if_spi_c2h_cmd(card); if (err) goto err; - if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) + } + if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) { err = if_spi_c2h_data(card); if (err) goto err; + } /* workaround: in PS mode, the card does not set the Command * Download Ready bit, but it sets TX Download Ready. */ -- cgit v1.2.3-59-g8ed1b From a3d558355e7695ca78fc3f0df611af482096bd87 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 22:26:04 +0200 Subject: drivers/net/wireless/prism54: Adjust confusing if indentation Indent the branch of an if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 77cd65db8500..d97a2caf582b 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -3234,7 +3234,7 @@ prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) switch (cmd) { case PRISM54_HOSTAPD: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EPERM; ret = prism54_hostapd(ndev, &wrq->u.data); return ret; } -- cgit v1.2.3-59-g8ed1b From 6fe140024ff66d7eccde1a151a08c262dc7a1e6f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 22:26:56 +0200 Subject: drivers/net/wireless/ath/ath9k: Adjust confusing if indentation Outdent the code following the if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 5b995bee70ae..a462da23e87e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -185,7 +185,7 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) ath_print(common, ATH_DBG_INTERRUPT, "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); - REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); + REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); } -- cgit v1.2.3-59-g8ed1b From c17512d846a4b063c8d3e708d82c0664d9c7182e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 5 Aug 2010 17:56:54 -0400 Subject: ath9k: remove duplicate get_hw_crypto_keytype() Use ath9k_cmn_get_hw_crypto_keytype() instead which is already exported and shared, and does exactly the same thing. Reported-by: Johannes Berg Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 4dda14e36227..457f07692ac7 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1407,22 +1407,6 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) return htype; } -static int get_hw_crypto_keytype(struct sk_buff *skb) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - - if (tx_info->control.hw_key) { - if (tx_info->control.hw_key->alg == ALG_WEP) - return ATH9K_KEY_TYPE_WEP; - else if (tx_info->control.hw_key->alg == ALG_TKIP) - return ATH9K_KEY_TYPE_TKIP; - else if (tx_info->control.hw_key->alg == ALG_CCMP) - return ATH9K_KEY_TYPE_AES; - } - - return ATH9K_KEY_TYPE_CLEAR; -} - static void assign_aggr_tid_seqno(struct sk_buff *skb, struct ath_buf *bf) { @@ -1661,7 +1645,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, bf->bf_state.bfs_paprd_timestamp = jiffies; bf->bf_flags = setup_tx_flags(skb, use_ldpc); - bf->bf_keytype = get_hw_crypto_keytype(skb); + bf->bf_keytype = ath9k_cmn_get_hw_crypto_keytype(skb); if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { bf->bf_frmlen += tx_info->control.hw_key->icv_len; bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; -- cgit v1.2.3-59-g8ed1b From 7e613e1666d59b5364f7918b3427bf328ac5f9ca Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 6 Aug 2010 20:45:38 +0200 Subject: rt2x00: Move USB tx/rx done handling to workqueue Move all TX and RX completion handling into a work structure, which is handeled on the mac80211 workqueue. This simplifies the code in rt2x00lib since it no longer needs to check if the device is USB or PCI to decide which mac80211 function should be used. In the watchdog some changes are needed since it can no longer rely on the TX completion function to be run while looping through the entries. (Both functions now work on the same workqueue, so this would deadlock). So the watchdog now waits for the URB to return, and handle the TX status report directly. As a side-effect, the debugfs entry for the RX queue now correctly displays the positions of the INDEX and INDEX_DONE counters. This also implies that it is not possible to perform checks like queue_empty() and queue_full() on the RX queue. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 9 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 35 +++----- drivers/net/wireless/rt2x00/rt2x00queue.c | 7 +- drivers/net/wireless/rt2x00/rt2x00queue.h | 6 +- drivers/net/wireless/rt2x00/rt2x00usb.c | 133 ++++++++++++++++++++++-------- 5 files changed, 128 insertions(+), 62 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c21af38cc5af..5276c19f380a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1,5 +1,6 @@ /* - Copyright (C) 2004 - 2009 Ivo van Doorn + Copyright (C) 2010 Willow Garage + Copyright (C) 2004 - 2010 Ivo van Doorn Copyright (C) 2004 - 2009 Gertjan van Wingerde @@ -862,6 +863,12 @@ struct rt2x00_dev { */ struct work_struct intf_work; + /** + * Scheduled work for TX/RX done handling (USB devices) + */ + struct work_struct rxdone_work; + struct work_struct txdone_work; + /* * Data queue arrays for RX, TX and Beacon. * The Beacon array also contains the Atim queue diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 585e8166f22a..94621bd4fb9b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1,5 +1,6 @@ /* - Copyright (C) 2004 - 2009 Ivo van Doorn + Copyright (C) 2010 Willow Garage + Copyright (C) 2004 - 2010 Ivo van Doorn This program is free software; you can redistribute it and/or modify @@ -383,15 +384,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, * send the status report back. */ if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) - /* - * Only PCI and SOC devices process the tx status in process - * context. Hence use ieee80211_tx_status for PCI and SOC - * devices and stick to ieee80211_tx_status_irqsafe for USB. - */ - if (rt2x00_is_usb(rt2x00dev)) - ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); - else - ieee80211_tx_status(rt2x00dev->hw, entry->skb); + ieee80211_tx_status(rt2x00dev->hw, entry->skb); else dev_kfree_skb_any(entry->skb); @@ -403,7 +396,6 @@ void rt2x00lib_txdone(struct queue_entry *entry, rt2x00dev->ops->lib->clear_entry(entry); - clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); /* @@ -463,6 +455,10 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; unsigned int header_length; int rate_idx; + + if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) + goto submit_entry; + /* * Allocate a new sk_buffer. If no new buffer available, drop the * received frame and reuse the existing buffer. @@ -540,26 +536,17 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, */ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status)); - - /* - * Currently only PCI and SOC devices handle rx interrupts in process - * context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni - * for PCI and SOC devices. - */ - if (rt2x00_is_usb(rt2x00dev)) - ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb); - else - ieee80211_rx_ni(rt2x00dev->hw, entry->skb); + ieee80211_rx_ni(rt2x00dev->hw, entry->skb); /* * Replace the skb with the freshly allocated one. */ entry->skb = skb; - entry->flags = 0; +submit_entry: rt2x00dev->ops->lib->clear_entry(entry); - rt2x00queue_index_inc(entry->queue, Q_INDEX); + rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); } EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); @@ -1017,6 +1004,8 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) * Stop all work. */ cancel_work_sync(&rt2x00dev->intf_work); + cancel_work_sync(&rt2x00dev->rxdone_work); + cancel_work_sync(&rt2x00dev->txdone_work); /* * Uninitialize device. diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index a3401d301058..18220953851e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -1,5 +1,6 @@ /* - Copyright (C) 2004 - 2009 Ivo van Doorn + Copyright (C) 2010 Willow Garage + Copyright (C) 2004 - 2010 Ivo van Doorn Copyright (C) 2004 - 2009 Gertjan van Wingerde @@ -730,9 +731,9 @@ void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) rt2x00queue_reset(queue); for (i = 0; i < queue->limit; i++) { - queue->entries[i].flags = 0; - rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); + if (queue->qid == QID_RX) + rt2x00queue_index_inc(queue, Q_INDEX); } } } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 191e7775a9c0..38b47919c868 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2009 Ivo van Doorn + Copyright (C) 2004 - 2010 Ivo van Doorn This program is free software; you can redistribute it and/or modify @@ -363,12 +363,16 @@ struct txentry_desc { * the device has signaled it is done with it. * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting * for the signal to start sending. + * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured + * while transfering the data to the hardware. No TX status report will + * be expected from the hardware. */ enum queue_entry_flags { ENTRY_BCN_ASSIGNED, ENTRY_OWNER_DEVICE_DATA, ENTRY_OWNER_DEVICE_CRYPTO, ENTRY_DATA_PENDING, + ENTRY_DATA_IO_FAILED }; /** diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index ff3a36622d1b..3f131017fd21 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -1,5 +1,6 @@ /* - Copyright (C) 2004 - 2009 Ivo van Doorn + Copyright (C) 2010 Willow Garage + Copyright (C) 2004 - 2010 Ivo van Doorn This program is free software; you can redistribute it and/or modify @@ -167,19 +168,12 @@ EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); /* * TX data handlers. */ -static void rt2x00usb_interrupt_txdone(struct urb *urb) +static void rt2x00usb_work_txdone_entry(struct queue_entry *entry) { - struct queue_entry *entry = (struct queue_entry *)urb->context; - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct txdone_entry_desc txdesc; - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || - !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) - return; - /* - * Obtain the status about this packet. - * Note that when the status is 0 it does not mean the + * If the transfer to hardware succeeded, it does not mean the * frame was send out correctly. It only means the frame * was succesfully pushed to the hardware, we have no * way to determine the transmission status right now. @@ -187,15 +181,56 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) * in the register). */ txdesc.flags = 0; - if (!urb->status) - __set_bit(TXDONE_UNKNOWN, &txdesc.flags); - else + if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) __set_bit(TXDONE_FAILURE, &txdesc.flags); + else + __set_bit(TXDONE_UNKNOWN, &txdesc.flags); txdesc.retry = 0; rt2x00lib_txdone(entry, &txdesc); } +static void rt2x00usb_work_txdone(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, txdone_work); + struct data_queue *queue; + struct queue_entry *entry; + + tx_queue_for_each(rt2x00dev, queue) { + while (!rt2x00queue_empty(queue)) { + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); + + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + break; + + rt2x00usb_work_txdone_entry(entry); + } + } +} + +static void rt2x00usb_interrupt_txdone(struct urb *urb) +{ + struct queue_entry *entry = (struct queue_entry *)urb->context; + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + + if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || + !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + return; + + /* + * Check if the frame was correctly uploaded + */ + if (urb->status) + __set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); + + /* + * Schedule the delayed work for reading the TX status + * from the device. + */ + ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); +} + static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; @@ -294,6 +329,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) { + struct queue_entry *entry; struct queue_entry_priv_usb *entry_priv; unsigned short threshold = queue->threshold; @@ -313,14 +349,22 @@ static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) * Reset all currently uploaded TX frames. */ while (!rt2x00queue_empty(queue)) { - entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data; + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); + entry_priv = entry->priv_data; usb_kill_urb(entry_priv->urb); /* * We need a short delay here to wait for - * the URB to be canceled and invoked the tx_done handler. + * the URB to be canceled */ - udelay(200); + do { + udelay(100); + } while (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)); + + /* + * Invoke the TX done handler + */ + rt2x00usb_work_txdone_entry(entry); } /* @@ -345,15 +389,41 @@ EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); /* * RX data handlers. */ +static void rt2x00usb_work_rxdone(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, rxdone_work); + struct queue_entry *entry; + struct skb_frame_desc *skbdesc; + u8 rxd[32]; + + while (!rt2x00queue_empty(rt2x00dev->rx)) { + entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); + + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + break; + + /* + * Fill in desc fields of the skb descriptor + */ + skbdesc = get_skb_frame_desc(entry->skb); + skbdesc->desc = rxd; + skbdesc->desc_len = entry->queue->desc_size; + + /* + * Send the frame to rt2x00lib for further processing. + */ + rt2x00lib_rxdone(rt2x00dev, entry); + } +} + static void rt2x00usb_interrupt_rxdone(struct urb *urb) { struct queue_entry *entry = (struct queue_entry *)urb->context; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - u8 rxd[32]; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || - !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; /* @@ -361,22 +431,14 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) * to be actually valid, or if the urb is signaling * a problem. */ - if (urb->actual_length < entry->queue->desc_size || urb->status) { - set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - usb_submit_urb(urb, GFP_ATOMIC); - return; - } - - /* - * Fill in desc fields of the skb descriptor - */ - skbdesc->desc = rxd; - skbdesc->desc_len = entry->queue->desc_size; + if (urb->actual_length < entry->queue->desc_size || urb->status) + __set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); /* - * Send the frame to rt2x00lib for further processing. + * Schedule the delayed work for reading the RX status + * from the device. */ - rt2x00lib_rxdone(rt2x00dev, entry); + ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); } /* @@ -405,6 +467,8 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) struct queue_entry_priv_usb *entry_priv = entry->priv_data; int pipe; + entry->flags = 0; + if (entry->queue->qid == QID_RX) { pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, @@ -413,8 +477,6 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); usb_submit_urb(entry_priv->urb, GFP_ATOMIC); - } else { - entry->flags = 0; } } EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); @@ -659,6 +721,9 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); + INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone); + INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone); + retval = rt2x00usb_alloc_reg(rt2x00dev); if (retval) goto exit_free_device; -- cgit v1.2.3-59-g8ed1b From 84804cdca043e2315bf5eae60807ac105929073f Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 6 Aug 2010 20:46:19 +0200 Subject: rt2x00: Set MIMO PS flag in tx descriptor for STAs in dynamic SMPS mode Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- drivers/net/wireless/rt2x00/rt2x00ht.c | 10 ++++++++++ drivers/net/wireless/rt2x00/rt2x00queue.h | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b66e0fd8f0fa..833b15751292 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -437,7 +437,8 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) rt2x00_desc_read(txwi, 0, &word); rt2x00_set_field32(&word, TXWI_W0_FRAG, test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); + rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, + test_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags)); rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); rt2x00_set_field32(&word, TXWI_W0_TS, test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index c004cd3a8847..ad3c7ff4837b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c @@ -54,6 +54,16 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, */ if (txrate->flags & IEEE80211_TX_RC_MCS) { txdesc->mcs = txrate->idx; + + /* + * MIMO PS should be set to 1 for STA's using dynamic SM PS + * when using more then one tx stream (>MCS7). + */ + if (tx_info->control.sta && txdesc->mcs > 7 && + (tx_info->control.sta->ht_cap.cap & + (WLAN_HT_CAP_SM_PS_DYNAMIC << + IEEE80211_HT_CAP_SM_PS_SHIFT))) + __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); } else { txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 38b47919c868..2d3bf843735f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -268,6 +268,7 @@ struct txdone_entry_desc { * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. * @ENTRY_TXD_HT_SHORT_GI: Use short GI. + * @ENTRY_TXD_HT_MIMO_PS: The receiving STA is in dynamic SM PS mode. */ enum txentry_desc_flags { ENTRY_TXD_RTS_FRAME, @@ -286,6 +287,7 @@ enum txentry_desc_flags { ENTRY_TXD_HT_AMPDU, ENTRY_TXD_HT_BW_40, ENTRY_TXD_HT_SHORT_GI, + ENTRY_TXD_HT_MIMO_PS, }; /** -- cgit v1.2.3-59-g8ed1b From 3392beced38f67615b7fc88374940cecec6a0e4f Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 6 Aug 2010 20:46:53 +0200 Subject: rt2x00: Add helper function for reporting tx status At some points, some drivers can't report the full TX status information. This can happen for the UNKNOWN state, or the FAILURE state (in case the URB failed). Add a wrapper function to simplify reporting the empty TX information. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 1 + drivers/net/wireless/rt2x00/rt2x00dev.c | 12 ++++++++++++ drivers/net/wireless/rt2x00/rt2x00usb.c | 10 ++-------- drivers/net/wireless/rt2x00/rt61pci.c | 6 +----- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 5276c19f380a..edfc2b759282 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1078,6 +1078,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc); +void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status); void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 94621bd4fb9b..6499cc416ca3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -408,6 +408,18 @@ void rt2x00lib_txdone(struct queue_entry *entry, } EXPORT_SYMBOL_GPL(rt2x00lib_txdone); +void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status) +{ + struct txdone_entry_desc txdesc; + + txdesc.flags = 0; + __set_bit(status, &txdesc.flags); + txdesc.retry = 0; + + rt2x00lib_txdone(entry, &txdesc); +} +EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo); + static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, struct rxdone_entry_desc *rxdesc) { diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 3f131017fd21..f76014f732ce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -170,8 +170,6 @@ EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); */ static void rt2x00usb_work_txdone_entry(struct queue_entry *entry) { - struct txdone_entry_desc txdesc; - /* * If the transfer to hardware succeeded, it does not mean the * frame was send out correctly. It only means the frame @@ -180,14 +178,10 @@ static void rt2x00usb_work_txdone_entry(struct queue_entry *entry) * (Only indirectly by looking at the failed TX counters * in the register). */ - txdesc.flags = 0; if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) - __set_bit(TXDONE_FAILURE, &txdesc.flags); + rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); else - __set_bit(TXDONE_UNKNOWN, &txdesc.flags); - txdesc.retry = 0; - - rt2x00lib_txdone(entry, &txdesc); + rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); } static void rt2x00usb_work_txdone(struct work_struct *work) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index e539c6cb636f..dc6f3ebb8376 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2107,11 +2107,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) "TX status report missed for entry %d\n", entry_done->entry_idx); - txdesc.flags = 0; - __set_bit(TXDONE_UNKNOWN, &txdesc.flags); - txdesc.retry = 0; - - rt2x00lib_txdone(entry_done, &txdesc); + rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); } -- cgit v1.2.3-59-g8ed1b From 0c5879bc62f9b8eb31520a86213466f3a68ec794 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 6 Aug 2010 20:47:20 +0200 Subject: rt2x00: Request TXWI pointer from driver The only reason why the write_tx_data callback function is needed inside the driver, is because the location of the TXWI descriptor is different on PCI and USB hardware. Except for the beacon, where the TXWI is always at the start of the SKB buffer. In both cases the drivers write_tx_data function only wrap around the function rt2800_write_txwi. Move write_tx_data completely into the rt2800lib library, and add a callback function to obtain the TXWI pointer. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 8 +++++--- drivers/net/wireless/rt2x00/rt2800lib.h | 11 ++++++++++- drivers/net/wireless/rt2x00/rt2800pci.c | 11 ++++------- drivers/net/wireless/rt2x00/rt2800usb.c | 14 +++++++------- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 833b15751292..6f1eb5824d2d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -427,8 +427,10 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2800_load_firmware); -void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) +void rt2800_write_tx_data(struct queue_entry *entry, + struct txentry_desc *txdesc) { + __le32 *txwi = rt2800_drv_get_txwi(entry); u32 word; /* @@ -479,7 +481,7 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); } -EXPORT_SYMBOL_GPL(rt2800_write_txwi); +EXPORT_SYMBOL_GPL(rt2800_write_tx_data); static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) { @@ -601,7 +603,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) /* * Add the TXWI for the beacon to the skb. */ - rt2800_write_txwi((__le32 *)entry->skb->data, txdesc); + rt2800_write_tx_data(entry, txdesc); /* * Dump beacon to userspace through debugfs. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 091641e3c5e2..8f975180727f 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -44,6 +44,7 @@ struct rt2800_ops { int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len); int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); + __le32 *(*drv_get_txwi)(struct queue_entry *entry); }; static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, @@ -126,6 +127,13 @@ static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) return rt2800ops->drv_init_registers(rt2x00dev); } +static inline __le32 *rt2800_drv_get_txwi(struct queue_entry *entry) +{ + const struct rt2800_ops *rt2800ops = entry->queue->rt2x00dev->ops->drv; + + return rt2800ops->drv_get_txwi(entry); +} + void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 command, const u8 token, const u8 arg0, const u8 arg1); @@ -135,7 +143,8 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len); -void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); +void rt2800_write_tx_data(struct queue_entry *entry, + struct txentry_desc *txdesc); void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 39b3846fa340..f415f6d5f601 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -566,15 +566,11 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, /* * TX descriptor initialization */ -static void rt2800pci_write_tx_data(struct queue_entry* entry, - struct txentry_desc *txdesc) +static __le32 *rt2800pci_get_txwi(struct queue_entry *entry) { - __le32 *txwi = (__le32 *) entry->skb->data; - - rt2800_write_txwi(txwi, txdesc); + return (__le32 *) entry->skb->data; } - static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, struct txentry_desc *txdesc) @@ -1011,6 +1007,7 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { .regbusy_read = rt2x00pci_regbusy_read, .drv_write_firmware = rt2800pci_write_firmware, .drv_init_registers = rt2800pci_init_registers, + .drv_get_txwi = rt2800pci_get_txwi, }; static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { @@ -1030,7 +1027,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, .write_tx_desc = rt2800pci_write_tx_desc, - .write_tx_data = rt2800pci_write_tx_data, + .write_tx_data = rt2800_write_tx_data, .write_beacon = rt2800_write_beacon, .kick_tx_queue = rt2800pci_kick_tx_queue, .kill_tx_queue = rt2800pci_kill_tx_queue, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 5a2dfe87c6b6..9084b9a36b57 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -320,15 +320,14 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, /* * TX descriptor initialization */ -static void rt2800usb_write_tx_data(struct queue_entry* entry, - struct txentry_desc *txdesc) +static __le32 *rt2800usb_get_txwi(struct queue_entry *entry) { - __le32 *txwi = (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE); - - rt2800_write_txwi(txwi, txdesc); + if (entry->queue->qid == QID_BEACON) + return (__le32 *) (entry->skb->data); + else + return (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE); } - static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, struct txentry_desc *txdesc) @@ -549,6 +548,7 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = { .regbusy_read = rt2x00usb_regbusy_read, .drv_write_firmware = rt2800usb_write_firmware, .drv_init_registers = rt2800usb_init_registers, + .drv_get_txwi = rt2800usb_get_txwi, }; static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { @@ -566,7 +566,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .link_tuner = rt2800_link_tuner, .watchdog = rt2x00usb_watchdog, .write_tx_desc = rt2800usb_write_tx_desc, - .write_tx_data = rt2800usb_write_tx_data, + .write_tx_data = rt2800_write_tx_data, .write_beacon = rt2800_write_beacon, .get_tx_data_len = rt2800usb_get_tx_data_len, .kick_tx_queue = rt2x00usb_kick_tx_queue, -- cgit v1.2.3-59-g8ed1b From 96481b20f4d6df7021867ae9a9deaa989ec32e40 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 6 Aug 2010 20:47:57 +0200 Subject: rt2x00: Implement TX status reporting for rt2800usb The TX_STA_FIFO register which is used for per-frame TX frame status reporting is also valid on rt2800usb. We can move the rt2800pci_txdone function into rt2800lib where it can also be used by rt2800usb. rt2800usb needs to overwrite the txdone work handler to a different function. Both rt2800usb as rt2800_txdone need to take into account that IO failures can occur while uploading the URB, which means that when obtaining the new entry the IO status must be checked. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 117 ++++++++++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2800lib.h | 4 ++ drivers/net/wireless/rt2x00/rt2800pci.c | 108 +---------------------------- drivers/net/wireless/rt2x00/rt2800usb.c | 40 ++++++++++- 4 files changed, 162 insertions(+), 107 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 6f1eb5824d2d..827a2580893b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1,4 +1,5 @@ /* + Copyright (C) 2010 Willow Garage Copyright (C) 2010 Ivo van Doorn Copyright (C) 2009 Bartlomiej Zolnierkiewicz Copyright (C) 2009 Gertjan van Wingerde @@ -572,6 +573,122 @@ void rt2800_process_rxwi(struct queue_entry *entry, } EXPORT_SYMBOL_GPL(rt2800_process_rxwi); +void rt2800_txdone(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + struct queue_entry *entry; + __le32 *txwi; + struct txdone_entry_desc txdesc; + u32 word; + u32 reg; + int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; + u16 mcs, real_mcs; + int i; + + /* + * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO + * at most X times and also stop processing once the TX_STA_FIFO_VALID + * flag is not set anymore. + * + * The legacy drivers use X=TX_RING_SIZE but state in a comment + * that the TX_STA_FIFO stack has a size of 16. We stick to our + * tx ring size for now. + */ + for (i = 0; i < TX_ENTRIES; i++) { + rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); + if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) + break; + + wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); + ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); + pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); + + /* + * Skip this entry when it contains an invalid + * queue identication number. + */ + if (pid <= 0 || pid > QID_RX) + continue; + + queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); + if (unlikely(!queue)) + continue; + + /* + * Inside each queue, we process each entry in a chronological + * order. We first check that the queue is not empty. + */ + entry = NULL; + while (!rt2x00queue_empty(queue)) { + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); + if (!test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) + break; + + rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); + } + + if (!entry || rt2x00queue_empty(queue)) + break; + + /* + * Check if we got a match by looking at WCID/ACK/PID + * fields + */ + txwi = rt2800_drv_get_txwi(entry); + + rt2x00_desc_read(txwi, 1, &word); + tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); + tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); + tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); + + if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) + WARNING(rt2x00dev, "invalid TX_STA_FIFO content"); + + /* + * Obtain the status about this packet. + */ + txdesc.flags = 0; + rt2x00_desc_read(txwi, 0, &word); + mcs = rt2x00_get_field32(word, TXWI_W0_MCS); + mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); + real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); + + /* + * Ralink has a retry mechanism using a global fallback + * table. We setup this fallback table to try the immediate + * lower rate for all rates. In the TX_STA_FIFO, the MCS field + * always contains the MCS used for the last transmission, be + * it successful or not. + */ + if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) { + /* + * Transmission succeeded. The number of retries is + * mcs - real_mcs + */ + __set_bit(TXDONE_SUCCESS, &txdesc.flags); + txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); + } else { + /* + * Transmission failed. The number of retries is + * always 7 in this case (for a total number of 8 + * frames sent). + */ + __set_bit(TXDONE_FAILURE, &txdesc.flags); + txdesc.retry = rt2x00dev->long_retry; + } + + /* + * the frame was retried at least once + * -> hw used fallback rates + */ + if (txdesc.retry) + __set_bit(TXDONE_FALLBACK, &txdesc.flags); + + rt2x00lib_txdone(entry, &txdesc); + } +} +EXPORT_SYMBOL_GPL(rt2800_txdone); + void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 8f975180727f..3b572c63382d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -1,4 +1,6 @@ /* + Copyright (C) 2010 Willow Garage + Copyright (C) 2010 Ivo van Doorn Copyright (C) 2009 Bartlomiej Zolnierkiewicz This program is free software; you can redistribute it and/or modify @@ -147,6 +149,8 @@ void rt2800_write_tx_data(struct queue_entry *entry, struct txentry_desc *txdesc); void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); +void rt2800_txdone(struct rt2x00_dev *rt2x00dev); + void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); extern const struct rt2x00debug rt2800_rt2x00debug; diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index f415f6d5f601..4390f2b74b2e 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009 Ivo van Doorn + Copyright (C) 2009 - 2010 Ivo van Doorn Copyright (C) 2009 Alban Browaeys Copyright (C) 2009 Felix Fietkau Copyright (C) 2009 Luis Correia @@ -724,110 +724,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, /* * Interrupt functions. */ -static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - struct queue_entry *entry; - __le32 *txwi; - struct txdone_entry_desc txdesc; - u32 word; - u32 reg; - int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; - u16 mcs, real_mcs; - int i; - - /* - * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO - * at most X times and also stop processing once the TX_STA_FIFO_VALID - * flag is not set anymore. - * - * The legacy drivers use X=TX_RING_SIZE but state in a comment - * that the TX_STA_FIFO stack has a size of 16. We stick to our - * tx ring size for now. - */ - for (i = 0; i < TX_ENTRIES; i++) { - rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); - if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) - break; - - wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); - ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); - pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); - - /* - * Skip this entry when it contains an invalid - * queue identication number. - */ - if (pid <= 0 || pid > QID_RX) - continue; - - queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); - if (unlikely(!queue)) - continue; - - /* - * Inside each queue, we process each entry in a chronological - * order. We first check that the queue is not empty. - */ - if (rt2x00queue_empty(queue)) - continue; - entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - - /* Check if we got a match by looking at WCID/ACK/PID - * fields */ - txwi = (__le32 *) entry->skb->data; - - rt2x00_desc_read(txwi, 1, &word); - tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); - tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); - tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); - - if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) - WARNING(rt2x00dev, "invalid TX_STA_FIFO content\n"); - - /* - * Obtain the status about this packet. - */ - txdesc.flags = 0; - rt2x00_desc_read(txwi, 0, &word); - mcs = rt2x00_get_field32(word, TXWI_W0_MCS); - real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); - - /* - * Ralink has a retry mechanism using a global fallback - * table. We setup this fallback table to try the immediate - * lower rate for all rates. In the TX_STA_FIFO, the MCS field - * always contains the MCS used for the last transmission, be - * it successful or not. - */ - if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) { - /* - * Transmission succeeded. The number of retries is - * mcs - real_mcs - */ - __set_bit(TXDONE_SUCCESS, &txdesc.flags); - txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); - } else { - /* - * Transmission failed. The number of retries is - * always 7 in this case (for a total number of 8 - * frames sent). - */ - __set_bit(TXDONE_FAILURE, &txdesc.flags); - txdesc.retry = 7; - } - - /* - * the frame was retried at least once - * -> hw used fallback rates - */ - if (txdesc.retry) - __set_bit(TXDONE_FALLBACK, &txdesc.flags); - - rt2x00lib_txdone(entry, &txdesc); - } -} - static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) { struct ieee80211_conf conf = { .flags = 0 }; @@ -863,7 +759,7 @@ static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) * 4 - Tx done interrupt. */ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) - rt2800pci_txdone(rt2x00dev); + rt2800_txdone(rt2x00dev); /* * 5 - Auto wakeup interrupt. diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 9084b9a36b57..9ad28be294eb 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1,5 +1,6 @@ /* - Copyright (C) 2009 Ivo van Doorn + Copyright (C) 2010 Willow Garage + Copyright (C) 2009 - 2010 Ivo van Doorn Copyright (C) 2009 Mattias Nissler Copyright (C) 2009 Felix Fietkau Copyright (C) 2009 Xose Vazquez Perez @@ -377,6 +378,38 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry) return length; } +/* + * TX control handlers + */ +static void rt2800usb_work_txdone(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, txdone_work); + struct data_queue *queue; + struct queue_entry *entry; + + rt2800_txdone(rt2x00dev); + + /* + * Process any trailing TX status reports for IO failures, + * we loop until we find the first non-IO error entry. This + * can either be a frame which is free, is being uploaded, + * or has completed the upload but didn't have an entry + * in the TX_STAT_FIFO register yet. + */ + tx_queue_for_each(rt2x00dev, queue) { + while (!rt2x00queue_empty(queue)) { + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); + + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || + !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) + break; + + rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); + } + } +} + /* * RX control handlers */ @@ -513,6 +546,11 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) */ rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; + /* + * Overwrite TX done handler + */ + PREPARE_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone); + return 0; } -- cgit v1.2.3-59-g8ed1b From 0856d9c04a1655612abd96793c1e8b1c1792457e Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Fri, 6 Aug 2010 20:48:27 +0200 Subject: rt2x00: Update comments regarding TXWI and TX_STA_FIFO Add some comments about the TXWI fields and the TX_STA_FIFO register. Especially describe the relationship between the TXWI field PACKETID and the PID field in the TX_STA_FIFO register. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index ed4ebcdde7c9..cf1f16bfcd5e 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1318,7 +1318,25 @@ #define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) /* - * TX_STA_FIFO: TX Result for specific PID status fifo register + * TX_STA_FIFO: TX Result for specific PID status fifo register. + * + * This register is implemented as FIFO with 16 entries in the HW. Each + * register read fetches the next tx result. If the FIFO is full because + * it wasn't read fast enough after the according interrupt (TX_FIFO_STATUS) + * triggered, the hw seems to simply drop further tx results. + * + * VALID: 1: this tx result is valid + * 0: no valid tx result -> driver should stop reading + * PID_TYPE: The PID latched from the PID field in the TXWI, can be used + * to match a frame with its tx result (even though the PID is + * only 4 bits wide). + * TX_SUCCESS: Indicates tx success (1) or failure (0) + * TX_AGGRE: Indicates if the frame was part of an aggregate (1) or not (0) + * TX_ACK_REQUIRED: Indicates if the frame needed to get ack'ed (1) or not (0) + * WCID: The wireless client ID. + * MCS: The tx rate used during the last transmission of this frame, be it + * successful or not. + * PHYMODE: The phymode used for the transmission. */ #define TX_STA_FIFO 0x1718 #define TX_STA_FIFO_VALID FIELD32(0x00000001) @@ -1945,6 +1963,13 @@ struct mac_iveiv_entry { /* * Word1 + * ACK: 0: No Ack needed, 1: Ack needed + * NSEQ: 0: Don't assign hw sequence number, 1: Assign hw sequence number + * BW_WIN_SIZE: BA windows size of the recipient + * WIRELESS_CLI_ID: Client ID for WCID table access + * MPDU_TOTAL_BYTE_COUNT: Length of 802.11 frame + * PACKETID: Will be latched into the TX_STA_FIFO register once the according + * frame was processed. 0: Don't report tx status for this frame. */ #define TXWI_W1_ACK FIELD32(0x00000001) #define TXWI_W1_NSEQ FIELD32(0x00000002) -- cgit v1.2.3-59-g8ed1b From e5ef5bad345f97f1fef7ccdc01a88c298629a5d9 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 6 Aug 2010 20:49:27 +0200 Subject: rt2x00: Remove ieee80211_rx_status from rt2x00_dev rt2x00 was keeping a copy of ieee80211_rx_status embedded into the rt2x00_dev structure. For each RX frame, this structure was copied into the skb->cb where mac80211 would handle it further. However at the moment only the fields current band, and frequency were updated. Whereas the band was already provided directly within the rt2x00_dev structure. Save a memcpy action, and reduce memory a bit, by adding a curr_freq field to rt2x00_dev, and completely remove the ieee80211_rx_status structure from rt2x00_dev. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 6 +----- drivers/net/wireless/rt2x00/rt2x00config.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00dev.c | 16 +++++++++------- drivers/net/wireless/rt2x00/rt61pci.c | 4 ++-- drivers/net/wireless/rt2x00/rt73usb.c | 4 ++-- 6 files changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 827a2580893b..3a150d3a9d9f 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -494,7 +494,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) u8 offset1; u8 offset2; - if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) { + if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0); offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index edfc2b759282..8c65244a847a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -699,6 +699,7 @@ struct rt2x00_dev { struct ieee80211_hw *hw; struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; enum ieee80211_band curr_band; + int curr_freq; /* * If enabled, the debugfs interface structures @@ -850,11 +851,6 @@ struct rt2x00_dev { */ struct ieee80211_low_level_stats low_level_stats; - /* - * RX configuration information. - */ - struct ieee80211_rx_status rx_status; - /* * Scheduled work. * NOTE: intf_work will use ieee80211_iterate_active_interfaces() diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index fb23af40008b..34f34fa7f53a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -201,10 +201,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, rt2x00link_reset_tuner(rt2x00dev, false); rt2x00dev->curr_band = conf->channel->band; + rt2x00dev->curr_freq = conf->channel->center_freq; rt2x00dev->tx_power = conf->power_level; rt2x00dev->short_retry = conf->short_frame_max_tx_count; rt2x00dev->long_retry = conf->long_frame_max_tx_count; - - rt2x00dev->rx_status.band = conf->channel->band; - rt2x00dev->rx_status.freq = conf->channel->center_freq; } diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 6499cc416ca3..e692608bee8b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -464,7 +464,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, { struct rxdone_entry_desc rxdesc; struct sk_buff *skb; - struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; + struct ieee80211_rx_status *rx_status; unsigned int header_length; int rate_idx; @@ -535,19 +535,21 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, */ rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); rt2x00debug_update_crypto(rt2x00dev, &rxdesc); + rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); + /* + * Initialize RX status information, and send frame + * to mac80211. + */ + rx_status = IEEE80211_SKB_RXCB(entry->skb); rx_status->mactime = rxdesc.timestamp; + rx_status->band = rt2x00dev->curr_band; + rx_status->freq = rt2x00dev->curr_freq; rx_status->rate_idx = rate_idx; rx_status->signal = rxdesc.rssi; rx_status->flag = rxdesc.flags; rx_status->antenna = rt2x00dev->link.ant.active.rx; - /* - * Send frame to mac80211 & debugfs. - * mac80211 will clean up the skb structure. - */ - rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); - memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status)); ieee80211_rx_ni(rt2x00dev->hw, entry->skb); /* diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index dc6f3ebb8376..cff503faac65 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1050,7 +1050,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, /* * Determine r17 bounds. */ - if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { low_bound = 0x28; up_bound = 0x48; if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { @@ -1972,7 +1972,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return 0; } - if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { if (lna == 3 || lna == 2) offset += 10; } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index aa9de18fd410..c65529678fbd 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -929,7 +929,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, /* * Determine r17 bounds. */ - if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { low_bound = 0x28; up_bound = 0x48; @@ -1597,7 +1597,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return 0; } - if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { if (lna == 3 || lna == 2) offset += 10; -- cgit v1.2.3-59-g8ed1b From 5cddea816eec8b5f6ab76d3fafcbb1533c8c2b9d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 7 Aug 2010 21:13:57 -0500 Subject: libertas: [usb] use new firmware locations Look for firmware where the linux-firmware tree actually puts it, but fall back to original firmware name & location when the new location doesn't exist. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_usb.c | 60 ++++++++++++++++++++++++++++++---- drivers/net/wireless/libertas/if_usb.h | 1 + 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 07ece9d26c63..238de10a4b57 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -26,15 +26,25 @@ #define MESSAGE_HEADER_LEN 4 -static char *lbs_fw_name = "usb8388.bin"; +static char *lbs_fw_name = NULL; module_param_named(fw_name, lbs_fw_name, charp, 0644); +MODULE_FIRMWARE("libertas/usb8388_v9.bin"); +MODULE_FIRMWARE("libertas/usb8388_v5.bin"); +MODULE_FIRMWARE("libertas/usb8388.bin"); +MODULE_FIRMWARE("libertas/usb8682.bin"); MODULE_FIRMWARE("usb8388.bin"); +enum { + MODEL_UNKNOWN = 0x0, + MODEL_8388 = 0x1, + MODEL_8682 = 0x2 +}; + static struct usb_device_id if_usb_table[] = { /* Enter the device signature inside */ - { USB_DEVICE(0x1286, 0x2001) }, - { USB_DEVICE(0x05a3, 0x8388) }, + { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 }, + { USB_DEVICE(0x05a3, 0x8388), .driver_info = MODEL_8388 }, {} /* Terminating entry */ }; @@ -66,6 +76,8 @@ static ssize_t if_usb_firmware_set(struct device *dev, struct if_usb_card *cardp = priv->card; int ret; + BUG_ON(buf == NULL); + ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW); if (ret == 0) return count; @@ -91,6 +103,8 @@ static ssize_t if_usb_boot2_set(struct device *dev, struct if_usb_card *cardp = priv->card; int ret; + BUG_ON(buf == NULL); + ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2); if (ret == 0) return count; @@ -244,6 +258,7 @@ static int if_usb_probe(struct usb_interface *intf, init_waitqueue_head(&cardp->fw_wq); cardp->udev = udev; + cardp->model = (uint32_t) id->driver_info; iface_desc = intf->cur_altsetting; lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" @@ -921,6 +936,38 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp, return ret; } +/* table of firmware file names */ +static const struct { + u32 model; + const char *fwname; +} fw_table[] = { + { MODEL_8388, "libertas/usb8388_v9.bin" }, + { MODEL_8388, "libertas/usb8388_v5.bin" }, + { MODEL_8388, "libertas/usb8388.bin" }, + { MODEL_8388, "usb8388.bin" }, + { MODEL_8682, "libertas/usb8682.bin" } +}; + +static int get_fw(struct if_usb_card *cardp, const char *fwname) +{ + int i; + + /* Try user-specified firmware first */ + if (fwname) + return request_firmware(&cardp->fw, fwname, &cardp->udev->dev); + + /* Otherwise search for firmware to use */ + for (i = 0; i < ARRAY_SIZE(fw_table); i++) { + if (fw_table[i].model != cardp->model) + continue; + if (request_firmware(&cardp->fw, fw_table[i].fwname, + &cardp->udev->dev) == 0) + return 0; + } + + return -ENOENT; +} + static int __if_usb_prog_firmware(struct if_usb_card *cardp, const char *fwname, int cmd) { @@ -930,10 +977,9 @@ static int __if_usb_prog_firmware(struct if_usb_card *cardp, lbs_deb_enter(LBS_DEB_USB); - ret = request_firmware(&cardp->fw, fwname, &cardp->udev->dev); - if (ret < 0) { - lbs_pr_err("request_firmware() failed with %#x\n", ret); - lbs_pr_err("firmware %s not found\n", fwname); + ret = get_fw(cardp, fwname); + if (ret) { + lbs_pr_err("failed to find firmware (%d)\n", ret); goto done; } diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index 5ba0aee0eb2f..d819e7e3c9aa 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h @@ -43,6 +43,7 @@ struct bootcmdresp /** USB card description structure*/ struct if_usb_card { struct usb_device *udev; + uint32_t model; /* MODEL_* */ struct urb *rx_urb, *tx_urb; struct lbs_private *priv; -- cgit v1.2.3-59-g8ed1b From 72f7a6671e8a1433467757e94c883d39eeccd4ba Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 7 Aug 2010 21:14:33 -0500 Subject: libertas: add two-stage firmware request helper SDIO, GSPI, and CS all use 2-stage firmware and the loading process and logic should be the same. Allow module parameters to override the automatic firmware choice, otherwise just walk the bus driver's firmware table and pick out the first firmware pair that exists for the given model. Some special care is taken to allow overriding of just the helper or the main firmware, but let the other of the pair be chosen automatically. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/decl.h | 13 +++++ drivers/net/wireless/libertas/main.c | 105 +++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 1d141fefd767..2ae752d10065 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -8,7 +8,14 @@ #define _LBS_DECL_H_ #include +#include +/* Should be terminated by a NULL entry */ +struct lbs_fw_table { + int model; + const char *helper; + const char *fwname; +}; struct lbs_private; struct sk_buff; @@ -53,4 +60,10 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv); u32 lbs_fw_index_to_data_rate(u8 index); u8 lbs_data_rate_to_fw_index(u32 rate); +int lbs_get_firmware(struct device *dev, const char *user_helper, + const char *user_mainfw, u32 card_model, + const struct lbs_fw_table *fw_table, + const struct firmware **helper, + const struct firmware **mainfw); + #endif diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 24958a86747b..47ce5a6ba120 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1047,6 +1047,111 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) } EXPORT_SYMBOL_GPL(lbs_notify_command_response); +/** + * @brief Retrieves two-stage firmware + * + * @param dev A pointer to device structure + * @param user_helper User-defined helper firmware file + * @param user_mainfw User-defined main firmware file + * @param card_model Bus-specific card model ID used to filter firmware table + * elements + * @param fw_table Table of firmware file names and device model numbers + * terminated by an entry with a NULL helper name + * @param helper On success, the helper firmware; caller must free + * @param mainfw On success, the main firmware; caller must free + * + * @return 0 on success, non-zero on failure + */ +int lbs_get_firmware(struct device *dev, const char *user_helper, + const char *user_mainfw, u32 card_model, + const struct lbs_fw_table *fw_table, + const struct firmware **helper, + const struct firmware **mainfw) +{ + const struct lbs_fw_table *iter; + int ret; + + BUG_ON(helper == NULL); + BUG_ON(mainfw == NULL); + + /* Try user-specified firmware first */ + if (user_helper) { + ret = request_firmware(helper, user_helper, dev); + if (ret) { + lbs_pr_err("couldn't find helper firmware %s", + user_helper); + goto fail; + } + } + if (user_mainfw) { + ret = request_firmware(mainfw, user_mainfw, dev); + if (ret) { + lbs_pr_err("couldn't find main firmware %s", + user_mainfw); + goto fail; + } + } + + if (*helper && *mainfw) + return 0; + + /* Otherwise search for firmware to use. If neither the helper or + * the main firmware were specified by the user, then we need to + * make sure that found helper & main are from the same entry in + * fw_table. + */ + iter = fw_table; + while (iter && iter->helper) { + if (iter->model != card_model) + goto next; + + if (*helper == NULL) { + ret = request_firmware(helper, iter->helper, dev); + if (ret) + goto next; + + /* If the device has one-stage firmware (ie cf8305) and + * we've got it then we don't need to bother with the + * main firmware. + */ + if (iter->fwname == NULL) + return 0; + } + + if (*mainfw == NULL) { + ret = request_firmware(mainfw, iter->fwname, dev); + if (ret && !user_helper) { + /* Clear the helper if it wasn't user-specified + * and the main firmware load failed, to ensure + * we don't have mismatched firmware pairs. + */ + release_firmware(*helper); + *helper = NULL; + } + } + + if (*helper && *mainfw) + return 0; + + next: + iter++; + } + + fail: + /* Failed */ + if (*helper) { + release_firmware(*helper); + *helper = NULL; + } + if (*mainfw) { + release_firmware(*mainfw); + *mainfw = NULL; + } + + return -ENOENT; +} +EXPORT_SYMBOL_GPL(lbs_get_firmware); + static int __init lbs_init_module(void) { lbs_deb_enter(LBS_DEB_MAIN); -- cgit v1.2.3-59-g8ed1b From 82222e9ba75298e5bcd89803b6a11e2d7dfae70e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 7 Aug 2010 21:15:19 -0500 Subject: libertas: [cs] use common firmware request helper and new firmware locations linux-firmware puts libertas firmware in /libertas. Fix the driver to look there first, but fall back to the old firmware names if the new ones don't exist. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_cs.c | 130 +++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 56 deletions(-) diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 08e4e3908003..a6fd70404c3d 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -49,7 +49,6 @@ MODULE_AUTHOR("Holger Schurig "); MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("libertas_cs_helper.fw"); @@ -62,9 +61,34 @@ struct if_cs_card { struct lbs_private *priv; void __iomem *iobase; bool align_regs; + u32 model; }; +enum { + MODEL_UNKNOWN = 0x00, + MODEL_8305 = 0x01, + MODEL_8381 = 0x02, + MODEL_8385 = 0x03 +}; + +static const struct lbs_fw_table fw_table[] = { + { MODEL_8305, "libertas/cf8305.bin", NULL }, + { MODEL_8305, "libertas_cs_helper.fw", NULL }, + { MODEL_8381, "libertas/cf8381_helper.bin", "libertas/cf8381.bin" }, + { MODEL_8381, "libertas_cs_helper.fw", "libertas_cs.fw" }, + { MODEL_8385, "libertas/cf8385_helper.bin", "libertas/cf8385.bin" }, + { MODEL_8385, "libertas_cs_helper.fw", "libertas_cs.fw" }, + { 0, NULL, NULL } +}; +MODULE_FIRMWARE("libertas/cf8305.bin"); +MODULE_FIRMWARE("libertas/cf8381_helper.bin"); +MODULE_FIRMWARE("libertas/cf8381.bin"); +MODULE_FIRMWARE("libertas/cf8385_helper.bin"); +MODULE_FIRMWARE("libertas/cf8385.bin"); +MODULE_FIRMWARE("libertas_cs_helper.fw"); +MODULE_FIRMWARE("libertas_cs.fw"); + /********************************************************************/ /* Hardware access */ @@ -290,22 +314,19 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r #define CF8385_MANFID 0x02df #define CF8385_CARDID 0x8103 -static inline int if_cs_hw_is_cf8305(struct pcmcia_device *p_dev) -{ - return (p_dev->manf_id == CF8305_MANFID && - p_dev->card_id == CF8305_CARDID); -} - -static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev) -{ - return (p_dev->manf_id == CF8381_MANFID && - p_dev->card_id == CF8381_CARDID); -} - -static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev) +/* FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when + * that gets fixed. Currently there's no way to access it from the probe hook. + */ +static inline u32 get_model(u16 manf_id, u16 card_id) { - return (p_dev->manf_id == CF8385_MANFID && - p_dev->card_id == CF8385_CARDID); + /* NOTE: keep in sync with if_cs_ids */ + if (manf_id == CF8305_MANFID && card_id == CF8305_CARDID) + return MODEL_8305; + else if (manf_id == CF8381_MANFID && card_id == CF8381_CARDID) + return MODEL_8381; + else if (manf_id == CF8385_MANFID && card_id == CF8385_CARDID) + return MODEL_8385; + return MODEL_UNKNOWN; } /********************************************************************/ @@ -559,12 +580,11 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) * * Return 0 on success */ -static int if_cs_prog_helper(struct if_cs_card *card) +static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw) { int ret = 0; int sent = 0; u8 scratch; - const struct firmware *fw; lbs_deb_enter(LBS_DEB_CS); @@ -590,14 +610,6 @@ static int if_cs_prog_helper(struct if_cs_card *card) goto done; } - /* TODO: make firmware file configurable */ - ret = request_firmware(&fw, "libertas_cs_helper.fw", - &card->p_dev->dev); - if (ret) { - lbs_pr_err("can't load helper firmware\n"); - ret = -ENODEV; - goto done; - } lbs_deb_cs("helper size %td\n", fw->size); /* "Set the 5 bytes of the helper image to 0" */ @@ -636,7 +648,7 @@ static int if_cs_prog_helper(struct if_cs_card *card) if (ret < 0) { lbs_pr_err("can't download helper at 0x%x, ret %d\n", sent, ret); - goto err_release; + goto done; } if (count == 0) @@ -645,17 +657,14 @@ static int if_cs_prog_helper(struct if_cs_card *card) sent += count; } -err_release: - release_firmware(fw); done: lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); return ret; } -static int if_cs_prog_real(struct if_cs_card *card) +static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw) { - const struct firmware *fw; int ret = 0; int retry = 0; int len = 0; @@ -663,21 +672,13 @@ static int if_cs_prog_real(struct if_cs_card *card) lbs_deb_enter(LBS_DEB_CS); - /* TODO: make firmware file configurable */ - ret = request_firmware(&fw, "libertas_cs.fw", - &card->p_dev->dev); - if (ret) { - lbs_pr_err("can't load firmware\n"); - ret = -ENODEV; - goto done; - } lbs_deb_cs("fw size %td\n", fw->size); ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, IF_CS_SQ_HELPER_OK); if (ret < 0) { lbs_pr_err("helper firmware doesn't answer\n"); - goto err_release; + goto done; } for (sent = 0; sent < fw->size; sent += len) { @@ -692,7 +693,7 @@ static int if_cs_prog_real(struct if_cs_card *card) if (retry > 20) { lbs_pr_err("could not download firmware\n"); ret = -ENODEV; - goto err_release; + goto done; } if (retry) { sent -= len; @@ -711,7 +712,7 @@ static int if_cs_prog_real(struct if_cs_card *card) IF_CS_BIT_COMMAND); if (ret < 0) { lbs_pr_err("can't download firmware at 0x%x\n", sent); - goto err_release; + goto done; } } @@ -719,9 +720,6 @@ static int if_cs_prog_real(struct if_cs_card *card) if (ret < 0) lbs_pr_err("firmware download failed\n"); -err_release: - release_firmware(fw); - done: lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); return ret; @@ -825,6 +823,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) unsigned int prod_id; struct lbs_private *priv; struct if_cs_card *card; + const struct firmware *helper = NULL; + const struct firmware *mainfw = NULL; lbs_deb_enter(LBS_DEB_CS); @@ -844,7 +844,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev) goto out1; } - /* * Allocate an interrupt line. Note that this does not assign * a handler to the interrupt, unless the 'Handler' member of @@ -883,34 +882,47 @@ static int if_cs_probe(struct pcmcia_device *p_dev) */ card->align_regs = 0; + card->model = get_model(p_dev->manf_id, p_dev->card_id); + if (card->model == MODEL_UNKNOWN) { + lbs_pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n", + p_dev->manf_id, p_dev->card_id); + goto out2; + } + /* Check if we have a current silicon */ prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); - if (if_cs_hw_is_cf8305(p_dev)) { + if (card->model == MODEL_8305) { card->align_regs = 1; if (prod_id < IF_CS_CF8305_B1_REV) { - lbs_pr_err("old chips like 8305 rev B3 " - "aren't supported\n"); + lbs_pr_err("8305 rev B0 and older are not supported\n"); ret = -ENODEV; goto out2; } } - if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) { - lbs_pr_err("old chips like 8381 rev B3 aren't supported\n"); + if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) { + lbs_pr_err("8381 rev B2 and older are not supported\n"); ret = -ENODEV; goto out2; } - if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) { - lbs_pr_err("old chips like 8385 rev B1 aren't supported\n"); + if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) { + lbs_pr_err("8385 rev B0 and older are not supported\n"); ret = -ENODEV; goto out2; } + ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model, + &fw_table[0], &helper, &mainfw); + if (ret) { + lbs_pr_err("failed to find firmware (%d)\n", ret); + goto out2; + } + /* Load the firmware early, before calling into libertas.ko */ - ret = if_cs_prog_helper(card); - if (ret == 0 && !if_cs_hw_is_cf8305(p_dev)) - ret = if_cs_prog_real(card); + ret = if_cs_prog_helper(card, helper); + if (ret == 0 && (card->model != MODEL_8305)) + ret = if_cs_prog_real(card, mainfw); if (ret) goto out2; @@ -959,6 +971,11 @@ out2: out1: pcmcia_disable_device(p_dev); out: + if (helper) + release_firmware(helper); + if (mainfw) + release_firmware(mainfw); + lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); return ret; } @@ -995,6 +1012,7 @@ static struct pcmcia_device_id if_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), + /* NOTE: keep in sync with get_model() */ PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); -- cgit v1.2.3-59-g8ed1b From 3d32a58b87cd251b50842f93b87d5458061c0cfc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 7 Aug 2010 21:15:52 -0500 Subject: libertas: [sdio] use common firmware request helper and new firmware locations linux-firmware puts libertas firmware in /libertas. Fix the driver to look there first, but fall back to the old firmware names if the new ones don't exist. Add preference for newer firmware versions too. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 143 ++++++++++++++------------------ drivers/net/wireless/libertas/if_sdio.h | 4 - 2 files changed, 60 insertions(+), 87 deletions(-) diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 6e71346a7550..024e5ca7b7f3 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -76,36 +76,32 @@ static const struct sdio_device_id if_sdio_ids[] = { MODULE_DEVICE_TABLE(sdio, if_sdio_ids); -struct if_sdio_model { - int model; - const char *helper; - const char *firmware; -}; - -static struct if_sdio_model if_sdio_models[] = { - { - /* 8385 */ - .model = IF_SDIO_MODEL_8385, - .helper = "sd8385_helper.bin", - .firmware = "sd8385.bin", - }, - { - /* 8686 */ - .model = IF_SDIO_MODEL_8686, - .helper = "sd8686_helper.bin", - .firmware = "sd8686.bin", - }, - { - /* 8688 */ - .model = IF_SDIO_MODEL_8688, - .helper = "sd8688_helper.bin", - .firmware = "sd8688.bin", - }, +#define MODEL_8385 0x04 +#define MODEL_8686 0x0b +#define MODEL_8688 0x10 + +static const struct lbs_fw_table fw_table[] = { + { MODEL_8385, "libertas/sd8385_helper.bin", "libertas/sd8385.bin" }, + { MODEL_8385, "sd8385_helper.bin", "sd8385.bin" }, + { MODEL_8686, "libertas/sd8686_v9_helper.bin", "libertas/sd8686_v9.bin" }, + { MODEL_8686, "libertas/sd8686_v8_helper.bin", "libertas/sd8686_v8.bin" }, + { MODEL_8686, "sd8686_helper.bin", "sd8686.bin" }, + { MODEL_8688, "libertas/sd8688_helper.bin", "libertas/sd8688.bin" }, + { MODEL_8688, "sd8688_helper.bin", "sd8688.bin" }, + { 0, NULL, NULL } }; +MODULE_FIRMWARE("libertas/sd8385_helper.bin"); +MODULE_FIRMWARE("libertas/sd8385.bin"); MODULE_FIRMWARE("sd8385_helper.bin"); MODULE_FIRMWARE("sd8385.bin"); +MODULE_FIRMWARE("libertas/sd8686_v9_helper.bin"); +MODULE_FIRMWARE("libertas/sd8686_v9.bin"); +MODULE_FIRMWARE("libertas/sd8686_v8_helper.bin"); +MODULE_FIRMWARE("libertas/sd8686_v8.bin"); MODULE_FIRMWARE("sd8686_helper.bin"); MODULE_FIRMWARE("sd8686.bin"); +MODULE_FIRMWARE("libertas/sd8688_helper.bin"); +MODULE_FIRMWARE("libertas/sd8688.bin"); MODULE_FIRMWARE("sd8688_helper.bin"); MODULE_FIRMWARE("sd8688.bin"); @@ -185,11 +181,11 @@ static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err) u16 rx_len; switch (card->model) { - case IF_SDIO_MODEL_8385: - case IF_SDIO_MODEL_8686: + case MODEL_8385: + case MODEL_8686: rx_len = if_sdio_read_scratch(card, &ret); break; - case IF_SDIO_MODEL_8688: + case MODEL_8688: default: /* for newer chipsets */ rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret); if (!ret) @@ -286,7 +282,7 @@ static int if_sdio_handle_event(struct if_sdio_card *card, lbs_deb_enter(LBS_DEB_SDIO); - if (card->model == IF_SDIO_MODEL_8385) { + if (card->model == MODEL_8385) { event = sdio_readb(card->func, IF_SDIO_EVENT, &ret); if (ret) goto out; @@ -464,10 +460,10 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY) -static int if_sdio_prog_helper(struct if_sdio_card *card) +static int if_sdio_prog_helper(struct if_sdio_card *card, + const struct firmware *fw) { int ret; - const struct firmware *fw; unsigned long timeout; u8 *chunk_buffer; u32 chunk_size; @@ -476,16 +472,10 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) lbs_deb_enter(LBS_DEB_SDIO); - ret = request_firmware(&fw, card->helper, &card->func->dev); - if (ret) { - lbs_pr_err("can't load helper firmware\n"); - goto out; - } - chunk_buffer = kzalloc(64, GFP_KERNEL); if (!chunk_buffer) { ret = -ENOMEM; - goto release_fw; + goto out; } sdio_claim_host(card->func); @@ -560,22 +550,19 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) release: sdio_release_host(card->func); kfree(chunk_buffer); -release_fw: - release_firmware(fw); out: if (ret) lbs_pr_err("failed to load helper firmware\n"); lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - return ret; } -static int if_sdio_prog_real(struct if_sdio_card *card) +static int if_sdio_prog_real(struct if_sdio_card *card, + const struct firmware *fw) { int ret; - const struct firmware *fw; unsigned long timeout; u8 *chunk_buffer; u32 chunk_size; @@ -584,16 +571,10 @@ static int if_sdio_prog_real(struct if_sdio_card *card) lbs_deb_enter(LBS_DEB_SDIO); - ret = request_firmware(&fw, card->firmware, &card->func->dev); - if (ret) { - lbs_pr_err("can't load firmware\n"); - goto out; - } - chunk_buffer = kzalloc(512, GFP_KERNEL); if (!chunk_buffer) { ret = -ENOMEM; - goto release_fw; + goto out; } sdio_claim_host(card->func); @@ -683,15 +664,12 @@ static int if_sdio_prog_real(struct if_sdio_card *card) release: sdio_release_host(card->func); kfree(chunk_buffer); -release_fw: - release_firmware(fw); out: if (ret) lbs_pr_err("failed to load firmware\n"); lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - return ret; } @@ -699,6 +677,8 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) { int ret; u16 scratch; + const struct firmware *helper = NULL; + const struct firmware *mainfw = NULL; lbs_deb_enter(LBS_DEB_SDIO); @@ -716,11 +696,18 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) goto success; } - ret = if_sdio_prog_helper(card); + ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, + card->model, &fw_table[0], &helper, &mainfw); + if (ret) { + lbs_pr_err("failed to find firmware (%d)\n", ret); + goto out; + } + + ret = if_sdio_prog_helper(card, helper); if (ret) goto out; - ret = if_sdio_prog_real(card); + ret = if_sdio_prog_real(card, mainfw); if (ret) goto out; @@ -731,8 +718,12 @@ success: ret = 0; out: - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); + if (helper) + release_firmware(helper); + if (mainfw) + release_firmware(mainfw); + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); return ret; } @@ -936,7 +927,7 @@ static int if_sdio_probe(struct sdio_func *func, "ID: %x", &model) == 1) break; if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { - model = IF_SDIO_MODEL_8385; + model = MODEL_8385; break; } } @@ -954,13 +945,13 @@ static int if_sdio_probe(struct sdio_func *func, card->model = model; switch (card->model) { - case IF_SDIO_MODEL_8385: + case MODEL_8385: card->scratch_reg = IF_SDIO_SCRATCH_OLD; break; - case IF_SDIO_MODEL_8686: + case MODEL_8686: card->scratch_reg = IF_SDIO_SCRATCH; break; - case IF_SDIO_MODEL_8688: + case MODEL_8688: default: /* for newer chipsets */ card->scratch_reg = IF_SDIO_FW_STATUS; break; @@ -970,31 +961,17 @@ static int if_sdio_probe(struct sdio_func *func, card->workqueue = create_workqueue("libertas_sdio"); INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); - for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) { - if (card->model == if_sdio_models[i].model) + /* Check if we support this card */ + for (i = 0; i < ARRAY_SIZE(fw_table); i++) { + if (card->model == fw_table[i].model) break; } - - if (i == ARRAY_SIZE(if_sdio_models)) { + if (i == ARRAY_SIZE(fw_table)) { lbs_pr_err("unknown card model 0x%x\n", card->model); ret = -ENODEV; goto free; } - card->helper = if_sdio_models[i].helper; - card->firmware = if_sdio_models[i].firmware; - - if (lbs_helper_name) { - lbs_deb_sdio("overriding helper firmware: %s\n", - lbs_helper_name); - card->helper = lbs_helper_name; - } - - if (lbs_fw_name) { - lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); - card->firmware = lbs_fw_name; - } - sdio_claim_host(func); ret = sdio_enable_func(func); @@ -1008,7 +985,7 @@ static int if_sdio_probe(struct sdio_func *func, /* For 1-bit transfers to the 8686 model, we need to enable the * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 * bit to allow access to non-vendor registers. */ - if ((card->model == IF_SDIO_MODEL_8686) && + if ((card->model == MODEL_8686) && (host->caps & MMC_CAP_SDIO_IRQ) && (host->ios.bus_width == MMC_BUS_WIDTH_1)) { u8 reg; @@ -1071,8 +1048,8 @@ static int if_sdio_probe(struct sdio_func *func, * Get rx_unit if the chip is SD8688 or newer. * SD8385 & SD8686 do not have rx_unit. */ - if ((card->model != IF_SDIO_MODEL_8385) - && (card->model != IF_SDIO_MODEL_8686)) + if ((card->model != MODEL_8385) + && (card->model != MODEL_8686)) card->rx_unit = if_sdio_read_rx_unit(card); else card->rx_unit = 0; @@ -1088,7 +1065,7 @@ static int if_sdio_probe(struct sdio_func *func, /* * FUNC_INIT is required for SD8688 WLAN/BT multiple functions */ - if (card->model == IF_SDIO_MODEL_8688) { + if (card->model == MODEL_8688) { struct cmd_header cmd; memset(&cmd, 0, sizeof(cmd)); @@ -1141,7 +1118,7 @@ static void if_sdio_remove(struct sdio_func *func) card = sdio_get_drvdata(func); - if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) { + if (user_rmmod && (card->model == MODEL_8688)) { /* * FUNC_SHUTDOWN is required for SD8688 WLAN/BT * multiple functions diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h index 12179c1dc9c9..62fda3592f67 100644 --- a/drivers/net/wireless/libertas/if_sdio.h +++ b/drivers/net/wireless/libertas/if_sdio.h @@ -12,10 +12,6 @@ #ifndef _LBS_IF_SDIO_H #define _LBS_IF_SDIO_H -#define IF_SDIO_MODEL_8385 0x04 -#define IF_SDIO_MODEL_8686 0x0b -#define IF_SDIO_MODEL_8688 0x10 - #define IF_SDIO_IOPORT 0x00 #define IF_SDIO_H_INT_MASK 0x04 -- cgit v1.2.3-59-g8ed1b From 915a824e30c503157c38115eb6a85f60bb653738 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 7 Aug 2010 21:16:30 -0500 Subject: libertas: [spi] use common firmware request helper and new firmware locations linux-firmware puts libertas firmware in /libertas. Fix the driver to look there first, but fall back to the old firmware names if the new ones don't exist. Add preference for newer firmware versions too. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_spi.c | 144 ++++++++++++++++----------------- drivers/net/wireless/libertas/if_spi.h | 5 -- 2 files changed, 69 insertions(+), 80 deletions(-) diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 3965c6cf504a..79bcb4e5d2ca 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -39,9 +39,6 @@ struct if_spi_card { struct lbs_private *priv; struct libertas_spi_platform_data *pdata; - char helper_fw_name[IF_SPI_FW_NAME_MAX]; - char main_fw_name[IF_SPI_FW_NAME_MAX]; - /* The card ID and card revision, as reported by the hardware. */ u16 card_id; u8 card_rev; @@ -70,10 +67,28 @@ static void free_if_spi_card(struct if_spi_card *card) kfree(card); } -static struct chip_ident chip_id_to_device_name[] = { - { .chip_id = 0x04, .name = 8385 }, - { .chip_id = 0x0b, .name = 8686 }, +#define MODEL_8385 0x04 +#define MODEL_8686 0x0b +#define MODEL_8688 0x10 + +static const struct lbs_fw_table fw_table[] = { + { MODEL_8385, "libertas/gspi8385_helper.bin", "libertas/gspi8385.bin" }, + { MODEL_8385, "libertas/gspi8385_hlp.bin", "libertas/gspi8385.bin" }, + { MODEL_8686, "libertas/gspi8686_v9_helper.bin", "libertas/gspi8686_v9.bin" }, + { MODEL_8686, "libertas/gspi8686_hlp.bin", "libertas/gspi8686.bin" }, + { MODEL_8688, "libertas/gspi8688_helper.bin", "libertas/gspi8688.bin" }, + { 0, NULL, NULL } }; +MODULE_FIRMWARE("libertas/gspi8385_helper.bin"); +MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); +MODULE_FIRMWARE("libertas/gspi8385.bin"); +MODULE_FIRMWARE("libertas/gspi8686_v9_helper.bin"); +MODULE_FIRMWARE("libertas/gspi8686_v9.bin"); +MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); +MODULE_FIRMWARE("libertas/gspi8686.bin"); +MODULE_FIRMWARE("libertas/gspi8688_helper.bin"); +MODULE_FIRMWARE("libertas/gspi8688.bin"); + /* * SPI Interface Unit Routines @@ -399,26 +414,20 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes) * Firmware Loading */ -static int if_spi_prog_helper_firmware(struct if_spi_card *card) +static int if_spi_prog_helper_firmware(struct if_spi_card *card, + const struct firmware *firmware) { int err = 0; - const struct firmware *firmware = NULL; int bytes_remaining; const u8 *fw; u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; - struct spi_device *spi = card->spi; lbs_deb_enter(LBS_DEB_SPI); err = spu_set_interrupt_mode(card, 1, 0); if (err) goto out; - /* Get helper firmware image */ - err = request_firmware(&firmware, card->helper_fw_name, &spi->dev); - if (err) { - lbs_pr_err("request_firmware failed with err = %d\n", err); - goto out; - } + bytes_remaining = firmware->size; fw = firmware->data; @@ -429,13 +438,13 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, HELPER_FW_LOAD_CHUNK_SZ); if (err) - goto release_firmware; + goto out; err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, IF_SPI_HIST_CMD_DOWNLOAD_RDY, IF_SPI_HIST_CMD_DOWNLOAD_RDY); if (err) - goto release_firmware; + goto out; /* Feed the data into the command read/write port reg * in chunks of 64 bytes */ @@ -446,16 +455,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, temp, HELPER_FW_LOAD_CHUNK_SZ); if (err) - goto release_firmware; + goto out; /* Interrupt the boot code */ err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); if (err) - goto release_firmware; + goto out; err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, IF_SPI_CIC_CMD_DOWNLOAD_OVER); if (err) - goto release_firmware; + goto out; bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; fw += HELPER_FW_LOAD_CHUNK_SZ; } @@ -465,18 +474,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) * bootloader. This completes the helper download. */ err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); if (err) - goto release_firmware; + goto out; err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); if (err) - goto release_firmware; + goto out; err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, IF_SPI_CIC_CMD_DOWNLOAD_OVER); - goto release_firmware; + goto out; lbs_deb_spi("waiting for helper to boot...\n"); -release_firmware: - release_firmware(firmware); out: if (err) lbs_pr_err("failed to load helper firmware (err=%d)\n", err); @@ -523,13 +530,12 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, return len; } -static int if_spi_prog_main_firmware(struct if_spi_card *card) +static int if_spi_prog_main_firmware(struct if_spi_card *card, + const struct firmware *firmware) { int len, prev_len; int bytes, crc_err = 0, err = 0; - const struct firmware *firmware = NULL; const u8 *fw; - struct spi_device *spi = card->spi; u16 num_crc_errs; lbs_deb_enter(LBS_DEB_SPI); @@ -538,19 +544,11 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) if (err) goto out; - /* Get firmware image */ - err = request_firmware(&firmware, card->main_fw_name, &spi->dev); - if (err) { - lbs_pr_err("%s: can't get firmware '%s' from kernel. " - "err = %d\n", __func__, card->main_fw_name, err); - goto out; - } - err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); if (err) { lbs_pr_err("%s: timed out waiting for initial " "scratch reg = 0\n", __func__); - goto release_firmware; + goto out; } num_crc_errs = 0; @@ -560,7 +558,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { if (len < 0) { err = len; - goto release_firmware; + goto out; } if (bytes < 0) { /* If there are no more bytes left, we would normally @@ -575,7 +573,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) lbs_pr_err("Too many CRC errors encountered " "in firmware load.\n"); err = -EIO; - goto release_firmware; + goto out; } } else { /* Previous transfer succeeded. Advance counters. */ @@ -590,15 +588,15 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); if (err) - goto release_firmware; + goto out; err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, card->cmd_buffer, len); if (err) - goto release_firmware; + goto out; err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , IF_SPI_CIC_CMD_DOWNLOAD_OVER); if (err) - goto release_firmware; + goto out; prev_len = len; } if (bytes > prev_len) { @@ -611,12 +609,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) SUCCESSFUL_FW_DOWNLOAD_MAGIC); if (err) { lbs_pr_err("failed to confirm the firmware download\n"); - goto release_firmware; + goto out; } -release_firmware: - release_firmware(firmware); - out: if (err) lbs_pr_err("failed to load firmware (err=%d)\n", err); @@ -888,37 +883,16 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) * SPI callbacks */ -static int if_spi_calculate_fw_names(u16 card_id, - char *helper_fw, char *main_fw) -{ - int i; - for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) { - if (card_id == chip_id_to_device_name[i].chip_id) - break; - } - if (i == ARRAY_SIZE(chip_id_to_device_name)) { - lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id); - return -EAFNOSUPPORT; - } - snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin", - chip_id_to_device_name[i].name); - snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin", - chip_id_to_device_name[i].name); - return 0; -} -MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); -MODULE_FIRMWARE("libertas/gspi8385.bin"); -MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); -MODULE_FIRMWARE("libertas/gspi8686.bin"); - static int __devinit if_spi_probe(struct spi_device *spi) { struct if_spi_card *card; struct lbs_private *priv = NULL; struct libertas_spi_platform_data *pdata = spi->dev.platform_data; - int err = 0; + int err = 0, i; u32 scratch; struct sched_param param = { .sched_priority = 1 }; + const struct firmware *helper = NULL; + const struct firmware *mainfw = NULL; lbs_deb_enter(LBS_DEB_SPI); @@ -963,10 +937,25 @@ static int __devinit if_spi_probe(struct spi_device *spi) lbs_deb_spi("Firmware is already loaded for " "Marvell WLAN 802.11 adapter\n"); else { - err = if_spi_calculate_fw_names(card->card_id, - card->helper_fw_name, card->main_fw_name); - if (err) + /* Check if we support this card */ + for (i = 0; i < ARRAY_SIZE(fw_table); i++) { + if (card->card_id == fw_table[i].model) + break; + } + if (i == ARRAY_SIZE(fw_table)) { + lbs_pr_err("Unsupported chip_id: 0x%02x\n", + card->card_id); + err = -ENODEV; goto free_card; + } + + err = lbs_get_firmware(&card->spi->dev, NULL, NULL, + card->card_id, &fw_table[0], &helper, + &mainfw); + if (err) { + lbs_pr_err("failed to find firmware (%d)\n", err); + goto free_card; + } lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " "(chip_id = 0x%04x, chip_rev = 0x%02x) " @@ -975,10 +964,10 @@ static int __devinit if_spi_probe(struct spi_device *spi) card->card_id, card->card_rev, spi->master->bus_num, spi->chip_select, spi->max_speed_hz); - err = if_spi_prog_helper_firmware(card); + err = if_spi_prog_helper_firmware(card, helper); if (err) goto free_card; - err = if_spi_prog_main_firmware(card); + err = if_spi_prog_main_firmware(card, mainfw); if (err) goto free_card; lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); @@ -1046,6 +1035,11 @@ remove_card: free_card: free_if_spi_card(card); out: + if (helper) + release_firmware(helper); + if (mainfw) + release_firmware(mainfw); + lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); return err; } diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h index f87eec410848..8b1417d3b71b 100644 --- a/drivers/net/wireless/libertas/if_spi.h +++ b/drivers/net/wireless/libertas/if_spi.h @@ -25,11 +25,6 @@ #define IF_SPI_FW_NAME_MAX 30 -struct chip_ident { - u16 chip_id; - u16 name; -}; - #define MAX_MAIN_FW_LOAD_CRC_ERR 10 /* Chunk size when loading the helper firmware */ -- cgit v1.2.3-59-g8ed1b From 97359d1235eaf634fe706c9faa6e40181cc95fb8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 10 Aug 2010 09:46:38 +0200 Subject: mac80211: use cipher suite selectors Currently, mac80211 translates the cfg80211 cipher suite selectors into ALG_* values. That isn't all too useful, and some drivers benefit from the distinction between WEP40 and WEP104 as well. Therefore, convert it all to use the cipher suite selectors. Signed-off-by: Johannes Berg Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/at76c50x-usb.c | 7 ++-- drivers/net/wireless/ath/ar9170/main.c | 31 ++++++++------- drivers/net/wireless/ath/ath5k/base.c | 9 +++-- drivers/net/wireless/ath/ath5k/pcu.c | 19 ++++----- drivers/net/wireless/ath/ath9k/common.c | 36 ++++++++++-------- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 5 ++- drivers/net/wireless/ath/ath9k/main.c | 5 ++- drivers/net/wireless/b43/main.c | 16 ++++---- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 16 ++++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 24 ++++++------ drivers/net/wireless/iwlwifi/iwl3945-base.c | 43 ++++++++++++--------- drivers/net/wireless/p54/main.c | 9 +++-- drivers/net/wireless/p54/txrx.c | 17 +++++---- drivers/net/wireless/rt2x00/rt2500usb.c | 4 +- drivers/net/wireless/rt2x00/rt2x00crypto.c | 17 ++++----- drivers/net/wireless/wl12xx/wl1251_main.c | 13 ++++--- drivers/net/wireless/wl12xx/wl1251_tx.c | 4 +- drivers/net/wireless/wl12xx/wl1271_main.c | 13 ++++--- drivers/net/wireless/wl12xx/wl1271_tx.c | 4 +- include/net/mac80211.h | 18 +-------- net/mac80211/cfg.c | 44 ++++++--------------- net/mac80211/debugfs_key.c | 55 +++++++++++---------------- net/mac80211/driver-trace.h | 4 +- net/mac80211/key.c | 25 ++++++------ net/mac80211/key.h | 4 +- net/mac80211/rx.c | 18 +++++---- net/mac80211/tx.c | 22 ++++++----- net/mac80211/wep.c | 2 +- net/mac80211/wpa.c | 6 +-- 31 files changed, 236 insertions(+), 260 deletions(-) diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index d5140a87f073..a267bf55574c 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -2061,11 +2061,12 @@ static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, int i; - at76_dbg(DBG_MAC80211, "%s(): cmd %d key->alg %d key->keyidx %d " + at76_dbg(DBG_MAC80211, "%s(): cmd %d key->cipher %d key->keyidx %d " "key->keylen %d", - __func__, cmd, key->alg, key->keyidx, key->keylen); + __func__, cmd, key->cipher, key->keyidx, key->keylen); - if (key->alg != ALG_WEP) + if ((key->cipher != WLAN_CIPHER_SUITE_WEP40) && + (key->cipher != WLAN_CIPHER_SUITE_WEP104)) return -EOPNOTSUPP; key->hw_key_idx = key->keyidx; diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index c67b05f3bcbd..29d2253ad7e4 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -1190,14 +1190,13 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) if (info->control.hw_key) { icv = info->control.hw_key->icv_len; - switch (info->control.hw_key->alg) { - case ALG_WEP: + switch (info->control.hw_key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: keytype = AR9170_TX_MAC_ENCR_RC4; break; - case ALG_TKIP: - keytype = AR9170_TX_MAC_ENCR_RC4; - break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: keytype = AR9170_TX_MAC_ENCR_AES; break; default: @@ -1778,17 +1777,17 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if ((!ar->vif) || (ar->disable_offload)) return -EOPNOTSUPP; - switch (key->alg) { - case ALG_WEP: - if (key->keylen == WLAN_KEY_LEN_WEP40) - ktype = AR9170_ENC_ALG_WEP64; - else - ktype = AR9170_ENC_ALG_WEP128; + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + ktype = AR9170_ENC_ALG_WEP64; + break; + case WLAN_CIPHER_SUITE_WEP104: + ktype = AR9170_ENC_ALG_WEP128; break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: ktype = AR9170_ENC_ALG_TKIP; break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: ktype = AR9170_ENC_ALG_AESCCMP; break; default: @@ -1827,7 +1826,7 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (err) goto out; - if (key->alg == ALG_TKIP) { + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 1, key->key + 16, 16); if (err) @@ -1864,7 +1863,7 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (err) goto out; - if (key->alg == ALG_TKIP) { + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { err = ar9170_upload_key(ar, key->hw_key_idx, NULL, AR9170_ENC_ALG_NONE, 1, diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 373dcfec689c..a729b8774670 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -3297,11 +3297,12 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (sc->opmode == NL80211_IFTYPE_AP) return -EOPNOTSUPP; - switch (key->alg) { - case ALG_WEP: - case ALG_TKIP: + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: if (sc->ah->ah_aes_support) break; diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 86fdb6ddfaaa..af273358c7cb 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -695,21 +695,18 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) static int ath5k_keycache_type(const struct ieee80211_key_conf *key) { - switch (key->alg) { - case ALG_TKIP: + switch (key->cipher) { + case WLAN_CIPHER_SUITE_TKIP: return AR5K_KEYTABLE_TYPE_TKIP; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: return AR5K_KEYTABLE_TYPE_CCM; - case ALG_WEP: - if (key->keylen == WLAN_KEY_LEN_WEP40) - return AR5K_KEYTABLE_TYPE_40; - else if (key->keylen == WLAN_KEY_LEN_WEP104) - return AR5K_KEYTABLE_TYPE_104; - return -EINVAL; + case WLAN_CIPHER_SUITE_WEP40: + return AR5K_KEYTABLE_TYPE_40; + case WLAN_CIPHER_SUITE_WEP104: + return AR5K_KEYTABLE_TYPE_104; default: return -EINVAL; } - return -EINVAL; } /* @@ -728,7 +725,7 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, bool is_tkip; const u8 *key_ptr; - is_tkip = (key->alg == ALG_TKIP); + is_tkip = (key->cipher == WLAN_CIPHER_SUITE_TKIP); /* * key->keylen comes in from mac80211 in bytes. diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index c86f7d3593ab..3100c87a4fcd 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -46,12 +46,17 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); if (tx_info->control.hw_key) { - if (tx_info->control.hw_key->alg == ALG_WEP) + switch (tx_info->control.hw_key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: return ATH9K_KEY_TYPE_WEP; - else if (tx_info->control.hw_key->alg == ALG_TKIP) + case WLAN_CIPHER_SUITE_TKIP: return ATH9K_KEY_TYPE_TKIP; - else if (tx_info->control.hw_key->alg == ALG_CCMP) + case WLAN_CIPHER_SUITE_CCMP: return ATH9K_KEY_TYPE_AES; + default: + break; + } } return ATH9K_KEY_TYPE_CLEAR; @@ -212,11 +217,11 @@ static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) } static int ath_reserve_key_cache_slot(struct ath_common *common, - enum ieee80211_key_alg alg) + u32 cipher) { int i; - if (alg == ALG_TKIP) + if (cipher == WLAN_CIPHER_SUITE_TKIP) return ath_reserve_key_cache_slot_tkip(common); /* First, try to find slots that would not be available for TKIP. */ @@ -293,14 +298,15 @@ int ath9k_cmn_key_config(struct ath_common *common, memset(&hk, 0, sizeof(hk)); - switch (key->alg) { - case ALG_WEP: + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: hk.kv_type = ATH9K_CIPHER_WEP; break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: hk.kv_type = ATH9K_CIPHER_TKIP; break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: hk.kv_type = ATH9K_CIPHER_AES_CCM; break; default: @@ -316,7 +322,7 @@ int ath9k_cmn_key_config(struct ath_common *common, memcpy(gmac, vif->addr, ETH_ALEN); gmac[0] |= 0x01; mac = gmac; - idx = ath_reserve_key_cache_slot(common, key->alg); + idx = ath_reserve_key_cache_slot(common, key->cipher); break; case NL80211_IFTYPE_ADHOC: if (!sta) { @@ -326,7 +332,7 @@ int ath9k_cmn_key_config(struct ath_common *common, memcpy(gmac, sta->addr, ETH_ALEN); gmac[0] |= 0x01; mac = gmac; - idx = ath_reserve_key_cache_slot(common, key->alg); + idx = ath_reserve_key_cache_slot(common, key->cipher); break; default: idx = key->keyidx; @@ -348,13 +354,13 @@ int ath9k_cmn_key_config(struct ath_common *common, return -EOPNOTSUPP; mac = sta->addr; - idx = ath_reserve_key_cache_slot(common, key->alg); + idx = ath_reserve_key_cache_slot(common, key->cipher); } if (idx < 0) return -ENOSPC; /* no free key cache entries */ - if (key->alg == ALG_TKIP) + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, vif->type == NL80211_IFTYPE_AP); else @@ -364,7 +370,7 @@ int ath9k_cmn_key_config(struct ath_common *common, return -EIO; set_bit(idx, common->keymap); - if (key->alg == ALG_TKIP) { + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { set_bit(idx + 64, common->keymap); if (common->splitmic) { set_bit(idx + 32, common->keymap); @@ -389,7 +395,7 @@ void ath9k_cmn_key_delete(struct ath_common *common, return; clear_bit(key->hw_key_idx, common->keymap); - if (key->alg != ALG_TKIP) + if (key->cipher != WLAN_CIPHER_SUITE_TKIP) return; clear_bit(key->hw_key_idx + 64, common->keymap); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 7d09b4b17bbd..4e345be62435 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1585,9 +1585,10 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, key->hw_key_idx = ret; /* push IV and Michael MIC generation to stack */ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - if (key->alg == ALG_TKIP) + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - if (priv->ah->sw_mgmt_crypto && key->alg == ALG_CCMP) + if (priv->ah->sw_mgmt_crypto && + key->cipher == WLAN_CIPHER_SUITE_CCMP) key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; ret = 0; } diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a3b0ea90439d..1165f909ef04 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1782,9 +1782,10 @@ static int ath9k_set_key(struct ieee80211_hw *hw, key->hw_key_idx = ret; /* push IV and Michael MIC generation to stack */ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - if (key->alg == ALG_TKIP) + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP) + if (sc->sc_ah->sw_mgmt_crypto && + key->cipher == WLAN_CIPHER_SUITE_CCMP) key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; ret = 0; } diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a3e2f2bfe3a7..a1186525c70d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3759,17 +3759,17 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } err = -EINVAL; - switch (key->alg) { - case ALG_WEP: - if (key->keylen == WLAN_KEY_LEN_WEP40) - algorithm = B43_SEC_ALGO_WEP40; - else - algorithm = B43_SEC_ALGO_WEP104; + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + algorithm = B43_SEC_ALGO_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + algorithm = B43_SEC_ALGO_WEP104; break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: algorithm = B43_SEC_ALGO_TKIP; break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: algorithm = B43_SEC_ALGO_AES; break; default: diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 69155aa448fb..3fc982e87921 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -470,8 +470,8 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, { struct ieee80211_key_conf *keyconf = info->control.hw_key; - switch (keyconf->alg) { - case ALG_CCMP: + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_CCMP: tx_cmd->sec_ctl = TX_CMD_SEC_CCM; memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); if (info->flags & IEEE80211_TX_CTL_AMPDU) @@ -479,20 +479,20 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; ieee80211_get_tkip_key(keyconf, skb_frag, IEEE80211_TKIP_P2_KEY, tx_cmd->key); IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); break; - case ALG_WEP: + case WLAN_CIPHER_SUITE_WEP104: + tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; + /* fall through */ + case WLAN_CIPHER_SUITE_WEP40: tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); - if (keyconf->keylen == WEP_KEY_LEN_128) - tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; - memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " @@ -500,7 +500,7 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, break; default: - IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); + IWL_ERR(priv, "Unknown encode cipher %x\n", keyconf->cipher); break; } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 43e078b87378..21a52ae05c0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3389,7 +3389,9 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, * in 1X mode. * In legacy wep mode, we use another host command to the uCode. */ - if (key->alg == ALG_WEP && !sta && vif->type != NL80211_IFTYPE_AP) { + if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || + key->cipher == WLAN_CIPHER_SUITE_WEP104) && + !sta && vif->type != NL80211_IFTYPE_AP) { if (cmd == SET_KEY) is_default_wep_key = !priv->key_mapping_key; else diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 599635547021..149619fb1c07 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -420,7 +420,7 @@ struct iwl_tid_data { }; struct iwl_hw_key { - enum ieee80211_key_alg alg; + u32 cipher; int keylen; u8 keyidx; u8 key[32]; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 7e0829be5e78..d5e8db37b86e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -818,7 +818,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; keyconf->hw_key_idx = HW_KEY_DEFAULT; - priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; + priv->stations[IWL_AP_ID].keyinfo.cipher = keyconf->cipher; priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, @@ -856,7 +856,7 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.alg = keyconf->alg; + priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx; @@ -906,7 +906,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.alg = keyconf->alg; + priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, @@ -955,7 +955,7 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.alg = keyconf->alg; + priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; priv->stations[sta_id].keyinfo.keylen = 16; if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) @@ -1090,24 +1090,26 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, priv->key_mapping_key++; keyconf->hw_key_idx = HW_KEY_DYNAMIC; - switch (keyconf->alg) { - case ALG_CCMP: + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_CCMP: ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id); break; - case ALG_WEP: + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id); break; default: IWL_ERR(priv, - "Unknown alg: %s alg = %d\n", __func__, keyconf->alg); + "Unknown alg: %s cipher = %x\n", __func__, + keyconf->cipher); ret = -EINVAL; } - IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", - keyconf->alg, keyconf->keylen, keyconf->keyidx, + IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n", + keyconf->cipher, keyconf->keylen, keyconf->keyidx, sta_id, ret); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b14eaf91c7c2..faa2e0037e10 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -152,7 +152,7 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv, key_flags &= ~STA_KEY_FLG_INVALID; spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.alg = keyconf->alg; + priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, keyconf->keylen); @@ -223,23 +223,25 @@ static int iwl3945_set_dynamic_key(struct iwl_priv *priv, keyconf->hw_key_idx = HW_KEY_DYNAMIC; - switch (keyconf->alg) { - case ALG_CCMP: + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_CCMP: ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id); break; - case ALG_WEP: + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id); break; default: - IWL_ERR(priv, "Unknown alg: %s alg = %d\n", __func__, keyconf->alg); + IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__, + keyconf->cipher); ret = -EINVAL; } - IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", - keyconf->alg, keyconf->keylen, keyconf->keyidx, + IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n", + keyconf->cipher, keyconf->keylen, keyconf->keyidx, sta_id, ret); return ret; @@ -255,10 +257,11 @@ static int iwl3945_remove_static_key(struct iwl_priv *priv) static int iwl3945_set_static_key(struct iwl_priv *priv, struct ieee80211_key_conf *key) { - if (key->alg == ALG_WEP) + if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || + key->cipher == WLAN_CIPHER_SUITE_WEP104) return -EOPNOTSUPP; - IWL_ERR(priv, "Static key invalid: alg %d\n", key->alg); + IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher); return -EINVAL; } @@ -370,23 +373,25 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; - switch (keyinfo->alg) { - case ALG_CCMP: + tx_cmd->sec_ctl = 0; + + switch (keyinfo->cipher) { + case WLAN_CIPHER_SUITE_CCMP: tx_cmd->sec_ctl = TX_CMD_SEC_CCM; memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen); IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: break; - case ALG_WEP: - tx_cmd->sec_ctl = TX_CMD_SEC_WEP | + case WLAN_CIPHER_SUITE_WEP104: + tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; + /* fall through */ + case WLAN_CIPHER_SUITE_WEP40: + tx_cmd->sec_ctl |= TX_CMD_SEC_WEP | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; - if (keyinfo->keylen == 13) - tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; - memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen); IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " @@ -394,7 +399,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, break; default: - IWL_ERR(priv, "Unknown encode alg %d\n", keyinfo->alg); + IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher); break; } } diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 47db439b63bf..622d27b6d8f2 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -429,8 +429,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, mutex_lock(&priv->conf_mutex); if (cmd == SET_KEY) { - switch (key->alg) { - case ALG_TKIP: + switch (key->cipher) { + case WLAN_CIPHER_SUITE_TKIP: if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL | BR_DESC_PRIV_CAP_TKIP))) { ret = -EOPNOTSUPP; @@ -439,7 +439,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; algo = P54_CRYPTO_TKIPMICHAEL; break; - case ALG_WEP: + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) { ret = -EOPNOTSUPP; goto out_unlock; @@ -447,7 +448,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; algo = P54_CRYPTO_WEP; break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) { ret = -EOPNOTSUPP; goto out_unlock; diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 427b46f558ed..e53f8cec7798 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -683,14 +683,15 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb, } } -static u8 p54_convert_algo(enum ieee80211_key_alg alg) +static u8 p54_convert_algo(u32 cipher) { - switch (alg) { - case ALG_WEP: + switch (cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: return P54_CRYPTO_WEP; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: return P54_CRYPTO_TKIPMICHAEL; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: return P54_CRYPTO_AESCCMP; default: return 0; @@ -731,7 +732,7 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) if (info->control.hw_key) { crypt_offset = ieee80211_get_hdrlen_from_skb(skb); - if (info->control.hw_key->alg == ALG_TKIP) { + if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { u8 *iv = (u8 *)(skb->data + crypt_offset); /* * The firmware excepts that the IV has to have @@ -827,10 +828,10 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) hdr->tries = ridx; txhdr->rts_rate_idx = 0; if (info->control.hw_key) { - txhdr->key_type = p54_convert_algo(info->control.hw_key->alg); + txhdr->key_type = p54_convert_algo(info->control.hw_key->cipher); txhdr->key_len = min((u8)16, info->control.hw_key->keylen); memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len); - if (info->control.hw_key->alg == ALG_TKIP) { + if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { /* reserve space for the MIC key */ len += 8; memcpy(skb_put(skb, 8), &(info->control.hw_key->key diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index cdaf93f48263..97cf72f8bc12 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -355,7 +355,9 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, * it is known that not work at least on some hardware. * SW crypto will be used in that case. */ - if (key->alg == ALG_WEP && key->keyidx != 0) + if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || + key->cipher == WLAN_CIPHER_SUITE_WEP104) && + key->keyidx != 0) return -EOPNOTSUPP; /* diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 583dacd8d241..5e9074bf2b8e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -31,15 +31,14 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key) { - switch (key->alg) { - case ALG_WEP: - if (key->keylen == WLAN_KEY_LEN_WEP40) - return CIPHER_WEP64; - else - return CIPHER_WEP128; - case ALG_TKIP: + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + return CIPHER_WEP64; + case WLAN_CIPHER_SUITE_WEP104: + return CIPHER_WEP128; + case WLAN_CIPHER_SUITE_TKIP: return CIPHER_TKIP; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: return CIPHER_AES; default: return CIPHER_NONE; @@ -95,7 +94,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, overhead += key->iv_len; if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { - if (key->alg == ALG_TKIP) + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) overhead += 8; } diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 861a5f33761e..6d31c855fcfe 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -725,8 +725,9 @@ static int wl1251_set_key_type(struct wl1251 *wl, struct ieee80211_key_conf *mac80211_key, const u8 *addr) { - switch (mac80211_key->alg) { - case ALG_WEP: + switch (mac80211_key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: if (is_broadcast_ether_addr(addr)) key->key_type = KEY_WEP_DEFAULT; else @@ -734,7 +735,7 @@ static int wl1251_set_key_type(struct wl1251 *wl, mac80211_key->hw_key_idx = mac80211_key->keyidx; break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: if (is_broadcast_ether_addr(addr)) key->key_type = KEY_TKIP_MIC_GROUP; else @@ -742,7 +743,7 @@ static int wl1251_set_key_type(struct wl1251 *wl, mac80211_key->hw_key_idx = mac80211_key->keyidx; break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: if (is_broadcast_ether_addr(addr)) key->key_type = KEY_AES_GROUP; else @@ -750,7 +751,7 @@ static int wl1251_set_key_type(struct wl1251 *wl, mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; break; default: - wl1251_error("Unknown key algo 0x%x", mac80211_key->alg); + wl1251_error("Unknown key cipher 0x%x", mac80211_key->cipher); return -EOPNOTSUPP; } @@ -783,7 +784,7 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", - key->alg, key->keyidx, key->keylen, key->flags); + key->cipher, key->keyidx, key->keylen, key->flags); wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen); if (is_zero_ether_addr(addr)) { diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index a38ec199187a..6634b3e27cfc 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c @@ -189,7 +189,7 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, tx_hdr = (struct tx_double_buffer_desc *) skb->data; if (control->control.hw_key && - control->control.hw_key->alg == ALG_TKIP) { + control->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { int hdrlen; __le16 fc; u16 length; @@ -399,7 +399,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl, */ frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc)); if (info->control.hw_key && - info->control.hw_key->alg == ALG_TKIP) { + info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { hdrlen = ieee80211_get_hdrlen_from_skb(skb); memmove(frame + WL1251_TKIP_IV_SPACE, frame, hdrlen); skb_pull(skb, WL1251_TKIP_IV_SPACE); diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 9d68f0012f05..30194c0f36a9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1439,7 +1439,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", - key_conf->alg, key_conf->keyidx, + key_conf->cipher, key_conf->keyidx, key_conf->keylen, key_conf->flags); wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); @@ -1455,20 +1455,21 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (ret < 0) goto out_unlock; - switch (key_conf->alg) { - case ALG_WEP: + switch (key_conf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: key_type = KEY_WEP; key_conf->hw_key_idx = key_conf->keyidx; break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: key_type = KEY_TKIP; key_conf->hw_key_idx = key_conf->keyidx; tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: key_type = KEY_AES; key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; @@ -1476,7 +1477,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); break; default: - wl1271_error("Unknown key algo 0x%x", key_conf->alg); + wl1271_error("Unknown key algo 0x%x", key_conf->cipher); ret = -EOPNOTSUPP; goto out_sleep; diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index c592cc2e9fe8..dc0b46c93c4b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -193,7 +193,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) info = IEEE80211_SKB_CB(skb); if (info->control.hw_key && - info->control.hw_key->alg == ALG_TKIP) + info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) extra = WL1271_TKIP_IV_SPACE; if (info->control.hw_key) { @@ -347,7 +347,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, /* remove TKIP header space if present */ if (info->control.hw_key && - info->control.hw_key->alg == ALG_TKIP) { + info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { int hdrlen = ieee80211_get_hdrlen_from_skb(skb); memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen); skb_pull(skb, WL1271_TKIP_IV_SPACE); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 871ed1de736a..914c747ac3a0 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -788,20 +788,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) return false; } -/** - * enum ieee80211_key_alg - key algorithm - * @ALG_WEP: WEP40 or WEP104 - * @ALG_TKIP: TKIP - * @ALG_CCMP: CCMP (AES) - * @ALG_AES_CMAC: AES-128-CMAC - */ -enum ieee80211_key_alg { - ALG_WEP, - ALG_TKIP, - ALG_CCMP, - ALG_AES_CMAC, -}; - /** * enum ieee80211_key_flags - key flags * @@ -839,7 +825,7 @@ enum ieee80211_key_flags { * @hw_key_idx: To be set by the driver, this is the key index the driver * wants to be given when a frame is transmitted and needs to be * encrypted in hardware. - * @alg: The key algorithm. + * @cipher: The key's cipher suite selector. * @flags: key flags, see &enum ieee80211_key_flags. * @keyidx: the key index (0-3) * @keylen: key material length @@ -852,7 +838,7 @@ enum ieee80211_key_flags { * @iv_len: The IV length for this key type */ struct ieee80211_key_conf { - enum ieee80211_key_alg alg; + u32 cipher; u8 icv_len; u8 iv_len; u8 hw_key_idx; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 19c6146010b7..9a35d9e7efd7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -116,7 +116,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, { struct ieee80211_sub_if_data *sdata; struct sta_info *sta = NULL; - enum ieee80211_key_alg alg; struct ieee80211_key *key; int err; @@ -125,31 +124,20 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); + /* reject WEP and TKIP keys if WEP failed to initialize */ switch (params->cipher) { case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - alg = ALG_WEP; - break; case WLAN_CIPHER_SUITE_TKIP: - alg = ALG_TKIP; - break; - case WLAN_CIPHER_SUITE_CCMP: - alg = ALG_CCMP; - break; - case WLAN_CIPHER_SUITE_AES_CMAC: - alg = ALG_AES_CMAC; + case WLAN_CIPHER_SUITE_WEP104: + if (IS_ERR(sdata->local->wep_tx_tfm)) + return -EINVAL; break; default: - return -EINVAL; + break; } - /* reject WEP and TKIP keys if WEP failed to initialize */ - if ((alg == ALG_WEP || alg == ALG_TKIP) && - IS_ERR(sdata->local->wep_tx_tfm)) - return -EINVAL; - - key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key, - params->seq_len, params->seq); + key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, + params->key, params->seq_len, params->seq); if (IS_ERR(key)) return PTR_ERR(key); @@ -247,10 +235,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, memset(¶ms, 0, sizeof(params)); - switch (key->conf.alg) { - case ALG_TKIP: - params.cipher = WLAN_CIPHER_SUITE_TKIP; + params.cipher = key->conf.cipher; + switch (key->conf.cipher) { + case WLAN_CIPHER_SUITE_TKIP: iv32 = key->u.tkip.tx.iv32; iv16 = key->u.tkip.tx.iv16; @@ -268,8 +256,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, params.seq = seq; params.seq_len = 6; break; - case ALG_CCMP: - params.cipher = WLAN_CIPHER_SUITE_CCMP; + case WLAN_CIPHER_SUITE_CCMP: seq[0] = key->u.ccmp.tx_pn[5]; seq[1] = key->u.ccmp.tx_pn[4]; seq[2] = key->u.ccmp.tx_pn[3]; @@ -279,14 +266,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, params.seq = seq; params.seq_len = 6; break; - case ALG_WEP: - if (key->conf.keylen == 5) - params.cipher = WLAN_CIPHER_SUITE_WEP40; - else - params.cipher = WLAN_CIPHER_SUITE_WEP104; - break; - case ALG_AES_CMAC: - params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; + case WLAN_CIPHER_SUITE_AES_CMAC: seq[0] = key->u.aes_cmac.tx_pn[5]; seq[1] = key->u.aes_cmac.tx_pn[4]; seq[2] = key->u.aes_cmac.tx_pn[3]; diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index fa5e76e658ef..1647f8dc5cda 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -64,26 +64,13 @@ static ssize_t key_algorithm_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { - char *alg; + char buf[15]; struct ieee80211_key *key = file->private_data; + u32 c = key->conf.cipher; - switch (key->conf.alg) { - case ALG_WEP: - alg = "WEP\n"; - break; - case ALG_TKIP: - alg = "TKIP\n"; - break; - case ALG_CCMP: - alg = "CCMP\n"; - break; - case ALG_AES_CMAC: - alg = "AES-128-CMAC\n"; - break; - default: - return 0; - } - return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg)); + sprintf(buf, "%.2x-%.2x-%.2x:%d\n", + c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff); + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); } KEY_OPS(algorithm); @@ -95,21 +82,22 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, int len; struct ieee80211_key *key = file->private_data; - switch (key->conf.alg) { - case ALG_WEP: + switch (key->conf.cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: len = scnprintf(buf, sizeof(buf), "\n"); break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: len = scnprintf(buf, sizeof(buf), "%08x %04x\n", key->u.tkip.tx.iv32, key->u.tkip.tx.iv16); break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: tpn = key->u.ccmp.tx_pn; len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); break; - case ALG_AES_CMAC: + case WLAN_CIPHER_SUITE_AES_CMAC: tpn = key->u.aes_cmac.tx_pn; len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], @@ -130,11 +118,12 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, int i, len; const u8 *rpn; - switch (key->conf.alg) { - case ALG_WEP: + switch (key->conf.cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: len = scnprintf(buf, sizeof(buf), "\n"); break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: for (i = 0; i < NUM_RX_DATA_QUEUES; i++) p += scnprintf(p, sizeof(buf)+buf-p, "%08x %04x\n", @@ -142,7 +131,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, key->u.tkip.rx[i].iv16); len = p - buf; break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) { rpn = key->u.ccmp.rx_pn[i]; p += scnprintf(p, sizeof(buf)+buf-p, @@ -152,7 +141,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, } len = p - buf; break; - case ALG_AES_CMAC: + case WLAN_CIPHER_SUITE_AES_CMAC: rpn = key->u.aes_cmac.rx_pn; p += scnprintf(p, sizeof(buf)+buf-p, "%02x%02x%02x%02x%02x%02x\n", @@ -174,11 +163,11 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf, char buf[20]; int len; - switch (key->conf.alg) { - case ALG_CCMP: + switch (key->conf.cipher) { + case WLAN_CIPHER_SUITE_CCMP: len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); break; - case ALG_AES_CMAC: + case WLAN_CIPHER_SUITE_AES_CMAC: len = scnprintf(buf, sizeof(buf), "%u\n", key->u.aes_cmac.replays); break; @@ -196,8 +185,8 @@ static ssize_t key_icverrors_read(struct file *file, char __user *userbuf, char buf[20]; int len; - switch (key->conf.alg) { - case ALG_AES_CMAC: + switch (key->conf.cipher) { + case WLAN_CIPHER_SUITE_AES_CMAC: len = scnprintf(buf, sizeof(buf), "%u\n", key->u.aes_cmac.icverrors); break; diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 5d5d2a974668..b5a95582d816 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -336,7 +336,7 @@ TRACE_EVENT(drv_set_key, LOCAL_ENTRY VIF_ENTRY STA_ENTRY - __field(enum ieee80211_key_alg, alg) + __field(u32, cipher) __field(u8, hw_key_idx) __field(u8, flags) __field(s8, keyidx) @@ -346,7 +346,7 @@ TRACE_EVENT(drv_set_key, LOCAL_ASSIGN; VIF_ASSIGN; STA_ASSIGN; - __entry->alg = key->alg; + __entry->cipher = key->cipher; __entry->flags = key->flags; __entry->keyidx = key->keyidx; __entry->hw_key_idx = key->hw_key_idx; diff --git a/net/mac80211/key.c b/net/mac80211/key.c index d6dbc8ea4ead..3203d1d3cd38 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -227,9 +227,7 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, } } -struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, - int idx, - size_t key_len, +struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, const u8 *key_data, size_t seq_len, const u8 *seq) { @@ -249,15 +247,16 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, key->conf.flags = 0; key->flags = 0; - key->conf.alg = alg; + key->conf.cipher = cipher; key->conf.keyidx = idx; key->conf.keylen = key_len; - switch (alg) { - case ALG_WEP: + switch (cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: key->conf.iv_len = WEP_IV_LEN; key->conf.icv_len = WEP_ICV_LEN; break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: key->conf.iv_len = TKIP_IV_LEN; key->conf.icv_len = TKIP_ICV_LEN; if (seq) { @@ -269,7 +268,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, } } break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: key->conf.iv_len = CCMP_HDR_LEN; key->conf.icv_len = CCMP_MIC_LEN; if (seq) { @@ -279,7 +278,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, seq[CCMP_PN_LEN - j - 1]; } break; - case ALG_AES_CMAC: + case WLAN_CIPHER_SUITE_AES_CMAC: key->conf.iv_len = 0; key->conf.icv_len = sizeof(struct ieee80211_mmie); if (seq) @@ -290,7 +289,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, memcpy(key->conf.key, key_data, key_len); INIT_LIST_HEAD(&key->list); - if (alg == ALG_CCMP) { + if (cipher == WLAN_CIPHER_SUITE_CCMP) { /* * Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. @@ -303,7 +302,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, } } - if (alg == ALG_AES_CMAC) { + if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) { /* * Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. @@ -328,9 +327,9 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) if (key->local) ieee80211_key_disable_hw_accel(key); - if (key->conf.alg == ALG_CCMP) + if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) ieee80211_aes_key_free(key->u.ccmp.tfm); - if (key->conf.alg == ALG_AES_CMAC) + if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); if (key->local) ieee80211_debugfs_key_remove(key); diff --git a/net/mac80211/key.h b/net/mac80211/key.h index b665bbb7a471..53b5ce12536f 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -123,9 +123,7 @@ struct ieee80211_key { struct ieee80211_key_conf conf; }; -struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, - int idx, - size_t key_len, +struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, const u8 *key_data, size_t seq_len, const u8 *seq); /* diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f24a0a1cff1a..ad2427021b26 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -961,7 +961,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) * pairwise or station-to-station keys, but for WEP we allow * using a key index as well. */ - if (rx->key && rx->key->conf.alg != ALG_WEP && + if (rx->key && rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && + rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && !is_multicast_ether_addr(hdr->addr1)) rx->key = NULL; } @@ -977,8 +978,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) return RX_DROP_UNUSABLE; /* the hdr variable is invalid now! */ - switch (rx->key->conf.alg) { - case ALG_WEP: + switch (rx->key->conf.cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: /* Check for weak IVs if possible */ if (rx->sta && ieee80211_is_data(fc) && (!(status->flag & RX_FLAG_IV_STRIPPED) || @@ -988,13 +990,13 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) result = ieee80211_crypto_wep_decrypt(rx); break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: result = ieee80211_crypto_tkip_decrypt(rx); break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: result = ieee80211_crypto_ccmp_decrypt(rx); break; - case ALG_AES_CMAC: + case WLAN_CIPHER_SUITE_AES_CMAC: result = ieee80211_crypto_aes_cmac_decrypt(rx); break; } @@ -1291,7 +1293,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) /* This is the first fragment of a new frame. */ entry = ieee80211_reassemble_add(rx->sdata, frag, seq, rx->queue, &(rx->skb)); - if (rx->key && rx->key->conf.alg == ALG_CCMP && + if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && ieee80211_has_protected(fc)) { int queue = ieee80211_is_mgmt(fc) ? NUM_RX_DATA_QUEUES : rx->queue; @@ -1320,7 +1322,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) int i; u8 pn[CCMP_PN_LEN], *rpn; int queue; - if (!rx->key || rx->key->conf.alg != ALG_CCMP) + if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP) return RX_DROP_UNUSABLE; memcpy(pn, entry->last_pn, CCMP_PN_LEN); for (i = CCMP_PN_LEN - 1; i >= 0; i--) { diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c54db966926b..bc4fefc91663 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -543,15 +543,16 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) tx->key->tx_rx_count++; /* TODO: add threshold stuff again */ - switch (tx->key->conf.alg) { - case ALG_WEP: + switch (tx->key->conf.cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: if (ieee80211_is_auth(hdr->frame_control)) break; - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: if (!ieee80211_is_data_present(hdr->frame_control)) tx->key = NULL; break; - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: if (!ieee80211_is_data_present(hdr->frame_control) && !ieee80211_use_mfp(hdr->frame_control, tx->sta, tx->skb)) @@ -561,7 +562,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) IEEE80211_KEY_FLAG_SW_MGMT) && ieee80211_is_mgmt(hdr->frame_control); break; - case ALG_AES_CMAC: + case WLAN_CIPHER_SUITE_AES_CMAC: if (!ieee80211_is_mgmt(hdr->frame_control)) tx->key = NULL; break; @@ -949,14 +950,15 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) if (!tx->key) return TX_CONTINUE; - switch (tx->key->conf.alg) { - case ALG_WEP: + switch (tx->key->conf.cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: return ieee80211_crypto_wep_encrypt(tx); - case ALG_TKIP: + case WLAN_CIPHER_SUITE_TKIP: return ieee80211_crypto_tkip_encrypt(tx); - case ALG_CCMP: + case WLAN_CIPHER_SUITE_CCMP: return ieee80211_crypto_ccmp_encrypt(tx); - case ALG_AES_CMAC: + case WLAN_CIPHER_SUITE_AES_CMAC: return ieee80211_crypto_aes_cmac_encrypt(tx); } diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 9ebc8d8a1f5b..f27484c22b9f 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -240,7 +240,7 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, keyidx = skb->data[hdrlen + 3] >> 6; - if (!key || keyidx != key->conf.keyidx || key->conf.alg != ALG_WEP) + if (!key || keyidx != key->conf.keyidx) return -1; klen = 3 + key->conf.keylen; diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 8d59d27d887e..b08ad94b56da 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -36,8 +36,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) int tail; hdr = (struct ieee80211_hdr *)skb->data; - if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 || - !ieee80211_is_data_present(hdr->frame_control)) + if (!tx->key || tx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || + skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control)) return TX_CONTINUE; hdrlen = ieee80211_hdrlen(hdr->frame_control); @@ -94,7 +94,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_MMIC_STRIPPED) return RX_CONTINUE; - if (!rx->key || rx->key->conf.alg != ALG_TKIP || + if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || !ieee80211_has_protected(hdr->frame_control) || !ieee80211_is_data_present(hdr->frame_control)) return RX_CONTINUE; -- cgit v1.2.3-59-g8ed1b From 60ae0f20058d19ada94093dc3ef7ae0737597fba Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 10 Aug 2010 09:46:39 +0200 Subject: mac80211: move key tfm setup There's no need to keep separate if statements for setting up the CCMP/AES-CMAC tfm structs; move that into the existing switch statement. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/key.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 3203d1d3cd38..9c27c53cfae5 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -277,19 +277,6 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, key->u.ccmp.rx_pn[i][j] = seq[CCMP_PN_LEN - j - 1]; } - break; - case WLAN_CIPHER_SUITE_AES_CMAC: - key->conf.iv_len = 0; - key->conf.icv_len = sizeof(struct ieee80211_mmie); - if (seq) - for (j = 0; j < 6; j++) - key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; - break; - } - memcpy(key->conf.key, key_data, key_len); - INIT_LIST_HEAD(&key->list); - - if (cipher == WLAN_CIPHER_SUITE_CCMP) { /* * Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. @@ -300,9 +287,13 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, kfree(key); key = ERR_PTR(err); } - } - - if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) { + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + key->conf.iv_len = 0; + key->conf.icv_len = sizeof(struct ieee80211_mmie); + if (seq) + for (j = 0; j < 6; j++) + key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; /* * Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. @@ -314,7 +305,10 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, kfree(key); key = ERR_PTR(err); } + break; } + memcpy(key->conf.key, key_data, key_len); + INIT_LIST_HEAD(&key->list); return key; } -- cgit v1.2.3-59-g8ed1b From dc1580ddfc1f70636f6ef80a385902f7e8278deb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 10 Aug 2010 09:46:40 +0200 Subject: mac80211: remove unused status flag checks The decryption code verifies whether or not a given frame was decrypted and verified by hardware. This is unnecessary, as the crypto RX handler already does it long before the decryption code is even invoked, so remove that code to avoid confusion. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/rx.c | 3 +++ net/mac80211/wpa.c | 26 ++++++-------------------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ad2427021b26..4fdbed58ca2f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -899,6 +899,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) if (!is_multicast_ether_addr(hdr->addr1) && stakey) { rx->key = stakey; + if ((status->flag & RX_FLAG_DECRYPTED) && + (status->flag & RX_FLAG_IV_STRIPPED)) + return RX_CONTINUE; /* Skip decryption if the frame is not protected. */ if (!ieee80211_has_protected(fc)) return RX_CONTINUE; diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index b08ad94b56da..43882b36da55 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -221,19 +221,13 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) if (!rx->sta || skb->len - hdrlen < 12) return RX_DROP_UNUSABLE; - if (status->flag & RX_FLAG_DECRYPTED) { - if (status->flag & RX_FLAG_IV_STRIPPED) { - /* - * Hardware took care of all processing, including - * replay protection, and stripped the ICV/IV so - * we cannot do any checks here. - */ - return RX_CONTINUE; - } - - /* let TKIP code verify IV, but skip decryption */ + /* + * Let TKIP code verify IV, but skip decryption. + * In the case where hardware checks the IV as well, + * we don't even get here, see ieee80211_rx_h_decrypt() + */ + if (status->flag & RX_FLAG_DECRYPTED) hwaccel = 1; - } res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, key, skb->data + hdrlen, @@ -447,10 +441,6 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) if (!rx->sta || data_len < 0) return RX_DROP_UNUSABLE; - if ((status->flag & RX_FLAG_DECRYPTED) && - (status->flag & RX_FLAG_IV_STRIPPED)) - return RX_CONTINUE; - ccmp_hdr2pn(pn, skb->data + hdrlen); queue = ieee80211_is_mgmt(hdr->frame_control) ? @@ -564,10 +554,6 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) if (!ieee80211_is_mgmt(hdr->frame_control)) return RX_CONTINUE; - if ((status->flag & RX_FLAG_DECRYPTED) && - (status->flag & RX_FLAG_IV_STRIPPED)) - return RX_CONTINUE; - if (skb->len < 24 + sizeof(*mmie)) return RX_DROP_UNUSABLE; -- cgit v1.2.3-59-g8ed1b From 5daa8a8e691e28c6c725e7e91319b160b555c615 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 10 Aug 2010 09:46:41 +0200 Subject: mac80211: dont advertise WEP if unavailable When WEP is unavailable, don't advertise it to cfg80211. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 06b9608a2130..0afccda42a24 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -536,6 +536,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) int channels, max_bitrates; bool supp_ht; static const u32 cipher_suites[] = { + /* keep WEP first, it may be removed below */ WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, @@ -623,6 +624,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) local->hw.wiphy->n_cipher_suites--; + if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) { + local->hw.wiphy->cipher_suites += 2; + local->hw.wiphy->n_cipher_suites -= 2; + } result = wiphy_register(local->hw.wiphy); if (result < 0) -- cgit v1.2.3-59-g8ed1b From afea0b7af7a0c070da8b2029d721abc930e5f96f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 10 Aug 2010 09:46:42 +0200 Subject: cfg80211: check if WEP is available for shared key auth When shared key auth is requested, cfg80211 should verify that the device is capable of WEP crypto which is required. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 37902a54e9c1..bb5b78eebeb2 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3572,6 +3572,21 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) if (err) goto unlock_rtnl; + if (key.idx >= 0) { + int i; + bool ok = false; + for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) { + if (key.p.cipher == rdev->wiphy.cipher_suites[i]) { + ok = true; + break; + } + } + if (!ok) { + err = -EINVAL; + goto out; + } + } + if (!rdev->ops->auth) { err = -EOPNOTSUPP; goto out; -- cgit v1.2.3-59-g8ed1b From b68b3c4d92ff2440414137763477648e6db6c96f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 10 Aug 2010 18:01:06 -0700 Subject: drivers/net/wireless/libertas/cfg.c: needs sched.h i386 allmodconfig: drivers/net/wireless/libertas/cfg.c: In function 'lbs_scan_worker': drivers/net/wireless/libertas/cfg.c:722: error: 'TASK_NORMAL' undeclared (first use in this function) drivers/net/wireless/libertas/cfg.c:722: error: (Each undeclared identifier is reported only once drivers/net/wireless/libertas/cfg.c:722: error: for each function it appears in.) drivers/net/wireless/libertas/cfg.c: In function 'lbs_cfg_connect': drivers/net/wireless/libertas/cfg.c:1267: error: 'TASK_INTERRUPTIBLE' undeclared (first use in this function) drivers/net/wireless/libertas/cfg.c:1267: error: implicit declaration of function 'signal_pending' drivers/net/wireless/libertas/cfg.c:1267: error: implicit declaration of function 'schedule_timeout' So wait.h has a dependency on sched.h, but doesn't include sched.h. This patch doesn't fix that. Cc: Dan Williams Cc: "John W. Linville" Cc: Ingo Molnar Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cfg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 08487a848e05..03b7108505e7 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3-59-g8ed1b From 6891dd25d3f82e50979b27fde1980aa96320b975 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 3 Aug 2010 21:49:40 +0000 Subject: bnx2x: Load firmware in open() instead of probe() Loading firmware when actually bringing eth device up. This also will allow driver to be insmoded when filesystem with firmware files is not available yet. Suggested by Stephen Hemminger Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_cmn.c | 20 ++++++++++++++++++++ drivers/net/bnx2x/bnx2x_cmn.h | 9 +++++++++ drivers/net/bnx2x/bnx2x_main.c | 26 +++++++------------------- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 02bf710629a3..da96d1a18c20 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "bnx2x_cmn.h" #ifdef BCM_VLAN @@ -1206,12 +1207,27 @@ static int bnx2x_set_num_queues(struct bnx2x *bp) return rc; } +static void bnx2x_release_firmware(struct bnx2x *bp) +{ + kfree(bp->init_ops_offsets); + kfree(bp->init_ops); + kfree(bp->init_data); + release_firmware(bp->firmware); +} + /* must be called with rtnl_lock */ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) { u32 load_code; int i, rc; + /* Set init arrays */ + rc = bnx2x_init_firmware(bp); + if (rc) { + BNX2X_ERR("Error loading firmware\n"); + return rc; + } + #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) return -EPERM; @@ -1427,6 +1443,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) #endif bnx2x_inc_load_cnt(bp); + bnx2x_release_firmware(bp); + return 0; #ifdef BCM_CNIC @@ -1454,6 +1472,8 @@ load_error1: netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); + bnx2x_release_firmware(bp); + return rc; } diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index d1979b1a7ed2..32543c32805c 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -114,6 +114,15 @@ void bnx2x_int_enable(struct bnx2x *bp); */ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw); +/** + * Loads device firmware + * + * @param bp + * + * @return int + */ +int bnx2x_init_firmware(struct bnx2x *bp); + /** * Init HW blocks according to current initialization stage: * COMMON, PORT or FUNCTION. diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index b4ec2b02a465..13309f1717b9 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -7254,7 +7254,7 @@ static void __devinit bnx2x_get_pcie_width_speed(struct bnx2x *bp, *speed = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT; } -static int __devinit bnx2x_check_firmware(struct bnx2x *bp) +static int bnx2x_check_firmware(struct bnx2x *bp) { const struct firmware *firmware = bp->firmware; struct bnx2x_fw_file_hdr *fw_hdr; @@ -7365,7 +7365,7 @@ do { \ (u8 *)bp->arr, len); \ } while (0) -static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev) +int bnx2x_init_firmware(struct bnx2x *bp) { const char *fw_file_name; struct bnx2x_fw_file_hdr *fw_hdr; @@ -7376,21 +7376,21 @@ static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev) else if (CHIP_IS_E1H(bp)) fw_file_name = FW_FILE_NAME_E1H; else { - dev_err(dev, "Unsupported chip revision\n"); + BNX2X_ERR("Unsupported chip revision\n"); return -EINVAL; } - dev_info(dev, "Loading %s\n", fw_file_name); + BNX2X_DEV_INFO("Loading %s\n", fw_file_name); - rc = request_firmware(&bp->firmware, fw_file_name, dev); + rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev); if (rc) { - dev_err(dev, "Can't load firmware file %s\n", fw_file_name); + BNX2X_ERR("Can't load firmware file %s\n", fw_file_name); goto request_firmware_exit; } rc = bnx2x_check_firmware(bp); if (rc) { - dev_err(dev, "Corrupt firmware file %s\n", fw_file_name); + BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name); goto request_firmware_exit; } @@ -7468,13 +7468,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, if (rc) goto init_one_exit; - /* Set init arrays */ - rc = bnx2x_init_firmware(bp, &pdev->dev); - if (rc) { - dev_err(&pdev->dev, "Error loading firmware\n"); - goto init_one_exit; - } - rc = register_netdev(dev); if (rc) { dev_err(&pdev->dev, "Cannot register net device\n"); @@ -7525,11 +7518,6 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) /* Make sure RESET task is not scheduled before continuing */ cancel_delayed_work_sync(&bp->reset_task); - kfree(bp->init_ops_offsets); - kfree(bp->init_ops); - kfree(bp->init_data); - release_firmware(bp->firmware); - if (bp->regview) iounmap(bp->regview); -- cgit v1.2.3-59-g8ed1b From bfb564e7391340638afe4ad67744a8f3858e7566 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Wed, 4 Aug 2010 06:15:52 +0000 Subject: core: Factor out flow calculation from get_rps_cpu Factor out flow calculation code from get_rps_cpu, since other functions can use the same code. Revisions: v2 (Ben): Separate flow calcuation out and use in select queue. v3 (Arnd): Don't re-implement MIN. v4 (Changli): skb->data points to ethernet header in macvtap, and make a fast path. Tested macvtap with this patch. v5 (Changli): - Cache skb->rxhash in skb_get_rxhash - macvtap may not have pow(2) queues, so change code for queue selection. (Arnd): - Use first available queue if all fails. Signed-off-by: Krishna Kumar Signed-off-by: David S. Miller --- include/linux/skbuff.h | 9 +++++ net/core/dev.c | 106 +++++++++++++++++++++++++++++-------------------- 2 files changed, 71 insertions(+), 44 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 77eb60d2b496..d8050382b189 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -558,6 +558,15 @@ extern unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, unsigned int to, struct ts_config *config, struct ts_state *state); +extern __u32 __skb_get_rxhash(struct sk_buff *skb); +static inline __u32 skb_get_rxhash(struct sk_buff *skb) +{ + if (!skb->rxhash) + skb->rxhash = __skb_get_rxhash(skb); + + return skb->rxhash; +} + #ifdef NET_SKBUFF_DATA_USES_OFFSET static inline unsigned char *skb_end_pointer(const struct sk_buff *skb) { diff --git a/net/core/dev.c b/net/core/dev.c index 1ae654391442..586a11cb4398 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2259,69 +2259,41 @@ static inline void ____napi_schedule(struct softnet_data *sd, __raise_softirq_irqoff(NET_RX_SOFTIRQ); } -#ifdef CONFIG_RPS - -/* One global table that all flow-based protocols share. */ -struct rps_sock_flow_table *rps_sock_flow_table __read_mostly; -EXPORT_SYMBOL(rps_sock_flow_table); - /* - * get_rps_cpu is called from netif_receive_skb and returns the target - * CPU from the RPS map of the receiving queue for a given skb. - * rcu_read_lock must be held on entry. + * __skb_get_rxhash: calculate a flow hash based on src/dst addresses + * and src/dst port numbers. Returns a non-zero hash number on success + * and 0 on failure. */ -static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, - struct rps_dev_flow **rflowp) +__u32 __skb_get_rxhash(struct sk_buff *skb) { + int nhoff, hash = 0; struct ipv6hdr *ip6; struct iphdr *ip; - struct netdev_rx_queue *rxqueue; - struct rps_map *map; - struct rps_dev_flow_table *flow_table; - struct rps_sock_flow_table *sock_flow_table; - int cpu = -1; u8 ip_proto; - u16 tcpu; u32 addr1, addr2, ihl; union { u32 v32; u16 v16[2]; } ports; - if (skb_rx_queue_recorded(skb)) { - u16 index = skb_get_rx_queue(skb); - if (unlikely(index >= dev->num_rx_queues)) { - WARN_ONCE(dev->num_rx_queues > 1, "%s received packet " - "on queue %u, but number of RX queues is %u\n", - dev->name, index, dev->num_rx_queues); - goto done; - } - rxqueue = dev->_rx + index; - } else - rxqueue = dev->_rx; - - if (!rxqueue->rps_map && !rxqueue->rps_flow_table) - goto done; - - if (skb->rxhash) - goto got_hash; /* Skip hash computation on packet header */ + nhoff = skb_network_offset(skb); switch (skb->protocol) { case __constant_htons(ETH_P_IP): - if (!pskb_may_pull(skb, sizeof(*ip))) + if (!pskb_may_pull(skb, sizeof(*ip) + nhoff)) goto done; - ip = (struct iphdr *) skb->data; + ip = (struct iphdr *) skb->data + nhoff; ip_proto = ip->protocol; addr1 = (__force u32) ip->saddr; addr2 = (__force u32) ip->daddr; ihl = ip->ihl; break; case __constant_htons(ETH_P_IPV6): - if (!pskb_may_pull(skb, sizeof(*ip6))) + if (!pskb_may_pull(skb, sizeof(*ip6) + nhoff)) goto done; - ip6 = (struct ipv6hdr *) skb->data; + ip6 = (struct ipv6hdr *) skb->data + nhoff; ip_proto = ip6->nexthdr; addr1 = (__force u32) ip6->saddr.s6_addr32[3]; addr2 = (__force u32) ip6->daddr.s6_addr32[3]; @@ -2330,6 +2302,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, default: goto done; } + switch (ip_proto) { case IPPROTO_TCP: case IPPROTO_UDP: @@ -2338,8 +2311,9 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, case IPPROTO_AH: case IPPROTO_SCTP: case IPPROTO_UDPLITE: - if (pskb_may_pull(skb, (ihl * 4) + 4)) { - ports.v32 = * (__force u32 *) (skb->data + (ihl * 4)); + if (pskb_may_pull(skb, (ihl * 4) + 4 + nhoff)) { + ports.v32 = * (__force u32 *) (skb->data + nhoff + + (ihl * 4)); if (ports.v16[1] < ports.v16[0]) swap(ports.v16[0], ports.v16[1]); break; @@ -2352,11 +2326,55 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, /* get a consistent hash (same value on both flow directions) */ if (addr2 < addr1) swap(addr1, addr2); - skb->rxhash = jhash_3words(addr1, addr2, ports.v32, hashrnd); - if (!skb->rxhash) - skb->rxhash = 1; -got_hash: + hash = jhash_3words(addr1, addr2, ports.v32, hashrnd); + if (!hash) + hash = 1; + +done: + return hash; +} +EXPORT_SYMBOL(__skb_get_rxhash); + +#ifdef CONFIG_RPS + +/* One global table that all flow-based protocols share. */ +struct rps_sock_flow_table *rps_sock_flow_table __read_mostly; +EXPORT_SYMBOL(rps_sock_flow_table); + +/* + * get_rps_cpu is called from netif_receive_skb and returns the target + * CPU from the RPS map of the receiving queue for a given skb. + * rcu_read_lock must be held on entry. + */ +static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, + struct rps_dev_flow **rflowp) +{ + struct netdev_rx_queue *rxqueue; + struct rps_map *map; + struct rps_dev_flow_table *flow_table; + struct rps_sock_flow_table *sock_flow_table; + int cpu = -1; + u16 tcpu; + + if (skb_rx_queue_recorded(skb)) { + u16 index = skb_get_rx_queue(skb); + if (unlikely(index >= dev->num_rx_queues)) { + WARN_ONCE(dev->num_rx_queues > 1, "%s received packet " + "on queue %u, but number of RX queues is %u\n", + dev->name, index, dev->num_rx_queues); + goto done; + } + rxqueue = dev->_rx + index; + } else + rxqueue = dev->_rx; + + if (!rxqueue->rps_map && !rxqueue->rps_flow_table) + goto done; + + if (!skb_get_rxhash(skb)) + goto done; + flow_table = rcu_dereference(rxqueue->rps_flow_table); sock_flow_table = rcu_dereference(rps_sock_flow_table); if (flow_table && sock_flow_table) { -- cgit v1.2.3-59-g8ed1b From 1565c7c1c4c8e931bdba66abc8aa6f141a406872 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Wed, 4 Aug 2010 06:15:59 +0000 Subject: macvtap: Implement multiqueue for macvtap driver Implement multiqueue facility for macvtap driver. The idea is that a macvtap device can be opened multiple times and the fd's can be used to register eg, as backend for vhost. Signed-off-by: Krishna Kumar Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 99 ++++++++++++++++++++++++++++++++++++++-------- include/linux/if_macvlan.h | 9 ++++- 2 files changed, 90 insertions(+), 18 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 3b1c54a9c6ef..42567279843e 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -84,26 +84,45 @@ static const struct proto_ops macvtap_socket_ops; static DEFINE_SPINLOCK(macvtap_lock); /* - * Choose the next free queue, for now there is only one + * get_slot: return a [unused/occupied] slot in vlan->taps[]: + * - if 'q' is NULL, return the first empty slot; + * - otherwise, return the slot this pointer occupies. */ +static int get_slot(struct macvlan_dev *vlan, struct macvtap_queue *q) +{ + int i; + + for (i = 0; i < MAX_MACVTAP_QUEUES; i++) { + if (rcu_dereference(vlan->taps[i]) == q) + return i; + } + + /* Should never happen */ + BUG_ON(1); +} + static int macvtap_set_queue(struct net_device *dev, struct file *file, struct macvtap_queue *q) { struct macvlan_dev *vlan = netdev_priv(dev); + int index; int err = -EBUSY; spin_lock(&macvtap_lock); - if (rcu_dereference(vlan->tap)) + if (vlan->numvtaps == MAX_MACVTAP_QUEUES) goto out; err = 0; + index = get_slot(vlan, NULL); rcu_assign_pointer(q->vlan, vlan); - rcu_assign_pointer(vlan->tap, q); + rcu_assign_pointer(vlan->taps[index], q); sock_hold(&q->sk); q->file = file; file->private_data = q; + vlan->numvtaps++; + out: spin_unlock(&macvtap_lock); return err; @@ -124,9 +143,12 @@ static void macvtap_put_queue(struct macvtap_queue *q) spin_lock(&macvtap_lock); vlan = rcu_dereference(q->vlan); if (vlan) { - rcu_assign_pointer(vlan->tap, NULL); + int index = get_slot(vlan, q); + + rcu_assign_pointer(vlan->taps[index], NULL); rcu_assign_pointer(q->vlan, NULL); sock_put(&q->sk); + --vlan->numvtaps; } spin_unlock(&macvtap_lock); @@ -136,39 +158,82 @@ static void macvtap_put_queue(struct macvtap_queue *q) } /* - * Since we only support one queue, just dereference the pointer. + * Select a queue based on the rxq of the device on which this packet + * arrived. If the incoming device is not mq, calculate a flow hash + * to select a queue. If all fails, find the first available queue. + * Cache vlan->numvtaps since it can become zero during the execution + * of this function. */ static struct macvtap_queue *macvtap_get_queue(struct net_device *dev, struct sk_buff *skb) { struct macvlan_dev *vlan = netdev_priv(dev); + struct macvtap_queue *tap = NULL; + int numvtaps = vlan->numvtaps; + __u32 rxq; + + if (!numvtaps) + goto out; + + if (likely(skb_rx_queue_recorded(skb))) { + rxq = skb_get_rx_queue(skb); + + while (unlikely(rxq >= numvtaps)) + rxq -= numvtaps; + + tap = rcu_dereference(vlan->taps[rxq]); + if (tap) + goto out; + } + + /* Check if we can use flow to select a queue */ + rxq = skb_get_rxhash(skb); + if (rxq) { + tap = rcu_dereference(vlan->taps[rxq % numvtaps]); + if (tap) + goto out; + } - return rcu_dereference(vlan->tap); + /* Everything failed - find first available queue */ + for (rxq = 0; rxq < MAX_MACVTAP_QUEUES; rxq++) { + tap = rcu_dereference(vlan->taps[rxq]); + if (tap) + break; + } + +out: + return tap; } /* * The net_device is going away, give up the reference - * that it holds on the queue (all the queues one day) - * and safely set the pointer from the queues to NULL. + * that it holds on all queues and safely set the pointer + * from the queues to NULL. */ static void macvtap_del_queues(struct net_device *dev) { struct macvlan_dev *vlan = netdev_priv(dev); - struct macvtap_queue *q; + struct macvtap_queue *q, *qlist[MAX_MACVTAP_QUEUES]; + int i, j = 0; + /* macvtap_put_queue can free some slots, so go through all slots */ spin_lock(&macvtap_lock); - q = rcu_dereference(vlan->tap); - if (!q) { - spin_unlock(&macvtap_lock); - return; + for (i = 0; i < MAX_MACVTAP_QUEUES && vlan->numvtaps; i++) { + q = rcu_dereference(vlan->taps[i]); + if (q) { + qlist[j++] = q; + rcu_assign_pointer(vlan->taps[i], NULL); + rcu_assign_pointer(q->vlan, NULL); + vlan->numvtaps--; + } } - - rcu_assign_pointer(vlan->tap, NULL); - rcu_assign_pointer(q->vlan, NULL); + BUG_ON(vlan->numvtaps != 0); spin_unlock(&macvtap_lock); synchronize_rcu(); - sock_put(&q->sk); + + for (--j; j >= 0; j--) + sock_put(&qlist[j]->sk); } /* diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 35280b302290..8a2fd66a8b5f 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -40,6 +40,12 @@ struct macvlan_rx_stats { unsigned long rx_errors; }; +/* + * Maximum times a macvtap device can be opened. This can be used to + * configure the number of receive queue, e.g. for multiqueue virtio. + */ +#define MAX_MACVTAP_QUEUES (NR_CPUS < 16 ? NR_CPUS : 16) + struct macvlan_dev { struct net_device *dev; struct list_head list; @@ -50,7 +56,8 @@ struct macvlan_dev { enum macvlan_mode mode; int (*receive)(struct sk_buff *skb); int (*forward)(struct net_device *dev, struct sk_buff *skb); - struct macvtap_queue *tap; + struct macvtap_queue *taps[MAX_MACVTAP_QUEUES]; + int numvtaps; }; static inline void macvlan_count_rx(const struct macvlan_dev *vlan, -- cgit v1.2.3-59-g8ed1b From 354c8e3104a8513dbbdc4dea1ffbefe714371e88 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 10:17:00 +0000 Subject: drivers/net/wan: Adjust confusing if indentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Indent the branch of an if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Acked-by: Krzysztof HaÅ‚asa Signed-off-by: David S. Miller --- drivers/net/wan/c101.c | 2 +- drivers/net/wan/n2.c | 2 +- drivers/net/wan/pci200syn.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c index 0bd898c94759..4ac85a09c5a6 100644 --- a/drivers/net/wan/c101.c +++ b/drivers/net/wan/c101.c @@ -264,7 +264,7 @@ static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) new_line.clock_type != CLOCK_TXFROMRX && new_line.clock_type != CLOCK_INT && new_line.clock_type != CLOCK_TXINT) - return -EINVAL; /* No such clock setting */ + return -EINVAL; /* No such clock setting */ if (new_line.loopback != 0 && new_line.loopback != 1) return -EINVAL; diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index 5394b51bdb2f..7a3720f09ce3 100644 --- a/drivers/net/wan/n2.c +++ b/drivers/net/wan/n2.c @@ -282,7 +282,7 @@ static int n2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) new_line.clock_type != CLOCK_TXFROMRX && new_line.clock_type != CLOCK_INT && new_line.clock_type != CLOCK_TXINT) - return -EINVAL; /* No such clock setting */ + return -EINVAL; /* No such clock setting */ if (new_line.loopback != 0 && new_line.loopback != 1) return -EINVAL; diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index e2cff64a446a..fd7375955e41 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -220,7 +220,7 @@ static int pci200_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) new_line.clock_type != CLOCK_TXFROMRX && new_line.clock_type != CLOCK_INT && new_line.clock_type != CLOCK_TXINT) - return -EINVAL; /* No such clock setting */ + return -EINVAL; /* No such clock setting */ if (new_line.loopback != 0 && new_line.loopback != 1) return -EINVAL; -- cgit v1.2.3-59-g8ed1b From 510a05edce43ec29ceb105677ad8e6ff58f02c72 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 10:19:00 +0000 Subject: net/atm: Adjust confusing if indentation Outdent the code following an if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- net/atm/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/atm/common.c b/net/atm/common.c index 940404a73b3d..1b9c52a02cd3 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -792,7 +792,7 @@ int vcc_getsockopt(struct socket *sock, int level, int optname, default: if (level == SOL_SOCKET) return -EINVAL; - break; + break; } if (!vcc->dev || !vcc->dev->ops->getsockopt) return -EINVAL; -- cgit v1.2.3-59-g8ed1b From 9b0f1d85968334c9bbe8675a0fc676c6e15ba577 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 10:22:00 +0000 Subject: drivers/net/irda: Adjust confusing if indentation Indent the branch of an if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/irda/mcs7780.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c index 5b1036ac38d7..74b20f179cea 100644 --- a/drivers/net/irda/mcs7780.c +++ b/drivers/net/irda/mcs7780.c @@ -734,7 +734,7 @@ static int mcs_net_open(struct net_device *netdev) } if (!mcs_setup_urbs(mcs)) - goto error3; + goto error3; ret = mcs_receive_start(mcs); if (ret) -- cgit v1.2.3-59-g8ed1b From 022484c17253aea84aa2603068ea065ca59bb5e5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 10:22:20 +0000 Subject: drivers/net: Adjust confusing if indentation In amd8111e.c, indent the branch of an if. In eepro.c, outdent the code following the if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/amd8111e.c | 4 ++-- drivers/net/eepro.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 585c25f4b60c..1f5fc64b3224 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -396,7 +396,7 @@ static int amd8111e_set_coalesce(struct net_device * dev, enum coal_mode cmod) event_count = coal_conf->rx_event_count; if( timeout > MAX_TIMEOUT || event_count > MAX_EVENT_COUNT ) - return -EINVAL; + return -EINVAL; timeout = timeout * DELAY_TIMER_CONV; writel(VAL0|STINTEN, mmio+INTEN0); @@ -409,7 +409,7 @@ static int amd8111e_set_coalesce(struct net_device * dev, enum coal_mode cmod) event_count = coal_conf->tx_event_count; if( timeout > MAX_TIMEOUT || event_count > MAX_EVENT_COUNT ) - return -EINVAL; + return -EINVAL; timeout = timeout * DELAY_TIMER_CONV; diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 8d97f168f018..7c826319ee5a 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -1457,11 +1457,11 @@ hardware_send_packet(struct net_device *dev, void *buf, short length) if (net_debug > 5) printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name); - /* determine how much of the transmit buffer space is available */ - if (lp->tx_end > lp->tx_start) + /* determine how much of the transmit buffer space is available */ + if (lp->tx_end > lp->tx_start) tx_available = lp->xmt_ram - (lp->tx_end - lp->tx_start); - else if (lp->tx_end < lp->tx_start) - tx_available = lp->tx_start - lp->tx_end; + else if (lp->tx_end < lp->tx_start) + tx_available = lp->tx_start - lp->tx_end; else tx_available = lp->xmt_ram; if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) { -- cgit v1.2.3-59-g8ed1b From 6f74dbbc29df6f53bc0deaa8e5a6ff81a4f91534 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 10:25:24 +0000 Subject: drivers/atm: Adjust confusing if indentation Indent the branch of an if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/atm/iphase.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index ee9ddeb53417..8b358d7d958f 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -220,7 +220,7 @@ static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) { while (!desc_num || (dev->desc_tbl[desc_num -1]).timestamp) { dev->ffL.tcq_rd += 2; if (dev->ffL.tcq_rd > dev->ffL.tcq_ed) - dev->ffL.tcq_rd = dev->ffL.tcq_st; + dev->ffL.tcq_rd = dev->ffL.tcq_st; if (dev->ffL.tcq_rd == dev->host_tcq_wr) return 0xFFFF; desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd); -- cgit v1.2.3-59-g8ed1b From 2145f1afc6b2abe97d983e90c53a1dc17e2da831 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 10:26:20 +0000 Subject: drivers/net: Adjust confusing if indentation Outdent the code following the if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 4f7c3f3ca234..3d9f958ebd2c 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1859,7 +1859,7 @@ static int register_grp_irqs(struct gfar_priv_grp *grp) printk(KERN_ERR "%s: Can't get IRQ %d\n", dev->name, grp->interruptError); - goto err_irq_fail; + goto err_irq_fail; } if ((err = request_irq(grp->interruptTransmit, gfar_transmit, -- cgit v1.2.3-59-g8ed1b From cc81735e8099deaed7436418f6d83a98be2c2101 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 10:26:38 +0000 Subject: drivers/net/bnx2x: Adjust confusing if indentation Outdent the code following the if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Acked-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_link.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index 0383e3066313..0fa09913051d 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c @@ -1254,11 +1254,11 @@ static void bnx2x_set_autoneg(struct link_params *params, PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX; - CL45_WR_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_CL73_IEEEB1, - MDIO_CL73_IEEEB1_AN_ADV2, - reg_val); + CL45_WR_OVER_CL22(bp, params->port, + params->phy_addr, + MDIO_REG_BANK_CL73_IEEEB1, + MDIO_CL73_IEEEB1_AN_ADV2, + reg_val); /* CL73 Autoneg Enabled */ reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN; -- cgit v1.2.3-59-g8ed1b From 1f1d47ef4779fb45e8cccde6f31c76c3cdabbec1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 10:28:12 +0000 Subject: drivers/net/hamradio: Adjust confusing if indentation Indent the branch of an if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/hamradio/scc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index 9f64c8637208..33655814448e 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c @@ -1069,7 +1069,8 @@ static void scc_tx_done(struct scc_channel *scc) case KISS_DUPLEX_LINK: scc->stat.tx_state = TXS_IDLE2; if (scc->kiss.idletime != TIMER_OFF) - scc_start_tx_timer(scc, t_idle, scc->kiss.idletime*100); + scc_start_tx_timer(scc, t_idle, + scc->kiss.idletime*100); break; case KISS_DUPLEX_OPTIMA: scc_notify(scc, HWEV_ALL_SENT); -- cgit v1.2.3-59-g8ed1b From 9e1634a734bdd2dac5687f57dd427bef083e4659 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 10:28:31 +0000 Subject: drivers/net: Adjust confusing if indentation Outdent the code following the if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/cpmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index e1f6156b3710..ac3985ceb5f7 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -506,7 +506,7 @@ static int cpmac_poll(struct napi_struct *napi, int budget) "restart rx from a descriptor that's " "not free: %p\n", priv->dev->name, restart); - goto fatal_error; + goto fatal_error; } cpmac_write(priv->regs, CPMAC_RX_PTR(0), restart->mapping); -- cgit v1.2.3-59-g8ed1b From f7df0b8d924ad2f39852ea397d39a51fbb955212 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 10:29:19 +0000 Subject: drivers/isdn: Adjust confusing if indentation In hisax/hfc_sx.c and mISDN/l1oip_core.c, the code after the if is outdented so that it is not aligned with the if branch. In mISDN/dsp_cmx.c, an else is added between the original if branch and the following statement, in line with the code following it. Without this change, the first assignment to dsp->rx_W has no useful effect. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/isdn/hisax/hfc_sx.c | 13 +++++++------ drivers/isdn/mISDN/dsp_cmx.c | 1 + drivers/isdn/mISDN/l1oip_core.c | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c index be5faf4aa868..5aa138eb0b3c 100644 --- a/drivers/isdn/hisax/hfc_sx.c +++ b/drivers/isdn/hisax/hfc_sx.c @@ -234,13 +234,14 @@ read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max) count++; if (count > trans_max) count = trans_max; /* limit length */ - if ((skb = dev_alloc_skb(count))) { - dst = skb_put(skb, count); - while (count--) + skb = dev_alloc_skb(count); + if (skb) { + dst = skb_put(skb, count); + while (count--) *dst++ = Read_hfc(cs, HFCSX_FIF_DRD); - return(skb); - } - else return(NULL); /* no memory */ + return skb; + } else + return NULL; /* no memory */ } do { diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c index 713ef2b805a2..76d9e673b4e1 100644 --- a/drivers/isdn/mISDN/dsp_cmx.c +++ b/drivers/isdn/mISDN/dsp_cmx.c @@ -1237,6 +1237,7 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb) if (dsp->cmx_delay) dsp->rx_W = (dsp->rx_R + dsp->cmx_delay) & CMX_BUFF_MASK; + else dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1)) & CMX_BUFF_MASK; } else { diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 22f38e48ac4e..5b59796ed250 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -972,7 +972,7 @@ channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq) if (debug & DEBUG_L1OIP_SOCKET) printk(KERN_DEBUG "%s: got new ip address from user " "space.\n", __func__); - l1oip_socket_open(hc); + l1oip_socket_open(hc); break; case MISDN_CTRL_UNSETPEER: if (debug & DEBUG_L1OIP_SOCKET) -- cgit v1.2.3-59-g8ed1b From bb8a10bbd10a45db0eb45bac520489bdbc0917ef Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Aug 2010 10:29:38 +0000 Subject: net/decnet: Adjust confusing if indentation Indent the branch of an if. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r disable braces4@ position p1,p2; statement S1,S2; @@ ( if (...) { ... } | if (...) S1@p1 S2@p2 ) @script:python@ p1 << r.p1; p2 << r.p2; @@ if (p1[0].column == p2[0].column): cocci.print_main("branch",p1) cocci.print_secs("after",p2) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- net/decnet/dn_nsp_out.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c index baeb1eaf011b..2ef115277bea 100644 --- a/net/decnet/dn_nsp_out.c +++ b/net/decnet/dn_nsp_out.c @@ -693,22 +693,22 @@ void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg) aux = scp->accessdata.acc_userl; *skb_put(skb, 1) = aux; if (aux > 0) - memcpy(skb_put(skb, aux), scp->accessdata.acc_user, aux); + memcpy(skb_put(skb, aux), scp->accessdata.acc_user, aux); aux = scp->accessdata.acc_passl; *skb_put(skb, 1) = aux; if (aux > 0) - memcpy(skb_put(skb, aux), scp->accessdata.acc_pass, aux); + memcpy(skb_put(skb, aux), scp->accessdata.acc_pass, aux); aux = scp->accessdata.acc_accl; *skb_put(skb, 1) = aux; if (aux > 0) - memcpy(skb_put(skb, aux), scp->accessdata.acc_acc, aux); + memcpy(skb_put(skb, aux), scp->accessdata.acc_acc, aux); aux = (__u8)le16_to_cpu(scp->conndata_out.opt_optl); *skb_put(skb, 1) = aux; if (aux > 0) - memcpy(skb_put(skb,aux), scp->conndata_out.opt_data, aux); + memcpy(skb_put(skb, aux), scp->conndata_out.opt_data, aux); scp->persist = dn_nsp_persist(sk); scp->persist_fxn = dn_nsp_retrans_conninit; -- cgit v1.2.3-59-g8ed1b From 01414802054c382072b6cb9a1bdc6e243c74b2d5 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 17 Aug 2010 02:31:15 -0700 Subject: ethtool: Provide a default implementation of ethtool_ops::get_drvinfo The driver name and bus address for a net_device can normally be found through the driver model now. Instead of requiring drivers to provide this information redundantly through the ethtool_ops::get_drvinfo operation, use the driver model to do so if the driver does not define the operation. Since ETHTOOL_GDRVINFO no longer requires the driver to implement any operations, do not require net_device::ethtool_ops to be set either. Remove implementations of get_drvinfo and ethtool_ops that provide only this information. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/firewire/net.c | 13 ------------- drivers/ieee1394/eth1394.c | 16 ---------------- drivers/net/bmac.c | 7 ------- drivers/net/fec_mpc52xx.c | 6 ------ drivers/net/pasemi_mac_ethtool.c | 16 ---------------- drivers/net/pcmcia/3c574_cs.c | 13 ------------- drivers/net/pcmcia/axnet_cs.c | 13 ------------- drivers/net/pcmcia/ibmtr_cs.c | 13 ------------- drivers/net/pcmcia/pcnet_cs.c | 16 ---------------- drivers/net/sc92031.c | 11 ----------- drivers/net/tulip/xircom_cb.c | 15 --------------- drivers/net/usb/hso.c | 9 --------- drivers/net/usb/kaweth.c | 9 --------- drivers/net/virtio_net.c | 14 -------------- drivers/net/wireless/ray_cs.c | 16 ---------------- drivers/net/wireless/wl3501_cs.c | 11 ----------- net/core/ethtool.c | 33 +++++++++++++++++++++++---------- 17 files changed, 23 insertions(+), 208 deletions(-) diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index da17d409a244..51e8a35ebd7e 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -1359,17 +1358,6 @@ static int fwnet_change_mtu(struct net_device *net, int new_mtu) return 0; } -static void fwnet_get_drvinfo(struct net_device *net, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, KBUILD_MODNAME); - strcpy(info->bus_info, "ieee1394"); -} - -static const struct ethtool_ops fwnet_ethtool_ops = { - .get_drvinfo = fwnet_get_drvinfo, -}; - static const struct net_device_ops fwnet_netdev_ops = { .ndo_open = fwnet_open, .ndo_stop = fwnet_stop, @@ -1388,7 +1376,6 @@ static void fwnet_init_dev(struct net_device *net) net->hard_header_len = FWNET_HLEN; net->type = ARPHRD_IEEE1394; net->tx_queue_len = 10; - SET_ETHTOOL_OPS(net, &fwnet_ethtool_ops); } /* caller must hold fwnet_device_mutex */ diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index bc289e367e30..63403822330e 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -58,7 +58,6 @@ #include #include #include -#include #include #include #include @@ -173,8 +172,6 @@ static netdev_tx_t ether1394_tx(struct sk_buff *skb, struct net_device *dev); static void ether1394_iso(struct hpsb_iso *iso); -static const struct ethtool_ops ethtool_ops; - static int ether1394_write(struct hpsb_host *host, int srcid, int destid, quadlet_t *data, u64 addr, size_t len, u16 flags); static void ether1394_add_host(struct hpsb_host *host); @@ -525,8 +522,6 @@ static void ether1394_init_dev(struct net_device *dev) dev->header_ops = ðer1394_header_ops; dev->netdev_ops = ðer1394_netdev_ops; - SET_ETHTOOL_OPS(dev, ðtool_ops); - dev->watchdog_timeo = ETHER1394_TIMEOUT; dev->flags = IFF_BROADCAST | IFF_MULTICAST; dev->features = NETIF_F_HIGHDMA; @@ -1695,17 +1690,6 @@ fail: return NETDEV_TX_OK; } -static void ether1394_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, driver_name); - strcpy(info->bus_info, "ieee1394"); /* FIXME provide more detail? */ -} - -static const struct ethtool_ops ethtool_ops = { - .get_drvinfo = ether1394_get_drvinfo -}; - static int __init ether1394_init_module(void) { int err; diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 959add2410bf..9322699bb31c 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1233,15 +1233,8 @@ static void bmac_reset_and_enable(struct net_device *dev) } spin_unlock_irqrestore(&bp->lock, flags); } -static void bmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct bmac_data *bp = netdev_priv(dev); - strcpy(info->driver, "bmac"); - strcpy(info->bus_info, dev_name(&bp->mdev->ofdev.dev)); -} static const struct ethtool_ops bmac_ethtool_ops = { - .get_drvinfo = bmac_get_drvinfo, .get_link = ethtool_op_get_link, }; diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index e3e10b4add9c..e9f5d030bc26 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -771,11 +771,6 @@ static void mpc52xx_fec_reset(struct net_device *dev) /* ethtool interface */ -static void mpc52xx_fec_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, DRIVER_NAME); -} static int mpc52xx_fec_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { @@ -810,7 +805,6 @@ static void mpc52xx_fec_set_msglevel(struct net_device *dev, u32 level) } static const struct ethtool_ops mpc52xx_fec_ethtool_ops = { - .get_drvinfo = mpc52xx_fec_get_drvinfo, .get_settings = mpc52xx_fec_get_settings, .set_settings = mpc52xx_fec_set_settings, .get_link = ethtool_op_get_link, diff --git a/drivers/net/pasemi_mac_ethtool.c b/drivers/net/pasemi_mac_ethtool.c index fefa79e34b95..4825959a0efe 100644 --- a/drivers/net/pasemi_mac_ethtool.c +++ b/drivers/net/pasemi_mac_ethtool.c @@ -90,21 +90,6 @@ pasemi_mac_ethtool_set_settings(struct net_device *netdev, return phy_ethtool_sset(phydev, cmd); } -static void -pasemi_mac_ethtool_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct pasemi_mac *mac; - mac = netdev_priv(netdev); - - /* clear and fill out info */ - memset(drvinfo, 0, sizeof(struct ethtool_drvinfo)); - strncpy(drvinfo->driver, "pasemi_mac", 12); - strcpy(drvinfo->version, "N/A"); - strcpy(drvinfo->fw_version, "N/A"); - strncpy(drvinfo->bus_info, pci_name(mac->pdev), 32); -} - static u32 pasemi_mac_ethtool_get_msglevel(struct net_device *netdev) { @@ -164,7 +149,6 @@ static void pasemi_mac_get_strings(struct net_device *netdev, u32 stringset, const struct ethtool_ops pasemi_mac_ethtool_ops = { .get_settings = pasemi_mac_ethtool_get_settings, .set_settings = pasemi_mac_ethtool_set_settings, - .get_drvinfo = pasemi_mac_ethtool_get_drvinfo, .get_msglevel = pasemi_mac_ethtool_get_msglevel, .set_msglevel = pasemi_mac_ethtool_set_msglevel, .get_link = ethtool_op_get_link, diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index c683f77c6f42..9a1840b67e78 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -83,7 +83,6 @@ earlier 3Com products. #include #include #include -#include #include #include @@ -238,7 +237,6 @@ static int el3_rx(struct net_device *dev, int worklimit); static int el3_close(struct net_device *dev); static void el3_tx_timeout(struct net_device *dev); static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static const struct ethtool_ops netdev_ethtool_ops; static void set_rx_mode(struct net_device *dev); static void set_multicast_list(struct net_device *dev); @@ -285,7 +283,6 @@ static int tc574_probe(struct pcmcia_device *link) link->conf.ConfigIndex = 1; dev->netdev_ops = &el3_netdev_ops; - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); dev->watchdog_timeo = TX_TIMEOUT; return tc574_config(link); @@ -1065,16 +1062,6 @@ static int el3_rx(struct net_device *dev, int worklimit) return worklimit; } -static void netdev_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, "3c574_cs"); -} - -static const struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, -}; - /* Provide ioctl() calls to examine the MII xcvr state. */ static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 5f05ffb240cc..a6e37b29e3bf 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -86,7 +85,6 @@ static netdev_tx_t axnet_start_xmit(struct sk_buff *skb, static struct net_device_stats *get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static void axnet_tx_timeout(struct net_device *dev); -static const struct ethtool_ops netdev_ethtool_ops; static irqreturn_t ei_irq_wrapper(int irq, void *dev_id); static void ei_watchdog(u_long arg); static void axnet_reset_8390(struct net_device *dev); @@ -171,7 +169,6 @@ static int axnet_probe(struct pcmcia_device *link) dev->netdev_ops = &axnet_netdev_ops; - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); dev->watchdog_timeo = TX_TIMEOUT; return axnet_config(link); @@ -658,16 +655,6 @@ reschedule: add_timer(&info->watchdog); } -static void netdev_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, "axnet_cs"); -} - -static const struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, -}; - /*====================================================================*/ static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index b0d06a3d962f..cbcda123b1bf 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -52,7 +52,6 @@ #include #include #include -#include #include #include #include @@ -107,16 +106,6 @@ typedef struct ibmtr_dev_t { struct tok_info *ti; } ibmtr_dev_t; -static void netdev_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, "ibmtr_cs"); -} - -static const struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, -}; - static irqreturn_t ibmtr_interrupt(int irq, void *dev_id) { ibmtr_dev_t *info = dev_id; struct net_device *dev = info->dev; @@ -159,8 +148,6 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link) info->dev = dev; - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - return ibmtr_config(link); } /* ibmtr_attach */ diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index c3edfe4c2651..2e1348c0033e 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -100,7 +99,6 @@ static void pcnet_release(struct pcmcia_device *link); static int pcnet_open(struct net_device *dev); static int pcnet_close(struct net_device *dev); static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static const struct ethtool_ops netdev_ethtool_ops; static irqreturn_t ei_irq_wrapper(int irq, void *dev_id); static void ei_watchdog(u_long arg); static void pcnet_reset_8390(struct net_device *dev); @@ -628,8 +626,6 @@ static int pcnet_config(struct pcmcia_device *link) ei_status.word16 = 1; ei_status.reset_8390 = &pcnet_reset_8390; - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - if (info->flags & (IS_DL10019|IS_DL10022)) mii_phy_probe(dev); @@ -1143,18 +1139,6 @@ reschedule: /*====================================================================*/ -static void netdev_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, "pcnet_cs"); -} - -static const struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, -}; - -/*====================================================================*/ - static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 8c4067af32b0..31b92f5f32cb 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -1251,16 +1251,6 @@ static int sc92031_ethtool_set_settings(struct net_device *dev, return 0; } -static void sc92031_ethtool_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *drvinfo) -{ - struct sc92031_priv *priv = netdev_priv(dev); - struct pci_dev *pdev = priv->pdev; - - strcpy(drvinfo->driver, SC92031_NAME); - strcpy(drvinfo->bus_info, pci_name(pdev)); -} - static void sc92031_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo) { @@ -1382,7 +1372,6 @@ static void sc92031_ethtool_get_ethtool_stats(struct net_device *dev, static const struct ethtool_ops sc92031_ethtool_ops = { .get_settings = sc92031_ethtool_get_settings, .set_settings = sc92031_ethtool_set_settings, - .get_drvinfo = sc92031_ethtool_get_drvinfo, .get_wol = sc92031_ethtool_get_wol, .set_wol = sc92031_ethtool_set_wol, .nway_reset = sc92031_ethtool_nway_reset, diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index a439e93be22d..5a73752be2ca 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -181,19 +180,6 @@ static void print_binary(unsigned int number) } #endif -static void netdev_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct xircom_private *private = netdev_priv(dev); - - strcpy(info->driver, "xircom_cb"); - strcpy(info->bus_info, pci_name(private->pdev)); -} - -static const struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, -}; - static const struct net_device_ops netdev_ops = { .ndo_open = xircom_open, .ndo_stop = xircom_close, @@ -279,7 +265,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ setup_descriptors(private); dev->netdev_ops = &netdev_ops; - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); pci_set_drvdata(pdev, dev); if (register_netdev(dev)) { diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 6efca66b8766..4f123f869bdc 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -843,16 +843,7 @@ static netdev_tx_t hso_net_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } -static void hso_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) -{ - struct hso_net *odev = netdev_priv(net); - - strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN); - usb_make_path(odev->parent->usb, info->bus_info, sizeof info->bus_info); -} - static const struct ethtool_ops ops = { - .get_drvinfo = hso_get_drvinfo, .get_link = ethtool_op_get_link }; diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 2b7b39cad1ce..5e98643a4a21 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -759,14 +759,6 @@ static int kaweth_close(struct net_device *net) return 0; } -static void kaweth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct kaweth_device *kaweth = netdev_priv(dev); - - strlcpy(info->driver, driver_name, sizeof(info->driver)); - usb_make_path(kaweth->dev, info->bus_info, sizeof (info->bus_info)); -} - static u32 kaweth_get_link(struct net_device *dev) { struct kaweth_device *kaweth = netdev_priv(dev); @@ -775,7 +767,6 @@ static u32 kaweth_get_link(struct net_device *dev) } static const struct ethtool_ops ops = { - .get_drvinfo = kaweth_get_drvinfo, .get_link = kaweth_get_link }; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 4598e9d2608f..bb6b67f6b0cc 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -705,19 +705,6 @@ static int virtnet_close(struct net_device *dev) return 0; } -static void virtnet_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *drvinfo) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct virtio_device *vdev = vi->vdev; - - strncpy(drvinfo->driver, KBUILD_MODNAME, ARRAY_SIZE(drvinfo->driver)); - strncpy(drvinfo->version, "N/A", ARRAY_SIZE(drvinfo->version)); - strncpy(drvinfo->fw_version, "N/A", ARRAY_SIZE(drvinfo->fw_version)); - strncpy(drvinfo->bus_info, dev_name(&vdev->dev), - ARRAY_SIZE(drvinfo->bus_info)); -} - static int virtnet_set_tx_csum(struct net_device *dev, u32 data) { struct virtnet_info *vi = netdev_priv(dev); @@ -830,7 +817,6 @@ static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) } static const struct ethtool_ops virtnet_ethtool_ops = { - .get_drvinfo = virtnet_get_drvinfo, .set_tx_csum = virtnet_set_tx_csum, .set_sg = ethtool_op_set_sg, .set_tso = ethtool_op_set_tso, diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 88560d0ae50a..3bd9cf76517d 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include @@ -80,8 +79,6 @@ static int ray_dev_config(struct net_device *dev, struct ifmap *map); static struct net_device_stats *ray_get_stats(struct net_device *dev); static int ray_dev_init(struct net_device *dev); -static const struct ethtool_ops netdev_ethtool_ops; - static int ray_open(struct net_device *dev); static netdev_tx_t ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev); @@ -333,7 +330,6 @@ static int ray_probe(struct pcmcia_device *p_dev) /* Raylink entries in the device structure */ dev->netdev_ops = &ray_netdev_ops; - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); dev->wireless_handlers = &ray_handler_def; #ifdef WIRELESS_SPY local->wireless_data.spy_data = &local->spy_data; @@ -1062,18 +1058,6 @@ AP to AP 1 1 dest AP src AP dest source } } /* end encapsulate_frame */ -/*===========================================================================*/ - -static void netdev_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, "ray_cs"); -} - -static const struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, -}; - /*====================================================================*/ /*------------------------------------------------------------------*/ diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index a1cc2d498a1c..420e9e986a18 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -1411,15 +1410,6 @@ static struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev) return wstats; } -static void wl3501_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - strlcpy(info->driver, "wl3501_cs", sizeof(info->driver)); -} - -static const struct ethtool_ops ops = { - .get_drvinfo = wl3501_get_drvinfo -}; - /** * wl3501_detach - deletes a driver "instance" * @link - FILL_IN @@ -1905,7 +1895,6 @@ static int wl3501_probe(struct pcmcia_device *p_dev) this->p_dev = p_dev; dev->wireless_data = &this->wireless_data; dev->wireless_handlers = &wl3501_handler_def; - SET_ETHTOOL_OPS(dev, &ops); netif_stop_queue(dev); p_dev->priv = dev; diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 7a85367b3c2f..d2c4da5a6a4f 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -205,18 +205,24 @@ static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo info; const struct ethtool_ops *ops = dev->ethtool_ops; - if (!ops->get_drvinfo) - return -EOPNOTSUPP; - memset(&info, 0, sizeof(info)); info.cmd = ETHTOOL_GDRVINFO; - ops->get_drvinfo(dev, &info); + if (ops && ops->get_drvinfo) { + ops->get_drvinfo(dev, &info); + } else if (dev->dev.parent && dev->dev.parent->driver) { + strlcpy(info.bus_info, dev_name(dev->dev.parent), + sizeof(info.bus_info)); + strlcpy(info.driver, dev->dev.parent->driver->name, + sizeof(info.driver)); + } else { + return -EOPNOTSUPP; + } /* * this method of obtaining string set info is deprecated; * Use ETHTOOL_GSSET_INFO instead. */ - if (ops->get_sset_count) { + if (ops && ops->get_sset_count) { int rc; rc = ops->get_sset_count(dev, ETH_SS_TEST); @@ -229,9 +235,9 @@ static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev, if (rc >= 0) info.n_priv_flags = rc; } - if (ops->get_regs_len) + if (ops && ops->get_regs_len) info.regdump_len = ops->get_regs_len(dev); - if (ops->get_eeprom_len) + if (ops && ops->get_eeprom_len) info.eedump_len = ops->get_eeprom_len(dev); if (copy_to_user(useraddr, &info, sizeof(info))) @@ -1402,12 +1408,19 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) if (!dev || !netif_device_present(dev)) return -ENODEV; - if (!dev->ethtool_ops) - return -EOPNOTSUPP; - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) return -EFAULT; + if (!dev->ethtool_ops) { + /* ETHTOOL_GDRVINFO does not require any driver support. + * It is also unprivileged and does not change anything, + * so we can take a shortcut to it. */ + if (ethcmd == ETHTOOL_GDRVINFO) + return ethtool_get_drvinfo(dev, useraddr); + else + return -EOPNOTSUPP; + } + /* Allow some commands to be done by anyone */ switch (ethcmd) { case ETHTOOL_GDRVINFO: -- cgit v1.2.3-59-g8ed1b From ea0a52c4fd8eb2c8e0586b939c484e160fb4a721 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 8 Aug 2010 02:32:05 +0000 Subject: pcnet_cs: Use proper netdev_*-printouts To prevent broken messages like: [ 204.024291] eth%d: pcnet_reset_8390() did not complete. Signed-off-by: Wolfram Sang Cc: Dominik Brodowski Cc: Joe Perches Cc: David Miller Signed-off-by: David S. Miller --- drivers/net/pcmcia/pcnet_cs.c | 58 ++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 2e1348c0033e..296f8a8e57ca 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -638,12 +638,12 @@ static int pcnet_config(struct pcmcia_device *link) if (info->flags & (IS_DL10019|IS_DL10022)) { u_char id = inb(dev->base_addr + 0x1a); - printk(KERN_INFO "%s: NE2000 (DL100%d rev %02x): ", - dev->name, ((info->flags & IS_DL10022) ? 22 : 19), id); + netdev_info(dev, "NE2000 (DL100%d rev %02x): ", + (info->flags & IS_DL10022) ? 22 : 19, id); if (info->pna_phy) printk("PNA, "); } else { - printk(KERN_INFO "%s: NE2000 Compatible: ", dev->name); + netdev_info(dev, "NE2000 Compatible: "); } printk("io %#3lx, irq %d,", dev->base_addr, dev->irq); if (info->flags & USE_SHMEM) @@ -924,7 +924,7 @@ static void mii_phy_probe(struct net_device *dev) phyid = tmp << 16; phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2); phyid &= MII_PHYID_REV_MASK; - pr_debug("%s: MII at %d is 0x%08x\n", dev->name, i, phyid); + netdev_dbg(dev, "MII at %d is 0x%08x\n", i, phyid); if (phyid == AM79C9XX_HOME_PHY) { info->pna_phy = i; } else if (phyid != AM79C9XX_ETH_PHY) { @@ -1010,8 +1010,8 @@ static void pcnet_reset_8390(struct net_device *dev) outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */ if (i == 100) - printk(KERN_ERR "%s: pcnet_reset_8390() did not complete.\n", - dev->name); + netdev_err(dev, "pcnet_reset_8390() did not complete.\n"); + set_misc_reg(dev); } /* pcnet_reset_8390 */ @@ -1027,8 +1027,7 @@ static int set_config(struct net_device *dev, struct ifmap *map) else if ((map->port < 1) || (map->port > 2)) return -EINVAL; dev->if_port = map->port; - printk(KERN_INFO "%s: switched to %s port\n", - dev->name, if_names[dev->if_port]); + netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]); NS8390_init(dev, 1); } return 0; @@ -1063,7 +1062,7 @@ static void ei_watchdog(u_long arg) this, we can limp along even if the interrupt is blocked */ if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) { if (!info->fast_poll) - printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); + netdev_info(dev, "interrupt(s) dropped!\n"); ei_irq_wrapper(dev->irq, dev); info->fast_poll = HZ; } @@ -1083,7 +1082,7 @@ static void ei_watchdog(u_long arg) if (info->eth_phy) { info->phy_id = info->eth_phy = 0; } else { - printk(KERN_INFO "%s: MII is missing!\n", dev->name); + netdev_info(dev, "MII is missing!\n"); info->flags &= ~HAS_MII; } goto reschedule; @@ -1092,8 +1091,7 @@ static void ei_watchdog(u_long arg) link &= 0x0004; if (link != info->link_status) { u_short p = mdio_read(mii_addr, info->phy_id, 5); - printk(KERN_INFO "%s: %s link beat\n", dev->name, - (link) ? "found" : "lost"); + netdev_info(dev, "%s link beat\n", link ? "found" : "lost"); if (link && (info->flags & IS_DL10022)) { /* Disable collision detection on full duplex links */ outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG); @@ -1104,13 +1102,12 @@ static void ei_watchdog(u_long arg) if (link) { if (info->phy_id == info->eth_phy) { if (p) - printk(KERN_INFO "%s: autonegotiation complete: " - "%sbaseT-%cD selected\n", dev->name, + netdev_info(dev, "autonegotiation complete: " + "%sbaseT-%cD selected\n", ((p & 0x0180) ? "100" : "10"), ((p & 0x0140) ? 'F' : 'H')); else - printk(KERN_INFO "%s: link partner did not " - "autonegotiate\n", dev->name); + netdev_info(dev, "link partner did not autonegotiate\n"); } NS8390_init(dev, 1); } @@ -1123,7 +1120,7 @@ static void ei_watchdog(u_long arg) /* isolate this MII and try flipping to the other one */ mdio_write(mii_addr, info->phy_id, 0, 0x0400); info->phy_id ^= info->pna_phy ^ info->eth_phy; - printk(KERN_INFO "%s: switched to %s transceiver\n", dev->name, + netdev_info(dev, "switched to %s transceiver\n", (info->phy_id == info->eth_phy) ? "ethernet" : "PNA"); mdio_write(mii_addr, info->phy_id, 0, (info->phy_id == info->eth_phy) ? 0x1000 : 0); @@ -1171,9 +1168,9 @@ static void dma_get_8390_hdr(struct net_device *dev, unsigned int nic_base = dev->base_addr; if (ei_status.dmaing) { - printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input." + netdev_notice(dev, "DMAing conflict in dma_block_input." "[DMAstat:%1x][irqlock:%1x]\n", - dev->name, ei_status.dmaing, ei_status.irqlock); + ei_status.dmaing, ei_status.irqlock); return; } @@ -1204,11 +1201,11 @@ static void dma_block_input(struct net_device *dev, int count, char *buf = skb->data; if ((ei_debug > 4) && (count != 4)) - pr_debug("%s: [bi=%d]\n", dev->name, count+4); + netdev_dbg(dev, "[bi=%d]\n", count+4); if (ei_status.dmaing) { - printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input." + netdev_notice(dev, "DMAing conflict in dma_block_input." "[DMAstat:%1x][irqlock:%1x]\n", - dev->name, ei_status.dmaing, ei_status.irqlock); + ei_status.dmaing, ei_status.irqlock); return; } ei_status.dmaing |= 0x01; @@ -1238,9 +1235,9 @@ static void dma_block_input(struct net_device *dev, int count, break; } while (--tries > 0); if (tries <= 0) - printk(KERN_NOTICE "%s: RX transfer address mismatch," + netdev_notice(dev, "RX transfer address mismatch," "%#4.4x (expected) vs. %#4.4x (actual).\n", - dev->name, ring_offset + xfer_count, addr); + ring_offset + xfer_count, addr); } #endif outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ @@ -1261,7 +1258,7 @@ static void dma_block_output(struct net_device *dev, int count, #ifdef PCMCIA_DEBUG if (ei_debug > 4) - printk(KERN_DEBUG "%s: [bo=%d]\n", dev->name, count); + netdev_dbg(dev, "[bo=%d]\n", count); #endif /* Round the count up for word writes. Do we need to do this? @@ -1270,9 +1267,9 @@ static void dma_block_output(struct net_device *dev, int count, if (count & 0x01) count++; if (ei_status.dmaing) { - printk(KERN_NOTICE "%s: DMAing conflict in dma_block_output." + netdev_notice(dev, "DMAing conflict in dma_block_output." "[DMAstat:%1x][irqlock:%1x]\n", - dev->name, ei_status.dmaing, ei_status.irqlock); + ei_status.dmaing, ei_status.irqlock); return; } ei_status.dmaing |= 0x01; @@ -1309,9 +1306,9 @@ static void dma_block_output(struct net_device *dev, int count, break; } while (--tries > 0); if (tries <= 0) { - printk(KERN_NOTICE "%s: Tx packet transfer address mismatch," + netdev_notice(dev, "Tx packet transfer address mismatch," "%#4.4x (expected) vs. %#4.4x (actual).\n", - dev->name, (start_page << 8) + count, addr); + (start_page << 8) + count, addr); if (retries++ == 0) goto retry; } @@ -1320,8 +1317,7 @@ static void dma_block_output(struct net_device *dev, int count, while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) { - printk(KERN_NOTICE "%s: timeout waiting for Tx RDC.\n", - dev->name); + netdev_notice(dev, "timeout waiting for Tx RDC.\n"); pcnet_reset_8390(dev); NS8390_init(dev, 1); break; -- cgit v1.2.3-59-g8ed1b From 7136e11e0cf520ab3fc7b55a20e60c2ec5ea88e1 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 8 Aug 2010 04:50:36 +0000 Subject: pcnet_cs: Use pr_fmt and pr_ It looks as if the printks in get_ax88190 are incorrect and were duplicated and superceded by a test in pcnet_config, so I removed them. Changed the level of the ax88190 test to KERN_NOTICE to match the other message styles in pcnet_config. Compiled but untested. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/pcmcia/pcnet_cs.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 296f8a8e57ca..1815b2644b96 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -28,6 +28,8 @@ ======================================================================*/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -432,8 +434,6 @@ static hw_info_t *get_ax88190(struct pcmcia_device *link) dev->dev_addr[i] = j & 0xff; dev->dev_addr[i+1] = j >> 8; } - printk(KERN_NOTICE "pcnet_cs: this is an AX88190 card!\n"); - printk(KERN_NOTICE "pcnet_cs: use axnet_cs instead.\n"); return NULL; } @@ -568,15 +568,15 @@ static int pcnet_config(struct pcmcia_device *link) if ((if_port == 1) || (if_port == 2)) dev->if_port = if_port; else - printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n"); + pr_notice("invalid if_port requested\n"); } else { dev->if_port = 0; } if ((link->conf.ConfigBase == 0x03c0) && (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { - printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n"); - printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n"); + pr_notice("this is an AX88190 card!\n"); + pr_notice("use axnet_cs instead.\n"); goto failed; } @@ -591,8 +591,8 @@ static int pcnet_config(struct pcmcia_device *link) local_hw_info = get_hwired(link); if (local_hw_info == NULL) { - printk(KERN_NOTICE "pcnet_cs: unable to read hardware net" - " address for io base %#3lx\n", dev->base_addr); + pr_notice("unable to read hardware net address for io base %#3lx\n", + dev->base_addr); goto failed; } @@ -632,7 +632,7 @@ static int pcnet_config(struct pcmcia_device *link) SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev) != 0) { - printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n"); + pr_notice("register_netdev() failed\n"); goto failed; } @@ -641,16 +641,16 @@ static int pcnet_config(struct pcmcia_device *link) netdev_info(dev, "NE2000 (DL100%d rev %02x): ", (info->flags & IS_DL10022) ? 22 : 19, id); if (info->pna_phy) - printk("PNA, "); + pr_cont("PNA, "); } else { netdev_info(dev, "NE2000 Compatible: "); } - printk("io %#3lx, irq %d,", dev->base_addr, dev->irq); + pr_cont("io %#3lx, irq %d,", dev->base_addr, dev->irq); if (info->flags & USE_SHMEM) - printk (" mem %#5lx,", dev->mem_start); + pr_cont(" mem %#5lx,", dev->mem_start); if (info->flags & HAS_MISC_REG) - printk(" %s xcvr,", if_names[dev->if_port]); - printk(" hw_addr %pM\n", dev->dev_addr); + pr_cont(" %s xcvr,", if_names[dev->if_port]); + pr_cont(" hw_addr %pM\n", dev->dev_addr); return 0; failed: -- cgit v1.2.3-59-g8ed1b From 2154c704c7240379fae4633359e06e8df875c1fd Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sun, 8 Aug 2010 10:08:44 +0000 Subject: r6040: fix all checkpatch errors and warnings This patch fixes a couple of errors and warnings spotted by checkpatch.pl: - some lines were over 80 columns - there were some whitespaces left The call to printk is now replaced by a call to pr_info and the log-level included in the driver version is now removed, so there are no longer false positives on this warning. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/r6040.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 142c381e1d73..0a00850da79d 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -200,7 +200,7 @@ struct r6040_private { int old_duplex; }; -static char version[] __devinitdata = KERN_INFO DRV_NAME +static char version[] __devinitdata = DRV_NAME ": RDC R6040 NAPI net driver," "version "DRV_VERSION " (" DRV_RELDATE ")"; @@ -224,7 +224,8 @@ static int r6040_phy_read(void __iomem *ioaddr, int phy_addr, int reg) } /* Write a word data from PHY Chip */ -static void r6040_phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val) +static void r6040_phy_write(void __iomem *ioaddr, + int phy_addr, int reg, u16 val) { int limit = 2048; u16 cmd; @@ -348,8 +349,8 @@ static int r6040_alloc_rxbufs(struct net_device *dev) } desc->skb_ptr = skb; desc->buf = cpu_to_le32(pci_map_single(lp->pdev, - desc->skb_ptr->data, - MAX_BUF_SIZE, PCI_DMA_FROMDEVICE)); + desc->skb_ptr->data, + MAX_BUF_SIZE, PCI_DMA_FROMDEVICE)); desc->status = DSC_OWNER_MAC; desc = desc->vndescp; } while (desc != lp->rx_ring); @@ -491,12 +492,14 @@ static int r6040_close(struct net_device *dev) /* Free Descriptor memory */ if (lp->rx_ring) { - pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma); + pci_free_consistent(pdev, + RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma); lp->rx_ring = NULL; } if (lp->tx_ring) { - pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma); + pci_free_consistent(pdev, + TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma); lp->tx_ring = NULL; } @@ -547,7 +550,7 @@ static int r6040_rx(struct net_device *dev, int limit) } goto next_descr; } - + /* Packet successfully received */ new_skb = netdev_alloc_skb(dev, MAX_BUF_SIZE); if (!new_skb) { @@ -556,13 +559,13 @@ static int r6040_rx(struct net_device *dev, int limit) } skb_ptr = descptr->skb_ptr; skb_ptr->dev = priv->dev; - + /* Do not count the CRC */ skb_put(skb_ptr, descptr->len - 4); pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf), MAX_BUF_SIZE, PCI_DMA_FROMDEVICE); skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev); - + /* Send to upper layer */ netif_receive_skb(skb_ptr); dev->stats.rx_packets++; @@ -710,8 +713,10 @@ static int r6040_up(struct net_device *dev) return ret; /* improve performance (by RDC guys) */ - r6040_phy_write(ioaddr, 30, 17, (r6040_phy_read(ioaddr, 30, 17) | 0x4000)); - r6040_phy_write(ioaddr, 30, 17, ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000)); + r6040_phy_write(ioaddr, 30, 17, + (r6040_phy_read(ioaddr, 30, 17) | 0x4000)); + r6040_phy_write(ioaddr, 30, 17, + ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000)); r6040_phy_write(ioaddr, 0, 19, 0x0000); r6040_phy_write(ioaddr, 0, 30, 0x01F0); @@ -946,7 +951,7 @@ static const struct net_device_ops r6040_netdev_ops = { .ndo_set_multicast_list = r6040_multicast_list, .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_do_ioctl = r6040_ioctl, .ndo_tx_timeout = r6040_tx_timeout, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -1039,7 +1044,7 @@ static int __devinit r6040_init_one(struct pci_dev *pdev, u16 *adrp; int i; - printk("%s\n", version); + pr_info("%s\n", version); err = pci_enable_device(pdev); if (err) @@ -1113,7 +1118,8 @@ static int __devinit r6040_init_one(struct pci_dev *pdev, /* Some bootloader/BIOSes do not initialize * MAC address, warn about that */ if (!(adrp[0] || adrp[1] || adrp[2])) { - netdev_warn(dev, "MAC address not initialized, generating random\n"); + netdev_warn(dev, "MAC address not initialized, " + "generating random\n"); random_ether_addr(dev->dev_addr); } -- cgit v1.2.3-59-g8ed1b From 264fd77a67f1a4fe102477d824014459c7ff61f3 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 9 Aug 2010 05:04:34 +0000 Subject: am79c961a: Use net_device_stats from struct net_device struct net_device has its own struct net_device_stats member, so we can use this one instead of a private copy in the dev_priv struct. Cc: Kulikov Vasiliy Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- drivers/net/arm/am79c961a.c | 35 ++++++++++++++++------------------- drivers/net/arm/am79c961a.h | 1 - 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 8c496fb1ac9e..62f21106efec 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -300,8 +300,6 @@ am79c961_open(struct net_device *dev) struct dev_priv *priv = netdev_priv(dev); int ret; - memset (&priv->stats, 0, sizeof (priv->stats)); - ret = request_irq(dev->irq, am79c961_interrupt, 0, dev->name, dev); if (ret) return ret; @@ -347,8 +345,7 @@ am79c961_close(struct net_device *dev) */ static struct net_device_stats *am79c961_getstats (struct net_device *dev) { - struct dev_priv *priv = netdev_priv(dev); - return &priv->stats; + return &dev->stats; } static void am79c961_mc_hash(char *addr, unsigned short *hash) @@ -510,14 +507,14 @@ am79c961_rx(struct net_device *dev, struct dev_priv *priv) if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) { am_writeword (dev, hdraddr + 2, RMD_OWN); - priv->stats.rx_errors ++; + dev->stats.rx_errors++; if (status & RMD_ERR) { if (status & RMD_FRAM) - priv->stats.rx_frame_errors ++; + dev->stats.rx_frame_errors++; if (status & RMD_CRC) - priv->stats.rx_crc_errors ++; + dev->stats.rx_crc_errors++; } else if (status & RMD_STP) - priv->stats.rx_length_errors ++; + dev->stats.rx_length_errors++; continue; } @@ -531,12 +528,12 @@ am79c961_rx(struct net_device *dev, struct dev_priv *priv) am_writeword(dev, hdraddr + 2, RMD_OWN); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); - priv->stats.rx_bytes += len; - priv->stats.rx_packets ++; + dev->stats.rx_bytes += len; + dev->stats.rx_packets++; } else { am_writeword (dev, hdraddr + 2, RMD_OWN); printk (KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name); - priv->stats.rx_dropped ++; + dev->stats.rx_dropped++; break; } } while (1); @@ -565,7 +562,7 @@ am79c961_tx(struct net_device *dev, struct dev_priv *priv) if (status & TMD_ERR) { u_int status2; - priv->stats.tx_errors ++; + dev->stats.tx_errors++; status2 = am_readword (dev, hdraddr + 6); @@ -575,18 +572,18 @@ am79c961_tx(struct net_device *dev, struct dev_priv *priv) am_writeword (dev, hdraddr + 6, 0); if (status2 & TST_RTRY) - priv->stats.collisions += 16; + dev->stats.collisions += 16; if (status2 & TST_LCOL) - priv->stats.tx_window_errors ++; + dev->stats.tx_window_errors++; if (status2 & TST_LCAR) - priv->stats.tx_carrier_errors ++; + dev->stats.tx_carrier_errors++; if (status2 & TST_UFLO) - priv->stats.tx_fifo_errors ++; + dev->stats.tx_fifo_errors++; continue; } - priv->stats.tx_packets ++; + dev->stats.tx_packets++; len = am_readword (dev, hdraddr + 4); - priv->stats.tx_bytes += -len; + dev->stats.tx_bytes += -len; } while (priv->txtail != priv->txhead); netif_wake_queue(dev); @@ -616,7 +613,7 @@ am79c961_interrupt(int irq, void *dev_id) } if (status & CSR0_MISS) { handled = 1; - priv->stats.rx_dropped ++; + dev->stats.rx_dropped++; } if (status & CSR0_CERR) { handled = 1; diff --git a/drivers/net/arm/am79c961a.h b/drivers/net/arm/am79c961a.h index 483009fe6ec2..fd634d32756b 100644 --- a/drivers/net/arm/am79c961a.h +++ b/drivers/net/arm/am79c961a.h @@ -130,7 +130,6 @@ #define ISALED0_LNKST 0x8000 struct dev_priv { - struct net_device_stats stats; unsigned long rxbuffer[RX_BUFFERS]; unsigned long txbuffer[TX_BUFFERS]; unsigned char txhead; -- cgit v1.2.3-59-g8ed1b From 559764d1996e6ae769feb07918687b0806f2d975 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sun, 8 Aug 2010 10:09:39 +0000 Subject: cpmac: fix all checkpatch errors and warnings This patches fixes a couple of checkpatch warnings and errors: - lines over 80 columns - printk() instead of pr_cont() - assignments in tests (if ((foo == bar()))) Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/cpmac.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index ac3985ceb5f7..8e142aaa05d4 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include MODULE_AUTHOR("Eugene Konev "); @@ -108,7 +108,7 @@ MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus"); #define CPMAC_RX_INT_CLEAR 0x019c #define CPMAC_MAC_INT_ENABLE 0x01a8 #define CPMAC_MAC_INT_CLEAR 0x01ac -#define CPMAC_MAC_ADDR_LO(channel) (0x01b0 + (channel) * 4) +#define CPMAC_MAC_ADDR_LO(channel) (0x01b0 + (channel) * 4) #define CPMAC_MAC_ADDR_MID 0x01d0 #define CPMAC_MAC_ADDR_HI 0x01d4 #define CPMAC_MAC_HASH_LO 0x01d8 @@ -227,7 +227,7 @@ static void cpmac_dump_regs(struct net_device *dev) for (i = 0; i < CPMAC_REG_END; i += 4) { if (i % 16 == 0) { if (i) - printk("\n"); + pr_cont("\n"); printk(KERN_DEBUG "%s: reg[%p]:", dev->name, priv->regs + i); } @@ -262,7 +262,7 @@ static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb) for (i = 0; i < skb->len; i++) { if (i % 16 == 0) { if (i) - printk("\n"); + pr_cont("\n"); printk(KERN_DEBUG "%s: data[%p]:", dev->name, skb->data + i); } @@ -873,7 +873,8 @@ static int cpmac_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return -EINVAL; } -static void cpmac_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring) +static void cpmac_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) { struct cpmac_priv *priv = netdev_priv(dev); @@ -888,7 +889,8 @@ static void cpmac_get_ringparam(struct net_device *dev, struct ethtool_ringparam ring->tx_pending = 1; } -static int cpmac_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ring) +static int cpmac_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) { struct cpmac_priv *priv = netdev_priv(dev); @@ -1012,8 +1014,8 @@ static int cpmac_open(struct net_device *dev) priv->rx_head->prev->hw_next = (u32)0; - if ((res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, - dev->name, dev))) { + res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, dev->name, dev); + if (res) { if (netif_msg_drv(priv)) printk(KERN_ERR "%s: failed to obtain irq\n", dev->name); @@ -1133,7 +1135,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev) } if (phy_id == PHY_MAX_ADDR) { - dev_err(&pdev->dev, "no PHY present, falling back to switch on MDIO bus 0\n"); + dev_err(&pdev->dev, "no PHY present, falling back " + "to switch on MDIO bus 0\n"); strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */ phy_id = pdev->id; } @@ -1169,7 +1172,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev) priv->msg_enable = netif_msg_init(debug_level, 0xff); memcpy(dev->dev_addr, pdata->dev_addr, sizeof(pdata->dev_addr)); - snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); + snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, + mdio_bus_id, phy_id); priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII); @@ -1182,7 +1186,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev) goto fail; } - if ((rc = register_netdev(dev))) { + rc = register_netdev(dev); + if (rc) { printk(KERN_ERR "cpmac: error %i registering device %s\n", rc, dev->name); goto fail; @@ -1248,11 +1253,13 @@ int __devinit cpmac_init(void) cpmac_mii->reset(cpmac_mii); - for (i = 0; i < 300; i++) - if ((mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE))) + for (i = 0; i < 300; i++) { + mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE); + if (mask) break; else msleep(10); + } mask &= 0x7fffffff; if (mask & (mask - 1)) { -- cgit v1.2.3-59-g8ed1b From 294dab25e7068f9df80af53aceed332f9621c970 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 10 Aug 2010 18:54:55 +0000 Subject: enic: Add set mac address This patch implements the ndo_set_mac_address netdev operation for an enic device Signed-off-by: Scott Feldman Signed-off-by: Roopa Prabhu Signed-off-by: Vasanthy Kolluri Signed-off-by: David S. Miller --- drivers/net/enic/enic.h | 2 +- drivers/net/enic/enic_main.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index f239aa8c6f4c..75869ed7226f 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -32,7 +32,7 @@ #define DRV_NAME "enic" #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" -#define DRV_VERSION "1.4.1.1" +#define DRV_VERSION "1.4.1.2" #define DRV_COPYRIGHT "Copyright 2008-2010 Cisco Systems, Inc" #define ENIC_BARS_MAX 6 diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 9aab85366d21..6f6c5dc36197 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -911,7 +911,9 @@ static int enic_set_mac_address_dynamic(struct net_device *netdev, void *p) static int enic_set_mac_address(struct net_device *netdev, void *p) { - return -EOPNOTSUPP; + struct sockaddr *saddr = p; + + return enic_set_mac_addr(netdev, (char *)saddr->sa_data); } static int enic_dev_packet_filter(struct enic *enic, int directed, -- cgit v1.2.3-59-g8ed1b From 90cf0b53d74ebca4f62d865ae39d21ed3bdbf877 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 10 Aug 2010 18:55:00 +0000 Subject: enic: Add support for firmware management device This patch adds support for firmware management device in enic driver. A management device is a virtual PCIe device that firmware can present to the host as its management endpoint. It provides the interface between the host and adapter firmware for all management operations. Signed-off-by: Scott Feldman Signed-off-by: Roopa Prabhu Signed-off-by: Vasanthy Kolluri Signed-off-by: David S. Miller --- drivers/net/enic/vnic_dev.c | 25 ++++++++++++++++++------- drivers/net/enic/vnic_resource.h | 13 +++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index 6a5b578a69e1..08d5d42da260 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c @@ -74,6 +74,7 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev, struct vnic_dev_bar *bar, unsigned int num_bars) { struct vnic_resource_header __iomem *rh; + struct mgmt_barmap_hdr __iomem *mrh; struct vnic_resource __iomem *r; u8 type; @@ -85,22 +86,32 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev, return -EINVAL; } - rh = bar->vaddr; + rh = bar->vaddr; + mrh = bar->vaddr; if (!rh) { pr_err("vNIC BAR0 res hdr not mem-mapped\n"); return -EINVAL; } - if (ioread32(&rh->magic) != VNIC_RES_MAGIC || - ioread32(&rh->version) != VNIC_RES_VERSION) { - pr_err("vNIC BAR0 res magic/version error " - "exp (%lx/%lx) curr (%x/%x)\n", + /* Check for mgmt vnic in addition to normal vnic */ + if ((ioread32(&rh->magic) != VNIC_RES_MAGIC) || + (ioread32(&rh->version) != VNIC_RES_VERSION)) { + if ((ioread32(&mrh->magic) != MGMTVNIC_MAGIC) || + (ioread32(&mrh->version) != MGMTVNIC_VERSION)) { + pr_err("vNIC BAR0 res magic/version error " + "exp (%lx/%lx) or (%lx/%lx), curr (%x/%x)\n", VNIC_RES_MAGIC, VNIC_RES_VERSION, + MGMTVNIC_MAGIC, MGMTVNIC_VERSION, ioread32(&rh->magic), ioread32(&rh->version)); - return -EINVAL; + return -EINVAL; + } } - r = (struct vnic_resource __iomem *)(rh + 1); + if (ioread32(&mrh->magic) == MGMTVNIC_MAGIC) + r = (struct vnic_resource __iomem *)(mrh + 1); + else + r = (struct vnic_resource __iomem *)(rh + 1); + while ((type = ioread8(&r->type)) != RES_TYPE_EOL) { diff --git a/drivers/net/enic/vnic_resource.h b/drivers/net/enic/vnic_resource.h index 810287beff14..e0a73f1ca6f4 100644 --- a/drivers/net/enic/vnic_resource.h +++ b/drivers/net/enic/vnic_resource.h @@ -22,6 +22,11 @@ #define VNIC_RES_MAGIC 0x766E6963L /* 'vnic' */ #define VNIC_RES_VERSION 0x00000000L +#define MGMTVNIC_MAGIC 0x544d474dL /* 'MGMT' */ +#define MGMTVNIC_VERSION 0x00000000L + +/* The MAC address assigned to the CFG vNIC is fixed. */ +#define MGMTVNIC_MAC { 0x02, 0x00, 0x54, 0x4d, 0x47, 0x4d } /* vNIC resource types */ enum vnic_res_type { @@ -52,6 +57,14 @@ struct vnic_resource_header { u32 version; }; +struct mgmt_barmap_hdr { + u32 magic; /* magic number */ + u32 version; /* header format version */ + u16 lif; /* loopback lif for mgmt frames */ + u16 pci_slot; /* installed pci slot */ + char serial[16]; /* card serial number */ +}; + struct vnic_resource { u8 type; u8 bar; -- cgit v1.2.3-59-g8ed1b From ae94abe1687871d9772494b3d378c6d3decd7f75 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 10 Aug 2010 18:55:05 +0000 Subject: enic: Add new firmware devcmds Add new firmware devcmds: CMD_PROXY_BY_INDEX, CMD_CONFIG_INFO_GET Signed-off-by: Scott Feldman Signed-off-by: Roopa Prabhu Signed-off-by: Vasanthy Kolluri Signed-off-by: David S. Miller --- drivers/net/enic/vnic_devcmd.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h index 20661755df6b..9abb3d51dea1 100644 --- a/drivers/net/enic/vnic_devcmd.h +++ b/drivers/net/enic/vnic_devcmd.h @@ -238,6 +238,18 @@ enum vnic_devcmd_cmd { * out: (u32)a0=status of proxied cmd * a1-a15=out args of proxied cmd */ CMD_PROXY_BY_BDF = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 42), + + /* + * As for BY_BDF except a0 is index of hvnlink subordinate vnic + * or SR-IOV virtual vnic */ + CMD_PROXY_BY_INDEX = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 43), + + /* + * in: (u64)a0=paddr of buffer to put latest VIC VIF-CONFIG-INFO TLV in + * (u32)a1=length of buffer in a0 + * out: (u64)a0=paddr of buffer with latest VIC VIF-CONFIG-INFO TLV + * (u32)a1=actual length of latest VIC VIF-CONFIG-INFO TLV */ + CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44), }; /* flags for CMD_OPEN */ -- cgit v1.2.3-59-g8ed1b From 7c46835e4845fed5f348f5845a3a6165874e2f05 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 10 Aug 2010 18:55:10 +0000 Subject: enic: Use offsetof macro in vic tlv length calculation Signed-off-by: Scott Feldman Signed-off-by: Roopa Prabhu Signed-off-by: Vasanthy Kolluri Signed-off-by: David S. Miller --- drivers/net/enic/vnic_vic.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/enic/vnic_vic.c b/drivers/net/enic/vnic_vic.c index 197c9d24af82..4725b79de0ef 100644 --- a/drivers/net/enic/vnic_vic.c +++ b/drivers/net/enic/vnic_vic.c @@ -54,8 +54,8 @@ int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length, if (!vp || !value) return -EINVAL; - if (ntohl(vp->length) + sizeof(*tlv) + length > - VIC_PROVINFO_MAX_TLV_DATA) + if (ntohl(vp->length) + offsetof(struct vic_provinfo_tlv, value) + + length > VIC_PROVINFO_MAX_TLV_DATA) return -ENOMEM; tlv = (struct vic_provinfo_tlv *)((u8 *)vp->tlv + @@ -66,7 +66,8 @@ int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length, memcpy(tlv->value, value, length); vp->num_tlvs = htonl(ntohl(vp->num_tlvs) + 1); - vp->length = htonl(ntohl(vp->length) + sizeof(*tlv) + length); + vp->length = htonl(ntohl(vp->length) + + offsetof(struct vic_provinfo_tlv, value) + length); return 0; } -- cgit v1.2.3-59-g8ed1b From ce16cc02f9fe21d4e42116305e5ea9d12e51635d Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 10 Aug 2010 18:55:15 +0000 Subject: enic: Clean up: remove enic_dev_stats_clear Remove function enic_dev_stats_clear and its reference in enic device init code. Firmware clears device stats on device open. So, no need for the driver to do it again. Signed-off-by: Scott Feldman Signed-off-by: Roopa Prabhu Signed-off-by: Vasanthy Kolluri Signed-off-by: David S. Miller --- drivers/net/enic/enic_main.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 6f6c5dc36197..711077a2e345 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -2154,17 +2154,6 @@ void enic_dev_deinit(struct enic *enic) enic_clear_intr_mode(enic); } -static int enic_dev_stats_clear(struct enic *enic) -{ - int err; - - spin_lock(&enic->devcmd_lock); - err = vnic_dev_stats_clear(enic->vdev); - spin_unlock(&enic->devcmd_lock); - - return err; -} - int enic_dev_init(struct enic *enic) { struct device *dev = enic_get_dev(enic); @@ -2207,10 +2196,6 @@ int enic_dev_init(struct enic *enic) enic_init_vnic_resources(enic); - /* Clear LIF stats - */ - enic_dev_stats_clear(enic); - err = enic_set_rq_alloc_buf(enic); if (err) { dev_err(dev, "Failed to set RQ buffer allocator, aborting\n"); -- cgit v1.2.3-59-g8ed1b From 832177901a61aeda1f2122e323c39881ec84af65 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 10 Aug 2010 18:55:20 +0000 Subject: enic: Check if rq/wq buf not NULL before freeing them Signed-off-by: Scott Feldman Signed-off-by: Roopa Prabhu Signed-off-by: Vasanthy Kolluri Signed-off-by: David S. Miller --- drivers/net/enic/vnic_rq.c | 6 ++++-- drivers/net/enic/vnic_wq.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/enic/vnic_rq.c b/drivers/net/enic/vnic_rq.c index dbb2aca258b9..b236d7cbc137 100644 --- a/drivers/net/enic/vnic_rq.c +++ b/drivers/net/enic/vnic_rq.c @@ -77,8 +77,10 @@ void vnic_rq_free(struct vnic_rq *rq) vnic_dev_free_desc_ring(vdev, &rq->ring); for (i = 0; i < VNIC_RQ_BUF_BLKS_MAX; i++) { - kfree(rq->bufs[i]); - rq->bufs[i] = NULL; + if (rq->bufs[i]) { + kfree(rq->bufs[i]); + rq->bufs[i] = NULL; + } } rq->ctrl = NULL; diff --git a/drivers/net/enic/vnic_wq.c b/drivers/net/enic/vnic_wq.c index 122e33bcc578..4b2a6c6a569b 100644 --- a/drivers/net/enic/vnic_wq.c +++ b/drivers/net/enic/vnic_wq.c @@ -77,8 +77,10 @@ void vnic_wq_free(struct vnic_wq *wq) vnic_dev_free_desc_ring(vdev, &wq->ring); for (i = 0; i < VNIC_WQ_BUF_BLKS_MAX; i++) { - kfree(wq->bufs[i]); - wq->bufs[i] = NULL; + if (wq->bufs[i]) { + kfree(wq->bufs[i]); + wq->bufs[i] = NULL; + } } wq->ctrl = NULL; -- cgit v1.2.3-59-g8ed1b From 1f76da51f58eda3a027e71e98404b80fcad2d80d Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 10 Aug 2010 18:55:26 +0000 Subject: enic: Mark intr_timer in vnic_enet_config as deprecated Signed-off-by: Scott Feldman Signed-off-by: Roopa Prabhu Signed-off-by: Vasanthy Kolluri Signed-off-by: David S. Miller --- drivers/net/enic/vnic_enet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/enic/vnic_enet.h index 3b3291248956..e8740e3704e4 100644 --- a/drivers/net/enic/vnic_enet.h +++ b/drivers/net/enic/vnic_enet.h @@ -30,7 +30,7 @@ struct vnic_enet_config { u32 wq_desc_count; u32 rq_desc_count; u16 mtu; - u16 intr_timer; + u16 intr_timer_deprecated; u8 intr_timer_type; u8 intr_mode; char devname[16]; -- cgit v1.2.3-59-g8ed1b From 933fce12a33f219e9021a9ab7b2f9cff94fa8b0e Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Tue, 17 Aug 2010 00:34:19 +0000 Subject: qlcnic: fix aer for virtual func Virtual function are not privilge to initialize firmware. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index bf6d87adda4f..4ecbf41230cb 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -2733,7 +2733,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev) if (qlcnic_api_lock(adapter)) return -EINVAL; - if (first_func) { + if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) { adapter->need_fw_reset = 1; set_bit(__QLCNIC_START_FW, &adapter->state); QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING); -- cgit v1.2.3-59-g8ed1b From 3c4b23b1be212d1b8494655182c0d4cef0a37be3 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Tue, 17 Aug 2010 00:34:20 +0000 Subject: qlcnic: device state management fixes for virtual func o NPAR state should be set to operationl by Mangement function only. o NPAR state should be set to non operational before device reset. o VF function should wait for NPAR state to be operational. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_hdr.h | 5 ++- drivers/net/qlcnic/qlcnic_main.c | 80 ++++++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h index 15fc32070be3..bd346d9aac94 100644 --- a/drivers/net/qlcnic/qlcnic_hdr.h +++ b/drivers/net/qlcnic/qlcnic_hdr.h @@ -718,8 +718,9 @@ enum { #define QLCNIC_DEV_FAILED 0x6 #define QLCNIC_DEV_QUISCENT 0x7 -#define QLCNIC_DEV_NPAR_NOT_RDY 0 -#define QLCNIC_DEV_NPAR_RDY 1 +#define QLCNIC_DEV_NPAR_NON_OPER 0 /* NON Operational */ +#define QLCNIC_DEV_NPAR_OPER 1 /* NPAR Operational */ +#define QLCNIC_DEV_NPAR_OPER_TIMEO 30 /* Operational time out */ #define QLC_DEV_CHECK_ACTIVE(VAL, FN) ((VAL) &= (1 << (FN * 4))) #define QLC_DEV_SET_REF_CNT(VAL, FN) ((VAL) |= (1 << (FN * 4))) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 4ecbf41230cb..70c4b6b0031e 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -2398,7 +2398,7 @@ qlcnic_fwinit_work(struct work_struct *work) { struct qlcnic_adapter *adapter = container_of(work, struct qlcnic_adapter, fw_work.work); - u32 dev_state = 0xf, npar_state; + u32 dev_state = 0xf; if (qlcnic_api_lock(adapter)) goto err_ret; @@ -2412,16 +2412,8 @@ qlcnic_fwinit_work(struct work_struct *work) } if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { - npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); - if (npar_state == QLCNIC_DEV_NPAR_RDY) { - qlcnic_api_unlock(adapter); - goto wait_npar; - } else { - qlcnic_schedule_work(adapter, qlcnic_fwinit_work, - FW_POLL_DELAY); - qlcnic_api_unlock(adapter); - return; - } + qlcnic_api_unlock(adapter); + goto wait_npar; } if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) { @@ -2470,20 +2462,17 @@ wait_npar: QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state); switch (dev_state) { - case QLCNIC_DEV_QUISCENT: - case QLCNIC_DEV_NEED_QUISCENT: - case QLCNIC_DEV_NEED_RESET: - qlcnic_schedule_work(adapter, - qlcnic_fwinit_work, FW_POLL_DELAY); - return; - case QLCNIC_DEV_FAILED: - break; - - default: + case QLCNIC_DEV_READY: if (!adapter->nic_ops->start_firmware(adapter)) { qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); return; } + case QLCNIC_DEV_FAILED: + break; + default: + qlcnic_schedule_work(adapter, + qlcnic_fwinit_work, FW_POLL_DELAY); + return; } err_ret: @@ -2530,6 +2519,22 @@ err_ret: } +/*Transit NPAR state to NON Operational */ +static void +qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter) +{ + u32 state; + + state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); + if (state == QLCNIC_DEV_NPAR_NON_OPER) + return; + + if (qlcnic_api_lock(adapter)) + return; + QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER); + qlcnic_api_unlock(adapter); +} + /*Transit to RESET state from READY state only */ static void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) @@ -2548,6 +2553,7 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) qlcnic_idc_debug_info(adapter, 0); } + QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER); qlcnic_api_unlock(adapter); } @@ -2555,21 +2561,14 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter) { - u32 state; - if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) || - adapter->op_mode == QLCNIC_NON_PRIV_FUNC) + adapter->op_mode != QLCNIC_MGMT_FUNC) return; if (qlcnic_api_lock(adapter)) return; - state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); - - if (state != QLCNIC_DEV_NPAR_RDY) { - QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, - QLCNIC_DEV_NPAR_RDY); - QLCDB(adapter, DRV, "NPAR READY state set\n"); - } + QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_OPER); + QLCDB(adapter, DRV, "NPAR operational state set\n"); qlcnic_api_unlock(adapter); } @@ -2631,8 +2630,11 @@ qlcnic_check_health(struct qlcnic_adapter *adapter) qlcnic_dev_request_reset(adapter); state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); - if (state == QLCNIC_DEV_NEED_RESET || state == QLCNIC_DEV_NEED_QUISCENT) + if (state == QLCNIC_DEV_NEED_RESET || + state == QLCNIC_DEV_NEED_QUISCENT) { + qlcnic_set_npar_non_operational(adapter); adapter->need_fw_reset = 1; + } heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); if (heartbit != adapter->heartbit) { @@ -2822,11 +2824,25 @@ static int qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) { int err; + u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO; + u32 npar_state; err = qlcnic_can_start_firmware(adapter); if (err) return err; + npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); + while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) { + msleep(1000); + npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); + } + + if (!npar_opt_timeo) { + dev_err(&adapter->pdev->dev, + "Waiting for NPAR state to opertional timeout\n"); + return -EIO; + } + qlcnic_check_options(adapter); adapter->need_fw_reset = 0; -- cgit v1.2.3-59-g8ed1b From ecd7d31038e2e0e95b4596eec021e02ba67a0a37 Mon Sep 17 00:00:00 2001 From: Rajesh Borundia Date: Tue, 17 Aug 2010 00:34:21 +0000 Subject: qlcnic: fix for setting function modes function modes was not working with CNA device, in CNA mode other function(FCOE) can be enabled before nic. Signed-off-by: Rajesh Borundia Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 70c4b6b0031e..06ffd7637f87 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -543,8 +543,6 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter) ret = qlcnic_api_lock(adapter); if (ret) goto err_lock; - if (QLC_DEV_CLR_REF_CNT(ref_count, adapter->ahw.pci_func)) - goto err_npar; if (qlcnic_config_npars) { for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { @@ -562,7 +560,6 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter) adapter->ahw.pci_func)); } writel(data, priv_op); -err_npar: qlcnic_api_unlock(adapter); err_lock: return ret; -- cgit v1.2.3-59-g8ed1b From b6021212291d1eb1e7d1245bbd8c53bcbe2355d7 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Tue, 17 Aug 2010 00:34:22 +0000 Subject: qlcnic: add eswitch statistics support Adding eswitch statistics support. User can get whole eswitch stats or stats of func belong to that eswitch. Added: o command to get statistics of eswitch and function. o sysfs support to export eswitch and func statatistics. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 31 +++++++++ drivers/net/qlcnic/qlcnic_ctx.c | 125 ++++++++++++++++++++++++++++++++++++ drivers/net/qlcnic/qlcnic_main.c | 132 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 287 insertions(+), 1 deletion(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 970389331bbc..7f4e11bd4cd4 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -555,6 +555,7 @@ struct qlcnic_recv_context { #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026 #define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027 #define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028 +#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a #define QLCNIC_RCODE_SUCCESS 0 #define QLCNIC_RCODE_TIMEOUT 17 @@ -1126,6 +1127,31 @@ struct qlcnic_esw_func_cfg { u8 reserved; }; +#define QLCNIC_STATS_VERSION 1 +#define QLCNIC_STATS_PORT 1 +#define QLCNIC_STATS_ESWITCH 2 +#define QLCNIC_QUERY_RX_COUNTER 0 +#define QLCNIC_QUERY_TX_COUNTER 1 +struct __qlcnic_esw_statistics { + __le16 context_id; + __le16 version; + __le16 size; + __le16 unused; + __le64 unicast_frames; + __le64 multicast_frames; + __le64 broadcast_frames; + __le64 dropped_frames; + __le64 errors; + __le64 local_frames; + __le64 numbytes; + __le64 rsvd[3]; +}; + +struct qlcnic_esw_statistics { + struct __qlcnic_esw_statistics rx; + struct __qlcnic_esw_statistics tx; +}; + int qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val); int qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val); @@ -1252,6 +1278,11 @@ int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8); int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8, u8, u8, u16); int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8); +int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8, + struct __qlcnic_esw_statistics *); +int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8, + struct __qlcnic_esw_statistics *); +int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8); extern int qlcnic_config_tso; /* diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index cc5d861d9a12..57c9b09bd16a 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c @@ -983,3 +983,128 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id, return err; } + +int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, + const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) { + + size_t stats_size = sizeof(struct __qlcnic_esw_statistics); + dma_addr_t stats_dma_t; + void *stats_addr; + u32 arg1; + int err; + + if (esw_stats == NULL) + return -ENOMEM; + + if (adapter->op_mode != QLCNIC_MGMT_FUNC && + func != adapter->ahw.pci_func) { + dev_err(&adapter->pdev->dev, + "Not privilege to query stats for func=%d", func); + return -EIO; + } + + stats_addr = pci_alloc_consistent(adapter->pdev, stats_size, + &stats_dma_t); + if (!stats_addr) { + dev_err(&adapter->pdev->dev, "Unable to allocate memory\n"); + return -ENOMEM; + } + memset(stats_addr, 0, stats_size); + + arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12; + arg1 |= rx_tx << 15 | stats_size << 16; + + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + arg1, + MSD(stats_dma_t), + LSD(stats_dma_t), + QLCNIC_CDRP_CMD_GET_ESWITCH_STATS); + + if (!err) + memcpy(esw_stats, stats_addr, stats_size); + + pci_free_consistent(adapter->pdev, stats_size, stats_addr, + stats_dma_t); + return err; +} + +int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch, + const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) { + + struct __qlcnic_esw_statistics port_stats; + u8 i; + int ret = -EIO; + + if (esw_stats == NULL) + return -ENOMEM; + if (adapter->op_mode != QLCNIC_MGMT_FUNC) + return -EIO; + if (adapter->npars == NULL) + return -EIO; + + memset(esw_stats, 0, sizeof(struct __qlcnic_esw_statistics)); + esw_stats->context_id = eswitch; + + for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { + if (adapter->npars[i].phy_port != eswitch) + continue; + + memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics)); + if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats)) + continue; + + esw_stats->size = port_stats.size; + esw_stats->version = port_stats.version; + esw_stats->unicast_frames += port_stats.unicast_frames; + esw_stats->multicast_frames += port_stats.multicast_frames; + esw_stats->broadcast_frames += port_stats.broadcast_frames; + esw_stats->dropped_frames += port_stats.dropped_frames; + esw_stats->errors += port_stats.errors; + esw_stats->local_frames += port_stats.local_frames; + esw_stats->numbytes += port_stats.numbytes; + + ret = 0; + } + return ret; +} + +int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, + const u8 port, const u8 rx_tx) +{ + + u32 arg1; + + if (adapter->op_mode != QLCNIC_MGMT_FUNC) + return -EIO; + + if (func_esw == QLCNIC_STATS_PORT) { + if (port >= QLCNIC_MAX_PCI_FUNC) + goto err_ret; + } else if (func_esw == QLCNIC_STATS_ESWITCH) { + if (port >= QLCNIC_NIU_MAX_XG_PORTS) + goto err_ret; + } else { + goto err_ret; + } + + if (rx_tx > QLCNIC_QUERY_TX_COUNTER) + goto err_ret; + + arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12; + arg1 |= BIT_14 | rx_tx << 15; + + return qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + arg1, + 0, + 0, + QLCNIC_CDRP_CMD_GET_ESWITCH_STATS); + +err_ret: + dev_err(&adapter->pdev->dev, "Invalid argument func_esw=%d port=%d" + "rx_ctx=%d\n", func_esw, port, rx_tx); + return -EIO; +} diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 06ffd7637f87..a30bde52d40b 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -3377,6 +3377,115 @@ qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj, return size; } +static ssize_t +qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t offset, size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + struct qlcnic_esw_statistics port_stats; + int ret; + + if (size != sizeof(struct qlcnic_esw_statistics)) + return QL_STATUS_INVALID_PARAM; + + if (offset >= QLCNIC_MAX_PCI_FUNC) + return QL_STATUS_INVALID_PARAM; + + memset(&port_stats, 0, size); + ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER, + &port_stats.rx); + if (ret) + return ret; + + ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER, + &port_stats.tx); + if (ret) + return ret; + + memcpy(buf, &port_stats, size); + return size; +} + +static ssize_t +qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t offset, size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + struct qlcnic_esw_statistics esw_stats; + int ret; + + if (size != sizeof(struct qlcnic_esw_statistics)) + return QL_STATUS_INVALID_PARAM; + + if (offset >= QLCNIC_NIU_MAX_XG_PORTS) + return QL_STATUS_INVALID_PARAM; + + memset(&esw_stats, 0, size); + ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER, + &esw_stats.rx); + if (ret) + return ret; + + ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER, + &esw_stats.tx); + if (ret) + return ret; + + memcpy(buf, &esw_stats, size); + return size; +} + +static ssize_t +qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t offset, size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + int ret; + + if (offset >= QLCNIC_NIU_MAX_XG_PORTS) + return QL_STATUS_INVALID_PARAM; + + ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset, + QLCNIC_QUERY_RX_COUNTER); + if (ret) + return ret; + + ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset, + QLCNIC_QUERY_TX_COUNTER); + if (ret) + return ret; + + return size; +} + +static ssize_t +qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t offset, size_t size) +{ + + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + int ret; + + if (offset >= QLCNIC_MAX_PCI_FUNC) + return QL_STATUS_INVALID_PARAM; + + ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, + QLCNIC_QUERY_RX_COUNTER); + if (ret) + return ret; + + ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, + QLCNIC_QUERY_TX_COUNTER); + if (ret) + return ret; + + return size; +} + static ssize_t qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t offset, size_t size) @@ -3426,6 +3535,20 @@ static struct bin_attribute bin_attr_pci_config = { .write = NULL, }; +static struct bin_attribute bin_attr_port_stats = { + .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_get_port_stats, + .write = qlcnic_sysfs_clear_port_stats, +}; + +static struct bin_attribute bin_attr_esw_stats = { + .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_get_esw_stats, + .write = qlcnic_sysfs_clear_esw_stats, +}; + static struct bin_attribute bin_attr_esw_config = { .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)}, .size = 0, @@ -3465,6 +3588,9 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) { struct device *dev = &adapter->pdev->dev; + if (device_create_bin_file(dev, &bin_attr_port_stats)) + dev_info(dev, "failed to create port stats sysfs entry"); + if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) return; if (device_create_file(dev, &dev_attr_diag_mode)) @@ -3484,7 +3610,8 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) dev_info(dev, "failed to create esw config sysfs entry"); if (device_create_bin_file(dev, &bin_attr_pm_config)) dev_info(dev, "failed to create pm config sysfs entry"); - + if (device_create_bin_file(dev, &bin_attr_esw_stats)) + dev_info(dev, "failed to create eswitch stats sysfs entry"); } static void @@ -3492,6 +3619,8 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) { struct device *dev = &adapter->pdev->dev; + device_remove_bin_file(dev, &bin_attr_port_stats); + if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) return; device_remove_file(dev, &dev_attr_diag_mode); @@ -3504,6 +3633,7 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) device_remove_bin_file(dev, &bin_attr_npar_config); device_remove_bin_file(dev, &bin_attr_esw_config); device_remove_bin_file(dev, &bin_attr_pm_config); + device_remove_bin_file(dev, &bin_attr_esw_stats); } #ifdef CONFIG_INET -- cgit v1.2.3-59-g8ed1b From 69324275de07584fbd0e77a517f9b43e82eaf9d6 Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Tue, 17 Aug 2010 00:34:23 +0000 Subject: qlcnic: fix link status message Display interface name with netdev_info() for link status message. Signed-off-by: Sony Chacko Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index a30bde52d40b..bf4077a1e824 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -1944,14 +1944,14 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup) struct net_device *netdev = adapter->netdev; if (adapter->ahw.linkup && !linkup) { - dev_info(&netdev->dev, "NIC Link is down\n"); + netdev_info(netdev, "NIC Link is down\n"); adapter->ahw.linkup = 0; if (netif_running(netdev)) { netif_carrier_off(netdev); netif_stop_queue(netdev); } } else if (!adapter->ahw.linkup && linkup) { - dev_info(&netdev->dev, "NIC Link is up\n"); + netdev_info(netdev, "NIC Link is up\n"); adapter->ahw.linkup = 1; if (netif_running(netdev)) { netif_carrier_on(netdev); -- cgit v1.2.3-59-g8ed1b From 8dec32cc421864702912c4341934fe0c737a9798 Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Tue, 17 Aug 2010 00:34:24 +0000 Subject: qlcnic: fix link diag test o Give sufficient time for all makes of PHY modules to establish the link after loopback test. o Perform online test before offline test. Signed-off-by: Sony Chacko Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_ethtool.c | 17 ++++++++--------- drivers/net/qlcnic/qlcnic_hw.c | 1 + 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 9328d59e21e0..3d4655dce4b5 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -747,6 +747,14 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, { memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN); + data[0] = qlcnic_reg_test(dev); + if (data[0]) + eth_test->flags |= ETH_TEST_FL_FAILED; + + data[1] = (u64) qlcnic_test_link(dev); + if (data[1]) + eth_test->flags |= ETH_TEST_FL_FAILED; + if (eth_test->flags == ETH_TEST_FL_OFFLINE) { data[2] = qlcnic_irq_test(dev); if (data[2]) @@ -757,15 +765,6 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, eth_test->flags |= ETH_TEST_FL_FAILED; } - - data[0] = qlcnic_reg_test(dev); - if (data[0]) - eth_test->flags |= ETH_TEST_FL_FAILED; - - /* link test */ - data[1] = (u64) qlcnic_test_link(dev); - if (data[1]) - eth_test->flags |= ETH_TEST_FL_FAILED; } static void diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index e08c8b0556a4..9d40ce05cb17 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -1245,4 +1245,5 @@ void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter) mode = VPORT_MISS_MODE_ACCEPT_MULTI; qlcnic_nic_set_promisc(adapter, mode); + msleep(1000); } -- cgit v1.2.3-59-g8ed1b From 24763d80fbb45aaf477d53c2203c929f6c41b5fc Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Tue, 17 Aug 2010 00:34:25 +0000 Subject: qlcnic: turn off lro when rxcsum is disabled. o Also dont allow lro to be turn on, if rx csum is disabled Signed-off-by: Sucheta Chakraborty Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 1 + drivers/net/qlcnic/qlcnic_ethtool.c | 23 +++++++++++++++++++++++ drivers/net/qlcnic/qlcnic_main.c | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 7f4e11bd4cd4..f6b887d409d5 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -894,6 +894,7 @@ struct qlcnic_mac_req { #define QLCNIC_MSI_ENABLED 0x02 #define QLCNIC_MSIX_ENABLED 0x04 #define QLCNIC_LRO_ENABLED 0x08 +#define QLCNIC_LRO_DISABLED 0x00 #define QLCNIC_BRIDGE_ENABLED 0X10 #define QLCNIC_DIAG_ENABLED 0x20 #define QLCNIC_ESWITCH_ENABLED 0x40 diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 3d4655dce4b5..e38fc3d96d43 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -818,7 +818,21 @@ static u32 qlcnic_get_rx_csum(struct net_device *dev) static int qlcnic_set_rx_csum(struct net_device *dev, u32 data) { struct qlcnic_adapter *adapter = netdev_priv(dev); + + if (!!data) { + adapter->rx_csum = !!data; + return 0; + } + + if (adapter->flags & QLCNIC_LRO_ENABLED) { + if (qlcnic_config_hw_lro(adapter, QLCNIC_LRO_DISABLED)) + return -EIO; + + dev->features &= ~NETIF_F_LRO; + qlcnic_send_lro_cleanup(adapter); + } adapter->rx_csum = !!data; + dev_info(&adapter->pdev->dev, "disabling LRO as rx_csum is off\n"); return 0; } @@ -1001,6 +1015,15 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data) if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)) return -EINVAL; + if (!adapter->rx_csum) { + dev_info(&adapter->pdev->dev, "rx csum is off, " + "cannot toggle lro\n"); + return -EINVAL; + } + + if ((data & ETH_FLAG_LRO) && (adapter->flags & QLCNIC_LRO_ENABLED)) + return 0; + if (data & ETH_FLAG_LRO) { hw_lro = QLCNIC_LRO_ENABLED; netdev->features |= NETIF_F_LRO; diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index bf4077a1e824..abd7cd6db6fd 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -995,7 +995,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) qlcnic_config_intr_coalesce(adapter); - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) + if (netdev->features & NETIF_F_LRO) qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED); qlcnic_napi_enable(adapter); -- cgit v1.2.3-59-g8ed1b From 366624ba7a2a03160cd5343ba109105758d45ff9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 16 Aug 2010 20:06:26 +0100 Subject: ASoC: Remove unused WM8974 private data Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8974.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index e61728b7339f..b4363f6d19b3 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -607,7 +607,6 @@ static int wm8974_resume(struct snd_soc_codec *codec) static int wm8974_probe(struct snd_soc_codec *codec) { - struct wm8974_priv *wm8974 = snd_soc_codec_get_drvdata(codec); int ret = 0; ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); -- cgit v1.2.3-59-g8ed1b From 3ca2ecd9200a8ef5b548e9c40253d75982c54886 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 15 Aug 2010 17:48:47 +0200 Subject: ASoC: Multi-component: JZ4740: QI_LB60 board fixes This patch contains two small fixes for the sound board driver for the qi_lb60 introduced by the multi-component patches: * Remove unnecessary includes: Those includes where only used to get the definitions for the DAI devices and are thus not needed anymore. * Fix a typo. Signed-off-By: Lars-Peter Clausen Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/jz4740/qi_lb60.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c index 78dabebe8fd0..ef1a99e6a3bd 100644 --- a/sound/soc/jz4740/qi_lb60.c +++ b/sound/soc/jz4740/qi_lb60.c @@ -22,11 +22,6 @@ #include #include -#include "../codecs/jz4740.h" -#include "jz4740-pcm.h" -#include "jz4740-i2s.h" - - #define QI_LB60_SND_GPIO JZ_GPIO_PORTB(29) #define QI_LB60_AMP_GPIO JZ_GPIO_PORTD(4) @@ -86,7 +81,7 @@ static struct snd_soc_dai_link qi_lb60_dai = { .name = "jz4740", .stream_name = "jz4740", .cpu_dai_name = "jz4740-i2s", - .platform_name = "jz4740-pmc-audio", + .platform_name = "jz4740-pcm-audio", .codec_dai_name = "jz4740-hifi", .codec_name = "jz4740-codec", .init = qi_lb60_codec_init, -- cgit v1.2.3-59-g8ed1b From 75a6d53b2b1b3f212ea0615ed3bb2d68a249af7b Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 17 Aug 2010 09:58:02 +0300 Subject: ASoC: multi-component - Drop board-n8x0.c changes These will conflict with queued changes to board-n8x0.c coming from linux-omap tree. Only side effect from this dropping is that the integrated digital microphone on Nokia N810 will stop working when ASoC multi-component is merged. As currently the N810 is not very usable in mainline, I consider this as a minor issue that can be fixed in linux-omap tree the after the multi-component is merged. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- arch/arm/mach-omap2/board-n8x0.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 4543b877a51a..a3e2b49aa39f 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -615,25 +614,11 @@ static int n8x0_menelaus_late_init(struct device *dev) return 0; } -static struct aic3x_setup_data n810_aic33_setup = { - .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, - .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, -}; - -static struct aic3x_pdata n810_aic33_data = { - .setup = &n810_aic33_setup, - .gpio_reset = -1, -}; - static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] = { { I2C_BOARD_INFO("menelaus", 0x72), .irq = INT_24XX_SYS_NIRQ, }, - { - I2C_BOARD_INFO("tlv320aic3x", 0x1b), - .platform_data = &n810_aic33_data, - }, }; static struct menelaus_platform_data n8x0_menelaus_platform_data = { -- cgit v1.2.3-59-g8ed1b From 1593d7dd8c7b939e31b9d637307b26ada3e3c514 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 17 Aug 2010 23:35:31 +0100 Subject: ASoC: Fix a few more PXA build errors Dead pxa2xx-pcm.h includes and a missing , Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/pxa/corgi.c | 1 - sound/soc/pxa/em-x270.c | 1 - sound/soc/pxa/poodle.c | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 11c6a495f970..555689cf6727 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -30,7 +30,6 @@ #include #include "../codecs/wm8731.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-i2s.h" #define CORGI_HP 0 diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c index 7046128b2a4c..eadf9d351a04 100644 --- a/sound/soc/pxa/em-x270.c +++ b/sound/soc/pxa/em-x270.c @@ -32,7 +32,6 @@ #include #include "../codecs/wm9712.h" -#include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" static struct snd_soc_dai_link em_x270_dai[] = { diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 3ba5a962ecb8..add0e1c25bc8 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -267,7 +267,7 @@ static struct snd_soc_dai_link poodle_dai = { .name = "WM8731", .stream_name = "WM8731", .cpu_dai_name = "pxa-i2s", - .codec_dai_name = "wm8731-hifi" + .codec_dai_name = "wm8731-hifi", .platform_name = "pxa-pcm-audio", .codec_name = "wm8731-codec.0-001a", .init = poodle_wm8731_init, -- cgit v1.2.3-59-g8ed1b From 9745e824a81e54ef009500e120e35b68e387b941 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 17 Aug 2010 23:40:24 +0100 Subject: ASoC: Support non-crystal master clocks for WM8731 Instead of unconditionally enabling the crystal oscillator on the WM8731 only enable it when explicitly selected via set_sysclk(), allowing machine drivers to specify that they drive a clock into MCLK alone. This avoids any conflicts between the oscillator and the external MCLK source and saves power for systems which do not need the oscillator. This should also deliver a small power saving on systems using the crystal since the oscillator will only be enabled when the ADC or DAC is active. Signed-off-by: Mark Brown --- sound/soc/atmel/sam9g20_wm8731.c | 2 +- sound/soc/au1x/db1200.c | 2 +- sound/soc/codecs/wm8731.c | 31 +++++++++++++++++++++++++++++-- sound/soc/codecs/wm8731.h | 4 +++- sound/soc/pxa/corgi.c | 2 +- sound/soc/pxa/poodle.c | 2 +- 6 files changed, 36 insertions(+), 7 deletions(-) diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 66a6f1879689..8399ac46cb33 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -146,7 +146,7 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) "at91sam9g20ek_wm8731 " ": at91sam9g20ek_wm8731_init() called\n"); - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, MCLK_RATE, SND_SOC_CLOCK_IN); if (ret < 0) { printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret); diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index 8780c90107fc..d8dc8225576a 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c @@ -49,7 +49,7 @@ static int db1200_i2s_startup(struct snd_pcm_substream *substream) int ret; /* WM8731 has its own 12MHz crystal */ - snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, + snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, 12000000, SND_SOC_CLOCK_IN); /* codec is bitclock and lrclk master */ diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 19844fc8cb1d..56f540838745 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -46,6 +46,7 @@ struct wm8731_priv { struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; u16 reg_cache[WM8731_CACHEREGNUM]; unsigned int sysclk; + int sysclk_type; }; @@ -110,6 +111,7 @@ static const struct snd_kcontrol_new wm8731_input_mux_controls = SOC_DAPM_ENUM("Input Select", wm8731_enum[0]); static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0), SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, &wm8731_output_mixer_controls[0], ARRAY_SIZE(wm8731_output_mixer_controls)), @@ -127,7 +129,18 @@ SND_SOC_DAPM_INPUT("RLINEIN"), SND_SOC_DAPM_INPUT("LLINEIN"), }; +static int wm8731_check_osc(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec); + + return wm8731->sysclk_type == WM8731_SYSCLK_MCLK; +} + static const struct snd_soc_dapm_route intercon[] = { + {"DAC", NULL, "OSC", wm8731_check_osc}, + {"ADC", NULL, "OSC", wm8731_check_osc}, + /* output mixer */ {"Output Mixer", "Line Bypass Switch", "Line Input"}, {"Output Mixer", "HiFi Playback Switch", "DAC"}, @@ -285,6 +298,15 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); + switch (clk_id) { + case WM8731_SYSCLK_XTAL: + case WM8731_SYSCLK_MCLK: + wm8731->sysclk_type = clk_id; + break; + default: + return -EINVAL; + } + switch (freq) { case 11289600: case 12000000: @@ -292,9 +314,14 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai, case 16934400: case 18432000: wm8731->sysclk = freq; - return 0; + break; + default: + return -EINVAL; } - return -EINVAL; + + snd_soc_dapm_sync(codec); + + return 0; } diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h index 73a70e206ba9..e9c0c76ab73b 100644 --- a/sound/soc/codecs/wm8731.h +++ b/sound/soc/codecs/wm8731.h @@ -31,7 +31,9 @@ #define WM8731_CACHEREGNUM 10 -#define WM8731_SYSCLK 0 +#define WM8731_SYSCLK_XTAL 1 +#define WM8731_SYSCLK_MCLK 2 + #define WM8731_DAI 0 #endif diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 555689cf6727..97e9423615c9 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -149,7 +149,7 @@ static int corgi_hw_params(struct snd_pcm_substream *substream, return ret; /* set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk, + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk, SND_SOC_CLOCK_IN); if (ret < 0) return ret; diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index add0e1c25bc8..fa752f6ec37d 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -128,7 +128,7 @@ static int poodle_hw_params(struct snd_pcm_substream *substream, return ret; /* set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk, + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk, SND_SOC_CLOCK_IN); if (ret < 0) return ret; -- cgit v1.2.3-59-g8ed1b From 4c3f9d5fcb46d769f4a52a044fead863419c1d58 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 18 Aug 2010 00:25:12 +0100 Subject: ASoC: core - fix build warning on x86_64 Output size_t type as a "%Zu" to avoid warnings. Signed-off-by: Liam Girdwood --- sound/soc/soc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3d480eb3555f..7093c1787128 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2916,7 +2916,7 @@ int snd_soc_register_dais(struct device *dev, struct snd_soc_dai *dai; int i, ret = 0; - dev_dbg(dev, "dai register %s #%d\n", dev_name(dev), count); + dev_dbg(dev, "dai register %s #%Zu\n", dev_name(dev), count); for (i = 0; i < count; i++) { -- cgit v1.2.3-59-g8ed1b From f81380925209bc60732a57eef41ab440c056aacf Mon Sep 17 00:00:00 2001 From: Anders Kaseorg <[andersk@ksplice.com]> Date: Tue, 17 Aug 2010 11:00:03 +0000 Subject: tipc: Fix log buffer memory leak if initialization fails Moves log buffer cleanup into tipc_core_stop() so that memory allocated for the log buffer is freed if tipc_core_start() is unsuccessful. Signed-off-by: Anders Kaseorg Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/tipc/core.c b/net/tipc/core.c index 696468117985..466b861dab91 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -169,6 +169,7 @@ void tipc_core_stop(void) tipc_nametbl_stop(); tipc_ref_table_stop(); tipc_socket_stop(); + tipc_log_resize(0); } /** @@ -203,7 +204,9 @@ static int __init tipc_init(void) { int res; - tipc_log_resize(CONFIG_TIPC_LOG); + if (tipc_log_resize(CONFIG_TIPC_LOG) != 0) + warn("Unable to create log buffer\n"); + info("Activated (version " TIPC_MOD_VER " compiled " __DATE__ " " __TIME__ ")\n"); @@ -230,7 +233,6 @@ static void __exit tipc_exit(void) tipc_core_stop_net(); tipc_core_stop(); info("Deactivated\n"); - tipc_log_resize(0); } module_init(tipc_init); -- cgit v1.2.3-59-g8ed1b From 3720d40b201fe82dce1d8a64a31bfbf49c221771 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 17 Aug 2010 11:00:04 +0000 Subject: tipc: add SO_RCVLOWAT support to stream socket receive path Add support for the SO_RCVLOWAT socket option to TIPC's stream socket type. Signed-off-by: Florian Westphal Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/socket.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 66e889ba48fd..69d0fd1f3920 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1026,9 +1026,8 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, struct sk_buff *buf; struct tipc_msg *msg; unsigned int sz; - int sz_to_copy; + int sz_to_copy, target, needed; int sz_copied = 0; - int needed; char __user *crs = m->msg_iov->iov_base; unsigned char *buf_crs; u32 err; @@ -1050,6 +1049,8 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, goto exit; } + target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); + restart: /* Look for a message in receive queue; wait if necessary */ @@ -1138,7 +1139,7 @@ restart: if ((sz_copied < buf_len) && /* didn't get all requested data */ (!skb_queue_empty(&sk->sk_receive_queue) || - (flags & MSG_WAITALL)) && /* and more is ready or required */ + (sz_copied < target)) && /* and more is ready or required */ (!(flags & MSG_PEEK)) && /* and aren't just peeking at data */ (!err)) /* and haven't reached a FIN */ goto restart; -- cgit v1.2.3-59-g8ed1b From 35997e3157eba16c6124d440bdf9272087129b2a Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 17 Aug 2010 11:00:05 +0000 Subject: tipc: Provide correct error code for unsupported connect() operation Modify TIPC to return EOPNOTSUPP if an application attempts to perform a non-blocking connect() operation, which is not supported by TIPC. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 69d0fd1f3920..b89c7b1a0d09 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1380,7 +1380,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, /* For now, TIPC does not support the non-blocking form of connect() */ if (flags & O_NONBLOCK) { - res = -EWOULDBLOCK; + res = -EOPNOTSUPP; goto exit; } -- cgit v1.2.3-59-g8ed1b From f662c07058f7e6365ae65080d772f9122f6f50a9 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 17 Aug 2010 11:00:06 +0000 Subject: tipc: correct problems with misleading flags returned using poll() Prevent TIPC from incorrectly setting returned flags to poll() in the following cases: - an unconnected socket no longer indicates that it is always readable - an unconnected, connecting, or listening socket no longer indicates that it is always writable Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/socket.c | 61 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index b89c7b1a0d09..7b81fdd4f6d6 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -429,36 +429,55 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr, * to handle any preventable race conditions, so TIPC will do the same ... * * TIPC sets the returned events as follows: - * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty - * or if a connection-oriented socket is does not have an active connection - * (i.e. a read operation will not block). - * b) POLLOUT is set except when a socket's connection has been terminated - * (i.e. a write operation will not block). - * c) POLLHUP is set when a socket's connection has been terminated. - * - * IMPORTANT: The fact that a read or write operation will not block does NOT - * imply that the operation will succeed! + * + * socket state flags set + * ------------ --------- + * unconnected no read flags + * no write flags + * + * connecting POLLIN/POLLRDNORM if ACK/NACK in rx queue + * no write flags + * + * connected POLLIN/POLLRDNORM if data in rx queue + * POLLOUT if port is not congested + * + * disconnecting POLLIN/POLLRDNORM/POLLHUP + * no write flags + * + * listening POLLIN if SYN in rx queue + * no write flags + * + * ready POLLIN/POLLRDNORM if data in rx queue + * [connectionless] POLLOUT (since port cannot be congested) + * + * IMPORTANT: The fact that a read or write operation is indicated does NOT + * imply that the operation will succeed, merely that it should be performed + * and will not block. */ static unsigned int poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; - u32 mask; + u32 mask = 0; poll_wait(file, sk_sleep(sk), wait); - if (!skb_queue_empty(&sk->sk_receive_queue) || - (sock->state == SS_UNCONNECTED) || - (sock->state == SS_DISCONNECTING)) - mask = (POLLRDNORM | POLLIN); - else - mask = 0; - - if (sock->state == SS_DISCONNECTING) - mask |= POLLHUP; - else - mask |= POLLOUT; + switch ((int)sock->state) { + case SS_READY: + case SS_CONNECTED: + if (!tipc_sk_port(sk)->congested) + mask |= POLLOUT; + /* fall thru' */ + case SS_CONNECTING: + case SS_LISTENING: + if (!skb_queue_empty(&sk->sk_receive_queue)) + mask |= (POLLIN | POLLRDNORM); + break; + case SS_DISCONNECTING: + mask = (POLLIN | POLLRDNORM | POLLHUP); + break; + } return mask; } -- cgit v1.2.3-59-g8ed1b From b02b69c8a403859ec72090742727e853d606a325 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 17 Aug 2010 11:00:07 +0000 Subject: tipc: Check for disabled bearer when processing incoming messages Add a check to tipc_recv_msg() to ensure it discards messages arriving on a newly disabled bearer. This is needed to deal with a race condition that can arise if the bearer is in the midst of being disabled when it receives a message. Performing the check after tipc_net_lock has been taken ensures that TIPC's bearers are in a stable state while the message is being processed. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/link.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/net/tipc/link.c b/net/tipc/link.c index a3616b99529b..9d18c9b7638b 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1802,6 +1802,15 @@ static int link_recv_buf_validate(struct sk_buff *buf) return pskb_may_pull(buf, hdr_size); } +/** + * tipc_recv_msg - process TIPC messages arriving from off-node + * @head: pointer to message buffer chain + * @tb_ptr: pointer to bearer message arrived on + * + * Invoked with no locks held. Bearer pointer must point to a valid bearer + * structure (i.e. cannot be NULL), but bearer can be inactive. + */ + void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) { read_lock_bh(&tipc_net_lock); @@ -1819,6 +1828,11 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) head = head->next; + /* Ensure bearer is still enabled */ + + if (unlikely(!b_ptr->active)) + goto cont; + /* Ensure message is well-formed */ if (unlikely(!link_recv_buf_validate(buf))) -- cgit v1.2.3-59-g8ed1b From 7e3e5d0950559d1118dccbdff3c765fffcf04fd5 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 17 Aug 2010 11:00:08 +0000 Subject: tipc: Prevent crash when broadcast link cannot send to all nodes Allow TIPC's broadcast link to continue operation when it is unable to send a message to all nodes in the cluster. Previously, the broadcast link attempted to put the broadcast pseudo-bearer into a blocked state; however, this caused a crash because the associated bearer structure is only partially initialized. Further investigation has revealed some conceptual problems with blocking the pseudo-bearer; consequently, this functionality has been disabled for the time being and the undelivered message is eventually resent by the broadcast link's existing message retransmission mechanism (if possible). Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/bcast.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index a008c6689305..42b1737f0dcf 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -609,11 +609,13 @@ static int tipc_bcbearer_send(struct sk_buff *buf, bcbearer->remains = bcbearer->remains_new; } - /* Unable to reach all targets */ + /* + * Unable to reach all targets (indicate success, since currently + * there isn't code in place to properly block & unblock the + * pseudo-bearer used by the broadcast link) + */ - bcbearer->bearer.publ.blocked = 1; - bcl->stats.bearer_congs++; - return 1; + return TIPC_OK; } /** -- cgit v1.2.3-59-g8ed1b From 5b1f7bdeb698547cc319c7a302a5acf585227a92 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 17 Aug 2010 11:00:09 +0000 Subject: tipc: Fix premature broadcast advertisement by sending node Prevent a TIPC node from sending out a LINK_STATE message advertising a broadcast message that it is in the process of sending, but has not yet actually sent. Previously, it was possible for a link timeout to occur in between the time the broadcast link updated its "last message sent" counter and the time the broadcast message was passed to the broadcast bearer for transmission. This ensures that the code which issues the LINK_STATE message isn't informed of the new message until the broadcast bearer has had a chance to send it. Note: The "last message sent" value is stored in the "fsm_msg_count" field of the link structure used by the broadcast link. Since the broadcast link doesn't utilize the normal link FSM, this field can be re-used rather than adding a new field to the broadcast link. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/bcast.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 42b1737f0dcf..eefdd1a85f4f 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -143,6 +143,19 @@ static void bcbuf_decr_acks(struct sk_buff *buf) } +static void bclink_set_last_sent(void) +{ + if (bcl->next_out) + bcl->fsm_msg_cnt = mod(buf_seqno(bcl->next_out) - 1); + else + bcl->fsm_msg_cnt = mod(bcl->next_out_no - 1); +} + +u32 tipc_bclink_get_last_sent(void) +{ + return bcl->fsm_msg_cnt; +} + /** * bclink_set_gap - set gap according to contents of current deferred pkt queue * @@ -237,8 +250,10 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) /* Try resolving broadcast link congestion, if necessary */ - if (unlikely(bcl->next_out)) + if (unlikely(bcl->next_out)) { tipc_link_push_queue(bcl); + bclink_set_last_sent(); + } if (unlikely(released && !list_empty(&bcl->waiting_ports))) tipc_link_wakeup_ports(bcl, 0); spin_unlock_bh(&bc_lock); @@ -394,8 +409,10 @@ int tipc_bclink_send_msg(struct sk_buff *buf) res = tipc_link_send_buf(bcl, buf); if (unlikely(res == -ELINKCONG)) buf_discard(buf); - else + else { bcl->stats.sent_info++; + bclink_set_last_sent(); + } if (bcl->out_queue_size > bcl->stats.max_queue_sz) bcl->stats.max_queue_sz = bcl->out_queue_size; @@ -529,15 +546,6 @@ receive: tipc_node_unlock(node); } -u32 tipc_bclink_get_last_sent(void) -{ - u32 last_sent = mod(bcl->next_out_no - 1); - - if (bcl->next_out) - last_sent = mod(buf_seqno(bcl->next_out) - 1); - return last_sent; -} - u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) { return (n_ptr->bclink.supported && -- cgit v1.2.3-59-g8ed1b From 0048b826afae7c47afdc47c3854707581cafe3d8 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 17 Aug 2010 11:00:10 +0000 Subject: tipc: Fix bug in broadcast link transmit statistics computation Modify TIPC's broadcast link so that it counts each piece of a fragmented message individually, rather than as treating the group as a single message. This ensures that proper correlation of sent and received traffic can be done when the broadcast link statistics are displayed, and is consistent with the way fragments are counted by TIPC's unicast links. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/bcast.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index eefdd1a85f4f..b11248c2d788 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -409,10 +409,8 @@ int tipc_bclink_send_msg(struct sk_buff *buf) res = tipc_link_send_buf(bcl, buf); if (unlikely(res == -ELINKCONG)) buf_discard(buf); - else { - bcl->stats.sent_info++; + else bclink_set_last_sent(); - } if (bcl->out_queue_size > bcl->stats.max_queue_sz) bcl->stats.max_queue_sz = bcl->out_queue_size; @@ -578,6 +576,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, msg = buf_msg(buf); msg_set_non_seq(msg, 1); msg_set_mc_netid(msg, tipc_net_id); + bcl->stats.sent_info++; } /* Send buffer over bearers until all targets reached */ -- cgit v1.2.3-59-g8ed1b From 96d841b7038b8091af3530a008793f5577337d3a Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 17 Aug 2010 11:00:11 +0000 Subject: tipc: Remove per-connection sequence number logic Remove validation of the per-connection sequence numbers on routable connections, since routable connections are not supported by TIPC. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/port.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/net/tipc/port.c b/net/tipc/port.c index 0737680e9266..ebcbc21d8f98 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -588,19 +588,10 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf) if (!p_ptr) { err = TIPC_ERR_NO_PORT; } else if (p_ptr->publ.connected) { - if (port_peernode(p_ptr) != msg_orignode(msg)) + if ((port_peernode(p_ptr) != msg_orignode(msg)) || + (port_peerport(p_ptr) != msg_origport(msg))) { err = TIPC_ERR_NO_PORT; - if (port_peerport(p_ptr) != msg_origport(msg)) - err = TIPC_ERR_NO_PORT; - if (!err && msg_routed(msg)) { - u32 seqno = msg_transp_seqno(msg); - u32 myno = ++p_ptr->last_in_seqno; - if (seqno != myno) { - err = TIPC_ERR_NO_PORT; - abort_buf = port_build_self_abort_msg(p_ptr, err); - } - } - if (msg_type(msg) == CONN_ACK) { + } else if (msg_type(msg) == CONN_ACK) { int wakeup = tipc_port_congested(p_ptr) && p_ptr->publ.congested && p_ptr->wakeup; -- cgit v1.2.3-59-g8ed1b From 76ae0d71d839b365faa7fdca0eec85a6d1a20d95 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 17 Aug 2010 11:00:12 +0000 Subject: tipc: Optimize tipc_node_has_active_links() Eliminate unnecessary checking for null node pointer and redundant check of second active link array entry. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/node.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/tipc/node.c b/net/tipc/node.c index b634942caba5..940851797615 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -237,8 +237,7 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr) int tipc_node_has_active_links(struct tipc_node *n_ptr) { - return (n_ptr && - ((n_ptr->active_links[0]) || (n_ptr->active_links[1]))); + return n_ptr->active_links[0] != NULL; } int tipc_node_has_redundant_links(struct tipc_node *n_ptr) -- cgit v1.2.3-59-g8ed1b From c2de58140a380172610b6a0f07f975abb2fbb311 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 17 Aug 2010 11:00:14 +0000 Subject: tipc: Minor enhancements to name table display format Eliminate printing of dashes after name table column headers (to adhere more closely to the standard format used in tipc-config), and simplify name table display logic using array lookups rather than if-then-else logic. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/name_table.c | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 8ba79620db3f..d504e490fd02 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -877,7 +877,7 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, u32 index) { char portIdStr[27]; - char *scopeStr; + const char *scope_str[] = {"", " zone", " cluster", " node"}; struct publication *publ = sseq->zone_list; tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper); @@ -893,15 +893,8 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, tipc_node(publ->node), publ->ref); tipc_printf(buf, "%-26s ", portIdStr); if (depth > 3) { - if (publ->node != tipc_own_addr) - scopeStr = ""; - else if (publ->scope == TIPC_NODE_SCOPE) - scopeStr = "node"; - else if (publ->scope == TIPC_CLUSTER_SCOPE) - scopeStr = "cluster"; - else - scopeStr = "zone"; - tipc_printf(buf, "%-10u %s", publ->key, scopeStr); + tipc_printf(buf, "%-10u %s", publ->key, + scope_str[publ->scope]); } publ = publ->zone_list_next; @@ -951,24 +944,19 @@ static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth, static void nametbl_header(struct print_buf *buf, u32 depth) { - tipc_printf(buf, "Type "); - - if (depth > 1) - tipc_printf(buf, "Lower Upper "); - if (depth > 2) - tipc_printf(buf, "Port Identity "); - if (depth > 3) - tipc_printf(buf, "Publication"); - - tipc_printf(buf, "\n-----------"); - - if (depth > 1) - tipc_printf(buf, "--------------------- "); - if (depth > 2) - tipc_printf(buf, "-------------------------- "); - if (depth > 3) - tipc_printf(buf, "------------------"); - + const char *header[] = { + "Type ", + "Lower Upper ", + "Port Identity ", + "Publication Scope" + }; + + int i; + + if (depth > 4) + depth = 4; + for (i = 0; i < depth; i++) + tipc_printf(buf, header[i]); tipc_printf(buf, "\n"); } -- cgit v1.2.3-59-g8ed1b From 564e83b51a12b794e3f63a2d872398e1ee21616f Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 17 Aug 2010 11:00:15 +0000 Subject: tipc: Allow connect() to wait indefinitely Cause a socket whose TIPC_CONN_TIMEOUT option is zero to wait indefinitely for a response to a connection request using connect(). Previously, specifying a timeout of 0 ms resulted in an immediate timeout, which was inconsistent with the behavior specified by Posix for a socket's receive and send timeout. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/socket.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 7b81fdd4f6d6..f7ac94de24fe 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -64,6 +64,7 @@ struct tipc_sock { struct sock sk; struct tipc_port *p; struct tipc_portid peer_name; + long conn_timeout; }; #define tipc_sk(sk) ((struct tipc_sock *)(sk)) @@ -240,9 +241,9 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol, sock->state = state; sock_init_data(sock, sk); - sk->sk_rcvtimeo = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT); sk->sk_backlog_rcv = backlog_rcv; tipc_sk(sk)->p = tp_ptr; + tipc_sk(sk)->conn_timeout = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT); spin_unlock_bh(tp_ptr->lock); @@ -1385,6 +1386,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, struct msghdr m = {NULL,}; struct sk_buff *buf; struct tipc_msg *msg; + long timeout; int res; lock_sock(sk); @@ -1445,11 +1447,12 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ + timeout = tipc_sk(sk)->conn_timeout; release_sock(sk); res = wait_event_interruptible_timeout(*sk_sleep(sk), (!skb_queue_empty(&sk->sk_receive_queue) || (sock->state != SS_CONNECTING)), - sk->sk_rcvtimeo); + timeout ? timeout : MAX_SCHEDULE_TIMEOUT); lock_sock(sk); if (res > 0) { @@ -1712,7 +1715,7 @@ static int setsockopt(struct socket *sock, res = tipc_set_portunreturnable(tport->ref, value); break; case TIPC_CONN_TIMEOUT: - sk->sk_rcvtimeo = msecs_to_jiffies(value); + tipc_sk(sk)->conn_timeout = msecs_to_jiffies(value); /* no need to set "res", since already 0 at this point */ break; default: @@ -1767,7 +1770,7 @@ static int getsockopt(struct socket *sock, res = tipc_portunreturnable(tport->ref, &value); break; case TIPC_CONN_TIMEOUT: - value = jiffies_to_msecs(sk->sk_rcvtimeo); + value = jiffies_to_msecs(tipc_sk(sk)->conn_timeout); /* no need to set "res", since already 0 at this point */ break; case TIPC_NODE_RECVQ_DEPTH: -- cgit v1.2.3-59-g8ed1b From 5a68d5ee000bb784c4856391b4861739c8bbd341 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 17 Aug 2010 11:00:16 +0000 Subject: tipc: Prevent missing name table entries when link flip-flops rapidly Ensure that TIPC does not re-establish communication with a neighboring node until it has finished updating all data structures containing information about that node to reflect the earlier loss of contact. Previously, it was possible for TIPC to perform its purge of name table entries relating to the node once contact had already been re-established, resulting in the unwanted removal of valid name table entries. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/discover.c | 8 ++++++++ net/tipc/link.c | 11 ++++++++++- net/tipc/node.c | 19 +++++++++++++++++++ net/tipc/node.h | 2 ++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/net/tipc/discover.c b/net/tipc/discover.c index fc1fcf5e6b53..f28d1ae93125 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -203,6 +203,14 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr) return; } spin_lock_bh(&n_ptr->lock); + + /* Don't talk to neighbor during cleanup after last session */ + + if (n_ptr->cleanup_required) { + spin_unlock_bh(&n_ptr->lock); + return; + } + link = n_ptr->links[b_ptr->identity]; if (!link) { dbg("creating link\n"); diff --git a/net/tipc/link.c b/net/tipc/link.c index 9d18c9b7638b..a6a3102bb4d6 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1869,13 +1869,22 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) goto cont; } - /* Locate unicast link endpoint that should handle message */ + /* Locate neighboring node that sent message */ n_ptr = tipc_node_find(msg_prevnode(msg)); if (unlikely(!n_ptr)) goto cont; tipc_node_lock(n_ptr); + /* Don't talk to neighbor during cleanup after last session */ + + if (n_ptr->cleanup_required) { + tipc_node_unlock(n_ptr); + goto cont; + } + + /* Locate unicast link endpoint that should handle message */ + l_ptr = n_ptr->links[b_ptr->identity]; if (unlikely(!l_ptr)) { tipc_node_unlock(n_ptr); diff --git a/net/tipc/node.c b/net/tipc/node.c index 940851797615..b702c7bf580f 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -383,6 +383,20 @@ static void node_established_contact(struct tipc_node *n_ptr) tipc_highest_allowed_slave); } +static void node_cleanup_finished(unsigned long node_addr) +{ + struct tipc_node *n_ptr; + + read_lock_bh(&tipc_net_lock); + n_ptr = tipc_node_find(node_addr); + if (n_ptr) { + tipc_node_lock(n_ptr); + n_ptr->cleanup_required = 0; + tipc_node_unlock(n_ptr); + } + read_unlock_bh(&tipc_net_lock); +} + static void node_lost_contact(struct tipc_node *n_ptr) { struct cluster *c_ptr; @@ -457,6 +471,11 @@ static void node_lost_contact(struct tipc_node *n_ptr) tipc_k_signal((Handler)ns->handle_node_down, (unsigned long)ns->usr_handle); } + + /* Prevent re-contact with node until all cleanup is done */ + + n_ptr->cleanup_required = 1; + tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); } /** diff --git a/net/tipc/node.h b/net/tipc/node.h index 6f990da5d143..45f3db3a595d 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -52,6 +52,7 @@ * @active_links: pointers to active links to node * @links: pointers to all links to node * @working_links: number of working links to node (both active and standby) + * @cleanup_required: non-zero if cleaning up after a prior loss of contact * @link_cnt: number of links to node * @permit_changeover: non-zero if node has redundant links to this system * @routers: bitmap (used for multicluster communication) @@ -78,6 +79,7 @@ struct tipc_node { struct link *links[MAX_BEARERS]; int link_cnt; int working_links; + int cleanup_required; int permit_changeover; u32 routers[512/32]; int last_router; -- cgit v1.2.3-59-g8ed1b From baeb2ffab4e67bb9174e6166e070a9a8ec94b0f6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 11 Aug 2010 07:02:48 +0000 Subject: drivers/net: Convert unbounded kzalloc calls to kcalloc These changes may be slightly safer in some instances. There are other kzalloc calls with a multiply, but those calls are typically "small fixed #" * sizeof(some pointer)" and those are not converted. Signed-off-by: Joe Perches Acked-by: Gertjan van Wingerde Acked-by: Luciano Coelho Signed-off-by: David S. Miller --- drivers/net/cnic.c | 2 +- drivers/net/ehea/ehea_main.c | 4 ++-- drivers/net/mlx4/alloc.c | 2 +- drivers/net/mlx4/en_rx.c | 2 +- drivers/net/mlx4/profile.c | 2 +- drivers/net/myri10ge/myri10ge.c | 4 ++-- drivers/net/niu.c | 4 ++-- drivers/net/vxge/vxge-main.c | 10 +++++----- drivers/net/wireless/airo.c | 5 ++--- drivers/net/wireless/b43/phy_n.c | 2 +- drivers/net/wireless/ipw2x00/ipw2100.c | 6 +++--- drivers/net/wireless/ipw2x00/ipw2200.c | 12 ++++++------ drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- drivers/net/wireless/rt2x00/rt2x00debug.c | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 4 ++-- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- drivers/net/wireless/wl12xx/wl1271_scan.c | 2 +- 21 files changed, 37 insertions(+), 38 deletions(-) diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 09610323a948..2ab6a7c4ffc1 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -1022,7 +1022,7 @@ static int cnic_alloc_bnx2x_context(struct cnic_dev *dev) if (blks > cp->ethdev->ctx_tbl_len) return -ENOMEM; - cp->ctx_arr = kzalloc(blks * sizeof(struct cnic_ctx), GFP_KERNEL); + cp->ctx_arr = kcalloc(blks, sizeof(struct cnic_ctx), GFP_KERNEL); if (cp->ctx_arr == NULL) return -ENOMEM; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 897719b49f96..0f9b27b93a71 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -180,7 +180,7 @@ static void ehea_update_firmware_handles(void) num_portres * EHEA_NUM_PORTRES_FW_HANDLES; if (num_fw_handles) { - arr = kzalloc(num_fw_handles * sizeof(*arr), GFP_KERNEL); + arr = kcalloc(num_fw_handles, sizeof(*arr), GFP_KERNEL); if (!arr) goto out; /* Keep the existing array */ } else @@ -265,7 +265,7 @@ static void ehea_update_bcmc_registrations(void) } if (num_registrations) { - arr = kzalloc(num_registrations * sizeof(*arr), GFP_ATOMIC); + arr = kcalloc(num_registrations, sizeof(*arr), GFP_ATOMIC); if (!arr) goto out; /* Keep the existing array */ } else diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c index 8c8515619b8e..537997f9443e 100644 --- a/drivers/net/mlx4/alloc.c +++ b/drivers/net/mlx4/alloc.c @@ -188,7 +188,7 @@ int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct, buf->nbufs = (size + PAGE_SIZE - 1) / PAGE_SIZE; buf->npages = buf->nbufs; buf->page_shift = PAGE_SHIFT; - buf->page_list = kzalloc(buf->nbufs * sizeof *buf->page_list, + buf->page_list = kcalloc(buf->nbufs, sizeof(*buf->page_list), GFP_KERNEL); if (!buf->page_list) return -ENOMEM; diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 8e2fcb7103c3..efc3fad468db 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -322,7 +322,7 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, ring->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY; ring->lro.max_desc = mdev->profile.num_lro; ring->lro.max_aggr = MAX_SKB_FRAGS; - ring->lro.lro_arr = kzalloc(mdev->profile.num_lro * + ring->lro.lro_arr = kcalloc(mdev->profile.num_lro, sizeof(struct net_lro_desc), GFP_KERNEL); if (!ring->lro.lro_arr) { diff --git a/drivers/net/mlx4/profile.c b/drivers/net/mlx4/profile.c index 5caf0115fa5b..e749f82865fe 100644 --- a/drivers/net/mlx4/profile.c +++ b/drivers/net/mlx4/profile.c @@ -85,7 +85,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, struct mlx4_resource tmp; int i, j; - profile = kzalloc(MLX4_RES_NUM * sizeof *profile, GFP_KERNEL); + profile = kcalloc(MLX4_RES_NUM, sizeof(*profile), GFP_KERNEL); if (!profile) return -ENOMEM; diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index fb2c0927d3cc..24ab8a43c777 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -3753,8 +3753,8 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) * slices. We give up on MSI-X if we can only get a single * vector. */ - mgp->msix_vectors = kzalloc(mgp->num_slices * - sizeof(*mgp->msix_vectors), GFP_KERNEL); + mgp->msix_vectors = kcalloc(mgp->num_slices, sizeof(*mgp->msix_vectors), + GFP_KERNEL); if (mgp->msix_vectors == NULL) goto disable_msix; for (i = 0; i < mgp->num_slices; i++) { diff --git a/drivers/net/niu.c b/drivers/net/niu.c index bc695d53cdcc..b4cc61f1fc59 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -4504,7 +4504,7 @@ static int niu_alloc_channels(struct niu *np) np->dev->real_num_tx_queues = np->num_tx_rings; - np->rx_rings = kzalloc(np->num_rx_rings * sizeof(struct rx_ring_info), + np->rx_rings = kcalloc(np->num_rx_rings, sizeof(struct rx_ring_info), GFP_KERNEL); err = -ENOMEM; if (!np->rx_rings) @@ -4538,7 +4538,7 @@ static int niu_alloc_channels(struct niu *np) return err; } - np->tx_rings = kzalloc(np->num_tx_rings * sizeof(struct tx_ring_info), + np->tx_rings = kcalloc(np->num_tx_rings, sizeof(struct tx_ring_info), GFP_KERNEL); err = -ENOMEM; if (!np->tx_rings) diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index c7c5605b3728..f5334b287fdb 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -2159,8 +2159,8 @@ start: /* Alarm MSIX Vectors count */ vdev->intr_cnt++; - vdev->entries = kzalloc(vdev->intr_cnt * sizeof(struct msix_entry), - GFP_KERNEL); + vdev->entries = kcalloc(vdev->intr_cnt, sizeof(struct msix_entry), + GFP_KERNEL); if (!vdev->entries) { vxge_debug_init(VXGE_ERR, "%s: memory allocation failed", @@ -2169,9 +2169,9 @@ start: goto alloc_entries_failed; } - vdev->vxge_entries = - kzalloc(vdev->intr_cnt * sizeof(struct vxge_msix_entry), - GFP_KERNEL); + vdev->vxge_entries = kcalloc(vdev->intr_cnt, + sizeof(struct vxge_msix_entry), + GFP_KERNEL); if (!vdev->vxge_entries) { vxge_debug_init(VXGE_ERR, "%s: memory allocation failed", VXGE_DRIVER_NAME); diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 1d05445d4ba3..7d26506957d7 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2723,9 +2723,8 @@ static int airo_networks_allocate(struct airo_info *ai) if (ai->networks) return 0; - ai->networks = - kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement), - GFP_KERNEL); + ai->networks = kcalloc(AIRO_MAX_NETWORK_COUNT, sizeof(BSSListElement), + GFP_KERNEL); if (!ai->networks) { airo_print_warn("", "Out of memory allocating beacons"); return -ENOMEM; diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 5a725703770c..e288c559481d 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1182,7 +1182,7 @@ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, len = bw << 1; } - samples = kzalloc(len * sizeof(struct b43_c32), GFP_KERNEL); + samples = kcalloc(len, sizeof(struct b43_c32), GFP_KERNEL); if (!samples) { b43err(dev->wl, "allocation for samples generation failed\n"); return 0; diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 1189dbb6e2a6..0c67b172d4c6 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -1921,9 +1921,9 @@ static int ipw2100_net_init(struct net_device *dev) bg_band->band = IEEE80211_BAND_2GHZ; bg_band->n_channels = geo->bg_channels; - bg_band->channels = - kzalloc(geo->bg_channels * - sizeof(struct ieee80211_channel), GFP_KERNEL); + bg_band->channels = kcalloc(geo->bg_channels, + sizeof(struct ieee80211_channel), + GFP_KERNEL); if (!bg_band->channels) { ipw2100_down(priv); return -ENOMEM; diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index cb2552a6777c..0f2508384c75 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11467,9 +11467,9 @@ static int ipw_net_init(struct net_device *dev) bg_band->band = IEEE80211_BAND_2GHZ; bg_band->n_channels = geo->bg_channels; - bg_band->channels = - kzalloc(geo->bg_channels * - sizeof(struct ieee80211_channel), GFP_KERNEL); + bg_band->channels = kcalloc(geo->bg_channels, + sizeof(struct ieee80211_channel), + GFP_KERNEL); /* translate geo->bg to bg_band.channels */ for (i = 0; i < geo->bg_channels; i++) { bg_band->channels[i].band = IEEE80211_BAND_2GHZ; @@ -11502,9 +11502,9 @@ static int ipw_net_init(struct net_device *dev) a_band->band = IEEE80211_BAND_5GHZ; a_band->n_channels = geo->a_channels; - a_band->channels = - kzalloc(geo->a_channels * - sizeof(struct ieee80211_channel), GFP_KERNEL); + a_band->channels = kcalloc(geo->a_channels, + sizeof(struct ieee80211_channel), + GFP_KERNEL); /* translate geo->bg to a_band.channels */ for (i = 0; i < geo->a_channels; i++) { a_band->channels[i].band = IEEE80211_BAND_2GHZ; diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 5063e01410e5..8e3fbdf48889 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1481,7 +1481,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Create channel information array */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); + info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index c2a555d5376b..1d174e42f11e 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1795,7 +1795,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Create channel information array */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); + info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index cdaf93f48263..8ddaae44d7fb 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1698,7 +1698,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Create channel information array */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); + info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b66e0fd8f0fa..8c00fbda8664 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2865,7 +2865,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Create channel information array */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); + info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index b0498e7e7aae..2d018ceffc54 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -333,7 +333,7 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file, if (*offset) return 0; - data = kzalloc(lines * MAX_LINE_LENGTH, GFP_KERNEL); + data = kcalloc(lines, MAX_LINE_LENGTH, GFP_KERNEL); if (!data) return -ENOMEM; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index a3401d301058..9c609be95083 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -755,7 +755,7 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, * Allocate all queue entries. */ entry_size = sizeof(*entries) + qdesc->priv_size; - entries = kzalloc(queue->limit * entry_size, GFP_KERNEL); + entries = kcalloc(queue->limit, entry_size, GFP_KERNEL); if (!entries) return -ENOMEM; @@ -891,7 +891,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) */ rt2x00dev->data_queues = 2 + rt2x00dev->ops->tx_queues + req_atim; - queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL); + queue = kcalloc(rt2x00dev->data_queues, sizeof(*queue), GFP_KERNEL); if (!queue) { ERROR(rt2x00dev, "Queue allocation failed.\n"); return -ENOMEM; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index e539c6cb636f..f226582dbc87 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2654,7 +2654,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Create channel information array */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); + info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index aa9de18fd410..99985a218653 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2084,7 +2084,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Create channel information array */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); + info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c index fec43eed8c55..30dc1000f563 100644 --- a/drivers/net/wireless/wl12xx/wl1271_scan.c +++ b/drivers/net/wireless/wl12xx/wl1271_scan.c @@ -248,7 +248,7 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, wl->scan.req = req; - wl->scan.scanned_ch = kzalloc(req->n_channels * + wl->scan.scanned_ch = kcalloc(req->n_channels, sizeof(*wl->scan.scanned_ch), GFP_KERNEL); wl1271_scan_stm(wl); -- cgit v1.2.3-59-g8ed1b From 3d529946ce292336793b85198bd59afc75e16bd4 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 18 Aug 2010 09:48:31 +1000 Subject: Fix spelling mistake in jhash Fix a spelling mistake. Signed-off-by: Anton Blanchard Signed-off-by: Jiri Kosina --- include/linux/jhash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/jhash.h b/include/linux/jhash.h index 2a2f99fbcb16..ced1159fa4f2 100644 --- a/include/linux/jhash.h +++ b/include/linux/jhash.h @@ -116,7 +116,7 @@ static inline u32 jhash2(const u32 *k, u32 length, u32 initval) /* A special ultra-optimized versions that knows they are hashing exactly * 3, 2 or 1 word(s). * - * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally + * NOTE: In particular the "c += length; __jhash_mix(a,b,c);" normally * done at the end is not done here. */ static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) -- cgit v1.2.3-59-g8ed1b From 415b54e37a5d0efa7ff5d4d12285b1e82d574c3e Mon Sep 17 00:00:00 2001 From: Nikanth Karthikesan Date: Tue, 17 Aug 2010 15:39:09 +0530 Subject: Fix typo s/contenious/continuous in comment Fix typo s/contenious/continuous in comment. Signed-off-by: Nikanth Karthikesan Signed-off-by: Jiri Kosina --- mm/vmscan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index ec5ddccbf82e..18fa3d76b3e0 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -79,8 +79,8 @@ struct scan_control { int order; /* - * Intend to reclaim enough contenious memory rather than to reclaim - * enough amount memory. I.e, it's the mode for high order allocation. + * Intend to reclaim enough continuous memory rather than reclaim + * enough amount of memory. i.e, mode for high order allocation. */ bool lumpy_reclaim_mode; -- cgit v1.2.3-59-g8ed1b From 720ffa4cf3f6b76c27737a9d57bd0e6cc6af1fba Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 18 Aug 2010 00:30:30 +0100 Subject: ASoC: core - fix build warning on x86_64 Output size_t type as a "%Zu" to avoid warnings. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3d480eb3555f..7093c1787128 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2916,7 +2916,7 @@ int snd_soc_register_dais(struct device *dev, struct snd_soc_dai *dai; int i, ret = 0; - dev_dbg(dev, "dai register %s #%d\n", dev_name(dev), count); + dev_dbg(dev, "dai register %s #%Zu\n", dev_name(dev), count); for (i = 0; i < count; i++) { -- cgit v1.2.3-59-g8ed1b From bd76af0f87f7a1815b311bde269a3f18305b3169 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 18 Aug 2010 14:16:54 +0200 Subject: ALSA: pcm midlevel code - add time check for double interrupt acknowledge The current code in pcm_lib.c do all checks using only the position in the ring buffer. Unfortunately, where the interrupts gets delayed or merged into one, we need another timing source to check when the buffer size boundary overlaps to avoid the wrong updating of the ring buffer pointers. This code uses jiffies to check the right time window without any performance impact. Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 1 + sound/core/pcm_lib.c | 14 +++++++++----- sound/core/pcm_native.c | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 85f1c6bf8566..dfd9b76b1853 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -278,6 +278,7 @@ struct snd_pcm_runtime { snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */ unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */ + unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */ snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */ /* -- HW params -- */ diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index e23e0e7ab26f..a1707cca9c66 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -334,11 +334,15 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, /* delta = "expected next hw_ptr" for in_interrupt != 0 */ delta = runtime->hw_ptr_interrupt + runtime->period_size; if (delta > new_hw_ptr) { - hw_base += runtime->buffer_size; - if (hw_base >= runtime->boundary) - hw_base = 0; - new_hw_ptr = hw_base + pos; - goto __delta; + /* check for double acknowledged interrupts */ + hdelta = jiffies - runtime->hw_ptr_jiffies; + if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { + hw_base += runtime->buffer_size; + if (hw_base >= runtime->boundary) + hw_base = 0; + new_hw_ptr = hw_base + pos; + goto __delta; + } } } /* new_hw_ptr might be lower than old_hw_ptr in case when */ diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 134fc6c2e08d..e2e73895db12 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -864,6 +864,8 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state) struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_trigger_tstamp(substream); runtime->hw_ptr_jiffies = jiffies; + runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / + runtime->rate; runtime->status->state = state; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0) -- cgit v1.2.3-59-g8ed1b From e77125105bbfe71f325466cdf9a16e496c96ac7a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 17 Aug 2010 23:40:24 +0100 Subject: ASoC: Support non-crystal master clocks for WM8731 Instead of unconditionally enabling the crystal oscillator on the WM8731 only enable it when explicitly selected via set_sysclk(), allowing machine drivers to specify that they drive a clock into MCLK alone. This avoids any conflicts between the oscillator and the external MCLK source and saves power for systems which do not need the oscillator. This should also deliver a small power saving on systems using the crystal since the oscillator will only be enabled when the ADC or DAC is active. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/atmel/sam9g20_wm8731.c | 2 +- sound/soc/au1x/db1200.c | 2 +- sound/soc/codecs/wm8731.c | 31 +++++++++++++++++++++++++++++-- sound/soc/codecs/wm8731.h | 4 +++- sound/soc/pxa/corgi.c | 2 +- sound/soc/pxa/poodle.c | 2 +- 6 files changed, 36 insertions(+), 7 deletions(-) diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 66a6f1879689..8399ac46cb33 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -146,7 +146,7 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) "at91sam9g20ek_wm8731 " ": at91sam9g20ek_wm8731_init() called\n"); - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, MCLK_RATE, SND_SOC_CLOCK_IN); if (ret < 0) { printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret); diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index 8780c90107fc..d8dc8225576a 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c @@ -49,7 +49,7 @@ static int db1200_i2s_startup(struct snd_pcm_substream *substream) int ret; /* WM8731 has its own 12MHz crystal */ - snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, + snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, 12000000, SND_SOC_CLOCK_IN); /* codec is bitclock and lrclk master */ diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 19844fc8cb1d..56f540838745 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -46,6 +46,7 @@ struct wm8731_priv { struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; u16 reg_cache[WM8731_CACHEREGNUM]; unsigned int sysclk; + int sysclk_type; }; @@ -110,6 +111,7 @@ static const struct snd_kcontrol_new wm8731_input_mux_controls = SOC_DAPM_ENUM("Input Select", wm8731_enum[0]); static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0), SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, &wm8731_output_mixer_controls[0], ARRAY_SIZE(wm8731_output_mixer_controls)), @@ -127,7 +129,18 @@ SND_SOC_DAPM_INPUT("RLINEIN"), SND_SOC_DAPM_INPUT("LLINEIN"), }; +static int wm8731_check_osc(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec); + + return wm8731->sysclk_type == WM8731_SYSCLK_MCLK; +} + static const struct snd_soc_dapm_route intercon[] = { + {"DAC", NULL, "OSC", wm8731_check_osc}, + {"ADC", NULL, "OSC", wm8731_check_osc}, + /* output mixer */ {"Output Mixer", "Line Bypass Switch", "Line Input"}, {"Output Mixer", "HiFi Playback Switch", "DAC"}, @@ -285,6 +298,15 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); + switch (clk_id) { + case WM8731_SYSCLK_XTAL: + case WM8731_SYSCLK_MCLK: + wm8731->sysclk_type = clk_id; + break; + default: + return -EINVAL; + } + switch (freq) { case 11289600: case 12000000: @@ -292,9 +314,14 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai, case 16934400: case 18432000: wm8731->sysclk = freq; - return 0; + break; + default: + return -EINVAL; } - return -EINVAL; + + snd_soc_dapm_sync(codec); + + return 0; } diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h index 73a70e206ba9..e9c0c76ab73b 100644 --- a/sound/soc/codecs/wm8731.h +++ b/sound/soc/codecs/wm8731.h @@ -31,7 +31,9 @@ #define WM8731_CACHEREGNUM 10 -#define WM8731_SYSCLK 0 +#define WM8731_SYSCLK_XTAL 1 +#define WM8731_SYSCLK_MCLK 2 + #define WM8731_DAI 0 #endif diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 555689cf6727..97e9423615c9 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -149,7 +149,7 @@ static int corgi_hw_params(struct snd_pcm_substream *substream, return ret; /* set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk, + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk, SND_SOC_CLOCK_IN); if (ret < 0) return ret; diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index add0e1c25bc8..fa752f6ec37d 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -128,7 +128,7 @@ static int poodle_hw_params(struct snd_pcm_substream *substream, return ret; /* set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk, + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk, SND_SOC_CLOCK_IN); if (ret < 0) return ret; -- cgit v1.2.3-59-g8ed1b From dad965f07be946726c6153cf578d089ea991f41e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 18 Aug 2010 16:25:59 +0100 Subject: ASoC: Fix device name for AT91SAM9G20-EK devices A couple of typos in the multi-component conversion. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/atmel/sam9g20_wm8731.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 8399ac46cb33..cf029a89ef76 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -183,8 +183,8 @@ static struct snd_soc_dai_link at91sam9g20ek_dai = { .cpu_dai_name = "atmel-ssc-dai.0", .codec_dai_name = "wm8731-hifi", .init = at91sam9g20ek_wm8731_init, - .platform_name = "atmel_pcm-audio", - .codec_name = "wm8731-codec.0-001a", + .platform_name = "atmel-pcm-audio", + .codec_name = "wm8731-codec.0-001b", .ops = &at91sam9g20ek_ops, }; -- cgit v1.2.3-59-g8ed1b From abfa4eae0bd2723859931631771ac275f97cada4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 18 Aug 2010 16:29:37 +0100 Subject: ASoC: Add simplfied device registration for Atmel SSC devices Since the SSC is already being registered as a device under arch and the DMA and SSC hardware are pretty much the same provide a simplified device registration function for the Atmel SSC which will add the ASoC-specific devices within the ASoC code, parenting the SSC device off the actual SSC device. Also use it in the sam9g20-ek driver. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/atmel/atmel_ssc_dai.c | 57 +++++++++++++++++++++++++++++++++++++--- sound/soc/atmel/atmel_ssc_dai.h | 2 ++ sound/soc/atmel/sam9g20_wm8731.c | 6 +++++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index eabf66af12cd..5d230cee3fa7 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -789,13 +789,14 @@ static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = { static __devinit int asoc_ssc_probe(struct platform_device *pdev) { - return snd_soc_register_dais(&pdev->dev, atmel_ssc_dai, - ARRAY_SIZE(atmel_ssc_dai)); + BUG_ON(pdev->id < 0); + BUG_ON(pdev->id >= ARRAY_SIZE(atmel_ssc_dai)); + return snd_soc_register_dai(&pdev->dev, &atmel_ssc_dai[pdev->id]); } static int __devexit asoc_ssc_remove(struct platform_device *pdev) { - snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(atmel_ssc_dai)); + snd_soc_unregister_dai(&pdev->dev); return 0; } @@ -809,6 +810,56 @@ static struct platform_driver asoc_ssc_driver = { .remove = __devexit_p(asoc_ssc_remove), }; +/** + * atmel_ssc_set_audio - Allocate the specified SSC for audio use. + */ +int atmel_ssc_set_audio(int ssc_id) +{ + struct ssc_device *ssc; + static struct platform_device *dma_pdev; + struct platform_device *ssc_pdev; + int ret; + + if (ssc_id < 0 || ssc_id >= ARRAY_SIZE(atmel_ssc_dai)) + return -EINVAL; + + /* Allocate a dummy device for DMA if we don't have one already */ + if (!dma_pdev) { + dma_pdev = platform_device_alloc("atmel-pcm-audio", -1); + if (!dma_pdev) + return -ENOMEM; + + ret = platform_device_add(dma_pdev); + if (ret < 0) { + platform_device_put(dma_pdev); + dma_pdev = NULL; + return ret; + } + } + + ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id); + if (!ssc_pdev) { + ssc_free(ssc); + return -ENOMEM; + } + + /* If we can grab the SSC briefly to parent the DAI device off it */ + ssc = ssc_request(ssc_id); + if (IS_ERR(ssc)) + pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n", + PTR_ERR(ssc)); + else + ssc_pdev->dev.parent = &(ssc->pdev->dev); + ssc_free(ssc); + + ret = platform_device_add(ssc_pdev); + if (ret < 0) + platform_device_put(ssc_pdev); + + return ret; +} +EXPORT_SYMBOL_GPL(atmel_ssc_set_audio); + static int __init snd_atmel_ssc_init(void) { return platform_driver_register(&asoc_ssc_driver); diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h index 392a46953112..5d4f0f9b4d9a 100644 --- a/sound/soc/atmel/atmel_ssc_dai.h +++ b/sound/soc/atmel/atmel_ssc_dai.h @@ -117,4 +117,6 @@ struct atmel_ssc_info { struct atmel_ssc_state ssc_state; }; +int atmel_ssc_set_audio(int ssc); + #endif /* _AT91_SSC_DAI_H */ diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index cf029a89ef76..293569dfd0ed 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -205,6 +205,12 @@ static int __init at91sam9g20ek_init(void) if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc())) return -ENODEV; + ret = atmel_ssc_set_audio(0); + if (ret != 0) { + pr_err("Failed to set SSC 0 for audio: %d\n", ret); + return ret; + } + /* * Codec MCLK is supplied by PCK0 - set it up. */ -- cgit v1.2.3-59-g8ed1b From f213f4b51777408c12bf6b890a9bcae385f7698f Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Thu, 19 Aug 2010 00:35:25 +0800 Subject: ASoC: add 88pm860x codec driver Add 88PM860x codec driver. 88PM860x codec supports two interfaces. And it also supports headset/mic/hook/short detection. Signed-off-by: Haojian Zhuang Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/88pm860x-codec.c | 1486 +++++++++++++++++++++++++++++++++++++ sound/soc/codecs/88pm860x-codec.h | 97 +++ sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + 4 files changed, 1589 insertions(+) create mode 100644 sound/soc/codecs/88pm860x-codec.c create mode 100644 sound/soc/codecs/88pm860x-codec.h diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c new file mode 100644 index 000000000000..01d19e9f53f9 --- /dev/null +++ b/sound/soc/codecs/88pm860x-codec.c @@ -0,0 +1,1486 @@ +/* + * 88pm860x-codec.c -- 88PM860x ALSA SoC Audio Driver + * + * Copyright 2010 Marvell International Ltd. + * Author: Haojian Zhuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "88pm860x-codec.h" + +#define MAX_NAME_LEN 20 +#define REG_CACHE_SIZE 0x40 +#define REG_CACHE_BASE 0xb0 + +/* Status Register 1 (0x01) */ +#define REG_STATUS_1 0x01 +#define MIC_STATUS (1 << 7) +#define HOOK_STATUS (1 << 6) +#define HEADSET_STATUS (1 << 5) + +/* Mic Detection Register (0x37) */ +#define REG_MIC_DET 0x37 +#define CONTINUOUS_POLLING (3 << 1) +#define EN_MIC_DET (1 << 0) +#define MICDET_MASK 0x07 + +/* Headset Detection Register (0x38) */ +#define REG_HS_DET 0x38 +#define EN_HS_DET (1 << 0) + +/* Misc2 Register (0x42) */ +#define REG_MISC2 0x42 +#define AUDIO_PLL (1 << 5) +#define AUDIO_SECTION_RESET (1 << 4) +#define AUDIO_SECTION_ON (1 << 3) + +/* PCM Interface Register 2 (0xb1) */ +#define PCM_INF2_BCLK (1 << 6) /* Bit clock polarity */ +#define PCM_INF2_FS (1 << 5) /* Frame Sync polarity */ +#define PCM_INF2_MASTER (1 << 4) /* Master / Slave */ +#define PCM_INF2_18WL (1 << 3) /* 18 / 16 bits */ +#define PCM_GENERAL_I2S 0 +#define PCM_EXACT_I2S 1 +#define PCM_LEFT_I2S 2 +#define PCM_RIGHT_I2S 3 +#define PCM_SHORT_FS 4 +#define PCM_LONG_FS 5 +#define PCM_MODE_MASK 7 + +/* I2S Interface Register 4 (0xbe) */ +#define I2S_EQU_BYP (1 << 6) + +/* DAC Offset Register (0xcb) */ +#define DAC_MUTE (1 << 7) +#define MUTE_LEFT (1 << 6) +#define MUTE_RIGHT (1 << 2) + +/* ADC Analog Register 1 (0xd0) */ +#define REG_ADC_ANA_1 0xd0 +#define MIC1BIAS_MASK 0x60 + +/* Earpiece/Speaker Control Register 2 (0xda) */ +#define REG_EAR2 0xda +#define RSYNC_CHANGE (1 << 2) + +/* Audio Supplies Register 2 (0xdc) */ +#define REG_SUPPLIES2 0xdc +#define LDO15_READY (1 << 4) +#define LDO15_EN (1 << 3) +#define CPUMP_READY (1 << 2) +#define CPUMP_EN (1 << 1) +#define AUDIO_EN (1 << 0) +#define SUPPLY_MASK (LDO15_EN | CPUMP_EN | AUDIO_EN) + +/* Audio Enable Register 1 (0xdd) */ +#define ADC_MOD_RIGHT (1 << 1) +#define ADC_MOD_LEFT (1 << 0) + +/* Audio Enable Register 2 (0xde) */ +#define ADC_LEFT (1 << 5) +#define ADC_RIGHT (1 << 4) + +/* DAC Enable Register 2 (0xe1) */ +#define DAC_LEFT (1 << 5) +#define DAC_RIGHT (1 << 4) +#define MODULATOR (1 << 3) + +/* Shorts Register (0xeb) */ +#define REG_SHORTS 0xeb +#define CLR_SHORT_LO2 (1 << 7) +#define SHORT_LO2 (1 << 6) +#define CLR_SHORT_LO1 (1 << 5) +#define SHORT_LO1 (1 << 4) +#define CLR_SHORT_HS2 (1 << 3) +#define SHORT_HS2 (1 << 2) +#define CLR_SHORT_HS1 (1 << 1) +#define SHORT_HS1 (1 << 0) + +/* + * This widget should be just after DAC & PGA in DAPM power-on sequence and + * before DAC & PGA in DAPM power-off sequence. + */ +#define PM860X_DAPM_OUTPUT(wname, wevent) \ +{ .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ + .shift = 0, .invert = 0, .kcontrols = NULL, \ + .num_kcontrols = 0, .event = wevent, \ + .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD, } + +struct pm860x_det { + struct snd_soc_jack *hp_jack; + struct snd_soc_jack *mic_jack; + int hp_det; + int mic_det; + int hook_det; + int hs_shrt; + int lo_shrt; +}; + +struct pm860x_priv { + unsigned int sysclk; + unsigned int pcmclk; + unsigned int dir; + unsigned int filter; + struct snd_soc_codec *codec; + struct i2c_client *i2c; + struct pm860x_chip *chip; + struct pm860x_det det; + + int irq[4]; + unsigned char name[4][MAX_NAME_LEN]; + unsigned char reg_cache[REG_CACHE_SIZE]; +}; + +/* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */ +static const DECLARE_TLV_DB_SCALE(dpga_tlv, -9450, 150, 1); + +/* -9dB to 0db in 3dB steps */ +static const DECLARE_TLV_DB_SCALE(adc_tlv, -900, 300, 0); + +/* {-23, -17, -13.5, -11, -9, -6, -3, 0}dB */ +static const unsigned int mic_tlv[] = { + TLV_DB_RANGE_HEAD(5), + 0, 0, TLV_DB_SCALE_ITEM(-2300, 0, 0), + 1, 1, TLV_DB_SCALE_ITEM(-1700, 0, 0), + 2, 2, TLV_DB_SCALE_ITEM(-1350, 0, 0), + 3, 3, TLV_DB_SCALE_ITEM(-1100, 0, 0), + 4, 7, TLV_DB_SCALE_ITEM(-900, 300, 0), +}; + +/* {0, 0, 0, -6, 0, 6, 12, 18}dB */ +static const unsigned int aux_tlv[] = { + TLV_DB_RANGE_HEAD(2), + 0, 2, TLV_DB_SCALE_ITEM(0, 0, 0), + 3, 7, TLV_DB_SCALE_ITEM(-600, 600, 0), +}; + +/* {-16, -13, -10, -7, -5.2, -3,3, -2.2, 0}dB, mute instead of -16dB */ +static const unsigned int out_tlv[] = { + TLV_DB_RANGE_HEAD(4), + 0, 3, TLV_DB_SCALE_ITEM(-1600, 300, 1), + 4, 4, TLV_DB_SCALE_ITEM(-520, 0, 0), + 5, 5, TLV_DB_SCALE_ITEM(-330, 0, 0), + 6, 7, TLV_DB_SCALE_ITEM(-220, 220, 0), +}; + +static const unsigned int st_tlv[] = { + TLV_DB_RANGE_HEAD(8), + 0, 1, TLV_DB_SCALE_ITEM(-12041, 602, 0), + 2, 3, TLV_DB_SCALE_ITEM(-11087, 250, 0), + 4, 5, TLV_DB_SCALE_ITEM(-10643, 158, 0), + 6, 7, TLV_DB_SCALE_ITEM(-10351, 116, 0), + 8, 9, TLV_DB_SCALE_ITEM(-10133, 92, 0), + 10, 13, TLV_DB_SCALE_ITEM(-9958, 70, 0), + 14, 17, TLV_DB_SCALE_ITEM(-9689, 53, 0), + 18, 271, TLV_DB_SCALE_ITEM(-9484, 37, 0), +}; + +/* Sidetone Gain = M * 2^(-5-N) */ +struct st_gain { + unsigned int db; + unsigned int m; + unsigned int n; +}; + +static struct st_gain st_table[] = { + {-12041, 1, 15}, {-11439, 1, 14}, {-11087, 3, 15}, {-10837, 1, 13}, + {-10643, 5, 15}, {-10485, 3, 14}, {-10351, 7, 15}, {-10235, 1, 12}, + {-10133, 9, 15}, {-10041, 5, 14}, { -9958, 11, 15}, { -9883, 3, 13}, + { -9813, 13, 15}, { -9749, 7, 14}, { -9689, 15, 15}, { -9633, 1, 11}, + { -9580, 17, 15}, { -9531, 9, 14}, { -9484, 19, 15}, { -9439, 5, 13}, + { -9397, 21, 15}, { -9356, 11, 14}, { -9318, 23, 15}, { -9281, 3, 12}, + { -9245, 25, 15}, { -9211, 13, 14}, { -9178, 27, 15}, { -9147, 7, 13}, + { -9116, 29, 15}, { -9087, 15, 14}, { -9058, 31, 15}, { -9031, 1, 10}, + { -8978, 17, 14}, { -8929, 9, 13}, { -8882, 19, 14}, { -8837, 5, 12}, + { -8795, 21, 14}, { -8754, 11, 13}, { -8716, 23, 14}, { -8679, 3, 11}, + { -8643, 25, 14}, { -8609, 13, 13}, { -8576, 27, 14}, { -8545, 7, 12}, + { -8514, 29, 14}, { -8485, 15, 13}, { -8456, 31, 14}, { -8429, 1, 9}, + { -8376, 17, 13}, { -8327, 9, 12}, { -8280, 19, 13}, { -8235, 5, 11}, + { -8193, 21, 13}, { -8152, 11, 12}, { -8114, 23, 13}, { -8077, 3, 10}, + { -8041, 25, 13}, { -8007, 13, 12}, { -7974, 27, 13}, { -7943, 7, 11}, + { -7912, 29, 13}, { -7883, 15, 12}, { -7854, 31, 13}, { -7827, 1, 8}, + { -7774, 17, 12}, { -7724, 9, 11}, { -7678, 19, 12}, { -7633, 5, 10}, + { -7591, 21, 12}, { -7550, 11, 11}, { -7512, 23, 12}, { -7475, 3, 9}, + { -7439, 25, 12}, { -7405, 13, 11}, { -7372, 27, 12}, { -7341, 7, 10}, + { -7310, 29, 12}, { -7281, 15, 11}, { -7252, 31, 12}, { -7225, 1, 7}, + { -7172, 17, 11}, { -7122, 9, 10}, { -7075, 19, 11}, { -7031, 5, 9}, + { -6989, 21, 11}, { -6948, 11, 10}, { -6910, 23, 11}, { -6873, 3, 8}, + { -6837, 25, 11}, { -6803, 13, 10}, { -6770, 27, 11}, { -6739, 7, 9}, + { -6708, 29, 11}, { -6679, 15, 10}, { -6650, 31, 11}, { -6623, 1, 6}, + { -6570, 17, 10}, { -6520, 9, 9}, { -6473, 19, 10}, { -6429, 5, 8}, + { -6386, 21, 10}, { -6346, 11, 9}, { -6307, 23, 10}, { -6270, 3, 7}, + { -6235, 25, 10}, { -6201, 13, 9}, { -6168, 27, 10}, { -6137, 7, 8}, + { -6106, 29, 10}, { -6077, 15, 9}, { -6048, 31, 10}, { -6021, 1, 5}, + { -5968, 17, 9}, { -5918, 9, 8}, { -5871, 19, 9}, { -5827, 5, 7}, + { -5784, 21, 9}, { -5744, 11, 8}, { -5705, 23, 9}, { -5668, 3, 6}, + { -5633, 25, 9}, { -5599, 13, 8}, { -5566, 27, 9}, { -5535, 7, 7}, + { -5504, 29, 9}, { -5475, 15, 8}, { -5446, 31, 9}, { -5419, 1, 4}, + { -5366, 17, 8}, { -5316, 9, 7}, { -5269, 19, 8}, { -5225, 5, 6}, + { -5182, 21, 8}, { -5142, 11, 7}, { -5103, 23, 8}, { -5066, 3, 5}, + { -5031, 25, 8}, { -4997, 13, 7}, { -4964, 27, 8}, { -4932, 7, 6}, + { -4902, 29, 8}, { -4873, 15, 7}, { -4844, 31, 8}, { -4816, 1, 3}, + { -4764, 17, 7}, { -4714, 9, 6}, { -4667, 19, 7}, { -4623, 5, 5}, + { -4580, 21, 7}, { -4540, 11, 6}, { -4501, 23, 7}, { -4464, 3, 4}, + { -4429, 25, 7}, { -4395, 13, 6}, { -4362, 27, 7}, { -4330, 7, 5}, + { -4300, 29, 7}, { -4270, 15, 6}, { -4242, 31, 7}, { -4214, 1, 2}, + { -4162, 17, 6}, { -4112, 9, 5}, { -4065, 19, 6}, { -4021, 5, 4}, + { -3978, 21, 6}, { -3938, 11, 5}, { -3899, 23, 6}, { -3862, 3, 3}, + { -3827, 25, 6}, { -3793, 13, 5}, { -3760, 27, 6}, { -3728, 7, 4}, + { -3698, 29, 6}, { -3668, 15, 5}, { -3640, 31, 6}, { -3612, 1, 1}, + { -3560, 17, 5}, { -3510, 9, 4}, { -3463, 19, 5}, { -3419, 5, 3}, + { -3376, 21, 5}, { -3336, 11, 4}, { -3297, 23, 5}, { -3260, 3, 2}, + { -3225, 25, 5}, { -3191, 13, 4}, { -3158, 27, 5}, { -3126, 7, 3}, + { -3096, 29, 5}, { -3066, 15, 4}, { -3038, 31, 5}, { -3010, 1, 0}, + { -2958, 17, 4}, { -2908, 9, 3}, { -2861, 19, 4}, { -2816, 5, 2}, + { -2774, 21, 4}, { -2734, 11, 3}, { -2695, 23, 4}, { -2658, 3, 1}, + { -2623, 25, 4}, { -2589, 13, 3}, { -2556, 27, 4}, { -2524, 7, 2}, + { -2494, 29, 4}, { -2464, 15, 3}, { -2436, 31, 4}, { -2408, 2, 0}, + { -2356, 17, 3}, { -2306, 9, 2}, { -2259, 19, 3}, { -2214, 5, 1}, + { -2172, 21, 3}, { -2132, 11, 2}, { -2093, 23, 3}, { -2056, 3, 0}, + { -2021, 25, 3}, { -1987, 13, 2}, { -1954, 27, 3}, { -1922, 7, 1}, + { -1892, 29, 3}, { -1862, 15, 2}, { -1834, 31, 3}, { -1806, 4, 0}, + { -1754, 17, 2}, { -1704, 9, 1}, { -1657, 19, 2}, { -1612, 5, 0}, + { -1570, 21, 2}, { -1530, 11, 1}, { -1491, 23, 2}, { -1454, 6, 0}, + { -1419, 25, 2}, { -1384, 13, 1}, { -1352, 27, 2}, { -1320, 7, 0}, + { -1290, 29, 2}, { -1260, 15, 1}, { -1232, 31, 2}, { -1204, 8, 0}, + { -1151, 17, 1}, { -1102, 9, 0}, { -1055, 19, 1}, { -1010, 10, 0}, + { -968, 21, 1}, { -928, 11, 0}, { -889, 23, 1}, { -852, 12, 0}, + { -816, 25, 1}, { -782, 13, 0}, { -750, 27, 1}, { -718, 14, 0}, + { -688, 29, 1}, { -658, 15, 0}, { -630, 31, 1}, { -602, 16, 0}, + { -549, 17, 0}, { -500, 18, 0}, { -453, 19, 0}, { -408, 20, 0}, + { -366, 21, 0}, { -325, 22, 0}, { -287, 23, 0}, { -250, 24, 0}, + { -214, 25, 0}, { -180, 26, 0}, { -148, 27, 0}, { -116, 28, 0}, + { -86, 29, 0}, { -56, 30, 0}, { -28, 31, 0}, { 0, 0, 0}, +}; + +static int pm860x_volatile(unsigned int reg) +{ + BUG_ON(reg >= REG_CACHE_SIZE); + + switch (reg) { + case PM860X_AUDIO_SUPPLIES_2: + return 1; + } + + return 0; +} + +static unsigned int pm860x_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + unsigned char *cache = codec->reg_cache; + + BUG_ON(reg >= REG_CACHE_SIZE); + + if (pm860x_volatile(reg)) + return cache[reg]; + + reg += REG_CACHE_BASE; + + return pm860x_reg_read(codec->control_data, reg); +} + +static int pm860x_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + unsigned char *cache = codec->reg_cache; + + BUG_ON(reg >= REG_CACHE_SIZE); + + if (!pm860x_volatile(reg)) + cache[reg] = (unsigned char)value; + + reg += REG_CACHE_BASE; + + return pm860x_reg_write(codec->control_data, reg, value); +} + +static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned int reg = mc->reg; + unsigned int reg2 = mc->rreg; + int val[2], val2[2], i; + + val[0] = snd_soc_read(codec, reg) & 0x3f; + val[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT) >> 4) & 0xf; + val2[0] = snd_soc_read(codec, reg2) & 0x3f; + val2[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT)) & 0xf; + + for (i = 0; i < ARRAY_SIZE(st_table); i++) { + if ((st_table[i].m == val[0]) && (st_table[i].n == val[1])) + ucontrol->value.integer.value[0] = i; + if ((st_table[i].m == val2[0]) && (st_table[i].n == val2[1])) + ucontrol->value.integer.value[1] = i; + } + return 0; +} + +static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned int reg = mc->reg; + unsigned int reg2 = mc->rreg; + int err; + unsigned int val, val2; + + val = ucontrol->value.integer.value[0]; + val2 = ucontrol->value.integer.value[1]; + + err = snd_soc_update_bits(codec, reg, 0x3f, st_table[val].m); + if (err < 0) + return err; + err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0xf0, + st_table[val].n << 4); + if (err < 0) + return err; + + err = snd_soc_update_bits(codec, reg2, 0x3f, st_table[val2].m); + if (err < 0) + return err; + err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0x0f, + st_table[val2].n); + return err; +} + +static int snd_soc_get_volsw_2r_out(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned int reg = mc->reg; + unsigned int reg2 = mc->rreg; + unsigned int shift = mc->shift; + int max = mc->max, val, val2; + unsigned int mask = (1 << fls(max)) - 1; + + val = snd_soc_read(codec, reg) >> shift; + val2 = snd_soc_read(codec, reg2) >> shift; + ucontrol->value.integer.value[0] = (max - val) & mask; + ucontrol->value.integer.value[1] = (max - val2) & mask; + + return 0; +} + +static int snd_soc_put_volsw_2r_out(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned int reg = mc->reg; + unsigned int reg2 = mc->rreg; + unsigned int shift = mc->shift; + int max = mc->max; + unsigned int mask = (1 << fls(max)) - 1; + int err; + unsigned int val, val2, val_mask; + + val_mask = mask << shift; + val = ((max - ucontrol->value.integer.value[0]) & mask); + val2 = ((max - ucontrol->value.integer.value[1]) & mask); + + val = val << shift; + val2 = val2 << shift; + + err = snd_soc_update_bits(codec, reg, val_mask, val); + if (err < 0) + return err; + + err = snd_soc_update_bits(codec, reg2, val_mask, val2); + return err; +} + +/* DAPM Widget Events */ +/* + * A lot registers are belong to RSYNC domain. It requires enabling RSYNC bit + * after updating these registers. Otherwise, these updated registers won't + * be effective. + */ +static int pm860x_rsync_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + + /* + * In order to avoid current on the load, mute power-on and power-off + * should be transients. + * Unmute by DAC_MUTE. It should be unmuted when DAPM sequence is + * finished. + */ + snd_soc_update_bits(codec, PM860X_DAC_OFFSET, DAC_MUTE, 0); + snd_soc_update_bits(codec, PM860X_EAR_CTRL_2, + RSYNC_CHANGE, RSYNC_CHANGE); + return 0; +} + +static int pm860x_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + unsigned int dac = 0; + int data; + + if (!strcmp(w->name, "Left DAC")) + dac = DAC_LEFT; + if (!strcmp(w->name, "Right DAC")) + dac = DAC_RIGHT; + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (dac) { + /* Auto mute in power-on sequence. */ + dac |= MODULATOR; + snd_soc_update_bits(codec, PM860X_DAC_OFFSET, + DAC_MUTE, DAC_MUTE); + snd_soc_update_bits(codec, PM860X_EAR_CTRL_2, + RSYNC_CHANGE, RSYNC_CHANGE); + /* update dac */ + snd_soc_update_bits(codec, PM860X_DAC_EN_2, + dac, dac); + } + break; + case SND_SOC_DAPM_PRE_PMD: + if (dac) { + /* Auto mute in power-off sequence. */ + snd_soc_update_bits(codec, PM860X_DAC_OFFSET, + DAC_MUTE, DAC_MUTE); + snd_soc_update_bits(codec, PM860X_EAR_CTRL_2, + RSYNC_CHANGE, RSYNC_CHANGE); + /* update dac */ + data = snd_soc_read(codec, PM860X_DAC_EN_2); + data &= ~dac; + if (!(data & (DAC_LEFT | DAC_RIGHT))) + data &= ~MODULATOR; + snd_soc_write(codec, PM860X_DAC_EN_2, data); + } + break; + } + return 0; +} + +static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"}; + +static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"}; + +static const struct soc_enum pm860x_hs1_opamp_enum = + SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts); + +static const struct soc_enum pm860x_hs2_opamp_enum = + SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts); + +static const struct soc_enum pm860x_hs1_pa_enum = + SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts); + +static const struct soc_enum pm860x_hs2_pa_enum = + SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts); + +static const struct soc_enum pm860x_lo1_opamp_enum = + SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts); + +static const struct soc_enum pm860x_lo2_opamp_enum = + SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts); + +static const struct soc_enum pm860x_lo1_pa_enum = + SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts); + +static const struct soc_enum pm860x_lo2_pa_enum = + SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts); + +static const struct soc_enum pm860x_spk_pa_enum = + SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts); + +static const struct soc_enum pm860x_ear_pa_enum = + SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts); + +static const struct soc_enum pm860x_spk_ear_opamp_enum = + SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts); + +static const struct snd_kcontrol_new pm860x_snd_controls[] = { + SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2, + PM860X_ADC_ANA_3, 6, 3, 0, adc_tlv), + SOC_DOUBLE_TLV("AUX Capture Volume", PM860X_ADC_ANA_3, 0, 3, 7, 0, + aux_tlv), + SOC_SINGLE_TLV("MIC1 Capture Volume", PM860X_ADC_ANA_2, 0, 7, 0, + mic_tlv), + SOC_SINGLE_TLV("MIC3 Capture Volume", PM860X_ADC_ANA_2, 3, 7, 0, + mic_tlv), + SOC_DOUBLE_R_EXT_TLV("Sidetone Volume", PM860X_SIDETONE_L_GAIN, + PM860X_SIDETONE_R_GAIN, 0, ARRAY_SIZE(st_table)-1, + 0, snd_soc_get_volsw_2r_st, + snd_soc_put_volsw_2r_st, st_tlv), + SOC_SINGLE_TLV("Speaker Playback Volume", PM860X_EAR_CTRL_1, + 0, 7, 0, out_tlv), + SOC_DOUBLE_R_TLV("Line Playback Volume", PM860X_LO1_CTRL, + PM860X_LO2_CTRL, 0, 7, 0, out_tlv), + SOC_DOUBLE_R_TLV("Headset Playback Volume", PM860X_HS1_CTRL, + PM860X_HS2_CTRL, 0, 7, 0, out_tlv), + SOC_DOUBLE_R_EXT_TLV("Hifi Left Playback Volume", + PM860X_HIFIL_GAIN_LEFT, + PM860X_HIFIL_GAIN_RIGHT, 0, 63, 0, + snd_soc_get_volsw_2r_out, + snd_soc_put_volsw_2r_out, dpga_tlv), + SOC_DOUBLE_R_EXT_TLV("Hifi Right Playback Volume", + PM860X_HIFIR_GAIN_LEFT, + PM860X_HIFIR_GAIN_RIGHT, 0, 63, 0, + snd_soc_get_volsw_2r_out, + snd_soc_put_volsw_2r_out, dpga_tlv), + SOC_DOUBLE_R_EXT_TLV("Lofi Playback Volume", PM860X_LOFI_GAIN_LEFT, + PM860X_LOFI_GAIN_RIGHT, 0, 63, 0, + snd_soc_get_volsw_2r_out, + snd_soc_put_volsw_2r_out, dpga_tlv), + SOC_ENUM("Headset1 Operational Amplifier Current", + pm860x_hs1_opamp_enum), + SOC_ENUM("Headset2 Operational Amplifier Current", + pm860x_hs2_opamp_enum), + SOC_ENUM("Headset1 Amplifier Current", pm860x_hs1_pa_enum), + SOC_ENUM("Headset2 Amplifier Current", pm860x_hs2_pa_enum), + SOC_ENUM("Lineout1 Operational Amplifier Current", + pm860x_lo1_opamp_enum), + SOC_ENUM("Lineout2 Operational Amplifier Current", + pm860x_lo2_opamp_enum), + SOC_ENUM("Lineout1 Amplifier Current", pm860x_lo1_pa_enum), + SOC_ENUM("Lineout2 Amplifier Current", pm860x_lo2_pa_enum), + SOC_ENUM("Speaker Operational Amplifier Current", + pm860x_spk_ear_opamp_enum), + SOC_ENUM("Speaker Amplifier Current", pm860x_spk_pa_enum), + SOC_ENUM("Earpiece Amplifier Current", pm860x_ear_pa_enum), +}; + +/* + * DAPM Controls + */ + +/* PCM Switch / PCM Interface */ +static const struct snd_kcontrol_new pcm_switch_controls = + SOC_DAPM_SINGLE("Switch", PM860X_ADC_EN_2, 0, 1, 0); + +/* AUX1 Switch */ +static const struct snd_kcontrol_new aux1_switch_controls = + SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 4, 1, 0); + +/* AUX2 Switch */ +static const struct snd_kcontrol_new aux2_switch_controls = + SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 5, 1, 0); + +/* Left Ex. PA Switch */ +static const struct snd_kcontrol_new lepa_switch_controls = + SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 2, 1, 0); + +/* Right Ex. PA Switch */ +static const struct snd_kcontrol_new repa_switch_controls = + SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 1, 1, 0); + +/* PCM Mux / Mux7 */ +static const char *aif1_text[] = { + "PCM L", "PCM R", +}; + +static const struct soc_enum aif1_enum = + SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text); + +static const struct snd_kcontrol_new aif1_mux = + SOC_DAPM_ENUM("PCM Mux", aif1_enum); + +/* I2S Mux / Mux9 */ +static const char *i2s_din_text[] = { + "DIN", "DIN1", +}; + +static const struct soc_enum i2s_din_enum = + SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text); + +static const struct snd_kcontrol_new i2s_din_mux = + SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum); + +/* I2S Mic Mux / Mux8 */ +static const char *i2s_mic_text[] = { + "Ex PA", "ADC", +}; + +static const struct soc_enum i2s_mic_enum = + SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text); + +static const struct snd_kcontrol_new i2s_mic_mux = + SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum); + +/* ADCL Mux / Mux2 */ +static const char *adcl_text[] = { + "ADCR", "ADCL", +}; + +static const struct soc_enum adcl_enum = + SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text); + +static const struct snd_kcontrol_new adcl_mux = + SOC_DAPM_ENUM("ADC Left Mux", adcl_enum); + +/* ADCR Mux / Mux3 */ +static const char *adcr_text[] = { + "ADCL", "ADCR", +}; + +static const struct soc_enum adcr_enum = + SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text); + +static const struct snd_kcontrol_new adcr_mux = + SOC_DAPM_ENUM("ADC Right Mux", adcr_enum); + +/* ADCR EC Mux / Mux6 */ +static const char *adcr_ec_text[] = { + "ADCR", "EC", +}; + +static const struct soc_enum adcr_ec_enum = + SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text); + +static const struct snd_kcontrol_new adcr_ec_mux = + SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum); + +/* EC Mux / Mux4 */ +static const char *ec_text[] = { + "Left", "Right", "Left + Right", +}; + +static const struct soc_enum ec_enum = + SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text); + +static const struct snd_kcontrol_new ec_mux = + SOC_DAPM_ENUM("EC Mux", ec_enum); + +static const char *dac_text[] = { + "No input", "Right", "Left", "No input", +}; + +/* DAC Headset 1 Mux / Mux10 */ +static const struct soc_enum dac_hs1_enum = + SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text); + +static const struct snd_kcontrol_new dac_hs1_mux = + SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum); + +/* DAC Headset 2 Mux / Mux11 */ +static const struct soc_enum dac_hs2_enum = + SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text); + +static const struct snd_kcontrol_new dac_hs2_mux = + SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum); + +/* DAC Lineout 1 Mux / Mux12 */ +static const struct soc_enum dac_lo1_enum = + SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text); + +static const struct snd_kcontrol_new dac_lo1_mux = + SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum); + +/* DAC Lineout 2 Mux / Mux13 */ +static const struct soc_enum dac_lo2_enum = + SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text); + +static const struct snd_kcontrol_new dac_lo2_mux = + SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum); + +/* DAC Spearker Earphone Mux / Mux14 */ +static const struct soc_enum dac_spk_ear_enum = + SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text); + +static const struct snd_kcontrol_new dac_spk_ear_mux = + SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum); + +/* Headset 1 Mux / Mux15 */ +static const char *in_text[] = { + "Digital", "Analog", +}; + +static const struct soc_enum hs1_enum = + SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text); + +static const struct snd_kcontrol_new hs1_mux = + SOC_DAPM_ENUM("Headset1 Mux", hs1_enum); + +/* Headset 2 Mux / Mux16 */ +static const struct soc_enum hs2_enum = + SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text); + +static const struct snd_kcontrol_new hs2_mux = + SOC_DAPM_ENUM("Headset2 Mux", hs2_enum); + +/* Lineout 1 Mux / Mux17 */ +static const struct soc_enum lo1_enum = + SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text); + +static const struct snd_kcontrol_new lo1_mux = + SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum); + +/* Lineout 2 Mux / Mux18 */ +static const struct soc_enum lo2_enum = + SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text); + +static const struct snd_kcontrol_new lo2_mux = + SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum); + +/* Speaker Earpiece Demux */ +static const char *spk_text[] = { + "Earpiece", "Speaker", +}; + +static const struct soc_enum spk_enum = + SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text); + +static const struct snd_kcontrol_new spk_demux = + SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum); + +/* MIC Mux / Mux1 */ +static const char *mic_text[] = { + "Mic 1", "Mic 2", +}; + +static const struct soc_enum mic_enum = + SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text); + +static const struct snd_kcontrol_new mic_mux = + SOC_DAPM_ENUM("MIC Mux", mic_enum); + +static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("PCM SDI", "PCM Playback", 0, + PM860X_ADC_EN_2, 0, 0), + SND_SOC_DAPM_AIF_OUT("PCM SDO", "PCM Capture", 0, + PM860X_PCM_IFACE_3, 1, 1), + + + SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0, + PM860X_DAC_EN_2, 0, 0), + SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0, + PM860X_DAC_EN_2, 0, 0), + SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0, + PM860X_I2S_IFACE_3, 5, 1), + SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux), + SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux), + SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux), + SND_SOC_DAPM_MUX("EC Mux", SND_SOC_NOPM, 0, 0, &ec_mux), + SND_SOC_DAPM_MUX("ADCR EC Mux", SND_SOC_NOPM, 0, 0, &adcr_ec_mux), + SND_SOC_DAPM_SWITCH("Left EPA", SND_SOC_NOPM, 0, 0, + &lepa_switch_controls), + SND_SOC_DAPM_SWITCH("Right EPA", SND_SOC_NOPM, 0, 0, + &repa_switch_controls), + + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Left ADC MOD", PM860X_ADC_EN_1, + 0, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Right ADC MOD", PM860X_ADC_EN_1, + 1, 1, 1, 0), + SND_SOC_DAPM_ADC("Left ADC", NULL, PM860X_ADC_EN_2, 5, 0), + SND_SOC_DAPM_ADC("Right ADC", NULL, PM860X_ADC_EN_2, 4, 0), + + SND_SOC_DAPM_SWITCH("AUX1 Switch", SND_SOC_NOPM, 0, 0, + &aux1_switch_controls), + SND_SOC_DAPM_SWITCH("AUX2 Switch", SND_SOC_NOPM, 0, 0, + &aux2_switch_controls), + + SND_SOC_DAPM_MUX("MIC Mux", SND_SOC_NOPM, 0, 0, &mic_mux), + SND_SOC_DAPM_MICBIAS("Mic1 Bias", PM860X_ADC_ANA_1, 2, 0), + SND_SOC_DAPM_MICBIAS("Mic3 Bias", PM860X_ADC_ANA_1, 7, 0), + SND_SOC_DAPM_PGA("MIC1 Volume", PM860X_ADC_EN_1, 2, 0, NULL, 0), + SND_SOC_DAPM_PGA("MIC3 Volume", PM860X_ADC_EN_1, 3, 0, NULL, 0), + SND_SOC_DAPM_PGA("AUX1 Volume", PM860X_ADC_EN_1, 4, 0, NULL, 0), + SND_SOC_DAPM_PGA("AUX2 Volume", PM860X_ADC_EN_1, 5, 0, NULL, 0), + SND_SOC_DAPM_PGA("Sidetone PGA", PM860X_ADC_EN_2, 1, 0, NULL, 0), + SND_SOC_DAPM_PGA("Lofi PGA", PM860X_ADC_EN_2, 2, 0, NULL, 0), + + SND_SOC_DAPM_INPUT("AUX1"), + SND_SOC_DAPM_INPUT("AUX2"), + SND_SOC_DAPM_INPUT("MIC1P"), + SND_SOC_DAPM_INPUT("MIC1N"), + SND_SOC_DAPM_INPUT("MIC2P"), + SND_SOC_DAPM_INPUT("MIC2N"), + SND_SOC_DAPM_INPUT("MIC3P"), + SND_SOC_DAPM_INPUT("MIC3N"), + + SND_SOC_DAPM_DAC_E("Left DAC", NULL, SND_SOC_NOPM, 0, 0, + pm860x_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_DAC_E("Right DAC", NULL, SND_SOC_NOPM, 0, 0, + pm860x_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_MUX("I2S DIN Mux", SND_SOC_NOPM, 0, 0, &i2s_din_mux), + SND_SOC_DAPM_MUX("DAC HS1 Mux", SND_SOC_NOPM, 0, 0, &dac_hs1_mux), + SND_SOC_DAPM_MUX("DAC HS2 Mux", SND_SOC_NOPM, 0, 0, &dac_hs2_mux), + SND_SOC_DAPM_MUX("DAC LO1 Mux", SND_SOC_NOPM, 0, 0, &dac_lo1_mux), + SND_SOC_DAPM_MUX("DAC LO2 Mux", SND_SOC_NOPM, 0, 0, &dac_lo2_mux), + SND_SOC_DAPM_MUX("DAC SP Mux", SND_SOC_NOPM, 0, 0, &dac_spk_ear_mux), + SND_SOC_DAPM_MUX("Headset1 Mux", SND_SOC_NOPM, 0, 0, &hs1_mux), + SND_SOC_DAPM_MUX("Headset2 Mux", SND_SOC_NOPM, 0, 0, &hs2_mux), + SND_SOC_DAPM_MUX("Lineout1 Mux", SND_SOC_NOPM, 0, 0, &lo1_mux), + SND_SOC_DAPM_MUX("Lineout2 Mux", SND_SOC_NOPM, 0, 0, &lo2_mux), + SND_SOC_DAPM_MUX("Speaker Earpiece Demux", SND_SOC_NOPM, 0, 0, + &spk_demux), + + + SND_SOC_DAPM_PGA("Headset1 PGA", PM860X_DAC_EN_1, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Headset2 PGA", PM860X_DAC_EN_1, 1, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("HS1"), + SND_SOC_DAPM_OUTPUT("HS2"), + SND_SOC_DAPM_PGA("Lineout1 PGA", PM860X_DAC_EN_1, 2, 0, NULL, 0), + SND_SOC_DAPM_PGA("Lineout2 PGA", PM860X_DAC_EN_1, 3, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("LINEOUT1"), + SND_SOC_DAPM_OUTPUT("LINEOUT2"), + SND_SOC_DAPM_PGA("Earpiece PGA", PM860X_DAC_EN_1, 4, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("EARP"), + SND_SOC_DAPM_OUTPUT("EARN"), + SND_SOC_DAPM_PGA("Speaker PGA", PM860X_DAC_EN_1, 5, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("LSP"), + SND_SOC_DAPM_OUTPUT("LSN"), + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "VCODEC", PM860X_AUDIO_SUPPLIES_2, + 0, SUPPLY_MASK, SUPPLY_MASK, 0), + + PM860X_DAPM_OUTPUT("RSYNC", pm860x_rsync_event), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + /* supply */ + {"Left DAC", NULL, "VCODEC"}, + {"Right DAC", NULL, "VCODEC"}, + {"Left ADC", NULL, "VCODEC"}, + {"Right ADC", NULL, "VCODEC"}, + {"Left ADC", NULL, "Left ADC MOD"}, + {"Right ADC", NULL, "Right ADC MOD"}, + + /* PCM/AIF1 Inputs */ + {"PCM SDO", NULL, "ADC Left Mux"}, + {"PCM SDO", NULL, "ADCR EC Mux"}, + + /* PCM/AFI2 Outputs */ + {"Lofi PGA", NULL, "PCM SDI"}, + {"Lofi PGA", NULL, "Sidetone PGA"}, + {"Left DAC", NULL, "Lofi PGA"}, + {"Right DAC", NULL, "Lofi PGA"}, + + /* I2S/AIF2 Inputs */ + {"MIC Mux", "Mic 1", "MIC1P"}, + {"MIC Mux", "Mic 1", "MIC1N"}, + {"MIC Mux", "Mic 2", "MIC2P"}, + {"MIC Mux", "Mic 2", "MIC2N"}, + {"MIC1 Volume", NULL, "MIC Mux"}, + {"MIC3 Volume", NULL, "MIC3P"}, + {"MIC3 Volume", NULL, "MIC3N"}, + {"Left ADC", NULL, "MIC1 Volume"}, + {"Right ADC", NULL, "MIC3 Volume"}, + {"ADC Left Mux", "ADCR", "Right ADC"}, + {"ADC Left Mux", "ADCL", "Left ADC"}, + {"ADC Right Mux", "ADCL", "Left ADC"}, + {"ADC Right Mux", "ADCR", "Right ADC"}, + {"Left EPA", "Switch", "Left DAC"}, + {"Right EPA", "Switch", "Right DAC"}, + {"EC Mux", "Left", "Left DAC"}, + {"EC Mux", "Right", "Right DAC"}, + {"EC Mux", "Left + Right", "Left DAC"}, + {"EC Mux", "Left + Right", "Right DAC"}, + {"ADCR EC Mux", "ADCR", "ADC Right Mux"}, + {"ADCR EC Mux", "EC", "EC Mux"}, + {"I2S Mic Mux", "Ex PA", "Left EPA"}, + {"I2S Mic Mux", "Ex PA", "Right EPA"}, + {"I2S Mic Mux", "ADC", "ADC Left Mux"}, + {"I2S Mic Mux", "ADC", "ADCR EC Mux"}, + {"I2S DOUT", NULL, "I2S Mic Mux"}, + + /* I2S/AIF2 Outputs */ + {"I2S DIN Mux", "DIN", "I2S DIN"}, + {"I2S DIN Mux", "DIN1", "I2S DIN1"}, + {"Left DAC", NULL, "I2S DIN Mux"}, + {"Right DAC", NULL, "I2S DIN Mux"}, + {"DAC HS1 Mux", "Left", "Left DAC"}, + {"DAC HS1 Mux", "Right", "Right DAC"}, + {"DAC HS2 Mux", "Left", "Left DAC"}, + {"DAC HS2 Mux", "Right", "Right DAC"}, + {"DAC LO1 Mux", "Left", "Left DAC"}, + {"DAC LO1 Mux", "Right", "Right DAC"}, + {"DAC LO2 Mux", "Left", "Left DAC"}, + {"DAC LO2 Mux", "Right", "Right DAC"}, + {"Headset1 Mux", "Digital", "DAC HS1 Mux"}, + {"Headset2 Mux", "Digital", "DAC HS2 Mux"}, + {"Lineout1 Mux", "Digital", "DAC LO1 Mux"}, + {"Lineout2 Mux", "Digital", "DAC LO2 Mux"}, + {"Headset1 PGA", NULL, "Headset1 Mux"}, + {"Headset2 PGA", NULL, "Headset2 Mux"}, + {"Lineout1 PGA", NULL, "Lineout1 Mux"}, + {"Lineout2 PGA", NULL, "Lineout2 Mux"}, + {"DAC SP Mux", "Left", "Left DAC"}, + {"DAC SP Mux", "Right", "Right DAC"}, + {"Speaker Earpiece Demux", "Speaker", "DAC SP Mux"}, + {"Speaker PGA", NULL, "Speaker Earpiece Demux"}, + {"Earpiece PGA", NULL, "Speaker Earpiece Demux"}, + + {"RSYNC", NULL, "Headset1 PGA"}, + {"RSYNC", NULL, "Headset2 PGA"}, + {"RSYNC", NULL, "Lineout1 PGA"}, + {"RSYNC", NULL, "Lineout2 PGA"}, + {"RSYNC", NULL, "Speaker PGA"}, + {"RSYNC", NULL, "Speaker PGA"}, + {"RSYNC", NULL, "Earpiece PGA"}, + {"RSYNC", NULL, "Earpiece PGA"}, + + {"HS1", NULL, "RSYNC"}, + {"HS2", NULL, "RSYNC"}, + {"LINEOUT1", NULL, "RSYNC"}, + {"LINEOUT2", NULL, "RSYNC"}, + {"LSP", NULL, "RSYNC"}, + {"LSN", NULL, "RSYNC"}, + {"EARP", NULL, "RSYNC"}, + {"EARN", NULL, "RSYNC"}, +}; + +/* + * Use MUTE_LEFT & MUTE_RIGHT to implement digital mute. + * These bits can also be used to mute. + */ +static int pm860x_digital_mute(struct snd_soc_dai *codec_dai, int mute) +{ + struct snd_soc_codec *codec = codec_dai->codec; + int data = 0, mask = MUTE_LEFT | MUTE_RIGHT; + + if (mute) + data = mask; + snd_soc_update_bits(codec, PM860X_DAC_OFFSET, mask, data); + snd_soc_update_bits(codec, PM860X_EAR_CTRL_2, + RSYNC_CHANGE, RSYNC_CHANGE); + return 0; +} + +static int pm860x_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + unsigned char inf = 0, mask = 0; + + /* bit size */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + inf &= ~PCM_INF2_18WL; + break; + case SNDRV_PCM_FORMAT_S18_3LE: + inf |= PCM_INF2_18WL; + break; + default: + return -EINVAL; + } + mask |= PCM_INF2_18WL; + snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf); + + /* sample rate */ + switch (params_rate(params)) { + case 8000: + inf = 0; + break; + case 16000: + inf = 3; + break; + case 32000: + inf = 6; + break; + case 48000: + inf = 8; + break; + default: + return -EINVAL; + } + snd_soc_update_bits(codec, PM860X_PCM_RATE, 0x0f, inf); + + return 0; +} + +static int pm860x_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); + unsigned char inf = 0, mask = 0; + int ret = -EINVAL; + + mask |= PCM_INF2_BCLK | PCM_INF2_FS | PCM_INF2_MASTER; + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBM_CFS: + if (pm860x->dir == PM860X_CLK_DIR_OUT) { + inf |= PCM_INF2_MASTER; + ret = 0; + } + break; + case SND_SOC_DAIFMT_CBS_CFS: + if (pm860x->dir == PM860X_CLK_DIR_IN) { + inf &= ~PCM_INF2_MASTER; + ret = 0; + } + break; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + inf |= PCM_EXACT_I2S; + ret = 0; + break; + } + mask |= PCM_MODE_MASK; + if (ret) + return ret; + snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf); + return 0; +} + +static int pm860x_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); + + if (dir == PM860X_CLK_DIR_OUT) + pm860x->dir = PM860X_CLK_DIR_OUT; + else { + pm860x->dir = PM860X_CLK_DIR_IN; + return -EINVAL; + } + + return 0; +} + +static int pm860x_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + unsigned char inf; + + /* bit size */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + inf = 0; + break; + case SNDRV_PCM_FORMAT_S18_3LE: + inf = PCM_INF2_18WL; + break; + default: + return -EINVAL; + } + snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, PCM_INF2_18WL, inf); + + /* sample rate */ + switch (params_rate(params)) { + case 8000: + inf = 0; + break; + case 11025: + inf = 1; + break; + case 16000: + inf = 3; + break; + case 22050: + inf = 4; + break; + case 32000: + inf = 6; + break; + case 44100: + inf = 7; + break; + case 48000: + inf = 8; + break; + default: + return -EINVAL; + } + snd_soc_update_bits(codec, PM860X_I2S_IFACE_4, 0xf, inf); + + return 0; +} + +static int pm860x_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); + unsigned char inf = 0, mask = 0; + + mask |= PCM_INF2_BCLK | PCM_INF2_FS | PCM_INF2_MASTER; + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + if (pm860x->dir == PM860X_CLK_DIR_OUT) + inf |= PCM_INF2_MASTER; + else + return -EINVAL; + break; + case SND_SOC_DAIFMT_CBS_CFS: + if (pm860x->dir == PM860X_CLK_DIR_IN) + inf &= ~PCM_INF2_MASTER; + else + return -EINVAL; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + inf |= PCM_EXACT_I2S; + break; + default: + return -EINVAL; + } + mask |= PCM_MODE_MASK; + snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, mask, inf); + return 0; +} + +static int pm860x_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + int data; + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + break; + + case SND_SOC_BIAS_STANDBY: + if (codec->bias_level == SND_SOC_BIAS_OFF) { + /* Enable Audio PLL & Audio section */ + data = AUDIO_PLL | AUDIO_SECTION_RESET + | AUDIO_SECTION_ON; + pm860x_reg_write(codec->control_data, REG_MISC2, data); + } + break; + + case SND_SOC_BIAS_OFF: + data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON; + pm860x_set_bits(codec->control_data, REG_MISC2, data, 0); + break; + } + codec->bias_level = level; + return 0; +} + +static struct snd_soc_dai_ops pm860x_pcm_dai_ops = { + .digital_mute = pm860x_digital_mute, + .hw_params = pm860x_pcm_hw_params, + .set_fmt = pm860x_pcm_set_dai_fmt, + .set_sysclk = pm860x_set_dai_sysclk, +}; + +static struct snd_soc_dai_ops pm860x_i2s_dai_ops = { + .digital_mute = pm860x_digital_mute, + .hw_params = pm860x_i2s_hw_params, + .set_fmt = pm860x_i2s_set_dai_fmt, + .set_sysclk = pm860x_set_dai_sysclk, +}; + +#define PM860X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000) + +static struct snd_soc_dai_driver pm860x_dai[] = { + { + /* DAI PCM */ + .name = "88pm860x-pcm", + .id = 1, + .playback = { + .stream_name = "PCM Playback", + .channels_min = 2, + .channels_max = 2, + .rates = PM860X_RATES, + .formats = SNDRV_PCM_FORMAT_S16_LE | \ + SNDRV_PCM_FORMAT_S18_3LE, + }, + .capture = { + .stream_name = "PCM Capture", + .channels_min = 2, + .channels_max = 2, + .rates = PM860X_RATES, + .formats = SNDRV_PCM_FORMAT_S16_LE | \ + SNDRV_PCM_FORMAT_S18_3LE, + }, + .ops = &pm860x_pcm_dai_ops, + }, { + /* DAI I2S */ + .name = "88pm860x-i2s", + .id = 2, + .playback = { + .stream_name = "I2S Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FORMAT_S16_LE | \ + SNDRV_PCM_FORMAT_S18_3LE, + }, + .capture = { + .stream_name = "I2S Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FORMAT_S16_LE | \ + SNDRV_PCM_FORMAT_S18_3LE, + }, + .ops = &pm860x_i2s_dai_ops, + }, +}; + +static irqreturn_t pm860x_codec_handler(int irq, void *data) +{ + struct pm860x_priv *pm860x = data; + int status, shrt, report = 0, mic_report = 0; + int mask; + + status = pm860x_reg_read(pm860x->i2c, REG_STATUS_1); + shrt = pm860x_reg_read(pm860x->i2c, REG_SHORTS); + mask = pm860x->det.hs_shrt | pm860x->det.hook_det | pm860x->det.lo_shrt + | pm860x->det.hp_det; + + if ((pm860x->det.hp_det & SND_JACK_HEADPHONE) + && (status & HEADSET_STATUS)) + report |= SND_JACK_HEADPHONE; + + if ((pm860x->det.mic_det & SND_JACK_MICROPHONE) + && (status & MIC_STATUS)) + mic_report |= SND_JACK_MICROPHONE; + + if (pm860x->det.hs_shrt && (shrt & (SHORT_HS1 | SHORT_HS2))) + report |= pm860x->det.hs_shrt; + + if (pm860x->det.hook_det && (status & HOOK_STATUS)) + report |= pm860x->det.hook_det; + + if (pm860x->det.lo_shrt && (shrt & (SHORT_LO1 | SHORT_LO2))) + report |= pm860x->det.lo_shrt; + + if (report) + snd_soc_jack_report(pm860x->det.hp_jack, report, mask); + if (mic_report) + snd_soc_jack_report(pm860x->det.mic_jack, SND_JACK_MICROPHONE, + SND_JACK_MICROPHONE); + + dev_dbg(pm860x->codec->dev, "headphone report:0x%x, mask:%x\n", + report, mask); + dev_dbg(pm860x->codec->dev, "microphone report:0x%x\n", mic_report); + return IRQ_HANDLED; +} + +int pm860x_hs_jack_detect(struct snd_soc_codec *codec, + struct snd_soc_jack *jack, + int det, int hook, int hs_shrt, int lo_shrt) +{ + struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); + int data; + + pm860x->det.hp_jack = jack; + pm860x->det.hp_det = det; + pm860x->det.hook_det = hook; + pm860x->det.hs_shrt = hs_shrt; + pm860x->det.lo_shrt = lo_shrt; + + if (det & SND_JACK_HEADPHONE) + pm860x_set_bits(codec->control_data, REG_HS_DET, + EN_HS_DET, EN_HS_DET); + /* headset short detect */ + if (hs_shrt) { + data = CLR_SHORT_HS2 | CLR_SHORT_HS1; + pm860x_set_bits(codec->control_data, REG_SHORTS, data, data); + } + /* Lineout short detect */ + if (lo_shrt) { + data = CLR_SHORT_LO2 | CLR_SHORT_LO1; + pm860x_set_bits(codec->control_data, REG_SHORTS, data, data); + } + + /* sync status */ + pm860x_codec_handler(0, pm860x); + return 0; +} +EXPORT_SYMBOL_GPL(pm860x_hs_jack_detect); + +int pm860x_mic_jack_detect(struct snd_soc_codec *codec, + struct snd_soc_jack *jack, int det) +{ + struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); + + pm860x->det.mic_jack = jack; + pm860x->det.mic_det = det; + + if (det & SND_JACK_MICROPHONE) + pm860x_set_bits(codec->control_data, REG_MIC_DET, + MICDET_MASK, MICDET_MASK); + + /* sync status */ + pm860x_codec_handler(0, pm860x); + return 0; +} +EXPORT_SYMBOL_GPL(pm860x_mic_jack_detect); + +static int pm860x_probe(struct snd_soc_codec *codec) +{ + struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); + int i, ret; + + pm860x->codec = codec; + + codec->control_data = pm860x->i2c; + + for (i = 0; i < 4; i++) { + ret = request_threaded_irq(pm860x->irq[i], NULL, + pm860x_codec_handler, IRQF_ONESHOT, + pm860x->name[i], pm860x); + if (ret < 0) { + dev_err(codec->dev, "Failed to request IRQ!\n"); + goto out_irq; + } + } + + pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + ret = pm860x_bulk_read(codec->control_data, REG_CACHE_BASE, + REG_CACHE_SIZE, codec->reg_cache); + if (ret < 0) { + dev_err(codec->dev, "Failed to fill register cache: %d\n", + ret); + goto out_codec; + } + + snd_soc_add_controls(codec, pm860x_snd_controls, + ARRAY_SIZE(pm860x_snd_controls)); + snd_soc_dapm_new_controls(codec, pm860x_dapm_widgets, + ARRAY_SIZE(pm860x_dapm_widgets)); + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + return 0; + +out_codec: + i = 3; +out_irq: + for (; i >= 0; i--) + free_irq(pm860x->irq[i], pm860x); + return -EINVAL; +} + +static int pm860x_remove(struct snd_soc_codec *codec) +{ + struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); + int i; + + for (i = 3; i >= 0; i--) + free_irq(pm860x->irq[i], pm860x); + pm860x_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_pm860x = { + .probe = pm860x_probe, + .remove = pm860x_remove, + .read = pm860x_read_reg_cache, + .write = pm860x_write_reg_cache, + .reg_cache_size = REG_CACHE_SIZE, + .reg_word_size = sizeof(u8), + .set_bias_level = pm860x_set_bias_level, +}; + +static int __devinit pm860x_codec_probe(struct platform_device *pdev) +{ + struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct pm860x_priv *pm860x; + struct resource *res; + int i, ret; + + pm860x = kzalloc(sizeof(struct pm860x_priv), GFP_KERNEL); + if (pm860x == NULL) + return -ENOMEM; + + pm860x->chip = chip; + pm860x->i2c = (chip->id == CHIP_PM8607) ? chip->client + : chip->companion; + platform_set_drvdata(pdev, pm860x); + + for (i = 0; i < 4; i++) { + res = platform_get_resource(pdev, IORESOURCE_IRQ, i); + if (!res) { + dev_err(&pdev->dev, "Failed to get IRQ resources\n"); + goto out; + } + pm860x->irq[i] = res->start + chip->irq_base; + strncpy(pm860x->name[i], res->name, MAX_NAME_LEN); + } + + ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pm860x, + pm860x_dai, ARRAY_SIZE(pm860x_dai)); + if (ret) { + dev_err(&pdev->dev, "Failed to register codec\n"); + goto out; + } + return ret; + +out: + platform_set_drvdata(pdev, NULL); + kfree(pm860x); + return -EINVAL; +} + +static int __devexit pm860x_codec_remove(struct platform_device *pdev) +{ + struct pm860x_priv *pm860x = platform_get_drvdata(pdev); + + snd_soc_unregister_codec(&pdev->dev); + platform_set_drvdata(pdev, NULL); + kfree(pm860x); + return 0; +} + +static struct platform_driver pm860x_codec_driver = { + .driver = { + .name = "88pm860x-codec", + .owner = THIS_MODULE, + }, + .probe = pm860x_codec_probe, + .remove = __devexit_p(pm860x_codec_remove), +}; + +static __init int pm860x_init(void) +{ + return platform_driver_register(&pm860x_codec_driver); +} +module_init(pm860x_init); + +static __exit void pm860x_exit(void) +{ + platform_driver_unregister(&pm860x_codec_driver); +} +module_exit(pm860x_exit); + +MODULE_DESCRIPTION("ASoC 88PM860x driver"); +MODULE_AUTHOR("Haojian Zhuang "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:88pm860x-codec"); + diff --git a/sound/soc/codecs/88pm860x-codec.h b/sound/soc/codecs/88pm860x-codec.h new file mode 100644 index 000000000000..3364ba4a3607 --- /dev/null +++ b/sound/soc/codecs/88pm860x-codec.h @@ -0,0 +1,97 @@ +/* + * 88pm860x-codec.h -- 88PM860x ALSA SoC Audio Driver + * + * Copyright 2010 Marvell International Ltd. + * Haojian Zhuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __88PM860X_H +#define __88PM860X_H + +/* The offset of these registers are 0xb0 */ +#define PM860X_PCM_IFACE_1 0x00 +#define PM860X_PCM_IFACE_2 0x01 +#define PM860X_PCM_IFACE_3 0x02 +#define PM860X_PCM_RATE 0x03 +#define PM860X_EC_PATH 0x04 +#define PM860X_SIDETONE_L_GAIN 0x05 +#define PM860X_SIDETONE_R_GAIN 0x06 +#define PM860X_SIDETONE_SHIFT 0x07 +#define PM860X_ADC_OFFSET_1 0x08 +#define PM860X_ADC_OFFSET_2 0x09 +#define PM860X_DMIC_DELAY 0x0a + +#define PM860X_I2S_IFACE_1 0x0b +#define PM860X_I2S_IFACE_2 0x0c +#define PM860X_I2S_IFACE_3 0x0d +#define PM860X_I2S_IFACE_4 0x0e +#define PM860X_EQUALIZER_N0_1 0x0f +#define PM860X_EQUALIZER_N0_2 0x10 +#define PM860X_EQUALIZER_N1_1 0x11 +#define PM860X_EQUALIZER_N1_2 0x12 +#define PM860X_EQUALIZER_D1_1 0x13 +#define PM860X_EQUALIZER_D1_2 0x14 +#define PM860X_LOFI_GAIN_LEFT 0x15 +#define PM860X_LOFI_GAIN_RIGHT 0x16 +#define PM860X_HIFIL_GAIN_LEFT 0x17 +#define PM860X_HIFIL_GAIN_RIGHT 0x18 +#define PM860X_HIFIR_GAIN_LEFT 0x19 +#define PM860X_HIFIR_GAIN_RIGHT 0x1a +#define PM860X_DAC_OFFSET 0x1b +#define PM860X_OFFSET_LEFT_1 0x1c +#define PM860X_OFFSET_LEFT_2 0x1d +#define PM860X_OFFSET_RIGHT_1 0x1e +#define PM860X_OFFSET_RIGHT_2 0x1f +#define PM860X_ADC_ANA_1 0x20 +#define PM860X_ADC_ANA_2 0x21 +#define PM860X_ADC_ANA_3 0x22 +#define PM860X_ADC_ANA_4 0x23 +#define PM860X_ANA_TO_ANA 0x24 +#define PM860X_HS1_CTRL 0x25 +#define PM860X_HS2_CTRL 0x26 +#define PM860X_LO1_CTRL 0x27 +#define PM860X_LO2_CTRL 0x28 +#define PM860X_EAR_CTRL_1 0x29 +#define PM860X_EAR_CTRL_2 0x2a +#define PM860X_AUDIO_SUPPLIES_1 0x2b +#define PM860X_AUDIO_SUPPLIES_2 0x2c +#define PM860X_ADC_EN_1 0x2d +#define PM860X_ADC_EN_2 0x2e +#define PM860X_DAC_EN_1 0x2f +#define PM860X_DAC_EN_2 0x31 +#define PM860X_AUDIO_CAL_1 0x32 +#define PM860X_AUDIO_CAL_2 0x33 +#define PM860X_AUDIO_CAL_3 0x34 +#define PM860X_AUDIO_CAL_4 0x35 +#define PM860X_AUDIO_CAL_5 0x36 +#define PM860X_ANA_INPUT_SEL_1 0x37 +#define PM860X_ANA_INPUT_SEL_2 0x38 + +#define PM860X_PCM_IFACE_4 0x39 +#define PM860X_I2S_IFACE_5 0x3a + +#define PM860X_SHORTS 0x3b +#define PM860X_PLL_ADJ_1 0x3c +#define PM860X_PLL_ADJ_2 0x3d + +/* bits definition */ +#define PM860X_CLK_DIR_IN 0 +#define PM860X_CLK_DIR_OUT 1 + +#define PM860X_DET_HEADSET (1 << 0) +#define PM860X_DET_MIC (1 << 1) +#define PM860X_DET_HOOK (1 << 2) +#define PM860X_SHORT_HEADSET (1 << 3) +#define PM860X_SHORT_LINEOUT (1 << 4) +#define PM860X_DET_MASK 0x1F + +extern int pm860x_hs_jack_detect(struct snd_soc_codec *, struct snd_soc_jack *, + int, int, int, int); +extern int pm860x_mic_jack_detect(struct snd_soc_codec *, struct snd_soc_jack *, + int); + +#endif /* __88PM860X_H */ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index bfdd92b78fb6..a3cfc184ee50 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" + select SND_SOC_88PM860X if MFD_88PM860X select SND_SOC_L3 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS select SND_SOC_AD1836 if SPI_MASTER @@ -85,6 +86,9 @@ config SND_SOC_ALL_CODECS If unsure select "N". +config SND_SOC_88PM860X + tristate + config SND_SOC_WM_HUBS tristate default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 9c3c39fd99ad..b9c43582c5bd 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -1,3 +1,4 @@ +snd-soc-88pm860x-objs := 88pm860x-codec.o snd-soc-ac97-objs := ac97.o snd-soc-ad1836-objs := ad1836.o snd-soc-ad193x-objs := ad193x.o @@ -67,6 +68,7 @@ snd-soc-tpa6130a2-objs := tpa6130a2.o snd-soc-wm2000-objs := wm2000.o snd-soc-wm9090-objs := wm9090.o +obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o -- cgit v1.2.3-59-g8ed1b From b0547a70db38ee851a32306ee2e1e43a1e0d28ea Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Thu, 19 Aug 2010 00:36:00 +0800 Subject: ASoC: add tavorevb3 machine driver for 88pm860x Signed-off-by: Haojian Zhuang Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 9 +++ sound/soc/pxa/Makefile | 2 + sound/soc/pxa/tavorevb3.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 sound/soc/pxa/tavorevb3.c diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index e30c8325f35e..04ddc7bcae61 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -117,6 +117,15 @@ config SND_PXA2XX_SOC_PALM27X Say Y if you want to add support for SoC audio on Palm T|X, T5, E2 or LifeDrive handheld computer. +config SND_SOC_TAVOREVB3 + tristate "SoC Audio support for Marvell Tavor EVB3" + depends on SND_PXA2XX_SOC && MACH_TAVOREVB3 + select SND_PXA_SOC_SSP + select SND_SOC_88PM860X + help + Say Y if you want to add support for SoC audio on the + Marvell Saarb reference platform. + config SND_SOC_ZYLONITE tristate "SoC Audio support for Marvell Zylonite" depends on SND_PXA2XX_SOC && MACH_ZYLONITE diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index caa03d8f4789..315941fe1abd 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -19,6 +19,7 @@ snd-soc-e800-objs := e800_wm9712.o snd-soc-spitz-objs := spitz.o snd-soc-em-x270-objs := em-x270.o snd-soc-palm27x-objs := palm27x.o +snd-soc-tavorevb3-objs := tavorevb3.o snd-soc-zylonite-objs := zylonite.o snd-soc-magician-objs := magician.o snd-soc-mioa701-objs := mioa701_wm9713.o @@ -38,6 +39,7 @@ obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o +obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o diff --git a/sound/soc/pxa/tavorevb3.c b/sound/soc/pxa/tavorevb3.c new file mode 100644 index 000000000000..248c283fc4df --- /dev/null +++ b/sound/soc/pxa/tavorevb3.c @@ -0,0 +1,200 @@ +/* + * tavorevb3.c -- SoC audio for Tavor EVB3 + * + * Copyright (C) 2010 Marvell International Ltd. + * Haojian Zhuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../codecs/88pm860x-codec.h" +#include "pxa-ssp.h" + +static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd); + +static struct platform_device *evb3_snd_device; + +static struct snd_soc_jack hs_jack, mic_jack; + +static struct snd_soc_jack_pin hs_jack_pins[] = { + { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, }, +}; + +static struct snd_soc_jack_pin mic_jack_pins[] = { + { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, }, +}; + +/* tavorevb3 machine dapm widgets */ +static const struct snd_soc_dapm_widget evb3_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headset Stereophone", NULL), + SND_SOC_DAPM_LINE("Lineout Out 1", NULL), + SND_SOC_DAPM_LINE("Lineout Out 2", NULL), + SND_SOC_DAPM_SPK("Ext Speaker", NULL), + SND_SOC_DAPM_MIC("Ext Mic 1", NULL), + SND_SOC_DAPM_MIC("Headset Mic 2", NULL), + SND_SOC_DAPM_MIC("Ext Mic 3", NULL), +}; + +/* tavorevb3 machine audio map */ +static const struct snd_soc_dapm_route audio_map[] = { + {"Headset Stereophone", NULL, "HS1"}, + {"Headset Stereophone", NULL, "HS2"}, + + {"Ext Speaker", NULL, "LSP"}, + {"Ext Speaker", NULL, "LSN"}, + + {"Lineout Out 1", NULL, "LINEOUT1"}, + {"Lineout Out 2", NULL, "LINEOUT2"}, + + {"MIC1P", NULL, "Mic1 Bias"}, + {"MIC1N", NULL, "Mic1 Bias"}, + {"Mic1 Bias", NULL, "Ext Mic 1"}, + + {"MIC2P", NULL, "Mic1 Bias"}, + {"MIC2N", NULL, "Mic1 Bias"}, + {"Mic1 Bias", NULL, "Headset Mic 2"}, + + {"MIC3P", NULL, "Mic3 Bias"}, + {"MIC3N", NULL, "Mic3 Bias"}, + {"Mic3 Bias", NULL, "Ext Mic 3"}, +}; + +static int evb3_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int width = snd_pcm_format_physical_width(params_format(params)); + int ret; + + ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0, + PM860X_CLK_DIR_OUT); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width); + return ret; +} + +static struct snd_soc_ops evb3_i2s_ops = { + .hw_params = evb3_i2s_hw_params, +}; + +static struct snd_soc_dai_link evb3_dai[] = { + { + .name = "88PM860x I2S", + .stream_name = "I2S Audio", + .cpu_dai_name = "pxa-ssp-dai.1", + .codec_dai_name = "88pm860x-i2s", + .platform_name = "pxa-pcm-audio", + .codec_name = "88pm860x-codec", + .init = evb3_pm860x_init, + .ops = &evb3_i2s_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_evb3 = { + .name = "Tavor EVB3", + .dai_link = evb3_dai, + .num_links = ARRAY_SIZE(evb3_dai), +}; + +static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + int ret; + + snd_soc_dapm_new_controls(codec, evb3_dapm_widgets, + ARRAY_SIZE(evb3_dapm_widgets)); + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + + /* connected pins */ + snd_soc_dapm_enable_pin(codec, "Ext Speaker"); + snd_soc_dapm_enable_pin(codec, "Ext Mic 1"); + snd_soc_dapm_enable_pin(codec, "Ext Mic 3"); + snd_soc_dapm_disable_pin(codec, "Headset Mic 2"); + snd_soc_dapm_disable_pin(codec, "Headset Stereophone"); + + ret = snd_soc_dapm_sync(codec); + if (ret) + return ret; + + /* Headset jack detection */ + snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE + | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, + &hs_jack); + snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), + hs_jack_pins); + snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE, + &mic_jack); + snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), + mic_jack_pins); + + /* headphone, microphone detection & headset short detection */ + pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE, + SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2); + pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE); + return 0; +} + +static int __init tavorevb3_init(void) +{ + int ret; + + if (!machine_is_tavorevb3()) + return -ENODEV; + evb3_snd_device = platform_device_alloc("soc-audio", -1); + if (!evb3_snd_device) + return -ENOMEM; + + platform_set_drvdata(evb3_snd_device, &snd_soc_card_evb3); + + ret = platform_device_add(evb3_snd_device); + if (ret) + platform_device_put(evb3_snd_device); + + return ret; +} + +static void __exit tavorevb3_exit(void) +{ + platform_device_unregister(evb3_snd_device); +} + +module_init(tavorevb3_init); +module_exit(tavorevb3_exit); + +MODULE_AUTHOR("Haojian Zhuang "); +MODULE_DESCRIPTION("ALSA SoC 88PM860x Tavor EVB3"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From b6905d0b1652efddb96cefdb3c8552cac8d98ed2 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Thu, 19 Aug 2010 00:36:30 +0800 Subject: ASoC: add saarb machine driver for 88pm860x 88PM860x codec is used in Marvell saarb development board. 88PM860x codec is used as master mode for SSP communication. Only I2S format is supported. Signed-off-by: Haojian Zhuang Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 9 +++ sound/soc/pxa/Makefile | 2 + sound/soc/pxa/saarb.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 sound/soc/pxa/saarb.c diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 04ddc7bcae61..37f191bbfdd9 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -117,6 +117,15 @@ config SND_PXA2XX_SOC_PALM27X Say Y if you want to add support for SoC audio on Palm T|X, T5, E2 or LifeDrive handheld computer. +config SND_SOC_SAARB + tristate "SoC Audio support for Marvell Saarb" + depends on SND_PXA2XX_SOC && MACH_SAARB + select SND_PXA_SOC_SSP + select SND_SOC_88PM860X + help + Say Y if you want to add support for SoC audio on the + Marvell Saarb reference platform. + config SND_SOC_TAVOREVB3 tristate "SoC Audio support for Marvell Tavor EVB3" depends on SND_PXA2XX_SOC && MACH_TAVOREVB3 diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index 315941fe1abd..07660165ec8d 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -19,6 +19,7 @@ snd-soc-e800-objs := e800_wm9712.o snd-soc-spitz-objs := spitz.o snd-soc-em-x270-objs := em-x270.o snd-soc-palm27x-objs := palm27x.o +snd-soc-saarb-objs := saarb.o snd-soc-tavorevb3-objs := tavorevb3.o snd-soc-zylonite-objs := zylonite.o snd-soc-magician-objs := magician.o @@ -39,6 +40,7 @@ obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o +obj-$(CONFIG_SND_SOC_SAARB) += snd-soc-saarb.o obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o diff --git a/sound/soc/pxa/saarb.c b/sound/soc/pxa/saarb.c new file mode 100644 index 000000000000..d63cb474b4e1 --- /dev/null +++ b/sound/soc/pxa/saarb.c @@ -0,0 +1,200 @@ +/* + * saarb.c -- SoC audio for saarb + * + * Copyright (C) 2010 Marvell International Ltd. + * Haojian Zhuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../codecs/88pm860x-codec.h" +#include "pxa-ssp.h" + +static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd); + +static struct platform_device *saarb_snd_device; + +static struct snd_soc_jack hs_jack, mic_jack; + +static struct snd_soc_jack_pin hs_jack_pins[] = { + { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, }, +}; + +static struct snd_soc_jack_pin mic_jack_pins[] = { + { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, }, +}; + +/* saarb machine dapm widgets */ +static const struct snd_soc_dapm_widget saarb_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Stereophone", NULL), + SND_SOC_DAPM_LINE("Lineout Out 1", NULL), + SND_SOC_DAPM_LINE("Lineout Out 2", NULL), + SND_SOC_DAPM_SPK("Ext Speaker", NULL), + SND_SOC_DAPM_MIC("Ext Mic 1", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Ext Mic 3", NULL), +}; + +/* saarb machine audio map */ +static const struct snd_soc_dapm_route audio_map[] = { + {"Headset Stereophone", NULL, "HS1"}, + {"Headset Stereophone", NULL, "HS2"}, + + {"Ext Speaker", NULL, "LSP"}, + {"Ext Speaker", NULL, "LSN"}, + + {"Lineout Out 1", NULL, "LINEOUT1"}, + {"Lineout Out 2", NULL, "LINEOUT2"}, + + {"MIC1P", NULL, "Mic1 Bias"}, + {"MIC1N", NULL, "Mic1 Bias"}, + {"Mic1 Bias", NULL, "Ext Mic 1"}, + + {"MIC2P", NULL, "Mic1 Bias"}, + {"MIC2N", NULL, "Mic1 Bias"}, + {"Mic1 Bias", NULL, "Headset Mic 2"}, + + {"MIC3P", NULL, "Mic3 Bias"}, + {"MIC3N", NULL, "Mic3 Bias"}, + {"Mic3 Bias", NULL, "Ext Mic 3"}, +}; + +static int saarb_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int width = snd_pcm_format_physical_width(params_format(params)); + int ret; + + ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0, + PM860X_CLK_DIR_OUT); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width); + + return ret; +} + +static struct snd_soc_ops saarb_i2s_ops = { + .hw_params = saarb_i2s_hw_params, +}; + +static struct snd_soc_dai_link saarb_dai[] = { + { + .name = "88PM860x I2S", + .stream_name = "I2S Audio", + .cpu_dai_name = "pxa-ssp-dai.1", + .codec_dai_name = "88pm860x-i2s", + .platform_name = "pxa-pcm-audio", + .codec_name = "88pm860x-codec", + .init = saarb_pm860x_init, + .ops = &saarb_i2s_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_saarb = { + .name = "Saarb", + .dai_link = saarb_dai, + .num_links = ARRAY_SIZE(saarb_dai), +}; + +static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + int ret; + + snd_soc_dapm_new_controls(codec, saarb_dapm_widgets, + ARRAY_SIZE(saarb_dapm_widgets)); + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + + /* connected pins */ + snd_soc_dapm_enable_pin(codec, "Ext Speaker"); + snd_soc_dapm_enable_pin(codec, "Ext Mic 1"); + snd_soc_dapm_enable_pin(codec, "Ext Mic 3"); + snd_soc_dapm_disable_pin(codec, "Headset Mic 2"); + snd_soc_dapm_disable_pin(codec, "Headset Stereophone"); + + ret = snd_soc_dapm_sync(codec); + if (ret) + return ret; + + /* Headset jack detection */ + snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE + | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, + &hs_jack); + snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), + hs_jack_pins); + snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE, + &mic_jack); + snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), + mic_jack_pins); + + /* headphone, microphone detection & headset short detection */ + pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE, + SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2); + pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE); + return 0; +} + +static int __init saarb_init(void) +{ + int ret; + + if (!machine_is_saarb()) + return -ENODEV; + saarb_snd_device = platform_device_alloc("soc-audio", -1); + if (!saarb_snd_device) + return -ENOMEM; + + platform_set_drvdata(saarb_snd_device, &snd_soc_card_saarb); + + ret = platform_device_add(saarb_snd_device); + if (ret) + platform_device_put(saarb_snd_device); + + return ret; +} + +static void __exit saarb_exit(void) +{ + platform_device_unregister(saarb_snd_device); +} + +module_init(saarb_init); +module_exit(saarb_exit); + +MODULE_AUTHOR("Haojian Zhuang "); +MODULE_DESCRIPTION("ALSA SoC 88PM860x Saarb"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 8e9d869028f3ce13631af5ef41910ad8d8e6c246 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 6 Aug 2010 12:16:12 -0500 Subject: asoc/multi-component: fsl: add support for variable SSI FIFO depth Add code that programs the DMA and SSI controllers differently based on the FIFO depth of the SSI. The SSI devices on the MPC8610 and the P1022 are identical in every way except one: the transmit and receive FIFO depth. On the MPC8610, the depth is eight. On the P1022, it's fifteen. The device tree nodes for the SSI include a "fsl,fifo-depth" property that specifies the FIFO depth. Signed-off-by: Timur Tabi Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/fsl/fsl_dma.c | 67 +++++++++++++++++++++++++++++++++++++------------ sound/soc/fsl/fsl_ssi.c | 25 +++++++++++++++--- 2 files changed, 73 insertions(+), 19 deletions(-) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 57774cb91ae3..dfe1cb94a70f 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -60,6 +60,7 @@ struct dma_object { struct snd_soc_platform_driver dai; dma_addr_t ssi_stx_phys; dma_addr_t ssi_srx_phys; + unsigned int ssi_fifo_depth; struct ccsr_dma_channel __iomem *channel; unsigned int irq; bool assigned; @@ -99,6 +100,7 @@ struct fsl_dma_private { unsigned int irq; struct snd_pcm_substream *substream; dma_addr_t ssi_sxx_phys; + unsigned int ssi_fifo_depth; dma_addr_t ld_buf_phys; unsigned int current_link; dma_addr_t dma_buf_phys; @@ -431,6 +433,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) else dma_private->ssi_sxx_phys = dma->ssi_srx_phys; + dma_private->ssi_fifo_depth = dma->ssi_fifo_depth; dma_private->dma_channel = dma->channel; dma_private->irq = dma->irq; dma_private->substream = substream; @@ -544,11 +547,11 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, struct device *dev = rtd->platform->dev; /* Number of bits per sample */ - unsigned int sample_size = + unsigned int sample_bits = snd_pcm_format_physical_width(params_format(hw_params)); /* Number of bytes per frame */ - unsigned int frame_size = 2 * (sample_size / 8); + unsigned int sample_bytes = sample_bits / 8; /* Bus address of SSI STX register */ dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys; @@ -588,7 +591,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, * that offset here. While we're at it, also tell the DMA controller * how much data to transfer per sample. */ - switch (sample_size) { + switch (sample_bits) { case 8: mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1; ssi_sxx_phys += 3; @@ -602,22 +605,42 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, break; default: /* We should never get here */ - dev_err(dev, "unsupported sample size %u\n", sample_size); + dev_err(dev, "unsupported sample size %u\n", sample_bits); return -EINVAL; } /* - * BWC should always be a multiple of the frame size. BWC determines - * how many bytes are sent/received before the DMA controller checks the - * SSI to see if it needs to stop. For playback, the transmit FIFO can - * hold three frames, so we want to send two frames at a time. For - * capture, the receive FIFO is triggered when it contains one frame, so - * we want to receive one frame at a time. + * BWC determines how many bytes are sent/received before the DMA + * controller checks the SSI to see if it needs to stop. BWC should + * always be a multiple of the frame size, so that we always transmit + * whole frames. Each frame occupies two slots in the FIFO. The + * parameter for CCSR_DMA_MR_BWC() is rounded down the next power of two + * (MR[BWC] can only represent even powers of two). + * + * To simplify the process, we set BWC to the largest value that is + * less than or equal to the FIFO watermark. For playback, this ensures + * that we transfer the maximum amount without overrunning the FIFO. + * For capture, this ensures that we transfer the maximum amount without + * underrunning the FIFO. + * + * f = SSI FIFO depth + * w = SSI watermark value (which equals f - 2) + * b = DMA bandwidth count (in bytes) + * s = sample size (in bytes, which equals frame_size * 2) + * + * For playback, we never transmit more than the transmit FIFO + * watermark, otherwise we might write more data than the FIFO can hold. + * The watermark is equal to the FIFO depth minus two. + * + * For capture, two equations must hold: + * w > f - (b / s) + * w >= b / s + * + * So, b > 2 * s, but b must also be <= s * w. To simplify, we set + * b = s * w, which is equal to + * (dma_private->ssi_fifo_depth - 2) * sample_bytes. */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - mr |= CCSR_DMA_MR_BWC(2 * frame_size); - else - mr |= CCSR_DMA_MR_BWC(frame_size); + mr |= CCSR_DMA_MR_BWC((dma_private->ssi_fifo_depth - 2) * sample_bytes); out_be32(&dma_channel->mr, mr); @@ -871,6 +894,7 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, struct device_node *np = of_dev->dev.of_node; struct device_node *ssi_np; struct resource res; + const uint32_t *iprop; int ret; /* Find the SSI node that points to us. */ @@ -881,15 +905,17 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, } ret = of_address_to_resource(ssi_np, 0, &res); - of_node_put(ssi_np); if (ret) { - dev_err(&of_dev->dev, "could not determine device resources\n"); + dev_err(&of_dev->dev, "could not determine resources for %s\n", + ssi_np->full_name); + of_node_put(ssi_np); return ret; } dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL); if (!dma) { dev_err(&of_dev->dev, "could not allocate dma object\n"); + of_node_put(ssi_np); return -ENOMEM; } @@ -902,6 +928,15 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0); dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0); + iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL); + if (iprop) + dma->ssi_fifo_depth = *iprop; + else + /* Older 8610 DTs didn't have the fifo-depth property */ + dma->ssi_fifo_depth = 8; + + of_node_put(ssi_np); + ret = snd_soc_register_platform(&of_dev->dev, &dma->dai); if (ret) { dev_err(&of_dev->dev, "could not register platform\n"); diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 7939c337ed9d..d1c855ade8fb 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -93,6 +93,7 @@ struct fsl_ssi_private { unsigned int playback; unsigned int capture; int asynchronous; + unsigned int fifo_depth; struct snd_soc_dai_driver cpu_dai_drv; struct device_attribute dev_attr; struct platform_device *pdev; @@ -337,11 +338,20 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, /* * Set the watermark for transmit FIFI 0 and receive FIFO 0. We - * don't use FIFO 1. Since the SSI only supports stereo, the - * watermark should never be an odd number. + * don't use FIFO 1. We program the transmit water to signal a + * DMA transfer if there are only two (or fewer) elements left + * in the FIFO. Two elements equals one frame (left channel, + * right channel). This value, however, depends on the depth of + * the transmit buffer. + * + * We program the receive FIFO to notify us if at least two + * elements (one frame) have been written to the FIFO. We could + * make this value larger (and maybe we should), but this way + * data will be written to memory as soon as it's available. */ out_be32(&ssi->sfcsr, - CCSR_SSI_SFCSR_TFWM0(6) | CCSR_SSI_SFCSR_RFWM0(2)); + CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) | + CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2)); /* * We keep the SSI disabled because if we enable it, then the @@ -622,6 +632,7 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev, struct device_attribute *dev_attr = NULL; struct device_node *np = of_dev->dev.of_node; const char *p, *sprop; + const uint32_t *iprop; struct resource res; char name[64]; @@ -678,6 +689,14 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev, else ssi_private->cpu_dai_drv.symmetric_rates = 1; + /* Determine the FIFO depth. */ + iprop = of_get_property(np, "fsl,fifo-depth", NULL); + if (iprop) + ssi_private->fifo_depth = *iprop; + else + /* Older 8610 DTs didn't have the fifo-depth property */ + ssi_private->fifo_depth = 8; + /* Initialize the the device_attribute structure */ dev_attr = &ssi_private->dev_attr; dev_attr->attr.name = "statistics"; -- cgit v1.2.3-59-g8ed1b From be265e9bae343d803145bbe910a8b00bc4bea3cc Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Thu, 12 Aug 2010 05:03:03 +0000 Subject: s2io: remove unused code usr_addrs is never referenced outside the initial struct population during open, thus making it unnecessary. Remove it, the code that references it, and the struct that it is the only user of. Signed-off-by: Jon Mason Signed-off-by: David S. Miller --- drivers/net/s2io.c | 2 -- drivers/net/s2io.h | 8 -------- 2 files changed, 10 deletions(-) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 18bc5b718bbb..0124f1201d97 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5124,8 +5124,6 @@ static void s2io_set_multicast(struct net_device *dev) /* Create the new Rx filter list and update the same in H/W. */ i = 0; netdev_for_each_mc_addr(ha, dev) { - memcpy(sp->usr_addrs[i].addr, ha->addr, - ETH_ALEN); mac_addr = 0; for (j = 0; j < ETH_ALEN; j++) { mac_addr |= ha->addr[j]; diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 0af033533905..924f618f2397 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -816,12 +816,6 @@ struct mac_info { struct stat_block *stats_info; /* Logical address of the stat block */ }; -/* structure representing the user defined MAC addresses */ -struct usr_addr { - char addr[ETH_ALEN]; - int usage_cnt; -}; - /* Default Tunable parameters of the NIC. */ #define DEFAULT_FIFO_0_LEN 4096 #define DEFAULT_FIFO_1_7_LEN 512 @@ -894,9 +888,7 @@ struct s2io_nic { #define ALL_MULTI 2 #define MAX_ADDRS_SUPPORTED 64 - u16 usr_addr_count; u16 mc_addr_count; - struct usr_addr usr_addrs[256]; u16 m_cast_flg; u16 all_multi_pos; -- cgit v1.2.3-59-g8ed1b From 666be4298bd8f9508b32833b17a686dde630f2a5 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Thu, 12 Aug 2010 05:03:04 +0000 Subject: s2io: Update driver version Update s2io driver's version to reflect the series of patches. Signed-off-by: Jon Mason Signed-off-by: David S. Miller --- drivers/net/s2io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 0124f1201d97..5f062ddfd5c5 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -90,7 +90,7 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.26.26" +#define DRV_VERSION "2.0.26.27" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; -- cgit v1.2.3-59-g8ed1b From 00093fab980d0a8950a64bdf9e346d0497b9a7e4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 14 Aug 2010 11:09:49 +0000 Subject: net/sched: remove unneeded NULL check There is no need to check "s". nla_data() doesn't return NULL. Also we already dereferenced "s" at this point so it would have oopsed ealier if it were NULL. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- net/sched/sch_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 408eea7086aa..6fb3d41c0e41 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -360,7 +360,7 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt) tsize = nla_len(tb[TCA_STAB_DATA]) / sizeof(u16); } - if (!s || tsize != s->tsize || (!tab && tsize > 0)) + if (tsize != s->tsize || (!tab && tsize > 0)) return ERR_PTR(-EINVAL); spin_lock(&qdisc_stab_lock); -- cgit v1.2.3-59-g8ed1b From 636b8116d4e116eca1ac978f546b16fadfc15a6c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 12 Aug 2010 12:22:51 +0000 Subject: drivers/net/pcmcia: Use pr_ and netdev_ On Mon, 2010-08-09 at 17:34 +0200, Dominik Brodowski wrote: > look good from a PCMCIA point of view, therefore: > Signed-off-by: Dominik Brodowski If PCMCIA is still being looked after, then here's another for you, maybe for 2.6.37. Use the more descriptive logging message styles. There are whitespace/indentation errors in the original sources that these changes do not modify, so checkpatch errors were cheerfully ignored. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/pcmcia/3c574_cs.c | 73 +++++++++-------- drivers/net/pcmcia/3c589_cs.c | 13 ++-- drivers/net/pcmcia/axnet_cs.c | 164 +++++++++++++++++++++------------------ drivers/net/pcmcia/com20020_cs.c | 32 ++++---- drivers/net/pcmcia/fmvj18x_cs.c | 60 +++++++------- drivers/net/pcmcia/ibmtr_cs.c | 13 ++-- drivers/net/pcmcia/nmclan_cs.c | 54 +++++++------ drivers/net/pcmcia/smc91c92_cs.c | 99 +++++++++++------------ drivers/net/pcmcia/xirc2ps_cs.c | 104 +++++++++++-------------- 9 files changed, 298 insertions(+), 314 deletions(-) diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 9a1840b67e78..9b319be7f1d2 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -69,6 +69,8 @@ earlier 3Com products. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -373,8 +375,8 @@ static int tc574_config(struct pcmcia_device *link) for (i = 0; i < 3; i++) phys_addr[i] = htons(read_eeprom(ioaddr, i + 10)); if (phys_addr[0] == htons(0x6060)) { - printk(KERN_NOTICE "3c574_cs: IO port conflict at 0x%03lx" - "-0x%03lx\n", dev->base_addr, dev->base_addr+15); + pr_notice("IO port conflict at 0x%03lx-0x%03lx\n", + dev->base_addr, dev->base_addr+15); goto failed; } } @@ -388,7 +390,7 @@ static int tc574_config(struct pcmcia_device *link) outw(2<<11, ioaddr + RunnerRdCtrl); mcr = inb(ioaddr + 2); outw(0<<11, ioaddr + RunnerRdCtrl); - printk(KERN_INFO " ASIC rev %d,", mcr>>3); + pr_info(" ASIC rev %d,", mcr>>3); EL3WINDOW(3); config = inl(ioaddr + Wn3_Config); lp->default_media = (config & Xcvr) >> Xcvr_shift; @@ -425,7 +427,7 @@ static int tc574_config(struct pcmcia_device *link) } } if (phy > 32) { - printk(KERN_NOTICE " No MII transceivers found!\n"); + pr_notice(" No MII transceivers found!\n"); goto failed; } i = mdio_read(ioaddr, lp->phys, 16) | 0x40; @@ -441,18 +443,16 @@ static int tc574_config(struct pcmcia_device *link) SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev) != 0) { - printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n"); + pr_notice("register_netdev() failed\n"); goto failed; } - printk(KERN_INFO "%s: %s at io %#3lx, irq %d, " - "hw_addr %pM.\n", - dev->name, cardname, dev->base_addr, dev->irq, - dev->dev_addr); - printk(" %dK FIFO split %s Rx:Tx, %sMII interface.\n", - 8 << config & Ram_size, - ram_split[(config & Ram_split) >> Ram_split_shift], - config & Autoselect ? "autoselect " : ""); + netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n", + cardname, dev->base_addr, dev->irq, dev->dev_addr); + netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n", + 8 << config & Ram_size, + ram_split[(config & Ram_split) >> Ram_split_shift], + config & Autoselect ? "autoselect " : ""); return 0; @@ -499,14 +499,14 @@ static void dump_status(struct net_device *dev) { unsigned int ioaddr = dev->base_addr; EL3WINDOW(1); - printk(KERN_INFO " irq status %04x, rx status %04x, tx status " - "%02x, tx free %04x\n", inw(ioaddr+EL3_STATUS), - inw(ioaddr+RxStatus), inb(ioaddr+TxStatus), - inw(ioaddr+TxFree)); + netdev_info(dev, " irq status %04x, rx status %04x, tx status %02x, tx free %04x\n", + inw(ioaddr+EL3_STATUS), + inw(ioaddr+RxStatus), inb(ioaddr+TxStatus), + inw(ioaddr+TxFree)); EL3WINDOW(4); - printk(KERN_INFO " diagnostics: fifo %04x net %04x ethernet %04x" - " media %04x\n", inw(ioaddr+0x04), inw(ioaddr+0x06), - inw(ioaddr+0x08), inw(ioaddr+0x0a)); + netdev_info(dev, " diagnostics: fifo %04x net %04x ethernet %04x media %04x\n", + inw(ioaddr+0x04), inw(ioaddr+0x06), + inw(ioaddr+0x08), inw(ioaddr+0x0a)); EL3WINDOW(1); } @@ -520,7 +520,7 @@ static void tc574_wait_for_completion(struct net_device *dev, int cmd) while (--i > 0) if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break; if (i == 0) - printk(KERN_NOTICE "%s: command 0x%04x did not complete!\n", dev->name, cmd); + netdev_notice(dev, "command 0x%04x did not complete!\n", cmd); } /* Read a word from the EEPROM using the regular EEPROM access register. @@ -722,7 +722,7 @@ static void el3_tx_timeout(struct net_device *dev) { unsigned int ioaddr = dev->base_addr; - printk(KERN_NOTICE "%s: Transmit timed out!\n", dev->name); + netdev_notice(dev, "Transmit timed out!\n"); dump_status(dev); dev->stats.tx_errors++; dev->trans_start = jiffies; /* prevent tx timeout */ @@ -845,8 +845,8 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id) EL3WINDOW(4); fifo_diag = inw(ioaddr + Wn4_FIFODiag); EL3WINDOW(1); - printk(KERN_NOTICE "%s: adapter failure, FIFO diagnostic" - " register %04x.\n", dev->name, fifo_diag); + netdev_notice(dev, "adapter failure, FIFO diagnostic register %04x\n", + fifo_diag); if (fifo_diag & 0x0400) { /* Tx overrun */ tc574_wait_for_completion(dev, TxReset); @@ -900,7 +900,7 @@ static void media_check(unsigned long arg) this, we can limp along even if the interrupt is blocked */ if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) { if (!lp->fast_poll) - printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); + netdev_info(dev, "interrupt(s) dropped!\n"); local_irq_save(flags); el3_interrupt(dev->irq, dev); @@ -923,23 +923,21 @@ static void media_check(unsigned long arg) if (media != lp->media_status) { if ((media ^ lp->media_status) & 0x0004) - printk(KERN_INFO "%s: %s link beat\n", dev->name, - (lp->media_status & 0x0004) ? "lost" : "found"); + netdev_info(dev, "%s link beat\n", + (lp->media_status & 0x0004) ? "lost" : "found"); if ((media ^ lp->media_status) & 0x0020) { lp->partner = 0; if (lp->media_status & 0x0020) { - printk(KERN_INFO "%s: autonegotiation restarted\n", - dev->name); + netdev_info(dev, "autonegotiation restarted\n"); } else if (partner) { partner &= lp->advertising; lp->partner = partner; - printk(KERN_INFO "%s: autonegotiation complete: " - "%sbaseT-%cD selected\n", dev->name, - ((partner & 0x0180) ? "100" : "10"), - ((partner & 0x0140) ? 'F' : 'H')); + netdev_info(dev, "autonegotiation complete: " + "%dbaseT-%cD selected\n", + (partner & 0x0180) ? 100 : 10, + (partner & 0x0140) ? 'F' : 'H'); } else { - printk(KERN_INFO "%s: link partner did not autonegotiate\n", - dev->name); + netdev_info(dev, "link partner did not autonegotiate\n"); } EL3WINDOW(3); @@ -949,10 +947,9 @@ static void media_check(unsigned long arg) } if (media & 0x0010) - printk(KERN_INFO "%s: remote fault detected\n", - dev->name); + netdev_info(dev, "remote fault detected\n"); if (media & 0x0002) - printk(KERN_INFO "%s: jabber detected\n", dev->name); + netdev_info(dev, "jabber detected\n"); lp->media_status = media; } spin_unlock_irqrestore(&lp->window_lock, flags); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 61f9cf2100ff..1c534f392474 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -19,6 +19,8 @@ ======================================================================*/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "3c589_cs" #define DRV_VERSION "1.162-ac" @@ -273,8 +275,7 @@ static int tc589_config(struct pcmcia_device *link) phys_addr = (__be16 *)dev->dev_addr; /* Is this a 3c562? */ if (link->manf_id != MANFID_3COM) - printk(KERN_INFO "3c589_cs: hmmm, is this really a " - "3Com card??\n"); + dev_info(&link->dev, "hmmm, is this really a 3Com card??\n"); multi = (link->card_id == PRODID_3COM_3C562); link->io_lines = 16; @@ -315,8 +316,8 @@ static int tc589_config(struct pcmcia_device *link) for (i = 0; i < 3; i++) phys_addr[i] = htons(read_eeprom(ioaddr, i)); if (phys_addr[0] == htons(0x6060)) { - printk(KERN_ERR "3c589_cs: IO port conflict at 0x%03lx" - "-0x%03lx\n", dev->base_addr, dev->base_addr+15); + dev_err(&link->dev, "IO port conflict at 0x%03lx-0x%03lx\n", + dev->base_addr, dev->base_addr+15); goto failed; } } @@ -330,12 +331,12 @@ static int tc589_config(struct pcmcia_device *link) if ((if_port >= 0) && (if_port <= 3)) dev->if_port = if_port; else - printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); + dev_err(&link->dev, "invalid if_port requested\n"); SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev) != 0) { - printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); + dev_err(&link->dev, "register_netdev() failed\n"); goto failed; } diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index a6e37b29e3bf..e97f1519a15f 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -24,6 +24,8 @@ ======================================================================*/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -344,8 +346,8 @@ static int axnet_config(struct pcmcia_device *link) dev->base_addr = link->resource[0]->start; if (!get_prom(link)) { - printk(KERN_NOTICE "axnet_cs: this is not an AX88190 card!\n"); - printk(KERN_NOTICE "axnet_cs: use pcnet_cs instead.\n"); + pr_notice("this is not an AX88190 card!\n"); + pr_notice("use pcnet_cs instead.\n"); goto failed; } @@ -390,19 +392,18 @@ static int axnet_config(struct pcmcia_device *link) SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev) != 0) { - printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n"); + pr_notice("register_netdev() failed\n"); goto failed; } - printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, " - "hw_addr %pM\n", - dev->name, ((info->flags & IS_AX88790) ? 7 : 1), - dev->base_addr, dev->irq, - dev->dev_addr); + netdev_info(dev, "Asix AX88%d90: io %#3lx, irq %d, hw_addr %pM\n", + ((info->flags & IS_AX88790) ? 7 : 1), + dev->base_addr, dev->irq, dev->dev_addr); if (info->phy_id != -1) { - dev_dbg(&link->dev, " MII transceiver at index %d, status %x.\n", info->phy_id, j); + netdev_dbg(dev, " MII transceiver at index %d, status %x\n", + info->phy_id, j); } else { - printk(KERN_NOTICE " No MII transceivers found!\n"); + netdev_notice(dev, " No MII transceivers found!\n"); } return 0; @@ -582,8 +583,7 @@ static void axnet_reset_8390(struct net_device *dev) outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */ if (i == 100) - printk(KERN_ERR "%s: axnet_reset_8390() did not complete.\n", - dev->name); + netdev_err(dev, "axnet_reset_8390() did not complete\n"); } /* axnet_reset_8390 */ @@ -610,7 +610,7 @@ static void ei_watchdog(u_long arg) this, we can limp along even if the interrupt is blocked */ if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) { if (!info->fast_poll) - printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); + netdev_info(dev, "interrupt(s) dropped!\n"); ei_irq_wrapper(dev->irq, dev); info->fast_poll = HZ; } @@ -625,7 +625,7 @@ static void ei_watchdog(u_long arg) goto reschedule; link = mdio_read(mii_addr, info->phy_id, 1); if (!link || (link == 0xffff)) { - printk(KERN_INFO "%s: MII is missing!\n", dev->name); + netdev_info(dev, "MII is missing!\n"); info->phy_id = -1; goto reschedule; } @@ -633,18 +633,14 @@ static void ei_watchdog(u_long arg) link &= 0x0004; if (link != info->link_status) { u_short p = mdio_read(mii_addr, info->phy_id, 5); - printk(KERN_INFO "%s: %s link beat\n", dev->name, - (link) ? "found" : "lost"); + netdev_info(dev, "%s link beat\n", link ? "found" : "lost"); if (link) { info->duplex_flag = (p & 0x0140) ? 0x80 : 0x00; if (p) - printk(KERN_INFO "%s: autonegotiation complete: " - "%sbaseT-%cD selected\n", dev->name, - ((p & 0x0180) ? "100" : "10"), - ((p & 0x0140) ? 'F' : 'H')); + netdev_info(dev, "autonegotiation complete: %dbaseT-%cD selected\n", + (p & 0x0180) ? 100 : 10, (p & 0x0140) ? 'F' : 'H'); else - printk(KERN_INFO "%s: link partner did not autonegotiate\n", - dev->name); + netdev_info(dev, "link partner did not autonegotiate\n"); AX88190_init(dev, 1); } info->link_status = link; @@ -842,9 +838,6 @@ module_exit(exit_axnet_cs); */ -static const char version_8390[] = KERN_INFO \ - "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@scyld.com)\n"; - #include #include #include @@ -991,9 +984,11 @@ static void axnet_tx_timeout(struct net_device *dev) isr = inb(e8390_base+EN0_ISR); spin_unlock_irqrestore(&ei_local->page_lock, flags); - printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", - dev->name, (txsr & ENTSR_ABT) ? "excess collisions." : - (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar); + netdev_printk(KERN_DEBUG, dev, + "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", + (txsr & ENTSR_ABT) ? "excess collisions." : + (isr) ? "lost interrupt?" : "cable problem?", + txsr, isr, tickssofar); if (!isr && !dev->stats.tx_packets) { @@ -1063,22 +1058,28 @@ static netdev_tx_t axnet_start_xmit(struct sk_buff *skb, output_page = ei_local->tx_start_page; ei_local->tx1 = send_length; if (ei_debug && ei_local->tx2 > 0) - printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n", - dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing); + netdev_printk(KERN_DEBUG, dev, + "idle transmitter tx2=%d, lasttx=%d, txing=%d\n", + ei_local->tx2, ei_local->lasttx, + ei_local->txing); } else if (ei_local->tx2 == 0) { output_page = ei_local->tx_start_page + TX_PAGES/2; ei_local->tx2 = send_length; if (ei_debug && ei_local->tx1 > 0) - printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n", - dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing); + netdev_printk(KERN_DEBUG, dev, + "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n", + ei_local->tx1, ei_local->lasttx, + ei_local->txing); } else { /* We should never get here. */ if (ei_debug) - printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n", - dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx); + netdev_printk(KERN_DEBUG, dev, + "No Tx buffers free! tx1=%d tx2=%d last=%d\n", + ei_local->tx1, ei_local->tx2, + ei_local->lasttx); ei_local->irqlock = 0; netif_stop_queue(dev); outb_p(ENISR_ALL, e8390_base + EN0_IMR); @@ -1166,23 +1167,26 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id) spin_lock_irqsave(&ei_local->page_lock, flags); - if (ei_local->irqlock) - { + if (ei_local->irqlock) { #if 1 /* This might just be an interrupt for a PCI device sharing this line */ + const char *msg; /* The "irqlock" check is only for testing. */ - printk(ei_local->irqlock - ? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n" - : "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n", - dev->name, inb_p(e8390_base + EN0_ISR), - inb_p(e8390_base + EN0_IMR)); + if (ei_local->irqlock) + msg = "Interrupted while interrupts are masked!"; + else + msg = "Reentering the interrupt handler!"; + netdev_info(dev, "%s, isr=%#2x imr=%#2x\n", + msg, + inb_p(e8390_base + EN0_ISR), + inb_p(e8390_base + EN0_IMR)); #endif spin_unlock_irqrestore(&ei_local->page_lock, flags); return IRQ_NONE; } if (ei_debug > 3) - printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name, - inb_p(e8390_base + EN0_ISR)); + netdev_printk(KERN_DEBUG, dev, "interrupt(isr=%#2.2x)\n", + inb_p(e8390_base + EN0_ISR)); outb_p(0x00, e8390_base + EN0_ISR); ei_local->irqlock = 1; @@ -1193,7 +1197,8 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id) { if (!netif_running(dev) || (interrupts == 0xff)) { if (ei_debug > 1) - printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name); + netdev_warn(dev, + "interrupt from stopped card\n"); outb_p(interrupts, e8390_base + EN0_ISR); interrupts = 0; break; @@ -1236,11 +1241,12 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id) { /* 0xFF is valid for a card removal */ if(interrupts!=0xFF) - printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n", - dev->name, interrupts); + netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n", + interrupts); outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */ } else { - printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts); + netdev_warn(dev, "unknown interrupt %#2x\n", + interrupts); outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */ } } @@ -1274,18 +1280,19 @@ static void ei_tx_err(struct net_device *dev) unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU); #ifdef VERBOSE_ERROR_DUMP - printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr); + netdev_printk(KERN_DEBUG, dev, + "transmitter error (%#2x):", txsr); if (txsr & ENTSR_ABT) - printk("excess-collisions "); + pr_cont(" excess-collisions"); if (txsr & ENTSR_ND) - printk("non-deferral "); + pr_cont(" non-deferral"); if (txsr & ENTSR_CRS) - printk("lost-carrier "); + pr_cont(" lost-carrier"); if (txsr & ENTSR_FU) - printk("FIFO-underrun "); + pr_cont(" FIFO-underrun"); if (txsr & ENTSR_CDH) - printk("lost-heartbeat "); - printk("\n"); + pr_cont(" lost-heartbeat"); + pr_cont("\n"); #endif if (tx_was_aborted) @@ -1322,8 +1329,9 @@ static void ei_tx_intr(struct net_device *dev) if (ei_local->tx1 < 0) { if (ei_local->lasttx != 1 && ei_local->lasttx != -1) - printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n", - ei_local->name, ei_local->lasttx, ei_local->tx1); + netdev_err(dev, "%s: bogus last_tx_buffer %d, tx1=%d\n", + ei_local->name, ei_local->lasttx, + ei_local->tx1); ei_local->tx1 = 0; if (ei_local->tx2 > 0) { @@ -1338,8 +1346,9 @@ static void ei_tx_intr(struct net_device *dev) else if (ei_local->tx2 < 0) { if (ei_local->lasttx != 2 && ei_local->lasttx != -2) - printk("%s: bogus last_tx_buffer %d, tx2=%d.\n", - ei_local->name, ei_local->lasttx, ei_local->tx2); + netdev_info(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n", + ei_local->name, ei_local->lasttx, + ei_local->tx2); ei_local->tx2 = 0; if (ei_local->tx1 > 0) { @@ -1352,8 +1361,9 @@ static void ei_tx_intr(struct net_device *dev) else ei_local->lasttx = 10, ei_local->txing = 0; } -// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n", -// dev->name, ei_local->lasttx); +// else +// netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n", +// ei_local->lasttx); /* Minimize Tx latency: update the statistics after we restart TXing. */ if (status & ENTSR_COL) @@ -1416,8 +1426,8 @@ static void ei_receive(struct net_device *dev) is that some clones crash in roughly the same way. */ if (ei_debug > 0 && this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF)) - printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n", - dev->name, this_frame, ei_local->current_page); + netdev_err(dev, "mismatched read page pointers %2x vs %2x\n", + this_frame, ei_local->current_page); if (this_frame == rxing_page) /* Read all the frames? */ break; /* Done for now */ @@ -1433,9 +1443,10 @@ static void ei_receive(struct net_device *dev) if (pkt_len < 60 || pkt_len > 1518) { if (ei_debug) - printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n", - dev->name, rx_frame.count, rx_frame.status, - rx_frame.next); + netdev_printk(KERN_DEBUG, dev, + "bogus packet size: %d, status=%#2x nxpg=%#2x\n", + rx_frame.count, rx_frame.status, + rx_frame.next); dev->stats.rx_errors++; dev->stats.rx_length_errors++; } @@ -1447,8 +1458,9 @@ static void ei_receive(struct net_device *dev) if (skb == NULL) { if (ei_debug > 1) - printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n", - dev->name, pkt_len); + netdev_printk(KERN_DEBUG, dev, + "Couldn't allocate a sk_buff of size %d\n", + pkt_len); dev->stats.rx_dropped++; break; } @@ -1468,9 +1480,10 @@ static void ei_receive(struct net_device *dev) else { if (ei_debug) - printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n", - dev->name, rx_frame.status, rx_frame.next, - rx_frame.count); + netdev_printk(KERN_DEBUG, dev, + "bogus packet: status=%#2x nxpg=%#2x size=%d\n", + rx_frame.status, rx_frame.next, + rx_frame.count); dev->stats.rx_errors++; /* NB: The NIC counts CRC, frame and missed errors. */ if (pkt_stat & ENRSR_FO) @@ -1480,8 +1493,8 @@ static void ei_receive(struct net_device *dev) /* This _should_ never happen: it's here for avoiding bad clones. */ if (next_frame >= ei_local->stop_page) { - printk("%s: next frame inconsistency, %#2x\n", dev->name, - next_frame); + netdev_info(dev, "next frame inconsistency, %#2x\n", + next_frame); next_frame = ei_local->rx_start_page; } ei_local->current_page = next_frame; @@ -1516,7 +1529,7 @@ static void ei_rx_overrun(struct net_device *dev) outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); if (ei_debug > 1) - printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name); + netdev_printk(KERN_DEBUG, dev, "Receiver overrun\n"); dev->stats.rx_over_errors++; /* @@ -1713,7 +1726,7 @@ static void AX88190_init(struct net_device *dev, int startp) { outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i)); if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i]) - printk(KERN_ERR "Hw. address read/write mismap %d\n",i); + netdev_err(dev, "Hw. address read/write mismap %d\n", i); } outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); @@ -1750,8 +1763,7 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length, if (inb_p(e8390_base) & E8390_TRANS) { - printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n", - dev->name); + netdev_warn(dev, "trigger_send() called with the transmitter busy\n"); return; } outb_p(length & 0xff, e8390_base + EN0_TCNTLO); diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 3c400cfa82ae..f065c35cd4b7 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -52,23 +52,23 @@ #define VERSION "arcnet: COM20020 PCMCIA support loaded.\n" -#ifdef DEBUG static void regdump(struct net_device *dev) { +#ifdef DEBUG int ioaddr = dev->base_addr; int count; - printk("com20020 register dump:\n"); + netdev_dbg(dev, "register dump:\n"); for (count = ioaddr; count < ioaddr + 16; count++) { if (!(count % 16)) - printk("\n%04X: ", count); - printk("%02X ", inb(count)); + pr_cont("%04X:", count); + pr_cont(" %02X", inb(count)); } - printk("\n"); + pr_cont("\n"); - printk("buffer0 dump:\n"); + netdev_dbg(dev, "buffer0 dump:\n"); /* set up the address register */ count = 0; outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI); @@ -77,19 +77,15 @@ static void regdump(struct net_device *dev) for (count = 0; count < 256+32; count++) { if (!(count % 16)) - printk("\n%04X: ", count); + pr_cont("%04X:", count); /* copy the data */ - printk("%02X ", inb(_MEMDATA)); + pr_cont(" %02X", inb(_MEMDATA)); } - printk("\n"); + pr_cont("\n"); +#endif } -#else - -static inline void regdump(struct net_device *dev) { } - -#endif /*====================================================================*/ @@ -301,13 +297,13 @@ static int com20020_config(struct pcmcia_device *link) i = com20020_found(dev, 0); /* calls register_netdev */ if (i != 0) { - dev_printk(KERN_NOTICE, &link->dev, - "com20020_cs: com20020_found() failed\n"); + dev_notice(&link->dev, + "com20020_found() failed\n"); goto failed; } - dev_dbg(&link->dev,KERN_INFO "%s: port %#3lx, irq %d\n", - dev->name, dev->base_addr, dev->irq); + netdev_dbg(dev, "port %#3lx, irq %d\n", + dev->base_addr, dev->irq); return 0; failed: diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 98fffb03ecd7..8f26d548d1bb 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -28,6 +28,8 @@ ======================================================================*/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "fmvj18x_cs" #define DRV_VERSION "2.9" @@ -291,7 +293,7 @@ static int mfc_try_io_port(struct pcmcia_device *link) link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; if (link->resource[1]->start == 0) { link->resource[1]->end = 0; - printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n"); + pr_notice("out of resource for serial\n"); } ret = pcmcia_request_io(link); if (ret == 0) @@ -503,7 +505,7 @@ static int fmvj18x_config(struct pcmcia_device *link) case XXX10304: /* Read MACID from Buggy CIS */ if (fmvj18x_get_hwinfo(link, buggybuf) == -1) { - printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n"); + pr_notice("unable to read hardware net address\n"); goto failed; } for (i = 0 ; i < 6; i++) { @@ -524,15 +526,14 @@ static int fmvj18x_config(struct pcmcia_device *link) SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev) != 0) { - printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n"); + pr_notice("register_netdev() failed\n"); goto failed; } /* print current configuration */ - printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, " - "hw_addr %pM\n", - dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2", - dev->base_addr, dev->irq, dev->dev_addr); + netdev_info(dev, "%s, sram %s, port %#3lx, irq %d, hw_addr %pM\n", + card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2", + dev->base_addr, dev->irq, dev->dev_addr); return 0; @@ -606,7 +607,7 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link) lp->base = ioremap(req.Base, req.Size); if (lp->base == NULL) { - printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n"); + netdev_notice(dev, "ioremap failed\n"); return -1; } @@ -800,17 +801,16 @@ static void fjn_tx_timeout(struct net_device *dev) struct local_info_t *lp = netdev_priv(dev); unsigned int ioaddr = dev->base_addr; - printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n", - dev->name, htons(inw(ioaddr + TX_STATUS)), - inb(ioaddr + TX_STATUS) & F_TMT_RDY - ? "IRQ conflict" : "network cable problem"); - printk(KERN_NOTICE "%s: timeout registers: %04x %04x %04x " - "%04x %04x %04x %04x %04x.\n", - dev->name, htons(inw(ioaddr + 0)), - htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)), - htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)), - htons(inw(ioaddr +10)), htons(inw(ioaddr +12)), - htons(inw(ioaddr +14))); + netdev_notice(dev, "transmit timed out with status %04x, %s?\n", + htons(inw(ioaddr + TX_STATUS)), + inb(ioaddr + TX_STATUS) & F_TMT_RDY + ? "IRQ conflict" : "network cable problem"); + netdev_notice(dev, "timeout registers: %04x %04x %04x " + "%04x %04x %04x %04x %04x.\n", + htons(inw(ioaddr + 0)), htons(inw(ioaddr + 2)), + htons(inw(ioaddr + 4)), htons(inw(ioaddr + 6)), + htons(inw(ioaddr + 8)), htons(inw(ioaddr + 10)), + htons(inw(ioaddr + 12)), htons(inw(ioaddr + 14))); dev->stats.tx_errors++; /* ToDo: We should try to restart the adaptor... */ local_irq_disable(); @@ -845,13 +845,13 @@ static netdev_tx_t fjn_start_xmit(struct sk_buff *skb, unsigned char *buf = skb->data; if (length > ETH_FRAME_LEN) { - printk(KERN_NOTICE "%s: Attempting to send a large packet" - " (%d bytes).\n", dev->name, length); + netdev_notice(dev, "Attempting to send a large packet (%d bytes)\n", + length); return NETDEV_TX_BUSY; } - pr_debug("%s: Transmitting a packet of length %lu.\n", - dev->name, (unsigned long)skb->len); + netdev_dbg(dev, "Transmitting a packet of length %lu\n", + (unsigned long)skb->len); dev->stats.tx_bytes += skb->len; /* Disable both interrupts. */ @@ -904,7 +904,7 @@ static void fjn_reset(struct net_device *dev) unsigned int ioaddr = dev->base_addr; int i; - pr_debug("fjn_reset(%s) called.\n",dev->name); + netdev_dbg(dev, "fjn_reset() called\n"); /* Reset controller */ if( sram_config == 0 ) @@ -988,8 +988,8 @@ static void fjn_rx(struct net_device *dev) while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) { u_short status = inw(ioaddr + DATAPORT); - pr_debug("%s: Rxing packet mode %02x status %04x.\n", - dev->name, inb(ioaddr + RX_MODE), status); + netdev_dbg(dev, "Rxing packet mode %02x status %04x.\n", + inb(ioaddr + RX_MODE), status); #ifndef final_version if (status == 0) { outb(F_SKP_PKT, ioaddr + RX_SKIP); @@ -1008,16 +1008,16 @@ static void fjn_rx(struct net_device *dev) struct sk_buff *skb; if (pkt_len > 1550) { - printk(KERN_NOTICE "%s: The FMV-18x claimed a very " - "large packet, size %d.\n", dev->name, pkt_len); + netdev_notice(dev, "The FMV-18x claimed a very large packet, size %d\n", + pkt_len); outb(F_SKP_PKT, ioaddr + RX_SKIP); dev->stats.rx_errors++; break; } skb = dev_alloc_skb(pkt_len+2); if (skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping " - "packet (len %d).\n", dev->name, pkt_len); + netdev_notice(dev, "Memory squeeze, dropping packet (len %d)\n", + pkt_len); outb(F_SKP_PKT, ioaddr + RX_SKIP); dev->stats.rx_dropped++; break; diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index cbcda123b1bf..dc85282193bf 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -45,6 +45,8 @@ ======================================================================*/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -272,15 +274,14 @@ static int __devinit ibmtr_config(struct pcmcia_device *link) i = ibmtr_probe_card(dev); if (i != 0) { - printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n"); + pr_notice("register_netdev() failed\n"); goto failed; } - printk(KERN_INFO - "%s: port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n", - dev->name, dev->base_addr, dev->irq, - (u_long)ti->mmio, (u_long)(ti->sram_base << 12), - dev->dev_addr); + netdev_info(dev, "port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n", + dev->base_addr, dev->irq, + (u_long)ti->mmio, (u_long)(ti->sram_base << 12), + dev->dev_addr); return 0; failed: diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 68f2deeb3ade..89cf63bb8c91 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -111,6 +111,8 @@ Log: nmclan_cs.c,v ---------------------------------------------------------------------------- */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "nmclan_cs" #define DRV_VERSION "0.16" @@ -563,7 +565,7 @@ static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr) /* Wait for reset bit to be cleared automatically after <= 200ns */; if(++ct > 500) { - printk(KERN_ERR "mace: reset failed, card removed ?\n"); + pr_err("reset failed, card removed?\n"); return -1; } udelay(1); @@ -610,7 +612,7 @@ static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr) { if(++ ct > 500) { - printk(KERN_ERR "mace: ADDRCHG timeout, card removed ?\n"); + pr_err("ADDRCHG timeout, card removed?\n"); return -1; } } @@ -678,8 +680,8 @@ static int nmclan_config(struct pcmcia_device *link) dev_dbg(&link->dev, "nmclan_cs configured: mace id=%x %x\n", sig[0], sig[1]); } else { - printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should" - " be 0x40 0x?9\n", sig[0], sig[1]); + pr_notice("mace id not found: %x %x should be 0x40 0x?9\n", + sig[0], sig[1]); return -ENODEV; } } @@ -691,20 +693,18 @@ static int nmclan_config(struct pcmcia_device *link) if (if_port <= 2) dev->if_port = if_port; else - printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n"); + pr_notice("invalid if_port requested\n"); SET_NETDEV_DEV(dev, &link->dev); i = register_netdev(dev); if (i != 0) { - printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n"); + pr_notice("register_netdev() failed\n"); goto failed; } - printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port," - " hw_addr %pM\n", - dev->name, dev->base_addr, dev->irq, if_names[dev->if_port], - dev->dev_addr); + netdev_info(dev, "nmclan: port %#3lx, irq %d, %s port, hw_addr %pM\n", + dev->base_addr, dev->irq, if_names[dev->if_port], dev->dev_addr); return 0; failed: @@ -798,8 +798,7 @@ static int mace_config(struct net_device *dev, struct ifmap *map) if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { if (map->port <= 2) { dev->if_port = map->port; - printk(KERN_INFO "%s: switched to %s port\n", dev->name, - if_names[dev->if_port]); + netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]); } else return -EINVAL; } @@ -878,12 +877,12 @@ static void mace_tx_timeout(struct net_device *dev) mace_private *lp = netdev_priv(dev); struct pcmcia_device *link = lp->p_dev; - printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name); + netdev_notice(dev, "transmit timed out -- "); #if RESET_ON_TIMEOUT - printk("resetting card\n"); + pr_cont("resetting card\n"); pcmcia_reset_card(link->socket); #else /* #if RESET_ON_TIMEOUT */ - printk("NOT resetting card\n"); + pr_cont("NOT resetting card\n"); #endif /* #if RESET_ON_TIMEOUT */ dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); @@ -965,22 +964,21 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) ioaddr = dev->base_addr; if (lp->tx_irq_disabled) { - printk( - (lp->tx_irq_disabled? - KERN_NOTICE "%s: Interrupt with tx_irq_disabled " - "[isr=%02X, imr=%02X]\n": - KERN_NOTICE "%s: Re-entering the interrupt handler " - "[isr=%02X, imr=%02X]\n"), - dev->name, - inb(ioaddr + AM2150_MACE_BASE + MACE_IR), - inb(ioaddr + AM2150_MACE_BASE + MACE_IMR) - ); + const char *msg; + if (lp->tx_irq_disabled) + msg = "Interrupt with tx_irq_disabled"; + else + msg = "Re-entering the interrupt handler"; + netdev_notice(dev, "%s [isr=%02X, imr=%02X]\n", + msg, + inb(ioaddr + AM2150_MACE_BASE + MACE_IR), + inb(ioaddr + AM2150_MACE_BASE + MACE_IMR)); /* WARNING: MACE_IR has been read! */ return IRQ_NONE; } if (!netif_device_present(dev)) { - pr_debug("%s: interrupt from dead card\n", dev->name); + netdev_dbg(dev, "interrupt from dead card\n"); return IRQ_NONE; } @@ -1378,8 +1376,8 @@ static void BuildLAF(int *ladrf, int *adr) printk(KERN_DEBUG " adr =%pM\n", adr); printk(KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63] =", hashcode); for (i = 0; i < 8; i++) - printk(KERN_CONT " %02X", ladrf[i]); - printk(KERN_CONT "\n"); + pr_cont(" %02X", ladrf[i]); + pr_cont("\n"); #endif } /* BuildLAF */ diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 377367d03b41..cc7a357feac9 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -25,6 +25,8 @@ ======================================================================*/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -820,7 +822,7 @@ static int check_sig(struct pcmcia_device *link) modconf_t mod = { .Attributes = CONF_IO_CHANGE_WIDTH, }; - printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); + pr_info("using 8-bit IO window\n"); smc91c92_suspend(link); pcmcia_modify_configuration(link, &mod); @@ -881,7 +883,7 @@ static int smc91c92_config(struct pcmcia_device *link) if ((if_port >= 0) && (if_port <= 2)) dev->if_port = if_port; else - printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n"); + dev_notice(&link->dev, "invalid if_port requested\n"); switch (smc->manfid) { case MANFID_OSITECH: @@ -899,7 +901,7 @@ static int smc91c92_config(struct pcmcia_device *link) } if (i != 0) { - printk(KERN_NOTICE "smc91c92_cs: Unable to find hardware address.\n"); + dev_notice(&link->dev, "Unable to find hardware address.\n"); goto config_failed; } @@ -952,30 +954,28 @@ static int smc91c92_config(struct pcmcia_device *link) SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev) != 0) { - printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n"); + dev_err(&link->dev, "register_netdev() failed\n"); goto config_undo; } - printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, " - "hw_addr %pM\n", - dev->name, name, (rev & 0x0f), dev->base_addr, dev->irq, - dev->dev_addr); + netdev_info(dev, "smc91c%s rev %d: io %#3lx, irq %d, hw_addr %pM\n", + name, (rev & 0x0f), dev->base_addr, dev->irq, dev->dev_addr); if (rev > 0) { if (mir & 0x3ff) - printk(KERN_INFO " %lu byte", mir); + netdev_info(dev, " %lu byte", mir); else - printk(KERN_INFO " %lu kb", mir>>10); - printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ? - "MII" : if_names[dev->if_port]); + netdev_info(dev, " %lu kb", mir>>10); + pr_cont(" buffer, %s xcvr\n", + (smc->cfg & CFG_MII_SELECT) ? "MII" : if_names[dev->if_port]); } if (smc->cfg & CFG_MII_SELECT) { if (smc->mii_if.phy_id != -1) { - dev_dbg(&link->dev, " MII transceiver at index %d, status %x.\n", - smc->mii_if.phy_id, j); + netdev_dbg(dev, " MII transceiver at index %d, status %x\n", + smc->mii_if.phy_id, j); } else { - printk(KERN_NOTICE " No MII transceivers found!\n"); + netdev_notice(dev, " No MII transceivers found!\n"); } } return 0; @@ -1081,10 +1081,10 @@ static void smc_dump(struct net_device *dev) save = inw(ioaddr + BANK_SELECT); for (w = 0; w < 4; w++) { SMC_SELECT_BANK(w); - printk(KERN_DEBUG "bank %d: ", w); + netdev_printk(KERN_DEBUG, dev, "bank %d: ", w); for (i = 0; i < 14; i += 2) - printk(" %04x", inw(ioaddr + i)); - printk("\n"); + pr_cont(" %04x", inw(ioaddr + i)); + pr_cont("\n"); } outw(save, ioaddr + BANK_SELECT); } @@ -1106,7 +1106,7 @@ static int smc_open(struct net_device *dev) return -ENODEV; /* Physical device present signature. */ if (check_sig(link) < 0) { - printk("smc91c92_cs: Yikes! Bad chip signature!\n"); + netdev_info(dev, "Yikes! Bad chip signature!\n"); return -ENODEV; } link->open++; @@ -1172,7 +1172,7 @@ static void smc_hardware_send_packet(struct net_device * dev) u_char packet_no; if (!skb) { - printk(KERN_ERR "%s: In XMIT with no packet to send.\n", dev->name); + netdev_err(dev, "In XMIT with no packet to send\n"); return; } @@ -1180,8 +1180,8 @@ static void smc_hardware_send_packet(struct net_device * dev) packet_no = inw(ioaddr + PNR_ARR) >> 8; if (packet_no & 0x80) { /* If not, there is a hardware problem! Likely an ejected card. */ - printk(KERN_WARNING "%s: 91c92 hardware Tx buffer allocation" - " failed, status %#2.2x.\n", dev->name, packet_no); + netdev_warn(dev, "hardware Tx buffer allocation failed, status %#2.2x\n", + packet_no); dev_kfree_skb_irq(skb); smc->saved_skb = NULL; netif_start_queue(dev); @@ -1200,8 +1200,7 @@ static void smc_hardware_send_packet(struct net_device * dev) u_char *buf = skb->data; u_int length = skb->len; /* The chip will pad to ethernet min. */ - pr_debug("%s: Trying to xmit packet of length %d.\n", - dev->name, length); + netdev_dbg(dev, "Trying to xmit packet of length %d\n", length); /* send the packet length: +6 for status word, length, and ctl */ outw(0, ioaddr + DATA_1); @@ -1233,9 +1232,8 @@ static void smc_tx_timeout(struct net_device *dev) struct smc_private *smc = netdev_priv(dev); unsigned int ioaddr = dev->base_addr; - printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, " - "Tx_status %2.2x status %4.4x.\n", - dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2)); + netdev_notice(dev, "transmit timed out, Tx_status %2.2x status %4.4x.\n", + inw(ioaddr)&0xff, inw(ioaddr + 2)); dev->stats.tx_errors++; smc_reset(dev); dev->trans_start = jiffies; /* prevent tx timeout */ @@ -1254,14 +1252,14 @@ static netdev_tx_t smc_start_xmit(struct sk_buff *skb, netif_stop_queue(dev); - pr_debug("%s: smc_start_xmit(length = %d) called," - " status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2)); + netdev_dbg(dev, "smc_start_xmit(length = %d) called, status %04x\n", + skb->len, inw(ioaddr + 2)); if (smc->saved_skb) { /* THIS SHOULD NEVER HAPPEN. */ dev->stats.tx_aborted_errors++; - printk(KERN_DEBUG "%s: Internal error -- sent packet while busy.\n", - dev->name); + netdev_printk(KERN_DEBUG, dev, + "Internal error -- sent packet while busy\n"); return NETDEV_TX_BUSY; } smc->saved_skb = skb; @@ -1269,7 +1267,7 @@ static netdev_tx_t smc_start_xmit(struct sk_buff *skb, num_pages = skb->len >> 8; if (num_pages > 7) { - printk(KERN_ERR "%s: Far too big packet error.\n", dev->name); + netdev_err(dev, "Far too big packet error: %d pages\n", num_pages); dev_kfree_skb (skb); smc->saved_skb = NULL; dev->stats.tx_dropped++; @@ -1339,8 +1337,7 @@ static void smc_tx_err(struct net_device * dev) } if (tx_status & TS_SUCCESS) { - printk(KERN_NOTICE "%s: Successful packet caused error " - "interrupt?\n", dev->name); + netdev_notice(dev, "Successful packet caused error interrupt?\n"); } /* re-enable transmit */ SMC_SELECT_BANK(0); @@ -1530,8 +1527,7 @@ static void smc_rx(struct net_device *dev) /* Assertion: we are in Window 2. */ if (inw(ioaddr + FIFO_PORTS) & FP_RXEMPTY) { - printk(KERN_ERR "%s: smc_rx() with nothing on Rx FIFO.\n", - dev->name); + netdev_err(dev, "smc_rx() with nothing on Rx FIFO\n"); return; } @@ -1646,8 +1642,7 @@ static int s9k_config(struct net_device *dev, struct ifmap *map) else if (map->port > 2) return -EINVAL; dev->if_port = map->port; - printk(KERN_INFO "%s: switched to %s port\n", - dev->name, if_names[dev->if_port]); + netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]); smc_reset(dev); } return 0; @@ -1798,7 +1793,7 @@ static void media_check(u_long arg) this, we can limp along even if the interrupt is blocked */ if (smc->watchdog++ && ((i>>8) & i)) { if (!smc->fast_poll) - printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); + netdev_info(dev, "interrupt(s) dropped!\n"); local_irq_save(flags); smc_interrupt(dev->irq, dev); local_irq_restore(flags); @@ -1822,7 +1817,7 @@ static void media_check(u_long arg) SMC_SELECT_BANK(3); link = mdio_read(dev, smc->mii_if.phy_id, 1); if (!link || (link == 0xffff)) { - printk(KERN_INFO "%s: MII is missing!\n", dev->name); + netdev_info(dev, "MII is missing!\n"); smc->mii_if.phy_id = -1; goto reschedule; } @@ -1830,15 +1825,13 @@ static void media_check(u_long arg) link &= 0x0004; if (link != smc->link_status) { u_short p = mdio_read(dev, smc->mii_if.phy_id, 5); - printk(KERN_INFO "%s: %s link beat\n", dev->name, - (link) ? "found" : "lost"); + netdev_info(dev, "%s link beat\n", link ? "found" : "lost"); smc->duplex = (((p & 0x0100) || ((p & 0x1c0) == 0x40)) ? TCR_FDUPLX : 0); if (link) { - printk(KERN_INFO "%s: autonegotiation complete: " - "%sbaseT-%cD selected\n", dev->name, - ((p & 0x0180) ? "100" : "10"), - (smc->duplex ? 'F' : 'H')); + netdev_info(dev, "autonegotiation complete: " + "%dbaseT-%cD selected\n", + (p & 0x0180) ? 100 : 10, smc->duplex ? 'F' : 'H'); } SMC_SELECT_BANK(0); outw(inw(ioaddr + TCR) | smc->duplex, ioaddr + TCR); @@ -1857,25 +1850,23 @@ static void media_check(u_long arg) if (media != smc->media_status) { if ((media & smc->media_status & 1) && ((smc->media_status ^ media) & EPH_LINK_OK)) - printk(KERN_INFO "%s: %s link beat\n", dev->name, - (smc->media_status & EPH_LINK_OK ? "lost" : "found")); + netdev_info(dev, "%s link beat\n", + smc->media_status & EPH_LINK_OK ? "lost" : "found"); else if ((media & smc->media_status & 2) && ((smc->media_status ^ media) & EPH_16COL)) - printk(KERN_INFO "%s: coax cable %s\n", dev->name, - (media & EPH_16COL ? "problem" : "ok")); + netdev_info(dev, "coax cable %s\n", + media & EPH_16COL ? "problem" : "ok"); if (dev->if_port == 0) { if (media & 1) { if (media & EPH_LINK_OK) - printk(KERN_INFO "%s: flipped to 10baseT\n", - dev->name); + netdev_info(dev, "flipped to 10baseT\n"); else smc_set_xcvr(dev, 2); } else { if (media & EPH_16COL) smc_set_xcvr(dev, 1); else - printk(KERN_INFO "%s: flipped to 10base2\n", - dev->name); + netdev_info(dev, "flipped to 10base2\n"); } } smc->media_status = media; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index f5819526b5ee..d858b5e4c4a7 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -63,6 +63,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -210,13 +212,6 @@ enum xirc_cmd { /* Commands */ static const char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; - -#define KDBG_XIRC KERN_DEBUG "xirc2ps_cs: " -#define KERR_XIRC KERN_ERR "xirc2ps_cs: " -#define KWRN_XIRC KERN_WARNING "xirc2ps_cs: " -#define KNOT_XIRC KERN_NOTICE "xirc2ps_cs: " -#define KINF_XIRC KERN_INFO "xirc2ps_cs: " - /* card types */ #define XIR_UNKNOWN 0 /* unknown: not supported */ #define XIR_CE 1 /* (prodid 1) different hardware: not supported */ @@ -350,26 +345,26 @@ PrintRegisters(struct net_device *dev) if (pc_debug > 1) { int i, page; - printk(KDBG_XIRC "Register common: "); + printk(KERN_DEBUG pr_fmt("Register common: ")); for (i = 0; i < 8; i++) - printk(" %2.2x", GetByte(i)); - printk("\n"); + pr_cont(" %2.2x", GetByte(i)); + pr_cont("\n"); for (page = 0; page <= 8; page++) { - printk(KDBG_XIRC "Register page %2x: ", page); + printk(KERN_DEBUG pr_fmt("Register page %2x: "), page); SelectPage(page); for (i = 8; i < 16; i++) - printk(" %2.2x", GetByte(i)); - printk("\n"); + pr_cont(" %2.2x", GetByte(i)); + pr_cont("\n"); } for (page=0x40 ; page <= 0x5f; page++) { if (page == 0x43 || (page >= 0x46 && page <= 0x4f) || (page >= 0x51 && page <=0x5e)) continue; - printk(KDBG_XIRC "Register page %2x: ", page); + printk(KERN_DEBUG pr_fmt("Register page %2x: "), page); SelectPage(page); for (i = 8; i < 16; i++) - printk(" %2.2x", GetByte(i)); - printk("\n"); + pr_cont(" %2.2x", GetByte(i)); + pr_cont("\n"); } } } @@ -608,11 +603,11 @@ set_card_type(struct pcmcia_device *link) local->modem = 0; local->card_type = XIR_UNKNOWN; if (!(prodid & 0x40)) { - printk(KNOT_XIRC "Ooops: Not a creditcard\n"); + pr_notice("Oops: Not a creditcard\n"); return 0; } if (!(mediaid & 0x01)) { - printk(KNOT_XIRC "Not an Ethernet card\n"); + pr_notice("Not an Ethernet card\n"); return 0; } if (mediaid & 0x10) { @@ -643,12 +638,11 @@ set_card_type(struct pcmcia_device *link) } } if (local->card_type == XIR_CE || local->card_type == XIR_CEM) { - printk(KNOT_XIRC "Sorry, this is an old CE card\n"); + pr_notice("Sorry, this is an old CE card\n"); return 0; } if (local->card_type == XIR_UNKNOWN) - printk(KNOT_XIRC "unknown card (mediaid=%02x prodid=%02x)\n", - mediaid, prodid); + pr_notice("unknown card (mediaid=%02x prodid=%02x)\n", mediaid, prodid); return 1; } @@ -748,7 +742,7 @@ xirc2ps_config(struct pcmcia_device * link) /* Is this a valid card */ if (link->has_manf_id == 0) { - printk(KNOT_XIRC "manfid not found in CIS\n"); + pr_notice("manfid not found in CIS\n"); goto failure; } @@ -770,14 +764,14 @@ xirc2ps_config(struct pcmcia_device * link) local->manf_str = "Toshiba"; break; default: - printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n", - (unsigned)link->manf_id); + pr_notice("Unknown Card Manufacturer ID: 0x%04x\n", + (unsigned)link->manf_id); goto failure; } dev_dbg(&link->dev, "found %s card\n", local->manf_str); if (!set_card_type(link)) { - printk(KNOT_XIRC "this card is not supported\n"); + pr_notice("this card is not supported\n"); goto failure; } @@ -803,7 +797,7 @@ xirc2ps_config(struct pcmcia_device * link) err = pcmcia_loop_tuple(link, CISTPL_FUNCE, pcmcia_get_mac_ce, dev); if (err) { - printk(KNOT_XIRC "node-id not found in CIS\n"); + pr_notice("node-id not found in CIS\n"); goto failure; } @@ -838,7 +832,7 @@ xirc2ps_config(struct pcmcia_device * link) * try to configure as Ethernet only. * .... */ } - printk(KNOT_XIRC "no ports available\n"); + pr_notice("no ports available\n"); } else { link->resource[0]->end = 16; for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { @@ -911,24 +905,24 @@ xirc2ps_config(struct pcmcia_device * link) #if 0 { u_char tmp; - printk(KERN_INFO "ECOR:"); + pr_info("ECOR:"); for (i=0; i < 7; i++) { tmp = readb(local->dingo_ccr + i*2); - printk(" %02x", tmp); + pr_cont(" %02x", tmp); } - printk("\n"); - printk(KERN_INFO "DCOR:"); + pr_cont("\n"); + pr_info("DCOR:"); for (i=0; i < 4; i++) { tmp = readb(local->dingo_ccr + 0x20 + i*2); - printk(" %02x", tmp); + pr_cont(" %02x", tmp); } - printk("\n"); - printk(KERN_INFO "SCOR:"); + pr_cont("\n"); + pr_info("SCOR:"); for (i=0; i < 10; i++) { tmp = readb(local->dingo_ccr + 0x40 + i*2); - printk(" %02x", tmp); + pr_cont(" %02x", tmp); } - printk("\n"); + pr_cont("\n"); } #endif @@ -947,7 +941,7 @@ xirc2ps_config(struct pcmcia_device * link) (local->mohawk && if_port==4)) dev->if_port = if_port; else - printk(KNOT_XIRC "invalid if_port requested\n"); + pr_notice("invalid if_port requested\n"); /* we can now register the device with the net subsystem */ dev->irq = link->irq; @@ -959,14 +953,14 @@ xirc2ps_config(struct pcmcia_device * link) SET_NETDEV_DEV(dev, &link->dev); if ((err=register_netdev(dev))) { - printk(KNOT_XIRC "register_netdev() failed\n"); + pr_notice("register_netdev() failed\n"); goto config_error; } /* give some infos about the hardware */ - printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr %pM\n", - dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq, - dev->dev_addr); + netdev_info(dev, "%s: port %#3lx, irq %d, hwaddr %pM\n", + local->manf_str, (u_long)dev->base_addr, (int)dev->irq, + dev->dev_addr); return 0; @@ -1098,8 +1092,7 @@ xirc2ps_interrupt(int irq, void *dev_id) skb = dev_alloc_skb(pktlen+3); /* 1 extra so we can use insw */ if (!skb) { - printk(KNOT_XIRC "low memory, packet dropped (size=%u)\n", - pktlen); + pr_notice("low memory, packet dropped (size=%u)\n", pktlen); dev->stats.rx_dropped++; } else { /* okay get the packet */ skb_reserve(skb, 2); @@ -1268,7 +1261,7 @@ xirc_tx_timeout(struct net_device *dev) { local_info_t *lp = netdev_priv(dev); dev->stats.tx_errors++; - printk(KERN_NOTICE "%s: transmit timed out\n", dev->name); + netdev_notice(dev, "transmit timed out\n"); schedule_work(&lp->tx_timeout_task); } @@ -1435,8 +1428,7 @@ do_config(struct net_device *dev, struct ifmap *map) local->probe_port = 0; dev->if_port = map->port; } - printk(KERN_INFO "%s: switching to %s port\n", - dev->name, if_names[dev->if_port]); + netdev_info(dev, "switching to %s port\n", if_names[dev->if_port]); do_reset(dev,1); /* not the fine way :-) */ } return 0; @@ -1576,7 +1568,7 @@ do_reset(struct net_device *dev, int full) { SelectPage(0); value = GetByte(XIRCREG_ESR); /* read the ESR */ - printk(KERN_DEBUG "%s: ESR is: %#02x\n", dev->name, value); + pr_debug("%s: ESR is: %#02x\n", dev->name, value); } #endif @@ -1626,13 +1618,12 @@ do_reset(struct net_device *dev, int full) if (full && local->mohawk && init_mii(dev)) { if (dev->if_port == 4 || local->dingo || local->new_mii) { - printk(KERN_INFO "%s: MII selected\n", dev->name); + netdev_info(dev, "MII selected\n"); SelectPage(2); PutByte(XIRCREG2_MSR, GetByte(XIRCREG2_MSR) | 0x08); msleep(20); } else { - printk(KERN_INFO "%s: MII detected; using 10mbs\n", - dev->name); + netdev_info(dev, "MII detected; using 10mbs\n"); SelectPage(0x42); if (dev->if_port == 2) /* enable 10Base2 */ PutByte(XIRCREG42_SWC1, 0xC0); @@ -1677,8 +1668,8 @@ do_reset(struct net_device *dev, int full) } if (full) - printk(KERN_INFO "%s: media %s, silicon revision %d\n", - dev->name, if_names[dev->if_port], local->silicon); + netdev_info(dev, "media %s, silicon revision %d\n", + if_names[dev->if_port], local->silicon); /* We should switch back to page 0 to avoid a bug in revision 0 * where regs with offset below 8 can't be read after an access * to the MAC registers */ @@ -1720,8 +1711,7 @@ init_mii(struct net_device *dev) control = mii_rd(ioaddr, 0, 0); if (control & 0x0400) { - printk(KERN_NOTICE "%s can't take PHY out of isolation mode\n", - dev->name); + netdev_notice(dev, "can't take PHY out of isolation mode\n"); local->probe_port = 0; return 0; } @@ -1739,8 +1729,7 @@ init_mii(struct net_device *dev) } if (!(status & 0x0020)) { - printk(KERN_INFO "%s: autonegotiation failed;" - " using 10mbs\n", dev->name); + netdev_info(dev, "autonegotiation failed; using 10mbs\n"); if (!local->new_mii) { control = 0x0000; mii_wr(ioaddr, 0, 0, control, 16); @@ -1750,8 +1739,7 @@ init_mii(struct net_device *dev) } } else { linkpartner = mii_rd(ioaddr, 0, 5); - printk(KERN_INFO "%s: MII link partner: %04x\n", - dev->name, linkpartner); + netdev_info(dev, "MII link partner: %04x\n", linkpartner); if (linkpartner & 0x0080) { dev->if_port = 4; } else -- cgit v1.2.3-59-g8ed1b From b3d18f15092a7db2f229cd7bc69fc40eac0774f4 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 16 Aug 2010 06:26:57 +0000 Subject: net/ax25: Use available error codes Error codes are stored in err, but the return value is always 0. Return err instead. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r@ local idexpression x; constant C; @@ if (...) { ... x = -C ... when != x ( return <+...x...+>; | return NULL; | return; | * return ...; ) } // Signed-off-by: Julia Lawall Acked-by: Ralf Baechle Signed-off-by: David S. Miller --- net/ax25/ax25_route.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index 7805945a5fd6..a1690845dc6e 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -412,7 +412,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) { ax25_uid_assoc *user; ax25_route *ax25_rt; - int err; + int err = 0; if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL) return -EHOSTUNREACH; @@ -453,7 +453,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) put: ax25_put_route(ax25_rt); - return 0; + return err; } struct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src, -- cgit v1.2.3-59-g8ed1b From 49339ccae5ba361b62e829886117dbce4b77194f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 16 Aug 2010 06:28:19 +0000 Subject: net/ax25: Use available error codes Error codes are stored in err, but the return value is always 0. Return err instead. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r@ local idexpression x; constant C; @@ if (...) { ... x = -C ... when != x ( return <+...x...+>; | return NULL; | return; | * return ...; ) } // Signed-off-by: Julia Lawall Acked-by: Ralf Baechle Signed-off-by: David S. Miller --- net/ax25/af_ax25.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index cfdfd7e2a172..26eaebf4aaa9 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1103,7 +1103,7 @@ done: out: release_sock(sk); - return 0; + return err; } /* -- cgit v1.2.3-59-g8ed1b From 900853a4db7098b0e58ddcb732632ac43a7b2148 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 16 Aug 2010 10:23:51 +0000 Subject: drivers/net/qlcnic: Use available error codes The error code is stored in the variable err, but it is the variable ret that is returned instead. So store the error code in ret. Err is then useless. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r@ local idexpression x; constant C; @@ if (...) { ... x = -C ... when != x ( return <+...x...+>; | return NULL; | return; | * return ...; ) } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index abd7cd6db6fd..384cc52a9c3e 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -474,7 +474,7 @@ static int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) { struct qlcnic_pci_info *pci_info; - int i, ret = 0, err; + int i, ret = 0; u8 pfn; pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); @@ -484,14 +484,14 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter) adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) * QLCNIC_MAX_PCI_FUNC, GFP_KERNEL); if (!adapter->npars) { - err = -ENOMEM; + ret = -ENOMEM; goto err_pci_info; } adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) * QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL); if (!adapter->eswitch) { - err = -ENOMEM; + ret = -ENOMEM; goto err_npars; } -- cgit v1.2.3-59-g8ed1b From cb5d991a99104565f7b622b1b97587f4b1effa82 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 17 Aug 2010 06:11:24 +0000 Subject: greth: Use return value of register_netdev Use the return value provided by register_netdev on error instead of hard setting it to -ENOMEM. Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- drivers/net/greth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index f15c64f1cd38..fbeaf70d1727 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -1547,10 +1547,10 @@ static int __devinit greth_of_probe(struct platform_device *ofdev, const struct dev->netdev_ops = &greth_netdev_ops; dev->ethtool_ops = &greth_ethtool_ops; - if (register_netdev(dev)) { + err = register_netdev(dev); + if (err) { if (netif_msg_probe(greth)) dev_err(greth->dev, "netdevice registration failed.\n"); - err = -ENOMEM; goto error5; } -- cgit v1.2.3-59-g8ed1b From 0b29b894b17747f7fa0c5668281c68b8cde7647b Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 17 Aug 2010 06:13:05 +0000 Subject: sunhme: Use return value of register_netdev Use the return value provided by register_netdev on error instead of using a previously set value. Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- drivers/net/sunhme.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index bd0df1c14955..d96431eb698b 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2808,7 +2808,8 @@ static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int i happy_meal_set_initial_advertisement(hp); spin_unlock_irq(&hp->happy_lock); - if (register_netdev(hp->dev)) { + err = register_netdev(hp->dev); + if (err) { printk(KERN_ERR "happymeal: Cannot register net device, " "aborting.\n"); goto err_out_free_coherent; @@ -3130,7 +3131,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, happy_meal_set_initial_advertisement(hp); spin_unlock_irq(&hp->happy_lock); - if (register_netdev(hp->dev)) { + err = register_netdev(hp->dev); + if (err) { printk(KERN_ERR "happymeal(PCI): Cannot register net device, " "aborting.\n"); goto err_out_iounmap; -- cgit v1.2.3-59-g8ed1b From c6c759884b05c7449a19d39c763a7482180e2def Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 17 Aug 2010 07:55:04 +0000 Subject: drivers/net/sungem: Use netdev_, netif_ and pr_ Use the current logging message styles. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/sungem.c | 211 +++++++++++++++++++---------------------------- drivers/net/sungem_phy.c | 3 +- 2 files changed, 85 insertions(+), 129 deletions(-) diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 434f9d735333..4ceb3cf6a9a9 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -31,6 +31,8 @@ * about when we can start taking interrupts or get xmit() called... */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -105,7 +107,6 @@ MODULE_DESCRIPTION("Sun GEM Gbit ethernet driver"); MODULE_LICENSE("GPL"); #define GEM_MODULE_NAME "gem" -#define PFX GEM_MODULE_NAME ": " static DEFINE_PCI_DEVICE_TABLE(gem_pci_tbl) = { { PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_GEM, @@ -262,8 +263,7 @@ static int gem_pcs_interrupt(struct net_device *dev, struct gem *gp, u32 gem_sta gp->dev->name, pcs_istat); if (!(pcs_istat & PCS_ISTAT_LSC)) { - printk(KERN_ERR "%s: PCS irq but no link status change???\n", - dev->name); + netdev_err(dev, "PCS irq but no link status change???\n"); return 0; } @@ -282,20 +282,16 @@ static int gem_pcs_interrupt(struct net_device *dev, struct gem *gp, u32 gem_sta * when autoneg has completed. */ if (pcs_miistat & PCS_MIISTAT_RF) - printk(KERN_INFO "%s: PCS AutoNEG complete, " - "RemoteFault\n", dev->name); + netdev_info(dev, "PCS AutoNEG complete, RemoteFault\n"); else - printk(KERN_INFO "%s: PCS AutoNEG complete.\n", - dev->name); + netdev_info(dev, "PCS AutoNEG complete\n"); } if (pcs_miistat & PCS_MIISTAT_LS) { - printk(KERN_INFO "%s: PCS link is now up.\n", - dev->name); + netdev_info(dev, "PCS link is now up\n"); netif_carrier_on(gp->dev); } else { - printk(KERN_INFO "%s: PCS link is now down.\n", - dev->name); + netdev_info(dev, "PCS link is now down\n"); netif_carrier_off(gp->dev); /* If this happens and the link timer is not running, * reset so we re-negotiate. @@ -323,14 +319,12 @@ static int gem_txmac_interrupt(struct net_device *dev, struct gem *gp, u32 gem_s return 0; if (txmac_stat & MAC_TXSTAT_URUN) { - printk(KERN_ERR "%s: TX MAC xmit underrun.\n", - dev->name); + netdev_err(dev, "TX MAC xmit underrun\n"); gp->net_stats.tx_fifo_errors++; } if (txmac_stat & MAC_TXSTAT_MPE) { - printk(KERN_ERR "%s: TX MAC max packet size error.\n", - dev->name); + netdev_err(dev, "TX MAC max packet size error\n"); gp->net_stats.tx_errors++; } @@ -377,8 +371,7 @@ static int gem_rxmac_reset(struct gem *gp) udelay(10); } if (limit == 5000) { - printk(KERN_ERR "%s: RX MAC will not reset, resetting whole " - "chip.\n", dev->name); + netdev_err(dev, "RX MAC will not reset, resetting whole chip\n"); return 1; } @@ -390,8 +383,7 @@ static int gem_rxmac_reset(struct gem *gp) udelay(10); } if (limit == 5000) { - printk(KERN_ERR "%s: RX MAC will not disable, resetting whole " - "chip.\n", dev->name); + netdev_err(dev, "RX MAC will not disable, resetting whole chip\n"); return 1; } @@ -403,8 +395,7 @@ static int gem_rxmac_reset(struct gem *gp) udelay(10); } if (limit == 5000) { - printk(KERN_ERR "%s: RX DMA will not disable, resetting whole " - "chip.\n", dev->name); + netdev_err(dev, "RX DMA will not disable, resetting whole chip\n"); return 1; } @@ -419,8 +410,7 @@ static int gem_rxmac_reset(struct gem *gp) udelay(10); } if (limit == 5000) { - printk(KERN_ERR "%s: RX reset command will not execute, resetting " - "whole chip.\n", dev->name); + netdev_err(dev, "RX reset command will not execute, resetting whole chip\n"); return 1; } @@ -429,8 +419,7 @@ static int gem_rxmac_reset(struct gem *gp) struct gem_rxd *rxd = &gp->init_block->rxd[i]; if (gp->rx_skbs[i] == NULL) { - printk(KERN_ERR "%s: Parts of RX ring empty, resetting " - "whole chip.\n", dev->name); + netdev_err(dev, "Parts of RX ring empty, resetting whole chip\n"); return 1; } @@ -479,8 +468,7 @@ static int gem_rxmac_interrupt(struct net_device *dev, struct gem *gp, u32 gem_s if (rxmac_stat & MAC_RXSTAT_OFLW) { u32 smac = readl(gp->regs + MAC_SMACHINE); - printk(KERN_ERR "%s: RX MAC fifo overflow smac[%08x].\n", - dev->name, smac); + netdev_err(dev, "RX MAC fifo overflow smac[%08x]\n", smac); gp->net_stats.rx_over_errors++; gp->net_stats.rx_fifo_errors++; @@ -542,19 +530,18 @@ static int gem_pci_interrupt(struct net_device *dev, struct gem *gp, u32 gem_sta if (gp->pdev->vendor == PCI_VENDOR_ID_SUN && gp->pdev->device == PCI_DEVICE_ID_SUN_GEM) { - printk(KERN_ERR "%s: PCI error [%04x] ", - dev->name, pci_estat); + netdev_err(dev, "PCI error [%04x]", pci_estat); if (pci_estat & GREG_PCIESTAT_BADACK) - printk(" "); + pr_cont(" "); if (pci_estat & GREG_PCIESTAT_DTRTO) - printk(" "); + pr_cont(" "); if (pci_estat & GREG_PCIESTAT_OTHER) - printk(""); - printk("\n"); + pr_cont(" "); + pr_cont("\n"); } else { pci_estat |= GREG_PCIESTAT_OTHER; - printk(KERN_ERR "%s: PCI error\n", dev->name); + netdev_err(dev, "PCI error\n"); } if (pci_estat & GREG_PCIESTAT_OTHER) { @@ -565,26 +552,20 @@ static int gem_pci_interrupt(struct net_device *dev, struct gem *gp, u32 gem_sta */ pci_read_config_word(gp->pdev, PCI_STATUS, &pci_cfg_stat); - printk(KERN_ERR "%s: Read PCI cfg space status [%04x]\n", - dev->name, pci_cfg_stat); + netdev_err(dev, "Read PCI cfg space status [%04x]\n", + pci_cfg_stat); if (pci_cfg_stat & PCI_STATUS_PARITY) - printk(KERN_ERR "%s: PCI parity error detected.\n", - dev->name); + netdev_err(dev, "PCI parity error detected\n"); if (pci_cfg_stat & PCI_STATUS_SIG_TARGET_ABORT) - printk(KERN_ERR "%s: PCI target abort.\n", - dev->name); + netdev_err(dev, "PCI target abort\n"); if (pci_cfg_stat & PCI_STATUS_REC_TARGET_ABORT) - printk(KERN_ERR "%s: PCI master acks target abort.\n", - dev->name); + netdev_err(dev, "PCI master acks target abort\n"); if (pci_cfg_stat & PCI_STATUS_REC_MASTER_ABORT) - printk(KERN_ERR "%s: PCI master abort.\n", - dev->name); + netdev_err(dev, "PCI master abort\n"); if (pci_cfg_stat & PCI_STATUS_SIG_SYSTEM_ERROR) - printk(KERN_ERR "%s: PCI system error SERR#.\n", - dev->name); + netdev_err(dev, "PCI system error SERR#\n"); if (pci_cfg_stat & PCI_STATUS_DETECTED_PARITY) - printk(KERN_ERR "%s: PCI parity error.\n", - dev->name); + netdev_err(dev, "PCI parity error\n"); /* Write the error bits back to clear them. */ pci_cfg_stat &= (PCI_STATUS_PARITY | @@ -874,8 +855,7 @@ static int gem_rx(struct gem *gp, int work_to_do) gp->rx_new = entry; if (drops) - printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n", - gp->dev->name); + netdev_info(gp->dev, "Memory squeeze, deferring packet\n"); return work_done; } @@ -981,21 +961,19 @@ static void gem_tx_timeout(struct net_device *dev) { struct gem *gp = netdev_priv(dev); - printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name); + netdev_err(dev, "transmit timed out, resetting\n"); if (!gp->running) { - printk("%s: hrm.. hw not running !\n", dev->name); + netdev_err(dev, "hrm.. hw not running !\n"); return; } - printk(KERN_ERR "%s: TX_STATE[%08x:%08x:%08x]\n", - dev->name, - readl(gp->regs + TXDMA_CFG), - readl(gp->regs + MAC_TXSTAT), - readl(gp->regs + MAC_TXCFG)); - printk(KERN_ERR "%s: RX_STATE[%08x:%08x:%08x]\n", - dev->name, - readl(gp->regs + RXDMA_CFG), - readl(gp->regs + MAC_RXSTAT), - readl(gp->regs + MAC_RXCFG)); + netdev_err(dev, "TX_STATE[%08x:%08x:%08x]\n", + readl(gp->regs + TXDMA_CFG), + readl(gp->regs + MAC_TXSTAT), + readl(gp->regs + MAC_TXCFG)); + netdev_err(dev, "RX_STATE[%08x:%08x:%08x]\n", + readl(gp->regs + RXDMA_CFG), + readl(gp->regs + MAC_RXSTAT), + readl(gp->regs + MAC_RXCFG)); spin_lock_irq(&gp->lock); spin_lock(&gp->tx_lock); @@ -1048,8 +1026,7 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb, if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) { netif_stop_queue(dev); spin_unlock_irqrestore(&gp->tx_lock, flags); - printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); + netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); return NETDEV_TX_BUSY; } @@ -1158,8 +1135,7 @@ static void gem_pcs_reset(struct gem *gp) break; } if (limit < 0) - printk(KERN_WARNING "%s: PCS reset bit would not clear.\n", - gp->dev->name); + netdev_warn(gp->dev, "PCS reset bit would not clear\n"); } static void gem_pcs_reinit_adv(struct gem *gp) @@ -1230,7 +1206,7 @@ static void gem_reset(struct gem *gp) } while (val & (GREG_SWRST_TXRST | GREG_SWRST_RXRST)); if (limit < 0) - printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name); + netdev_err(gp->dev, "SW reset is ghetto\n"); if (gp->phy_type == phy_serialink || gp->phy_type == phy_serdes) gem_pcs_reinit_adv(gp); @@ -1395,9 +1371,8 @@ static int gem_set_link_modes(struct gem *gp) speed = SPEED_1000; } - if (netif_msg_link(gp)) - printk(KERN_INFO "%s: Link is up at %d Mbps, %s-duplex.\n", - gp->dev->name, speed, (full_duplex ? "full" : "half")); + netif_info(gp, link, gp->dev, "Link is up at %d Mbps, %s-duplex\n", + speed, (full_duplex ? "full" : "half")); if (!gp->running) return 0; @@ -1451,15 +1426,13 @@ static int gem_set_link_modes(struct gem *gp) if (netif_msg_link(gp)) { if (pause) { - printk(KERN_INFO "%s: Pause is enabled " - "(rxfifo: %d off: %d on: %d)\n", - gp->dev->name, - gp->rx_fifo_sz, - gp->rx_pause_off, - gp->rx_pause_on); + netdev_info(gp->dev, + "Pause is enabled (rxfifo: %d off: %d on: %d)\n", + gp->rx_fifo_sz, + gp->rx_pause_off, + gp->rx_pause_on); } else { - printk(KERN_INFO "%s: Pause is disabled\n", - gp->dev->name); + netdev_info(gp->dev, "Pause is disabled\n"); } } @@ -1484,9 +1457,8 @@ static int gem_mdio_link_not_up(struct gem *gp) { switch (gp->lstate) { case link_force_ret: - if (netif_msg_link(gp)) - printk(KERN_INFO "%s: Autoneg failed again, keeping" - " forced mode\n", gp->dev->name); + netif_info(gp, link, gp->dev, + "Autoneg failed again, keeping forced mode\n"); gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, gp->last_forced_speed, DUPLEX_HALF); gp->timer_ticks = 5; @@ -1499,9 +1471,7 @@ static int gem_mdio_link_not_up(struct gem *gp) */ if (gp->phy_mii.def->magic_aneg) return 1; - if (netif_msg_link(gp)) - printk(KERN_INFO "%s: switching to forced 100bt\n", - gp->dev->name); + netif_info(gp, link, gp->dev, "switching to forced 100bt\n"); /* Try forced modes. */ gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, SPEED_100, DUPLEX_HALF); @@ -1517,9 +1487,8 @@ static int gem_mdio_link_not_up(struct gem *gp) gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, SPEED_10, DUPLEX_HALF); gp->timer_ticks = 5; - if (netif_msg_link(gp)) - printk(KERN_INFO "%s: switching to forced 10bt\n", - gp->dev->name); + netif_info(gp, link, gp->dev, + "switching to forced 10bt\n"); return 0; } else return 1; @@ -1574,8 +1543,8 @@ static void gem_link_timer(unsigned long data) gp->last_forced_speed = gp->phy_mii.speed; gp->timer_ticks = 5; if (netif_msg_link(gp)) - printk(KERN_INFO "%s: Got link after fallback, retrying" - " autoneg once...\n", gp->dev->name); + netdev_info(gp->dev, + "Got link after fallback, retrying autoneg once...\n"); gp->phy_mii.def->ops->setup_aneg(&gp->phy_mii, gp->phy_mii.advertising); } else if (gp->lstate != link_up) { gp->lstate = link_up; @@ -1589,9 +1558,7 @@ static void gem_link_timer(unsigned long data) */ if (gp->lstate == link_up) { gp->lstate = link_down; - if (netif_msg_link(gp)) - printk(KERN_INFO "%s: Link down\n", - gp->dev->name); + netif_info(gp, link, gp->dev, "Link down\n"); netif_carrier_off(gp->dev); gp->reset_task_pending = 1; schedule_work(&gp->reset_task); @@ -1746,8 +1713,7 @@ static void gem_init_phy(struct gem *gp) if (phy_read(gp, MII_BMCR) != 0xffff) break; if (i == 2) - printk(KERN_WARNING "%s: GMAC PHY not responding !\n", - gp->dev->name); + netdev_warn(gp->dev, "GMAC PHY not responding !\n"); } } @@ -2038,7 +2004,7 @@ static int gem_check_invariants(struct gem *gp) * as this chip has no gigabit PHY. */ if ((mif_cfg & (MIF_CFG_MDI0 | MIF_CFG_MDI1)) == 0) { - printk(KERN_ERR PFX "RIO GEM lacks MII phy, mif_cfg[%08x]\n", + pr_err("RIO GEM lacks MII phy, mif_cfg[%08x]\n", mif_cfg); return -1; } @@ -2078,7 +2044,7 @@ static int gem_check_invariants(struct gem *gp) } if (i == 32) { if (pdev->device != PCI_DEVICE_ID_SUN_GEM) { - printk(KERN_ERR PFX "RIO MII phy will not respond.\n"); + pr_err("RIO MII phy will not respond\n"); return -1; } gp->phy_type = phy_serdes; @@ -2093,7 +2059,7 @@ static int gem_check_invariants(struct gem *gp) if (pdev->device == PCI_DEVICE_ID_SUN_GEM) { if (gp->tx_fifo_sz != (9 * 1024) || gp->rx_fifo_sz != (20 * 1024)) { - printk(KERN_ERR PFX "GEM has bogus fifo sizes tx(%d) rx(%d)\n", + pr_err("GEM has bogus fifo sizes tx(%d) rx(%d)\n", gp->tx_fifo_sz, gp->rx_fifo_sz); return -1; } @@ -2101,7 +2067,7 @@ static int gem_check_invariants(struct gem *gp) } else { if (gp->tx_fifo_sz != (2 * 1024) || gp->rx_fifo_sz != (2 * 1024)) { - printk(KERN_ERR PFX "RIO GEM has bogus fifo sizes tx(%d) rx(%d)\n", + pr_err("RIO GEM has bogus fifo sizes tx(%d) rx(%d)\n", gp->tx_fifo_sz, gp->rx_fifo_sz); return -1; } @@ -2239,7 +2205,7 @@ static int gem_do_start(struct net_device *dev) if (request_irq(gp->pdev->irq, gem_interrupt, IRQF_SHARED, dev->name, (void *)dev)) { - printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name); + netdev_err(dev, "failed to request irq !\n"); spin_lock_irqsave(&gp->lock, flags); spin_lock(&gp->tx_lock); @@ -2378,9 +2344,8 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state) mutex_lock(&gp->pm_mutex); - printk(KERN_INFO "%s: suspending, WakeOnLan %s\n", - dev->name, - (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled"); + netdev_info(dev, "suspending, WakeOnLan %s\n", + (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled"); /* Keep the cell enabled during the entire operation */ spin_lock_irqsave(&gp->lock, flags); @@ -2440,7 +2405,7 @@ static int gem_resume(struct pci_dev *pdev) struct gem *gp = netdev_priv(dev); unsigned long flags; - printk(KERN_INFO "%s: resuming\n", dev->name); + netdev_info(dev, "resuming\n"); mutex_lock(&gp->pm_mutex); @@ -2452,8 +2417,7 @@ static int gem_resume(struct pci_dev *pdev) /* Make sure PCI access and bus master are enabled */ if (pci_enable_device(gp->pdev)) { - printk(KERN_ERR "%s: Can't re-enable chip !\n", - dev->name); + netdev_err(dev, "Can't re-enable chip !\n"); /* Put cell and forget it for now, it will be considered as * still asleep, a new sleep cycle may bring it back */ @@ -2938,7 +2902,7 @@ static int __devinit gem_get_device_address(struct gem *gp) addr = idprom->id_ethaddr; #else printk("\n"); - printk(KERN_ERR "%s: can't get mac-address\n", dev->name); + pr_err("%s: can't get mac-address\n", dev->name); return -1; #endif } @@ -3009,14 +2973,12 @@ static const struct net_device_ops gem_netdev_ops = { static int __devinit gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int gem_version_printed = 0; unsigned long gemreg_base, gemreg_len; struct net_device *dev; struct gem *gp; int err, pci_using_dac; - if (gem_version_printed++ == 0) - printk(KERN_INFO "%s", version); + printk_once(KERN_INFO "%s", version); /* Apple gmac note: during probe, the chip is powered up by * the arch code to allow the code below to work (and to let @@ -3026,8 +2988,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, */ err = pci_enable_device(pdev); if (err) { - printk(KERN_ERR PFX "Cannot enable MMIO operation, " - "aborting.\n"); + pr_err("Cannot enable MMIO operation, aborting\n"); return err; } pci_set_master(pdev); @@ -3048,8 +3009,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, } else { err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { - printk(KERN_ERR PFX "No usable DMA configuration, " - "aborting.\n"); + pr_err("No usable DMA configuration, aborting\n"); goto err_disable_device; } pci_using_dac = 0; @@ -3059,15 +3019,14 @@ static int __devinit gem_init_one(struct pci_dev *pdev, gemreg_len = pci_resource_len(pdev, 0); if ((pci_resource_flags(pdev, 0) & IORESOURCE_IO) != 0) { - printk(KERN_ERR PFX "Cannot find proper PCI device " - "base address, aborting.\n"); + pr_err("Cannot find proper PCI device base address, aborting\n"); err = -ENODEV; goto err_disable_device; } dev = alloc_etherdev(sizeof(*gp)); if (!dev) { - printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); + pr_err("Etherdev alloc failed, aborting\n"); err = -ENOMEM; goto err_disable_device; } @@ -3077,8 +3036,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, err = pci_request_regions(pdev, DRV_NAME); if (err) { - printk(KERN_ERR PFX "Cannot obtain PCI resources, " - "aborting.\n"); + pr_err("Cannot obtain PCI resources, aborting\n"); goto err_out_free_netdev; } @@ -3104,8 +3062,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, gp->regs = ioremap(gemreg_base, gemreg_len); if (!gp->regs) { - printk(KERN_ERR PFX "Cannot map device registers, " - "aborting.\n"); + pr_err("Cannot map device registers, aborting\n"); err = -EIO; goto err_out_free_res; } @@ -3150,8 +3107,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, pci_alloc_consistent(pdev, sizeof(struct gem_init_block), &gp->gblock_dvma); if (!gp->init_block) { - printk(KERN_ERR PFX "Cannot allocate init block, " - "aborting.\n"); + pr_err("Cannot allocate init block, aborting\n"); err = -ENOMEM; goto err_out_iounmap; } @@ -3180,19 +3136,18 @@ static int __devinit gem_init_one(struct pci_dev *pdev, /* Register with kernel */ if (register_netdev(dev)) { - printk(KERN_ERR PFX "Cannot register net device, " - "aborting.\n"); + pr_err("Cannot register net device, aborting\n"); err = -ENOMEM; goto err_out_free_consistent; } - printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n", - dev->name, dev->dev_addr); + netdev_info(dev, "Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n", + dev->dev_addr); if (gp->phy_type == phy_mii_mdio0 || gp->phy_type == phy_mii_mdio1) - printk(KERN_INFO "%s: Found %s PHY\n", dev->name, - gp->phy_mii.def ? gp->phy_mii.def->name : "no"); + netdev_info(dev, "Found %s PHY\n", + gp->phy_mii.def ? gp->phy_mii.def->name : "no"); /* GEM can do it all... */ dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_LLTX; diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c index 78f8cee5fd74..4a4fac630337 100644 --- a/drivers/net/sungem_phy.c +++ b/drivers/net/sungem_phy.c @@ -1175,7 +1175,8 @@ int mii_phy_probe(struct mii_phy *phy, int mii_id) /* Read ID and find matching entry */ id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2)); - printk(KERN_DEBUG "PHY ID: %x, addr: %x\n", id, mii_id); + printk(KERN_DEBUG KBUILD_MODNAME ": " "PHY ID: %x, addr: %x\n", + id, mii_id); for (i=0; (def = mii_phy_table[i]) != NULL; i++) if ((id & def->phy_id_mask) == def->phy_id) break; -- cgit v1.2.3-59-g8ed1b From 4d5870ec103e6569851b9710f0093f072b08439a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 17 Aug 2010 07:55:05 +0000 Subject: drivers/net/sunvnet.c: Use pr_ and netdev_ Use the current message logging styles. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/sunvnet.c | 50 +++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index d281a7b34701..bf3c762de620 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c @@ -3,6 +3,8 @@ * Copyright (C) 2007, 2008 David S. Miller */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -20,7 +22,6 @@ #include "sunvnet.h" #define DRV_MODULE_NAME "sunvnet" -#define PFX DRV_MODULE_NAME ": " #define DRV_MODULE_VERSION "1.0" #define DRV_MODULE_RELDATE "June 25, 2007" @@ -45,9 +46,9 @@ static int vnet_handle_unknown(struct vnet_port *port, void *arg) { struct vio_msg_tag *pkt = arg; - printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n", + pr_err("Received unknown msg [%02x:%02x:%04x:%08x]\n", pkt->type, pkt->stype, pkt->stype_env, pkt->sid); - printk(KERN_ERR PFX "Resetting connection.\n"); + pr_err("Resetting connection\n"); ldc_disconnect(port->vio.lp); @@ -400,8 +401,8 @@ static int vnet_rx(struct vnet_port *port, void *msgbuf) if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA)) return 0; if (unlikely(pkt->seq != dr->rcv_nxt)) { - printk(KERN_ERR PFX "RX out of sequence seq[0x%llx] " - "rcv_nxt[0x%llx]\n", pkt->seq, dr->rcv_nxt); + pr_err("RX out of sequence seq[0x%llx] rcv_nxt[0x%llx]\n", + pkt->seq, dr->rcv_nxt); return 0; } @@ -464,8 +465,7 @@ static int handle_mcast(struct vnet_port *port, void *msgbuf) struct vio_net_mcast_info *pkt = msgbuf; if (pkt->tag.stype != VIO_SUBTYPE_ACK) - printk(KERN_ERR PFX "%s: Got unexpected MCAST reply " - "[%02x:%02x:%04x:%08x]\n", + pr_err("%s: Got unexpected MCAST reply [%02x:%02x:%04x:%08x]\n", port->vp->dev->name, pkt->tag.type, pkt->tag.stype, @@ -520,7 +520,7 @@ static void vnet_event(void *arg, int event) } if (unlikely(event != LDC_EVENT_DATA_READY)) { - printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event); + pr_warning("Unexpected LDC event %d\n", event); spin_unlock_irqrestore(&vio->lock, flags); return; } @@ -662,8 +662,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); /* This is a hard error, log it. */ - printk(KERN_ERR PFX "%s: BUG! Tx Ring full when " - "queue awake!\n", dev->name); + netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); dev->stats.tx_errors++; } spin_unlock_irqrestore(&port->vio.lock, flags); @@ -696,8 +695,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) err = __vnet_tx_trigger(port); if (unlikely(err < 0)) { - printk(KERN_INFO PFX "%s: TX trigger error %d\n", - dev->name, err); + netdev_info(dev, "TX trigger error %d\n", err); d->hdr.state = VIO_DESC_FREE; dev->stats.tx_carrier_errors++; goto out_dropped_unlock; @@ -952,12 +950,12 @@ static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port) err = -ENOMEM; if (!buf) { - printk(KERN_ERR "TX buffer allocation failure\n"); + pr_err("TX buffer allocation failure\n"); goto err_out; } err = -EFAULT; if ((unsigned long)buf & (8UL - 1)) { - printk(KERN_ERR "TX buffer misaligned\n"); + pr_err("TX buffer misaligned\n"); kfree(buf); goto err_out; } @@ -1030,7 +1028,7 @@ static struct vnet * __devinit vnet_new(const u64 *local_mac) dev = alloc_etherdev(sizeof(*vp)); if (!dev) { - printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); + pr_err("Etherdev alloc failed, aborting\n"); return ERR_PTR(-ENOMEM); } @@ -1056,12 +1054,11 @@ static struct vnet * __devinit vnet_new(const u64 *local_mac) err = register_netdev(dev); if (err) { - printk(KERN_ERR PFX "Cannot register net device, " - "aborting.\n"); + pr_err("Cannot register net device, aborting\n"); goto err_out_free_dev; } - printk(KERN_INFO "%s: Sun LDOM vnet %pM\n", dev->name, dev->dev_addr); + netdev_info(dev, "Sun LDOM vnet %pM\n", dev->dev_addr); list_add(&vp->list, &vnet_list); @@ -1133,10 +1130,7 @@ static struct vio_driver_ops vnet_vio_ops = { static void __devinit print_version(void) { - static int version_printed; - - if (version_printed++ == 0) - printk(KERN_INFO "%s", version); + printk_once(KERN_INFO "%s", version); } const char *remote_macaddr_prop = "remote-mac-address"; @@ -1157,7 +1151,7 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev, vp = vnet_find_parent(hp, vdev->mp); if (IS_ERR(vp)) { - printk(KERN_ERR PFX "Cannot find port parent vnet.\n"); + pr_err("Cannot find port parent vnet\n"); err = PTR_ERR(vp); goto err_out_put_mdesc; } @@ -1165,15 +1159,14 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev, rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len); err = -ENODEV; if (!rmac) { - printk(KERN_ERR PFX "Port lacks %s property.\n", - remote_macaddr_prop); + pr_err("Port lacks %s property\n", remote_macaddr_prop); goto err_out_put_mdesc; } port = kzalloc(sizeof(*port), GFP_KERNEL); err = -ENOMEM; if (!port) { - printk(KERN_ERR PFX "Cannot allocate vnet_port.\n"); + pr_err("Cannot allocate vnet_port\n"); goto err_out_put_mdesc; } @@ -1214,9 +1207,8 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev, dev_set_drvdata(&vdev->dev, port); - printk(KERN_INFO "%s: PORT ( remote-mac %pM%s )\n", - vp->dev->name, port->raddr, - switch_port ? " switch-port" : ""); + pr_info("%s: PORT ( remote-mac %pM%s )\n", + vp->dev->name, port->raddr, switch_port ? " switch-port" : ""); vio_port_up(&port->vio); -- cgit v1.2.3-59-g8ed1b From 2244d07bfa2097cb00600da91c715a8aa547917e Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 17 Aug 2010 08:59:14 +0000 Subject: net: simplify flags for tx timestamping This patch removes the abstraction introduced by the union skb_shared_tx in the shared skb data. The access of the different union elements at several places led to some confusion about accessing the shared tx_flags e.g. in skb_orphan_try(). http://marc.info/?l=linux-netdev&m=128084897415886&w=2 Signed-off-by: Oliver Hartkopp Signed-off-by: David S. Miller --- Documentation/networking/timestamping.txt | 22 +++++++++------- drivers/net/bfin_mac.c | 10 +++---- drivers/net/gianfar.c | 15 +++++------ drivers/net/igb/igb.h | 2 +- drivers/net/igb/igb_main.c | 11 ++++---- include/linux/skbuff.h | 44 +++++++++++-------------------- include/net/ip.h | 2 +- include/net/sock.h | 8 ++---- net/can/raw.c | 4 +-- net/core/dev.c | 6 ++--- net/core/skbuff.c | 2 +- net/ipv4/icmp.c | 4 +-- net/ipv4/ip_output.c | 6 ++--- net/ipv4/raw.c | 2 +- net/ipv4/udp.c | 4 +-- net/packet/af_packet.c | 4 +-- net/socket.c | 9 +++---- 17 files changed, 68 insertions(+), 87 deletions(-) diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt index e8c8f4f06c67..98097d8cb910 100644 --- a/Documentation/networking/timestamping.txt +++ b/Documentation/networking/timestamping.txt @@ -172,15 +172,19 @@ struct skb_shared_hwtstamps { }; Time stamps for outgoing packets are to be generated as follows: -- In hard_start_xmit(), check if skb_tx(skb)->hardware is set no-zero. - If yes, then the driver is expected to do hardware time stamping. +- In hard_start_xmit(), check if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) + is set no-zero. If yes, then the driver is expected to do hardware time + stamping. - If this is possible for the skb and requested, then declare - that the driver is doing the time stamping by setting the field - skb_tx(skb)->in_progress non-zero. You might want to keep a pointer - to the associated skb for the next step and not free the skb. A driver - not supporting hardware time stamping doesn't do that. A driver must - never touch sk_buff::tstamp! It is used to store software generated - time stamps by the network subsystem. + that the driver is doing the time stamping by setting the flag + SKBTX_IN_PROGRESS in skb_shinfo(skb)->tx_flags , e.g. with + + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + + You might want to keep a pointer to the associated skb for the next step + and not free the skb. A driver not supporting hardware time stamping doesn't + do that. A driver must never touch sk_buff::tstamp! It is used to store + software generated time stamps by the network subsystem. - As soon as the driver has sent the packet and/or obtained a hardware time stamp for it, it passes the time stamp back by calling skb_hwtstamp_tx() with the original skb, the raw @@ -191,6 +195,6 @@ Time stamps for outgoing packets are to be generated as follows: this would occur at a later time in the processing pipeline than other software time stamping and therefore could lead to unexpected deltas between time stamps. -- If the driver did not call set skb_tx(skb)->in_progress, then +- If the driver did not set the SKBTX_IN_PROGRESS flag (see above), then dev_hard_start_xmit() checks whether software time stamping is wanted as fallback and potentially generates the time stamp. diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 012613fde3f4..7a0e4156fade 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -803,15 +803,14 @@ static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompa static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) { struct bfin_mac_local *lp = netdev_priv(netdev); - union skb_shared_tx *shtx = skb_tx(skb); - if (shtx->hardware) { + if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { int timeout_cnt = MAX_TIMEOUT_CNT; /* When doing time stamping, keep the connection to the socket * a while longer */ - shtx->in_progress = 1; + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; /* * The timestamping is done at the EMAC module's MII/RMII interface @@ -991,7 +990,6 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, struct bfin_mac_local *lp = netdev_priv(dev); u16 *data; u32 data_align = (unsigned long)(skb->data) & 0x3; - union skb_shared_tx *shtx = skb_tx(skb); current_tx_ptr->skb = skb; @@ -1005,7 +1003,7 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, * of this field are the length of the packet payload in bytes and the higher * 4 bits are the timestamping enable field. */ - if (shtx->hardware) + if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) *data |= 0x1000; current_tx_ptr->desc_a.start_addr = (u32)data; @@ -1015,7 +1013,7 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, } else { *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); /* enable timestamping for the sent packet */ - if (shtx->hardware) + if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) *((u16 *)(current_tx_ptr->packet)) |= 0x1000; memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, skb->len); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 3d9f958ebd2c..e6048d6ab0ea 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -2048,7 +2048,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) u32 bufaddr; unsigned long flags; unsigned int nr_frags, nr_txbds, length; - union skb_shared_tx *shtx; /* * TOE=1 frames larger than 2500 bytes may see excess delays @@ -2069,10 +2068,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) txq = netdev_get_tx_queue(dev, rq); base = tx_queue->tx_bd_base; regs = tx_queue->grp->regs; - shtx = skb_tx(skb); /* check if time stamp should be generated */ - if (unlikely(shtx->hardware && priv->hwts_tx_en)) + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && + priv->hwts_tx_en)) do_tstamp = 1; /* make space for additional header when fcb is needed */ @@ -2174,7 +2173,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Setup tx hardware time stamping if requested */ if (unlikely(do_tstamp)) { - shtx->in_progress = 1; + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; if (fcb == NULL) fcb = gfar_add_fcb(skb); fcb->ptp = 1; @@ -2446,7 +2445,6 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) int howmany = 0; u32 lstatus; size_t buflen; - union skb_shared_tx *shtx; rx_queue = priv->rx_queue[tx_queue->qindex]; bdp = tx_queue->dirty_tx; @@ -2461,8 +2459,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) * When time stamping, one additional TxBD must be freed. * Also, we need to dma_unmap_single() the TxPAL. */ - shtx = skb_tx(skb); - if (unlikely(shtx->in_progress)) + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) nr_txbds = frags + 2; else nr_txbds = frags + 1; @@ -2476,7 +2473,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) (lstatus & BD_LENGTH_MASK)) break; - if (unlikely(shtx->in_progress)) { + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { next = next_txbd(bdp, base, tx_ring_size); buflen = next->length + GMAC_FCB_LEN; } else @@ -2485,7 +2482,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr, buflen, DMA_TO_DEVICE); - if (unlikely(shtx->in_progress)) { + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { struct skb_shared_hwtstamps shhwtstamps; u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7); memset(&shhwtstamps, 0, sizeof(shhwtstamps)); diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 6e63d9a7fc75..44e0ff1494e0 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -143,7 +143,7 @@ struct igb_buffer { u16 next_to_watch; unsigned int bytecount; u16 gso_segs; - union skb_shared_tx shtx; + u8 tx_flags; u8 mapped_as_page; }; /* RX */ diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 9b4e5895f5f9..985e37cf17b6 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3954,7 +3954,7 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb, } tx_ring->buffer_info[i].skb = skb; - tx_ring->buffer_info[i].shtx = skb_shinfo(skb)->tx_flags; + tx_ring->buffer_info[i].tx_flags = skb_shinfo(skb)->tx_flags; /* multiply data chunks by size of headers */ tx_ring->buffer_info[i].bytecount = ((gso_segs - 1) * hlen) + skb->len; tx_ring->buffer_info[i].gso_segs = gso_segs; @@ -4088,7 +4088,6 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb, u32 tx_flags = 0; u16 first; u8 hdr_len = 0; - union skb_shared_tx *shtx = skb_tx(skb); /* need: 1 descriptor per page, * + 2 desc gap to keep tail from touching head, @@ -4100,8 +4099,8 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb, return NETDEV_TX_BUSY; } - if (unlikely(shtx->hardware)) { - shtx->in_progress = 1; + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; tx_flags |= IGB_TX_FLAGS_TSTAMP; } @@ -5319,7 +5318,7 @@ static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct igb_buffer *bu u64 regval; /* if skb does not support hw timestamp or TX stamp not valid exit */ - if (likely(!buffer_info->shtx.hardware) || + if (likely(!(buffer_info->tx_flags & SKBTX_HW_TSTAMP)) || !(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID)) return; @@ -5500,7 +5499,7 @@ static void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr, * values must belong to this one here and therefore we don't need to * compare any of the additional attributes stored for it. * - * If nothing went wrong, then it should have a skb_shared_tx that we + * If nothing went wrong, then it should have a shared tx_flags that we * can turn into a skb_shared_hwtstamps. */ if (staterr & E1000_RXDADV_STAT_TSIP) { diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index d8050382b189..f067c95cf18a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -163,26 +163,19 @@ struct skb_shared_hwtstamps { ktime_t syststamp; }; -/** - * struct skb_shared_tx - instructions for time stamping of outgoing packets - * @hardware: generate hardware time stamp - * @software: generate software time stamp - * @in_progress: device driver is going to provide - * hardware time stamp - * @prevent_sk_orphan: make sk reference available on driver level - * @flags: all shared_tx flags - * - * These flags are attached to packets as part of the - * &skb_shared_info. Use skb_tx() to get a pointer. - */ -union skb_shared_tx { - struct { - __u8 hardware:1, - software:1, - in_progress:1, - prevent_sk_orphan:1; - }; - __u8 flags; +/* Definitions for tx_flags in struct skb_shared_info */ +enum { + /* generate hardware time stamp */ + SKBTX_HW_TSTAMP = 1 << 0, + + /* generate software time stamp */ + SKBTX_SW_TSTAMP = 1 << 1, + + /* device driver is going to provide hardware time stamp */ + SKBTX_IN_PROGRESS = 1 << 2, + + /* ensure the originating sk reference is available on driver level */ + SKBTX_DRV_NEEDS_SK_REF = 1 << 3, }; /* This data is invariant across clones and lives at @@ -195,7 +188,7 @@ struct skb_shared_info { unsigned short gso_segs; unsigned short gso_type; __be32 ip6_frag_id; - union skb_shared_tx tx_flags; + __u8 tx_flags; struct sk_buff *frag_list; struct skb_shared_hwtstamps hwtstamps; @@ -587,11 +580,6 @@ static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb) return &skb_shinfo(skb)->hwtstamps; } -static inline union skb_shared_tx *skb_tx(struct sk_buff *skb) -{ - return &skb_shinfo(skb)->tx_flags; -} - /** * skb_queue_empty - check if a queue is empty * @list: queue head @@ -1996,8 +1984,8 @@ extern void skb_tstamp_tx(struct sk_buff *orig_skb, static inline void sw_tx_timestamp(struct sk_buff *skb) { - union skb_shared_tx *shtx = skb_tx(skb); - if (shtx->software && !shtx->in_progress) + if (skb_shinfo(skb)->tx_flags & SKBTX_SW_TSTAMP && + !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) skb_tstamp_tx(skb, NULL); } diff --git a/include/net/ip.h b/include/net/ip.h index 890f9725d681..7691aca133db 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -53,7 +53,7 @@ struct ipcm_cookie { __be32 addr; int oif; struct ip_options *opt; - union skb_shared_tx shtx; + __u8 tx_flags; }; #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) diff --git a/include/net/sock.h b/include/net/sock.h index ac53bfbdfe16..100e43bf95fb 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1669,17 +1669,13 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, /** * sock_tx_timestamp - checks whether the outgoing packet is to be time stamped - * @msg: outgoing packet * @sk: socket sending this packet - * @shtx: filled with instructions for time stamping + * @tx_flags: filled with instructions for time stamping * * Currently only depends on SOCK_TIMESTAMPING* flags. Returns error code if * parameters are invalid. */ -extern int sock_tx_timestamp(struct msghdr *msg, - struct sock *sk, - union skb_shared_tx *shtx); - +extern int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags); /** * sk_eat_skb - Release a skb if it is no longer needed diff --git a/net/can/raw.c b/net/can/raw.c index a10e3338f084..7d77e67e57af 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -647,12 +647,12 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); if (err < 0) goto free_skb; - err = sock_tx_timestamp(msg, sk, skb_tx(skb)); + err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); if (err < 0) goto free_skb; /* to be able to check the received tx sock reference in raw_rcv() */ - skb_tx(skb)->prevent_sk_orphan = 1; + skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF; skb->dev = dev; skb->sk = sk; diff --git a/net/core/dev.c b/net/core/dev.c index 586a11cb4398..c1dc8a95f6ff 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1902,14 +1902,14 @@ static int dev_gso_segment(struct sk_buff *skb) /* * Try to orphan skb early, right before transmission by the device. - * We cannot orphan skb if tx timestamp is requested, since - * drivers need to call skb_tstamp_tx() to send the timestamp. + * We cannot orphan skb if tx timestamp is requested or the sk-reference + * is needed on driver level for other reasons, e.g. see net/can/raw.c */ static inline void skb_orphan_try(struct sk_buff *skb) { struct sock *sk = skb->sk; - if (sk && !skb_tx(skb)->flags) { + if (sk && !skb_shinfo(skb)->tx_flags) { /* skb_tx_hash() wont be able to get sk. * We copy sk_hash into skb->rxhash */ diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 3a2513f0d0c3..99ef721f773d 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3016,7 +3016,7 @@ void skb_tstamp_tx(struct sk_buff *orig_skb, } else { /* * no hardware time stamps available, - * so keep the skb_shared_tx and only + * so keep the shared tx_flags and only * store software time stamp */ skb->tstamp = ktime_get_real(); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index a0d847c7cba5..96bc7f9475a3 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -379,7 +379,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) inet->tos = ip_hdr(skb)->tos; daddr = ipc.addr = rt->rt_src; ipc.opt = NULL; - ipc.shtx.flags = 0; + ipc.tx_flags = 0; if (icmp_param->replyopts.optlen) { ipc.opt = &icmp_param->replyopts; if (ipc.opt->srr) @@ -538,7 +538,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) inet_sk(sk)->tos = tos; ipc.addr = iph->saddr; ipc.opt = &icmp_param.replyopts; - ipc.shtx.flags = 0; + ipc.tx_flags = 0; { struct flowi fl = { diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 04b69896df5f..e807492f1777 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -953,7 +953,7 @@ alloc_new_skb: else /* only the initial fragment is time stamped */ - ipc->shtx.flags = 0; + ipc->tx_flags = 0; } if (skb == NULL) goto error; @@ -964,7 +964,7 @@ alloc_new_skb: skb->ip_summed = csummode; skb->csum = 0; skb_reserve(skb, hh_len); - *skb_tx(skb) = ipc->shtx; + skb_shinfo(skb)->tx_flags = ipc->tx_flags; /* * Find where to start putting bytes. @@ -1384,7 +1384,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar daddr = ipc.addr = rt->rt_src; ipc.opt = NULL; - ipc.shtx.flags = 0; + ipc.tx_flags = 0; if (replyopts.opt.optlen) { ipc.opt = &replyopts.opt; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 009a7b2aa1ef..1f85ef289895 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -505,7 +505,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ipc.addr = inet->inet_saddr; ipc.opt = NULL; - ipc.shtx.flags = 0; + ipc.tx_flags = 0; ipc.oif = sk->sk_bound_dev_if; if (msg->msg_controllen) { diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 32e0bef60d0a..86e757e162ee 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -797,7 +797,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, return -EOPNOTSUPP; ipc.opt = NULL; - ipc.shtx.flags = 0; + ipc.tx_flags = 0; if (up->pending) { /* @@ -845,7 +845,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ipc.addr = inet->inet_saddr; ipc.oif = sk->sk_bound_dev_if; - err = sock_tx_timestamp(msg, sk, &ipc.shtx); + err = sock_tx_timestamp(sk, &ipc.tx_flags); if (err) return err; if (msg->msg_controllen) { diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 9a17f28b1253..3616f27b9d46 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -488,7 +488,7 @@ retry: skb->dev = dev; skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; - err = sock_tx_timestamp(msg, sk, skb_tx(skb)); + err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); if (err < 0) goto out_unlock; @@ -1209,7 +1209,7 @@ static int packet_snd(struct socket *sock, err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len); if (err) goto out_free; - err = sock_tx_timestamp(msg, sk, skb_tx(skb)); + err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); if (err < 0) goto out_free; diff --git a/net/socket.c b/net/socket.c index 2270b941bcc7..7848d12f5e4d 100644 --- a/net/socket.c +++ b/net/socket.c @@ -535,14 +535,13 @@ void sock_release(struct socket *sock) } EXPORT_SYMBOL(sock_release); -int sock_tx_timestamp(struct msghdr *msg, struct sock *sk, - union skb_shared_tx *shtx) +int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags) { - shtx->flags = 0; + *tx_flags = 0; if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) - shtx->hardware = 1; + *tx_flags |= SKBTX_HW_TSTAMP; if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) - shtx->software = 1; + *tx_flags |= SKBTX_SW_TSTAMP; return 0; } EXPORT_SYMBOL(sock_tx_timestamp); -- cgit v1.2.3-59-g8ed1b From 25aec76a3bd962f0aae1d7980ab1efa56cb24b43 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 18 Aug 2010 20:15:04 +0000 Subject: ether1: Use net_device_stats from struct net_device struct net_device has its own struct net_device_stats member, so use this one instead of a private copy in the ether1_priv struct. As the new ndo_get_stats function would just return dev->stats we can omit it. This patch also removes an incorrect memset of the stats on open. Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- drivers/net/arm/ether1.c | 34 ++++++++++++---------------------- drivers/net/arm/ether1.h | 1 - 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c index b17ab5153f51..b00781c02d5d 100644 --- a/drivers/net/arm/ether1.c +++ b/drivers/net/arm/ether1.c @@ -68,7 +68,6 @@ static int ether1_open(struct net_device *dev); static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev); static irqreturn_t ether1_interrupt(int irq, void *dev_id); static int ether1_close(struct net_device *dev); -static struct net_device_stats *ether1_getstats(struct net_device *dev); static void ether1_setmulticastlist(struct net_device *dev); static void ether1_timeout(struct net_device *dev); @@ -649,8 +648,6 @@ ether1_open (struct net_device *dev) if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev)) return -EAGAIN; - memset (&priv(dev)->stats, 0, sizeof (struct net_device_stats)); - if (ether1_init_for_open (dev)) { free_irq (dev->irq, dev); return -EAGAIN; @@ -673,7 +670,7 @@ ether1_timeout(struct net_device *dev) if (ether1_init_for_open (dev)) printk (KERN_ERR "%s: unable to restart interface\n", dev->name); - priv(dev)->stats.tx_errors++; + dev->stats.tx_errors++; netif_wake_queue(dev); } @@ -802,21 +799,21 @@ again: while (nop.nop_status & STAT_COMPLETE) { if (nop.nop_status & STAT_OK) { - priv(dev)->stats.tx_packets ++; - priv(dev)->stats.collisions += (nop.nop_status & STAT_COLLISIONS); + dev->stats.tx_packets++; + dev->stats.collisions += (nop.nop_status & STAT_COLLISIONS); } else { - priv(dev)->stats.tx_errors ++; + dev->stats.tx_errors++; if (nop.nop_status & STAT_COLLAFTERTX) - priv(dev)->stats.collisions ++; + dev->stats.collisions++; if (nop.nop_status & STAT_NOCARRIER) - priv(dev)->stats.tx_carrier_errors ++; + dev->stats.tx_carrier_errors++; if (nop.nop_status & STAT_TXLOSTCTS) printk (KERN_WARNING "%s: cts lost\n", dev->name); if (nop.nop_status & STAT_TXSLOWDMA) - priv(dev)->stats.tx_fifo_errors ++; + dev->stats.tx_fifo_errors++; if (nop.nop_status & STAT_COLLEXCESSIVE) - priv(dev)->stats.collisions += 16; + dev->stats.collisions += 16; } if (nop.nop_link == caddr) { @@ -879,13 +876,13 @@ ether1_recv_done (struct net_device *dev) skb->protocol = eth_type_trans (skb, dev); netif_rx (skb); - priv(dev)->stats.rx_packets ++; + dev->stats.rx_packets++; } else - priv(dev)->stats.rx_dropped ++; + dev->stats.rx_dropped++; } else { printk(KERN_WARNING "%s: %s\n", dev->name, (rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid"); - priv(dev)->stats.rx_dropped ++; + dev->stats.rx_dropped++; } nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS); @@ -939,7 +936,7 @@ ether1_interrupt (int irq, void *dev_id) printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name); ether1_writew(dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS); writeb(CTRL_CA, REG_CONTROL); - priv(dev)->stats.rx_dropped ++; /* we suspended due to lack of buffer space */ + dev->stats.rx_dropped++; /* we suspended due to lack of buffer space */ } else printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name, ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS)); @@ -962,12 +959,6 @@ ether1_close (struct net_device *dev) return 0; } -static struct net_device_stats * -ether1_getstats (struct net_device *dev) -{ - return &priv(dev)->stats; -} - /* * Set or clear the multicast filter for this adaptor. * num_addrs == -1 Promiscuous mode, receive all packets. @@ -994,7 +985,6 @@ static const struct net_device_ops ether1_netdev_ops = { .ndo_open = ether1_open, .ndo_stop = ether1_close, .ndo_start_xmit = ether1_sendpacket, - .ndo_get_stats = ether1_getstats, .ndo_set_multicast_list = ether1_setmulticastlist, .ndo_tx_timeout = ether1_timeout, .ndo_validate_addr = eth_validate_addr, diff --git a/drivers/net/arm/ether1.h b/drivers/net/arm/ether1.h index c8a4b2389d85..3a5830ab3dc7 100644 --- a/drivers/net/arm/ether1.h +++ b/drivers/net/arm/ether1.h @@ -38,7 +38,6 @@ struct ether1_priv { void __iomem *base; - struct net_device_stats stats; unsigned int tx_link; unsigned int tx_head; volatile unsigned int tx_tail; -- cgit v1.2.3-59-g8ed1b From bb2537f1e76b3fb18c3fc1dff1df98ebc10af633 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 18 Aug 2010 20:15:31 +0000 Subject: ether3: Use net_device_stats from struct net_device struct net_device has its own struct net_device_stats member, so use this one instead of a private copy in the ether1_priv struct. As the new ndo_get_stats function would just return dev->stats we can omit it. This patch also removes an incorrect memset of the stats on open. Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- drivers/net/arm/ether3.c | 33 ++++++++++----------------------- drivers/net/arm/ether3.h | 1 - 2 files changed, 10 insertions(+), 24 deletions(-) diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index 1361b7367c28..44a8746f4014 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c @@ -81,7 +81,6 @@ static int ether3_open (struct net_device *dev); static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev); static irqreturn_t ether3_interrupt (int irq, void *dev_id); static int ether3_close (struct net_device *dev); -static struct net_device_stats *ether3_getstats (struct net_device *dev); static void ether3_setmulticastlist (struct net_device *dev); static void ether3_timeout(struct net_device *dev); @@ -323,8 +322,6 @@ ether3_init_for_open(struct net_device *dev) { int i; - memset(&priv(dev)->stats, 0, sizeof(struct net_device_stats)); - /* Reset the chip */ ether3_outw(CFG2_RESET, REG_CONFIG2); udelay(4); @@ -441,15 +438,6 @@ ether3_close(struct net_device *dev) return 0; } -/* - * Get the current statistics. This may be called with the card open or - * closed. - */ -static struct net_device_stats *ether3_getstats(struct net_device *dev) -{ - return &priv(dev)->stats; -} - /* * Set or clear promiscuous/multicast mode filter for this adaptor. * @@ -490,7 +478,7 @@ static void ether3_timeout(struct net_device *dev) local_irq_restore(flags); priv(dev)->regs.config2 |= CFG2_CTRLO; - priv(dev)->stats.tx_errors += 1; + dev->stats.tx_errors += 1; ether3_outw(priv(dev)->regs.config2, REG_CONFIG2); priv(dev)->tx_head = priv(dev)->tx_tail = 0; @@ -509,7 +497,7 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev) if (priv(dev)->broken) { dev_kfree_skb(skb); - priv(dev)->stats.tx_dropped ++; + dev->stats.tx_dropped++; netif_start_queue(dev); return NETDEV_TX_OK; } @@ -673,7 +661,7 @@ if (next_ptr < RX_START || next_ptr >= RX_END) { } else goto dropping; } else { - struct net_device_stats *stats = &priv(dev)->stats; + struct net_device_stats *stats = &dev->stats; ether3_outw(next_ptr >> 8, REG_RECVEND); if (status & RXSTAT_OVERSIZE) stats->rx_over_errors ++; if (status & RXSTAT_CRCERROR) stats->rx_crc_errors ++; @@ -685,14 +673,14 @@ if (next_ptr < RX_START || next_ptr >= RX_END) { while (-- maxcnt); done: - priv(dev)->stats.rx_packets += received; + dev->stats.rx_packets += received; priv(dev)->rx_head = next_ptr; /* * If rx went off line, then that means that the buffer may be full. We * have dropped at least one packet. */ if (!(ether3_inw(REG_STATUS) & STAT_RXON)) { - priv(dev)->stats.rx_dropped ++; + dev->stats.rx_dropped++; ether3_outw(next_ptr, REG_RECVPTR); ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND); } @@ -710,7 +698,7 @@ dropping:{ last_warned = jiffies; printk("%s: memory squeeze, dropping packet.\n", dev->name); } - priv(dev)->stats.rx_dropped ++; + dev->stats.rx_dropped++; goto done; } } @@ -743,13 +731,13 @@ static void ether3_tx(struct net_device *dev) * Update errors */ if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS))) - priv(dev)->stats.tx_packets++; + dev->stats.tx_packets++; else { - priv(dev)->stats.tx_errors ++; + dev->stats.tx_errors++; if (status & TXSTAT_16COLLISIONS) - priv(dev)->stats.collisions += 16; + dev->stats.collisions += 16; if (status & TXSTAT_BABBLED) - priv(dev)->stats.tx_fifo_errors ++; + dev->stats.tx_fifo_errors++; } tx_tail = (tx_tail + 1) & 15; @@ -773,7 +761,6 @@ static const struct net_device_ops ether3_netdev_ops = { .ndo_open = ether3_open, .ndo_stop = ether3_close, .ndo_start_xmit = ether3_sendpacket, - .ndo_get_stats = ether3_getstats, .ndo_set_multicast_list = ether3_setmulticastlist, .ndo_tx_timeout = ether3_timeout, .ndo_validate_addr = eth_validate_addr, diff --git a/drivers/net/arm/ether3.h b/drivers/net/arm/ether3.h index 1921a3a07da7..2db63b08bdf3 100644 --- a/drivers/net/arm/ether3.h +++ b/drivers/net/arm/ether3.h @@ -164,7 +164,6 @@ struct dev_priv { unsigned char tx_head; /* buffer nr to insert next packet */ unsigned char tx_tail; /* buffer nr of transmitting packet */ unsigned int rx_head; /* address to fetch next packet from */ - struct net_device_stats stats; struct timer_list timer; int broken; /* 0 = ok, 1 = something went wrong */ }; -- cgit v1.2.3-59-g8ed1b From b92840900fb575004cac694e56fd0a43f54dc344 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 18 Aug 2010 10:44:34 +0000 Subject: atm: remove a net_device_stats clear No need to clear device stats in lec_open() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/atm/lec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/atm/lec.c b/net/atm/lec.c index d98bde1a0ac8..181d70c73d70 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -220,7 +220,6 @@ static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc) static int lec_open(struct net_device *dev) { netif_start_queue(dev); - memset(&dev->stats, 0, sizeof(struct net_device_stats)); return 0; } -- cgit v1.2.3-59-g8ed1b From d7d28bc29f4ea7c2d23ed002a9973c64a92bcdb8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 18 Aug 2010 14:16:54 +0200 Subject: ALSA: pcm midlevel code - add time check for double interrupt acknowledge The current code in pcm_lib.c do all checks using only the position in the ring buffer. Unfortunately, where the interrupts gets delayed or merged into one, we need another timing source to check when the buffer size boundary overlaps to avoid the wrong updating of the ring buffer pointers. This code uses jiffies to check the right time window without any performance impact. Signed-off-by: Jaroslav Kysela --- include/sound/pcm.h | 1 + sound/core/pcm_lib.c | 14 +++++++++----- sound/core/pcm_native.c | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index dd76cdede64d..54c4ccf6fec2 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -274,6 +274,7 @@ struct snd_pcm_runtime { snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */ unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */ + unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */ snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */ /* -- HW params -- */ diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index e9d98be190c5..d6ecca27bb68 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -329,11 +329,15 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, /* delta = "expected next hw_ptr" for in_interrupt != 0 */ delta = runtime->hw_ptr_interrupt + runtime->period_size; if (delta > new_hw_ptr) { - hw_base += runtime->buffer_size; - if (hw_base >= runtime->boundary) - hw_base = 0; - new_hw_ptr = hw_base + pos; - goto __delta; + /* check for double acknowledged interrupts */ + hdelta = jiffies - runtime->hw_ptr_jiffies; + if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { + hw_base += runtime->buffer_size; + if (hw_base >= runtime->boundary) + hw_base = 0; + new_hw_ptr = hw_base + pos; + goto __delta; + } } } /* new_hw_ptr might be lower than old_hw_ptr in case when */ diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 303ac04ff6e4..2d2e1b65ee9a 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -867,6 +867,8 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state) struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_trigger_tstamp(substream); runtime->hw_ptr_jiffies = jiffies; + runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / + runtime->rate; runtime->status->state = state; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0) -- cgit v1.2.3-59-g8ed1b From dd57f970f91e2371040db709b3731ac34e43ccdb Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 18 Aug 2010 03:42:54 +0000 Subject: vxge: Implement 64bit stats vxge_get_stats() is racy, since it clears a block of memory (net_stats) possibly still used by other cpus. We can update this driver to full 64bit stats, since ndo_get_stats64() provides a private block to store results, and driver maintains 64bit counters already. We also remove net_stats field from struct vxge_sw_stats Signed-off-by: Eric Dumazet Acked-by: Jon Mason Signed-off-by: David S. Miller --- drivers/net/vxge/vxge-main.c | 22 +++++++--------------- drivers/net/vxge/vxge-main.h | 1 - 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index f5334b287fdb..01cdec712b64 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -2914,26 +2914,18 @@ static int vxge_change_mtu(struct net_device *dev, int new_mtu) } /** - * vxge_get_stats + * vxge_get_stats64 * @dev: pointer to the device structure + * @stats: pointer to struct rtnl_link_stats64 * - * Updates the device statistics structure. This function updates the device - * statistics structure in the net_device structure and returns a pointer - * to the same. */ -static struct net_device_stats * -vxge_get_stats(struct net_device *dev) +static struct rtnl_link_stats64 * +vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats) { - struct vxgedev *vdev; - struct net_device_stats *net_stats; + struct vxgedev *vdev = netdev_priv(dev); int k; - vdev = netdev_priv(dev); - - net_stats = &vdev->stats.net_stats; - - memset(net_stats, 0, sizeof(struct net_device_stats)); - + /* net_stats already zeroed by caller */ for (k = 0; k < vdev->no_of_vpath; k++) { net_stats->rx_packets += vdev->vpaths[k].ring.stats.rx_frms; net_stats->rx_bytes += vdev->vpaths[k].ring.stats.rx_bytes; @@ -3102,7 +3094,7 @@ vxge_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) static const struct net_device_ops vxge_netdev_ops = { .ndo_open = vxge_open, .ndo_stop = vxge_close, - .ndo_get_stats = vxge_get_stats, + .ndo_get_stats64 = vxge_get_stats64, .ndo_start_xmit = vxge_xmit, .ndo_validate_addr = eth_validate_addr, .ndo_set_multicast_list = vxge_set_multicast, diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h index 2e3b064b8e4b..d4be07eaacd7 100644 --- a/drivers/net/vxge/vxge-main.h +++ b/drivers/net/vxge/vxge-main.h @@ -172,7 +172,6 @@ struct vxge_msix_entry { struct vxge_sw_stats { /* Network Stats (interface stats) */ - struct net_device_stats net_stats; /* Tx */ u64 tx_frms; -- cgit v1.2.3-59-g8ed1b From 6f0bee16d0840c272229f2038a23a9a02dfc803d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 18 Aug 2010 03:13:08 +0000 Subject: slip: fix get_stats() method Use integrated net_device_stats instead of a static one, and make sure no transient values are feeded. ndo_get_stats() can be called by concurrent cpus. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/slip.c | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/net/slip.c b/drivers/net/slip.c index fa434fb8fb7c..d5a36f5417cc 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -561,36 +561,36 @@ static int sl_change_mtu(struct net_device *dev, int new_mtu) static struct net_device_stats * sl_get_stats(struct net_device *dev) { - static struct net_device_stats stats; + struct net_device_stats *stats = &dev->stats; struct slip *sl = netdev_priv(dev); + unsigned long c_rx_dropped = 0; #ifdef SL_INCLUDE_CSLIP - struct slcompress *comp; -#endif + unsigned long c_rx_fifo_errors = 0; + unsigned long c_tx_fifo_errors = 0; + unsigned long c_collisions = 0; + struct slcompress *comp = sl->slcomp; - memset(&stats, 0, sizeof(struct net_device_stats)); - - stats.rx_packets = sl->rx_packets; - stats.tx_packets = sl->tx_packets; - stats.rx_bytes = sl->rx_bytes; - stats.tx_bytes = sl->tx_bytes; - stats.rx_dropped = sl->rx_dropped; - stats.tx_dropped = sl->tx_dropped; - stats.tx_errors = sl->tx_errors; - stats.rx_errors = sl->rx_errors; - stats.rx_over_errors = sl->rx_over_errors; -#ifdef SL_INCLUDE_CSLIP - stats.rx_fifo_errors = sl->rx_compressed; - stats.tx_fifo_errors = sl->tx_compressed; - stats.collisions = sl->tx_misses; - comp = sl->slcomp; if (comp) { - stats.rx_fifo_errors += comp->sls_i_compressed; - stats.rx_dropped += comp->sls_i_tossed; - stats.tx_fifo_errors += comp->sls_o_compressed; - stats.collisions += comp->sls_o_misses; + c_rx_fifo_errors = comp->sls_i_compressed; + c_rx_dropped = comp->sls_i_tossed; + c_tx_fifo_errors = comp->sls_o_compressed; + c_collisions = comp->sls_o_misses; } -#endif /* CONFIG_INET */ - return (&stats); + stats->rx_fifo_errors = sl->rx_compressed + c_rx_fifo_errors; + stats->tx_fifo_errors = sl->tx_compressed + c_tx_fifo_errors; + stats->collisions = sl->tx_misses + c_collisions; +#endif + + stats->rx_packets = sl->rx_packets; + stats->tx_packets = sl->tx_packets; + stats->rx_bytes = sl->rx_bytes; + stats->tx_bytes = sl->tx_bytes; + stats->rx_dropped = sl->rx_dropped + c_rx_dropped; + stats->tx_dropped = sl->tx_dropped; + stats->tx_errors = sl->tx_errors; + stats->rx_errors = sl->rx_errors; + stats->rx_over_errors = sl->rx_over_errors; + return stats; } /* Netdevice register callback */ -- cgit v1.2.3-59-g8ed1b From 357e8b5f723ba9e1d0a0f8ffb1361d607e43e19a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 18 Aug 2010 01:22:49 +0000 Subject: xilinx_emaclite: netpoll support Netconsole requires poll support. Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/xilinx_emaclite.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index ecbbb688eba0..71122ee4e830 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c @@ -1269,6 +1269,16 @@ static int __devexit xemaclite_of_remove(struct platform_device *of_dev) return 0; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void +xemaclite_poll_controller(struct net_device *ndev) +{ + disable_irq(ndev->irq); + xemaclite_interrupt(ndev->irq, ndev); + enable_irq(ndev->irq); +} +#endif + static struct net_device_ops xemaclite_netdev_ops = { .ndo_open = xemaclite_open, .ndo_stop = xemaclite_close, @@ -1276,6 +1286,9 @@ static struct net_device_ops xemaclite_netdev_ops = { .ndo_set_mac_address = xemaclite_set_mac_address, .ndo_tx_timeout = xemaclite_tx_timeout, .ndo_get_stats = xemaclite_get_stats, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = xemaclite_poll_controller, +#endif }; /* Match table for OF platform binding */ -- cgit v1.2.3-59-g8ed1b From 08ff45ca60e4bc1cc27a71a9fe06886e870aa7d8 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 19 Aug 2010 12:02:21 +0800 Subject: Use kzalloc in idedisk_prep_fn. Signed-off-by: Tao Ma Acked-by: Jeff Garzik Signed-off-by: Jiri Kosina --- drivers/ide/ide-disk.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 7433e07de30e..471bb0d42eb0 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -435,12 +435,11 @@ static int idedisk_prep_fn(struct request_queue *q, struct request *rq) if (!(rq->cmd_flags & REQ_FLUSH)) return BLKPREP_OK; - cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); + cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); /* FIXME: map struct ide_taskfile on rq->cmd[] */ BUG_ON(cmd == NULL); - memset(cmd, 0, sizeof(*cmd)); if (ata_id_flush_ext_enabled(drive->id) && (drive->capacity64 >= (1UL << 28))) cmd->tf.command = ATA_CMD_FLUSH_EXT; -- cgit v1.2.3-59-g8ed1b From 140176159597ea1f23dcccb47b5c38fdf7c7faa8 Mon Sep 17 00:00:00 2001 From: Randolph Chung Date: Thu, 19 Aug 2010 12:06:17 +0100 Subject: ASoC: Configure symmetric rates for tlv320aic3x The tlv320aic3x codec driver only supports symmetric rates for capture/ playback. Set the flag in the DAI accordingly. Signed-off-by: Randolph Chung Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 43fd9c171742..867bf1fb1825 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1117,6 +1117,7 @@ static struct snd_soc_dai_driver aic3x_dai = { .rates = AIC3X_RATES, .formats = AIC3X_FORMATS,}, .ops = &aic3x_dai_ops, + .symmetric_rates = 1, }; static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state) -- cgit v1.2.3-59-g8ed1b From ec46475f3e3163dd80bfee086fa71b36455ecc0b Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Thu, 19 Aug 2010 15:09:36 +0300 Subject: power_supply: Add isp1704 charger detection driver NXP ISP1704 is Battery Charging Specification 1.0 compliant USB transceiver. This adds a power supply driver for ISP1704 and ISP1707 USB transceivers. Signed-off-by: Heikki Krogerus Signed-off-by: Anton Vorontsov --- drivers/power/Kconfig | 7 + drivers/power/Makefile | 1 + drivers/power/isp1704_charger.c | 369 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 377 insertions(+) create mode 100644 drivers/power/isp1704_charger.c diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 07343568a12e..c2a1b8b713f6 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -166,4 +166,11 @@ config BATTERY_INTEL_MID Say Y here to enable the battery driver on Intel MID platforms. +config CHARGER_ISP1704 + tristate "ISP1704 USB Charger Detection" + depends on USB_OTG_UTILS + help + Say Y to enable support for USB Charger Detection with + ISP1707/ISP1704 USB transceivers. + endif # POWER_SUPPLY diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 10143aaf4ee3..c73d381037a0 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -37,3 +37,4 @@ obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o +obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c new file mode 100644 index 000000000000..72512185f3e2 --- /dev/null +++ b/drivers/power/isp1704_charger.c @@ -0,0 +1,369 @@ +/* + * ISP1704 USB Charger Detection driver + * + * Copyright (C) 2010 Nokia Corporation + * + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Vendor specific Power Control register */ +#define ISP1704_PWR_CTRL 0x3d +#define ISP1704_PWR_CTRL_SWCTRL (1 << 0) +#define ISP1704_PWR_CTRL_DET_COMP (1 << 1) +#define ISP1704_PWR_CTRL_BVALID_RISE (1 << 2) +#define ISP1704_PWR_CTRL_BVALID_FALL (1 << 3) +#define ISP1704_PWR_CTRL_DP_WKPU_EN (1 << 4) +#define ISP1704_PWR_CTRL_VDAT_DET (1 << 5) +#define ISP1704_PWR_CTRL_DPVSRC_EN (1 << 6) +#define ISP1704_PWR_CTRL_HWDETECT (1 << 7) + +#define NXP_VENDOR_ID 0x04cc + +static u16 isp170x_id[] = { + 0x1704, + 0x1707, +}; + +struct isp1704_charger { + struct device *dev; + struct power_supply psy; + struct otg_transceiver *otg; + struct notifier_block nb; + struct work_struct work; + + char model[7]; + unsigned present:1; +}; + +/* + * ISP1704 detects PS/2 adapters as charger. To make sure the detected charger + * is actually a dedicated charger, the following steps need to be taken. + */ +static inline int isp1704_charger_verify(struct isp1704_charger *isp) +{ + int ret = 0; + u8 r; + + /* Reset the transceiver */ + r = otg_io_read(isp->otg, ULPI_FUNC_CTRL); + r |= ULPI_FUNC_CTRL_RESET; + otg_io_write(isp->otg, ULPI_FUNC_CTRL, r); + usleep_range(1000, 2000); + + /* Set normal mode */ + r &= ~(ULPI_FUNC_CTRL_RESET | ULPI_FUNC_CTRL_OPMODE_MASK); + otg_io_write(isp->otg, ULPI_FUNC_CTRL, r); + + /* Clear the DP and DM pull-down bits */ + r = ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN; + otg_io_write(isp->otg, ULPI_CLR(ULPI_OTG_CTRL), r); + + /* Enable strong pull-up on DP (1.5K) and reset */ + r = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET; + otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL), r); + usleep_range(1000, 2000); + + /* Read the line state */ + if (!otg_io_read(isp->otg, ULPI_DEBUG)) { + /* Disable strong pull-up on DP (1.5K) */ + otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL), + ULPI_FUNC_CTRL_TERMSELECT); + return 1; + } + + /* Is it a charger or PS/2 connection */ + + /* Enable weak pull-up resistor on DP */ + otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL), + ISP1704_PWR_CTRL_DP_WKPU_EN); + + /* Disable strong pull-up on DP (1.5K) */ + otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL), + ULPI_FUNC_CTRL_TERMSELECT); + + /* Enable weak pull-down resistor on DM */ + otg_io_write(isp->otg, ULPI_SET(ULPI_OTG_CTRL), + ULPI_OTG_CTRL_DM_PULLDOWN); + + /* It's a charger if the line states are clear */ + if (!(otg_io_read(isp->otg, ULPI_DEBUG))) + ret = 1; + + /* Disable weak pull-up resistor on DP */ + otg_io_write(isp->otg, ULPI_CLR(ISP1704_PWR_CTRL), + ISP1704_PWR_CTRL_DP_WKPU_EN); + + return ret; +} + +static inline int isp1704_charger_detect(struct isp1704_charger *isp) +{ + unsigned long timeout; + u8 r; + int ret = 0; + + /* set SW control bit in PWR_CTRL register */ + otg_io_write(isp->otg, ISP1704_PWR_CTRL, + ISP1704_PWR_CTRL_SWCTRL); + + /* enable manual charger detection */ + r = (ISP1704_PWR_CTRL_SWCTRL | ISP1704_PWR_CTRL_DPVSRC_EN); + otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL), r); + usleep_range(1000, 2000); + + timeout = jiffies + msecs_to_jiffies(300); + do { + /* Check if there is a charger */ + if (otg_io_read(isp->otg, ISP1704_PWR_CTRL) + & ISP1704_PWR_CTRL_VDAT_DET) { + ret = isp1704_charger_verify(isp); + break; + } + } while (!time_after(jiffies, timeout)); + + return ret; +} + +static void isp1704_charger_work(struct work_struct *data) +{ + int detect; + struct isp1704_charger *isp = + container_of(data, struct isp1704_charger, work); + + /* + * FIXME Only supporting dedicated chargers even though isp1704 can + * detect HUB and HOST chargers. If the device has already been + * enumerated, the detection will break the connection. + */ + if (isp->otg->state != OTG_STATE_B_IDLE) + return; + + /* disable data pullups */ + if (isp->otg->gadget) + usb_gadget_disconnect(isp->otg->gadget); + + /* detect charger */ + detect = isp1704_charger_detect(isp); + if (detect) { + isp->present = detect; + power_supply_changed(&isp->psy); + } + + /* enable data pullups */ + if (isp->otg->gadget) + usb_gadget_connect(isp->otg->gadget); +} + +static int isp1704_notifier_call(struct notifier_block *nb, + unsigned long event, void *unused) +{ + struct isp1704_charger *isp = + container_of(nb, struct isp1704_charger, nb); + + switch (event) { + case USB_EVENT_VBUS: + schedule_work(&isp->work); + break; + case USB_EVENT_NONE: + if (isp->present) { + isp->present = 0; + power_supply_changed(&isp->psy); + } + break; + default: + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + +static int isp1704_charger_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct isp1704_charger *isp = + container_of(psy, struct isp1704_charger, psy); + + switch (psp) { + case POWER_SUPPLY_PROP_PRESENT: + val->intval = isp->present; + break; + case POWER_SUPPLY_PROP_MODEL_NAME: + val->strval = isp->model; + break; + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = "NXP"; + break; + default: + return -EINVAL; + } + return 0; +} + +static enum power_supply_property power_props[] = { + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_MANUFACTURER, +}; + +static inline int isp1704_test_ulpi(struct isp1704_charger *isp) +{ + int vendor; + int product; + int i; + int ret = -ENODEV; + + /* Test ULPI interface */ + ret = otg_io_write(isp->otg, ULPI_SCRATCH, 0xaa); + if (ret < 0) + return ret; + + ret = otg_io_read(isp->otg, ULPI_SCRATCH); + if (ret < 0) + return ret; + + if (ret != 0xaa) + return -ENODEV; + + /* Verify the product and vendor id matches */ + vendor = otg_io_read(isp->otg, ULPI_VENDOR_ID_LOW); + vendor |= otg_io_read(isp->otg, ULPI_VENDOR_ID_HIGH) << 8; + if (vendor != NXP_VENDOR_ID) + return -ENODEV; + + product = otg_io_read(isp->otg, ULPI_PRODUCT_ID_LOW); + product |= otg_io_read(isp->otg, ULPI_PRODUCT_ID_HIGH) << 8; + + for (i = 0; i < ARRAY_SIZE(isp170x_id); i++) { + if (product == isp170x_id[i]) { + sprintf(isp->model, "isp%x", product); + return product; + } + } + + dev_err(isp->dev, "product id %x not matching known ids", product); + + return -ENODEV; +} + +static int __devinit isp1704_charger_probe(struct platform_device *pdev) +{ + struct isp1704_charger *isp; + int ret = -ENODEV; + + isp = kzalloc(sizeof *isp, GFP_KERNEL); + if (!isp) + return -ENOMEM; + + isp->otg = otg_get_transceiver(); + if (!isp->otg) + goto fail0; + + ret = isp1704_test_ulpi(isp); + if (ret < 0) + goto fail1; + + isp->dev = &pdev->dev; + platform_set_drvdata(pdev, isp); + + isp->psy.name = "isp1704"; + isp->psy.type = POWER_SUPPLY_TYPE_USB; + isp->psy.properties = power_props; + isp->psy.num_properties = ARRAY_SIZE(power_props); + isp->psy.get_property = isp1704_charger_get_property; + + ret = power_supply_register(isp->dev, &isp->psy); + if (ret) + goto fail1; + + /* + * REVISIT: using work in order to allow the otg notifications to be + * made atomically in the future. + */ + INIT_WORK(&isp->work, isp1704_charger_work); + + isp->nb.notifier_call = isp1704_notifier_call; + + ret = otg_register_notifier(isp->otg, &isp->nb); + if (ret) + goto fail2; + + dev_info(isp->dev, "registered with product id %s\n", isp->model); + + return 0; +fail2: + power_supply_unregister(&isp->psy); +fail1: + otg_put_transceiver(isp->otg); +fail0: + kfree(isp); + + dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret); + + return ret; +} + +static int __devexit isp1704_charger_remove(struct platform_device *pdev) +{ + struct isp1704_charger *isp = platform_get_drvdata(pdev); + + otg_unregister_notifier(isp->otg, &isp->nb); + power_supply_unregister(&isp->psy); + otg_put_transceiver(isp->otg); + kfree(isp); + + return 0; +} + +static struct platform_driver isp1704_charger_driver = { + .driver = { + .name = "isp1704_charger", + }, + .probe = isp1704_charger_probe, + .remove = __devexit_p(isp1704_charger_remove), +}; + +static int __init isp1704_charger_init(void) +{ + return platform_driver_register(&isp1704_charger_driver); +} +module_init(isp1704_charger_init); + +static void __exit isp1704_charger_exit(void) +{ + platform_driver_unregister(&isp1704_charger_driver); +} +module_exit(isp1704_charger_exit); + +MODULE_ALIAS("platform:isp1704_charger"); +MODULE_AUTHOR("Nokia Corporation"); +MODULE_DESCRIPTION("ISP170x USB Charger driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 5394637a246f4709e6f9c62b6af2356f49ef46a7 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 19 Aug 2010 15:15:50 +0200 Subject: ASoC: Use a more adequate name for the CX20442 codec DAI In the process of unification of codec DAI names while implementing multi-component, the CX20442 codec DAI has been renamed to "cx20442-hifi". This new name seems not adequate for a 8kHz voice codec. Use a better name, "cx20442-voice", as suggested by Liam Girdwood. Signed-off-by: Janusz Krzysztofik Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/cx20442.c | 2 +- sound/soc/omap/ams-delta.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index cf4323dbf9c4..e8d27c8f9ba3 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -318,7 +318,7 @@ EXPORT_SYMBOL_GPL(v253_ops); */ static struct snd_soc_dai_driver cx20442_dai = { - .name = "cx20442-hifi", + .name = "cx20442-voice", .playback = { .stream_name = "Playback", .channels_min = 1, diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 9d88efa06e3c..438146addbb8 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -584,7 +584,7 @@ static struct snd_soc_dai_link ams_delta_dai_link = { .name = "CX20442", .stream_name = "CX20442", .cpu_dai_name ="omap-mcbsp-dai.0", - .codec_dai_name = "cx20442-hifi", + .codec_dai_name = "cx20442-voice", .init = ams_delta_cx20442_init, .platform_name = "omap-pcm-audio", .codec_name = "cx20442-codec", -- cgit v1.2.3-59-g8ed1b From 083fc582b8752c64b0ae73935ddb45a1dd794b4c Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 19 Aug 2010 13:33:16 +0000 Subject: ixgbe: cleanup ixgbe_get_drvinfo to be extra careful with buffer boundaries Make the code in ixgbe_get_drvinfo more protected against buffer overflow boundaries by using snprintf and sizeof with snprintf. Signed-off-by: Don Skidmore Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_ethtool.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index dcebc82c6f4d..fb6d8e88eb05 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -820,16 +820,19 @@ static void ixgbe_get_drvinfo(struct net_device *netdev, struct ixgbe_adapter *adapter = netdev_priv(netdev); char firmware_version[32]; - strncpy(drvinfo->driver, ixgbe_driver_name, 32); - strncpy(drvinfo->version, ixgbe_driver_version, 32); - - sprintf(firmware_version, "%d.%d-%d", - (adapter->eeprom_version & 0xF000) >> 12, - (adapter->eeprom_version & 0x0FF0) >> 4, - adapter->eeprom_version & 0x000F); - - strncpy(drvinfo->fw_version, firmware_version, 32); - strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); + strncpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver)); + strncpy(drvinfo->version, ixgbe_driver_version, + sizeof(drvinfo->version)); + + snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d", + (adapter->eeprom_version & 0xF000) >> 12, + (adapter->eeprom_version & 0x0FF0) >> 4, + adapter->eeprom_version & 0x000F); + + strncpy(drvinfo->fw_version, firmware_version, + sizeof(drvinfo->fw_version)); + strncpy(drvinfo->bus_info, pci_name(adapter->pdev), + sizeof(drvinfo->bus_info)); drvinfo->n_stats = IXGBE_STATS_LEN; drvinfo->testinfo_len = IXGBE_TEST_LEN; drvinfo->regdump_len = ixgbe_get_regs_len(netdev); -- cgit v1.2.3-59-g8ed1b From d716a7d88549c99f9afbfc1f75dda1c390e2dc3a Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:33:41 +0000 Subject: ixgbe: remove redundant DMA alignment code This patch removes the redundant DMA alignment code from the Rx buffer allocation path. This code is no longer necessary since all x86 buffers are now DMA aligned due to recent changes to NET_IP_ALIGN and NET_SKB_PAD. It also moves the setting of the Rx queue value into the allocation path since it is more likely that the queue mapping will still be in the cache at the time of allocation. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index e32af434cc9d..5dceaf3dbb7f 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -955,7 +955,6 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, bool is_vlan = (status & IXGBE_RXD_STAT_VP); u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan); - skb_record_rx_queue(skb, ring->queue_index); if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK)) vlan_gro_receive(napi, adapter->vlgrp, tag, skb); @@ -1037,10 +1036,12 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, struct ixgbe_ring *rx_ring, int cleaned_count) { + struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; union ixgbe_adv_rx_desc *rx_desc; struct ixgbe_rx_buffer *bi; unsigned int i; + unsigned int bufsz = rx_ring->rx_buf_len; i = rx_ring->next_to_use; bi = &rx_ring->rx_buffer_info[i]; @@ -1051,7 +1052,7 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, if (!bi->page_dma && (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)) { if (!bi->page) { - bi->page = alloc_page(GFP_ATOMIC); + bi->page = netdev_alloc_page(netdev); if (!bi->page) { adapter->alloc_rx_page_failed++; goto no_buffers; @@ -1069,22 +1070,21 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, } if (!bi->skb) { - struct sk_buff *skb; - /* netdev_alloc_skb reserves 32 bytes up front!! */ - uint bufsz = rx_ring->rx_buf_len + SMP_CACHE_BYTES; - skb = netdev_alloc_skb(adapter->netdev, bufsz); + struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev, + bufsz); + bi->skb = skb; if (!skb) { adapter->alloc_rx_buff_failed++; goto no_buffers; } + /* initialize queue mapping */ + skb_record_rx_queue(skb, rx_ring->queue_index); + } - /* advance the data pointer to the next cache line */ - skb_reserve(skb, (PTR_ALIGN(skb->data, SMP_CACHE_BYTES) - - skb->data)); - - bi->skb = skb; - bi->dma = dma_map_single(&pdev->dev, skb->data, + if (!bi->dma) { + bi->dma = dma_map_single(&pdev->dev, + bi->skb->data, rx_ring->rx_buf_len, DMA_FROM_DEVICE); } -- cgit v1.2.3-59-g8ed1b From 67ebd79141e2dd503b0bc4898d06d07f07fc2635 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:34:04 +0000 Subject: ixgbe: move setting of GSO size for 82598 into ixgbe_configure_dcb We are unnecessarily modifying the GSO size for all HW when we don't need to. The code can be simplified by moving the check for DCB and the adjustment of the GSO size for 82598 into ixgbe_configure_dcb. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 5dceaf3dbb7f..fffb1ce4f6ea 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3157,6 +3157,15 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) u32 txdctl; int i, j; + if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) { + if (hw->mac.type == ixgbe_mac_82598EB) + netif_set_gso_max_size(adapter->netdev, 65536); + return; + } + + if (hw->mac.type == ixgbe_mac_82598EB) + netif_set_gso_max_size(adapter->netdev, 32768); + ixgbe_dcb_check_config(&adapter->dcb_cfg); ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_TX_CONFIG); ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_RX_CONFIG); @@ -3188,17 +3197,7 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) ixgbe_restore_vlan(adapter); #ifdef CONFIG_IXGBE_DCB - if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - if (hw->mac.type == ixgbe_mac_82598EB) - netif_set_gso_max_size(netdev, 32768); - else - netif_set_gso_max_size(netdev, 65536); - ixgbe_configure_dcb(adapter); - } else { - netif_set_gso_max_size(netdev, 65536); - } -#else - netif_set_gso_max_size(netdev, 65536); + ixgbe_configure_dcb(adapter); #endif #ifdef IXGBE_FCOE -- cgit v1.2.3-59-g8ed1b From 179b4096e25c190fc987832e0037b40507cc7ca0 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:34:27 +0000 Subject: ixgbe: combine two modifications of TXDCTL into one In ixgbe_up_complete we were doing a read-modify-write of TXDCTL followed by another one just a few lines further down. Instead of performing two separate read-modify-writes it would make more sense to combine the two into one. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index fffb1ce4f6ea..5d90f699fa78 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3411,6 +3411,12 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); } + if (hw->mac.type == ixgbe_mac_82599EB) { + /* DMATXCTL.EN must be set after all Tx queue config is done */ + dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); + dmatxctl |= IXGBE_DMATXCTL_TE; + IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); + } for (i = 0; i < adapter->num_tx_queues; i++) { j = adapter->tx_ring[i]->reg_idx; txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); @@ -3421,18 +3427,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) /* enable WTHRESH=8 descriptors, to encourage burst writeback */ txdctl |= (8 << 16); } - IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl); - } - - if (hw->mac.type == ixgbe_mac_82599EB) { - /* DMATXCTL.EN must be set after all Tx queue config is done */ - dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); - dmatxctl |= IXGBE_DMATXCTL_TE; - IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); - } - for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i]->reg_idx; - txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); txdctl |= IXGBE_TXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl); if (hw->mac.type == ixgbe_mac_82599EB) { -- cgit v1.2.3-59-g8ed1b From 120ff942cc6357b08fc817d89a5458038942edeb Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:34:50 +0000 Subject: ixgbe: move configuration of the MTQC register into it's own function This patch moves the configuration of the MTQC register into it's own function call similar to ixgbe_setup_mrqc. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 73 +++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 5d90f699fa78..c4e42075335a 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2424,6 +2424,45 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) e_info(hw, "Legacy interrupt IVAR setup done\n"); } +static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 rttdcs; + u32 mask; + + if (hw->mac.type == ixgbe_mac_82598EB) + return; + + /* disable the arbiter while setting MTQC */ + rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); + rttdcs |= IXGBE_RTTDCS_ARBDIS; + IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); + + /* set transmit pool layout */ + mask = (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_DCB_ENABLED); + switch (adapter->flags & mask) { + + case (IXGBE_FLAG_SRIOV_ENABLED): + IXGBE_WRITE_REG(hw, IXGBE_MTQC, + (IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF)); + break; + + case (IXGBE_FLAG_DCB_ENABLED): + /* We enable 8 traffic classes, DCB only */ + IXGBE_WRITE_REG(hw, IXGBE_MTQC, + (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ)); + break; + + default: + IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB); + break; + } + + /* re-enable the arbiter */ + rttdcs &= ~IXGBE_RTTDCS_ARBDIS; + IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); +} + /** * ixgbe_configure_tx - Configure 8259x Transmit Unit after Reset * @adapter: board private structure @@ -2475,39 +2514,7 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) } } - if (hw->mac.type == ixgbe_mac_82599EB) { - u32 rttdcs; - u32 mask; - - /* disable the arbiter while setting MTQC */ - rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); - rttdcs |= IXGBE_RTTDCS_ARBDIS; - IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); - - /* set transmit pool layout */ - mask = (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_DCB_ENABLED); - switch (adapter->flags & mask) { - - case (IXGBE_FLAG_SRIOV_ENABLED): - IXGBE_WRITE_REG(hw, IXGBE_MTQC, - (IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF)); - break; - - case (IXGBE_FLAG_DCB_ENABLED): - /* We enable 8 traffic classes, DCB only */ - IXGBE_WRITE_REG(hw, IXGBE_MTQC, - (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ)); - break; - - default: - IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB); - break; - } - - /* re-eable the arbiter */ - rttdcs &= ~IXGBE_RTTDCS_ARBDIS; - IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); - } + ixgbe_setup_mtqc(adapter); } #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 -- cgit v1.2.3-59-g8ed1b From 43e69bf0f0df2691001dbd055ab8d4f795d1900c Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:35:12 +0000 Subject: ixgbe: move Tx ring configuration into a separate function This patch moves the Tx ring configuration into a separate function. In addition the function drops the setting of the head writeback RO bit since head writeback is no longer used within ixgbe. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 69 ++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 40 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index c4e42075335a..37d1f64a34d5 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2424,6 +2424,32 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) e_info(hw, "Legacy interrupt IVAR setup done\n"); } +/** + * ixgbe_configure_tx_ring - Configure 8259x Tx ring after Reset + * @adapter: board private structure + * @ring: structure containing ring specific data + * + * Configure the Tx descriptor ring after a reset. + **/ + static void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter, + struct ixgbe_ring *ring) +{ + struct ixgbe_hw *hw = &adapter->hw; + u64 tdba = ring->dma; + u16 reg_idx = ring->reg_idx; + + IXGBE_WRITE_REG(hw, IXGBE_TDBAL(reg_idx), + (tdba & DMA_BIT_MASK(32))); + IXGBE_WRITE_REG(hw, IXGBE_TDBAH(reg_idx), (tdba >> 32)); + IXGBE_WRITE_REG(hw, IXGBE_TDLEN(reg_idx), + ring->count * sizeof(union ixgbe_adv_tx_desc)); + IXGBE_WRITE_REG(hw, IXGBE_TDH(reg_idx), 0); + IXGBE_WRITE_REG(hw, IXGBE_TDT(reg_idx), 0); + ring->head = IXGBE_TDH(reg_idx); + ring->tail = IXGBE_TDT(reg_idx); + +} + static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; @@ -2471,48 +2497,11 @@ static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter) **/ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) { - u64 tdba; - struct ixgbe_hw *hw = &adapter->hw; - u32 i, j, tdlen, txctrl; + u32 i; /* Setup the HW Tx Head and Tail descriptor pointers */ - for (i = 0; i < adapter->num_tx_queues; i++) { - struct ixgbe_ring *ring = adapter->tx_ring[i]; - j = ring->reg_idx; - tdba = ring->dma; - tdlen = ring->count * sizeof(union ixgbe_adv_tx_desc); - IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j), - (tdba & DMA_BIT_MASK(32))); - IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32)); - IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), tdlen); - IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0); - IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0); - adapter->tx_ring[i]->head = IXGBE_TDH(j); - adapter->tx_ring[i]->tail = IXGBE_TDT(j); - /* - * Disable Tx Head Writeback RO bit, since this hoses - * bookkeeping if things aren't delivered in order. - */ - switch (hw->mac.type) { - case ixgbe_mac_82598EB: - txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j)); - break; - case ixgbe_mac_82599EB: - default: - txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j)); - break; - } - txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; - switch (hw->mac.type) { - case ixgbe_mac_82598EB: - IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl); - break; - case ixgbe_mac_82599EB: - default: - IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl); - break; - } - } + for (i = 0; i < adapter->num_tx_queues; i++) + ixgbe_configure_tx_ring(adapter, adapter->tx_ring[i]); ixgbe_setup_mtqc(adapter); } -- cgit v1.2.3-59-g8ed1b From 05abb126c148b081ee9da5a611960e2a80205ea2 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:35:41 +0000 Subject: ixgbe: consolidate all setting of MRQC into one function This change simplifies the configuration of MRQC by consolidating the setting of it into one function. As such the register is no longer set in multiple places which should make any future changes easier to work with. In addition we can combine RSS related register writes into the call since enabling all of those bits without enabling RSS itself in MRQC should have no effect. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 100 ++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 57 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 37d1f64a34d5..f5d890239ac6 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2545,20 +2545,46 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl); } -static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) +static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) { - u32 mrqc = 0; + struct ixgbe_hw *hw = &adapter->hw; + static const u32 seed[10] = { 0xE291D73D, 0x1805EC6C, 0x2A94B30D, + 0xA54F2BEC, 0xEA49AF7C, 0xE214AD3D, 0xB855AABE, + 0x6A3E67EA, 0x14364D17, 0x3BED200D}; + u32 mrqc = 0, reta = 0; + u32 rxcsum; + int i, j; int mask; - if (!(adapter->hw.mac.type == ixgbe_mac_82599EB)) - return mrqc; + /* Fill out hash function seeds */ + for (i = 0; i < 10; i++) + IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]); + + /* Fill out redirection table */ + for (i = 0, j = 0; i < 128; i++, j++) { + if (j == adapter->ring_feature[RING_F_RSS].indices) + j = 0; + /* reta = 4-byte sliding window of + * 0x00..(indices-1)(indices-1)00..etc. */ + reta = (reta << 8) | (j * 0x11); + if ((i & 3) == 3) + IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); + } + + /* Disable indicating checksum in descriptor, enables RSS hash */ + rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); + rxcsum |= IXGBE_RXCSUM_PCSD; + IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); - mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED + if (adapter->hw.mac.type == ixgbe_mac_82598EB) + mask = adapter->flags & IXGBE_FLAG_RSS_ENABLED; + else + mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED #ifdef CONFIG_IXGBE_DCB - | IXGBE_FLAG_DCB_ENABLED + | IXGBE_FLAG_DCB_ENABLED #endif - | IXGBE_FLAG_SRIOV_ENABLED - ); + | IXGBE_FLAG_SRIOV_ENABLED + ); switch (mask) { case (IXGBE_FLAG_RSS_ENABLED): @@ -2576,7 +2602,13 @@ static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) break; } - return mrqc; + /* Perform hash on these packet types */ + mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4 + | IXGBE_MRQC_RSS_FIELD_IPV4_TCP + | IXGBE_MRQC_RSS_FIELD_IPV6 + | IXGBE_MRQC_RSS_FIELD_IPV6_TCP; + + IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); } /** @@ -2637,12 +2669,8 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) struct net_device *netdev = adapter->netdev; int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; int i, j; - u32 rdlen, rxctrl, rxcsum; - static const u32 seed[10] = { 0xE291D73D, 0x1805EC6C, 0x2A94B30D, - 0xA54F2BEC, 0xEA49AF7C, 0xE214AD3D, 0xB855AABE, - 0x6A3E67EA, 0x14364D17, 0x3BED200D}; + u32 rdlen, rxctrl; u32 fctrl, hlreg0; - u32 reta = 0, mrqc = 0; u32 rdrxctl; int rx_buf_len; @@ -2774,33 +2802,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) } /* Program MRQC for the distribution of queues */ - mrqc = ixgbe_setup_mrqc(adapter); - - if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { - /* Fill out redirection table */ - for (i = 0, j = 0; i < 128; i++, j++) { - if (j == adapter->ring_feature[RING_F_RSS].indices) - j = 0; - /* reta = 4-byte sliding window of - * 0x00..(indices-1)(indices-1)00..etc. */ - reta = (reta << 8) | (j * 0x11); - if ((i & 3) == 3) - IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); - } - - /* Fill out hash function seeds */ - for (i = 0; i < 10; i++) - IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]); - - if (hw->mac.type == ixgbe_mac_82598EB) - mrqc |= IXGBE_MRQC_RSSEN; - /* Perform hash on these packet types */ - mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4 - | IXGBE_MRQC_RSS_FIELD_IPV4_TCP - | IXGBE_MRQC_RSS_FIELD_IPV6 - | IXGBE_MRQC_RSS_FIELD_IPV6_TCP; - } - IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); + ixgbe_setup_mrqc(adapter); if (adapter->num_vfs) { u32 reg; @@ -2816,22 +2818,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, reg); } - rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); - - if (adapter->flags & IXGBE_FLAG_RSS_ENABLED || - adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED) { - /* Disable indicating checksum in descriptor, enables - * RSS hash */ - rxcsum |= IXGBE_RXCSUM_PCSD; - } - if (!(rxcsum & IXGBE_RXCSUM_PCSD)) { - /* Enable IPv4 payload checksum for UDP fragments - * if PCSD is not set */ - rxcsum |= IXGBE_RXCSUM_IPPCSE; - } - - IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); - if (hw->mac.type == ixgbe_mac_82599EB) { rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP; -- cgit v1.2.3-59-g8ed1b From acd37177cc2e034ecb6cbb784a8b998229fa85c4 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:36:05 +0000 Subject: ixgbe: pull ring configuration into it's own function These changes add ixgbe_configure_rx_ring which is used to setup the base function pointers for the ring. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index f5d890239ac6..ddabe14bbbca 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2655,6 +2655,23 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index) IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl); } +static void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter, + struct ixgbe_ring *ring) +{ + struct ixgbe_hw *hw = &adapter->hw; + u64 rdba = ring->dma; + u16 reg_idx = ring->reg_idx; + + IXGBE_WRITE_REG(hw, IXGBE_RDBAL(reg_idx), (rdba & DMA_BIT_MASK(32))); + IXGBE_WRITE_REG(hw, IXGBE_RDBAH(reg_idx), (rdba >> 32)); + IXGBE_WRITE_REG(hw, IXGBE_RDLEN(reg_idx), + ring->count * sizeof(union ixgbe_adv_rx_desc)); + IXGBE_WRITE_REG(hw, IXGBE_RDH(reg_idx), 0); + IXGBE_WRITE_REG(hw, IXGBE_RDT(reg_idx), 0); + ring->head = IXGBE_RDH(reg_idx); + ring->tail = IXGBE_RDT(reg_idx); +} + /** * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset * @adapter: board private structure @@ -2663,13 +2680,12 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index) **/ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) { - u64 rdba; struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_ring *rx_ring; struct net_device *netdev = adapter->netdev; int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; - int i, j; - u32 rdlen, rxctrl; + int i; + u32 rxctrl; u32 fctrl, hlreg0; u32 rdrxctl; int rx_buf_len; @@ -2718,7 +2734,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) #endif IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); - rdlen = adapter->rx_ring[0]->count * sizeof(union ixgbe_adv_rx_desc); /* disable receives while setting up the descriptors */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN); @@ -2729,15 +2744,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) */ for (i = 0; i < adapter->num_rx_queues; i++) { rx_ring = adapter->rx_ring[i]; - rdba = rx_ring->dma; - j = rx_ring->reg_idx; - IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), (rdba & DMA_BIT_MASK(32))); - IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32)); - IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), rdlen); - IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0); - IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0); - rx_ring->head = IXGBE_RDH(j); - rx_ring->tail = IXGBE_RDT(j); rx_ring->rx_buf_len = rx_buf_len; if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) @@ -2758,6 +2764,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) } #endif /* IXGBE_FCOE */ + ixgbe_configure_rx_ring(adapter, rx_ring); ixgbe_configure_srrctl(adapter, rx_ring); } -- cgit v1.2.3-59-g8ed1b From 486545216472d67c16e3d3d60c5f21f60959c855 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:36:27 +0000 Subject: ixgbe: pull PSRTYPE configuration into a separate function The configuration of PSRTYPE was being done conditionally on if packet split is enabled or not. It can be configured always since it will not have any effect when packet split is not enabled. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index ddabe14bbbca..88e6936a1579 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2672,6 +2672,29 @@ static void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter, ring->tail = IXGBE_RDT(reg_idx); } +static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + int p; + + /* PSRTYPE must be initialized in non 82598 adapters */ + u32 psrtype = IXGBE_PSRTYPE_TCPHDR | + IXGBE_PSRTYPE_UDPHDR | + IXGBE_PSRTYPE_IPV4HDR | + IXGBE_PSRTYPE_L2HDR | + IXGBE_PSRTYPE_IPV6HDR; + + if (hw->mac.type == ixgbe_mac_82598EB) + return; + + if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) + psrtype |= (adapter->num_rx_queues_per_pool << 29); + + for (p = 0; p < adapter->num_rx_pools; p++) + IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(adapter->num_vfs + p), + psrtype); +} + /** * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset * @adapter: board private structure @@ -2690,6 +2713,8 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) u32 rdrxctl; int rx_buf_len; + ixgbe_setup_psrtype(adapter); + /* Decide whether to use packet split mode or not */ /* Do not use packet split if we're in SR-IOV Mode */ if (!adapter->num_vfs) @@ -2698,17 +2723,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) /* Set the RX buffer length according to the mode */ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { rx_buf_len = IXGBE_RX_HDR_SIZE; - if (hw->mac.type == ixgbe_mac_82599EB) { - /* PSRTYPE must be initialized in 82599 */ - u32 psrtype = IXGBE_PSRTYPE_TCPHDR | - IXGBE_PSRTYPE_UDPHDR | - IXGBE_PSRTYPE_IPV4HDR | - IXGBE_PSRTYPE_IPV6HDR | - IXGBE_PSRTYPE_L2HDR; - IXGBE_WRITE_REG(hw, - IXGBE_PSRTYPE(adapter->num_vfs), - psrtype); - } } else { if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) && (netdev->mtu <= ETH_DATA_LEN)) -- cgit v1.2.3-59-g8ed1b From f5dc442b4671e2961c2e5bb3e16a86ce7da86cd3 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:36:49 +0000 Subject: ixgbe: combine accesses to FCTRL register into ixgbe_set_rx_mode We are accessing the FCTRL register in multiple spots in the init path and we can simplify things by combining the configuration all into ixgbe_set_rx_mode. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 88e6936a1579..b7553643f9ad 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2709,7 +2709,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; int i; u32 rxctrl; - u32 fctrl, hlreg0; + u32 hlreg0; u32 rdrxctl; int rx_buf_len; @@ -2731,12 +2731,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) rx_buf_len = ALIGN(max_frame, 1024); } - fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); - fctrl |= IXGBE_FCTRL_BAM; - fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */ - fctrl |= IXGBE_FCTRL_PMCF; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl); - hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); if (adapter->netdev->mtu <= ETH_DATA_LEN) hlreg0 &= ~IXGBE_HLREG0_JUMBOEN; @@ -3055,6 +3049,11 @@ void ixgbe_set_rx_mode(struct net_device *netdev) fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); + /* set all bits that we expect to always be set */ + fctrl |= IXGBE_FCTRL_BAM; + fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */ + fctrl |= IXGBE_FCTRL_PMCF; + /* clear the bits we are changing the status of */ fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); -- cgit v1.2.3-59-g8ed1b From 1395807091300b84789316cad2a9142b58f9092a Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:37:21 +0000 Subject: ixgbe: bump PS header size to 512 bytes Bump the header size for packet split to 512 bytes since this makes the best use of the 1k buffer that is allocated for any skb 512 bytes or smaller. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 9e15eb93860e..7233fef7e9b8 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -69,15 +69,20 @@ #define IXGBE_MAX_FCPAUSE 0xFFFF /* Supported Rx Buffer Sizes */ -#define IXGBE_RXBUFFER_64 64 /* Used for packet split */ -#define IXGBE_RXBUFFER_128 128 /* Used for packet split */ -#define IXGBE_RXBUFFER_256 256 /* Used for packet split */ +#define IXGBE_RXBUFFER_512 512 /* Used for packet split */ #define IXGBE_RXBUFFER_2048 2048 #define IXGBE_RXBUFFER_4096 4096 #define IXGBE_RXBUFFER_8192 8192 #define IXGBE_MAX_RXBUFFER 16384 /* largest size for a single descriptor */ -#define IXGBE_RX_HDR_SIZE IXGBE_RXBUFFER_256 +/* + * NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN mans we + * reserve 2 more, and skb_shared_info adds an additional 384 bytes more, + * this adds up to 512 bytes of extra data meaning the smallest allocation + * we could have is 1K. + * i.e. RXBUFFER_512 --> size-1024 slab + */ +#define IXGBE_RX_HDR_SIZE IXGBE_RXBUFFER_512 #define MAXIMUM_ETHERNET_VLAN_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN) -- cgit v1.2.3-59-g8ed1b From 826437d3de43174a8199776b5c1178bafa0b6634 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:37:48 +0000 Subject: ixgbe: remove redundant configuration of vmolr, rename generic variable The vmolr is configured already in ixgbe_set_rx_mode for the PF so there is no need to set it again in ixgbe_configure_rx. Instead of using the variable name reg, it is easier to just rename it to gcr_ext to reflect the register contents that the variable holds. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index b7553643f9ad..520b95fc4d41 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2709,7 +2709,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; int i; u32 rxctrl; - u32 hlreg0; + u32 hlreg0, gcr_ext; u32 rdrxctl; int rx_buf_len; @@ -2813,24 +2813,21 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift)); IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (1 << vf_shift)); IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); - ixgbe_set_vmolr(hw, adapter->num_vfs, true); } /* Program MRQC for the distribution of queues */ ixgbe_setup_mrqc(adapter); if (adapter->num_vfs) { - u32 reg; - /* Map PF MAC address in RAR Entry 0 to first pool * following VFs */ hw->mac.ops.set_vmdq(hw, 0, adapter->num_vfs); /* Set up VF register offsets for selected VT Mode, i.e. * 64 VFs for SR-IOV */ - reg = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); - reg |= IXGBE_GCR_EXT_SRIOV; - IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, reg); + gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); + gcr_ext |= IXGBE_GCR_EXT_SRIOV; + IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); } if (hw->mac.type == ixgbe_mac_82599EB) { -- cgit v1.2.3-59-g8ed1b From 477de6ed027dbbeb0424a4d1a978429037287d22 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:38:11 +0000 Subject: ixgbe: Move max frame size and Rx buffer length configuration into a function This change consolidates all of the Rx max frame size and Rx buffer length configuration into a single function. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 108 +++++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 48 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 520b95fc4d41..841ef9827ec6 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2695,25 +2695,15 @@ static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter) psrtype); } -/** - * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Rx unit of the MAC after a reset. - **/ -static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) +static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - struct ixgbe_ring *rx_ring; struct net_device *netdev = adapter->netdev; int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; - int i; - u32 rxctrl; - u32 hlreg0, gcr_ext; - u32 rdrxctl; int rx_buf_len; - - ixgbe_setup_psrtype(adapter); + struct ixgbe_ring *rx_ring; + int i; + u32 mhadd, hlreg0; /* Decide whether to use packet split mode or not */ /* Do not use packet split if we're in SR-IOV Mode */ @@ -2728,23 +2718,28 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) (netdev->mtu <= ETH_DATA_LEN)) rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE; else - rx_buf_len = ALIGN(max_frame, 1024); + rx_buf_len = ALIGN(max_frame + VLAN_HLEN, 1024); } - hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); - if (adapter->netdev->mtu <= ETH_DATA_LEN) - hlreg0 &= ~IXGBE_HLREG0_JUMBOEN; - else - hlreg0 |= IXGBE_HLREG0_JUMBOEN; #ifdef IXGBE_FCOE - if (netdev->features & NETIF_F_FCOE_MTU) - hlreg0 |= IXGBE_HLREG0_JUMBOEN; -#endif - IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); + /* adjust max frame to be able to do baby jumbo for FCoE */ + if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) && + (max_frame < IXGBE_FCOE_JUMBO_FRAME_SIZE)) + max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE; - /* disable receives while setting up the descriptors */ - rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); - IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN); +#endif /* IXGBE_FCOE */ + mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); + if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) { + mhadd &= ~IXGBE_MHADD_MFS_MASK; + mhadd |= max_frame << IXGBE_MHADD_MFS_SHIFT; + + IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); + } + + hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); + /* set jumbo enable since MHADD.MFS is keeping size locked at max_frame */ + hlreg0 |= IXGBE_HLREG0_JUMBOEN; + IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); /* * Setup the HW Rx Head and Tail Descriptor Pointers and @@ -2760,7 +2755,8 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED; #ifdef IXGBE_FCOE - if (netdev->features & NETIF_F_FCOE_MTU) { + if (netdev->features & NETIF_F_FCOE_MTU) + { struct ixgbe_ring_feature *f; f = &adapter->ring_feature[RING_F_FCOE]; if ((i >= f->mask) && (i < f->mask + f->indices)) { @@ -2770,8 +2766,41 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) IXGBE_FCOE_JUMBO_FRAME_SIZE; } } - #endif /* IXGBE_FCOE */ + } + +} + +/** + * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset + * @adapter: board private structure + * + * Configure the Rx unit of the MAC after a reset. + **/ +static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_ring *rx_ring; + int i; + u32 rxctrl; + u32 gcr_ext; + u32 rdrxctl; + + /* disable receives while setting up the descriptors */ + rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); + IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN); + + ixgbe_setup_psrtype(adapter); + + /* set_rx_buffer_len must be called before ring initialization */ + ixgbe_set_rx_buffer_len(adapter); + + /* + * Setup the HW Rx Head and Tail Descriptor Pointers and + * the Base and Length of the Rx Descriptor Ring + */ + for (i = 0; i < adapter->num_rx_queues; i++) { + rx_ring = adapter->rx_ring[i]; ixgbe_configure_rx_ring(adapter, rx_ring); ixgbe_configure_srrctl(adapter, rx_ring); } @@ -3322,13 +3351,11 @@ static inline void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter, static int ixgbe_up_complete(struct ixgbe_adapter *adapter) { - struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; int i, j = 0; int num_rx_rings = adapter->num_rx_queues; int err; - int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; - u32 txdctl, rxdctl, mhadd; + u32 txdctl, rxdctl; u32 dmatxctl; u32 gpie; u32 ctrl_ext; @@ -3395,21 +3422,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); } -#ifdef IXGBE_FCOE - /* adjust max frame to be able to do baby jumbo for FCoE */ - if ((netdev->features & NETIF_F_FCOE_MTU) && - (max_frame < IXGBE_FCOE_JUMBO_FRAME_SIZE)) - max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE; - -#endif /* IXGBE_FCOE */ - mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); - if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) { - mhadd &= ~IXGBE_MHADD_MFS_MASK; - mhadd |= max_frame << IXGBE_MHADD_MFS_SHIFT; - - IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); - } - if (hw->mac.type == ixgbe_mac_82599EB) { /* DMATXCTL.EN must be set after all Tx queue config is done */ dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); @@ -3522,7 +3534,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) &(adapter->tx_ring[i]->reinit_state)); /* enable transmits */ - netif_tx_start_all_queues(netdev); + netif_tx_start_all_queues(adapter->netdev); /* bring the link up in the watchdog, this could race with our first * link up interrupt but shouldn't be a problem */ -- cgit v1.2.3-59-g8ed1b From 7367096a43259c9b461ec3120dcaaf674a092132 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:38:34 +0000 Subject: ixgbe: move all Rx DMA control register writes to one central location This change moves all of the Rx DMA control register writes to one central location. This should help to avoid accidentally overwriting existing settings. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 91 ++++++++++++++++++++++-------------------- drivers/net/ixgbe/ixgbe_type.h | 2 + 2 files changed, 50 insertions(+), 43 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 841ef9827ec6..f8cdc992f24d 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2616,25 +2616,26 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) * @adapter: address of board private structure * @index: index of ring to set **/ -static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index) +static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, + struct ixgbe_ring *ring) { - struct ixgbe_ring *rx_ring; struct ixgbe_hw *hw = &adapter->hw; - int j; u32 rscctrl; int rx_buf_len; + u16 reg_idx = ring->reg_idx; + + if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) + return; - rx_ring = adapter->rx_ring[index]; - j = rx_ring->reg_idx; - rx_buf_len = rx_ring->rx_buf_len; - rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j)); + rx_buf_len = ring->rx_buf_len; + rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(reg_idx)); rscctrl |= IXGBE_RSCCTL_RSCEN; /* * we must limit the number of descriptors so that the * total size of max desc * buf_len is not greater * than 65535 */ - if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { + if (ring->flags & IXGBE_RING_RX_PS_ENABLED) { #if (MAX_SKB_FRAGS > 16) rscctrl |= IXGBE_RSCCTL_MAXDESC_16; #elif (MAX_SKB_FRAGS > 8) @@ -2652,7 +2653,7 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index) else rscctrl |= IXGBE_RSCCTL_MAXDESC_4; } - IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl); + IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl); } static void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter, @@ -2771,6 +2772,42 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter) } +static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); + + switch (hw->mac.type) { + case ixgbe_mac_82598EB: + /* + * For VMDq support of different descriptor types or + * buffer sizes through the use of multiple SRRCTL + * registers, RDRXCTL.MVMEN must be set to 1 + * + * also, the manual doesn't mention it clearly but DCA hints + * will only use queue 0's tags unless this bit is set. Side + * effects of setting this bit are only that SRRCTL must be + * fully programmed [0..15] + */ + rdrxctl |= IXGBE_RDRXCTL_MVMEN; + break; + case ixgbe_mac_82599EB: + /* Disable RSC for ACK packets */ + IXGBE_WRITE_REG(hw, IXGBE_RSCDBU, + (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU))); + rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE; + /* hardware requires some bits to be set by default */ + rdrxctl |= (IXGBE_RDRXCTL_RSCACKC | IXGBE_RDRXCTL_FCOE_WRFIX); + rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP; + break; + default: + /* We should do nothing since we don't know this hardware */ + return; + } + + IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); +} + /** * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset * @adapter: board private structure @@ -2784,13 +2821,13 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) int i; u32 rxctrl; u32 gcr_ext; - u32 rdrxctl; /* disable receives while setting up the descriptors */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN); ixgbe_setup_psrtype(adapter); + ixgbe_setup_rdrxctl(adapter); /* set_rx_buffer_len must be called before ring initialization */ ixgbe_set_rx_buffer_len(adapter); @@ -2803,22 +2840,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) rx_ring = adapter->rx_ring[i]; ixgbe_configure_rx_ring(adapter, rx_ring); ixgbe_configure_srrctl(adapter, rx_ring); - } - - if (hw->mac.type == ixgbe_mac_82598EB) { - /* - * For VMDq support of different descriptor types or - * buffer sizes through the use of multiple SRRCTL - * registers, RDRXCTL.MVMEN must be set to 1 - * - * also, the manual doesn't mention it clearly but DCA hints - * will only use queue 0's tags unless this bit is set. Side - * effects of setting this bit are only that SRRCTL must be - * fully programmed [0..15] - */ - rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); - rdrxctl |= IXGBE_RDRXCTL_MVMEN; - IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); + ixgbe_configure_rscctl(adapter, rx_ring); } if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { @@ -2858,23 +2880,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) gcr_ext |= IXGBE_GCR_EXT_SRIOV; IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); } - - if (hw->mac.type == ixgbe_mac_82599EB) { - rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); - rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP; - rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE; - IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); - } - - if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { - /* Enable 82599 HW-RSC */ - for (i = 0; i < adapter->num_rx_queues; i++) - ixgbe_configure_rscctl(adapter, i); - - /* Disable RSC for ACK packets */ - IXGBE_WRITE_REG(hw, IXGBE_RSCDBU, - (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU))); - } } static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 9587d975d66c..d3cc6ce7c973 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -871,6 +871,8 @@ #define IXGBE_RDRXCTL_MVMEN 0x00000020 #define IXGBE_RDRXCTL_DMAIDONE 0x00000008 /* DMA init cycle done */ #define IXGBE_RDRXCTL_AGGDIS 0x00010000 /* Aggregation disable */ +#define IXGBE_RDRXCTL_RSCACKC 0x02000000 /* must set 1 when RSC enabled */ +#define IXGBE_RDRXCTL_FCOE_WRFIX 0x04000000 /* must set 1 when RSC enabled */ /* RQTC Bit Masks and Shifts */ #define IXGBE_RQTC_SHIFT_TC(_i) ((_i) * 4) -- cgit v1.2.3-59-g8ed1b From f5b4a52e81d46b51ba07a983036739dc0c2c6c1c Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:38:57 +0000 Subject: ixgbe: Move virtualization config into a separate function This change moves the configuration that was done in configure_rx into a separate virtualization configuration function. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 84 +++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index f8cdc992f24d..d358beff57fc 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2696,6 +2696,48 @@ static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter) psrtype); } +static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 gcr_ext; + u32 vt_reg_bits; + u32 reg_offset, vf_shift; + u32 vmdctl; + + if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) + return; + + vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL); + vt_reg_bits = IXGBE_VMD_CTL_VMDQ_EN | IXGBE_VT_CTL_REPLEN; + vt_reg_bits |= (adapter->num_vfs << IXGBE_VT_CTL_POOL_SHIFT); + IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl | vt_reg_bits); + + vf_shift = adapter->num_vfs % 32; + reg_offset = (adapter->num_vfs > 32) ? 1 : 0; + + /* Enable only the PF's pool for Tx/Rx */ + IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift)); + IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset ^ 1), 0); + IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (1 << vf_shift)); + IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset ^ 1), 0); + IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); + + /* Map PF MAC address in RAR Entry 0 to first pool following VFs */ + hw->mac.ops.set_vmdq(hw, 0, adapter->num_vfs); + + /* + * Set up VF register offsets for selected VT Mode, + * i.e. 32 or 64 VFs for SR-IOV + */ + gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); + gcr_ext |= IXGBE_GCR_EXT_MSIX_EN; + gcr_ext |= IXGBE_GCR_EXT_VT_MODE_64; + IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); + + /* enable Tx loopback for VF/PF communication */ + IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); +} + static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; @@ -2820,7 +2862,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) struct ixgbe_ring *rx_ring; int i; u32 rxctrl; - u32 gcr_ext; /* disable receives while setting up the descriptors */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); @@ -2829,6 +2870,10 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) ixgbe_setup_psrtype(adapter); ixgbe_setup_rdrxctl(adapter); + /* Program MRQC for the distribution of queues */ + ixgbe_setup_mrqc(adapter); + ixgbe_configure_virtualization(adapter); + /* set_rx_buffer_len must be called before ring initialization */ ixgbe_set_rx_buffer_len(adapter); @@ -2843,43 +2888,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) ixgbe_configure_rscctl(adapter, rx_ring); } - if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { - u32 vt_reg_bits; - u32 reg_offset, vf_shift; - u32 vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL); - vt_reg_bits = IXGBE_VMD_CTL_VMDQ_EN - | IXGBE_VT_CTL_REPLEN; - vt_reg_bits |= (adapter->num_vfs << - IXGBE_VT_CTL_POOL_SHIFT); - IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl | vt_reg_bits); - IXGBE_WRITE_REG(hw, IXGBE_MRQC, 0); - - vf_shift = adapter->num_vfs % 32; - reg_offset = adapter->num_vfs / 32; - IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), 0); - IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), 0); - IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), 0); - IXGBE_WRITE_REG(hw, IXGBE_VFTE(1), 0); - /* Enable only the PF's pool for Tx/Rx */ - IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift)); - IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (1 << vf_shift)); - IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); - } - - /* Program MRQC for the distribution of queues */ - ixgbe_setup_mrqc(adapter); - - if (adapter->num_vfs) { - /* Map PF MAC address in RAR Entry 0 to first pool - * following VFs */ - hw->mac.ops.set_vmdq(hw, 0, adapter->num_vfs); - - /* Set up VF register offsets for selected VT Mode, i.e. - * 64 VFs for SR-IOV */ - gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); - gcr_ext |= IXGBE_GCR_EXT_SRIOV; - IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); - } } static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) -- cgit v1.2.3-59-g8ed1b From a34bcfffae8ebbba9dcbacbc3de718cca66689dd Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:39:20 +0000 Subject: ixgbe: move all GPIE register config into a single function This change moves all GPIE register configuration into a single function. The advantage of this is that we can avoid a number of unnecessary read/modify/write cycles on the register. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 72 ++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d358beff57fc..0b235221f14c 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3362,38 +3362,15 @@ static inline void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter, (adapter->rx_ring[rxr]->count - 1)); } -static int ixgbe_up_complete(struct ixgbe_adapter *adapter) +static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - int i, j = 0; - int num_rx_rings = adapter->num_rx_queues; - int err; - u32 txdctl, rxdctl; - u32 dmatxctl; - u32 gpie; - u32 ctrl_ext; - - ixgbe_get_hw_control(adapter); - - if ((adapter->flags & IXGBE_FLAG_MSIX_ENABLED) || - (adapter->flags & IXGBE_FLAG_MSI_ENABLED)) { - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - gpie = (IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_EIAME | - IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD); - } else { - /* MSI only */ - gpie = 0; - } - if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { - gpie &= ~IXGBE_GPIE_VTMODE_MASK; - gpie |= IXGBE_GPIE_VTMODE_64; - } - /* XXX: to interrupt immediately for EICS writes, enable this */ - /* gpie |= IXGBE_GPIE_EIMEN; */ - IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); - } + u32 gpie = 0; if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + gpie = IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_PBA_SUPPORT | + IXGBE_GPIE_OCD; + gpie |= IXGBE_GPIE_EIAME; /* * use EIAM to auto-mask when MSI-X interrupt is asserted * this saves a register write for every interrupt @@ -3414,26 +3391,37 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); } - /* Enable Thermal over heat sensor interrupt */ - if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) { - gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); - gpie |= IXGBE_SDP0_GPIEN; - IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); + /* XXX: to interrupt immediately for EICS writes, enable this */ + /* gpie |= IXGBE_GPIE_EIMEN; */ + + if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { + gpie &= ~IXGBE_GPIE_VTMODE_MASK; + gpie |= IXGBE_GPIE_VTMODE_64; } - /* Enable fan failure interrupt if media type is copper */ - if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) { - gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); + /* Enable fan failure interrupt */ + if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) gpie |= IXGBE_SDP1_GPIEN; - IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); - } - if (hw->mac.type == ixgbe_mac_82599EB) { - gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); + if (hw->mac.type == ixgbe_mac_82599EB) gpie |= IXGBE_SDP1_GPIEN; gpie |= IXGBE_SDP2_GPIEN; - IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); - } + + IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); +} + +static int ixgbe_up_complete(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + int i, j = 0; + int num_rx_rings = adapter->num_rx_queues; + int err; + u32 txdctl, rxdctl; + u32 dmatxctl; + u32 ctrl_ext; + + ixgbe_get_hw_control(adapter); + ixgbe_setup_gpie(adapter); if (hw->mac.type == ixgbe_mac_82599EB) { /* DMATXCTL.EN must be set after all Tx queue config is done */ -- cgit v1.2.3-59-g8ed1b From 2f1860b8d94a4457e401895be6fc9b9ffa2c8b2c Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:39:43 +0000 Subject: ixgbe: pull all Tx init into ixgbe_configure_tx The Tx init was spread out over ixgbe_configure, ixgbe_configure_tx, and ixgbe_up_complete. This change combines all of that into the ixgbe_configure_tx function in order to simplify the Tx init path. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 91 ++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 39 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 0b235221f14c..fd2026efae88 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2436,8 +2436,16 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; u64 tdba = ring->dma; + int wait_loop = 10; + u32 txdctl; u16 reg_idx = ring->reg_idx; + /* disable queue to avoid issues while updating state */ + txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx)); + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), + txdctl & ~IXGBE_TXDCTL_ENABLE); + IXGBE_WRITE_FLUSH(hw); + IXGBE_WRITE_REG(hw, IXGBE_TDBAL(reg_idx), (tdba & DMA_BIT_MASK(32))); IXGBE_WRITE_REG(hw, IXGBE_TDBAH(reg_idx), (tdba >> 32)); @@ -2448,6 +2456,38 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) ring->head = IXGBE_TDH(reg_idx); ring->tail = IXGBE_TDT(reg_idx); + /* configure fetching thresholds */ + if (adapter->rx_itr_setting == 0) { + /* cannot set wthresh when itr==0 */ + txdctl &= ~0x007F0000; + } else { + /* enable WTHRESH=8 descriptors, to encourage burst writeback */ + txdctl |= (8 << 16); + } + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + /* PThresh workaround for Tx hang with DFP enabled. */ + txdctl |= 32; + } + + /* reinitialize flowdirector state */ + set_bit(__IXGBE_FDIR_INIT_DONE, &ring->reinit_state); + + /* enable queue */ + txdctl |= IXGBE_TXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), txdctl); + + /* TXDCTL.EN will return 0 on 82598 if link is down, so skip it */ + if (hw->mac.type == ixgbe_mac_82598EB && + !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP)) + return; + + /* poll to verify queue is enabled */ + do { + msleep(1); + txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx)); + } while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE)); + if (!wait_loop) + e_err(drv, "Could not enable Tx Queue %d\n", reg_idx); } static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter) @@ -2497,13 +2537,22 @@ static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter) **/ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) { + struct ixgbe_hw *hw = &adapter->hw; + u32 dmatxctl; u32 i; + ixgbe_setup_mtqc(adapter); + + if (hw->mac.type != ixgbe_mac_82598EB) { + /* DMATXCTL.EN must be before Tx queues are enabled */ + dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); + dmatxctl |= IXGBE_DMATXCTL_TE; + IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); + } + /* Setup the HW Tx Head and Tail descriptor pointers */ for (i = 0; i < adapter->num_tx_queues; i++) ixgbe_configure_tx_ring(adapter, adapter->tx_ring[i]); - - ixgbe_setup_mtqc(adapter); } #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 @@ -3416,44 +3465,12 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) int i, j = 0; int num_rx_rings = adapter->num_rx_queues; int err; - u32 txdctl, rxdctl; - u32 dmatxctl; + u32 rxdctl; u32 ctrl_ext; ixgbe_get_hw_control(adapter); ixgbe_setup_gpie(adapter); - if (hw->mac.type == ixgbe_mac_82599EB) { - /* DMATXCTL.EN must be set after all Tx queue config is done */ - dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); - dmatxctl |= IXGBE_DMATXCTL_TE; - IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); - } - for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i]->reg_idx; - txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); - if (adapter->rx_itr_setting == 0) { - /* cannot set wthresh when itr==0 */ - txdctl &= ~0x007F0000; - } else { - /* enable WTHRESH=8 descriptors, to encourage burst writeback */ - txdctl |= (8 << 16); - } - txdctl |= IXGBE_TXDCTL_ENABLE; - IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl); - if (hw->mac.type == ixgbe_mac_82599EB) { - int wait_loop = 10; - /* poll for Tx Enable ready */ - do { - msleep(1); - txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); - } while (--wait_loop && - !(txdctl & IXGBE_TXDCTL_ENABLE)); - if (!wait_loop) - e_err(drv, "Could not enable Tx Queue %d\n", j); - } - } - for (i = 0; i < num_rx_rings; i++) { j = adapter->rx_ring[i]->reg_idx; rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j)); @@ -3530,10 +3547,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) e_err(probe, "link_config FAILED %d\n", err); } - for (i = 0; i < adapter->num_tx_queues; i++) - set_bit(__IXGBE_FDIR_INIT_DONE, - &(adapter->tx_ring[i]->reinit_state)); - /* enable transmits */ netif_tx_start_all_queues(adapter->netdev); -- cgit v1.2.3-59-g8ed1b From 9e10e045f8223e09f2c70cd6849ff86803d50c88 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:40:06 +0000 Subject: ixgbe: combine Rx into into ixgbe_configure_rx The Rx init is currently split over ixgbe_configure, ixgbe_configure_rx, and ixgbe_up_complete. Instead of leaving it split over 3 function it is easier to consolidate them all into ixgbe_configure_rx. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 152 +++++++++++++++++++++++++---------------- 1 file changed, 95 insertions(+), 57 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index fd2026efae88..c88ba13c1131 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2574,6 +2574,8 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK; + if (adapter->num_vfs) + srrctl |= IXGBE_SRRCTL_DROP_EN; srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & IXGBE_SRRCTL_BSIZEHDR_MASK; @@ -2705,13 +2707,72 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl); } +/** + * ixgbe_set_uta - Set unicast filter table address + * @adapter: board private structure + * + * The unicast table address is a register array of 32-bit registers. + * The table is meant to be used in a way similar to how the MTA is used + * however due to certain limitations in the hardware it is necessary to + * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous + * enable bit to allow vlan tag stripping when promiscuous mode is enabled + **/ +static void ixgbe_set_uta(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + int i; + + /* The UTA table only exists on 82599 hardware and newer */ + if (hw->mac.type < ixgbe_mac_82599EB) + return; + + /* we only need to do this if VMDq is enabled */ + if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) + return; + + for (i = 0; i < 128; i++) + IXGBE_WRITE_REG(hw, IXGBE_UTA(i), ~0); +} + +#define IXGBE_MAX_RX_DESC_POLL 10 +static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter, + struct ixgbe_ring *ring) +{ + struct ixgbe_hw *hw = &adapter->hw; + int reg_idx = ring->reg_idx; + int wait_loop = IXGBE_MAX_RX_DESC_POLL; + u32 rxdctl; + + /* RXDCTL.EN will return 0 on 82598 if link is down, so skip it */ + if (hw->mac.type == ixgbe_mac_82598EB && + !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP)) + return; + + do { + msleep(1); + rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx)); + } while (--wait_loop && !(rxdctl & IXGBE_RXDCTL_ENABLE)); + + if (!wait_loop) { + e_err(drv, "RXDCTL.ENABLE on Rx queue %d not set within " + "the polling period\n", reg_idx); + } +} + static void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter, struct ixgbe_ring *ring) { struct ixgbe_hw *hw = &adapter->hw; u64 rdba = ring->dma; + u32 rxdctl; u16 reg_idx = ring->reg_idx; + /* disable queue to avoid issues while updating state */ + rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx)); + IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), + rxdctl & ~IXGBE_RXDCTL_ENABLE); + IXGBE_WRITE_FLUSH(hw); + IXGBE_WRITE_REG(hw, IXGBE_RDBAL(reg_idx), (rdba & DMA_BIT_MASK(32))); IXGBE_WRITE_REG(hw, IXGBE_RDBAH(reg_idx), (rdba >> 32)); IXGBE_WRITE_REG(hw, IXGBE_RDLEN(reg_idx), @@ -2720,6 +2781,28 @@ static void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter, IXGBE_WRITE_REG(hw, IXGBE_RDT(reg_idx), 0); ring->head = IXGBE_RDH(reg_idx); ring->tail = IXGBE_RDT(reg_idx); + + ixgbe_configure_srrctl(adapter, ring); + ixgbe_configure_rscctl(adapter, ring); + + if (hw->mac.type == ixgbe_mac_82598EB) { + /* + * enable cache line friendly hardware writes: + * PTHRESH=32 descriptors (half the internal cache), + * this also removes ugly rx_no_buffer_count increment + * HTHRESH=4 descriptors (to minimize latency on fetch) + * WTHRESH=8 burst writeback up to two cache lines + */ + rxdctl &= ~0x3FFFFF; + rxdctl |= 0x080420; + } + + /* enable receive descriptor ring */ + rxdctl |= IXGBE_RXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl); + + ixgbe_rx_desc_queue_enable(adapter, ring); + ixgbe_alloc_rx_buffers(adapter, ring, IXGBE_DESC_UNUSED(ring)); } static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter) @@ -2908,7 +2991,6 @@ static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter) static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - struct ixgbe_ring *rx_ring; int i; u32 rxctrl; @@ -2919,10 +3001,12 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) ixgbe_setup_psrtype(adapter); ixgbe_setup_rdrxctl(adapter); - /* Program MRQC for the distribution of queues */ + /* Program registers for the distribution of queues */ ixgbe_setup_mrqc(adapter); ixgbe_configure_virtualization(adapter); + ixgbe_set_uta(adapter); + /* set_rx_buffer_len must be called before ring initialization */ ixgbe_set_rx_buffer_len(adapter); @@ -2930,13 +3014,16 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) * Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ - for (i = 0; i < adapter->num_rx_queues; i++) { - rx_ring = adapter->rx_ring[i]; - ixgbe_configure_rx_ring(adapter, rx_ring); - ixgbe_configure_srrctl(adapter, rx_ring); - ixgbe_configure_rscctl(adapter, rx_ring); - } + for (i = 0; i < adapter->num_rx_queues; i++) + ixgbe_configure_rx_ring(adapter, adapter->rx_ring[i]); + /* disable drop enable for 82598 parts */ + if (hw->mac.type == ixgbe_mac_82598EB) + rxctrl |= IXGBE_RXCTRL_DMBYPS; + + /* enable all receives */ + rxctrl |= IXGBE_RXCTRL_RXEN; + hw->mac.ops.enable_rx_dma(hw, rxctrl); } static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) @@ -3306,9 +3393,6 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) ixgbe_configure_tx(adapter); ixgbe_configure_rx(adapter); - for (i = 0; i < adapter->num_rx_queues; i++) - ixgbe_alloc_rx_buffers(adapter, adapter->rx_ring[i], - (adapter->rx_ring[i]->count - 1)); } static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw) @@ -3389,28 +3473,6 @@ link_cfg_out: return ret; } -#define IXGBE_MAX_RX_DESC_POLL 10 -static inline void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter, - int rxr) -{ - int j = adapter->rx_ring[rxr]->reg_idx; - int k; - - for (k = 0; k < IXGBE_MAX_RX_DESC_POLL; k++) { - if (IXGBE_READ_REG(&adapter->hw, - IXGBE_RXDCTL(j)) & IXGBE_RXDCTL_ENABLE) - break; - else - msleep(1); - } - if (k >= IXGBE_MAX_RX_DESC_POLL) { - e_err(drv, "RXDCTL.ENABLE on Rx queue %d not set within " - "the polling period\n", rxr); - } - ixgbe_release_rx_desc(&adapter->hw, adapter->rx_ring[rxr], - (adapter->rx_ring[rxr]->count - 1)); -} - static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; @@ -3462,35 +3524,12 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter) static int ixgbe_up_complete(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - int i, j = 0; - int num_rx_rings = adapter->num_rx_queues; int err; - u32 rxdctl; u32 ctrl_ext; ixgbe_get_hw_control(adapter); ixgbe_setup_gpie(adapter); - for (i = 0; i < num_rx_rings; i++) { - j = adapter->rx_ring[i]->reg_idx; - rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j)); - /* enable PTHRESH=32 descriptors (half the internal cache) - * and HTHRESH=0 descriptors (to minimize latency on fetch), - * this also removes a pesky rx_no_buffer_count increment */ - rxdctl |= 0x0020; - rxdctl |= IXGBE_RXDCTL_ENABLE; - IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(j), rxdctl); - if (hw->mac.type == ixgbe_mac_82599EB) - ixgbe_rx_desc_queue_enable(adapter, i); - } - /* enable all receives */ - rxdctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); - if (hw->mac.type == ixgbe_mac_82598EB) - rxdctl |= (IXGBE_RXCTRL_DMBYPS | IXGBE_RXCTRL_RXEN); - else - rxdctl |= IXGBE_RXCTRL_RXEN; - hw->mac.ops.enable_rx_dma(hw, rxdctl); - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) ixgbe_configure_msix(adapter); else @@ -3505,7 +3544,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) /* clear any pending interrupts, may auto mask */ IXGBE_READ_REG(hw, IXGBE_EICR); - ixgbe_irq_enable(adapter); /* -- cgit v1.2.3-59-g8ed1b From 31f05a2d875327ef133ac4b62261c4b875d1d10c Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:40:31 +0000 Subject: ixgbe: update all DESC_ADV macros to accept a ring pointer All of the DESC_ADV macros are currently needing the pointers to be de-referenced before accessing the ring. Instead of having to add all of the asterisks it is easier to just update the macro to expect a pointer to the ring. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 6 +++--- drivers/net/ixgbe/ixgbe_ethtool.c | 4 ++-- drivers/net/ixgbe/ixgbe_fcoe.c | 2 +- drivers/net/ixgbe/ixgbe_main.c | 24 ++++++++++++------------ 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 7233fef7e9b8..ac4b90edb58e 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -256,11 +256,11 @@ struct ixgbe_q_vector { (R)->next_to_clean - (R)->next_to_use - 1) #define IXGBE_RX_DESC_ADV(R, i) \ - (&(((union ixgbe_adv_rx_desc *)((R).desc))[i])) + (&(((union ixgbe_adv_rx_desc *)((R)->desc))[i])) #define IXGBE_TX_DESC_ADV(R, i) \ - (&(((union ixgbe_adv_tx_desc *)((R).desc))[i])) + (&(((union ixgbe_adv_tx_desc *)((R)->desc))[i])) #define IXGBE_TX_CTXTDESC_ADV(R, i) \ - (&(((struct ixgbe_adv_tx_context_desc *)((R).desc))[i])) + (&(((struct ixgbe_adv_tx_context_desc *)((R)->desc))[i])) #define IXGBE_MAX_JUMBO_FRAME_SIZE 16128 #ifdef IXGBE_FCOE diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index fb6d8e88eb05..4d74f4bc7a01 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1560,7 +1560,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(0), reg_data); for (i = 0; i < tx_ring->count; i++) { - union ixgbe_adv_tx_desc *desc = IXGBE_TX_DESC_ADV(*tx_ring, i); + union ixgbe_adv_tx_desc *desc = IXGBE_TX_DESC_ADV(tx_ring, i); struct sk_buff *skb; unsigned int size = 1024; @@ -1661,7 +1661,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) for (i = 0; i < rx_ring->count; i++) { union ixgbe_adv_rx_desc *rx_desc = - IXGBE_RX_DESC_ADV(*rx_ring, i); + IXGBE_RX_DESC_ADV(rx_ring, i); struct sk_buff *skb; skb = alloc_skb(IXGBE_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL); diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index 072327c5e41a..86fa07cb061d 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -471,7 +471,7 @@ int ixgbe_fso(struct ixgbe_adapter *adapter, /* write context desc */ i = tx_ring->next_to_use; - context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i); + context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i); context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof); context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index c88ba13c1131..85ecf0e39b99 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -385,7 +385,7 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter) "leng ntw timestamp bi->skb\n"); for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { - tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); + tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i); tx_buffer_info = &tx_ring->tx_buffer_info[i]; u0 = (struct my_u0 *)tx_desc; printk(KERN_INFO "T [0x%03X] %016llX %016llX %016llX" @@ -466,7 +466,7 @@ rx_ring_summary: for (i = 0; i < rx_ring->count; i++) { rx_buffer_info = &rx_ring->rx_buffer_info[i]; - rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i); + rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i); u0 = (struct my_u0 *)rx_desc; staterr = le32_to_cpu(rx_desc->wb.upper.status_error); if (staterr & IXGBE_RXD_STAT_DD) { @@ -695,7 +695,7 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, ixgbe_tx_xon_state(adapter, tx_ring)) { /* detected Tx unit hang */ union ixgbe_adv_tx_desc *tx_desc; - tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); + tx_desc = IXGBE_TX_DESC_ADV(tx_ring, eop); e_err(drv, "Detected Tx Unit Hang\n" " Tx Queue <%d>\n" " TDH, TDT <%x>, <%x>\n" @@ -743,7 +743,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, i = tx_ring->next_to_clean; eop = tx_ring->tx_buffer_info[i].next_to_watch; - eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); + eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop); while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && (count < tx_ring->work_limit)) { @@ -751,7 +751,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, rmb(); /* read buffer_info after eop_desc */ for ( ; !cleaned; count++) { struct sk_buff *skb; - tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); + tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i); tx_buffer_info = &tx_ring->tx_buffer_info[i]; cleaned = (i == eop); skb = tx_buffer_info->skb; @@ -791,7 +791,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, } eop = tx_ring->tx_buffer_info[i].next_to_watch; - eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); + eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop); } tx_ring->next_to_clean = i; @@ -1047,7 +1047,7 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, bi = &rx_ring->rx_buffer_info[i]; while (cleaned_count--) { - rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i); + rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i); if (!bi->page_dma && (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)) { @@ -1188,7 +1188,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, #endif /* IXGBE_FCOE */ i = rx_ring->next_to_clean; - rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i); + rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i); staterr = le32_to_cpu(rx_desc->wb.upper.status_error); rx_buffer_info = &rx_ring->rx_buffer_info[i]; @@ -1263,7 +1263,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, if (i == rx_ring->count) i = 0; - next_rxd = IXGBE_RX_DESC_ADV(*rx_ring, i); + next_rxd = IXGBE_RX_DESC_ADV(rx_ring, i); prefetch(next_rxd); cleaned_count++; @@ -5813,7 +5813,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, i = tx_ring->next_to_use; tx_buffer_info = &tx_ring->tx_buffer_info[i]; - context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i); + context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i); /* VLAN MACLEN IPLEN */ if (tx_flags & IXGBE_TX_FLAGS_VLAN) @@ -5872,7 +5872,7 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, (tx_flags & IXGBE_TX_FLAGS_VLAN)) { i = tx_ring->next_to_use; tx_buffer_info = &tx_ring->tx_buffer_info[i]; - context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i); + context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i); if (tx_flags & IXGBE_TX_FLAGS_VLAN) vlan_macip_lens |= @@ -6101,7 +6101,7 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, i = tx_ring->next_to_use; while (count--) { tx_buffer_info = &tx_ring->tx_buffer_info[i]; - tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); + tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i); tx_desc->read.buffer_addr = cpu_to_le64(tx_buffer_info->dma); tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type_len | tx_buffer_info->length); -- cgit v1.2.3-59-g8ed1b From 84418e3b10b5ba43eb5b85f725e75fd9c9730670 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Aug 2010 13:40:54 +0000 Subject: ixgbe: rewrite ethtool test to use standard config functions This change makes it so that the ethtool loopback test uses the standard ring configuration and allocation functions. As a result the loopback test will be much more effective at testing core driver functionality. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 11 ++ drivers/net/ixgbe/ixgbe_ethtool.c | 362 +++++++++++++------------------------- drivers/net/ixgbe/ixgbe_main.c | 49 ++++-- 3 files changed, 169 insertions(+), 253 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index ac4b90edb58e..5cebc3755b64 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -453,9 +453,20 @@ extern int ixgbe_setup_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *) extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); +extern void ixgbe_configure_rx_ring(struct ixgbe_adapter *,struct ixgbe_ring *); +extern void ixgbe_configure_tx_ring(struct ixgbe_adapter *,struct ixgbe_ring *); extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter); extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter); +extern netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *, + struct net_device *, + struct ixgbe_adapter *, + struct ixgbe_ring *); +extern void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *, + struct ixgbe_tx_buffer *); +extern void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, + struct ixgbe_ring *rx_ring, + int cleaned_count); extern void ixgbe_write_eitr(struct ixgbe_q_vector *); extern int ethtool_ioctl(struct ifreq *ifr); extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw); diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 4d74f4bc7a01..25ef8b197373 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1438,9 +1438,7 @@ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter) struct ixgbe_ring *tx_ring = &adapter->test_tx_ring; struct ixgbe_ring *rx_ring = &adapter->test_rx_ring; struct ixgbe_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; u32 reg_ctl; - int i; /* shut down the DMA engines now so they can be reinitialized later */ @@ -1448,14 +1446,15 @@ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter) reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); reg_ctl &= ~IXGBE_RXCTRL_RXEN; IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_ctl); - reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(0)); + reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rx_ring->reg_idx)); reg_ctl &= ~IXGBE_RXDCTL_ENABLE; - IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(0), reg_ctl); + IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rx_ring->reg_idx), reg_ctl); /* now Tx */ - reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(0)); + reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx)); reg_ctl &= ~IXGBE_TXDCTL_ENABLE; - IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(0), reg_ctl); + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx), reg_ctl); + if (hw->mac.type == ixgbe_mac_82599EB) { reg_ctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); reg_ctl &= ~IXGBE_DMATXCTL_TE; @@ -1464,221 +1463,57 @@ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter) ixgbe_reset(adapter); - if (tx_ring->desc && tx_ring->tx_buffer_info) { - for (i = 0; i < tx_ring->count; i++) { - struct ixgbe_tx_buffer *buf = - &(tx_ring->tx_buffer_info[i]); - if (buf->dma) - dma_unmap_single(&pdev->dev, buf->dma, - buf->length, DMA_TO_DEVICE); - if (buf->skb) - dev_kfree_skb(buf->skb); - } - } - - if (rx_ring->desc && rx_ring->rx_buffer_info) { - for (i = 0; i < rx_ring->count; i++) { - struct ixgbe_rx_buffer *buf = - &(rx_ring->rx_buffer_info[i]); - if (buf->dma) - dma_unmap_single(&pdev->dev, buf->dma, - IXGBE_RXBUFFER_2048, - DMA_FROM_DEVICE); - if (buf->skb) - dev_kfree_skb(buf->skb); - } - } - - if (tx_ring->desc) { - dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, - tx_ring->dma); - tx_ring->desc = NULL; - } - if (rx_ring->desc) { - dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, - rx_ring->dma); - rx_ring->desc = NULL; - } - - kfree(tx_ring->tx_buffer_info); - tx_ring->tx_buffer_info = NULL; - kfree(rx_ring->rx_buffer_info); - rx_ring->rx_buffer_info = NULL; + ixgbe_free_tx_resources(adapter, &adapter->test_tx_ring); + ixgbe_free_rx_resources(adapter, &adapter->test_rx_ring); } static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) { struct ixgbe_ring *tx_ring = &adapter->test_tx_ring; struct ixgbe_ring *rx_ring = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; u32 rctl, reg_data; - int i, ret_val; + int ret_val; + int err; /* Setup Tx descriptor ring and Tx buffers */ + tx_ring->count = IXGBE_DEFAULT_TXD; + tx_ring->queue_index = 0; + tx_ring->reg_idx = adapter->tx_ring[0]->reg_idx; + tx_ring->numa_node = adapter->node; - if (!tx_ring->count) - tx_ring->count = IXGBE_DEFAULT_TXD; - - tx_ring->tx_buffer_info = kcalloc(tx_ring->count, - sizeof(struct ixgbe_tx_buffer), - GFP_KERNEL); - if (!(tx_ring->tx_buffer_info)) { - ret_val = 1; - goto err_nomem; - } - - tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc); - tx_ring->size = ALIGN(tx_ring->size, 4096); - tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size, - &tx_ring->dma, GFP_KERNEL); - if (!(tx_ring->desc)) { - ret_val = 2; - goto err_nomem; - } - tx_ring->next_to_use = tx_ring->next_to_clean = 0; - - IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAL(0), - ((u64) tx_ring->dma & 0x00000000FFFFFFFF)); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAH(0), - ((u64) tx_ring->dma >> 32)); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDLEN(0), - tx_ring->count * sizeof(union ixgbe_adv_tx_desc)); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDH(0), 0); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), 0); - - reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0); - reg_data |= IXGBE_HLREG0_TXPADEN; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data); + err = ixgbe_setup_tx_resources(adapter, tx_ring); + if (err) + return 1; if (adapter->hw.mac.type == ixgbe_mac_82599EB) { reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL); reg_data |= IXGBE_DMATXCTL_TE; IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data); } - reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(0)); - reg_data |= IXGBE_TXDCTL_ENABLE; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(0), reg_data); - - for (i = 0; i < tx_ring->count; i++) { - union ixgbe_adv_tx_desc *desc = IXGBE_TX_DESC_ADV(tx_ring, i); - struct sk_buff *skb; - unsigned int size = 1024; - - skb = alloc_skb(size, GFP_KERNEL); - if (!skb) { - ret_val = 3; - goto err_nomem; - } - skb_put(skb, size); - tx_ring->tx_buffer_info[i].skb = skb; - tx_ring->tx_buffer_info[i].length = skb->len; - tx_ring->tx_buffer_info[i].dma = - dma_map_single(&pdev->dev, skb->data, skb->len, - DMA_TO_DEVICE); - desc->read.buffer_addr = - cpu_to_le64(tx_ring->tx_buffer_info[i].dma); - desc->read.cmd_type_len = cpu_to_le32(skb->len); - desc->read.cmd_type_len |= cpu_to_le32(IXGBE_TXD_CMD_EOP | - IXGBE_TXD_CMD_IFCS | - IXGBE_TXD_CMD_RS); - desc->read.olinfo_status = 0; - if (adapter->hw.mac.type == ixgbe_mac_82599EB) - desc->read.olinfo_status |= - (skb->len << IXGBE_ADVTXD_PAYLEN_SHIFT); - } + ixgbe_configure_tx_ring(adapter, tx_ring); /* Setup Rx Descriptor ring and Rx buffers */ - - if (!rx_ring->count) - rx_ring->count = IXGBE_DEFAULT_RXD; - - rx_ring->rx_buffer_info = kcalloc(rx_ring->count, - sizeof(struct ixgbe_rx_buffer), - GFP_KERNEL); - if (!(rx_ring->rx_buffer_info)) { + rx_ring->count = IXGBE_DEFAULT_RXD; + rx_ring->queue_index = 0; + rx_ring->reg_idx = adapter->rx_ring[0]->reg_idx; + rx_ring->rx_buf_len = IXGBE_RXBUFFER_2048; + rx_ring->numa_node = adapter->node; + + err = ixgbe_setup_rx_resources(adapter, rx_ring); + if (err) { ret_val = 4; goto err_nomem; } - rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc); - rx_ring->size = ALIGN(rx_ring->size, 4096); - rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, - &rx_ring->dma, GFP_KERNEL); - if (!(rx_ring->desc)) { - ret_val = 5; - goto err_nomem; - } - rx_ring->next_to_use = rx_ring->next_to_clean = 0; - rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXCTRL); IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl & ~IXGBE_RXCTRL_RXEN); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAL(0), - ((u64)rx_ring->dma & 0xFFFFFFFF)); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAH(0), - ((u64) rx_ring->dma >> 32)); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDLEN(0), rx_ring->size); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDH(0), 0); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), 0); - reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); - reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data); - - reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0); - reg_data &= ~IXGBE_HLREG0_LPBK; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data); - - reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RDRXCTL); -#define IXGBE_RDRXCTL_RDMTS_MASK 0x00000003 /* Receive Descriptor Minimum - Threshold Size mask */ - reg_data &= ~IXGBE_RDRXCTL_RDMTS_MASK; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDRXCTL, reg_data); - - reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_MCSTCTRL); -#define IXGBE_MCSTCTRL_MO_MASK 0x00000003 /* Multicast Offset mask */ - reg_data &= ~IXGBE_MCSTCTRL_MO_MASK; - reg_data |= adapter->hw.mac.mc_filter_type; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_MCSTCTRL, reg_data); - - reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(0)); - reg_data |= IXGBE_RXDCTL_ENABLE; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(0), reg_data); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - int j = adapter->rx_ring[0]->reg_idx; - u32 k; - for (k = 0; k < 10; k++) { - if (IXGBE_READ_REG(&adapter->hw, - IXGBE_RXDCTL(j)) & IXGBE_RXDCTL_ENABLE) - break; - else - msleep(1); - } - } + ixgbe_configure_rx_ring(adapter, rx_ring); rctl |= IXGBE_RXCTRL_RXEN | IXGBE_RXCTRL_DMBYPS; IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl); - for (i = 0; i < rx_ring->count; i++) { - union ixgbe_adv_rx_desc *rx_desc = - IXGBE_RX_DESC_ADV(rx_ring, i); - struct sk_buff *skb; - - skb = alloc_skb(IXGBE_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL); - if (!skb) { - ret_val = 6; - goto err_nomem; - } - skb_reserve(skb, NET_IP_ALIGN); - rx_ring->rx_buffer_info[i].skb = skb; - rx_ring->rx_buffer_info[i].dma = - dma_map_single(&pdev->dev, skb->data, - IXGBE_RXBUFFER_2048, DMA_FROM_DEVICE); - rx_desc->read.pkt_addr = - cpu_to_le64(rx_ring->rx_buffer_info[i].dma); - memset(skb->data, 0x00, skb->len); - } - return 0; err_nomem: @@ -1692,16 +1527,21 @@ static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter) u32 reg_data; /* right now we only support MAC loopback in the driver */ - - /* Setup MAC loopback */ reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0); + /* Setup MAC loopback */ reg_data |= IXGBE_HLREG0_LPBK; IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data); + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); + reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data); + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_AUTOC); reg_data &= ~IXGBE_AUTOC_LMS_MASK; reg_data |= IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU; IXGBE_WRITE_REG(&adapter->hw, IXGBE_AUTOC, reg_data); + IXGBE_WRITE_FLUSH(&adapter->hw); + msleep(10); /* Disable Atlas Tx lanes; re-enabled in reset path */ if (hw->mac.type == ixgbe_mac_82598EB) { @@ -1759,15 +1599,81 @@ static int ixgbe_check_lbtest_frame(struct sk_buff *skb, return 13; } +static u16 ixgbe_clean_test_rings(struct ixgbe_adapter *adapter, + struct ixgbe_ring *rx_ring, + struct ixgbe_ring *tx_ring, + unsigned int size) +{ + union ixgbe_adv_rx_desc *rx_desc; + struct ixgbe_rx_buffer *rx_buffer_info; + struct ixgbe_tx_buffer *tx_buffer_info; + const int bufsz = rx_ring->rx_buf_len; + u32 staterr; + u16 rx_ntc, tx_ntc, count = 0; + + /* initialize next to clean and descriptor values */ + rx_ntc = rx_ring->next_to_clean; + tx_ntc = tx_ring->next_to_clean; + rx_desc = IXGBE_RX_DESC_ADV(rx_ring, rx_ntc); + staterr = le32_to_cpu(rx_desc->wb.upper.status_error); + + while (staterr & IXGBE_RXD_STAT_DD) { + /* check Rx buffer */ + rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc]; + + /* unmap Rx buffer, will be remapped by alloc_rx_buffers */ + dma_unmap_single(&adapter->pdev->dev, + rx_buffer_info->dma, + bufsz, + DMA_FROM_DEVICE); + rx_buffer_info->dma = 0; + + /* verify contents of skb */ + if (!ixgbe_check_lbtest_frame(rx_buffer_info->skb, size)) + count++; + + /* unmap buffer on Tx side */ + tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc]; + ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info); + + /* increment Rx/Tx next to clean counters */ + rx_ntc++; + if (rx_ntc == rx_ring->count) + rx_ntc = 0; + tx_ntc++; + if (tx_ntc == tx_ring->count) + tx_ntc = 0; + + /* fetch next descriptor */ + rx_desc = IXGBE_RX_DESC_ADV(rx_ring, rx_ntc); + staterr = le32_to_cpu(rx_desc->wb.upper.status_error); + } + + /* re-map buffers to ring, store next to clean values */ + ixgbe_alloc_rx_buffers(adapter, rx_ring, count); + rx_ring->next_to_clean = rx_ntc; + tx_ring->next_to_clean = tx_ntc; + + return count; +} + static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter) { struct ixgbe_ring *tx_ring = &adapter->test_tx_ring; struct ixgbe_ring *rx_ring = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - int i, j, k, l, lc, good_cnt, ret_val = 0; - unsigned long time; + int i, j, lc, good_cnt, ret_val = 0; + unsigned int size = 1024; + netdev_tx_t tx_ret_val; + struct sk_buff *skb; + + /* allocate test skb */ + skb = alloc_skb(size, GFP_KERNEL); + if (!skb) + return 11; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), rx_ring->count - 1); + /* place data into test skb */ + ixgbe_create_lbtest_frame(skb, size); + skb_put(skb, size); /* * Calculate the loop count based on the largest descriptor ring @@ -1780,54 +1686,40 @@ static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter) else lc = ((rx_ring->count / 64) * 2) + 1; - k = l = 0; for (j = 0; j <= lc; j++) { - for (i = 0; i < 64; i++) { - ixgbe_create_lbtest_frame( - tx_ring->tx_buffer_info[k].skb, - 1024); - dma_sync_single_for_device(&pdev->dev, - tx_ring->tx_buffer_info[k].dma, - tx_ring->tx_buffer_info[k].length, - DMA_TO_DEVICE); - if (unlikely(++k == tx_ring->count)) - k = 0; - } - IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), k); - msleep(200); - /* set the start time for the receive */ - time = jiffies; + /* reset count of good packets */ good_cnt = 0; - do { - /* receive the sent packets */ - dma_sync_single_for_cpu(&pdev->dev, - rx_ring->rx_buffer_info[l].dma, - IXGBE_RXBUFFER_2048, - DMA_FROM_DEVICE); - ret_val = ixgbe_check_lbtest_frame( - rx_ring->rx_buffer_info[l].skb, 1024); - if (!ret_val) + + /* place 64 packets on the transmit queue*/ + for (i = 0; i < 64; i++) { + skb_get(skb); + tx_ret_val = ixgbe_xmit_frame_ring(skb, + adapter->netdev, + adapter, + tx_ring); + if (tx_ret_val == NETDEV_TX_OK) good_cnt++; - if (++l == rx_ring->count) - l = 0; - /* - * time + 20 msecs (200 msecs on 2.4) is more than - * enough time to complete the receives, if it's - * exceeded, break and error off - */ - } while (good_cnt < 64 && jiffies < (time + 20)); + } + if (good_cnt != 64) { - /* ret_val is the same as mis-compare */ - ret_val = 13; + ret_val = 12; break; } - if (jiffies >= (time + 20)) { - /* Error code for time out error */ - ret_val = 14; + + /* allow 200 milliseconds for packets to go from Tx to Rx */ + msleep(200); + + good_cnt = ixgbe_clean_test_rings(adapter, rx_ring, + tx_ring, size); + if (good_cnt != 64) { + ret_val = 13; break; } } + /* free the original skb */ + kfree_skb(skb); + return ret_val; } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 85ecf0e39b99..18163e312a39 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -601,9 +601,9 @@ static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter, } } -static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter, - struct ixgbe_tx_buffer - *tx_buffer_info) +void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter, + struct ixgbe_tx_buffer + *tx_buffer_info) { if (tx_buffer_info->dma) { if (tx_buffer_info->mapped_as_page) @@ -1032,9 +1032,9 @@ static inline void ixgbe_release_rx_desc(struct ixgbe_hw *hw, * ixgbe_alloc_rx_buffers - Replace used receive buffers; packet split * @adapter: address of board private structure **/ -static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring, - int cleaned_count) +void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, + struct ixgbe_ring *rx_ring, + int cleaned_count) { struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; @@ -1095,6 +1095,7 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, rx_desc->read.hdr_addr = cpu_to_le64(bi->dma); } else { rx_desc->read.pkt_addr = cpu_to_le64(bi->dma); + rx_desc->read.hdr_addr = 0; } i++; @@ -2431,8 +2432,8 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) * * Configure the Tx descriptor ring after a reset. **/ - static void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter, - struct ixgbe_ring *ring) +void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter, + struct ixgbe_ring *ring) { struct ixgbe_hw *hw = &adapter->hw; u64 tdba = ring->dma; @@ -2759,8 +2760,8 @@ static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter, } } -static void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter, - struct ixgbe_ring *ring) +void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter, + struct ixgbe_ring *ring) { struct ixgbe_hw *hw = &adapter->hw; u64 rdba = ring->dma; @@ -3671,8 +3672,11 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, unsigned long size; unsigned int i; - /* Free all the Rx ring sk_buffs */ + /* ring already cleared, nothing to do */ + if (!rx_ring->rx_buffer_info) + return; + /* Free all the Rx ring sk_buffs */ for (i = 0; i < rx_ring->count; i++) { struct ixgbe_rx_buffer *rx_buffer_info; @@ -3739,8 +3743,11 @@ static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter, unsigned long size; unsigned int i; - /* Free all the Tx ring sk_buffs */ + /* ring already cleared, nothing to do */ + if (!tx_ring->tx_buffer_info) + return; + /* Free all the Tx ring sk_buffs */ for (i = 0; i < tx_ring->count; i++) { tx_buffer_info = &tx_ring->tx_buffer_info[i]; ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info); @@ -6239,11 +6246,10 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb) return skb_tx_hash(dev, skb); } -static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) +netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev, + struct ixgbe_adapter *adapter, + struct ixgbe_ring *tx_ring) { - struct ixgbe_adapter *adapter = netdev_priv(netdev); - struct ixgbe_ring *tx_ring; struct netdev_queue *txq; unsigned int first; unsigned int tx_flags = 0; @@ -6267,8 +6273,6 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, tx_flags |= IXGBE_TX_FLAGS_VLAN; } - tx_ring = adapter->tx_ring[skb->queue_mapping]; - #ifdef IXGBE_FCOE /* for FCoE with DCB, we force the priority to what * was specified by the switch */ @@ -6362,6 +6366,15 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, return NETDEV_TX_OK; } +static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_ring *tx_ring; + + tx_ring = adapter->tx_ring[skb->queue_mapping]; + return ixgbe_xmit_frame_ring(skb, netdev, adapter, tx_ring); +} + /** * ixgbe_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure -- cgit v1.2.3-59-g8ed1b From f1bf7a5247a0f8e42025d19d732cbc70a57e6342 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Thu, 19 Aug 2010 05:08:22 +0000 Subject: qlcnic: fix inconsistent lock state Spin_lock(rds_ring->lock) is not required while posting buffers from qlcnic_open and freeing buffers from qlcnic_down. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_init.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 75ba744b173c..08da25895fad 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -136,8 +136,6 @@ void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter) for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; - spin_lock(&rds_ring->lock); - INIT_LIST_HEAD(&rds_ring->free_list); rx_buf = rds_ring->rx_buf_arr; @@ -146,8 +144,6 @@ void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter) &rds_ring->free_list); rx_buf++; } - - spin_unlock(&rds_ring->lock); } } @@ -1587,8 +1583,6 @@ qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid, int producer, count = 0; struct list_head *head; - spin_lock(&rds_ring->lock); - producer = rds_ring->producer; head = &rds_ring->free_list; @@ -1618,7 +1612,6 @@ qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid, writel((producer-1) & (rds_ring->num_desc-1), rds_ring->crb_rcv_producer); } - spin_unlock(&rds_ring->lock); } static void -- cgit v1.2.3-59-g8ed1b From 39895e07ca8ce13d8b38d00bf66236b93907c027 Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Thu, 19 Aug 2010 05:08:23 +0000 Subject: qlcnic: remove unused code Serial number references are not used in driver. Signed-off-by: Sony Chacko Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 1 - drivers/net/qlcnic/qlcnic_main.c | 19 ------------------- 2 files changed, 20 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index f6b887d409d5..5c549c5c2dd7 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -933,7 +933,6 @@ struct qlcnic_adapter { u8 max_rds_rings; u8 max_sds_rings; - u8 driver_mismatch; u8 msix_supported; u8 rx_csum; u8 portnum; diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 384cc52a9c3e..beadf2e41130 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -709,24 +709,8 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) { u32 fw_major, fw_minor, fw_build; char brd_name[QLCNIC_MAX_BOARD_NAME_LEN]; - char serial_num[32]; - int i, offset, val; - int *ptr32; struct pci_dev *pdev = adapter->pdev; struct qlcnic_info nic_info; - adapter->driver_mismatch = 0; - - ptr32 = (int *)&serial_num; - offset = QLCNIC_FW_SERIAL_NUM_OFFSET; - for (i = 0; i < 8; i++) { - if (qlcnic_rom_fast_read(adapter, offset, &val) == -1) { - dev_err(&pdev->dev, "error reading board info\n"); - adapter->driver_mismatch = 1; - return; - } - ptr32[i] = cpu_to_le32(val); - offset += sizeof(u32); - } fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR); fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR); @@ -1584,9 +1568,6 @@ static int qlcnic_open(struct net_device *netdev) struct qlcnic_adapter *adapter = netdev_priv(netdev); int err; - if (adapter->driver_mismatch) - return -EIO; - err = qlcnic_attach(adapter); if (err) return err; -- cgit v1.2.3-59-g8ed1b From 251b036a22f530aff26cf70f5cdb0cf64a072e46 Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Thu, 19 Aug 2010 05:08:24 +0000 Subject: qlcnic: replace magic numbers with defines Signed-off-by: Sony Chacko Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 1 + drivers/net/qlcnic/qlcnic_hdr.h | 4 ++++ drivers/net/qlcnic/qlcnic_init.c | 4 ++-- drivers/net/qlcnic/qlcnic_main.c | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 5c549c5c2dd7..d19836758c6e 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -148,6 +148,7 @@ #define DEFAULT_RCV_DESCRIPTORS_1G 2048 #define DEFAULT_RCV_DESCRIPTORS_10G 4096 +#define MAX_RDS_RINGS 2 #define get_next_index(index, length) \ (((index) + 1) & ((length) - 1)) diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h index bd346d9aac94..39db4df0f650 100644 --- a/drivers/net/qlcnic/qlcnic_hdr.h +++ b/drivers/net/qlcnic/qlcnic_hdr.h @@ -745,6 +745,10 @@ enum { #define FW_POLL_DELAY (1 * HZ) #define FW_FAIL_THRESH 2 +#define QLCNIC_RESET_TIMEOUT_SECS 10 +#define QLCNIC_INIT_TIMEOUT_SECS 30 + + #define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC))) #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 08da25895fad..90766757c314 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -553,12 +553,12 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) { } adapter->physical_port = (val >> 2); if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo)) - timeo = 30; + timeo = QLCNIC_INIT_TIMEOUT_SECS; adapter->dev_init_timeo = timeo; if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DRV_RESET_TIMEOUT, &timeo)) - timeo = 10; + timeo = QLCNIC_RESET_TIMEOUT_SECS; adapter->reset_ack_timeo = timeo; diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index beadf2e41130..c6f19c961c3d 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -754,7 +754,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) adapter->num_txd = MAX_CMD_DESCRIPTORS; - adapter->max_rds_rings = 2; + adapter->max_rds_rings = MAX_RDS_RINGS; } static int -- cgit v1.2.3-59-g8ed1b From 4e8acb011f0e9e86e29b53ff051e699ba0c5726d Mon Sep 17 00:00:00 2001 From: Rajesh Borundia Date: Thu, 19 Aug 2010 05:08:25 +0000 Subject: qlcnic: configure port on eswitch o Nic partition capable devices has embedded switch, this needs to support various features like external switch. Signed-off-by: Rajesh Borundia Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 22 +++-- drivers/net/qlcnic/qlcnic_ctx.c | 174 ++++++++++++++++++++++++++---------- drivers/net/qlcnic/qlcnic_hdr.h | 7 ++ drivers/net/qlcnic/qlcnic_main.c | 185 +++++++++++++++++++++------------------ 4 files changed, 254 insertions(+), 134 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index d19836758c6e..9433a05555f1 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -556,6 +556,7 @@ struct qlcnic_recv_context { #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026 #define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027 #define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028 +#define QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG 0x00000029 #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a #define QLCNIC_RCODE_SUCCESS 0 @@ -1044,7 +1045,7 @@ struct qlcnic_pci_info { }; struct qlcnic_npar_info { - u16 vlan_id; + u16 pvid; u16 min_bw; u16 max_bw; u8 phy_port; @@ -1052,11 +1053,13 @@ struct qlcnic_npar_info { u8 active; u8 enable_pm; u8 dest_npar; - u8 host_vlan_tag; - u8 promisc_mode; u8 discard_tagged; u8 mac_learning; + u8 mac_anti_spoof; + u8 promisc_mode; + u8 offload_flags; }; + struct qlcnic_eswitch { u8 port; u8 active_vports; @@ -1088,7 +1091,6 @@ struct qlcnic_eswitch { #define IS_VALID_BW(bw) (bw >= MIN_BW && bw <= MAX_BW) #define IS_VALID_TX_QUEUES(que) (que > 0 && que <= MAX_TX_QUEUES) #define IS_VALID_RX_QUEUES(que) (que > 0 && que <= MAX_RX_QUEUES) -#define IS_VALID_MODE(mode) (mode == 0 || mode == 1) struct qlcnic_pci_func_cfg { u16 func_type; @@ -1120,12 +1122,16 @@ struct qlcnic_pm_func_cfg { struct qlcnic_esw_func_cfg { u16 vlan_id; + u8 op_mode; + u8 op_type; u8 pci_func; u8 host_vlan_tag; u8 promisc_mode; u8 discard_tagged; u8 mac_learning; - u8 reserved; + u8 mac_anti_spoof; + u8 offload_flags; + u8 reserved[5]; }; #define QLCNIC_STATS_VERSION 1 @@ -1276,8 +1282,10 @@ int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *, u8, int qlcnic_get_eswitch_status(struct qlcnic_adapter *, u8, struct qlcnic_eswitch *); int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8); -int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8, - u8, u8, u16); +int qlcnic_config_switch_port(struct qlcnic_adapter *, + struct qlcnic_esw_func_cfg *); +int qlcnic_get_eswitch_port_config(struct qlcnic_adapter *, + struct qlcnic_esw_func_cfg *); int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8); int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8, struct __qlcnic_esw_statistics *); diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index 57c9b09bd16a..74ae3b0a5ea8 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c @@ -813,9 +813,8 @@ int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *adapter, u8 port, arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); eswitch->port = arg1 & 0xf; - eswitch->active_vports = LSB(arg2); - eswitch->max_ucast_filters = MSB(arg2); - eswitch->max_active_vlans = LSB(MSW(arg2)); + eswitch->max_ucast_filters = LSW(arg2); + eswitch->max_active_vlans = MSW(arg2) & 0xfff; if (arg1 & BIT_6) eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING; if (arg1 & BIT_7) @@ -943,47 +942,6 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, return err; } -/* Configure eSwitch port */ -int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id, - int vlan_tagging, u8 discard_tagged, u8 promsc_mode, - u8 mac_learn, u8 pci_func, u16 vlan_id) -{ - int err = -EIO; - u32 arg1; - struct qlcnic_eswitch *eswitch; - - if (adapter->op_mode != QLCNIC_MGMT_FUNC) - return err; - - eswitch = &adapter->eswitch[id]; - if (!(eswitch->flags & QLCNIC_SWITCH_ENABLE)) - return err; - - arg1 = eswitch->port | (discard_tagged ? BIT_4 : 0); - arg1 |= (promsc_mode ? BIT_6 : 0) | (mac_learn ? BIT_7 : 0); - arg1 |= pci_func << 8; - if (vlan_tagging) - arg1 |= BIT_5 | (vlan_id << 16); - - err = qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, - adapter->fw_hal_version, - arg1, - 0, - 0, - QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH); - - if (err != QLCNIC_RCODE_SUCCESS) { - dev_err(&adapter->pdev->dev, - "Failed to configure eswitch port%d\n", eswitch->port); - } else { - dev_info(&adapter->pdev->dev, - "Configured eSwitch for port %d\n", eswitch->port); - } - - return err; -} - int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) { @@ -1108,3 +1066,131 @@ err_ret: "rx_ctx=%d\n", func_esw, port, rx_tx); return -EIO; } + +static int +__qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, + u32 *arg1, u32 *arg2) +{ + int err = -EIO; + u8 pci_func; + pci_func = (*arg1 >> 8); + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + *arg1, + 0, + 0, + QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG); + + if (err == QLCNIC_RCODE_SUCCESS) { + *arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); + *arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); + dev_info(&adapter->pdev->dev, + "eSwitch port config for pci func%d\n", pci_func); + } else { + dev_err(&adapter->pdev->dev, + "Failed to get eswitch port config%d\n", pci_func); + } + return err; +} +/* Configure eSwitch port +op_mode = 0 for setting default port behavior +op_mode = 1 for setting vlan id +op_mode = 2 for deleting vlan id +op_type = 0 for vlan_id +op_type = 1 for port vlan_id +*/ +int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, + struct qlcnic_esw_func_cfg *esw_cfg) +{ + int err = -EIO; + u32 arg1, arg2 = 0; + u8 pci_func; + + if (adapter->op_mode != QLCNIC_MGMT_FUNC) + return err; + pci_func = esw_cfg->pci_func; + arg1 = (adapter->npars[pci_func].phy_port & BIT_0); + arg1 |= (pci_func << 8); + + if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) + return err; + arg1 &= ~(0x0ff << 8); + arg1 |= (pci_func << 8); + arg1 &= ~(BIT_2 | BIT_3); + switch (esw_cfg->op_mode) { + case QLCNIC_PORT_DEFAULTS: + arg1 |= (BIT_4 | BIT_6 | BIT_7); + arg2 |= (BIT_0 | BIT_1); + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) + arg2 |= (BIT_2 | BIT_3); + if (!(esw_cfg->discard_tagged)) + arg1 &= ~BIT_4; + if (!(esw_cfg->promisc_mode)) + arg1 &= ~BIT_6; + if (!(esw_cfg->mac_learning)) + arg1 &= ~BIT_7; + if (!(esw_cfg->mac_anti_spoof)) + arg2 &= ~BIT_0; + if (!(esw_cfg->offload_flags & BIT_0)) + arg2 &= ~(BIT_1 | BIT_2 | BIT_3); + if (!(esw_cfg->offload_flags & BIT_1)) + arg2 &= ~BIT_2; + if (!(esw_cfg->offload_flags & BIT_2)) + arg2 &= ~BIT_3; + break; + case QLCNIC_ADD_VLAN: + arg1 |= (BIT_2 | BIT_5); + arg1 |= (esw_cfg->vlan_id << 16); + break; + case QLCNIC_DEL_VLAN: + arg1 |= (BIT_3 | BIT_5); + arg1 &= ~(0x0ffff << 16); + default: + return err; + } + + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + arg1, + arg2, + 0, + QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH); + + if (err != QLCNIC_RCODE_SUCCESS) { + dev_err(&adapter->pdev->dev, + "Failed to configure eswitch port%d\n", pci_func); + } else { + dev_info(&adapter->pdev->dev, + "Configured eSwitch for port %d\n", pci_func); + } + + return err; +} + +int +qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, + struct qlcnic_esw_func_cfg *esw_cfg) +{ + u32 arg1, arg2; + u8 phy_port; + if (adapter->op_mode == QLCNIC_MGMT_FUNC) + phy_port = adapter->npars[esw_cfg->pci_func].phy_port; + else + phy_port = adapter->physical_port; + arg1 = phy_port; + arg1 |= (esw_cfg->pci_func << 8); + if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) + return -EIO; + + esw_cfg->discard_tagged = !!(arg1 & BIT_4); + esw_cfg->host_vlan_tag = !!(arg1 & BIT_5); + esw_cfg->promisc_mode = !!(arg1 & BIT_6); + esw_cfg->mac_learning = !!(arg1 & BIT_7); + esw_cfg->vlan_id = LSW(arg1 >> 16); + esw_cfg->mac_anti_spoof = (arg2 & 0x1); + esw_cfg->offload_flags = ((arg2 >> 1) & 0x7); + + return 0; +} diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h index 39db4df0f650..eae03b5b0323 100644 --- a/drivers/net/qlcnic/qlcnic_hdr.h +++ b/drivers/net/qlcnic/qlcnic_hdr.h @@ -775,6 +775,7 @@ struct qlcnic_legacy_intr_set { #define QLCNIC_DRV_OP_MODE 0x1b2170 #define QLCNIC_MSIX_BASE 0x132110 #define QLCNIC_MAX_PCI_FUNC 8 +#define QLCNIC_MAX_VLAN_FILTERS 64 /* PCI function operational mode */ enum { @@ -783,6 +784,12 @@ enum { QLCNIC_NON_PRIV_FUNC = 2 }; +enum { + QLCNIC_PORT_DEFAULTS = 0, + QLCNIC_ADD_VLAN = 1, + QLCNIC_DEL_VLAN = 2 +}; + #define QLC_DEV_DRV_DEFAULT 0x11111111 #define LSB(x) ((uint8_t)(x)) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index c6f19c961c3d..7bb32859b928 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -506,7 +506,6 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter) adapter->npars[pfn].active = pci_info[i].active; adapter->npars[pfn].type = pci_info[i].type; adapter->npars[pfn].phy_port = pci_info[i].default_port; - adapter->npars[pfn].mac_learning = DEFAULT_MAC_LEARN; adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw; adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw; } @@ -757,48 +756,65 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) adapter->max_rds_rings = MAX_RDS_RINGS; } +static int +qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter, + struct qlcnic_npar_info *npar, int pci_func) +{ + struct qlcnic_esw_func_cfg esw_cfg; + esw_cfg.op_mode = QLCNIC_PORT_DEFAULTS; + esw_cfg.pci_func = pci_func; + esw_cfg.vlan_id = npar->pvid; + esw_cfg.mac_learning = npar->mac_learning; + esw_cfg.discard_tagged = npar->discard_tagged; + esw_cfg.mac_anti_spoof = npar->mac_anti_spoof; + esw_cfg.offload_flags = npar->offload_flags; + esw_cfg.promisc_mode = npar->promisc_mode; + if (qlcnic_config_switch_port(adapter, &esw_cfg)) + return -EIO; + + esw_cfg.op_mode = QLCNIC_ADD_VLAN; + if (qlcnic_config_switch_port(adapter, &esw_cfg)) + return -EIO; + + return 0; +} + static int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) { - int i, err = 0; + int i, err; struct qlcnic_npar_info *npar; struct qlcnic_info nic_info; if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) || - !adapter->need_fw_reset) + !adapter->need_fw_reset || adapter->op_mode != QLCNIC_MGMT_FUNC) return 0; - if (adapter->op_mode == QLCNIC_MGMT_FUNC) { - /* Set the NPAR config data after FW reset */ - for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { - npar = &adapter->npars[i]; - if (npar->type != QLCNIC_TYPE_NIC) - continue; - err = qlcnic_get_nic_info(adapter, &nic_info, i); - if (err) - goto err_out; - nic_info.min_tx_bw = npar->min_bw; - nic_info.max_tx_bw = npar->max_bw; - err = qlcnic_set_nic_info(adapter, &nic_info); - if (err) - goto err_out; - - if (npar->enable_pm) { - err = qlcnic_config_port_mirroring(adapter, - npar->dest_npar, 1, i); - if (err) - goto err_out; + /* Set the NPAR config data after FW reset */ + for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { + npar = &adapter->npars[i]; + if (npar->type != QLCNIC_TYPE_NIC) + continue; + err = qlcnic_get_nic_info(adapter, &nic_info, i); + if (err) + return err; + nic_info.min_tx_bw = npar->min_bw; + nic_info.max_tx_bw = npar->max_bw; + err = qlcnic_set_nic_info(adapter, &nic_info); + if (err) + return err; - } - npar->mac_learning = DEFAULT_MAC_LEARN; - npar->host_vlan_tag = 0; - npar->promisc_mode = 0; - npar->discard_tagged = 0; - npar->vlan_id = 0; + if (npar->enable_pm) { + err = qlcnic_config_port_mirroring(adapter, + npar->dest_npar, 1, i); + if (err) + return err; } + err = qlcnic_reset_eswitch_config(adapter, npar, i); + if (err) + return err; } -err_out: - return err; + return 0; } static int @@ -863,12 +879,10 @@ wait_init: QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); qlcnic_idc_debug_info(adapter, 1); - - qlcnic_check_options(adapter); if (qlcnic_reset_npar_config(adapter)) goto err_out; qlcnic_dev_set_npar_ready(adapter); - + qlcnic_check_options(adapter); adapter->need_fw_reset = 0; qlcnic_release_firmware(adapter); @@ -3082,9 +3096,6 @@ validate_pm_config(struct qlcnic_adapter *adapter, if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC) return QL_STATUS_INVALID_PARAM; - if (!IS_VALID_MODE(pm_cfg[i].action)) - return QL_STATUS_INVALID_PARAM; - s_esw_id = adapter->npars[src_pci_func].phy_port; d_esw_id = adapter->npars[dest_pci_func].phy_port; @@ -3118,7 +3129,7 @@ qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj, return ret; for (i = 0; i < count; i++) { pci_func = pm_cfg[i].pci_func; - action = pm_cfg[i].action; + action = !!pm_cfg[i].action; id = adapter->npars[pci_func].phy_port; ret = qlcnic_config_port_mirroring(adapter, id, action, pci_func); @@ -3129,7 +3140,7 @@ qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj, for (i = 0; i < count; i++) { pci_func = pm_cfg[i].pci_func; id = adapter->npars[pci_func].phy_port; - adapter->npars[pci_func].enable_pm = pm_cfg[i].action; + adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action; adapter->npars[pci_func].dest_npar = id; } return size; @@ -3161,30 +3172,38 @@ qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj, static int validate_esw_config(struct qlcnic_adapter *adapter, - struct qlcnic_esw_func_cfg *esw_cfg, int count) + struct qlcnic_esw_func_cfg *esw_cfg, int count) { u8 pci_func; int i; - for (i = 0; i < count; i++) { pci_func = esw_cfg[i].pci_func; if (pci_func >= QLCNIC_MAX_PCI_FUNC) return QL_STATUS_INVALID_PARAM; - if (adapter->npars[i].type != QLCNIC_TYPE_NIC) - return QL_STATUS_INVALID_PARAM; + if (adapter->op_mode == QLCNIC_MGMT_FUNC) + if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) + return QL_STATUS_INVALID_PARAM; - if (esw_cfg->host_vlan_tag == 1) + switch (esw_cfg[i].op_mode) { + case QLCNIC_PORT_DEFAULTS: + break; + case QLCNIC_ADD_VLAN: if (!IS_VALID_VLAN(esw_cfg[i].vlan_id)) return QL_STATUS_INVALID_PARAM; - - if (!IS_VALID_MODE(esw_cfg[i].promisc_mode) - || !IS_VALID_MODE(esw_cfg[i].host_vlan_tag) - || !IS_VALID_MODE(esw_cfg[i].mac_learning) - || !IS_VALID_MODE(esw_cfg[i].discard_tagged)) + if (!esw_cfg[i].op_type) + return QL_STATUS_INVALID_PARAM; + break; + case QLCNIC_DEL_VLAN: + if (!IS_VALID_VLAN(esw_cfg[i].vlan_id)) + return QL_STATUS_INVALID_PARAM; + if (!esw_cfg[i].op_type) + return QL_STATUS_INVALID_PARAM; + break; + default: return QL_STATUS_INVALID_PARAM; + } } - return 0; } @@ -3195,8 +3214,9 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, struct device *dev = container_of(kobj, struct device, kobj); struct qlcnic_adapter *adapter = dev_get_drvdata(dev); struct qlcnic_esw_func_cfg *esw_cfg; + struct qlcnic_npar_info *npar; int count, rem, i, ret; - u8 id, pci_func; + u8 pci_func; count = size / sizeof(struct qlcnic_esw_func_cfg); rem = size % sizeof(struct qlcnic_esw_func_cfg); @@ -3209,28 +3229,28 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, return ret; for (i = 0; i < count; i++) { - pci_func = esw_cfg[i].pci_func; - id = adapter->npars[pci_func].phy_port; - ret = qlcnic_config_switch_port(adapter, id, - esw_cfg[i].host_vlan_tag, - esw_cfg[i].discard_tagged, - esw_cfg[i].promisc_mode, - esw_cfg[i].mac_learning, - esw_cfg[i].pci_func, - esw_cfg[i].vlan_id); - if (ret) - return ret; + if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) + return QL_STATUS_INVALID_PARAM; } for (i = 0; i < count; i++) { pci_func = esw_cfg[i].pci_func; - adapter->npars[pci_func].promisc_mode = esw_cfg[i].promisc_mode; - adapter->npars[pci_func].mac_learning = esw_cfg[i].mac_learning; - adapter->npars[pci_func].vlan_id = esw_cfg[i].vlan_id; - adapter->npars[pci_func].discard_tagged = - esw_cfg[i].discard_tagged; - adapter->npars[pci_func].host_vlan_tag = - esw_cfg[i].host_vlan_tag; + npar = &adapter->npars[pci_func]; + switch (esw_cfg[i].op_mode) { + case QLCNIC_PORT_DEFAULTS: + npar->promisc_mode = esw_cfg[i].promisc_mode; + npar->mac_learning = esw_cfg[i].mac_learning; + npar->offload_flags = esw_cfg[i].offload_flags; + npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof; + npar->discard_tagged = esw_cfg[i].discard_tagged; + break; + case QLCNIC_ADD_VLAN: + npar->pvid = esw_cfg[i].vlan_id; + break; + case QLCNIC_DEL_VLAN: + npar->pvid = 0; + break; + } } return size; @@ -3243,7 +3263,7 @@ qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj, struct device *dev = container_of(kobj, struct device, kobj); struct qlcnic_adapter *adapter = dev_get_drvdata(dev); struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC]; - int i; + u8 i; if (size != sizeof(esw_cfg)) return QL_STATUS_INVALID_PARAM; @@ -3251,12 +3271,9 @@ qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj, for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { if (adapter->npars[i].type != QLCNIC_TYPE_NIC) continue; - - esw_cfg[i].host_vlan_tag = adapter->npars[i].host_vlan_tag; - esw_cfg[i].promisc_mode = adapter->npars[i].promisc_mode; - esw_cfg[i].discard_tagged = adapter->npars[i].discard_tagged; - esw_cfg[i].vlan_id = adapter->npars[i].vlan_id; - esw_cfg[i].mac_learning = adapter->npars[i].mac_learning; + esw_cfg[i].pci_func = i; + if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i])) + return QL_STATUS_INVALID_PARAM; } memcpy(buf, &esw_cfg, size); @@ -3580,15 +3597,16 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) dev_info(dev, "failed to create crb sysfs entry\n"); if (device_create_bin_file(dev, &bin_attr_mem)) dev_info(dev, "failed to create mem sysfs entry\n"); - if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) || - adapter->op_mode != QLCNIC_MGMT_FUNC) + if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) + return; + if (device_create_bin_file(dev, &bin_attr_esw_config)) + dev_info(dev, "failed to create esw config sysfs entry"); + if (adapter->op_mode != QLCNIC_MGMT_FUNC) return; if (device_create_bin_file(dev, &bin_attr_pci_config)) dev_info(dev, "failed to create pci config sysfs entry"); if (device_create_bin_file(dev, &bin_attr_npar_config)) dev_info(dev, "failed to create npar config sysfs entry"); - if (device_create_bin_file(dev, &bin_attr_esw_config)) - dev_info(dev, "failed to create esw config sysfs entry"); if (device_create_bin_file(dev, &bin_attr_pm_config)) dev_info(dev, "failed to create pm config sysfs entry"); if (device_create_bin_file(dev, &bin_attr_esw_stats)) @@ -3607,12 +3625,13 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) device_remove_file(dev, &dev_attr_diag_mode); device_remove_bin_file(dev, &bin_attr_crb); device_remove_bin_file(dev, &bin_attr_mem); - if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) || - adapter->op_mode != QLCNIC_MGMT_FUNC) + if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) + return; + device_remove_bin_file(dev, &bin_attr_esw_config); + if (adapter->op_mode != QLCNIC_MGMT_FUNC) return; device_remove_bin_file(dev, &bin_attr_pci_config); device_remove_bin_file(dev, &bin_attr_npar_config); - device_remove_bin_file(dev, &bin_attr_esw_config); device_remove_bin_file(dev, &bin_attr_pm_config); device_remove_bin_file(dev, &bin_attr_esw_stats); } -- cgit v1.2.3-59-g8ed1b From 0325d69b2a1feb72f11413dbfcc1705ccfc203c1 Mon Sep 17 00:00:00 2001 From: Rajesh Borundia Date: Thu, 19 Aug 2010 05:08:26 +0000 Subject: qlcnic: configure offload setting on eswitch Device is not capable of enabling/disabling offload setting per port in case of Nic Partition.So offload settings needs to be enabled/disabled per eswitch and it will affect all the function on that eswitch. Signed-off-by: Rajesh Borundia Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_ethtool.c | 18 +++++- drivers/net/qlcnic/qlcnic_main.c | 121 ++++++++++++++++++++++++++++++++++-- 2 files changed, 133 insertions(+), 6 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index e38fc3d96d43..2805f88aaf7c 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -804,6 +804,20 @@ qlcnic_get_ethtool_stats(struct net_device *dev, } } +static int qlcnic_set_tx_csum(struct net_device *dev, u32 data) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + + if ((adapter->flags & QLCNIC_ESWITCH_ENABLED)) + return -EOPNOTSUPP; + if (data) + dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + else + dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + + return 0; + +} static u32 qlcnic_get_tx_csum(struct net_device *dev) { return dev->features & NETIF_F_IP_CSUM; @@ -819,6 +833,8 @@ static int qlcnic_set_rx_csum(struct net_device *dev, u32 data) { struct qlcnic_adapter *adapter = netdev_priv(dev); + if ((adapter->flags & QLCNIC_ESWITCH_ENABLED)) + return -EOPNOTSUPP; if (!!data) { adapter->rx_csum = !!data; return 0; @@ -1070,7 +1086,7 @@ const struct ethtool_ops qlcnic_ethtool_ops = { .get_pauseparam = qlcnic_get_pauseparam, .set_pauseparam = qlcnic_set_pauseparam, .get_tx_csum = qlcnic_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, + .set_tx_csum = qlcnic_set_tx_csum, .set_sg = ethtool_op_set_sg, .get_tso = qlcnic_get_tso, .set_tso = qlcnic_set_tso, diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 7bb32859b928..aa1f6b3c3b80 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -110,6 +110,8 @@ static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *); static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); static int qlcnicvf_start_firmware(struct qlcnic_adapter *); +static void qlcnic_set_netdev_features(struct qlcnic_adapter *, + struct qlcnic_esw_func_cfg *); /* PCI Device ID Table */ #define ENTRY(device) \ {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ @@ -756,6 +758,98 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) adapter->max_rds_rings = MAX_RDS_RINGS; } +static void +qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, + struct qlcnic_esw_func_cfg *esw_cfg) +{ + qlcnic_set_netdev_features(adapter, esw_cfg); +} + +static int +qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) +{ + struct qlcnic_esw_func_cfg esw_cfg; + + if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) + return 0; + + esw_cfg.pci_func = adapter->ahw.pci_func; + if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg)) + return -EIO; + qlcnic_set_eswitch_port_features(adapter, &esw_cfg); + + return 0; +} + +static void +qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, + struct qlcnic_esw_func_cfg *esw_cfg) +{ + struct net_device *netdev = adapter->netdev; + unsigned long features, vlan_features; + + features = (NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | NETIF_F_GRO); + vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM); + + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) { + features |= (NETIF_F_TSO | NETIF_F_TSO6); + vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6); + } + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) + features |= NETIF_F_LRO; + + if (esw_cfg->offload_flags & BIT_0) { + netdev->features |= features; + adapter->rx_csum = 1; + if (!(esw_cfg->offload_flags & BIT_1)) + netdev->features &= ~NETIF_F_TSO; + if (!(esw_cfg->offload_flags & BIT_2)) + netdev->features &= ~NETIF_F_TSO6; + } else { + netdev->features &= ~features; + adapter->rx_csum = 0; + } + + netdev->vlan_features = (features & vlan_features); +} + +static int +qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) +{ + struct qlcnic_esw_func_cfg esw_cfg; + struct qlcnic_npar_info *npar; + u8 i; + + if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) || + adapter->need_fw_reset || + adapter->op_mode != QLCNIC_MGMT_FUNC) + return 0; + + for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { + if (adapter->npars[i].type != QLCNIC_TYPE_NIC) + continue; + memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg)); + esw_cfg.pci_func = i; + esw_cfg.offload_flags = BIT_0; + esw_cfg.mac_learning = BIT_0; + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) + esw_cfg.offload_flags |= (BIT_1 | BIT_2); + if (qlcnic_config_switch_port(adapter, &esw_cfg)) + return -EIO; + npar = &adapter->npars[i]; + npar->pvid = esw_cfg.vlan_id; + npar->mac_learning = esw_cfg.offload_flags; + npar->mac_anti_spoof = esw_cfg.mac_anti_spoof; + npar->discard_tagged = esw_cfg.discard_tagged; + npar->promisc_mode = esw_cfg.promisc_mode; + npar->offload_flags = esw_cfg.offload_flags; + } + + return 0; +} + static int qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter, struct qlcnic_npar_info *npar, int pci_func) @@ -879,6 +973,8 @@ wait_init: QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); qlcnic_idc_debug_info(adapter, 1); + if (qlcnic_set_default_offload_settings(adapter)) + goto err_out; if (qlcnic_reset_npar_config(adapter)) goto err_out; qlcnic_dev_set_npar_ready(adapter); @@ -974,6 +1070,8 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) return 0; + if (qlcnic_set_eswitch_port_config(adapter)) + return -EIO; if (qlcnic_fw_create_ctx(adapter)) return -EIO; @@ -1291,7 +1389,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) netdev->features |= NETIF_F_LRO; - netdev->irq = adapter->msix_entries[0].vector; if (qlcnic_read_mac_addr(adapter)) @@ -3216,7 +3313,7 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, struct qlcnic_esw_func_cfg *esw_cfg; struct qlcnic_npar_info *npar; int count, rem, i, ret; - u8 pci_func; + u8 pci_func, op_mode = 0; count = size / sizeof(struct qlcnic_esw_func_cfg); rem = size % sizeof(struct qlcnic_esw_func_cfg); @@ -3229,10 +3326,24 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, return ret; for (i = 0; i < count; i++) { - if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) - return QL_STATUS_INVALID_PARAM; + if (adapter->op_mode == QLCNIC_MGMT_FUNC) + if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) + return QL_STATUS_INVALID_PARAM; + if (adapter->ahw.pci_func == esw_cfg[i].pci_func) + op_mode = esw_cfg[i].op_mode; + qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]); + esw_cfg[i].op_mode = op_mode; + esw_cfg[i].pci_func = adapter->ahw.pci_func; + switch (esw_cfg[i].op_mode) { + case QLCNIC_PORT_DEFAULTS: + qlcnic_set_eswitch_port_features(adapter, + &esw_cfg[i]); + break; + } } + if (adapter->op_mode != QLCNIC_MGMT_FUNC) + goto out; for (i = 0; i < count; i++) { pci_func = esw_cfg[i].pci_func; npar = &adapter->npars[pci_func]; @@ -3252,7 +3363,7 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, break; } } - +out: return size; } -- cgit v1.2.3-59-g8ed1b From fe4d434da8e96142e36eb22fc5cf29ef2c2df9c2 Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Thu, 19 Aug 2010 05:08:27 +0000 Subject: qlcnic: support anti mac spoofing Administrator can configure to drop packet in transmit, if it doesn't match interface mac address, in case of virtual function. Signed-off-by: Sony Chacko Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 1 + drivers/net/qlcnic/qlcnic_main.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 9433a05555f1..b58c4119f279 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -900,6 +900,7 @@ struct qlcnic_mac_req { #define QLCNIC_BRIDGE_ENABLED 0X10 #define QLCNIC_DIAG_ENABLED 0x20 #define QLCNIC_ESWITCH_ENABLED 0x40 +#define QLCNIC_MACSPOOF 0x200 #define QLCNIC_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index aa1f6b3c3b80..de4be00e31e5 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -762,6 +762,11 @@ static void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, struct qlcnic_esw_func_cfg *esw_cfg) { + adapter->flags &= ~QLCNIC_MACSPOOF; + if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) + if (esw_cfg->mac_anti_spoof) + adapter->flags |= QLCNIC_MACSPOOF; + qlcnic_set_netdev_features(adapter, esw_cfg); } @@ -1912,6 +1917,12 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_BUSY; } + if (adapter->flags & QLCNIC_MACSPOOF) { + if (compare_ether_addr(eth_hdr(skb)->h_source, + adapter->mac_addr)) + goto drop_packet; + } + frag_count = skb_shinfo(skb)->nr_frags + 1; /* 4 fragments per cmd des */ -- cgit v1.2.3-59-g8ed1b From 78f84e1a7028a77b72aebc769642a5e93d32b4f9 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Thu, 19 Aug 2010 05:08:28 +0000 Subject: qlcnic: fix npar state Privilege functions should wait for npar state to be operational. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 43 +++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index de4be00e31e5..6a8e9702c7b7 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -916,6 +916,27 @@ qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) return 0; } +static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter) +{ + u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO; + u32 npar_state; + + if (adapter->op_mode == QLCNIC_MGMT_FUNC) + return 0; + + npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); + while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) { + msleep(1000); + npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); + } + if (!npar_opt_timeo) { + dev_err(&adapter->pdev->dev, + "Waiting for NPAR state to opertional timeout\n"); + return -EIO; + } + return 0; +} + static int qlcnic_start_firmware(struct qlcnic_adapter *adapter) { @@ -978,6 +999,11 @@ wait_init: QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); qlcnic_idc_debug_info(adapter, 1); + err = qlcnic_check_npar_opertional(adapter); + if (err) { + qlcnic_release_firmware(adapter); + return err; + } if (qlcnic_set_default_offload_settings(adapter)) goto err_out; if (qlcnic_reset_npar_config(adapter)) @@ -2919,29 +2945,18 @@ static void qlcnic_io_resume(struct pci_dev *pdev) FW_POLL_DELAY); } - static int qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) { int err; - u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO; - u32 npar_state; err = qlcnic_can_start_firmware(adapter); if (err) return err; - npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); - while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) { - msleep(1000); - npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); - } - - if (!npar_opt_timeo) { - dev_err(&adapter->pdev->dev, - "Waiting for NPAR state to opertional timeout\n"); - return -EIO; - } + err = qlcnic_check_npar_opertional(adapter); + if (err) + return err; qlcnic_check_options(adapter); -- cgit v1.2.3-59-g8ed1b From 21854f029da525b5bef1dbd63c622e16a2eb2f90 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Thu, 19 Aug 2010 05:08:29 +0000 Subject: qlcnic: mark device state as failed Mark device state failed in error path. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 6a8e9702c7b7..6e246c819204 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -94,7 +94,7 @@ static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter); static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding); -static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter); +static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8); static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); static irqreturn_t qlcnic_tmp_intr(int irq, void *data); @@ -1561,7 +1561,7 @@ err_out_disable_msi: qlcnic_teardown_intr(adapter); err_out_decr_ref: - qlcnic_clr_all_drv_state(adapter); + qlcnic_clr_all_drv_state(adapter, 0); err_out_iounmap: qlcnic_cleanup_pci_map(adapter); @@ -1600,7 +1600,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev) if (adapter->eswitch != NULL) kfree(adapter->eswitch); - qlcnic_clr_all_drv_state(adapter); + qlcnic_clr_all_drv_state(adapter, 0); clear_bit(__QLCNIC_RESETTING, &adapter->state); @@ -1632,7 +1632,7 @@ static int __qlcnic_shutdown(struct pci_dev *pdev) if (netif_running(netdev)) qlcnic_down(adapter, netdev); - qlcnic_clr_all_drv_state(adapter); + qlcnic_clr_all_drv_state(adapter, 0); clear_bit(__QLCNIC_RESETTING, &adapter->state); @@ -2379,7 +2379,7 @@ qlcnic_clr_drv_state(struct qlcnic_adapter *adapter) } static void -qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter) +qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed) { u32 val; @@ -2390,7 +2390,11 @@ qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter) QLC_DEV_CLR_REF_CNT(val, adapter->portnum); QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val); - if (!(val & 0x11111111)) + if (failed) { + QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED); + dev_info(&adapter->pdev->dev, + "Device state set to Failed. Please Reboot\n"); + } else if (!(val & 0x11111111)) QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_COLD); val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); @@ -2605,7 +2609,7 @@ err_ret: dev_err(&adapter->pdev->dev, "Fwinit work failed state=%u " "fw_wait_cnt=%u\n", dev_state, adapter->fw_wait_cnt); netif_device_attach(adapter->netdev); - qlcnic_clr_all_drv_state(adapter); + qlcnic_clr_all_drv_state(adapter, 0); } static void @@ -2641,8 +2645,7 @@ err_ret: dev_err(&adapter->pdev->dev, "detach failed; status=%d temp=%d\n", status, adapter->temp); netif_device_attach(netdev); - qlcnic_clr_all_drv_state(adapter); - + qlcnic_clr_all_drv_state(adapter, 1); } /*Transit NPAR state to NON Operational */ @@ -2879,7 +2882,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev) if (netif_running(netdev)) { err = qlcnic_attach(adapter); if (err) { - qlcnic_clr_all_drv_state(adapter); + qlcnic_clr_all_drv_state(adapter, 1); clear_bit(__QLCNIC_AER, &adapter->state); netif_device_attach(netdev); return err; -- cgit v1.2.3-59-g8ed1b From 63e74e9cb7944b073c49159db934f69ca98a4ae6 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Thu, 19 Aug 2010 05:08:30 +0000 Subject: qlcnic: fix endiness in eswitch statistics Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_ctx.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index 74ae3b0a5ea8..315705b22be2 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c @@ -946,6 +946,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) { size_t stats_size = sizeof(struct __qlcnic_esw_statistics); + struct __qlcnic_esw_statistics *stats; dma_addr_t stats_dma_t; void *stats_addr; u32 arg1; @@ -980,8 +981,21 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, LSD(stats_dma_t), QLCNIC_CDRP_CMD_GET_ESWITCH_STATS); - if (!err) - memcpy(esw_stats, stats_addr, stats_size); + if (!err) { + stats = (struct __qlcnic_esw_statistics *)stats_addr; + esw_stats->context_id = le16_to_cpu(stats->context_id); + esw_stats->version = le16_to_cpu(stats->version); + esw_stats->size = le16_to_cpu(stats->size); + esw_stats->multicast_frames = + le64_to_cpu(stats->multicast_frames); + esw_stats->broadcast_frames = + le64_to_cpu(stats->broadcast_frames); + esw_stats->unicast_frames = le64_to_cpu(stats->unicast_frames); + esw_stats->dropped_frames = le64_to_cpu(stats->dropped_frames); + esw_stats->local_frames = le64_to_cpu(stats->local_frames); + esw_stats->errors = le64_to_cpu(stats->errors); + esw_stats->numbytes = le64_to_cpu(stats->numbytes); + } pci_free_consistent(adapter->pdev, stats_size, stats_addr, stats_dma_t); -- cgit v1.2.3-59-g8ed1b From d4066833bb1b35fefb1dd45eb2b10659d46bf151 Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Thu, 19 Aug 2010 05:08:31 +0000 Subject: qlcnic: firmware initialization update Cleanup legacy code which is not valid for Qlogic CNA adapters. Signed-off-by: Sony Chacko Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 4 +- drivers/net/qlcnic/qlcnic_hdr.h | 3 +- drivers/net/qlcnic/qlcnic_init.c | 133 ++++++++++----------------------------- drivers/net/qlcnic/qlcnic_main.c | 38 +++-------- 4 files changed, 47 insertions(+), 131 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index b58c4119f279..43cb925fd77b 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -54,6 +54,8 @@ #define _QLCNIC_LINUX_SUBVERSION 7 #define QLCNIC_LINUX_VERSIONID "5.0.7" #define QLCNIC_DRV_IDC_VER 0x01 +#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ + (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) #define QLCNIC_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) #define _major(v) (((v) >> 24) & 0xff) @@ -1233,7 +1235,7 @@ void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter); void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter); void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter); -int qlcnic_init_firmware(struct qlcnic_adapter *adapter); +int qlcnic_check_fw_status(struct qlcnic_adapter *adapter); void qlcnic_watchdog_task(struct work_struct *work); void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid, struct qlcnic_host_rds_ring *rds_ring); diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h index eae03b5b0323..794f6572e8fd 100644 --- a/drivers/net/qlcnic/qlcnic_hdr.h +++ b/drivers/net/qlcnic/qlcnic_hdr.h @@ -747,7 +747,8 @@ enum { #define QLCNIC_RESET_TIMEOUT_SECS 10 #define QLCNIC_INIT_TIMEOUT_SECS 30 - +#define QLCNIC_HEARTBEAT_PERIOD_MSECS 200 +#define QLCNIC_HEARTBEAT_RETRY_COUNT 30 #define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC))) #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 90766757c314..e7a399f90326 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -435,11 +435,14 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter) u32 off; struct pci_dev *pdev = adapter->pdev; - /* resetall */ + QLCWR32(adapter, CRB_CMDPEG_STATE, 0); + QLCWR32(adapter, CRB_RCVPEG_STATE, 0); + qlcnic_rom_lock(adapter); QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff); qlcnic_rom_unlock(adapter); + /* Init HW CRB block */ if (qlcnic_rom_fast_read(adapter, 0, &n) != 0 || (n != 0xcafecafe) || qlcnic_rom_fast_read(adapter, 4, &n) != 0) { dev_err(&pdev->dev, "ERROR Reading crb_init area: val:%x\n", n); @@ -520,13 +523,10 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter) } kfree(buf); - /* p2dn replyCount */ + /* Initialize protocol process engine */ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0xec, 0x1e); - /* disable_peg_cache 0 & 1*/ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0x4c, 8); QLCWR32(adapter, QLCNIC_CRB_PEG_NET_I + 0x4c, 8); - - /* peg_clr_all */ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x8, 0); QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0xc, 0); QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x8, 0); @@ -535,9 +535,35 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter) QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0xc, 0); QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x8, 0); QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0xc, 0); + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x8, 0); + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0xc, 0); + msleep(1); + QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0); + QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0); return 0; } +int +qlcnic_check_fw_status(struct qlcnic_adapter *adapter) +{ + u32 heartbit, ret = -EIO; + int retries = QLCNIC_HEARTBEAT_RETRY_COUNT; + + adapter->heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); + do { + msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS); + heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); + if (heartbit != adapter->heartbit) { + /* Complete firmware handshake */ + QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); + ret = QLCNIC_RCODE_SUCCESS; + break; + } + } while (--retries); + + return ret; +} + int qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) { @@ -905,35 +931,12 @@ qlcnic_get_bios_version(struct qlcnic_adapter *adapter) int qlcnic_need_fw_reset(struct qlcnic_adapter *adapter) { - u32 count, old_count; u32 val, version, major, minor, build; - int i, timeout; if (adapter->need_fw_reset) return 1; - /* last attempt had failed */ - if (QLCRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED) - return 1; - - old_count = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); - - for (i = 0; i < 10; i++) { - - timeout = msleep_interruptible(200); - if (timeout) { - QLCWR32(adapter, CRB_CMDPEG_STATE, - PHAN_INITIALIZE_FAILED); - return -EINTR; - } - - count = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); - if (count != old_count) - break; - } - - /* firmware is dead */ - if (count == old_count) + if (qlcnic_check_fw_status(adapter)) return 1; /* check if we have got newer or different file firmware */ @@ -1158,78 +1161,6 @@ qlcnic_release_firmware(struct qlcnic_adapter *adapter) adapter->fw = NULL; } -static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter) -{ - u32 val; - int retries = 60; - - do { - val = QLCRD32(adapter, CRB_CMDPEG_STATE); - - switch (val) { - case PHAN_INITIALIZE_COMPLETE: - case PHAN_INITIALIZE_ACK: - return 0; - case PHAN_INITIALIZE_FAILED: - goto out_err; - default: - break; - } - - msleep(500); - - } while (--retries); - - QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED); - -out_err: - dev_err(&adapter->pdev->dev, "Command Peg initialization not " - "complete, state: 0x%x.\n", val); - return -EIO; -} - -static int -qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter) -{ - u32 val; - int retries = 2000; - - do { - val = QLCRD32(adapter, CRB_RCVPEG_STATE); - - if (val == PHAN_PEG_RCV_INITIALIZED) - return 0; - - msleep(10); - - } while (--retries); - - if (!retries) { - dev_err(&adapter->pdev->dev, "Receive Peg initialization not " - "complete, state: 0x%x.\n", val); - return -EIO; - } - - return 0; -} - -int qlcnic_init_firmware(struct qlcnic_adapter *adapter) -{ - int err; - - err = qlcnic_cmd_peg_ready(adapter); - if (err) - return err; - - err = qlcnic_receive_peg_ready(adapter); - if (err) - return err; - - QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); - - return err; -} - static void qlcnic_handle_linkevent(struct qlcnic_adapter *adapter, struct qlcnic_fw_msg *msg) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 6e246c819204..fa87a9633939 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -940,18 +940,13 @@ static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter) static int qlcnic_start_firmware(struct qlcnic_adapter *adapter) { - int val, err, first_boot; + int err; err = qlcnic_can_start_firmware(adapter); if (err < 0) return err; else if (!err) - goto wait_init; - - first_boot = QLCRD32(adapter, QLCNIC_CAM_RAM(0x1fc)); - if (first_boot == 0x55555555) - /* This is the first boot after power up */ - QLCWR32(adapter, QLCNIC_CAM_RAM(0x1fc), QLCNIC_BDINFO_MAGIC); + goto check_fw_status; if (load_fw_file) qlcnic_request_firmware(adapter); @@ -963,21 +958,12 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter) } err = qlcnic_need_fw_reset(adapter); - if (err < 0) - goto err_out; if (err == 0) - goto wait_init; - - if (first_boot != 0x55555555) { - QLCWR32(adapter, CRB_CMDPEG_STATE, 0); - QLCWR32(adapter, CRB_RCVPEG_STATE, 0); - qlcnic_pinit_from_rom(adapter); - msleep(1); - } - - QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0); - QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0); + goto set_dev_ready; + err = qlcnic_pinit_from_rom(adapter); + if (err) + goto err_out; qlcnic_set_port_mode(adapter); err = qlcnic_load_firmware(adapter); @@ -985,18 +971,14 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter) goto err_out; qlcnic_release_firmware(adapter); + QLCWR32(adapter, CRB_DRIVER_VERSION, QLCNIC_DRIVER_VERSION); - val = (_QLCNIC_LINUX_MAJOR << 16) - | ((_QLCNIC_LINUX_MINOR << 8)) - | (_QLCNIC_LINUX_SUBVERSION); - QLCWR32(adapter, CRB_DRIVER_VERSION, val); - -wait_init: - /* Handshake with the card before we register the devices. */ - err = qlcnic_init_firmware(adapter); +check_fw_status: + err = qlcnic_check_fw_status(adapter); if (err) goto err_out; +set_dev_ready: QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); qlcnic_idc_debug_info(adapter, 1); err = qlcnic_check_npar_opertional(adapter); -- cgit v1.2.3-59-g8ed1b From 091754a1652fad24664f1357ee7616e66953dd30 Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Thu, 19 Aug 2010 05:08:32 +0000 Subject: qlcnic: rom lock recovery Fw can get stuck while holding pci semaphore. Driver will not be able to perform fw initialization, without this lock. Release semaphore forcefully in that case. Signed-off-by: Sucheta Chakraborty Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_hw.c | 4 ++-- drivers/net/qlcnic/qlcnic_init.c | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 9d40ce05cb17..5e6f4864df94 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -297,8 +297,8 @@ qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg) break; if (++timeout >= QLCNIC_PCIE_SEM_TIMEOUT) { dev_err(&adapter->pdev->dev, - "Failed to acquire sem=%d lock;reg_id=%d\n", - sem, id_reg); + "Failed to acquire sem=%d lock; holdby=%d\n", + sem, id_reg ? QLCRD32(adapter, id_reg) : -1); return -EIO; } msleep(1); diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index e7a399f90326..a174521daa63 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -928,15 +928,25 @@ qlcnic_get_bios_version(struct qlcnic_adapter *adapter) return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24); } +static void qlcnic_rom_lock_recovery(struct qlcnic_adapter *adapter) +{ + if (qlcnic_pcie_sem_lock(adapter, 2, QLCNIC_ROM_LOCK_ID)) + dev_info(&adapter->pdev->dev, "Resetting rom_lock\n"); + + qlcnic_pcie_sem_unlock(adapter, 2); +} + int qlcnic_need_fw_reset(struct qlcnic_adapter *adapter) { u32 val, version, major, minor, build; - if (adapter->need_fw_reset) + if (qlcnic_check_fw_status(adapter)) { + qlcnic_rom_lock_recovery(adapter); return 1; + } - if (qlcnic_check_fw_status(adapter)) + if (adapter->need_fw_reset) return 1; /* check if we have got newer or different file firmware */ -- cgit v1.2.3-59-g8ed1b From 91fe8173be4f4e330c6c3ab3fd4de96c11c98444 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Thu, 19 Aug 2010 05:08:33 +0000 Subject: qlcnic: update version 5.0.8 Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 43cb925fd77b..508d531a55e5 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -51,8 +51,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 0 -#define _QLCNIC_LINUX_SUBVERSION 7 -#define QLCNIC_LINUX_VERSIONID "5.0.7" +#define _QLCNIC_LINUX_SUBVERSION 8 +#define QLCNIC_LINUX_VERSIONID "5.0.8" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) -- cgit v1.2.3-59-g8ed1b From 2d47b45951af087c1a4439c559309b0bf90a0718 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 17 Aug 2010 19:00:56 +0000 Subject: net: rps: reset network header before calling skb_get_rxhash() skb_get_rxhash() assumes the network header pointer of the skb is set properly after the commit: commit bfb564e7391340638afe4ad67744a8f3858e7566 Author: Krishna Kumar Date: Wed Aug 4 06:15:52 2010 +0000 core: Factor out flow calculation from get_rps_cpu Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- net/core/dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/dev.c b/net/core/dev.c index c1dc8a95f6ff..cf87fde3a29b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2372,6 +2372,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, if (!rxqueue->rps_map && !rxqueue->rps_flow_table) goto done; + skb_reset_network_header(skb); if (!skb_get_rxhash(skb)) goto done; -- cgit v1.2.3-59-g8ed1b From dbe5775bbc00116ed5699babfe17c54f32eb34c3 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 17 Aug 2010 19:01:38 +0000 Subject: net: rps: skip fragment when computing rxhash Fragmented IP packets may have no transfer header, so when computing rxhash, we should skip them. Signed-off-by: Changli Gao Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index cf87fde3a29b..7e97e891636e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2284,7 +2284,10 @@ __u32 __skb_get_rxhash(struct sk_buff *skb) goto done; ip = (struct iphdr *) skb->data + nhoff; - ip_proto = ip->protocol; + if (ip->frag_off & htons(IP_MF | IP_OFFSET)) + ip_proto = 0; + else + ip_proto = ip->protocol; addr1 = (__force u32) ip->saddr; addr2 = (__force u32) ip->daddr; ihl = ip->ihl; -- cgit v1.2.3-59-g8ed1b From e760702ed8333588f9f21e7bf6597873993006f1 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 17 Aug 2010 19:03:44 +0000 Subject: net: introduce proto_ports_offset() Introduce proto_ports_offset() for getting the position of the ports or SPI in the message of a protocol. Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- include/linux/in.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/linux/in.h b/include/linux/in.h index 41d88a4689af..beeb6dee2b49 100644 --- a/include/linux/in.h +++ b/include/linux/in.h @@ -250,6 +250,25 @@ struct sockaddr_in { #ifdef __KERNEL__ +#include + +static inline int proto_ports_offset(int proto) +{ + switch (proto) { + case IPPROTO_TCP: + case IPPROTO_UDP: + case IPPROTO_DCCP: + case IPPROTO_ESP: /* SPI */ + case IPPROTO_SCTP: + case IPPROTO_UDPLITE: + return 0; + case IPPROTO_AH: /* SPI */ + return 4; + default: + return -EINVAL; + } +} + static inline bool ipv4_is_loopback(__be32 addr) { return (addr & htonl(0xff000000)) == htonl(0x7f000000); -- cgit v1.2.3-59-g8ed1b From 12fcdefb3643607c47f39906a49056cf608bb545 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 17 Aug 2010 19:04:32 +0000 Subject: net: rps: use proto_ports_offset() to handle the AH message correctly The SPI isn't at the beginning of an AH message. Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- net/core/dev.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 7e97e891636e..da584f5ab3d2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2266,7 +2266,7 @@ static inline void ____napi_schedule(struct softnet_data *sd, */ __u32 __skb_get_rxhash(struct sk_buff *skb) { - int nhoff, hash = 0; + int nhoff, hash = 0, poff; struct ipv6hdr *ip6; struct iphdr *ip; u8 ip_proto; @@ -2306,24 +2306,15 @@ __u32 __skb_get_rxhash(struct sk_buff *skb) goto done; } - switch (ip_proto) { - case IPPROTO_TCP: - case IPPROTO_UDP: - case IPPROTO_DCCP: - case IPPROTO_ESP: - case IPPROTO_AH: - case IPPROTO_SCTP: - case IPPROTO_UDPLITE: - if (pskb_may_pull(skb, (ihl * 4) + 4 + nhoff)) { - ports.v32 = * (__force u32 *) (skb->data + nhoff + - (ihl * 4)); + ports.v32 = 0; + poff = proto_ports_offset(ip_proto); + if (poff >= 0) { + nhoff += ihl * 4 + poff; + if (pskb_may_pull(skb, nhoff + 4)) { + ports.v32 = * (__force u32 *) (skb->data + nhoff); if (ports.v16[1] < ports.v16[0]) swap(ports.v16[0], ports.v16[1]); - break; } - default: - ports.v32 = 0; - break; } /* get a consistent hash (same value on both flow directions) */ -- cgit v1.2.3-59-g8ed1b From 78d3307eded853f01c5e9aaa8c0768c2f75825a3 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 17 Aug 2010 19:05:08 +0000 Subject: net_sched: cls_flow: use proto_ports_offset() to support AH message Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- net/sched/cls_flow.c | 67 +++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index e17096e3913c..cd709f1294df 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c @@ -111,44 +111,41 @@ static u32 flow_get_proto(struct sk_buff *skb) } } -static int has_ports(u8 protocol) -{ - switch (protocol) { - case IPPROTO_TCP: - case IPPROTO_UDP: - case IPPROTO_UDPLITE: - case IPPROTO_SCTP: - case IPPROTO_DCCP: - case IPPROTO_ESP: - return 1; - default: - return 0; - } -} - static u32 flow_get_proto_src(struct sk_buff *skb) { switch (skb->protocol) { case htons(ETH_P_IP): { struct iphdr *iph; + int poff; if (!pskb_network_may_pull(skb, sizeof(*iph))) break; iph = ip_hdr(skb); - if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && - has_ports(iph->protocol) && - pskb_network_may_pull(skb, iph->ihl * 4 + 2)) - return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4)); + if (iph->frag_off & htons(IP_MF|IP_OFFSET)) + break; + poff = proto_ports_offset(iph->protocol); + if (poff >= 0 && + pskb_network_may_pull(skb, iph->ihl * 4 + 2 + poff)) { + iph = ip_hdr(skb); + return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + + poff)); + } break; } case htons(ETH_P_IPV6): { struct ipv6hdr *iph; + int poff; - if (!pskb_network_may_pull(skb, sizeof(*iph) + 2)) + if (!pskb_network_may_pull(skb, sizeof(*iph))) break; iph = ipv6_hdr(skb); - if (has_ports(iph->nexthdr)) - return ntohs(*(__be16 *)&iph[1]); + poff = proto_ports_offset(iph->nexthdr); + if (poff >= 0 && + pskb_network_may_pull(skb, sizeof(*iph) + poff + 2)) { + iph = ipv6_hdr(skb); + return ntohs(*(__be16 *)((void *)iph + sizeof(*iph) + + poff)); + } break; } } @@ -161,24 +158,36 @@ static u32 flow_get_proto_dst(struct sk_buff *skb) switch (skb->protocol) { case htons(ETH_P_IP): { struct iphdr *iph; + int poff; if (!pskb_network_may_pull(skb, sizeof(*iph))) break; iph = ip_hdr(skb); - if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && - has_ports(iph->protocol) && - pskb_network_may_pull(skb, iph->ihl * 4 + 4)) - return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + 2)); + if (iph->frag_off & htons(IP_MF|IP_OFFSET)) + break; + poff = proto_ports_offset(iph->protocol); + if (poff >= 0 && + pskb_network_may_pull(skb, iph->ihl * 4 + 4 + poff)) { + iph = ip_hdr(skb); + return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + + 2 + poff)); + } break; } case htons(ETH_P_IPV6): { struct ipv6hdr *iph; + int poff; - if (!pskb_network_may_pull(skb, sizeof(*iph) + 4)) + if (!pskb_network_may_pull(skb, sizeof(*iph))) break; iph = ipv6_hdr(skb); - if (has_ports(iph->nexthdr)) - return ntohs(*(__be16 *)((void *)&iph[1] + 2)); + poff = proto_ports_offset(iph->nexthdr); + if (poff >= 0 && + pskb_network_may_pull(skb, sizeof(*iph) + poff + 4)) { + iph = ipv6_hdr(skb); + return ntohs(*(__be16 *)((void *)iph + sizeof(*iph) + + poff + 2)); + } break; } } -- cgit v1.2.3-59-g8ed1b From 3d04ebb6ab2ac9a3bea7644f0d13cdf65002b870 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 17 Aug 2010 20:34:40 +0000 Subject: netfilter: ipt_CLUSTERIP: use proto_ports_offset() to support AH message Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- net/ipv4/netfilter/ipt_CLUSTERIP.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 3a43cf36db87..1e26a4897655 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -29,6 +29,7 @@ #include #include #include +#include #define CLUSTERIP_VERSION "0.8" @@ -231,24 +232,22 @@ clusterip_hashfn(const struct sk_buff *skb, { const struct iphdr *iph = ip_hdr(skb); unsigned long hashval; - u_int16_t sport, dport; - const u_int16_t *ports; - - switch (iph->protocol) { - case IPPROTO_TCP: - case IPPROTO_UDP: - case IPPROTO_UDPLITE: - case IPPROTO_SCTP: - case IPPROTO_DCCP: - case IPPROTO_ICMP: - ports = (const void *)iph+iph->ihl*4; - sport = ports[0]; - dport = ports[1]; - break; - default: + u_int16_t sport = 0, dport = 0; + int poff; + + poff = proto_ports_offset(iph->protocol); + if (poff >= 0) { + const u_int16_t *ports; + u16 _ports[2]; + + ports = skb_header_pointer(skb, iph->ihl * 4 + poff, 4, _ports); + if (ports) { + sport = ports[0]; + dport = ports[1]; + } + } else { if (net_ratelimit()) pr_info("unknown protocol %u\n", iph->protocol); - sport = dport = 0; } switch (config->hash_mode) { -- cgit v1.2.3-59-g8ed1b From aca071c1c1c07bcc0b100b7c58e59790d6be6a69 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 17 Aug 2010 19:06:39 +0000 Subject: netfilter: xt_hashlimit: use proto_ports_offset() to support AH message Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- net/netfilter/xt_hashlimit.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index b46a8390896d..9228ee0dc11a 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -448,6 +448,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo, { __be16 _ports[2], *ports; u8 nexthdr; + int poff; memset(dst, 0, sizeof(*dst)); @@ -492,19 +493,13 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo, return 0; } - switch (nexthdr) { - case IPPROTO_TCP: - case IPPROTO_UDP: - case IPPROTO_UDPLITE: - case IPPROTO_SCTP: - case IPPROTO_DCCP: - ports = skb_header_pointer(skb, protoff, sizeof(_ports), + poff = proto_ports_offset(nexthdr); + if (poff >= 0) { + ports = skb_header_pointer(skb, protoff + poff, sizeof(_ports), &_ports); - break; - default: + } else { _ports[0] = _ports[1] = 0; ports = _ports; - break; } if (!ports) return -1; -- cgit v1.2.3-59-g8ed1b From b9959c2e4460b1df1d113d829180398588bb04b4 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 17 Aug 2010 19:07:35 +0000 Subject: net_sched: sch_sfq: use proto_ports_offset() to support AH message Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- net/sched/sch_sfq.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 201cbac2b32c..3cf478d012dd 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -123,40 +123,39 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) case htons(ETH_P_IP): { const struct iphdr *iph; + int poff; if (!pskb_network_may_pull(skb, sizeof(*iph))) goto err; iph = ip_hdr(skb); h = (__force u32)iph->daddr; h2 = (__force u32)iph->saddr ^ iph->protocol; - if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && - (iph->protocol == IPPROTO_TCP || - iph->protocol == IPPROTO_UDP || - iph->protocol == IPPROTO_UDPLITE || - iph->protocol == IPPROTO_SCTP || - iph->protocol == IPPROTO_DCCP || - iph->protocol == IPPROTO_ESP) && - pskb_network_may_pull(skb, iph->ihl * 4 + 4)) - h2 ^= *(((u32*)iph) + iph->ihl); + if (iph->frag_off & htons(IP_MF|IP_OFFSET)) + break; + poff = proto_ports_offset(iph->protocol); + if (poff >= 0 && + pskb_network_may_pull(skb, iph->ihl * 4 + 4 + poff)) { + iph = ip_hdr(skb); + h2 ^= *(u32*)((void *)iph + iph->ihl * 4 + poff); + } break; } case htons(ETH_P_IPV6): { struct ipv6hdr *iph; + int poff; if (!pskb_network_may_pull(skb, sizeof(*iph))) goto err; iph = ipv6_hdr(skb); h = (__force u32)iph->daddr.s6_addr32[3]; h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr; - if ((iph->nexthdr == IPPROTO_TCP || - iph->nexthdr == IPPROTO_UDP || - iph->nexthdr == IPPROTO_UDPLITE || - iph->nexthdr == IPPROTO_SCTP || - iph->nexthdr == IPPROTO_DCCP || - iph->nexthdr == IPPROTO_ESP) && - pskb_network_may_pull(skb, sizeof(*iph) + 4)) - h2 ^= *(u32*)&iph[1]; + poff = proto_ports_offset(iph->nexthdr); + if (poff >= 0 && + pskb_network_may_pull(skb, sizeof(*iph) + 4 + poff)) { + iph = ipv6_hdr(skb); + h2 ^= *(u32*)((void *)iph + sizeof(*iph) + poff); + } break; } default: -- cgit v1.2.3-59-g8ed1b From 5dbfbc4027f819c3da92844f34f241524f99c9eb Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 18 Aug 2010 22:10:34 +0000 Subject: ep93xx_eth: Use net_device_stats from struct net_device struct net_device has its own struct net_device_stats member, so use this one instead of a private copy in the ep93xx_priv struct. As the new ndo_get_stats function would just return dev->stats we can omit it. Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- drivers/net/arm/ep93xx_eth.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 4a5ec9470aa1..5a77001b6d10 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -175,8 +175,6 @@ struct ep93xx_priv struct net_device *dev; struct napi_struct napi; - struct net_device_stats stats; - struct mii_if_info mii; u8 mdc_divisor; }; @@ -230,12 +228,6 @@ static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int d pr_info("mdio write timed out\n"); } -static struct net_device_stats *ep93xx_get_stats(struct net_device *dev) -{ - struct ep93xx_priv *ep = netdev_priv(dev); - return &(ep->stats); -} - static int ep93xx_rx(struct net_device *dev, int processed, int budget) { struct ep93xx_priv *ep = netdev_priv(dev); @@ -267,15 +259,15 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget) pr_crit("entry mismatch %.8x %.8x\n", rstat0, rstat1); if (!(rstat0 & RSTAT0_RWE)) { - ep->stats.rx_errors++; + dev->stats.rx_errors++; if (rstat0 & RSTAT0_OE) - ep->stats.rx_fifo_errors++; + dev->stats.rx_fifo_errors++; if (rstat0 & RSTAT0_FE) - ep->stats.rx_frame_errors++; + dev->stats.rx_frame_errors++; if (rstat0 & (RSTAT0_RUNT | RSTAT0_EDATA)) - ep->stats.rx_length_errors++; + dev->stats.rx_length_errors++; if (rstat0 & RSTAT0_CRCE) - ep->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; goto err; } @@ -300,10 +292,10 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget) netif_receive_skb(skb); - ep->stats.rx_packets++; - ep->stats.rx_bytes += length; + dev->stats.rx_packets++; + dev->stats.rx_bytes += length; } else { - ep->stats.rx_dropped++; + dev->stats.rx_dropped++; } err: @@ -359,7 +351,7 @@ static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) int entry; if (unlikely(skb->len > MAX_PKT_SIZE)) { - ep->stats.tx_dropped++; + dev->stats.tx_dropped++; dev_kfree_skb(skb); return NETDEV_TX_OK; } @@ -415,17 +407,17 @@ static void ep93xx_tx_complete(struct net_device *dev) if (tstat0 & TSTAT0_TXWE) { int length = ep->descs->tdesc[entry].tdesc1 & 0xfff; - ep->stats.tx_packets++; - ep->stats.tx_bytes += length; + dev->stats.tx_packets++; + dev->stats.tx_bytes += length; } else { - ep->stats.tx_errors++; + dev->stats.tx_errors++; } if (tstat0 & TSTAT0_OW) - ep->stats.tx_window_errors++; + dev->stats.tx_window_errors++; if (tstat0 & TSTAT0_TXU) - ep->stats.tx_fifo_errors++; - ep->stats.collisions += (tstat0 >> 16) & 0x1f; + dev->stats.tx_fifo_errors++; + dev->stats.collisions += (tstat0 >> 16) & 0x1f; ep->tx_clean_pointer = (entry + 1) & (TX_QUEUE_ENTRIES - 1); if (ep->tx_pending == TX_QUEUE_ENTRIES) @@ -758,7 +750,6 @@ static const struct net_device_ops ep93xx_netdev_ops = { .ndo_open = ep93xx_open, .ndo_stop = ep93xx_close, .ndo_start_xmit = ep93xx_xmit, - .ndo_get_stats = ep93xx_get_stats, .ndo_do_ioctl = ep93xx_ioctl, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = eth_change_mtu, -- cgit v1.2.3-59-g8ed1b From 0add79e3134a618c10acabe58834ac647075111a Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 18 Aug 2010 22:11:25 +0000 Subject: tehuti: Use net_device_stats from struct net_device struct net_device has its own struct net_device_stats member, so use this one instead of a private copy in the bdx_priv struct. Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- drivers/net/tehuti.c | 21 +++++++-------------- drivers/net/tehuti.h | 1 - 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 737df6032bbc..d808f95a87ca 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -927,13 +927,6 @@ static void bdx_update_stats(struct bdx_priv *priv) BDX_ASSERT((sizeof(struct bdx_stats) / sizeof(u64)) != i); } -static struct net_device_stats *bdx_get_stats(struct net_device *ndev) -{ - struct bdx_priv *priv = netdev_priv(ndev); - struct net_device_stats *net_stat = &priv->net_stats; - return net_stat; -} - static void print_rxdd(struct rxd_desc *rxdd, u32 rxd_val1, u16 len, u16 rxd_vlan); static void print_rxfd(struct rxf_desc *rxfd); @@ -1220,6 +1213,7 @@ static void bdx_recycle_skb(struct bdx_priv *priv, struct rxd_desc *rxdd) static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget) { + struct net_device *ndev = priv->ndev; struct sk_buff *skb, *skb2; struct rxd_desc *rxdd; struct rx_map *dm; @@ -1273,7 +1267,7 @@ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget) if (unlikely(GET_RXD_ERR(rxd_val1))) { DBG("rxd_err = 0x%x\n", GET_RXD_ERR(rxd_val1)); - priv->net_stats.rx_errors++; + ndev->stats.rx_errors++; bdx_recycle_skb(priv, rxdd); continue; } @@ -1300,11 +1294,11 @@ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget) bdx_rxdb_free_elem(db, rxdd->va_lo); } - priv->net_stats.rx_bytes += len; + ndev->stats.rx_bytes += len; skb_put(skb, len); skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->protocol = eth_type_trans(skb, priv->ndev); + skb->protocol = eth_type_trans(skb, ndev); /* Non-IP packets aren't checksum-offloaded */ if (GET_RXD_PKT_ID(rxd_val1) == 0) @@ -1316,7 +1310,7 @@ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget) break; } - priv->net_stats.rx_packets += done; + ndev->stats.rx_packets += done; /* FIXME: do smth to minimize pci accesses */ WRITE_REG(priv, f->m.reg_RPTR, f->m.rptr & TXF_WPTR_WR_PTR); @@ -1712,8 +1706,8 @@ static netdev_tx_t bdx_tx_transmit(struct sk_buff *skb, #ifdef BDX_LLTX ndev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ #endif - priv->net_stats.tx_packets++; - priv->net_stats.tx_bytes += skb->len; + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; if (priv->tx_level < BDX_MIN_TX_LEVEL) { DBG("%s: %s: TX Q STOP level %d\n", @@ -1888,7 +1882,6 @@ static const struct net_device_ops bdx_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = bdx_ioctl, .ndo_set_multicast_list = bdx_setmulti, - .ndo_get_stats = bdx_get_stats, .ndo_change_mtu = bdx_change_mtu, .ndo_set_mac_address = bdx_set_mac, .ndo_vlan_rx_register = bdx_vlan_rx_register, diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h index 67e3b71bf705..b6ba8601e2b5 100644 --- a/drivers/net/tehuti.h +++ b/drivers/net/tehuti.h @@ -269,7 +269,6 @@ struct bdx_priv { u32 msg_enable; int stats_flag; struct bdx_stats hw_stats; - struct net_device_stats net_stats; struct pci_dev *pdev; struct pci_nic *nic; -- cgit v1.2.3-59-g8ed1b From 4da79504b2b41410dd56e9268c9ad403aa65e89c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 19 Aug 2010 08:52:44 +0000 Subject: qlge: pull NULL check ahead of dereference There was a dereference before NULL check issue introduced in 1e213303d "qlge: Add tx multiqueue support." I've pulled the NULL check of "net_rsp" forward a couple lines to avoid that. Also Ron Mercer says that the early exit should be above the index write. ql_write_cq_idx(rx_ring); Signed-off-by: Dan Carpenter Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 8d63f69b27d9..c9f9754f0784 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2222,10 +2222,11 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) ql_update_cq(rx_ring); prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); } + if (!net_rsp) + return 0; ql_write_cq_idx(rx_ring); tx_ring = &qdev->tx_ring[net_rsp->txq_idx]; - if (__netif_subqueue_stopped(qdev->ndev, tx_ring->wq_id) && - net_rsp != NULL) { + if (__netif_subqueue_stopped(qdev->ndev, tx_ring->wq_id)) { if (atomic_read(&tx_ring->queue_stopped) && (atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4))) /* -- cgit v1.2.3-59-g8ed1b From 7656e2486cb1ab7cdee65652ee695bdff894ea73 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 20 Aug 2010 15:59:40 +0900 Subject: sh: Support type 1 accesses for SH7786 PCI. This enables support for type 1 config space accesses on the SH7786 PCI controller. At the same time, add in some extra sanity checks for controller asserted errors. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/ops-sh7786.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/arch/sh/drivers/pci/ops-sh7786.c b/arch/sh/drivers/pci/ops-sh7786.c index 48f594b9582b..57134a38686a 100644 --- a/arch/sh/drivers/pci/ops-sh7786.c +++ b/arch/sh/drivers/pci/ops-sh7786.c @@ -1,7 +1,7 @@ /* * Generic SH7786 PCI-Express operations. * - * Copyright (C) 2009 Paul Mundt + * Copyright (C) 2009 - 2010 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License v2. See the file "COPYING" in the main directory of this archive @@ -35,22 +35,34 @@ static int sh7786_pcie_config_access(unsigned char access_type, if (devfn) return PCIBIOS_DEVICE_NOT_FOUND; + /* Clear errors */ + pci_write_reg(chan, pci_read_reg(chan, SH4A_PCIEERRFR), SH4A_PCIEERRFR); + /* Set the PIO address */ pci_write_reg(chan, (bus->number << 24) | (dev << 19) | (func << 16) | (where & ~3), SH4A_PCIEPAR); /* Enable the configuration access */ - pci_write_reg(chan, (1 << 31), SH4A_PCIEPCTLR); + if (bus->number) { + /* Type 1 */ + pci_write_reg(chan, (1 << 31) | (1 << 8), SH4A_PCIEPCTLR); + } else { + /* Type 0 */ + pci_write_reg(chan, (1 << 31), SH4A_PCIEPCTLR); + } + + /* Check for errors */ + if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10) + return PCIBIOS_DEVICE_NOT_FOUND; + /* Check for master and target aborts */ + if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28))) + return PCIBIOS_DEVICE_NOT_FOUND; if (access_type == PCI_ACCESS_READ) *data = pci_read_reg(chan, SH4A_PCIEPDR); else pci_write_reg(chan, *data, SH4A_PCIEPDR); - /* Check for master and target aborts */ - if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28))) - return PCIBIOS_DEVICE_NOT_FOUND; - return PCIBIOS_SUCCESSFUL; } @@ -69,8 +81,10 @@ static int sh7786_pcie_read(struct pci_bus *bus, unsigned int devfn, spin_lock_irqsave(&sh7786_pcie_lock, flags); ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus, devfn, where, &data); - if (ret != PCIBIOS_SUCCESSFUL) + if (ret != PCIBIOS_SUCCESSFUL) { + *val = 0xffffffff; goto out; + } if (size == 1) *val = (data >> ((where & 3) << 3)) & 0xff; -- cgit v1.2.3-59-g8ed1b From 53178d71b9f2d5c96bfcd2dd2c4b99c4e95a77d5 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 20 Aug 2010 16:04:59 +0900 Subject: sh: Fix up SH7786 PCIe PHY initialization. This brings the clocking and register setting in line with the somewhat factually ambiguous specification. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pcie-sh7786.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index 68cb9b0ac9d2..03e6d8217b0c 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -148,16 +148,11 @@ static int pci_wait_for_irq(struct pci_channel *chan, unsigned int mask) static void phy_write_reg(struct pci_channel *chan, unsigned int addr, unsigned int lane, unsigned int data) { - unsigned long phyaddr, ctrl; + unsigned long phyaddr; phyaddr = (1 << BITS_CMD) + ((lane & 0xf) << BITS_LANE) + ((addr & 0xff) << BITS_ADR); - /* Enable clock */ - ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR); - ctrl |= (1 << BITS_CKE); - pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR); - /* Set write data */ pci_write_reg(chan, data, SH4A_PCIEPHYDOUTR); pci_write_reg(chan, phyaddr, SH4A_PCIEPHYADRR); @@ -165,20 +160,22 @@ static void phy_write_reg(struct pci_channel *chan, unsigned int addr, phy_wait_for_ack(chan); /* Clear command */ + pci_write_reg(chan, 0, SH4A_PCIEPHYDOUTR); pci_write_reg(chan, 0, SH4A_PCIEPHYADRR); phy_wait_for_ack(chan); - - /* Disable clock */ - ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR); - ctrl &= ~(1 << BITS_CKE); - pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR); } static int phy_init(struct pci_channel *chan) { + unsigned long ctrl; unsigned int timeout = 100; + /* Enable clock */ + ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR); + ctrl |= (1 << BITS_CKE); + pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR); + /* Initialize the phy */ phy_write_reg(chan, 0x60, 0xf, 0x004b008b); phy_write_reg(chan, 0x61, 0xf, 0x00007b41); @@ -187,9 +184,15 @@ static int phy_init(struct pci_channel *chan) phy_write_reg(chan, 0x66, 0xf, 0x00000010); phy_write_reg(chan, 0x74, 0xf, 0x0007001c); phy_write_reg(chan, 0x79, 0xf, 0x01fc000d); + phy_write_reg(chan, 0xb0, 0xf, 0x00000610); /* Deassert Standby */ - phy_write_reg(chan, 0x67, 0xf, 0x00000400); + phy_write_reg(chan, 0x67, 0x1, 0x00000400); + + /* Disable clock */ + ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR); + ctrl &= ~(1 << BITS_CKE); + pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR); while (timeout--) { if (pci_read_reg(chan, SH4A_PCIEPHYSR)) @@ -287,6 +290,9 @@ static int pcie_init(struct sh7786_pcie_port *port) __raw_writel(memphys, chan->reg_base + SH4A_PCIELAR0); __raw_writel((memsize - SZ_256) | 1, chan->reg_base + SH4A_PCIELAMR0); + __raw_writel(memphys, chan->reg_base + SH4A_PCIEPCICONF4); + __raw_writel(0, chan->reg_base + SH4A_PCIEPCICONF5); + /* Finish initialization */ data = pci_read_reg(chan, SH4A_PCIETCTLR); data |= 0x1; -- cgit v1.2.3-59-g8ed1b From 49e8ab03ebcacd8e37660ffec20c0c46721a2800 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 19 Aug 2010 06:10:45 +0000 Subject: net: build_ehash_secret() and rt_bind_peer() cleanups Now cmpxchg() is available on all arches, we can use it in build_ehash_secret() and rt_bind_peer() instead of using spinlocks. Signed-off-by: Eric Dumazet CC: Mathieu Desnoyers Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 8 +++----- net/ipv4/route.c | 9 +-------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 6a1100c25a9f..f581f77d1097 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -227,18 +227,16 @@ EXPORT_SYMBOL(inet_ehash_secret); /* * inet_ehash_secret must be set exactly once - * Instead of using a dedicated spinlock, we (ab)use inetsw_lock */ void build_ehash_secret(void) { u32 rnd; + do { get_random_bytes(&rnd, sizeof(rnd)); } while (rnd == 0); - spin_lock_bh(&inetsw_lock); - if (!inet_ehash_secret) - inet_ehash_secret = rnd; - spin_unlock_bh(&inetsw_lock); + + cmpxchg(&inet_ehash_secret, 0, rnd); } EXPORT_SYMBOL(build_ehash_secret); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 3f56b6e6c6aa..85a67c9d5982 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1268,18 +1268,11 @@ skip_hashing: void rt_bind_peer(struct rtable *rt, int create) { - static DEFINE_SPINLOCK(rt_peer_lock); struct inet_peer *peer; peer = inet_getpeer(rt->rt_dst, create); - spin_lock_bh(&rt_peer_lock); - if (rt->peer == NULL) { - rt->peer = peer; - peer = NULL; - } - spin_unlock_bh(&rt_peer_lock); - if (peer) + if (peer && cmpxchg(&rt->peer, NULL, peer) != NULL) inet_putpeer(peer); } -- cgit v1.2.3-59-g8ed1b From eb4d40654505e47aa9d2035bb97f631fa61d14b4 Mon Sep 17 00:00:00 2001 From: Grégoire Baron Date: Wed, 18 Aug 2010 13:10:35 +0000 Subject: net/sched: add ACT_CSUM action to update packets checksums net/sched: add ACT_CSUM action to update packets checksums ACT_CSUM can be called just after ACT_PEDIT in order to re-compute some altered checksums in IPv4 and IPv6 packets. The following checksums are supported by this patch: - IPv4: IPv4 header, ICMP, IGMP, TCP, UDP & UDPLite - IPv6: ICMPv6, TCP, UDP & UDPLite It's possible to request in the same action to update different kind of checksums, if the packets flow mix TCP, UDP and UDPLite, ... An example of usage is done in the associated iproute2 patch. Version 3 changes: - remove useless goto instructions - improve IPv6 hop options decoding Version 2 changes: - coding style correction - remove useless arguments of some functions - use stack in tcf_csum_dump() - add tcf_csum_skb_nextlayer() to factor code Signed-off-by: Gregoire Baron Acked-by: jamal Signed-off-by: David S. Miller --- include/linux/tc_act/Kbuild | 1 + include/linux/tc_act/tc_csum.h | 32 +++ include/net/tc_act/tc_csum.h | 15 ++ net/sched/Kconfig | 10 + net/sched/Makefile | 1 + net/sched/act_csum.c | 595 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 654 insertions(+) create mode 100644 include/linux/tc_act/tc_csum.h create mode 100644 include/net/tc_act/tc_csum.h create mode 100644 net/sched/act_csum.c diff --git a/include/linux/tc_act/Kbuild b/include/linux/tc_act/Kbuild index 76990937f4c9..67b501c302b2 100644 --- a/include/linux/tc_act/Kbuild +++ b/include/linux/tc_act/Kbuild @@ -4,3 +4,4 @@ header-y += tc_mirred.h header-y += tc_pedit.h header-y += tc_nat.h header-y += tc_skbedit.h +header-y += tc_csum.h diff --git a/include/linux/tc_act/tc_csum.h b/include/linux/tc_act/tc_csum.h new file mode 100644 index 000000000000..a047c49a3153 --- /dev/null +++ b/include/linux/tc_act/tc_csum.h @@ -0,0 +1,32 @@ +#ifndef __LINUX_TC_CSUM_H +#define __LINUX_TC_CSUM_H + +#include +#include + +#define TCA_ACT_CSUM 16 + +enum { + TCA_CSUM_UNSPEC, + TCA_CSUM_PARMS, + TCA_CSUM_TM, + __TCA_CSUM_MAX +}; +#define TCA_CSUM_MAX (__TCA_CSUM_MAX - 1) + +enum { + TCA_CSUM_UPDATE_FLAG_IPV4HDR = 1, + TCA_CSUM_UPDATE_FLAG_ICMP = 2, + TCA_CSUM_UPDATE_FLAG_IGMP = 4, + TCA_CSUM_UPDATE_FLAG_TCP = 8, + TCA_CSUM_UPDATE_FLAG_UDP = 16, + TCA_CSUM_UPDATE_FLAG_UDPLITE = 32 +}; + +struct tc_csum { + tc_gen; + + __u32 update_flags; +}; + +#endif /* __LINUX_TC_CSUM_H */ diff --git a/include/net/tc_act/tc_csum.h b/include/net/tc_act/tc_csum.h new file mode 100644 index 000000000000..9e8710be7a04 --- /dev/null +++ b/include/net/tc_act/tc_csum.h @@ -0,0 +1,15 @@ +#ifndef __NET_TC_CSUM_H +#define __NET_TC_CSUM_H + +#include +#include + +struct tcf_csum { + struct tcf_common common; + + u32 update_flags; +}; +#define to_tcf_csum(pc) \ + container_of(pc,struct tcf_csum,common) + +#endif /* __NET_TC_CSUM_H */ diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 2f691fb180d1..522d5a9a2825 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -518,6 +518,16 @@ config NET_ACT_SKBEDIT To compile this code as a module, choose M here: the module will be called act_skbedit. +config NET_ACT_CSUM + tristate "Checksum Updating" + depends on NET_CLS_ACT + ---help--- + Say Y here to update some common checksum after some direct + packet alterations. + + To compile this code as a module, choose M here: the + module will be called act_csum. + config NET_CLS_IND bool "Incoming device classification" depends on NET_CLS_U32 || NET_CLS_FW diff --git a/net/sched/Makefile b/net/sched/Makefile index f14e71bfa58f..960f5dba6304 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_NET_ACT_NAT) += act_nat.o obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o +obj-$(CONFIG_NET_ACT_CSUM) += act_csum.o obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c new file mode 100644 index 000000000000..58d7f36949da --- /dev/null +++ b/net/sched/act_csum.c @@ -0,0 +1,595 @@ +/* + * Checksum updating actions + * + * Copyright (c) 2010 Gregoire Baron + * + * 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. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define CSUM_TAB_MASK 15 +static struct tcf_common *tcf_csum_ht[CSUM_TAB_MASK + 1]; +static u32 csum_idx_gen; +static DEFINE_RWLOCK(csum_lock); + +static struct tcf_hashinfo csum_hash_info = { + .htab = tcf_csum_ht, + .hmask = CSUM_TAB_MASK, + .lock = &csum_lock, +}; + +static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = { + [TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), }, +}; + +static int tcf_csum_init(struct nlattr *nla, struct nlattr *est, + struct tc_action *a, int ovr, int bind) +{ + struct nlattr *tb[TCA_CSUM_MAX + 1]; + struct tc_csum *parm; + struct tcf_common *pc; + struct tcf_csum *p; + int ret = 0, err; + + if (nla == NULL) + return -EINVAL; + + err = nla_parse_nested(tb, TCA_CSUM_MAX, nla,csum_policy); + if (err < 0) + return err; + + if (tb[TCA_CSUM_PARMS] == NULL) + return -EINVAL; + parm = nla_data(tb[TCA_CSUM_PARMS]); + + pc = tcf_hash_check(parm->index, a, bind, &csum_hash_info); + if (!pc) { + pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind, &csum_idx_gen, &csum_hash_info); + if (IS_ERR(pc)) + return PTR_ERR(pc); + p = to_tcf_csum(pc); + ret = ACT_P_CREATED; + } else { + p = to_tcf_csum(pc); + if (!ovr) { + tcf_hash_release(pc, bind, &csum_hash_info); + return -EEXIST; + } + } + + spin_lock_bh(&p->tcf_lock); + p->tcf_action = parm->action; + p->update_flags = parm->update_flags; + spin_unlock_bh(&p->tcf_lock); + + if (ret == ACT_P_CREATED) + tcf_hash_insert(pc, &csum_hash_info); + + return ret; +} + +static int tcf_csum_cleanup(struct tc_action *a, int bind) +{ + struct tcf_csum *p = a->priv; + return tcf_hash_release(&p->common, bind, &csum_hash_info); +} + +/** + * tcf_csum_skb_nextlayer - Get next layer pointer + * @skb: sk_buff to use + * @ihl: previous summed headers length + * @ipl: complete packet length + * @jhl: next header length + * + * Check the expected next layer availability in the specified sk_buff. + * Return the next layer pointer if pass, NULL otherwise. + */ +static void *tcf_csum_skb_nextlayer(struct sk_buff *skb, + unsigned int ihl, unsigned int ipl, + unsigned int jhl) +{ + int ntkoff = skb_network_offset(skb); + int hl = ihl + jhl; + + if (!pskb_may_pull(skb, ipl + ntkoff) || (ipl < hl) || + (skb_cloned(skb) && + !skb_clone_writable(skb, hl + ntkoff) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) + return NULL; + else + return (void *)(skb_network_header(skb) + ihl); +} + +static int tcf_csum_ipv4_icmp(struct sk_buff *skb, + unsigned int ihl, unsigned int ipl) +{ + struct icmphdr *icmph; + + icmph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*icmph)); + if (icmph == NULL) + return 0; + + icmph->checksum = 0; + skb->csum = csum_partial(icmph, ipl - ihl, 0); + icmph->checksum = csum_fold(skb->csum); + + skb->ip_summed = CHECKSUM_NONE; + + return 1; +} + +static int tcf_csum_ipv4_igmp(struct sk_buff *skb, + unsigned int ihl, unsigned int ipl) +{ + struct igmphdr *igmph; + + igmph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*igmph)); + if (igmph == NULL) + return 0; + + igmph->csum = 0; + skb->csum = csum_partial(igmph, ipl - ihl, 0); + igmph->csum = csum_fold(skb->csum); + + skb->ip_summed = CHECKSUM_NONE; + + return 1; +} + +static int tcf_csum_ipv6_icmp(struct sk_buff *skb, struct ipv6hdr *ip6h, + unsigned int ihl, unsigned int ipl) +{ + struct icmp6hdr *icmp6h; + + icmp6h = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*icmp6h)); + if (icmp6h == NULL) + return 0; + + icmp6h->icmp6_cksum = 0; + skb->csum = csum_partial(icmp6h, ipl - ihl, 0); + icmp6h->icmp6_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + ipl - ihl, IPPROTO_ICMPV6, + skb->csum); + + skb->ip_summed = CHECKSUM_NONE; + + return 1; +} + +static int tcf_csum_ipv4_tcp(struct sk_buff *skb, struct iphdr *iph, + unsigned int ihl, unsigned int ipl) +{ + struct tcphdr *tcph; + + tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph)); + if (tcph == NULL) + return 0; + + tcph->check = 0; + skb->csum = csum_partial(tcph, ipl - ihl, 0); + tcph->check = tcp_v4_check(ipl - ihl, + iph->saddr, iph->daddr, skb->csum); + + skb->ip_summed = CHECKSUM_NONE; + + return 1; +} + +static int tcf_csum_ipv6_tcp(struct sk_buff *skb, struct ipv6hdr *ip6h, + unsigned int ihl, unsigned int ipl) +{ + struct tcphdr *tcph; + + tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph)); + if (tcph == NULL) + return 0; + + tcph->check = 0; + skb->csum = csum_partial(tcph, ipl - ihl, 0); + tcph->check = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + ipl - ihl, IPPROTO_TCP, + skb->csum); + + skb->ip_summed = CHECKSUM_NONE; + + return 1; +} + +static int tcf_csum_ipv4_udp(struct sk_buff *skb, struct iphdr *iph, + unsigned int ihl, unsigned int ipl, int udplite) +{ + struct udphdr *udph; + u16 ul; + + /* Support both UDP and UDPLITE checksum algorithms, + * Don't use udph->len to get the real length without any protocol check, + * UDPLITE uses udph->len for another thing, + * Use iph->tot_len, or just ipl. + */ + + udph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*udph)); + if (udph == NULL) + return 0; + + ul = ntohs(udph->len); + + if (udplite || udph->check) { + + udph->check = 0; + + if (udplite) { + if (ul == 0) + skb->csum = csum_partial(udph, ipl - ihl, 0); + + else if ((ul >= sizeof(*udph)) && (ul <= ipl - ihl)) + skb->csum = csum_partial(udph, ul, 0); + + else + goto ignore_obscure_skb; + } else { + if (ul != ipl - ihl) + goto ignore_obscure_skb; + + skb->csum = csum_partial(udph, ul, 0); + } + + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, + ul, iph->protocol, + skb->csum); + + if (!udph->check) + udph->check = CSUM_MANGLED_0; + } + + skb->ip_summed = CHECKSUM_NONE; + +ignore_obscure_skb: + return 1; +} + +static int tcf_csum_ipv6_udp(struct sk_buff *skb, struct ipv6hdr *ip6h, + unsigned int ihl, unsigned int ipl, int udplite) +{ + struct udphdr *udph; + u16 ul; + + /* Support both UDP and UDPLITE checksum algorithms, + * Don't use udph->len to get the real length without any protocol check, + * UDPLITE uses udph->len for another thing, + * Use ip6h->payload_len + sizeof(*ip6h) ... , or just ipl. + */ + + udph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*udph)); + if (udph == NULL) + return 0; + + ul = ntohs(udph->len); + + udph->check = 0; + + if (udplite) { + if (ul == 0) + skb->csum = csum_partial(udph, ipl - ihl, 0); + + else if ((ul >= sizeof(*udph)) && (ul <= ipl - ihl)) + skb->csum = csum_partial(udph, ul, 0); + + else + goto ignore_obscure_skb; + } else { + if (ul != ipl - ihl) + goto ignore_obscure_skb; + + skb->csum = csum_partial(udph, ul, 0); + } + + udph->check = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, ul, + udplite ? IPPROTO_UDPLITE : IPPROTO_UDP, + skb->csum); + + if (!udph->check) + udph->check = CSUM_MANGLED_0; + + skb->ip_summed = CHECKSUM_NONE; + +ignore_obscure_skb: + return 1; +} + +static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags) +{ + struct iphdr *iph; + int ntkoff; + + ntkoff = skb_network_offset(skb); + + if (!pskb_may_pull(skb, sizeof(*iph) + ntkoff)) + goto fail; + + iph = ip_hdr(skb); + + switch (iph->frag_off & htons(IP_OFFSET) ? 0 : iph->protocol) { + case IPPROTO_ICMP: + if (update_flags & TCA_CSUM_UPDATE_FLAG_ICMP) + if (!tcf_csum_ipv4_icmp(skb, + iph->ihl * 4, ntohs(iph->tot_len))) + goto fail; + break; + case IPPROTO_IGMP: + if (update_flags & TCA_CSUM_UPDATE_FLAG_IGMP) + if (!tcf_csum_ipv4_igmp(skb, + iph->ihl * 4, ntohs(iph->tot_len))) + goto fail; + break; + case IPPROTO_TCP: + if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP) + if (!tcf_csum_ipv4_tcp(skb, iph, + iph->ihl * 4, ntohs(iph->tot_len))) + goto fail; + break; + case IPPROTO_UDP: + if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP) + if (!tcf_csum_ipv4_udp(skb, iph, + iph->ihl * 4, ntohs(iph->tot_len), 0)) + goto fail; + break; + case IPPROTO_UDPLITE: + if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE) + if (!tcf_csum_ipv4_udp(skb, iph, + iph->ihl * 4, ntohs(iph->tot_len), 1)) + goto fail; + break; + } + + if (update_flags & TCA_CSUM_UPDATE_FLAG_IPV4HDR) { + if (skb_cloned(skb) && + !skb_clone_writable(skb, sizeof(*iph) + ntkoff) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto fail; + + ip_send_check(iph); + } + + return 1; + +fail: + return 0; +} + +static int tcf_csum_ipv6_hopopts(struct ipv6_opt_hdr *ip6xh, + unsigned int ixhl, unsigned int *pl) +{ + int off, len, optlen; + unsigned char *xh = (void *)ip6xh; + + off = sizeof(*ip6xh); + len = ixhl - off; + + while (len > 1) { + switch (xh[off]) + { + case IPV6_TLV_PAD0: + optlen = 1; + break; + case IPV6_TLV_JUMBO: + optlen = xh[off + 1] + 2; + if (optlen != 6 || len < 6 || (off & 3) != 2) + /* wrong jumbo option length/alignment */ + return 0; + *pl = ntohl(*(__be32 *)(xh + off + 2)); + goto done; + default: + optlen = xh[off + 1] + 2; + if (optlen > len) + /* ignore obscure options */ + goto done; + break; + } + off += optlen; + len -= optlen; + } + +done: + return 1; +} + +static int tcf_csum_ipv6(struct sk_buff *skb, u32 update_flags) +{ + struct ipv6hdr *ip6h; + struct ipv6_opt_hdr *ip6xh; + unsigned int hl, ixhl; + unsigned int pl; + int ntkoff; + u8 nexthdr; + + ntkoff = skb_network_offset(skb); + + hl = sizeof(*ip6h); + + if (!pskb_may_pull(skb, hl + ntkoff)) + goto fail; + + ip6h = ipv6_hdr(skb); + + pl = ntohs(ip6h->payload_len); + nexthdr = ip6h->nexthdr; + + do { + switch (nexthdr) { + case NEXTHDR_FRAGMENT: + goto ignore_skb; + case NEXTHDR_ROUTING: + case NEXTHDR_HOP: + case NEXTHDR_DEST: + if (!pskb_may_pull(skb, hl + sizeof(*ip6xh) + ntkoff)) + goto fail; + ip6xh = (void *)(skb_network_header(skb) + hl); + ixhl = ipv6_optlen(ip6xh); + if (!pskb_may_pull(skb, hl + ixhl + ntkoff)) + goto fail; + if ((nexthdr == NEXTHDR_HOP) && + !(tcf_csum_ipv6_hopopts(ip6xh, ixhl, &pl))) + goto fail; + nexthdr = ip6xh->nexthdr; + hl += ixhl; + break; + case IPPROTO_ICMPV6: + if (update_flags & TCA_CSUM_UPDATE_FLAG_ICMP) + if (!tcf_csum_ipv6_icmp(skb, ip6h, + hl, pl + sizeof(*ip6h))) + goto fail; + goto done; + case IPPROTO_TCP: + if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP) + if (!tcf_csum_ipv6_tcp(skb, ip6h, + hl, pl + sizeof(*ip6h))) + goto fail; + goto done; + case IPPROTO_UDP: + if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP) + if (!tcf_csum_ipv6_udp(skb, ip6h, + hl, pl + sizeof(*ip6h), 0)) + goto fail; + goto done; + case IPPROTO_UDPLITE: + if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE) + if (!tcf_csum_ipv6_udp(skb, ip6h, + hl, pl + sizeof(*ip6h), 1)) + goto fail; + goto done; + default: + goto ignore_skb; + } + } while (pskb_may_pull(skb, hl + 1 + ntkoff)); + +done: +ignore_skb: + return 1; + +fail: + return 0; +} + +static int tcf_csum(struct sk_buff *skb, + struct tc_action *a, struct tcf_result *res) +{ + struct tcf_csum *p = a->priv; + int action; + u32 update_flags; + + spin_lock(&p->tcf_lock); + p->tcf_tm.lastuse = jiffies; + p->tcf_bstats.bytes += qdisc_pkt_len(skb); + p->tcf_bstats.packets++; + action = p->tcf_action; + update_flags = p->update_flags; + spin_unlock(&p->tcf_lock); + + if (unlikely(action == TC_ACT_SHOT)) + goto drop; + + switch (skb->protocol) { + case cpu_to_be16(ETH_P_IP): + if (!tcf_csum_ipv4(skb, update_flags)) + goto drop; + break; + case cpu_to_be16(ETH_P_IPV6): + if (!tcf_csum_ipv6(skb, update_flags)) + goto drop; + break; + } + + return action; + +drop: + spin_lock(&p->tcf_lock); + p->tcf_qstats.drops++; + spin_unlock(&p->tcf_lock); + return TC_ACT_SHOT; +} + +static int tcf_csum_dump(struct sk_buff *skb, + struct tc_action *a, int bind, int ref) +{ + unsigned char *b = skb_tail_pointer(skb); + struct tcf_csum *p = a->priv; + struct tc_csum opt = { + .update_flags = p->update_flags, + + .index = p->tcf_index, + .action = p->tcf_action, + .refcnt = p->tcf_refcnt - ref, + .bindcnt = p->tcf_bindcnt - bind, + }; + struct tcf_t t; + + NLA_PUT(skb, TCA_CSUM_PARMS, sizeof(opt), &opt); + t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); + t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); + t.expires = jiffies_to_clock_t(p->tcf_tm.expires); + NLA_PUT(skb, TCA_CSUM_TM, sizeof(t), &t); + + return skb->len; + +nla_put_failure: + nlmsg_trim(skb, b); + return -1; +} + +static struct tc_action_ops act_csum_ops = { + .kind = "csum", + .hinfo = &csum_hash_info, + .type = TCA_ACT_CSUM, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_csum, + .dump = tcf_csum_dump, + .cleanup = tcf_csum_cleanup, + .lookup = tcf_hash_search, + .init = tcf_csum_init, + .walk = tcf_generic_walker +}; + +MODULE_DESCRIPTION("Checksum updating actions"); +MODULE_LICENSE("GPL"); + +static int __init csum_init_module(void) +{ + return tcf_register_action(&act_csum_ops); +} + +static void __exit csum_cleanup_module(void) +{ + tcf_unregister_action(&act_csum_ops); +} + +module_init(csum_init_module); +module_exit(csum_cleanup_module); -- cgit v1.2.3-59-g8ed1b From 960bc368e7561791b94b749087d2e0d7b36d231c Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 20 Aug 2010 19:10:38 +0900 Subject: sh: reinstate clock framework rate rounding. This was killed off by a simplification patch previously that failed to take the cpufreq use case in to account, so reinstate the old bounding logic. The lowest rate bounding on the other hand was broken in that it never actually got assigned a rate and the best fit rate was instead just getting lucky based on the ordering of the rate table, fix this up so the code actually does what it was intended to do originally. Signed-off-by: Paul Mundt --- drivers/sh/clk.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/sh/clk.c b/drivers/sh/clk.c index cede14e34507..b9c57a640c24 100644 --- a/drivers/sh/clk.c +++ b/drivers/sh/clk.c @@ -1,7 +1,7 @@ /* * drivers/sh/clk.c - SuperH clock framework * - * Copyright (C) 2005 - 2009 Paul Mundt + * Copyright (C) 2005 - 2010 Paul Mundt * * This clock framework is derived from the OMAP version by: * @@ -73,14 +73,23 @@ long clk_rate_table_round(struct clk *clk, { unsigned long rate_error, rate_error_prev = ~0UL; unsigned long rate_best_fit = rate; + unsigned long highest, lowest; int i; + highest = 0; + lowest = ~0UL; + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned long freq = freq_table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; + if (freq > highest) + highest = freq; + if (freq < lowest) + lowest = freq; + rate_error = abs(freq - rate); if (rate_error < rate_error_prev) { rate_best_fit = freq; @@ -91,6 +100,11 @@ long clk_rate_table_round(struct clk *clk, break; } + if (rate >= highest) + rate_best_fit = highest; + if (rate <= lowest) + rate_best_fit = lowest; + return rate_best_fit; } -- cgit v1.2.3-59-g8ed1b From b67696b40f2e7f890d017db3c6805ff90cb392b6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 19 Aug 2010 14:40:25 +0800 Subject: ASoC: e740_wm9705 - free gpio in e740_exit() In e740_init(), we call gpio_request() for GPIO_E740_MIC_ON, GPIO_E740_AMP_ON and GPIO_E740_WM9705_nAVDD2. We should free the these gpio accordingly in e740_exit(). Signed-off-by: Axel Lin Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/pxa/e740_wm9705.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index f614607b2055..c82cedb602fd 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -198,6 +198,9 @@ free_mic_amp_gpio: static void __exit e740_exit(void) { platform_device_unregister(e740_snd_device); + gpio_free(GPIO_E740_WM9705_nAVDD2); + gpio_free(GPIO_E740_AMP_ON); + gpio_free(GPIO_E740_MIC_ON); } module_init(e740_init); -- cgit v1.2.3-59-g8ed1b From c04019d450a885a095a2ca38fcd5db8d57cd2718 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 19 Aug 2010 16:43:42 -0500 Subject: ASoC: add support for separate codec DAIs to the fsl_dma driver Some codecs have separate DAIs for playback and capture, so the DMA driver should allocate a DMA buffer only for the streams that are valid when the driver is opened. Signed-off-by: Timur Tabi Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_dma.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 57774cb91ae3..5a6f56d63756 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -303,21 +303,29 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = fsl_dma_dmamask; - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, - fsl_dma_hardware.buffer_bytes_max, - &pcm->streams[0].substream->dma_buffer); - if (ret) { - dev_err(card->dev, "can't allocate playback dma buffer\n"); - return ret; + /* Some codecs have separate DAIs for playback and capture, so we + * should allocate a DMA buffer only for the streams that are valid. + */ + + if (dai->driver->playback.channels_min) { + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, + fsl_dma_hardware.buffer_bytes_max, + &pcm->streams[0].substream->dma_buffer); + if (ret) { + dev_err(card->dev, "can't alloc playback dma buffer\n"); + return ret; + } } - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, - fsl_dma_hardware.buffer_bytes_max, - &pcm->streams[1].substream->dma_buffer); - if (ret) { - snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); - dev_err(card->dev, "can't allocate capture dma buffer\n"); - return ret; + if (dai->driver->capture.channels_min) { + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, + fsl_dma_hardware.buffer_bytes_max, + &pcm->streams[1].substream->dma_buffer); + if (ret) { + snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); + dev_err(card->dev, "can't alloc capture dma buffer\n"); + return ret; + } } return 0; -- cgit v1.2.3-59-g8ed1b From 6184f105aa75009e6d380b59316305079a44a6ee Mon Sep 17 00:00:00 2001 From: Randolph Chung Date: Fri, 20 Aug 2010 12:47:53 +0800 Subject: ASoC: Add support for tlv320aic3007 to tlv320aic3x codec. This patch adds support for the tlv320aic3007 codec to the tlv320aic3x driver. The tlv320aic3007 is similar to the aic31, but has an additional class-D speaker amp. The speaker amp control register overlaps with the mono output register of other codecs in this family, so we add logic to identify the actual codec being registered to set things up accordingly. Signed-off-by: Randolph Chung Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 79 ++++++++++++++++++++++++++++++++++++------ sound/soc/codecs/tlv320aic3x.h | 2 ++ 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 867bf1fb1825..c07465720cdb 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -12,11 +12,11 @@ * * Notes: * The AIC3X is a driver for a low power stereo audio - * codecs aic31, aic32, aic33. + * codecs aic31, aic32, aic33, aic3007. * * It supports full aic33 codec functionality. - * The compatibility with aic32, aic31 is as follows: - * aic32 | aic31 + * The compatibility with aic32, aic31 and aic3007 is as follows: + * aic32/aic3007 | aic31 * --------------------------------------- * MONO_LOUT -> N/A | MONO_LOUT -> N/A * | IN1L -> LINE1L @@ -70,6 +70,10 @@ struct aic3x_priv { unsigned int sysclk; int master; int gpio_reset; +#define AIC3X_MODEL_3X 0 +#define AIC3X_MODEL_33 1 +#define AIC3X_MODEL_3007 2 + u16 model; }; /* @@ -361,6 +365,14 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), }; +/* + * Class-D amplifier gain. From 0 to 18 dB in 6 dB steps + */ +static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0); + +static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl = + SOC_DOUBLE_TLV("Class-D Amplifier Gain", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv); + /* Left DAC Mux */ static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]); @@ -589,6 +601,15 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { SND_SOC_DAPM_INPUT("LINE2R"), }; +static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = { + /* Class-D outputs */ + SND_SOC_DAPM_PGA("Left Class-D Out", CLASSD_CTRL, 3, 0, NULL, 0), + SND_SOC_DAPM_PGA("Right Class-D Out", CLASSD_CTRL, 2, 0, NULL, 0), + + SND_SOC_DAPM_OUTPUT("SPOP"), + SND_SOC_DAPM_OUTPUT("SPOM"), +}; + static const struct snd_soc_dapm_route intercon[] = { /* Left Output */ {"Left DAC Mux", "DAC_L1", "Left DAC"}, @@ -759,14 +780,30 @@ static const struct snd_soc_dapm_route intercon[] = { {"GPIO1 dmic modclk", NULL, "DMic Rate 32"}, }; +static const struct snd_soc_dapm_route intercon_3007[] = { + /* Class-D outputs */ + {"Left Class-D Out", NULL, "Left Line Out"}, + {"Right Class-D Out", NULL, "Left Line Out"}, + {"SPOP", NULL, "Left Class-D Out"}, + {"SPOM", NULL, "Right Class-D Out"}, +}; + static int aic3x_add_widgets(struct snd_soc_codec *codec) { + struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); + snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, ARRAY_SIZE(aic3x_dapm_widgets)); /* set up audio path interconnects */ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); + if (aic3x->model == AIC3X_MODEL_3007) { + snd_soc_dapm_new_controls(codec, aic3007_dapm_widgets, + ARRAY_SIZE(aic3007_dapm_widgets)); + snd_soc_dapm_add_routes(codec, intercon_3007, ARRAY_SIZE(intercon_3007)); + } + return 0; } @@ -1151,6 +1188,7 @@ static int aic3x_resume(struct snd_soc_codec *codec) */ static int aic3x_init(struct snd_soc_codec *codec) { + struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); int reg; aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); @@ -1219,6 +1257,17 @@ static int aic3x_init(struct snd_soc_codec *codec) aic3x_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL); aic3x_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); + if (aic3x->model == AIC3X_MODEL_3007) { + /* Class-D speaker driver init; datasheet p. 46 */ + aic3x_write(codec, AIC3X_PAGE_SELECT, 0x0D); + aic3x_write(codec, 0xD, 0x0D); + aic3x_write(codec, 0x8, 0x5C); + aic3x_write(codec, 0x8, 0x5D); + aic3x_write(codec, 0x8, 0x5C); + aic3x_write(codec, AIC3X_PAGE_SELECT, 0x00); + aic3x_write(codec, CLASSD_CTRL, 0); + } + /* off, with power on */ aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1244,6 +1293,8 @@ static int aic3x_probe(struct snd_soc_codec *codec) snd_soc_add_controls(codec, aic3x_snd_controls, ARRAY_SIZE(aic3x_snd_controls)); + if (aic3x->model == AIC3X_MODEL_3007) + snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); aic3x_add_widgets(codec); @@ -1275,6 +1326,14 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = { * 0x18, 0x19, 0x1A, 0x1B */ +static const struct i2c_device_id aic3x_i2c_id[] = { + [AIC3X_MODEL_3X] = { "tlv320aic3x", 0 }, + [AIC3X_MODEL_33] = { "tlv320aic33", 0 }, + [AIC3X_MODEL_3007] = { "tlv320aic3007", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); + /* * If the i2c layer weren't so broken, we could pass this kind of data * around @@ -1286,6 +1345,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, struct aic3x_setup_data *setup = pdata->setup; struct aic3x_priv *aic3x; int ret, i; + const struct i2c_device_id *tbl; aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); if (aic3x == NULL) { @@ -1306,6 +1366,12 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, gpio_direction_output(aic3x->gpio_reset, 0); } + for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) { + if (!strcmp(tbl->name, id->name)) + break; + } + aic3x->model = tbl - aic3x_i2c_id; + for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) aic3x->supplies[i].supply = aic3x_supply_names[i]; @@ -1360,13 +1426,6 @@ static int aic3x_i2c_remove(struct i2c_client *client) return 0; } -static const struct i2c_device_id aic3x_i2c_id[] = { - { "tlv320aic3x", 0 }, - { "tlv320aic33", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); - /* machine i2c codec control layer */ static struct i2c_driver aic3x_i2c_driver = { .driver = { diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index f6e3d9b42daf..98e44395b662 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -111,6 +111,8 @@ #define DACL1_2_MONOLOPM_VOL 75 #define DACR1_2_MONOLOPM_VOL 78 #define MONOLOPM_CTRL 79 +/* Class-D speaker driver on tlv320aic3007 */ +#define CLASSD_CTRL 73 /* Line Output Plus/Minus control registers */ #define LINE2L_2_LLOPM_VOL 80 #define LINE2L_2_RLOPM_VOL 87 -- cgit v1.2.3-59-g8ed1b From b9c1261db46a4afdaebf08233d1c1e47f2d93979 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 20 Aug 2010 13:23:36 +0800 Subject: ASoC: remove include of pxa2xx-pcm.h in pxa2xx-ac97.c Fix reference to moved header file, which was unused anyway. This change fixes below build error: CC sound/soc/pxa/pxa2xx-ac97.o sound/soc/pxa/pxa2xx-ac97.c:27:24: error: pxa2xx-pcm.h: No such file or directory make[3]: *** [sound/soc/pxa/pxa2xx-ac97.o] Error 1 make[2]: *** [sound/soc/pxa] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 Signed-off-by: Axel Lin Signed-off-by: Haojian Zhuang Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-ac97.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 9c2bafa112ad..ac51c6d25c42 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -24,7 +24,6 @@ #include #include -#include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) -- cgit v1.2.3-59-g8ed1b From 27ef3744f85bbbd00175ce7e9ac46b52089ee83c Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 19 Aug 2010 17:11:40 -0500 Subject: ASoC: add support for the Freescale P1022 DS reference board The Freescale P1022 is a dual-core e500-based SOC with multimedia capabilities, specifically the same SSI audio controller on the MPC8610. The P1022 DS reference board includes a P1022 and a Wolfson Microelectronics WM8776 codec. Signed-off-by: Timur Tabi Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 24 +- sound/soc/fsl/Makefile | 8 +- sound/soc/fsl/p1022_ds.c | 590 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 614 insertions(+), 8 deletions(-) create mode 100644 sound/soc/fsl/p1022_ds.c diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 981868700388..d754d34d68a6 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,24 +1,36 @@ config SND_MPC52xx_DMA tristate -# ASoC platform support for the Freescale MPC8610 SOC. This compiles drivers -# for the SSI and the Elo DMA controller. You will still need to select -# a platform driver and a codec driver. -config SND_SOC_MPC8610 +# ASoC platform support for the Freescale PowerPC SOCs that have an SSI and +# an Elo DMA controller, such as the MPC8610 and P1022. You will still need to +# select a platform driver and a codec driver. +config SND_SOC_POWERPC_SSI tristate - depends on MPC8610 + depends on FSL_SOC config SND_SOC_MPC8610_HPCD tristate "ALSA SoC support for the Freescale MPC8610 HPCD board" # I2C is necessary for the CS4270 driver depends on MPC8610_HPCD && I2C - select SND_SOC_MPC8610 + select SND_SOC_POWERPC_SSI select SND_SOC_CS4270 select SND_SOC_CS4270_VD33_ERRATA default y if MPC8610_HPCD help Say Y if you want to enable audio on the Freescale MPC8610 HPCD. +config SND_SOC_P1022_DS + tristate "ALSA SoC support for the Freescale P1022 DS board" + # I2C is necessary for the WM8776 driver + depends on P1022_DS && I2C + select SND_SOC_POWERPC_SSI + select SND_SOC_WM8776 + default y if P1022_DS + help + Say Y if you want to enable audio on the Freescale P1022 DS board. + This will also include the Wolfson Microelectronics WM8776 codec + driver. + config SND_SOC_MPC5200_I2S tristate "Freescale MPC5200 PSC in I2S mode driver" depends on PPC_MPC52xx && PPC_BESTCOMM diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 7e472a53fcd3..b4a38c0ac58c 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -2,10 +2,14 @@ snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o -# MPC8610 Platform Support +# P1022 DS Machine Support +snd-soc-p1022-ds-objs := p1022_ds.o +obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o + +# Freescale PowerPC SSI/DMA Platform Support snd-soc-fsl-ssi-objs := fsl_ssi.o snd-soc-fsl-dma-objs := fsl_dma.o -obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o +obj-$(CONFIG_SND_SOC_POWERPC_SSI) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o # MPC5200 Platform Support obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c new file mode 100644 index 000000000000..f8176e8e1adf --- /dev/null +++ b/sound/soc/fsl/p1022_ds.c @@ -0,0 +1,590 @@ +/** + * Freescale P1022DS ALSA SoC Machine driver + * + * Author: Timur Tabi + * + * Copyright 2010 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include + +#include "fsl_dma.h" +#include "fsl_ssi.h" + +/* P1022-specific PMUXCR and DMUXCR bit definitions */ + +#define CCSR_GUTS_PMUXCR_UART0_I2C1_MASK 0x0001c000 +#define CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI 0x00010000 +#define CCSR_GUTS_PMUXCR_UART0_I2C1_SSI 0x00018000 + +#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK 0x00000c00 +#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI 0x00000000 + +#define CCSR_GUTS_DMUXCR_PAD 1 /* DMA controller/channel set to pad */ +#define CCSR_GUTS_DMUXCR_SSI 2 /* DMA controller/channel set to SSI */ + +/* + * Set the DMACR register in the GUTS + * + * The DMACR register determines the source of initiated transfers for each + * channel on each DMA controller. Rather than have a bunch of repetitive + * macros for the bit patterns, we just have a function that calculates + * them. + * + * guts: Pointer to GUTS structure + * co: The DMA controller (0 or 1) + * ch: The channel on the DMA controller (0, 1, 2, or 3) + * device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx) + */ +static inline void guts_set_dmuxcr(struct ccsr_guts_85xx __iomem *guts, + unsigned int co, unsigned int ch, unsigned int device) +{ + unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); + + clrsetbits_be32(&guts->dmuxcr, 3 << shift, device << shift); +} + +/* There's only one global utilities register */ +static phys_addr_t guts_phys; + +#define DAI_NAME_SIZE 32 + +/** + * machine_data: machine-specific ASoC device data + * + * This structure contains data for a single sound platform device on an + * P1022 DS. Some of the data is taken from the device tree. + */ +struct machine_data { + struct snd_soc_dai_link dai[2]; + struct snd_soc_card card; + unsigned int dai_format; + unsigned int codec_clk_direction; + unsigned int cpu_clk_direction; + unsigned int clk_frequency; + unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */ + unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */ + unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/ + char codec_name[DAI_NAME_SIZE]; + char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */ +}; + +/** + * p1022_ds_machine_probe: initialize the board + * + * This function is used to initialize the board-specific hardware. + * + * Here we program the DMACR and PMUXCR registers. + */ +static int p1022_ds_machine_probe(struct platform_device *sound_device) +{ + struct snd_soc_card *card = platform_get_drvdata(sound_device); + struct machine_data *mdata = + container_of(card, struct machine_data, card); + struct ccsr_guts_85xx __iomem *guts; + + guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx)); + if (!guts) { + dev_err(card->dev, "could not map global utilities\n"); + return -ENOMEM; + } + + /* Enable SSI Tx signal */ + clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK, + CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI); + + /* Enable SSI Rx signal */ + clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK, + CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI); + + /* Enable DMA Channel for SSI */ + guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0], + CCSR_GUTS_DMUXCR_SSI); + + guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1], + CCSR_GUTS_DMUXCR_SSI); + + iounmap(guts); + + return 0; +} + +/** + * p1022_ds_startup: program the board with various hardware parameters + * + * This function takes board-specific information, like clock frequencies + * and serial data formats, and passes that information to the codec and + * transport drivers. + */ +static int p1022_ds_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct machine_data *mdata = + container_of(rtd->card, struct machine_data, card); + struct device *dev = rtd->card->dev; + int ret = 0; + + /* Tell the codec driver what the serial protocol is. */ + ret = snd_soc_dai_set_fmt(rtd->codec_dai, mdata->dai_format); + if (ret < 0) { + dev_err(dev, "could not set codec driver audio format\n"); + return ret; + } + + /* + * Tell the codec driver what the MCLK frequency is, and whether it's + * a slave or master. + */ + ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, mdata->clk_frequency, + mdata->codec_clk_direction); + if (ret < 0) { + dev_err(dev, "could not set codec driver clock params\n"); + return ret; + } + + return 0; +} + +/** + * p1022_ds_machine_remove: Remove the sound device + * + * This function is called to remove the sound device for one SSI. We + * de-program the DMACR and PMUXCR register. + */ +static int p1022_ds_machine_remove(struct platform_device *sound_device) +{ + struct snd_soc_card *card = platform_get_drvdata(sound_device); + struct machine_data *mdata = + container_of(card, struct machine_data, card); + struct ccsr_guts_85xx __iomem *guts; + + guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx)); + if (!guts) { + dev_err(card->dev, "could not map global utilities\n"); + return -ENOMEM; + } + + /* Restore the signal routing */ + clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK); + clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK); + guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0], 0); + guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1], 0); + + iounmap(guts); + + return 0; +} + +/** + * p1022_ds_ops: ASoC machine driver operations + */ +static struct snd_soc_ops p1022_ds_ops = { + .startup = p1022_ds_startup, +}; + +/** + * get_node_by_phandle_name - get a node by its phandle name + * + * This function takes a node, the name of a property in that node, and a + * compatible string. Assuming the property is a phandle to another node, + * it returns that node, (optionally) if that node is compatible. + * + * If the property is not a phandle, or the node it points to is not compatible + * with the specific string, then NULL is returned. + */ +static struct device_node *get_node_by_phandle_name(struct device_node *np, + const char *name, const char *compatible) +{ + np = of_parse_phandle(np, name, 0); + if (!np) + return NULL; + + if (!of_device_is_compatible(np, compatible)) { + of_node_put(np); + return NULL; + } + + return np; +} + +/** + * get_parent_cell_index -- return the cell-index of the parent of a node + * + * Return the value of the cell-index property of the parent of the given + * node. This is used for DMA channel nodes that need to know the DMA ID + * of the controller they are on. + */ +static int get_parent_cell_index(struct device_node *np) +{ + struct device_node *parent = of_get_parent(np); + const u32 *iprop; + int ret = -1; + + if (!parent) + return -1; + + iprop = of_get_property(parent, "cell-index", NULL); + if (iprop) + ret = *iprop; + + of_node_put(parent); + + return ret; +} + +/** + * codec_node_dev_name - determine the dev_name for a codec node + * + * This function determines the dev_name for an I2C node. This is the name + * that would be returned by dev_name() if this device_node were part of a + * 'struct device' It's ugly and hackish, but it works. + * + * The dev_name for such devices include the bus number and I2C address. For + * example, "cs4270-codec.0-004f". + */ +static int codec_node_dev_name(struct device_node *np, char *buf, size_t len) +{ + const u32 *iprop; + int bus, addr; + char temp[DAI_NAME_SIZE]; + + of_modalias_node(np, temp, DAI_NAME_SIZE); + + iprop = of_get_property(np, "reg", NULL); + if (!iprop) + return -EINVAL; + + addr = *iprop; + + bus = get_parent_cell_index(np); + if (bus < 0) + return bus; + + snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr); + + return 0; +} + +static int get_dma_channel(struct device_node *ssi_np, + const char *compatible, + struct snd_soc_dai_link *dai, + unsigned int *dma_channel_id, + unsigned int *dma_id) +{ + struct resource res; + struct device_node *dma_channel_np; + const u32 *iprop; + int ret; + + dma_channel_np = get_node_by_phandle_name(ssi_np, compatible, + "fsl,ssi-dma-channel"); + if (!dma_channel_np) + return -EINVAL; + + /* Determine the dev_name for the device_node. This code mimics the + * behavior of of_device_make_bus_id(). We need this because ASoC uses + * the dev_name() of the device to match the platform (DMA) device with + * the CPU (SSI) device. It's all ugly and hackish, but it works (for + * now). + * + * dai->platform name should already point to an allocated buffer. + */ + ret = of_address_to_resource(dma_channel_np, 0, &res); + if (ret) + return ret; + snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", + (unsigned long long) res.start, dma_channel_np->name); + + iprop = of_get_property(dma_channel_np, "cell-index", NULL); + if (!iprop) { + of_node_put(dma_channel_np); + return -EINVAL; + } + + *dma_channel_id = *iprop; + *dma_id = get_parent_cell_index(dma_channel_np); + of_node_put(dma_channel_np); + + return 0; +} + +/** + * p1022_ds_probe: platform probe function for the machine driver + * + * Although this is a machine driver, the SSI node is the "master" node with + * respect to audio hardware connections. Therefore, we create a new ASoC + * device for each new SSI node that has a codec attached. + */ +static int p1022_ds_probe(struct platform_device *pdev) +{ + struct device *dev = pdev->dev.parent; + /* ssi_pdev is the platform device for the SSI node that probed us */ + struct platform_device *ssi_pdev = + container_of(dev, struct platform_device, dev); + struct device_node *np = ssi_pdev->dev.of_node; + struct device_node *codec_np = NULL; + struct platform_device *sound_device = NULL; + struct machine_data *mdata; + int ret = -ENODEV; + const char *sprop; + const u32 *iprop; + + /* Find the codec node for this SSI. */ + codec_np = of_parse_phandle(np, "codec-handle", 0); + if (!codec_np) { + dev_err(dev, "could not find codec node\n"); + return -EINVAL; + } + + mdata = kzalloc(sizeof(struct machine_data), GFP_KERNEL); + if (!mdata) + return -ENOMEM; + + mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); + mdata->dai[0].ops = &p1022_ds_ops; + + /* Determine the codec name, it will be used as the codec DAI name */ + ret = codec_node_dev_name(codec_np, mdata->codec_name, DAI_NAME_SIZE); + if (ret) { + dev_err(&pdev->dev, "invalid codec node %s\n", + codec_np->full_name); + ret = -EINVAL; + goto error; + } + mdata->dai[0].codec_name = mdata->codec_name; + + /* We register two DAIs per SSI, one for playback and the other for + * capture. We support codecs that have separate DAIs for both playback + * and capture. + */ + memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link)); + + /* The DAI names from the codec (snd_soc_dai_driver.name) */ + mdata->dai[0].codec_dai_name = "wm8776-hifi-playback"; + mdata->dai[1].codec_dai_name = "wm8776-hifi-capture"; + + /* Get the device ID */ + iprop = of_get_property(np, "cell-index", NULL); + if (!iprop) { + dev_err(&pdev->dev, "cell-index property not found\n"); + ret = -EINVAL; + goto error; + } + mdata->ssi_id = *iprop; + + /* Get the serial format and clock direction. */ + sprop = of_get_property(np, "fsl,mode", NULL); + if (!sprop) { + dev_err(&pdev->dev, "fsl,mode property not found\n"); + ret = -EINVAL; + goto error; + } + + if (strcasecmp(sprop, "i2s-slave") == 0) { + mdata->dai_format = SND_SOC_DAIFMT_I2S; + mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; + mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; + + /* In i2s-slave mode, the codec has its own clock source, so we + * need to get the frequency from the device tree and pass it to + * the codec driver. + */ + iprop = of_get_property(codec_np, "clock-frequency", NULL); + if (!iprop || !*iprop) { + dev_err(&pdev->dev, "codec bus-frequency " + "property is missing or invalid\n"); + ret = -EINVAL; + goto error; + } + mdata->clk_frequency = *iprop; + } else if (strcasecmp(sprop, "i2s-master") == 0) { + mdata->dai_format = SND_SOC_DAIFMT_I2S; + mdata->codec_clk_direction = SND_SOC_CLOCK_IN; + mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; + } else if (strcasecmp(sprop, "lj-slave") == 0) { + mdata->dai_format = SND_SOC_DAIFMT_LEFT_J; + mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; + mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; + } else if (strcasecmp(sprop, "lj-master") == 0) { + mdata->dai_format = SND_SOC_DAIFMT_LEFT_J; + mdata->codec_clk_direction = SND_SOC_CLOCK_IN; + mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; + } else if (strcasecmp(sprop, "rj-slave") == 0) { + mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J; + mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; + mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; + } else if (strcasecmp(sprop, "rj-master") == 0) { + mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J; + mdata->codec_clk_direction = SND_SOC_CLOCK_IN; + mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; + } else if (strcasecmp(sprop, "ac97-slave") == 0) { + mdata->dai_format = SND_SOC_DAIFMT_AC97; + mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; + mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; + } else if (strcasecmp(sprop, "ac97-master") == 0) { + mdata->dai_format = SND_SOC_DAIFMT_AC97; + mdata->codec_clk_direction = SND_SOC_CLOCK_IN; + mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; + } else { + dev_err(&pdev->dev, + "unrecognized fsl,mode property '%s'\n", sprop); + ret = -EINVAL; + goto error; + } + + if (!mdata->clk_frequency) { + dev_err(&pdev->dev, "unknown clock frequency\n"); + ret = -EINVAL; + goto error; + } + + /* Find the playback DMA channel to use. */ + mdata->dai[0].platform_name = mdata->platform_name[0]; + ret = get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0], + &mdata->dma_channel_id[0], + &mdata->dma_id[0]); + if (ret) { + dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n"); + goto error; + } + + /* Find the capture DMA channel to use. */ + mdata->dai[1].platform_name = mdata->platform_name[1]; + ret = get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1], + &mdata->dma_channel_id[1], + &mdata->dma_id[1]); + if (ret) { + dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n"); + goto error; + } + + /* Initialize our DAI data structure. */ + mdata->dai[0].stream_name = "playback"; + mdata->dai[1].stream_name = "capture"; + mdata->dai[0].name = mdata->dai[0].stream_name; + mdata->dai[1].name = mdata->dai[1].stream_name; + + mdata->card.probe = p1022_ds_machine_probe; + mdata->card.remove = p1022_ds_machine_remove; + mdata->card.name = pdev->name; /* The platform driver name */ + mdata->card.num_links = 2; + mdata->card.dai_link = mdata->dai; + + /* Allocate a new audio platform device structure */ + sound_device = platform_device_alloc("soc-audio", -1); + if (!sound_device) { + dev_err(&pdev->dev, "platform device alloc failed\n"); + ret = -ENOMEM; + goto error; + } + + /* Associate the card data with the sound device */ + platform_set_drvdata(sound_device, &mdata->card); + + /* Register with ASoC */ + ret = platform_device_add(sound_device); + if (ret) { + dev_err(&pdev->dev, "platform device add failed\n"); + goto error; + } + + of_node_put(codec_np); + + return 0; + +error: + of_node_put(codec_np); + + if (sound_device) + platform_device_unregister(sound_device); + + kfree(mdata); + + return ret; +} + +/** + * p1022_ds_remove: remove the platform device + * + * This function is called when the platform device is removed. + */ +static int __devexit p1022_ds_remove(struct platform_device *pdev) +{ + struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); + struct snd_soc_card *card = platform_get_drvdata(sound_device); + struct machine_data *mdata = + container_of(card, struct machine_data, card); + + platform_device_unregister(sound_device); + + kfree(mdata); + sound_device->dev.platform_data = NULL; + + dev_set_drvdata(&pdev->dev, NULL); + + return 0; +} + +static struct platform_driver p1022_ds_driver = { + .probe = p1022_ds_probe, + .remove = __devexit_p(p1022_ds_remove), + .driver = { + /* The name must match the 'model' property in the device tree, + * in lowercase letters, but only the part after that last + * comma. This is because some model properties have a "fsl," + * prefix. + */ + .name = "snd-soc-p1022", + .owner = THIS_MODULE, + }, +}; + +/** + * p1022_ds_init: machine driver initialization. + * + * This function is called when this module is loaded. + */ +static int __init p1022_ds_init(void) +{ + struct device_node *guts_np; + struct resource res; + + pr_info("Freescale P1022 DS ALSA SoC machine driver\n"); + + /* Get the physical address of the global utilities registers */ + guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); + if (of_address_to_resource(guts_np, 0, &res)) { + pr_err("p1022-ds: missing/invalid global utilities node\n"); + return -EINVAL; + } + guts_phys = res.start; + of_node_put(guts_np); + + return platform_driver_register(&p1022_ds_driver); +} + +/** + * p1022_ds_exit: machine driver exit + * + * This function is called when this driver is unloaded. + */ +static void __exit p1022_ds_exit(void) +{ + platform_driver_unregister(&p1022_ds_driver); +} + +module_init(p1022_ds_init); +module_exit(p1022_ds_exit); + +MODULE_AUTHOR("Timur Tabi "); +MODULE_DESCRIPTION("Freescale P1022 DS ALSA SoC machine driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-59-g8ed1b From 65c23f54c01fabae171d54c0e78df354b3709b93 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 20 Aug 2010 20:26:41 +0900 Subject: sh: Relax devfn constraints for SH7786 PCIe. SH7786 PCIe has 1 slot per port, but no specific restriction on function. Relax the devfn restriction and look to the slot number instead when configured as a root complex. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/ops-sh7786.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/arch/sh/drivers/pci/ops-sh7786.c b/arch/sh/drivers/pci/ops-sh7786.c index 57134a38686a..79a5ddae733d 100644 --- a/arch/sh/drivers/pci/ops-sh7786.c +++ b/arch/sh/drivers/pci/ops-sh7786.c @@ -25,14 +25,15 @@ static int sh7786_pcie_config_access(unsigned char access_type, struct pci_bus *bus, unsigned int devfn, int where, u32 *data) { struct pci_channel *chan = bus->sysdata; - int dev, func; + int dev, func, type; dev = PCI_SLOT(devfn); func = PCI_FUNC(devfn); + type = !!bus->parent; if (bus->number > 255 || dev > 31 || func > 7) return PCIBIOS_FUNC_NOT_SUPPORTED; - if (devfn) + if (bus->parent == NULL && dev) return PCIBIOS_DEVICE_NOT_FOUND; /* Clear errors */ @@ -43,13 +44,7 @@ static int sh7786_pcie_config_access(unsigned char access_type, (func << 16) | (where & ~3), SH4A_PCIEPAR); /* Enable the configuration access */ - if (bus->number) { - /* Type 1 */ - pci_write_reg(chan, (1 << 31) | (1 << 8), SH4A_PCIEPCTLR); - } else { - /* Type 0 */ - pci_write_reg(chan, (1 << 31), SH4A_PCIEPCTLR); - } + pci_write_reg(chan, (1 << 31) | (type << 8), SH4A_PCIEPCTLR); /* Check for errors */ if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10) -- cgit v1.2.3-59-g8ed1b From d2d5bc58d79321bd29ed1c8c61e806ec0541e3bf Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 20 Aug 2010 20:38:24 +0900 Subject: sh: sh2007/sh7757lcr defconfig reduction. These were newly added while the defconfig reduction work was ongoing, strip them down now. Signed-off-by: Paul Mundt --- arch/sh/configs/sh2007_defconfig | 1144 ----------------------------------- arch/sh/configs/sh7757lcr_defconfig | 1041 ------------------------------- 2 files changed, 2185 deletions(-) diff --git a/arch/sh/configs/sh2007_defconfig b/arch/sh/configs/sh2007_defconfig index adf7a6b05814..c4927962538d 100644 --- a/arch/sh/configs/sh2007_defconfig +++ b/arch/sh/configs/sh2007_defconfig @@ -1,1096 +1,132 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.35-rc2 -# Fri Jun 18 19:46:14 2010 -# -CONFIG_SUPERH=y -CONFIG_SUPERH32=y -# CONFIG_SUPERH64 is not set -CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig" -CONFIG_RWSEM_GENERIC_SPINLOCK=y -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_IRQ_PER_CPU=y -CONFIG_SPARSE_IRQ=y -# CONFIG_GENERIC_GPIO is not set -CONFIG_GENERIC_TIME=y -CONFIG_GENERIC_CLOCKEVENTS=y -# CONFIG_ARCH_SUSPEND_POSSIBLE is not set -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_SYS_SUPPORTS_HUGETLBFS=y -CONFIG_SYS_SUPPORTS_TMU=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_HAVE_LATENCYTOP_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_HAS_DEFAULT_IDLE=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y -CONFIG_NO_IOPORT=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_CONSTRUCTORS=y - -# -# General setup -# CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_CROSS_COMPILE="" -CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_BZIP2=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_BZIP2 is not set -# CONFIG_KERNEL_LZMA is not set -# CONFIG_KERNEL_LZO is not set -CONFIG_SWAP=y CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y CONFIG_BSD_PROCESS_ACCT=y -# CONFIG_BSD_PROCESS_ACCT_V3 is not set -# CONFIG_TASKSTATS is not set CONFIG_AUDIT=y CONFIG_AUDITSYSCALL=y -CONFIG_AUDIT_TREE=y - -# -# RCU Subsystem -# -CONFIG_TREE_RCU=y -# CONFIG_TREE_PREEMPT_RCU is not set -# CONFIG_TINY_RCU is not set -# CONFIG_RCU_TRACE is not set -CONFIG_RCU_FANOUT=32 -# CONFIG_RCU_FANOUT_EXACT is not set -# CONFIG_TREE_RCU_TRACE is not set CONFIG_IKCONFIG=y -# CONFIG_IKCONFIG_PROC is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y -# CONFIG_RELAY is not set -# CONFIG_NAMESPACES is not set -# CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_EMBEDDED=y -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_AIO=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_PERF_USE_VMALLOC=y - -# -# Kernel Performance Events And Counters -# -CONFIG_PERF_EVENTS=y -# CONFIG_PERF_COUNTERS is not set -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_COMPAT_BRK=y CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set -# CONFIG_PROFILING is not set -CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_IOREMAP_PROT=y -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_DMA_ATTRS=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_HW_BREAKPOINT=y -CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y - -# -# GCOV-based kernel profiling -# -# CONFIG_GCOV_KERNEL is not set -# CONFIG_SLOW_WORK is not set -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 -# CONFIG_MODULES is not set -CONFIG_BLOCK=y -CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_INTEGRITY is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" -# CONFIG_INLINE_SPIN_TRYLOCK is not set -# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK is not set -# CONFIG_INLINE_SPIN_LOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK_IRQ is not set -# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set -CONFIG_INLINE_SPIN_UNLOCK=y -# CONFIG_INLINE_SPIN_UNLOCK_BH is not set -CONFIG_INLINE_SPIN_UNLOCK_IRQ=y -# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_READ_TRYLOCK is not set -# CONFIG_INLINE_READ_LOCK is not set -# CONFIG_INLINE_READ_LOCK_BH is not set -# CONFIG_INLINE_READ_LOCK_IRQ is not set -# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set -CONFIG_INLINE_READ_UNLOCK=y -# CONFIG_INLINE_READ_UNLOCK_BH is not set -CONFIG_INLINE_READ_UNLOCK_IRQ=y -# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_WRITE_TRYLOCK is not set -# CONFIG_INLINE_WRITE_LOCK is not set -# CONFIG_INLINE_WRITE_LOCK_BH is not set -# CONFIG_INLINE_WRITE_LOCK_IRQ is not set -# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set -CONFIG_INLINE_WRITE_UNLOCK=y -# CONFIG_INLINE_WRITE_UNLOCK_BH is not set -CONFIG_INLINE_WRITE_UNLOCK_IRQ=y -# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set -# CONFIG_MUTEX_SPIN_ON_OWNER is not set -# CONFIG_FREEZER is not set - -# -# System type -# -CONFIG_CPU_SH4=y -CONFIG_CPU_SH4A=y -# CONFIG_CPU_SUBTYPE_SH7619 is not set -# CONFIG_CPU_SUBTYPE_SH7201 is not set -# CONFIG_CPU_SUBTYPE_SH7203 is not set -# CONFIG_CPU_SUBTYPE_SH7206 is not set -# CONFIG_CPU_SUBTYPE_SH7263 is not set -# CONFIG_CPU_SUBTYPE_MXG is not set -# CONFIG_CPU_SUBTYPE_SH7705 is not set -# CONFIG_CPU_SUBTYPE_SH7706 is not set -# CONFIG_CPU_SUBTYPE_SH7707 is not set -# CONFIG_CPU_SUBTYPE_SH7708 is not set -# CONFIG_CPU_SUBTYPE_SH7709 is not set -# CONFIG_CPU_SUBTYPE_SH7710 is not set -# CONFIG_CPU_SUBTYPE_SH7712 is not set -# CONFIG_CPU_SUBTYPE_SH7720 is not set -# CONFIG_CPU_SUBTYPE_SH7721 is not set -# CONFIG_CPU_SUBTYPE_SH7750 is not set -# CONFIG_CPU_SUBTYPE_SH7091 is not set -# CONFIG_CPU_SUBTYPE_SH7750R is not set -# CONFIG_CPU_SUBTYPE_SH7750S is not set -# CONFIG_CPU_SUBTYPE_SH7751 is not set -# CONFIG_CPU_SUBTYPE_SH7751R is not set -# CONFIG_CPU_SUBTYPE_SH7760 is not set -# CONFIG_CPU_SUBTYPE_SH4_202 is not set -# CONFIG_CPU_SUBTYPE_SH7723 is not set -# CONFIG_CPU_SUBTYPE_SH7724 is not set -# CONFIG_CPU_SUBTYPE_SH7757 is not set -# CONFIG_CPU_SUBTYPE_SH7763 is not set -# CONFIG_CPU_SUBTYPE_SH7770 is not set CONFIG_CPU_SUBTYPE_SH7780=y -# CONFIG_CPU_SUBTYPE_SH7785 is not set -# CONFIG_CPU_SUBTYPE_SH7786 is not set -# CONFIG_CPU_SUBTYPE_SHX3 is not set -# CONFIG_CPU_SUBTYPE_SH7343 is not set -# CONFIG_CPU_SUBTYPE_SH7722 is not set -# CONFIG_CPU_SUBTYPE_SH7366 is not set - -# -# Memory management options -# -CONFIG_QUICKLIST=y -CONFIG_MMU=y -CONFIG_PAGE_OFFSET=0x80000000 -CONFIG_FORCE_MAX_ZONEORDER=11 -CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 -CONFIG_29BIT=y -# CONFIG_PMB is not set # CONFIG_VSYSCALL is not set -CONFIG_ARCH_FLATMEM_ENABLE=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SPARSEMEM_DEFAULT=y -CONFIG_MAX_ACTIVE_REGIONS=1 -CONFIG_ARCH_POPULATES_NODE_MAP=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_UNCACHED_MAPPING=y -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PAGE_SIZE_16KB is not set -# CONFIG_PAGE_SIZE_64KB is not set -CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -CONFIG_SPARSEMEM_STATIC=y -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=1 -# CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 - -# -# Cache configuration -# -CONFIG_CACHE_WRITEBACK=y -# CONFIG_CACHE_WRITETHROUGH is not set -# CONFIG_CACHE_OFF is not set - -# -# Processor features -# -CONFIG_CPU_LITTLE_ENDIAN=y -# CONFIG_CPU_BIG_ENDIAN is not set -CONFIG_SH_FPU=y -# CONFIG_SH_STORE_QUEUES is not set -# CONFIG_SPECULATIVE_EXECUTION is not set -CONFIG_CPU_HAS_INTEVT=y -CONFIG_CPU_HAS_SR_RB=y -CONFIG_CPU_HAS_FPU=y - -# -# Board support -# -# CONFIG_SH_7780_SOLUTION_ENGINE is not set -# CONFIG_SH_SDK7780 is not set -# CONFIG_SH_HIGHLANDER is not set CONFIG_SH_SH2007=y - -# -# Timer and clock configuration -# -CONFIG_SH_TIMER_TMU=y -CONFIG_SH_PCLK_FREQ=50000000 -CONFIG_SH_CLK_CPG=y -CONFIG_SH_CLK_CPG_LEGACY=y -CONFIG_TICK_ONESHOT=y -# CONFIG_NO_HZ is not set CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y - -# -# CPU Frequency scaling -# -# CONFIG_CPU_FREQ is not set - -# -# DMA support -# CONFIG_SH_DMA=y -CONFIG_SH_DMA_IRQ_MULTI=y CONFIG_SH_DMA_API=y -CONFIG_NR_ONCHIP_DMA_CHANNELS=12 CONFIG_NR_DMA_CHANNELS_BOOL=y -CONFIG_NR_DMA_CHANNELS=12 - -# -# Companion Chips -# - -# -# Additional SuperH Device Drivers -# -# CONFIG_HEARTBEAT is not set -# CONFIG_PUSH_SWITCH is not set - -# -# Kernel features -# CONFIG_HZ_100=y -# CONFIG_HZ_250 is not set -# CONFIG_HZ_300 is not set -# CONFIG_HZ_1000 is not set -CONFIG_HZ=100 -CONFIG_SCHED_HRTICK=y -# CONFIG_KEXEC is not set -# CONFIG_CRASH_DUMP is not set -# CONFIG_SECCOMP is not set -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set -# CONFIG_PREEMPT is not set -CONFIG_GUSA=y -# CONFIG_INTC_USERIMASK is not set - -# -# Boot options -# -CONFIG_ZERO_PAGE_OFFSET=0x00001000 -CONFIG_BOOT_LINK_OFFSET=0x00800000 -CONFIG_ENTRY_OFFSET=0x00001000 CONFIG_CMDLINE_OVERWRITE=y -# CONFIG_CMDLINE_EXTEND is not set CONFIG_CMDLINE="console=ttySC1,115200 ip=dhcp root=/dev/nfs rw nfsroot=/nfs/rootfs,rsize=1024,wsize=1024 earlyprintk=sh-sci.1" - -# -# Bus options -# -# CONFIG_ARCH_SUPPORTS_MSI is not set CONFIG_PCCARD=y -CONFIG_PCMCIA=y -CONFIG_PCMCIA_LOAD_CIS=y - -# -# PC-card bridges -# - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -# CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=y - -# -# Power management options (EXPERIMENTAL) -# -# CONFIG_PM is not set -# CONFIG_CPU_IDLE is not set -CONFIG_NET=y - -# -# Networking options -# CONFIG_PACKET=y CONFIG_UNIX=y -CONFIG_XFRM=y CONFIG_XFRM_USER=y -# CONFIG_XFRM_SUB_POLICY is not set -CONFIG_XFRM_MIGRATE=y -# CONFIG_XFRM_STATISTICS is not set CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_ASK_IP_FIB_HASH=y -# CONFIG_IP_FIB_TRIE is not set -CONFIG_IP_FIB_HASH=y CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_MULTIPATH=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set CONFIG_NET_IPIP=y -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=y # CONFIG_INET_XFRM_MODE_TRANSPORT is not set # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_LRO is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set CONFIG_NETWORK_SECMARK=y -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_RDS is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_L2TP is not set -# CONFIG_BRIDGE is not set -# CONFIG_NET_DSA is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_PHONET is not set -# CONFIG_IEEE802154 is not set -# CONFIG_NET_SCHED is not set -# CONFIG_DCB is not set - -# -# Network testing -# CONFIG_NET_PKTGEN=y -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set -CONFIG_FIB_RULES=y -CONFIG_WIRELESS=y -# CONFIG_CFG80211 is not set -# CONFIG_LIB80211 is not set - -# -# CFG80211 needs to be enabled for MAC80211 -# - -# -# Some wireless drivers require a rate control algorithm -# -# CONFIG_WIMAX is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set -# CONFIG_CAIF is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_DEVTMPFS is not set -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y -CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="" -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV=y -# CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set - -# -# DRBD disabled because PROC_FS, INET or CONNECTOR not selected -# -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_XIP is not set CONFIG_CDROM_PKTCDVD=y -CONFIG_CDROM_PKTCDVD_BUFFERS=8 -# CONFIG_CDROM_PKTCDVD_WCACHE is not set -# CONFIG_ATA_OVER_ETH is not set # CONFIG_MISC_DEVICES is not set - -# -# SCSI device support -# -CONFIG_SCSI_MOD=y CONFIG_RAID_ATTRS=y CONFIG_SCSI=y -CONFIG_SCSI_DMA=y CONFIG_SCSI_TGT=y -CONFIG_SCSI_NETLINK=y -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set CONFIG_CHR_DEV_SG=y -# CONFIG_CHR_DEV_SCH is not set CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y - -# -# SCSI Transports -# CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=y -# CONFIG_SCSI_FC_TGT_ATTRS is not set CONFIG_SCSI_ISCSI_ATTRS=y -# CONFIG_SCSI_SAS_LIBSAS is not set CONFIG_SCSI_SRP_ATTRS=y -# CONFIG_SCSI_SRP_TGT_ATTRS is not set # CONFIG_SCSI_LOWLEVEL is not set -# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set -# CONFIG_SCSI_DH is not set -# CONFIG_SCSI_OSD_INITIATOR is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y -# CONFIG_BONDING is not set -# CONFIG_MACVLAN is not set CONFIG_EQUALIZER=y CONFIG_TUN=y CONFIG_VETH=y -CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -# CONFIG_MARVELL_PHY is not set -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_FIXED_PHY is not set -# CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y -CONFIG_MII=y -# CONFIG_AX88796 is not set -# CONFIG_STNIC is not set -# CONFIG_SMC91X is not set -# CONFIG_ETHOC is not set -# CONFIG_SMC911X is not set CONFIG_SMSC911X=y -# CONFIG_DNET is not set -# CONFIG_IBM_NEW_EMAC_ZMII is not set -# CONFIG_IBM_NEW_EMAC_RGMII is not set -# CONFIG_IBM_NEW_EMAC_TAH is not set -# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set -# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set -# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set -# CONFIG_B44 is not set -# CONFIG_KS8842 is not set -# CONFIG_KS8851_MLL is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_WLAN is not set - -# -# Enable WiMAX (Networking options) to see the WiMAX drivers -# - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_IPHETH is not set -# CONFIG_NET_PCMCIA is not set -# CONFIG_WAN is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_ISDN is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y CONFIG_INPUT_FF_MEMLESS=y -# CONFIG_INPUT_POLLDEV is not set -# CONFIG_INPUT_SPARSEKMAP is not set - -# -# Userland interfaces -# # CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# # CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_DEVKMEM is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_N_GSM is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_NR_UARTS=2 CONFIG_SERIAL_SH_SCI_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_TIMBERDALE is not set -# CONFIG_SERIAL_ALTERA_JTAGUART is not set -# CONFIG_SERIAL_ALTERA_UART is not set -CONFIG_UNIX98_PTYS=y -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set -# CONFIG_IPMI_HANDLER is not set -CONFIG_HW_RANDOM=y -# CONFIG_HW_RANDOM_TIMERIOMEM is not set -# CONFIG_R3964 is not set - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set -# CONFIG_CARDMAN_4000 is not set -# CONFIG_CARDMAN_4040 is not set -# CONFIG_IPWIRELESS is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_RAMOOPS is not set -# CONFIG_I2C is not set -# CONFIG_SPI is not set - -# -# PPS support -# -# CONFIG_PPS is not set -# CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set -# CONFIG_THERMAL is not set CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set CONFIG_SH_WDT=y -# CONFIG_SH_WDT_MMAP is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set -CONFIG_SSB_POSSIBLE=y - -# -# Sonics Silicon Backplane -# CONFIG_SSB=y -CONFIG_SSB_PCMCIAHOST_POSSIBLE=y -# CONFIG_SSB_PCMCIAHOST is not set -# CONFIG_SSB_SILENT is not set -# CONFIG_SSB_DEBUG is not set -CONFIG_MFD_SUPPORT=y -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_SH_MOBILE_SDHI is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_REGULATOR is not set -# CONFIG_MEDIA_SUPPORT is not set - -# -# Graphics support -# -# CONFIG_VGASTATE is not set -# CONFIG_VIDEO_OUTPUT_CONTROL is not set CONFIG_FB=y -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FB_DDC is not set -# CONFIG_FB_BOOT_VESA_SUPPORT is not set -# CONFIG_FB_CFB_FILLRECT is not set -# CONFIG_FB_CFB_COPYAREA is not set -# CONFIG_FB_CFB_IMAGEBLIT is not set -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -# CONFIG_FB_SYS_FILLRECT is not set -# CONFIG_FB_SYS_COPYAREA is not set -# CONFIG_FB_SYS_IMAGEBLIT is not set -# CONFIG_FB_FOREIGN_ENDIAN is not set -# CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -# CONFIG_FB_MODE_HELPERS is not set -# CONFIG_FB_TILEBLITTING is not set - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_SH_MOBILE_LCDC is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FB_METRONOME is not set -# CONFIG_FB_MB862XX is not set -# CONFIG_FB_BROADSHEET is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y # CONFIG_LCD_CLASS_DEVICE is not set -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_GENERIC=y - -# -# Display device support -# -# CONFIG_DISPLAY_SUPPORT is not set - -# -# Console display driver support -# -CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y CONFIG_LOGO=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_LOGO_SUPERH_MONO=y -CONFIG_LOGO_SUPERH_VGA16=y -CONFIG_LOGO_SUPERH_CLUT224=y -# CONFIG_SOUND is not set # CONFIG_HID_SUPPORT is not set -CONFIG_USB_SUPPORT=y -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB_ARCH_HAS_EHCI is not set CONFIG_USB=y -# CONFIG_USB_DEBUG is not set -# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set - -# -# Miscellaneous USB options -# CONFIG_USB_DEVICEFS=y # CONFIG_USB_DEVICE_CLASS is not set -# CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set CONFIG_USB_MON=y -# CONFIG_USB_WUSB is not set -# CONFIG_USB_WUSB_CBAF is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_C67X00_HCD is not set -# CONFIG_USB_OXU210HP_HCD is not set -# CONFIG_USB_ISP116X_HCD is not set -# CONFIG_USB_ISP1760_HCD is not set -# CONFIG_USB_ISP1362_HCD is not set -# CONFIG_USB_SL811_HCD is not set -# CONFIG_USB_R8A66597_HCD is not set -# CONFIG_USB_HWA_HCD is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_WDM is not set -# CONFIG_USB_TMC is not set - -# -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may -# - -# -# also be needed; see USB_STORAGE Help for more info -# -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_LIBUSUAL is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set - -# -# USB port drivers -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_ADUTUX is not set -# CONFIG_USB_SEVSEG is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYPRESS_CY7C63 is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_FTDI_ELAN is not set -# CONFIG_USB_APPLEDISPLAY is not set -# CONFIG_USB_LD is not set -# CONFIG_USB_TRANCEVIBRATOR is not set -# CONFIG_USB_IOWARRIOR is not set -# CONFIG_USB_TEST is not set -# CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set -# CONFIG_MMC is not set -# CONFIG_MEMSTICK is not set CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y - -# -# LED drivers -# CONFIG_LEDS_TRIGGERS=y - -# -# LED Triggers -# -# CONFIG_LEDS_TRIGGER_TIMER is not set -# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set -# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set -# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set - -# -# iptables trigger is under Netfilter config (LED target) -# -# CONFIG_ACCESSIBILITY is not set -CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y -CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -# CONFIG_RTC_DEBUG is not set - -# -# RTC interfaces -# -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_DEV=y CONFIG_RTC_INTF_DEV_UIE_EMUL=y -# CONFIG_RTC_DRV_TEST is not set - -# -# SPI RTC drivers -# - -# -# Platform RTC drivers -# -# CONFIG_RTC_DRV_DS1286 is not set -# CONFIG_RTC_DRV_DS1511 is not set -# CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_DS1742 is not set -# CONFIG_RTC_DRV_STK17TA8 is not set -# CONFIG_RTC_DRV_M48T86 is not set -# CONFIG_RTC_DRV_M48T35 is not set -# CONFIG_RTC_DRV_M48T59 is not set -# CONFIG_RTC_DRV_MSM6242 is not set -# CONFIG_RTC_DRV_BQ4802 is not set -# CONFIG_RTC_DRV_RP5C01 is not set -# CONFIG_RTC_DRV_V3020 is not set - -# -# on-CPU RTC drivers -# -# CONFIG_RTC_DRV_SH is not set -# CONFIG_RTC_DRV_GENERIC is not set CONFIG_DMADEVICES=y -# CONFIG_DMADEVICES_DEBUG is not set - -# -# DMA Devices -# CONFIG_TIMB_DMA=y -CONFIG_DMA_ENGINE=y - -# -# DMA Clients -# -# CONFIG_NET_DMA is not set -# CONFIG_ASYNC_TX_DMA is not set -# CONFIG_DMATEST is not set -# CONFIG_AUXDISPLAY is not set -# CONFIG_UIO is not set -# CONFIG_STAGING is not set - -# -# File systems -# -# CONFIG_EXT2_FS is not set CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4_FS is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_BTRFS_FS is not set -# CONFIG_NILFS2_FS is not set -CONFIG_FILE_LOCKING=y -CONFIG_FSNOTIFY=y -CONFIG_DNOTIFY=y -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set -CONFIG_GENERIC_ACL=y - -# -# Caches -# -# CONFIG_FSCACHE is not set - -# -# CD-ROM/DVD Filesystems -# CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y CONFIG_UDF_FS=y -CONFIG_UDF_NLS=y - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=932 CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y -CONFIG_PROC_SYSCTL=y -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_SYSFS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set CONFIG_CONFIGFS_FS=y # CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y -# CONFIG_NFS_V4_1 is not set CONFIG_ROOT_NFS=y -# CONFIG_NFSD is not set -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_NFS_ACL_SUPPORT=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -CONFIG_SUNRPC_GSS=y -CONFIG_RPCSEC_GSS_KRB5=y -# CONFIG_RPCSEC_GSS_SPKM3 is not set -# CONFIG_SMB_FS is not set -# CONFIG_CEPH_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_NLS=y CONFIG_NLS_DEFAULT="utf8" CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_737=y @@ -1130,177 +166,31 @@ CONFIG_NLS_ISO8859_15=y CONFIG_NLS_KOI8_R=y CONFIG_NLS_KOI8_U=y CONFIG_NLS_UTF8=y -# CONFIG_DLM is not set - -# -# Kernel hacking -# -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -# CONFIG_PRINTK_TIME is not set # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_FRAME_WARN=1024 -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_STRIP_ASM_SYMS is not set -# CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set # CONFIG_DETECT_SOFTLOCKUP is not set -# CONFIG_DETECT_HUNG_TASK is not set # CONFIG_SCHED_DEBUG is not set -# CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_KMEMLEAK is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_LOCK_STAT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_INFO=y -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_DEBUG_CREDENTIALS is not set CONFIG_FRAME_POINTER=y -# CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -# CONFIG_LKDTM is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_LATENCYTOP is not set -# CONFIG_SYSCTL_SYSCALL_CHECK is not set -# CONFIG_PAGE_POISONING is not set -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_SYSCALL_TRACEPOINTS=y -CONFIG_TRACING_SUPPORT=y -CONFIG_FTRACE=y -# CONFIG_FUNCTION_TRACER is not set -# CONFIG_IRQSOFF_TRACER is not set -# CONFIG_SCHED_TRACER is not set -# CONFIG_ENABLE_DEFAULT_TRACERS is not set -# CONFIG_FTRACE_SYSCALLS is not set -# CONFIG_BOOT_TRACER is not set -CONFIG_BRANCH_PROFILE_NONE=y -# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set -# CONFIG_PROFILE_ALL_BRANCHES is not set -# CONFIG_KSYM_TRACER is not set -# CONFIG_STACK_TRACER is not set -# CONFIG_KMEMTRACE is not set -# CONFIG_WORKQUEUE_TRACER is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_DYNAMIC_DEBUG is not set -# CONFIG_DMA_API_DEBUG is not set -# CONFIG_ATOMIC64_SELFTEST is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set CONFIG_SH_STANDARD_BIOS=y -# CONFIG_STACK_DEBUG is not set -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_4KSTACKS is not set -CONFIG_DUMP_CODE=y -# CONFIG_DWARF_UNWINDER is not set -# CONFIG_SH_NO_BSS_INIT is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITYFS is not set -# CONFIG_DEFAULT_SECURITY_SELINUX is not set -# CONFIG_DEFAULT_SECURITY_SMACK is not set -# CONFIG_DEFAULT_SECURITY_TOMOYO is not set -CONFIG_DEFAULT_SECURITY_DAC=y -CONFIG_DEFAULT_SECURITY="" -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_ALGAPI2=y -CONFIG_CRYPTO_AEAD=y -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_PCOMP=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_GF128MUL=y CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_WORKQUEUE=y -# CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_AUTHENC=y - -# -# Authenticated Encryption with Associated Data -# -# CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set -# CONFIG_CRYPTO_SEQIV is not set - -# -# Block modes -# -CONFIG_CRYPTO_CBC=y -# CONFIG_CRYPTO_CTR is not set -# CONFIG_CRYPTO_CTS is not set CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_LRW=y CONFIG_CRYPTO_PCBC=y CONFIG_CRYPTO_XTS=y - -# -# Hash modes -# CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_XCBC=y -# CONFIG_CRYPTO_VMAC is not set - -# -# Digest -# -CONFIG_CRYPTO_CRC32C=y -# CONFIG_CRYPTO_GHASH is not set CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=y -# CONFIG_CRYPTO_RMD128 is not set -# CONFIG_CRYPTO_RMD160 is not set -# CONFIG_CRYPTO_RMD256 is not set -# CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_TGR192=y CONFIG_CRYPTO_WP512=y - -# -# Ciphers -# CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_ANUBIS=y CONFIG_CRYPTO_ARC4=y @@ -1308,50 +198,16 @@ CONFIG_CRYPTO_BLOWFISH=y CONFIG_CRYPTO_CAMELLIA=y CONFIG_CRYPTO_CAST5=y CONFIG_CRYPTO_CAST6=y -CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_FCRYPT=y CONFIG_CRYPTO_KHAZAD=y -# CONFIG_CRYPTO_SALSA20 is not set CONFIG_CRYPTO_SEED=y CONFIG_CRYPTO_SERPENT=y CONFIG_CRYPTO_TEA=y CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_TWOFISH_COMMON=y - -# -# Compression -# CONFIG_CRYPTO_DEFLATE=y -# CONFIG_CRYPTO_ZLIB is not set CONFIG_CRYPTO_LZO=y - -# -# Random Number Generation -# # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set -# CONFIG_VIRTUALIZATION is not set -# CONFIG_BINARY_PRINTF is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=y CONFIG_CRC16=y -# CONFIG_CRC_T10DIF is not set -CONFIG_CRC_ITU_T=y -CONFIG_CRC32=y -# CONFIG_CRC7 is not set CONFIG_LIBCRC32C=y -CONFIG_AUDIT_GENERIC=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_DMA=y -CONFIG_HAVE_LMB=y -CONFIG_NLATTR=y -CONFIG_GENERIC_ATOMIC64=y diff --git a/arch/sh/configs/sh7757lcr_defconfig b/arch/sh/configs/sh7757lcr_defconfig index 635933e76e31..273f3fa198f7 100644 --- a/arch/sh/configs/sh7757lcr_defconfig +++ b/arch/sh/configs/sh7757lcr_defconfig @@ -1,1126 +1,85 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.35-rc3 -# Mon Jul 5 20:42:01 2010 -# -CONFIG_SUPERH=y -CONFIG_SUPERH32=y -# CONFIG_SUPERH64 is not set -CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig" -CONFIG_RWSEM_GENERIC_SPINLOCK=y -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_IRQ_PER_CPU=y -CONFIG_SPARSE_IRQ=y -CONFIG_GENERIC_GPIO=y -CONFIG_GENERIC_TIME=y -CONFIG_GENERIC_CLOCKEVENTS=y -# CONFIG_ARCH_SUSPEND_POSSIBLE is not set -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_SYS_SUPPORTS_HUGETLBFS=y -CONFIG_SYS_SUPPORTS_TMU=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_HAVE_LATENCYTOP_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_HAS_DEFAULT_IDLE=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_CONSTRUCTORS=y - -# -# General setup -# CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_CROSS_COMPILE="" -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_BZIP2=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_BZIP2 is not set -# CONFIG_KERNEL_LZMA is not set -# CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y CONFIG_BSD_PROCESS_ACCT=y -# CONFIG_BSD_PROCESS_ACCT_V3 is not set CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y -# CONFIG_AUDIT is not set - -# -# RCU Subsystem -# -CONFIG_TREE_RCU=y -# CONFIG_TREE_PREEMPT_RCU is not set -# CONFIG_TINY_RCU is not set -# CONFIG_RCU_TRACE is not set -CONFIG_RCU_FANOUT=32 -# CONFIG_RCU_FANOUT_EXACT is not set -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set -# CONFIG_SYSFS_DEPRECATED_V2 is not set -# CONFIG_RELAY is not set -# CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_RD_GZIP=y -# CONFIG_RD_BZIP2 is not set -# CONFIG_RD_LZMA is not set -# CONFIG_RD_LZO is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_EMBEDDED=y -CONFIG_UID16=y # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_AIO=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_PERF_USE_VMALLOC=y - -# -# Kernel Performance Events And Counters -# -CONFIG_PERF_EVENTS=y -# CONFIG_PERF_COUNTERS is not set -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_COMPAT_BRK=y CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set -# CONFIG_PROFILING is not set -CONFIG_HAVE_OPROFILE=y -# CONFIG_KPROBES is not set -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_DMA_ATTRS=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_HW_BREAKPOINT=y -CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y - -# -# GCOV-based kernel profiling -# -# CONFIG_SLOW_WORK is not set -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 CONFIG_MODULES=y -# CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -# CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_BLOCK=y -CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_INTEGRITY is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" -# CONFIG_INLINE_SPIN_TRYLOCK is not set -# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK is not set -# CONFIG_INLINE_SPIN_LOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK_IRQ is not set -# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set -CONFIG_INLINE_SPIN_UNLOCK=y -# CONFIG_INLINE_SPIN_UNLOCK_BH is not set -CONFIG_INLINE_SPIN_UNLOCK_IRQ=y -# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_READ_TRYLOCK is not set -# CONFIG_INLINE_READ_LOCK is not set -# CONFIG_INLINE_READ_LOCK_BH is not set -# CONFIG_INLINE_READ_LOCK_IRQ is not set -# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set -CONFIG_INLINE_READ_UNLOCK=y -# CONFIG_INLINE_READ_UNLOCK_BH is not set -CONFIG_INLINE_READ_UNLOCK_IRQ=y -# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_WRITE_TRYLOCK is not set -# CONFIG_INLINE_WRITE_LOCK is not set -# CONFIG_INLINE_WRITE_LOCK_BH is not set -# CONFIG_INLINE_WRITE_LOCK_IRQ is not set -# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set -CONFIG_INLINE_WRITE_UNLOCK=y -# CONFIG_INLINE_WRITE_UNLOCK_BH is not set -CONFIG_INLINE_WRITE_UNLOCK_IRQ=y -# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set -# CONFIG_MUTEX_SPIN_ON_OWNER is not set -# CONFIG_FREEZER is not set - -# -# System type -# -CONFIG_CPU_SH4=y -CONFIG_CPU_SH4A=y -CONFIG_CPU_SHX2=y -# CONFIG_CPU_SUBTYPE_SH7619 is not set -# CONFIG_CPU_SUBTYPE_SH7201 is not set -# CONFIG_CPU_SUBTYPE_SH7203 is not set -# CONFIG_CPU_SUBTYPE_SH7206 is not set -# CONFIG_CPU_SUBTYPE_SH7263 is not set -# CONFIG_CPU_SUBTYPE_MXG is not set -# CONFIG_CPU_SUBTYPE_SH7705 is not set -# CONFIG_CPU_SUBTYPE_SH7706 is not set -# CONFIG_CPU_SUBTYPE_SH7707 is not set -# CONFIG_CPU_SUBTYPE_SH7708 is not set -# CONFIG_CPU_SUBTYPE_SH7709 is not set -# CONFIG_CPU_SUBTYPE_SH7710 is not set -# CONFIG_CPU_SUBTYPE_SH7712 is not set -# CONFIG_CPU_SUBTYPE_SH7720 is not set -# CONFIG_CPU_SUBTYPE_SH7721 is not set -# CONFIG_CPU_SUBTYPE_SH7750 is not set -# CONFIG_CPU_SUBTYPE_SH7091 is not set -# CONFIG_CPU_SUBTYPE_SH7750R is not set -# CONFIG_CPU_SUBTYPE_SH7750S is not set -# CONFIG_CPU_SUBTYPE_SH7751 is not set -# CONFIG_CPU_SUBTYPE_SH7751R is not set -# CONFIG_CPU_SUBTYPE_SH7760 is not set -# CONFIG_CPU_SUBTYPE_SH4_202 is not set -# CONFIG_CPU_SUBTYPE_SH7723 is not set -# CONFIG_CPU_SUBTYPE_SH7724 is not set CONFIG_CPU_SUBTYPE_SH7757=y -# CONFIG_CPU_SUBTYPE_SH7763 is not set -# CONFIG_CPU_SUBTYPE_SH7770 is not set -# CONFIG_CPU_SUBTYPE_SH7780 is not set -# CONFIG_CPU_SUBTYPE_SH7785 is not set -# CONFIG_CPU_SUBTYPE_SH7786 is not set -# CONFIG_CPU_SUBTYPE_SHX3 is not set -# CONFIG_CPU_SUBTYPE_SH7343 is not set -# CONFIG_CPU_SUBTYPE_SH7722 is not set -# CONFIG_CPU_SUBTYPE_SH7366 is not set - -# -# Memory management options -# -CONFIG_QUICKLIST=y -CONFIG_MMU=y -CONFIG_PAGE_OFFSET=0x80000000 -CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x40000000 CONFIG_MEMORY_SIZE=0x0f000000 -# CONFIG_29BIT is not set -CONFIG_32BIT=y CONFIG_PMB=y -CONFIG_X2TLB=y -CONFIG_VSYSCALL=y -CONFIG_ARCH_FLATMEM_ENABLE=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SPARSEMEM_DEFAULT=y -CONFIG_MAX_ACTIVE_REGIONS=1 -CONFIG_ARCH_POPULATES_NODE_MAP=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_IOREMAP_FIXED=y -CONFIG_UNCACHED_MAPPING=y -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PAGE_SIZE_16KB is not set -# CONFIG_PAGE_SIZE_64KB is not set -CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -CONFIG_SPARSEMEM_STATIC=y -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=1 -# CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 - -# -# Cache configuration -# -CONFIG_CACHE_WRITEBACK=y -# CONFIG_CACHE_WRITETHROUGH is not set -# CONFIG_CACHE_OFF is not set - -# -# Processor features -# -CONFIG_CPU_LITTLE_ENDIAN=y -# CONFIG_CPU_BIG_ENDIAN is not set -CONFIG_SH_FPU=y -# CONFIG_SH_STORE_QUEUES is not set -CONFIG_CPU_HAS_INTEVT=y -CONFIG_CPU_HAS_SR_RB=y -CONFIG_CPU_HAS_FPU=y - -# -# Board support -# CONFIG_SH_SH7757LCR=y - -# -# Timer and clock configuration -# -CONFIG_SH_TIMER_TMU=y -CONFIG_SH_CLK_CPG=y -# CONFIG_NO_HZ is not set -# CONFIG_HIGH_RES_TIMERS is not set -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y - -# -# CPU Frequency scaling -# -# CONFIG_CPU_FREQ is not set - -# -# DMA support -# -# CONFIG_SH_DMA is not set - -# -# Companion Chips -# - -# -# Additional SuperH Device Drivers -# CONFIG_HEARTBEAT=y -# CONFIG_PUSH_SWITCH is not set - -# -# Kernel features -# -# CONFIG_HZ_100 is not set -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_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 -CONFIG_GUSA=y -# CONFIG_INTC_USERIMASK is not set - -# -# Boot options -# -CONFIG_ZERO_PAGE_OFFSET=0x00001000 -CONFIG_BOOT_LINK_OFFSET=0x00800000 -CONFIG_ENTRY_OFFSET=0x00001000 CONFIG_CMDLINE_OVERWRITE=y -# CONFIG_CMDLINE_EXTEND is not set CONFIG_CMDLINE="console=ttySC2,115200 root=/dev/nfs ip=dhcp" - -# -# Bus options -# -# CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCCARD is not set - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -# CONFIG_HAVE_AOUT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Power management options (EXPERIMENTAL) -# -# CONFIG_PM is not set -# CONFIG_CPU_IDLE is not set CONFIG_NET=y - -# -# Networking options -# CONFIG_PACKET=y CONFIG_UNIX=y -CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_XFRM_STATISTICS is not set -# CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=y -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y # CONFIG_INET_LRO is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=y -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_MIP6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -CONFIG_INET6_XFRM_MODE_TRANSPORT=y -CONFIG_INET6_XFRM_MODE_TUNNEL=y -CONFIG_INET6_XFRM_MODE_BEET=y -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -CONFIG_IPV6_SIT=y -# CONFIG_IPV6_SIT_6RD is not set -CONFIG_IPV6_NDISC_NODETYPE=y -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set -# CONFIG_IPV6_MROUTE is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_RDS is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_L2TP is not set -# CONFIG_BRIDGE is not set -# CONFIG_NET_DSA is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_PHONET is not set -# CONFIG_IEEE802154 is not set -# CONFIG_NET_SCHED is not set -# CONFIG_DCB is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set # CONFIG_WIRELESS is not set -# CONFIG_WIMAX is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set -# CONFIG_CAIF is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_DEVTMPFS is not set -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV=y -# CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_LOOP is not set - -# -# DRBD disabled because PROC_FS, INET or CONNECTOR not selected -# -# CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_XIP is not set -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set -# CONFIG_BLK_DEV_HD is not set # CONFIG_MISC_DEVICES is not set -CONFIG_HAVE_IDE=y -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI_MOD=y -# CONFIG_RAID_ATTRS is not set -# CONFIG_SCSI is not set -# CONFIG_SCSI_DMA is not set -# CONFIG_SCSI_NETLINK is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_MACVLAN is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_VETH is not set CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -# CONFIG_MARVELL_PHY is not set -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set CONFIG_VITESSE_PHY=y -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_FIXED_PHY is not set CONFIG_MDIO_BITBANG=y -# CONFIG_MDIO_GPIO is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y -# CONFIG_AX88796 is not set -# CONFIG_STNIC is not set -CONFIG_SH_ETH=y -# CONFIG_SMC91X is not set -# CONFIG_ETHOC is not set -# CONFIG_SMC911X is not set -# CONFIG_SMSC911X is not set -# CONFIG_DNET is not set -# CONFIG_IBM_NEW_EMAC_ZMII is not set -# CONFIG_IBM_NEW_EMAC_RGMII is not set -# CONFIG_IBM_NEW_EMAC_TAH is not set -# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set -# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set -# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set -# CONFIG_B44 is not set -# CONFIG_KS8842 is not set -# CONFIG_KS8851_MLL is not set -CONFIG_NETDEV_1000=y # CONFIG_NETDEV_10000 is not set # CONFIG_WLAN is not set - -# -# Enable WiMAX (Networking options) to see the WiMAX drivers -# -# CONFIG_WAN is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_ISDN is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_POLLDEV is not set -# CONFIG_INPUT_SPARSEKMAP is not set - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y # CONFIG_KEYBOARD_ATKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_GPIO is not set -# CONFIG_KEYBOARD_MATRIX is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_OPENCORES is not set -# CONFIG_KEYBOARD_STOWAWAY is not set -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_SH_KEYSC is not set -# CONFIG_KEYBOARD_XTKBD is not set -CONFIG_INPUT_MOUSE=y # CONFIG_MOUSE_PS2 is not set -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_MOUSE_GPIO is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# # CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -CONFIG_DEVKMEM=y -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_N_GSM is not set - -# -# Serial drivers -# CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=2 -CONFIG_SERIAL_8250_RUNTIME_UARTS=2 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# CONFIG_SERIAL_SH_SCI=y CONFIG_SERIAL_SH_SCI_NR_UARTS=3 CONFIG_SERIAL_SH_SCI_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_TIMBERDALE is not set -# CONFIG_SERIAL_ALTERA_JTAGUART is not set -# CONFIG_SERIAL_ALTERA_UART is not set -CONFIG_UNIX98_PTYS=y -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set -# CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set -# CONFIG_R3964 is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_RAMOOPS is not set -# CONFIG_I2C is not set -# CONFIG_SPI is not set - -# -# PPS support -# -# CONFIG_PPS is not set -CONFIG_ARCH_REQUIRE_GPIOLIB=y -CONFIG_GPIOLIB=y -# CONFIG_DEBUG_GPIO is not set -# CONFIG_GPIO_SYSFS is not set - -# -# Memory mapped GPIO expanders: -# -# CONFIG_GPIO_IT8761E is not set - -# -# I2C GPIO expanders: -# - -# -# PCI GPIO expanders: -# - -# -# SPI GPIO expanders: -# - -# -# AC97 GPIO expanders: -# - -# -# MODULbus GPIO expanders: -# -# CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set -# CONFIG_THERMAL is not set -# CONFIG_WATCHDOG is not set -CONFIG_SSB_POSSIBLE=y - -# -# Sonics Silicon Backplane -# -# CONFIG_SSB is not set -CONFIG_MFD_SUPPORT=y -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_SH_MOBILE_SDHI is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_REGULATOR is not set -# CONFIG_MEDIA_SUPPORT is not set - -# -# Graphics support -# -# CONFIG_VGASTATE is not set -# CONFIG_VIDEO_OUTPUT_CONTROL is not set -# CONFIG_FB is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Display device support -# -# CONFIG_DISPLAY_SUPPORT is not set - -# -# Console display driver support -# -CONFIG_DUMMY_CONSOLE=y -# CONFIG_SOUND is not set -CONFIG_HID_SUPPORT=y -CONFIG_HID=y -# CONFIG_HIDRAW is not set -# CONFIG_HID_PID is not set - -# -# Special HID drivers -# # CONFIG_USB_SUPPORT is not set -# CONFIG_MMC is not set -# CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_ACCESSIBILITY is not set -CONFIG_RTC_LIB=y -# CONFIG_RTC_CLASS is not set -# CONFIG_DMADEVICES is not set -# CONFIG_AUXDISPLAY is not set -# CONFIG_UIO is not set -# CONFIG_STAGING is not set - -# -# File systems -# CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4_FS is not set -CONFIG_JBD=y -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_BTRFS_FS is not set -# CONFIG_NILFS2_FS is not set -CONFIG_FILE_LOCKING=y -CONFIG_FSNOTIFY=y -CONFIG_DNOTIFY=y CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set - -# -# Caches -# -# CONFIG_FSCACHE is not set - -# -# CD-ROM/DVD Filesystems -# CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -# CONFIG_MSDOS_FS is not set CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y -CONFIG_PROC_SYSCTL=y -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_SYSFS=y CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set -# CONFIG_CONFIGFS_FS is not set -CONFIG_MISC_FILESYSTEMS=y -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_LOGFS is not set -# CONFIG_CRAMFS is not set CONFIG_SQUASHFS=y -# CONFIG_SQUASHFS_XATTRS is not set -# CONFIG_SQUASHFS_EMBEDDED is not set -CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 -# CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y -# CONFIG_OMFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set CONFIG_ROOT_NFS=y -# CONFIG_NFSD is not set -CONFIG_LOCKD=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 is not set -# CONFIG_SMB_FS is not set -# CONFIG_CEPH_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set CONFIG_NLS_CODEPAGE_932=y -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set -# CONFIG_DLM is not set - -# -# Kernel hacking -# -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y -CONFIG_FRAME_WARN=1024 -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_STRIP_ASM_SYMS is not set -# CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set -# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set # CONFIG_DETECT_SOFTLOCKUP is not set -# CONFIG_DETECT_HUNG_TASK is not set # CONFIG_SCHED_DEBUG is not set -# CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_KMEMLEAK is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_LOCK_STAT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO=y -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_DEBUG_CREDENTIALS is not set -# CONFIG_FRAME_POINTER is not set -# CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_LATENCYTOP is not set -# CONFIG_SYSCTL_SYSCALL_CHECK is not set -# CONFIG_PAGE_POISONING is not set -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_SYSCALL_TRACEPOINTS=y -CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set -# CONFIG_DMA_API_DEBUG is not set -# CONFIG_ATOMIC64_SELFTEST is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set -# CONFIG_SH_STANDARD_BIOS is not set -# CONFIG_STACK_DEBUG is not set -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_4KSTACKS is not set -# CONFIG_DUMP_CODE is not set -# CONFIG_DWARF_UNWINDER is not set -# CONFIG_SH_NO_BSS_INIT is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITYFS is not set -# CONFIG_DEFAULT_SECURITY_SELINUX is not set -# CONFIG_DEFAULT_SECURITY_SMACK is not set -# CONFIG_DEFAULT_SECURITY_TOMOYO is not set -CONFIG_DEFAULT_SECURITY_DAC=y -CONFIG_DEFAULT_SECURITY="" -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -# CONFIG_CRYPTO_MANAGER is not set -# CONFIG_CRYPTO_MANAGER2 is not set -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set -# CONFIG_CRYPTO_TEST is not set - -# -# Authenticated Encryption with Associated Data -# -# CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set -# CONFIG_CRYPTO_SEQIV is not set - -# -# Block modes -# -# CONFIG_CRYPTO_CBC is not set -# CONFIG_CRYPTO_CTR is not set -# CONFIG_CRYPTO_CTS is not set -# CONFIG_CRYPTO_ECB is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_XTS is not set - -# -# Hash modes -# -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_XCBC is not set -# CONFIG_CRYPTO_VMAC is not set - -# -# Digest -# -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_RMD128 is not set -# CONFIG_CRYPTO_RMD160 is not set -# CONFIG_CRYPTO_RMD256 is not set -# CONFIG_CRYPTO_RMD320 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_WP512 is not set - -# -# Ciphers -# -# CONFIG_CRYPTO_AES is not set -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_ARC4 is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_TWOFISH is not set - -# -# Compression -# -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set - -# -# Random Number Generation -# # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRYPTO_HW=y -# CONFIG_VIRTUALIZATION is not set -# CONFIG_BINARY_PRINTF is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -CONFIG_GENERIC_FIND_LAST_BIT=y -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -# CONFIG_CRC_T10DIF is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_DECOMPRESS_GZIP=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -CONFIG_HAVE_LMB=y -CONFIG_NLATTR=y -CONFIG_GENERIC_ATOMIC64=y -- cgit v1.2.3-59-g8ed1b From 3fabe089ad8b8f238bc9de3e7586ae8d2a81f57c Mon Sep 17 00:00:00 2001 From: "Matti J. Aaltonen" Date: Fri, 20 Aug 2010 12:32:46 +0300 Subject: ASoC: TI WL1273 FM Radio Codec. This is an ALSA codec for the Texas Instruments WL1273 FM Radio. Signed-off-by: Matti J. Aaltonen Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/wl1273.c | 525 ++++++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/wl1273.h | 101 +++++++++ 2 files changed, 626 insertions(+) create mode 100644 sound/soc/codecs/wl1273.c create mode 100644 sound/soc/codecs/wl1273.h diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c new file mode 100644 index 000000000000..0cd590970883 --- /dev/null +++ b/sound/soc/codecs/wl1273.c @@ -0,0 +1,525 @@ +/* + * ALSA SoC WL1273 codec driver + * + * Author: Matti Aaltonen, + * + * Copyright: (C) 2010 Nokia Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "wl1273.h" + +enum wl1273_mode { WL1273_MODE_BT, WL1273_MODE_FM_RX, WL1273_MODE_FM_TX }; + +/* codec private data */ +struct wl1273_priv { + enum wl1273_mode mode; + struct wl1273_core *core; + unsigned int channels; +}; + +static int snd_wl1273_fm_set_i2s_mode(struct wl1273_core *core, + int rate, int width) +{ + struct device *dev = &core->i2c_dev->dev; + int r = 0; + u16 mode; + + dev_dbg(dev, "rate: %d\n", rate); + dev_dbg(dev, "width: %d\n", width); + + mutex_lock(&core->lock); + + mode = core->i2s_mode & ~WL1273_IS2_WIDTH & ~WL1273_IS2_RATE; + + switch (rate) { + case 48000: + mode |= WL1273_IS2_RATE_48K; + break; + case 44100: + mode |= WL1273_IS2_RATE_44_1K; + break; + case 32000: + mode |= WL1273_IS2_RATE_32K; + break; + case 22050: + mode |= WL1273_IS2_RATE_22_05K; + break; + case 16000: + mode |= WL1273_IS2_RATE_16K; + break; + case 12000: + mode |= WL1273_IS2_RATE_12K; + break; + case 11025: + mode |= WL1273_IS2_RATE_11_025; + break; + case 8000: + mode |= WL1273_IS2_RATE_8K; + break; + default: + dev_err(dev, "Sampling rate: %d not supported\n", rate); + r = -EINVAL; + goto out; + } + + switch (width) { + case 16: + mode |= WL1273_IS2_WIDTH_32; + break; + case 20: + mode |= WL1273_IS2_WIDTH_40; + break; + case 24: + mode |= WL1273_IS2_WIDTH_48; + break; + case 25: + mode |= WL1273_IS2_WIDTH_50; + break; + case 30: + mode |= WL1273_IS2_WIDTH_60; + break; + case 32: + mode |= WL1273_IS2_WIDTH_64; + break; + case 40: + mode |= WL1273_IS2_WIDTH_80; + break; + case 48: + mode |= WL1273_IS2_WIDTH_96; + break; + case 64: + mode |= WL1273_IS2_WIDTH_128; + break; + default: + dev_err(dev, "Data width: %d not supported\n", width); + r = -EINVAL; + goto out; + } + + dev_dbg(dev, "WL1273_I2S_DEF_MODE: 0x%04x\n", WL1273_I2S_DEF_MODE); + dev_dbg(dev, "core->i2s_mode: 0x%04x\n", core->i2s_mode); + dev_dbg(dev, "mode: 0x%04x\n", mode); + + if (core->i2s_mode != mode) { + r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, mode); + if (r) + goto out; + + core->i2s_mode = mode; + r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE, + WL1273_AUDIO_ENABLE_I2S); + if (r) + goto out; + } +out: + mutex_unlock(&core->lock); + + return r; +} + +static int snd_wl1273_fm_set_channel_number(struct wl1273_core *core, + int channel_number) +{ + struct i2c_client *client = core->i2c_dev; + struct device *dev = &client->dev; + int r = 0; + + dev_dbg(dev, "%s\n", __func__); + + mutex_lock(&core->lock); + + if (core->channel_number == channel_number) + goto out; + + if (channel_number == 1 && core->mode == WL1273_MODE_RX) + r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET, + WL1273_RX_MONO); + else if (channel_number == 1 && core->mode == WL1273_MODE_TX) + r = wl1273_fm_write_cmd(core, WL1273_MONO_SET, + WL1273_TX_MONO); + else if (channel_number == 2 && core->mode == WL1273_MODE_RX) + r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET, + WL1273_RX_STEREO); + else if (channel_number == 2 && core->mode == WL1273_MODE_TX) + r = wl1273_fm_write_cmd(core, WL1273_MONO_SET, + WL1273_TX_STEREO); + else + r = -EINVAL; +out: + mutex_unlock(&core->lock); + + return r; +} + +static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = wl1273->mode; + + return 0; +} + +static const char *wl1273_audio_route[] = { "Bt", "FmRx", "FmTx" }; + +static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); + + /* Do not allow changes while stream is running */ + if (codec->active) + return -EPERM; + + if (ucontrol->value.integer.value[0] < 0 || + ucontrol->value.integer.value[0] >= ARRAY_SIZE(wl1273_audio_route)) + return -EINVAL; + + wl1273->mode = ucontrol->value.integer.value[0]; + + return 1; +} + +static const struct soc_enum wl1273_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_route), wl1273_audio_route); + +static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); + + dev_dbg(codec->dev, "%s: enter.\n", __func__); + + ucontrol->value.integer.value[0] = wl1273->core->audio_mode; + + return 0; +} + +static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); + int val, r = 0; + + dev_dbg(codec->dev, "%s: enter.\n", __func__); + + val = ucontrol->value.integer.value[0]; + if (wl1273->core->audio_mode == val) + return 0; + + r = wl1273_fm_set_audio(wl1273->core, val); + if (r < 0) + return r; + + return 1; +} + +static const char *wl1273_audio_strings[] = { "Digital", "Analog" }; + +static const struct soc_enum wl1273_audio_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_strings), + wl1273_audio_strings); + +static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); + + dev_dbg(codec->dev, "%s: enter.\n", __func__); + + ucontrol->value.integer.value[0] = wl1273->core->volume; + + return 0; +} + +static int snd_wl1273_fm_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); + int r; + + dev_dbg(codec->dev, "%s: enter.\n", __func__); + + r = wl1273_fm_set_volume(wl1273->core, + ucontrol->value.integer.value[0]); + if (r) + return r; + + return 1; +} + +static const struct snd_kcontrol_new wl1273_controls[] = { + SOC_ENUM_EXT("Codec Mode", wl1273_enum, + snd_wl1273_get_audio_route, snd_wl1273_set_audio_route), + SOC_ENUM_EXT("Audio Switch", wl1273_audio_enum, + snd_wl1273_fm_audio_get, snd_wl1273_fm_audio_put), + SOC_SINGLE_EXT("Volume", 0, 0, WL1273_MAX_VOLUME, 0, + snd_wl1273_fm_volume_get, snd_wl1273_fm_volume_put), +}; + +static int wl1273_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); + + switch (wl1273->mode) { + case WL1273_MODE_BT: + snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, + 8000, 8000); + snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_CHANNELS, 1, 1); + break; + case WL1273_MODE_FM_RX: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + pr_err("Cannot play in RX mode.\n"); + return -EINVAL; + } + break; + case WL1273_MODE_FM_TX: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + pr_err("Cannot capture in TX mode.\n"); + return -EINVAL; + } + break; + default: + return -EINVAL; + break; + } + + return 0; +} + +static int wl1273_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(rtd->codec); + struct wl1273_core *core = wl1273->core; + unsigned int rate, width, r; + + if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) { + pr_err("Only SNDRV_PCM_FORMAT_S16_LE supported.\n"); + return -EINVAL; + } + + rate = params_rate(params); + width = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min; + + if (wl1273->mode == WL1273_MODE_BT) { + if (rate != 8000) { + pr_err("Rate %d not supported.\n", params_rate(params)); + return -EINVAL; + } + + if (params_channels(params) != 1) { + pr_err("Only mono supported.\n"); + return -EINVAL; + } + + return 0; + } + + if (wl1273->mode == WL1273_MODE_FM_TX && + substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + pr_err("Only playback supported with TX.\n"); + return -EINVAL; + } + + if (wl1273->mode == WL1273_MODE_FM_RX && + substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + pr_err("Only capture supported with RX.\n"); + return -EINVAL; + } + + if (wl1273->mode != WL1273_MODE_FM_RX && + wl1273->mode != WL1273_MODE_FM_TX) { + pr_err("Unexpected mode: %d.\n", wl1273->mode); + return -EINVAL; + } + + r = snd_wl1273_fm_set_i2s_mode(core, rate, width); + if (r) + return r; + + wl1273->channels = params_channels(params); + r = snd_wl1273_fm_set_channel_number(core, wl1273->channels); + if (r) + return r; + + return 0; +} + +static struct snd_soc_dai_ops wl1273_dai_ops = { + .startup = wl1273_startup, + .hw_params = wl1273_hw_params, +}; + +static struct snd_soc_dai_driver wl1273_dai = { + .name = "wl1273-fm", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE}, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE}, + .ops = &wl1273_dai_ops, +}; + +/* Audio interface format for the soc_card driver */ +int wl1273_get_format(struct snd_soc_codec *codec, unsigned int *fmt) +{ + struct wl1273_priv *wl1273; + + if (codec == NULL || fmt == NULL) + return -EINVAL; + + wl1273 = snd_soc_codec_get_drvdata(codec); + + switch (wl1273->mode) { + case WL1273_MODE_FM_RX: + case WL1273_MODE_FM_TX: + *fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM; + + break; + case WL1273_MODE_BT: + *fmt = SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | + SND_SOC_DAIFMT_CBM_CFM; + + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(wl1273_get_format); + +static int wl1273_probe(struct snd_soc_codec *codec) +{ + struct wl1273_core **core = codec->dev->platform_data; + struct wl1273_priv *wl1273; + int r; + + dev_dbg(codec->dev, "%s.\n", __func__); + + if (!core) { + dev_err(codec->dev, "Platform data is missing.\n"); + return -EINVAL; + } + + wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL); + if (wl1273 == NULL) { + dev_err(codec->dev, "Cannot allocate memory.\n"); + return -ENOMEM; + } + + wl1273->mode = WL1273_MODE_BT; + wl1273->core = *core; + + snd_soc_codec_set_drvdata(codec, wl1273); + mutex_init(&codec->mutex); + + r = snd_soc_add_controls(codec, wl1273_controls, + ARRAY_SIZE(wl1273_controls)); + if (r) + kfree(wl1273); + + return r; +} + +static int wl1273_remove(struct snd_soc_codec *codec) +{ + struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); + + dev_dbg(codec->dev, "%s\n", __func__); + kfree(wl1273); + + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_wl1273 = { + .probe = wl1273_probe, + .remove = wl1273_remove, +}; + +static int __devinit wl1273_platform_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wl1273, + &wl1273_dai, 1); +} + +static int __devexit wl1273_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +MODULE_ALIAS("platform:wl1273-codec"); + +static struct platform_driver wl1273_platform_driver = { + .driver = { + .name = "wl1273-codec", + .owner = THIS_MODULE, + }, + .probe = wl1273_platform_probe, + .remove = __devexit_p(wl1273_platform_remove), +}; + +static int __init wl1273_init(void) +{ + return platform_driver_register(&wl1273_platform_driver); +} +module_init(wl1273_init); + +static void __exit wl1273_exit(void) +{ + platform_driver_unregister(&wl1273_platform_driver); +} +module_exit(wl1273_exit); + +MODULE_AUTHOR("Matti Aaltonen "); +MODULE_DESCRIPTION("ASoC WL1273 codec driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wl1273.h b/sound/soc/codecs/wl1273.h new file mode 100644 index 000000000000..14ed027fdcfc --- /dev/null +++ b/sound/soc/codecs/wl1273.h @@ -0,0 +1,101 @@ +/* + * sound/soc/codec/wl1273.h + * + * ALSA SoC WL1273 codec driver + * + * Copyright (C) Nokia Corporation + * Author: Matti Aaltonen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL1273_CODEC_H__ +#define __WL1273_CODEC_H__ + +/* I2S protocol, left channel first, data width 16 bits */ +#define WL1273_PCM_DEF_MODE 0x00 + +/* Rx */ +#define WL1273_AUDIO_ENABLE_I2S (1 << 0) +#define WL1273_AUDIO_ENABLE_ANALOG (1 << 1) + +/* Tx */ +#define WL1273_AUDIO_IO_SET_ANALOG 0 +#define WL1273_AUDIO_IO_SET_I2S 1 + +#define WL1273_POWER_SET_OFF 0 +#define WL1273_POWER_SET_FM (1 << 0) +#define WL1273_POWER_SET_RDS (1 << 1) +#define WL1273_POWER_SET_RETENTION (1 << 4) + +#define WL1273_PUPD_SET_OFF 0x00 +#define WL1273_PUPD_SET_ON 0x01 +#define WL1273_PUPD_SET_RETENTION 0x10 + +/* I2S mode */ +#define WL1273_IS2_WIDTH_32 0x0 +#define WL1273_IS2_WIDTH_40 0x1 +#define WL1273_IS2_WIDTH_22_23 0x2 +#define WL1273_IS2_WIDTH_23_22 0x3 +#define WL1273_IS2_WIDTH_48 0x4 +#define WL1273_IS2_WIDTH_50 0x5 +#define WL1273_IS2_WIDTH_60 0x6 +#define WL1273_IS2_WIDTH_64 0x7 +#define WL1273_IS2_WIDTH_80 0x8 +#define WL1273_IS2_WIDTH_96 0x9 +#define WL1273_IS2_WIDTH_128 0xa +#define WL1273_IS2_WIDTH 0xf + +#define WL1273_IS2_FORMAT_STD (0x0 << 4) +#define WL1273_IS2_FORMAT_LEFT (0x1 << 4) +#define WL1273_IS2_FORMAT_RIGHT (0x2 << 4) +#define WL1273_IS2_FORMAT_USER (0x3 << 4) + +#define WL1273_IS2_MASTER (0x0 << 6) +#define WL1273_IS2_SLAVEW (0x1 << 6) + +#define WL1273_IS2_TRI_AFTER_SENDING (0x0 << 7) +#define WL1273_IS2_TRI_ALWAYS_ACTIVE (0x1 << 7) + +#define WL1273_IS2_SDOWS_RR (0x0 << 8) +#define WL1273_IS2_SDOWS_RF (0x1 << 8) +#define WL1273_IS2_SDOWS_FR (0x2 << 8) +#define WL1273_IS2_SDOWS_FF (0x3 << 8) + +#define WL1273_IS2_TRI_OPT (0x0 << 10) +#define WL1273_IS2_TRI_ALWAYS (0x1 << 10) + +#define WL1273_IS2_RATE_48K (0x0 << 12) +#define WL1273_IS2_RATE_44_1K (0x1 << 12) +#define WL1273_IS2_RATE_32K (0x2 << 12) +#define WL1273_IS2_RATE_22_05K (0x4 << 12) +#define WL1273_IS2_RATE_16K (0x5 << 12) +#define WL1273_IS2_RATE_12K (0x8 << 12) +#define WL1273_IS2_RATE_11_025 (0x9 << 12) +#define WL1273_IS2_RATE_8K (0xa << 12) +#define WL1273_IS2_RATE (0xf << 12) + +#define WL1273_I2S_DEF_MODE (WL1273_IS2_WIDTH_32 | \ + WL1273_IS2_FORMAT_STD | \ + WL1273_IS2_MASTER | \ + WL1273_IS2_TRI_AFTER_SENDING | \ + WL1273_IS2_SDOWS_RR | \ + WL1273_IS2_TRI_OPT | \ + WL1273_IS2_RATE_48K) + +int wl1273_get_format(struct snd_soc_codec *codec, unsigned int *fmt); + +#endif /* End of __WL1273_CODEC_H__ */ -- cgit v1.2.3-59-g8ed1b From 26b01ccdc8ded270a1a65721b99acacf0c44e088 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 18 Aug 2010 20:20:55 +0100 Subject: ASoC: Don't call DAI registration for CODECs with no DAI Otherwise we generate worrying (but benign) warnings for amps. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-core.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 7093c1787128..65352c7d4b7f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3122,10 +3122,12 @@ int snd_soc_register_codec(struct device *dev, fixup_codec_formats(&dai_drv[i].capture); } - /* register DAIs */ - ret = snd_soc_register_dais(dev, dai_drv, num_dai); - if (ret < 0) + /* register any DAIs */ + if (num_dai) { + ret = snd_soc_register_dais(dev, dai_drv, num_dai); + if (ret < 0) goto error; + } mutex_lock(&client_mutex); list_add(&codec->list, &codec_list); @@ -3164,8 +3166,9 @@ void snd_soc_unregister_codec(struct device *dev) return; found: - for (i = 0; i < codec->num_dai; i++) - snd_soc_unregister_dai(dev); + if (codec->num_dai) + for (i = 0; i < codec->num_dai; i++) + snd_soc_unregister_dai(dev); mutex_lock(&client_mutex); list_del(&codec->list); -- cgit v1.2.3-59-g8ed1b From 38fec7272bc033b75a0eb8976c56c2024d371b7d Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 19 Aug 2010 15:26:58 -0500 Subject: ASoC: mpc8610: replace of_device with platform_device 'struct of_device' no longer exists, and its functionality has been merged into platform_device. Update the MPC8610 HPCD audio drivers (fsl_ssi, fsl_dma, and mpc8610_hpcd) accordingly. Also add a #include for slab.h, which is now needed for kmalloc and kfree. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_dma.c | 23 ++++++++++++----------- sound/soc/fsl/fsl_ssi.c | 42 +++++++++++++++++++++--------------------- sound/soc/fsl/mpc8610_hpcd.c | 10 ++++++---- 3 files changed, 39 insertions(+), 36 deletions(-) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index f039e8db0765..4cf98c03af22 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -895,11 +896,11 @@ static struct snd_pcm_ops fsl_dma_ops = { .pointer = fsl_dma_pointer, }; -static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, +static int __devinit fsl_soc_dma_probe(struct platform_device *pdev, const struct of_device_id *match) { struct dma_object *dma; - struct device_node *np = of_dev->dev.of_node; + struct device_node *np = pdev->dev.of_node; struct device_node *ssi_np; struct resource res; const uint32_t *iprop; @@ -908,13 +909,13 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, /* Find the SSI node that points to us. */ ssi_np = find_ssi_node(np); if (!ssi_np) { - dev_err(&of_dev->dev, "cannot find parent SSI node\n"); + dev_err(&pdev->dev, "cannot find parent SSI node\n"); return -ENODEV; } ret = of_address_to_resource(ssi_np, 0, &res); if (ret) { - dev_err(&of_dev->dev, "could not determine resources for %s\n", + dev_err(&pdev->dev, "could not determine resources for %s\n", ssi_np->full_name); of_node_put(ssi_np); return ret; @@ -922,7 +923,7 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL); if (!dma) { - dev_err(&of_dev->dev, "could not allocate dma object\n"); + dev_err(&pdev->dev, "could not allocate dma object\n"); of_node_put(ssi_np); return -ENOMEM; } @@ -945,9 +946,9 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, of_node_put(ssi_np); - ret = snd_soc_register_platform(&of_dev->dev, &dma->dai); + ret = snd_soc_register_platform(&pdev->dev, &dma->dai); if (ret) { - dev_err(&of_dev->dev, "could not register platform\n"); + dev_err(&pdev->dev, "could not register platform\n"); kfree(dma); return ret; } @@ -955,16 +956,16 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, dma->channel = of_iomap(np, 0); dma->irq = irq_of_parse_and_map(np, 0); - dev_set_drvdata(&of_dev->dev, dma); + dev_set_drvdata(&pdev->dev, dma); return 0; } -static int __devexit fsl_soc_dma_remove(struct of_device *of_dev) +static int __devexit fsl_soc_dma_remove(struct platform_device *pdev) { - struct dma_object *dma = dev_get_drvdata(&of_dev->dev); + struct dma_object *dma = dev_get_drvdata(&pdev->dev); - snd_soc_unregister_platform(&of_dev->dev); + snd_soc_unregister_platform(&pdev->dev); iounmap(dma->channel); irq_dispose_mapping(dma->irq); kfree(dma); diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index d1c855ade8fb..4cc167a7aeb8 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -624,13 +624,13 @@ static void make_lowercase(char *s) } } -static int __devinit fsl_ssi_probe(struct of_device *of_dev, +static int __devinit fsl_ssi_probe(struct platform_device *pdev, const struct of_device_id *match) { struct fsl_ssi_private *ssi_private; int ret = 0; struct device_attribute *dev_attr = NULL; - struct device_node *np = of_dev->dev.of_node; + struct device_node *np = pdev->dev.of_node; const char *p, *sprop; const uint32_t *iprop; struct resource res; @@ -645,14 +645,14 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev, /* Check for a codec-handle property. */ if (!of_get_property(np, "codec-handle", NULL)) { - dev_err(&of_dev->dev, "missing codec-handle property\n"); + dev_err(&pdev->dev, "missing codec-handle property\n"); return -ENODEV; } /* We only support the SSI in "I2S Slave" mode */ sprop = of_get_property(np, "fsl,mode", NULL); if (!sprop || strcmp(sprop, "i2s-slave")) { - dev_notice(&of_dev->dev, "mode %s is unsupported\n", sprop); + dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop); return -ENODEV; } @@ -661,7 +661,7 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev, ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p), GFP_KERNEL); if (!ssi_private) { - dev_err(&of_dev->dev, "could not allocate DAI object\n"); + dev_err(&pdev->dev, "could not allocate DAI object\n"); return -ENOMEM; } @@ -675,7 +675,7 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev, /* Get the addresses and IRQ */ ret = of_address_to_resource(np, 0, &res); if (ret) { - dev_err(&of_dev->dev, "could not determine device resources\n"); + dev_err(&pdev->dev, "could not determine device resources\n"); kfree(ssi_private); return ret; } @@ -703,19 +703,19 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev, dev_attr->attr.mode = S_IRUGO; dev_attr->show = fsl_sysfs_ssi_show; - ret = device_create_file(&of_dev->dev, dev_attr); + ret = device_create_file(&pdev->dev, dev_attr); if (ret) { - dev_err(&of_dev->dev, "could not create sysfs %s file\n", + dev_err(&pdev->dev, "could not create sysfs %s file\n", ssi_private->dev_attr.attr.name); goto error; } /* Register with ASoC */ - dev_set_drvdata(&of_dev->dev, ssi_private); + dev_set_drvdata(&pdev->dev, ssi_private); - ret = snd_soc_register_dai(&of_dev->dev, &ssi_private->cpu_dai_drv); + ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv); if (ret) { - dev_err(&of_dev->dev, "failed to register DAI: %d\n", ret); + dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); goto error; } @@ -733,20 +733,20 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev, make_lowercase(name); ssi_private->pdev = - platform_device_register_data(&of_dev->dev, name, 0, NULL, 0); + platform_device_register_data(&pdev->dev, name, 0, NULL, 0); if (IS_ERR(ssi_private->pdev)) { ret = PTR_ERR(ssi_private->pdev); - dev_err(&of_dev->dev, "failed to register platform: %d\n", ret); + dev_err(&pdev->dev, "failed to register platform: %d\n", ret); goto error; } return 0; error: - snd_soc_unregister_dai(&of_dev->dev); - dev_set_drvdata(&of_dev->dev, NULL); + snd_soc_unregister_dai(&pdev->dev); + dev_set_drvdata(&pdev->dev, NULL); if (dev_attr) - device_remove_file(&of_dev->dev, dev_attr); + device_remove_file(&pdev->dev, dev_attr); irq_dispose_mapping(ssi_private->irq); iounmap(ssi_private->ssi); kfree(ssi_private); @@ -754,16 +754,16 @@ error: return ret; } -static int fsl_ssi_remove(struct of_device *of_dev) +static int fsl_ssi_remove(struct platform_device *pdev) { - struct fsl_ssi_private *ssi_private = dev_get_drvdata(&of_dev->dev); + struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev); platform_device_unregister(ssi_private->pdev); - snd_soc_unregister_dai(&of_dev->dev); - device_remove_file(&of_dev->dev, &ssi_private->dev_attr); + snd_soc_unregister_dai(&pdev->dev); + device_remove_file(&pdev->dev, &ssi_private->dev_attr); kfree(ssi_private); - dev_set_drvdata(&of_dev->dev, NULL); + dev_set_drvdata(&pdev->dev, NULL); return 0; } diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 38339c158ed9..0d7dcf1e4863 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -323,9 +324,10 @@ static int get_dma_channel(struct device_node *ssi_np, static int mpc8610_hpcd_probe(struct platform_device *pdev) { struct device *dev = pdev->dev.parent; - /* of_dev is the OF device for the SSI node that probed us */ - struct of_device *of_dev = container_of(dev, struct of_device, dev); - struct device_node *np = of_dev->dev.of_node; + /* ssi_pdev is the platform device for the SSI node that probed us */ + struct platform_device *ssi_pdev = + container_of(dev, struct platform_device, dev); + struct device_node *np = ssi_pdev->dev.of_node; struct device_node *codec_np = NULL; struct platform_device *sound_device = NULL; struct mpc8610_hpcd_data *machine_data; @@ -348,7 +350,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) if (!machine_data) return -ENOMEM; - machine_data->dai[0].cpu_dai_name = dev_name(&of_dev->dev); + machine_data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); machine_data->dai[0].ops = &mpc8610_hpcd_ops; /* Determine the codec name, it will be used as the codec DAI name */ -- cgit v1.2.3-59-g8ed1b From fd0964c5f1bdaa979a7ea5cfc9af2de9b0a1e766 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Thu, 19 Aug 2010 15:09:37 +0300 Subject: omap: rx51: Add support for USB chargers This enables isp1704 power supply driver on RX51, allowing USB charger detection with N900. Signed-off-by: Heikki Krogerus Acked-by: Tony Lindgren Signed-off-by: Anton Vorontsov --- arch/arm/mach-omap2/board-rx51-peripherals.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 9a5eb87425fc..a4b1f8bdff43 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -104,6 +104,10 @@ static struct spi_board_info rx51_peripherals_spi_board_info[] __initdata = { }, }; +static struct platform_device rx51_charger_device = { + .name = "isp1704_charger", +}; + #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) #define RX51_GPIO_CAMERA_LENS_COVER 110 @@ -909,5 +913,6 @@ void __init rx51_peripherals_init(void) spi_register_board_info(rx51_peripherals_spi_board_info, ARRAY_SIZE(rx51_peripherals_spi_board_info)); omap2_hsmmc_init(mmc); + platform_device_register(&rx51_charger_device); } -- cgit v1.2.3-59-g8ed1b From 1003489e06c04d807c783a8958f2ccc9aed7a244 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Sat, 21 Aug 2010 06:13:28 +0000 Subject: net: rps: fix the wrong network header pointer __skb_get_rxhash() was broken after the commit: commit bfb564e7391340638afe4ad67744a8f3858e7566 Author: Krishna Kumar Date: Wed Aug 4 06:15:52 2010 +0000 core: Factor out flow calculation from get_rps_cpu Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- net/core/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index da584f5ab3d2..4d74d26b8e1a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2283,7 +2283,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb) if (!pskb_may_pull(skb, sizeof(*ip) + nhoff)) goto done; - ip = (struct iphdr *) skb->data + nhoff; + ip = (struct iphdr *) (skb->data + nhoff); if (ip->frag_off & htons(IP_MF | IP_OFFSET)) ip_proto = 0; else @@ -2296,7 +2296,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb) if (!pskb_may_pull(skb, sizeof(*ip6) + nhoff)) goto done; - ip6 = (struct ipv6hdr *) skb->data + nhoff; + ip6 = (struct ipv6hdr *) (skb->data + nhoff); ip_proto = ip6->nexthdr; addr1 = (__force u32) ip6->saddr.s6_addr32[3]; addr2 = (__force u32) ip6->daddr.s6_addr32[3]; -- cgit v1.2.3-59-g8ed1b From 00959ade36acadc00e757f87060bf6e4501d545f Mon Sep 17 00:00:00 2001 From: Dmitry Kozlov Date: Sat, 21 Aug 2010 23:05:39 -0700 Subject: PPTP: PPP over IPv4 (Point-to-Point Tunneling Protocol) PPP: introduce "pptp" module which implements point-to-point tunneling protocol using pppox framework NET: introduce the "gre" module for demultiplexing GRE packets on version criteria (required to pptp and ip_gre may coexists) NET: ip_gre: update to use the "gre" module This patch introduces then pptp support to the linux kernel which dramatically speeds up pptp vpn connections and decreases cpu usage in comparison of existing user-space implementation (poptop/pptpclient). There is accel-pptp project (https://sourceforge.net/projects/accel-pptp/) to utilize this module, it contains plugin for pppd to use pptp in client-mode and modified pptpd (poptop) to build high-performance pptp NAS. There was many changes from initial submitted patch, most important are: 1. using rcu instead of read-write locks 2. using static bitmap instead of dynamically allocated 3. using vmalloc for memory allocation instead of BITS_PER_LONG + __get_free_pages 4. fixed many coding style issues Thanks to Eric Dumazet. Signed-off-by: Dmitry Kozlov Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- MAINTAINERS | 14 + drivers/net/Kconfig | 11 + drivers/net/Makefile | 1 + drivers/net/pptp.c | 726 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/if_pppox.h | 52 ++-- include/net/gre.h | 18 ++ net/ipv4/Kconfig | 7 + net/ipv4/Makefile | 1 + net/ipv4/gre.c | 151 ++++++++++ net/ipv4/ip_gre.c | 14 +- 10 files changed, 971 insertions(+), 24 deletions(-) create mode 100644 drivers/net/pptp.c create mode 100644 include/net/gre.h create mode 100644 net/ipv4/gre.c diff --git a/MAINTAINERS b/MAINTAINERS index b5b8baa1d70e..43c9efcd8e10 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6528,6 +6528,20 @@ M: "Maciej W. Rozycki" S: Maintained F: drivers/serial/zs.* +GRE DEMULTIPLEXER DRIVER +M: Dmitry Kozlov +L: netdev@vger.kernel.org +S: Maintained +F: net/ipv4/gre.c +F: include/net/gre.h + +PPTP DRIVER +M: Dmitry Kozlov +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/pptp.c +W: http://sourceforge.net/projects/accel-pptp + THE REST M: Linus Torvalds L: linux-kernel@vger.kernel.org diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5a6895320b48..9b2a72089a68 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -3192,6 +3192,17 @@ config PPPOE which contains instruction on how to use this driver (under the heading "Kernel mode PPPoE"). +config PPTP + tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)" + depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX + help + Support for PPP over IPv4.(Point-to-Point Tunneling Protocol) + + This driver requires pppd plugin to work in client mode or + modified pptpd (poptop) to work in server mode. + See http://accel-pptp.sourceforge.net/ for information how to + utilize this module. + config PPPOATM tristate "PPP over ATM" depends on ATM && PPP diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 56e8c27f77ce..0b371083d481 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -162,6 +162,7 @@ obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o obj-$(CONFIG_PPPOE) += pppox.o pppoe.o obj-$(CONFIG_PPPOL2TP) += pppox.o +obj-$(CONFIG_PPTP) += pppox.o pptp.o obj-$(CONFIG_SLIP) += slip.o obj-$(CONFIG_SLHC) += slhc.o diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c new file mode 100644 index 000000000000..761f0eced724 --- /dev/null +++ b/drivers/net/pptp.c @@ -0,0 +1,726 @@ +/* + * Point-to-Point Tunneling Protocol for Linux + * + * Authors: Dmitry Kozlov + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define PPTP_DRIVER_VERSION "0.8.5" + +#define MAX_CALLID 65535 + +static DECLARE_BITMAP(callid_bitmap, MAX_CALLID + 1); +static struct pppox_sock **callid_sock; + +static DEFINE_SPINLOCK(chan_lock); + +static struct proto pptp_sk_proto __read_mostly; +static struct ppp_channel_ops pptp_chan_ops; +static const struct proto_ops pptp_ops; + +#define PPP_LCP_ECHOREQ 0x09 +#define PPP_LCP_ECHOREP 0x0A +#define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) + +#define MISSING_WINDOW 20 +#define WRAPPED(curseq, lastseq)\ + ((((curseq) & 0xffffff00) == 0) &&\ + (((lastseq) & 0xffffff00) == 0xffffff00)) + +#define PPTP_GRE_PROTO 0x880B +#define PPTP_GRE_VER 0x1 + +#define PPTP_GRE_FLAG_C 0x80 +#define PPTP_GRE_FLAG_R 0x40 +#define PPTP_GRE_FLAG_K 0x20 +#define PPTP_GRE_FLAG_S 0x10 +#define PPTP_GRE_FLAG_A 0x80 + +#define PPTP_GRE_IS_C(f) ((f)&PPTP_GRE_FLAG_C) +#define PPTP_GRE_IS_R(f) ((f)&PPTP_GRE_FLAG_R) +#define PPTP_GRE_IS_K(f) ((f)&PPTP_GRE_FLAG_K) +#define PPTP_GRE_IS_S(f) ((f)&PPTP_GRE_FLAG_S) +#define PPTP_GRE_IS_A(f) ((f)&PPTP_GRE_FLAG_A) + +#define PPTP_HEADER_OVERHEAD (2+sizeof(struct pptp_gre_header)) +struct pptp_gre_header { + u8 flags; + u8 ver; + u16 protocol; + u16 payload_len; + u16 call_id; + u32 seq; + u32 ack; +} __packed; + +static struct pppox_sock *lookup_chan(u16 call_id, __be32 s_addr) +{ + struct pppox_sock *sock; + struct pptp_opt *opt; + + rcu_read_lock(); + sock = rcu_dereference(callid_sock[call_id]); + if (sock) { + opt = &sock->proto.pptp; + if (opt->dst_addr.sin_addr.s_addr != s_addr) + sock = NULL; + else + sock_hold(sk_pppox(sock)); + } + rcu_read_unlock(); + + return sock; +} + +static int lookup_chan_dst(u16 call_id, __be32 d_addr) +{ + struct pppox_sock *sock; + struct pptp_opt *opt; + int i; + + rcu_read_lock(); + for (i = find_next_bit(callid_bitmap, MAX_CALLID, 1); i < MAX_CALLID; + i = find_next_bit(callid_bitmap, MAX_CALLID, i + 1)) { + sock = rcu_dereference(callid_sock[i]); + if (!sock) + continue; + opt = &sock->proto.pptp; + if (opt->dst_addr.call_id == call_id && + opt->dst_addr.sin_addr.s_addr == d_addr) + break; + } + rcu_read_unlock(); + + return i < MAX_CALLID; +} + +static int add_chan(struct pppox_sock *sock) +{ + static int call_id; + + spin_lock(&chan_lock); + if (!sock->proto.pptp.src_addr.call_id) { + call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1); + if (call_id == MAX_CALLID) { + call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1); + if (call_id == MAX_CALLID) + goto out_err; + } + sock->proto.pptp.src_addr.call_id = call_id; + } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap)) + goto out_err; + + set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap); + rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock); + spin_unlock(&chan_lock); + + return 0; + +out_err: + spin_unlock(&chan_lock); + return -1; +} + +static void del_chan(struct pppox_sock *sock) +{ + spin_lock(&chan_lock); + clear_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap); + rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], NULL); + spin_unlock(&chan_lock); + synchronize_rcu(); +} + +static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) +{ + struct sock *sk = (struct sock *) chan->private; + struct pppox_sock *po = pppox_sk(sk); + struct pptp_opt *opt = &po->proto.pptp; + struct pptp_gre_header *hdr; + unsigned int header_len = sizeof(*hdr); + int err = 0; + int islcp; + int len; + unsigned char *data; + __u32 seq_recv; + + + struct rtable *rt; + struct net_device *tdev; + struct iphdr *iph; + int max_headroom; + + if (sk_pppox(po)->sk_state & PPPOX_DEAD) + goto tx_error; + + { + struct flowi fl = { .oif = 0, + .nl_u = { + .ip4_u = { + .daddr = opt->dst_addr.sin_addr.s_addr, + .saddr = opt->src_addr.sin_addr.s_addr, + .tos = RT_TOS(0) } }, + .proto = IPPROTO_GRE }; + err = ip_route_output_key(&init_net, &rt, &fl); + if (err) + goto tx_error; + } + tdev = rt->dst.dev; + + max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(*iph) + sizeof(*hdr) + 2; + + if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { + struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); + if (!new_skb) { + ip_rt_put(rt); + goto tx_error; + } + if (skb->sk) + skb_set_owner_w(new_skb, skb->sk); + kfree_skb(skb); + skb = new_skb; + } + + data = skb->data; + islcp = ((data[0] << 8) + data[1]) == PPP_LCP && 1 <= data[2] && data[2] <= 7; + + /* compress protocol field */ + if ((opt->ppp_flags & SC_COMP_PROT) && data[0] == 0 && !islcp) + skb_pull(skb, 1); + + /* Put in the address/control bytes if necessary */ + if ((opt->ppp_flags & SC_COMP_AC) == 0 || islcp) { + data = skb_push(skb, 2); + data[0] = PPP_ALLSTATIONS; + data[1] = PPP_UI; + } + + len = skb->len; + + seq_recv = opt->seq_recv; + + if (opt->ack_sent == seq_recv) + header_len -= sizeof(hdr->ack); + + /* Push down and install GRE header */ + skb_push(skb, header_len); + hdr = (struct pptp_gre_header *)(skb->data); + + hdr->flags = PPTP_GRE_FLAG_K; + hdr->ver = PPTP_GRE_VER; + hdr->protocol = htons(PPTP_GRE_PROTO); + hdr->call_id = htons(opt->dst_addr.call_id); + + hdr->flags |= PPTP_GRE_FLAG_S; + hdr->seq = htonl(++opt->seq_sent); + if (opt->ack_sent != seq_recv) { + /* send ack with this message */ + hdr->ver |= PPTP_GRE_FLAG_A; + hdr->ack = htonl(seq_recv); + opt->ack_sent = seq_recv; + } + hdr->payload_len = htons(len); + + /* Push down and install the IP header. */ + + skb_reset_transport_header(skb); + skb_push(skb, sizeof(*iph)); + skb_reset_network_header(skb); + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); + IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED); + + iph = ip_hdr(skb); + iph->version = 4; + iph->ihl = sizeof(struct iphdr) >> 2; + if (ip_dont_fragment(sk, &rt->dst)) + iph->frag_off = htons(IP_DF); + else + iph->frag_off = 0; + iph->protocol = IPPROTO_GRE; + iph->tos = 0; + iph->daddr = rt->rt_dst; + iph->saddr = rt->rt_src; + iph->ttl = dst_metric(&rt->dst, RTAX_HOPLIMIT); + iph->tot_len = htons(skb->len); + + skb_dst_drop(skb); + skb_dst_set(skb, &rt->dst); + + nf_reset(skb); + + skb->ip_summed = CHECKSUM_NONE; + ip_select_ident(iph, &rt->dst, NULL); + ip_send_check(iph); + + ip_local_out(skb); + +tx_error: + return 1; +} + +static int pptp_rcv_core(struct sock *sk, struct sk_buff *skb) +{ + struct pppox_sock *po = pppox_sk(sk); + struct pptp_opt *opt = &po->proto.pptp; + int headersize, payload_len, seq; + __u8 *payload; + struct pptp_gre_header *header; + + if (!(sk->sk_state & PPPOX_CONNECTED)) { + if (sock_queue_rcv_skb(sk, skb)) + goto drop; + return NET_RX_SUCCESS; + } + + header = (struct pptp_gre_header *)(skb->data); + + /* test if acknowledgement present */ + if (PPTP_GRE_IS_A(header->ver)) { + __u32 ack = (PPTP_GRE_IS_S(header->flags)) ? + header->ack : header->seq; /* ack in different place if S = 0 */ + + ack = ntohl(ack); + + if (ack > opt->ack_recv) + opt->ack_recv = ack; + /* also handle sequence number wrap-around */ + if (WRAPPED(ack, opt->ack_recv)) + opt->ack_recv = ack; + } + + /* test if payload present */ + if (!PPTP_GRE_IS_S(header->flags)) + goto drop; + + headersize = sizeof(*header); + payload_len = ntohs(header->payload_len); + seq = ntohl(header->seq); + + /* no ack present? */ + if (!PPTP_GRE_IS_A(header->ver)) + headersize -= sizeof(header->ack); + /* check for incomplete packet (length smaller than expected) */ + if (skb->len - headersize < payload_len) + goto drop; + + payload = skb->data + headersize; + /* check for expected sequence number */ + if (seq < opt->seq_recv + 1 || WRAPPED(opt->seq_recv, seq)) { + if ((payload[0] == PPP_ALLSTATIONS) && (payload[1] == PPP_UI) && + (PPP_PROTOCOL(payload) == PPP_LCP) && + ((payload[4] == PPP_LCP_ECHOREQ) || (payload[4] == PPP_LCP_ECHOREP))) + goto allow_packet; + } else { + opt->seq_recv = seq; +allow_packet: + skb_pull(skb, headersize); + + if (payload[0] == PPP_ALLSTATIONS && payload[1] == PPP_UI) { + /* chop off address/control */ + if (skb->len < 3) + goto drop; + skb_pull(skb, 2); + } + + if ((*skb->data) & 1) { + /* protocol is compressed */ + skb_push(skb, 1)[0] = 0; + } + + skb->ip_summed = CHECKSUM_NONE; + skb_set_network_header(skb, skb->head-skb->data); + ppp_input(&po->chan, skb); + + return NET_RX_SUCCESS; + } +drop: + kfree_skb(skb); + return NET_RX_DROP; +} + +static int pptp_rcv(struct sk_buff *skb) +{ + struct pppox_sock *po; + struct pptp_gre_header *header; + struct iphdr *iph; + + if (skb->pkt_type != PACKET_HOST) + goto drop; + + if (!pskb_may_pull(skb, 12)) + goto drop; + + iph = ip_hdr(skb); + + header = (struct pptp_gre_header *)skb->data; + + if (ntohs(header->protocol) != PPTP_GRE_PROTO || /* PPTP-GRE protocol for PPTP */ + PPTP_GRE_IS_C(header->flags) || /* flag C should be clear */ + PPTP_GRE_IS_R(header->flags) || /* flag R should be clear */ + !PPTP_GRE_IS_K(header->flags) || /* flag K should be set */ + (header->flags&0xF) != 0) /* routing and recursion ctrl = 0 */ + /* if invalid, discard this packet */ + goto drop; + + po = lookup_chan(htons(header->call_id), iph->saddr); + if (po) { + skb_dst_drop(skb); + nf_reset(skb); + return sk_receive_skb(sk_pppox(po), skb, 0); + } +drop: + kfree_skb(skb); + return NET_RX_DROP; +} + +static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, + int sockaddr_len) +{ + struct sock *sk = sock->sk; + struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; + struct pppox_sock *po = pppox_sk(sk); + struct pptp_opt *opt = &po->proto.pptp; + int error = 0; + + lock_sock(sk); + + opt->src_addr = sp->sa_addr.pptp; + if (add_chan(po)) { + release_sock(sk); + error = -EBUSY; + } + + release_sock(sk); + return error; +} + +static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, + int sockaddr_len, int flags) +{ + struct sock *sk = sock->sk; + struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; + struct pppox_sock *po = pppox_sk(sk); + struct pptp_opt *opt = &po->proto.pptp; + struct rtable *rt; + int error = 0; + + if (sp->sa_protocol != PX_PROTO_PPTP) + return -EINVAL; + + if (lookup_chan_dst(sp->sa_addr.pptp.call_id, sp->sa_addr.pptp.sin_addr.s_addr)) + return -EALREADY; + + lock_sock(sk); + /* Check for already bound sockets */ + if (sk->sk_state & PPPOX_CONNECTED) { + error = -EBUSY; + goto end; + } + + /* Check for already disconnected sockets, on attempts to disconnect */ + if (sk->sk_state & PPPOX_DEAD) { + error = -EALREADY; + goto end; + } + + if (!opt->src_addr.sin_addr.s_addr || !sp->sa_addr.pptp.sin_addr.s_addr) { + error = -EINVAL; + goto end; + } + + po->chan.private = sk; + po->chan.ops = &pptp_chan_ops; + + { + struct flowi fl = { + .nl_u = { + .ip4_u = { + .daddr = opt->dst_addr.sin_addr.s_addr, + .saddr = opt->src_addr.sin_addr.s_addr, + .tos = RT_CONN_FLAGS(sk) } }, + .proto = IPPROTO_GRE }; + security_sk_classify_flow(sk, &fl); + if (ip_route_output_key(&init_net, &rt, &fl)) { + error = -EHOSTUNREACH; + goto end; + } + sk_setup_caps(sk, &rt->dst); + } + po->chan.mtu = dst_mtu(&rt->dst); + if (!po->chan.mtu) + po->chan.mtu = PPP_MTU; + ip_rt_put(rt); + po->chan.mtu -= PPTP_HEADER_OVERHEAD; + + po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header); + error = ppp_register_channel(&po->chan); + if (error) { + pr_err("PPTP: failed to register PPP channel (%d)\n", error); + goto end; + } + + opt->dst_addr = sp->sa_addr.pptp; + sk->sk_state = PPPOX_CONNECTED; + + end: + release_sock(sk); + return error; +} + +static int pptp_getname(struct socket *sock, struct sockaddr *uaddr, + int *usockaddr_len, int peer) +{ + int len = sizeof(struct sockaddr_pppox); + struct sockaddr_pppox sp; + + sp.sa_family = AF_PPPOX; + sp.sa_protocol = PX_PROTO_PPTP; + sp.sa_addr.pptp = pppox_sk(sock->sk)->proto.pptp.src_addr; + + memcpy(uaddr, &sp, len); + + *usockaddr_len = len; + + return 0; +} + +static int pptp_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + struct pppox_sock *po; + struct pptp_opt *opt; + int error = 0; + + if (!sk) + return 0; + + lock_sock(sk); + + if (sock_flag(sk, SOCK_DEAD)) { + release_sock(sk); + return -EBADF; + } + + po = pppox_sk(sk); + opt = &po->proto.pptp; + del_chan(po); + + pppox_unbind_sock(sk); + sk->sk_state = PPPOX_DEAD; + + sock_orphan(sk); + sock->sk = NULL; + + release_sock(sk); + sock_put(sk); + + return error; +} + +static void pptp_sock_destruct(struct sock *sk) +{ + if (!(sk->sk_state & PPPOX_DEAD)) { + del_chan(pppox_sk(sk)); + pppox_unbind_sock(sk); + } + skb_queue_purge(&sk->sk_receive_queue); +} + +static int pptp_create(struct net *net, struct socket *sock) +{ + int error = -ENOMEM; + struct sock *sk; + struct pppox_sock *po; + struct pptp_opt *opt; + + sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pptp_sk_proto); + if (!sk) + goto out; + + sock_init_data(sock, sk); + + sock->state = SS_UNCONNECTED; + sock->ops = &pptp_ops; + + sk->sk_backlog_rcv = pptp_rcv_core; + sk->sk_state = PPPOX_NONE; + sk->sk_type = SOCK_STREAM; + sk->sk_family = PF_PPPOX; + sk->sk_protocol = PX_PROTO_PPTP; + sk->sk_destruct = pptp_sock_destruct; + + po = pppox_sk(sk); + opt = &po->proto.pptp; + + opt->seq_sent = 0; opt->seq_recv = 0; + opt->ack_recv = 0; opt->ack_sent = 0; + + error = 0; +out: + return error; +} + +static int pptp_ppp_ioctl(struct ppp_channel *chan, unsigned int cmd, + unsigned long arg) +{ + struct sock *sk = (struct sock *) chan->private; + struct pppox_sock *po = pppox_sk(sk); + struct pptp_opt *opt = &po->proto.pptp; + void __user *argp = (void __user *)arg; + int __user *p = argp; + int err, val; + + err = -EFAULT; + switch (cmd) { + case PPPIOCGFLAGS: + val = opt->ppp_flags; + if (put_user(val, p)) + break; + err = 0; + break; + case PPPIOCSFLAGS: + if (get_user(val, p)) + break; + opt->ppp_flags = val & ~SC_RCV_BITS; + err = 0; + break; + default: + err = -ENOTTY; + } + + return err; +} + +static struct ppp_channel_ops pptp_chan_ops = { + .start_xmit = pptp_xmit, + .ioctl = pptp_ppp_ioctl, +}; + +static struct proto pptp_sk_proto __read_mostly = { + .name = "PPTP", + .owner = THIS_MODULE, + .obj_size = sizeof(struct pppox_sock), +}; + +static const struct proto_ops pptp_ops = { + .family = AF_PPPOX, + .owner = THIS_MODULE, + .release = pptp_release, + .bind = pptp_bind, + .connect = pptp_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = pptp_getname, + .poll = sock_no_poll, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .setsockopt = sock_no_setsockopt, + .getsockopt = sock_no_getsockopt, + .sendmsg = sock_no_sendmsg, + .recvmsg = sock_no_recvmsg, + .mmap = sock_no_mmap, + .ioctl = pppox_ioctl, +}; + +static struct pppox_proto pppox_pptp_proto = { + .create = pptp_create, + .owner = THIS_MODULE, +}; + +static struct gre_protocol gre_pptp_protocol = { + .handler = pptp_rcv, +}; + +static int __init pptp_init_module(void) +{ + int err = 0; + pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n"); + + callid_sock = __vmalloc((MAX_CALLID + 1) * sizeof(void *), + GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL); + if (!callid_sock) { + pr_err("PPTP: cann't allocate memory\n"); + return -ENOMEM; + } + + err = gre_add_protocol(&gre_pptp_protocol, GREPROTO_PPTP); + if (err) { + pr_err("PPTP: can't add gre protocol\n"); + goto out_mem_free; + } + + err = proto_register(&pptp_sk_proto, 0); + if (err) { + pr_err("PPTP: can't register sk_proto\n"); + goto out_gre_del_protocol; + } + + err = register_pppox_proto(PX_PROTO_PPTP, &pppox_pptp_proto); + if (err) { + pr_err("PPTP: can't register pppox_proto\n"); + goto out_unregister_sk_proto; + } + + return 0; + +out_unregister_sk_proto: + proto_unregister(&pptp_sk_proto); +out_gre_del_protocol: + gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP); +out_mem_free: + vfree(callid_sock); + + return err; +} + +static void __exit pptp_exit_module(void) +{ + unregister_pppox_proto(PX_PROTO_PPTP); + proto_unregister(&pptp_sk_proto); + gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP); + vfree(callid_sock); +} + +module_init(pptp_init_module); +module_exit(pptp_exit_module); + +MODULE_DESCRIPTION("Point-to-Point Tunneling Protocol"); +MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h index 1925e0c3f162..1525b2156b2a 100644 --- a/include/linux/if_pppox.h +++ b/include/linux/if_pppox.h @@ -40,25 +40,35 @@ * PPPoE addressing definition */ typedef __be16 sid_t; -struct pppoe_addr{ - sid_t sid; /* Session identifier */ - unsigned char remote[ETH_ALEN]; /* Remote address */ - char dev[IFNAMSIZ]; /* Local device to use */ +struct pppoe_addr { + sid_t sid; /* Session identifier */ + unsigned char remote[ETH_ALEN]; /* Remote address */ + char dev[IFNAMSIZ]; /* Local device to use */ }; /************************************************************************ - * Protocols supported by AF_PPPOX - */ + * PPTP addressing definition + */ +struct pptp_addr { + u16 call_id; + struct in_addr sin_addr; +}; + +/************************************************************************ + * Protocols supported by AF_PPPOX + */ #define PX_PROTO_OE 0 /* Currently just PPPoE */ #define PX_PROTO_OL2TP 1 /* Now L2TP also */ -#define PX_MAX_PROTO 2 - -struct sockaddr_pppox { - sa_family_t sa_family; /* address family, AF_PPPOX */ - unsigned int sa_protocol; /* protocol identifier */ - union{ - struct pppoe_addr pppoe; - }sa_addr; +#define PX_PROTO_PPTP 2 +#define PX_MAX_PROTO 3 + +struct sockaddr_pppox { + sa_family_t sa_family; /* address family, AF_PPPOX */ + unsigned int sa_protocol; /* protocol identifier */ + union { + struct pppoe_addr pppoe; + struct pptp_addr pptp; + } sa_addr; } __packed; /* The use of the above union isn't viable because the size of this @@ -101,7 +111,7 @@ struct pppoe_tag { __be16 tag_type; __be16 tag_len; char tag_data[0]; -} __attribute ((packed)); +} __packed; /* Tag identifiers */ #define PTT_EOL __cpu_to_be16(0x0000) @@ -150,15 +160,23 @@ struct pppoe_opt { relayed to (PPPoE relaying) */ }; +struct pptp_opt { + struct pptp_addr src_addr; + struct pptp_addr dst_addr; + u32 ack_sent, ack_recv; + u32 seq_sent, seq_recv; + int ppp_flags; +}; #include struct pppox_sock { /* struct sock must be the first member of pppox_sock */ - struct sock sk; - struct ppp_channel chan; + struct sock sk; + struct ppp_channel chan; struct pppox_sock *next; /* for hash table */ union { struct pppoe_opt pppoe; + struct pptp_opt pptp; } proto; __be16 num; }; diff --git a/include/net/gre.h b/include/net/gre.h new file mode 100644 index 000000000000..82665474bcb7 --- /dev/null +++ b/include/net/gre.h @@ -0,0 +1,18 @@ +#ifndef __LINUX_GRE_H +#define __LINUX_GRE_H + +#include + +#define GREPROTO_CISCO 0 +#define GREPROTO_PPTP 1 +#define GREPROTO_MAX 2 + +struct gre_protocol { + int (*handler)(struct sk_buff *skb); + void (*err_handler)(struct sk_buff *skb, u32 info); +}; + +int gre_add_protocol(const struct gre_protocol *proto, u8 version); +int gre_del_protocol(const struct gre_protocol *proto, u8 version); + +#endif diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 7c3a7d191249..7458bdae7e9f 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -215,8 +215,15 @@ config NET_IPIP be inserted in and removed from the running kernel whenever you want). Most people won't need this and can say N. +config NET_IPGRE_DEMUX + tristate "IP: GRE demultiplexer" + help + This is helper module to demultiplex GRE packets on GRE version field criteria. + Required by ip_gre and pptp modules. + config NET_IPGRE tristate "IP: GRE tunnels over IP" + depends on NET_IPGRE_DEMUX help Tunneling means encapsulating data of one protocol type within another protocol and sending it over a channel that understands the diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 80ff87ce43aa..4978d22f9a75 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o obj-$(CONFIG_IP_MROUTE) += ipmr.o obj-$(CONFIG_NET_IPIP) += ipip.o +obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o obj-$(CONFIG_NET_IPGRE) += ip_gre.o obj-$(CONFIG_SYN_COOKIES) += syncookies.o obj-$(CONFIG_INET_AH) += ah4.o diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c new file mode 100644 index 000000000000..b546736da2e1 --- /dev/null +++ b/net/ipv4/gre.c @@ -0,0 +1,151 @@ +/* + * GRE over IPv4 demultiplexer driver + * + * Authors: Dmitry Kozlov (xeb@mail.ru) + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +const struct gre_protocol *gre_proto[GREPROTO_MAX] __read_mostly; +static DEFINE_SPINLOCK(gre_proto_lock); + +int gre_add_protocol(const struct gre_protocol *proto, u8 version) +{ + if (version >= GREPROTO_MAX) + goto err_out; + + spin_lock(&gre_proto_lock); + if (gre_proto[version]) + goto err_out_unlock; + + rcu_assign_pointer(gre_proto[version], proto); + spin_unlock(&gre_proto_lock); + return 0; + +err_out_unlock: + spin_unlock(&gre_proto_lock); +err_out: + return -1; +} +EXPORT_SYMBOL_GPL(gre_add_protocol); + +int gre_del_protocol(const struct gre_protocol *proto, u8 version) +{ + if (version >= GREPROTO_MAX) + goto err_out; + + spin_lock(&gre_proto_lock); + if (gre_proto[version] != proto) + goto err_out_unlock; + rcu_assign_pointer(gre_proto[version], NULL); + spin_unlock(&gre_proto_lock); + synchronize_rcu(); + return 0; + +err_out_unlock: + spin_unlock(&gre_proto_lock); +err_out: + return -1; +} +EXPORT_SYMBOL_GPL(gre_del_protocol); + +static int gre_rcv(struct sk_buff *skb) +{ + const struct gre_protocol *proto; + u8 ver; + int ret; + + if (!pskb_may_pull(skb, 12)) + goto drop; + + ver = skb->data[1]&0x7f; + if (ver >= GREPROTO_MAX) + goto drop; + + rcu_read_lock(); + proto = rcu_dereference(gre_proto[ver]); + if (!proto || !proto->handler) + goto drop_unlock; + ret = proto->handler(skb); + rcu_read_unlock(); + return ret; + +drop_unlock: + rcu_read_unlock(); +drop: + kfree_skb(skb); + return NET_RX_DROP; +} + +static void gre_err(struct sk_buff *skb, u32 info) +{ + const struct gre_protocol *proto; + u8 ver; + + if (!pskb_may_pull(skb, 12)) + goto drop; + + ver = skb->data[1]&0x7f; + if (ver >= GREPROTO_MAX) + goto drop; + + rcu_read_lock(); + proto = rcu_dereference(gre_proto[ver]); + if (!proto || !proto->err_handler) + goto drop_unlock; + proto->err_handler(skb, info); + rcu_read_unlock(); + return; + +drop_unlock: + rcu_read_unlock(); +drop: + kfree_skb(skb); +} + +static const struct net_protocol net_gre_protocol = { + .handler = gre_rcv, + .err_handler = gre_err, + .netns_ok = 1, +}; + +static int __init gre_init(void) +{ + pr_info("GRE over IPv4 demultiplexor driver"); + + if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) { + pr_err("gre: can't add protocol\n"); + return -EAGAIN; + } + + return 0; +} + +static void __exit gre_exit(void) +{ + inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); +} + +module_init(gre_init); +module_exit(gre_exit); + +MODULE_DESCRIPTION("GRE over IPv4 demultiplexer driver"); +MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); +MODULE_LICENSE("GPL"); + diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 945b20a5ad50..85176895495a 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -44,6 +44,7 @@ #include #include #include +#include #ifdef CONFIG_IPV6 #include @@ -1278,10 +1279,9 @@ static void ipgre_fb_tunnel_init(struct net_device *dev) } -static const struct net_protocol ipgre_protocol = { - .handler = ipgre_rcv, - .err_handler = ipgre_err, - .netns_ok = 1, +static const struct gre_protocol ipgre_protocol = { + .handler = ipgre_rcv, + .err_handler = ipgre_err, }; static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head) @@ -1663,7 +1663,7 @@ static int __init ipgre_init(void) if (err < 0) return err; - err = inet_add_protocol(&ipgre_protocol, IPPROTO_GRE); + err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); if (err < 0) { printk(KERN_INFO "ipgre init: can't add protocol\n"); goto add_proto_failed; @@ -1683,7 +1683,7 @@ out: tap_ops_failed: rtnl_link_unregister(&ipgre_link_ops); rtnl_link_failed: - inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); + gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); add_proto_failed: unregister_pernet_device(&ipgre_net_ops); goto out; @@ -1693,7 +1693,7 @@ static void __exit ipgre_fini(void) { rtnl_link_unregister(&ipgre_tap_ops); rtnl_link_unregister(&ipgre_link_ops); - if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) + if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0) printk(KERN_INFO "ipgre close: can't remove protocol\n"); unregister_pernet_device(&ipgre_net_ops); } -- cgit v1.2.3-59-g8ed1b From a2c483a19a96cf5cb9465f42cca34548b9211954 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 20 Aug 2010 02:55:16 +0000 Subject: atl1c: use net_device_stats from struct net_device struct net_device has its own struct net_device_stats member, so use this one instead of a private copy in the atl1c_adapter struct. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/atl1c/atl1c.h | 1 - drivers/net/atl1c/atl1c_main.c | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index 52abbbdf8a08..ef4115b897bf 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h @@ -559,7 +559,6 @@ struct atl1c_adapter { struct napi_struct napi; struct atl1c_hw hw; struct atl1c_hw_stats hw_stats; - struct net_device_stats net_stats; struct mii_if_info mii; /* MII interface info */ u16 rx_buffer_len; diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index c7b8ef507ebd..61f1634ab3f8 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -1562,7 +1562,7 @@ static struct net_device_stats *atl1c_get_stats(struct net_device *netdev) { struct atl1c_adapter *adapter = netdev_priv(netdev); struct atl1c_hw_stats *hw_stats = &adapter->hw_stats; - struct net_device_stats *net_stats = &adapter->net_stats; + struct net_device_stats *net_stats = &netdev->stats; atl1c_update_hw_stats(adapter); net_stats->rx_packets = hw_stats->rx_ok; @@ -1590,7 +1590,7 @@ static struct net_device_stats *atl1c_get_stats(struct net_device *netdev) net_stats->tx_aborted_errors = hw_stats->tx_abort_col; net_stats->tx_window_errors = hw_stats->tx_late_col; - return &adapter->net_stats; + return net_stats; } static inline void atl1c_clear_phy_int(struct atl1c_adapter *adapter) @@ -1700,7 +1700,7 @@ static irqreturn_t atl1c_intr(int irq, void *data) /* link event */ if (status & (ISR_GPHY | ISR_MANUAL)) { - adapter->net_stats.tx_carrier_errors++; + netdev->stats.tx_carrier_errors++; atl1c_link_chg_event(adapter); break; } -- cgit v1.2.3-59-g8ed1b From c3227e546c574172e77616270a16a04eae561b8f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 20 Aug 2010 03:08:23 +0000 Subject: amd8111e: use net_device_stats from struct net_device struct net_device has its own struct net_device_stats member, so use this one instead of a private copy in the amd8111e_priv struct. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/amd8111e.c | 14 +++++++------- drivers/net/amd8111e.h | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 1f5fc64b3224..58a0ab4923ee 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -903,18 +903,18 @@ static int amd8111e_read_mib(void __iomem *mmio, u8 MIB_COUNTER) } /* -This function reads the mib registers and returns the hardware statistics. It updates previous internal driver statistics with new values. -*/ -static struct net_device_stats *amd8111e_get_stats(struct net_device * dev) + * This function reads the mib registers and returns the hardware statistics. + * It updates previous internal driver statistics with new values. + */ +static struct net_device_stats *amd8111e_get_stats(struct net_device *dev) { struct amd8111e_priv *lp = netdev_priv(dev); void __iomem *mmio = lp->mmio; unsigned long flags; - /* struct net_device_stats *prev_stats = &lp->prev_stats; */ - struct net_device_stats* new_stats = &lp->stats; + struct net_device_stats *new_stats = &dev->stats; - if(!lp->opened) - return &lp->stats; + if (!lp->opened) + return new_stats; spin_lock_irqsave (&lp->lock, flags); /* stats.rx_packets */ diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h index ac36eb6981e3..b5926af03a7e 100644 --- a/drivers/net/amd8111e.h +++ b/drivers/net/amd8111e.h @@ -787,7 +787,6 @@ struct amd8111e_priv{ struct vlan_group *vlgrp; #endif char opened; - struct net_device_stats stats; unsigned int drv_rx_errors; struct amd8111e_coalesce_conf coal_conf; -- cgit v1.2.3-59-g8ed1b From 81ce790bd75d49a0d119f5d7b27405e1d9b1bd57 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 19 Aug 2010 23:51:33 +0000 Subject: irda: use net_device_stats from struct net_device struct net_device has its own struct net_device_stats member, so use this one instead of a private copy in the irlan_cb struct. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/irda/irlan_common.h | 1 - net/irda/irlan/irlan_eth.c | 32 +++++++++----------------------- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/include/net/irda/irlan_common.h b/include/net/irda/irlan_common.h index 73cacb3ac16c..0af8b8dfbc22 100644 --- a/include/net/irda/irlan_common.h +++ b/include/net/irda/irlan_common.h @@ -171,7 +171,6 @@ struct irlan_cb { int magic; struct list_head dev_list; struct net_device *dev; /* Ethernet device structure*/ - struct net_device_stats stats; __u32 saddr; /* Source device address */ __u32 daddr; /* Destination device address */ diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index 5bb8353105cc..8ee1ff6c742f 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -45,13 +45,11 @@ static int irlan_eth_close(struct net_device *dev); static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev); static void irlan_eth_set_multicast_list( struct net_device *dev); -static struct net_device_stats *irlan_eth_get_stats(struct net_device *dev); static const struct net_device_ops irlan_eth_netdev_ops = { .ndo_open = irlan_eth_open, .ndo_stop = irlan_eth_close, .ndo_start_xmit = irlan_eth_xmit, - .ndo_get_stats = irlan_eth_get_stats, .ndo_set_multicast_list = irlan_eth_set_multicast_list, .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, @@ -208,10 +206,10 @@ static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb, * tried :-) DB */ /* irttp_data_request already free the packet */ - self->stats.tx_dropped++; + dev->stats.tx_dropped++; } else { - self->stats.tx_packets++; - self->stats.tx_bytes += len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += len; } return NETDEV_TX_OK; @@ -226,15 +224,16 @@ static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb, int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb) { struct irlan_cb *self = instance; + struct net_device *dev = self->dev; if (skb == NULL) { - ++self->stats.rx_dropped; + dev->stats.rx_dropped++; return 0; } if (skb->len < ETH_HLEN) { IRDA_DEBUG(0, "%s() : IrLAN frame too short (%d)\n", __func__, skb->len); - ++self->stats.rx_dropped; + dev->stats.rx_dropped++; dev_kfree_skb(skb); return 0; } @@ -244,10 +243,10 @@ int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb) * might have been previously set by the low level IrDA network * device driver */ - skb->protocol = eth_type_trans(skb, self->dev); /* Remove eth header */ + skb->protocol = eth_type_trans(skb, dev); /* Remove eth header */ - self->stats.rx_packets++; - self->stats.rx_bytes += skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; netif_rx(skb); /* Eat it! */ @@ -348,16 +347,3 @@ static void irlan_eth_set_multicast_list(struct net_device *dev) else irlan_set_broadcast_filter(self, FALSE); } - -/* - * Function irlan_get_stats (dev) - * - * Get the current statistics for this device - * - */ -static struct net_device_stats *irlan_eth_get_stats(struct net_device *dev) -{ - struct irlan_cb *self = netdev_priv(dev); - - return &self->stats; -} -- cgit v1.2.3-59-g8ed1b From 739a91ef0625e0e4a40b835f4f891313c47915df Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Sat, 21 Aug 2010 06:23:15 +0000 Subject: net_sched: cls_flow: add key rxhash We can use rxhash to classify the traffic into flows. As rxhash maybe supplied by NIC or RPS, it is cheaper. Signed-off-by: Changli Gao Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/linux/pkt_cls.h | 1 + net/sched/cls_flow.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h index 7f6ba8658abe..defbde203d07 100644 --- a/include/linux/pkt_cls.h +++ b/include/linux/pkt_cls.h @@ -332,6 +332,7 @@ enum { FLOW_KEY_SKUID, FLOW_KEY_SKGID, FLOW_KEY_VLAN_TAG, + FLOW_KEY_RXHASH, __FLOW_KEY_MAX, }; diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index cd709f1294df..5b271a18bc3a 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c @@ -306,6 +306,11 @@ static u32 flow_get_vlan_tag(const struct sk_buff *skb) return tag & VLAN_VID_MASK; } +static u32 flow_get_rxhash(struct sk_buff *skb) +{ + return skb_get_rxhash(skb); +} + static u32 flow_key_get(struct sk_buff *skb, int key) { switch (key) { @@ -343,6 +348,8 @@ static u32 flow_key_get(struct sk_buff *skb, int key) return flow_get_skgid(skb); case FLOW_KEY_VLAN_TAG: return flow_get_vlan_tag(skb); + case FLOW_KEY_RXHASH: + return flow_get_rxhash(skb); default: WARN_ON(1); return 0; -- cgit v1.2.3-59-g8ed1b From 773bc97397ea2cfc2ff3c075f712aaf376ed7cb0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 22 Aug 2010 00:54:30 -0700 Subject: tokenring: remove unneeded NULL checks "fw_entry" is always non-NULL at this point and anyway release_firmware() handles NULL parameters. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/tokenring/tms380tr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index 435ef7d5470f..08182fde3dcd 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -1321,14 +1321,12 @@ static int tms380tr_reset_adapter(struct net_device *dev) /* Clear CPHALT and start BUD */ SIFWRITEW(c, SIFACL); - if (fw_entry) - release_firmware(fw_entry); + release_firmware(fw_entry); return (1); } } while(count == 0); - if (fw_entry) - release_firmware(fw_entry); + release_firmware(fw_entry); printk(KERN_INFO "%s: Adapter Download Failed\n", dev->name); return (-1); } -- cgit v1.2.3-59-g8ed1b From d8287fc864643beaf1623c92aceb1ab38eae0648 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Sun, 22 Aug 2010 18:37:27 -0700 Subject: net: use __be16 instead of u16 for the userspace code Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- include/linux/if_pppox.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h index 1525b2156b2a..770e8fa669d2 100644 --- a/include/linux/if_pppox.h +++ b/include/linux/if_pppox.h @@ -50,8 +50,8 @@ struct pppoe_addr { * PPTP addressing definition */ struct pptp_addr { - u16 call_id; - struct in_addr sin_addr; + __be16 call_id; + struct in_addr sin_addr; }; /************************************************************************ -- cgit v1.2.3-59-g8ed1b From 2436243a39de56f03d38c74139261cc61bea8456 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 22 Aug 2010 20:31:14 -0700 Subject: net/sched: need to include net/ip6_checksum.h for the declararion of csum_ipv6_magic. Fixes this build error on PowerPC (at least): net/sched/act_csum.c: In function 'tcf_csum_ipv6_icmp': net/sched/act_csum.c:178: error: implicit declaration of function 'csum_ipv6_magic' Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- net/sched/act_csum.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index 58d7f36949da..be41f1cc10ee 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c @@ -29,6 +29,7 @@ #include #include #include +#include #include -- cgit v1.2.3-59-g8ed1b From 05532121da0728eaedac2a0a5c3cecad3a95d765 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Sun, 22 Aug 2010 21:03:33 -0700 Subject: net: 802.1q: make vlan_hwaccel_do_receive() return void vlan_hwaccel_do_receive() always returns 0, so make it return void. Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 5 ++--- net/8021q/vlan_core.c | 3 +-- net/core/dev.c | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 3d870fda8c4f..a52320751bfc 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -119,7 +119,7 @@ extern u16 vlan_dev_vlan_id(const struct net_device *dev); extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling); -extern int vlan_hwaccel_do_receive(struct sk_buff *skb); +extern void vlan_hwaccel_do_receive(struct sk_buff *skb); extern gro_result_t vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb); @@ -147,9 +147,8 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, return NET_XMIT_SUCCESS; } -static inline int vlan_hwaccel_do_receive(struct sk_buff *skb) +static inline void vlan_hwaccel_do_receive(struct sk_buff *skb) { - return 0; } static inline gro_result_t diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 01ddb0472f86..07eeb5b99dce 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -35,7 +35,7 @@ drop: } EXPORT_SYMBOL(__vlan_hwaccel_rx); -int vlan_hwaccel_do_receive(struct sk_buff *skb) +void vlan_hwaccel_do_receive(struct sk_buff *skb) { struct net_device *dev = skb->dev; struct vlan_rx_stats *rx_stats; @@ -69,7 +69,6 @@ int vlan_hwaccel_do_receive(struct sk_buff *skb) break; } u64_stats_update_end(&rx_stats->syncp); - return 0; } struct net_device *vlan_dev_real_dev(const struct net_device *dev) diff --git a/net/core/dev.c b/net/core/dev.c index 7cd5237d9822..d569f88bcf80 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2841,8 +2841,8 @@ static int __netif_receive_skb(struct sk_buff *skb) if (!netdev_tstamp_prequeue) net_timestamp_check(skb); - if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb)) - return NET_RX_SUCCESS; + if (vlan_tx_tag_present(skb)) + vlan_hwaccel_do_receive(skb); /* if we've gotten here through NAPI, check netpoll */ if (netpoll_receive_skb(skb)) -- cgit v1.2.3-59-g8ed1b From cd709aa90648195e5b5823fa90eb0b3fb0e78ee4 Mon Sep 17 00:00:00 2001 From: John Feeney Date: Sun, 22 Aug 2010 17:45:53 +0000 Subject: bnx2: Add PCI Advanced Error Reporting support. Signed-off-by: John Feeney Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index e6a803f1c507..a0e02aa42214 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -49,6 +49,7 @@ #include #include #include +#include #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE) #define BCM_CNIC 1 @@ -7890,6 +7891,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) int rc, i, j; u32 reg; u64 dma_mask, persist_dma_mask; + int err; SET_NETDEV_DEV(dev, &pdev->dev); bp = netdev_priv(dev); @@ -7925,6 +7927,14 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) goto err_out_disable; } + /* AER (Advanced Error Reporting) hooks */ + err = pci_enable_pcie_error_reporting(pdev); + if (err) { + dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed " + "0x%x\n", err); + /* non-fatal, continue */ + } + pci_set_master(pdev); pci_save_state(pdev); @@ -8246,6 +8256,7 @@ err_out_unmap: } err_out_release: + pci_disable_pcie_error_reporting(pdev); pci_release_regions(pdev); err_out_disable: @@ -8436,6 +8447,9 @@ bnx2_remove_one(struct pci_dev *pdev) kfree(bp->temp_stats_blk); free_netdev(dev); + + pci_disable_pcie_error_reporting(pdev); + pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); @@ -8527,25 +8541,35 @@ static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct bnx2 *bp = netdev_priv(dev); + pci_ers_result_t result; + int err; rtnl_lock(); if (pci_enable_device(pdev)) { dev_err(&pdev->dev, "Cannot re-enable PCI device after reset\n"); - rtnl_unlock(); - return PCI_ERS_RESULT_DISCONNECT; + result = PCI_ERS_RESULT_DISCONNECT; + } else { + pci_set_master(pdev); + pci_restore_state(pdev); + pci_save_state(pdev); + + if (netif_running(dev)) { + bnx2_set_power_state(bp, PCI_D0); + bnx2_init_nic(bp, 1); + } + result = PCI_ERS_RESULT_RECOVERED; } - pci_set_master(pdev); - pci_restore_state(pdev); - pci_save_state(pdev); + rtnl_unlock(); - if (netif_running(dev)) { - bnx2_set_power_state(bp, PCI_D0); - bnx2_init_nic(bp, 1); + err = pci_cleanup_aer_uncorrect_error_status(pdev); + if (err) { + dev_err(&pdev->dev, + "pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n", + err); /* non-fatal, continue */ } - rtnl_unlock(); - return PCI_ERS_RESULT_RECOVERED; + return result; } /** -- cgit v1.2.3-59-g8ed1b From fcb12fd2236f49aa8fdc1568ed4ebdfe4fddc6b5 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Sun, 22 Aug 2010 16:41:59 +0000 Subject: net: rds: remove duplication type definitions __be* are defined in linux/types.h now, and in fact, rds.h isn't exported to user space even. Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- include/linux/rds.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/include/linux/rds.h b/include/linux/rds.h index 24bce3ded9ea..7f3971d9fc5c 100644 --- a/include/linux/rds.h +++ b/include/linux/rds.h @@ -36,15 +36,6 @@ #include -/* These sparse annotated types shouldn't be in any user - * visible header file. We should clean this up rather - * than kludging around them. */ -#ifndef __KERNEL__ -#define __be16 u_int16_t -#define __be32 u_int32_t -#define __be64 u_int64_t -#endif - #define RDS_IB_ABI_VERSION 0x301 /* -- cgit v1.2.3-59-g8ed1b From c2368e795cec561229ef66a04ac51629b918a9e8 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Sun, 22 Aug 2010 17:35:32 +0000 Subject: bridge: is PACKET_LOOPBACK unlikely()? While looking at using netdev_rx_handler_register for openvswitch Jesse Gross suggested that an unlikely() might be worthwhile in that code. I'm interested to see if its appropriate for the bridge code. Cc: Jesse Gross Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/bridge/br_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 826cd5221536..6d04cfdf4541 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -141,7 +141,7 @@ struct sk_buff *br_handle_frame(struct sk_buff *skb) const unsigned char *dest = eth_hdr(skb)->h_dest; int (*rhook)(struct sk_buff *skb); - if (skb->pkt_type == PACKET_LOOPBACK) + if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) return skb; if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) -- cgit v1.2.3-59-g8ed1b From e88c64f0a42575e01c7ace903d0570bc0b7fcf85 Mon Sep 17 00:00:00 2001 From: Hagen Paul Pfeifer Date: Thu, 19 Aug 2010 06:33:05 +0000 Subject: tcp: allow effective reduction of TCP's rcv-buffer via setsockopt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Via setsockopt it is possible to reduce the socket RX buffer (SO_RCVBUF). TCP method to select the initial window and window scaling option in tcp_select_initial_window() currently misbehaves and do not consider a reduced RX socket buffer via setsockopt. Even though the server's RX buffer is reduced via setsockopt() to 256 byte (Initial Window 384 byte => 256 * 2 - (256 * 2 / 4)) the window scale option is still 7: 192.168.1.38.40676 > 78.47.222.210.5001: Flags [S], seq 2577214362, win 5840, options [mss 1460,sackOK,TS val 338417 ecr 0,nop,wscale 0], length 0 78.47.222.210.5001 > 192.168.1.38.40676: Flags [S.], seq 1570631029, ack 2577214363, win 384, options [mss 1452,sackOK,TS val 2435248895 ecr 338417,nop,wscale 7], length 0 192.168.1.38.40676 > 78.47.222.210.5001: Flags [.], ack 1, win 5840, options [nop,nop,TS val 338421 ecr 2435248895], length 0 Within tcp_select_initial_window() the original space argument - a representation of the rx buffer size - is expanded during tcp_select_initial_window(). Only sysctl_tcp_rmem[2], sysctl_rmem_max and window_clamp are considered to calculate the initial window. This patch adjust the window_clamp argument if the user explicitly reduce the receive buffer. Signed-off-by: Hagen Paul Pfeifer Cc: David S. Miller Cc: Patrick McHardy Cc: Eric Dumazet Cc: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index de3bd8458588..01b94b8d9ec9 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2429,6 +2429,12 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, __u8 rcv_wscale; /* Set this up on the first call only */ req->window_clamp = tp->window_clamp ? : dst_metric(dst, RTAX_WINDOW); + + /* limit the window selection if the user enforce a smaller rx buffer */ + if (sk->sk_userlocks & SOCK_RCVBUF_LOCK && + (req->window_clamp > tcp_full_space(sk) || req->window_clamp == 0)) + req->window_clamp = tcp_full_space(sk); + /* tcp_full_space because it is guaranteed to be the first packet */ tcp_select_initial_window(tcp_full_space(sk), mss - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0), @@ -2555,6 +2561,11 @@ static void tcp_connect_init(struct sock *sk) tcp_initialize_rcv_mss(sk); + /* limit the window selection if the user enforce a smaller rx buffer */ + if (sk->sk_userlocks & SOCK_RCVBUF_LOCK && + (tp->window_clamp > tcp_full_space(sk) || tp->window_clamp == 0)) + tp->window_clamp = tcp_full_space(sk); + tcp_select_initial_window(tcp_full_space(sk), tp->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0), &tp->rcv_wnd, -- cgit v1.2.3-59-g8ed1b From f502bf2bc0de4795e8dd081a2095006021c00a0f Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 18 Aug 2010 23:27:49 +0000 Subject: xen: use less generic names in netfront driver. All Xen frontend drivers have a couple of identically named functions which makes figuring out which device went wrong from a stacktrace harder than it needs to be. Rename them to something specificto the device type. Signed-off-by: Ian Campbell Cc: Jeremy Fitzhardinge Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index b50fedcef8ac..788a9bc1dbac 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1395,7 +1395,7 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info) } /* Common code used when first setting up, and when resuming. */ -static int talk_to_backend(struct xenbus_device *dev, +static int talk_to_netback(struct xenbus_device *dev, struct netfront_info *info) { const char *message; @@ -1545,7 +1545,7 @@ static int xennet_connect(struct net_device *dev) return -ENODEV; } - err = talk_to_backend(np->xbdev, np); + err = talk_to_netback(np->xbdev, np); if (err) return err; @@ -1599,7 +1599,7 @@ static int xennet_connect(struct net_device *dev) /** * Callback received when the backend's state changes. */ -static void backend_changed(struct xenbus_device *dev, +static void netback_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { struct netfront_info *np = dev_get_drvdata(&dev->dev); @@ -1801,7 +1801,7 @@ static struct xenbus_driver netfront_driver = { .probe = netfront_probe, .remove = __devexit_p(xennet_remove), .resume = netfront_resume, - .otherend_changed = backend_changed, + .otherend_changed = netback_changed, }; static int __init netif_init(void) -- cgit v1.2.3-59-g8ed1b From f3c58aceaa3f237ba43735805f4677950327b8ee Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Tue, 17 Aug 2010 21:51:18 +0000 Subject: mlx4: remove num_lro parameter As suggested by David, this parameter can die, we can use ethtool to turn LRO on/off. Compile tests only. Signed-off-by: WANG Cong Signed-off-by: David S. Miller --- drivers/net/mlx4/en_ethtool.c | 2 -- drivers/net/mlx4/en_main.c | 5 ----- drivers/net/mlx4/en_netdev.c | 3 +-- drivers/net/mlx4/en_rx.c | 4 ++-- drivers/net/mlx4/mlx4_en.h | 1 - 5 files changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c index b275238fe70d..398d54136967 100644 --- a/drivers/net/mlx4/en_ethtool.c +++ b/drivers/net/mlx4/en_ethtool.c @@ -398,8 +398,6 @@ static int mlx4_ethtool_op_set_flags(struct net_device *dev, u32 data) return -EOPNOTSUPP; if (data & ETH_FLAG_LRO) { - if (mdev->profile.num_lro == 0) - return -EOPNOTSUPP; if (!(dev->features & NETIF_F_LRO)) changed = 1; } else if (dev->features & NETIF_F_LRO) { diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c index 97934f1ec53a..cacac4e966ee 100644 --- a/drivers/net/mlx4/en_main.c +++ b/drivers/net/mlx4/en_main.c @@ -69,10 +69,6 @@ MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS"); /* RSS hash type mask - default to */ MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask"); -/* Number of LRO sessions per Rx ring (rounded up to a power of two) */ -MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS, - "Number of LRO sessions per ring or disabled (0)"); - /* Priority pausing */ MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]." " Per priority bit mask"); @@ -109,7 +105,6 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev) params->rss_xor = (rss_xor != 0); params->rss_mask = rss_mask & 0x1f; - params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS); for (i = 1; i <= MLX4_MAX_PORTS; i++) { params->prof[i].rx_pause = 1; params->prof[i].rx_ppp = pfcrx; diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index a0d8a26f5a02..d00bfe250b05 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -1038,8 +1038,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; - if (mdev->profile.num_lro) - dev->features |= NETIF_F_LRO; + dev->features |= NETIF_F_LRO; if (mdev->LSO_support) { dev->features |= NETIF_F_TSO; dev->features |= NETIF_F_TSO6; diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index efc3fad468db..2add04025fd0 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -320,9 +320,9 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, ring->lro.frag_align_pad = NET_IP_ALIGN; ring->lro.ip_summed = CHECKSUM_UNNECESSARY; ring->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY; - ring->lro.max_desc = mdev->profile.num_lro; + ring->lro.max_desc = MLX4_EN_MAX_LRO_DESCRIPTORS; ring->lro.max_aggr = MAX_SKB_FRAGS; - ring->lro.lro_arr = kcalloc(mdev->profile.num_lro, + ring->lro.lro_arr = kcalloc(MLX4_EN_MAX_LRO_DESCRIPTORS, sizeof(struct net_lro_desc), GFP_KERNEL); if (!ring->lro.lro_arr) { diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 449210994ee9..9d0932348b96 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -313,7 +313,6 @@ struct mlx4_en_port_profile { struct mlx4_en_profile { int rss_xor; - int num_lro; u8 rss_mask; u32 active_ports; u32 small_pkt_int; -- cgit v1.2.3-59-g8ed1b From 23b224d9d42a111ce451e4300304415a0ba5da75 Mon Sep 17 00:00:00 2001 From: Garnet MacPhee Date: Sat, 21 Aug 2010 14:37:34 -0600 Subject: ALSA: ice1712: Add support for Edirol DA-2496 This device is similar to the M-Audio Delta 1010LT in that it uses the AK4524VF ADC/DAC, but it does not use the CS8427 for SPDIF. The SPDIF appears to be set up correctly, but I am not able to test it as I do not have any devices that use it. This patch makes the ADC/DAC's and the hardware mixer visible to apps such as alsamixer and envy24control. Signed-off-by: Garnet MacPhee Signed-off-by: Takashi Iwai --- sound/pci/ice1712/delta.c | 10 ++++++++++ sound/pci/ice1712/delta.h | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index d216362626d0..712c1710f9a2 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c @@ -563,6 +563,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice) case ICE1712_SUBDEVICE_DELTA1010E: case ICE1712_SUBDEVICE_DELTA1010LT: case ICE1712_SUBDEVICE_MEDIASTATION: + case ICE1712_SUBDEVICE_EDIROLDA2496: ice->num_total_dacs = 8; ice->num_total_adcs = 8; break; @@ -635,6 +636,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice) err = snd_ice1712_akm4xxx_init(ak, &akm_delta410, &akm_delta410_priv, ice); break; case ICE1712_SUBDEVICE_DELTA1010LT: + case ICE1712_SUBDEVICE_EDIROLDA2496: err = snd_ice1712_akm4xxx_init(ak, &akm_delta1010lt, &akm_delta1010lt_priv, ice); break; case ICE1712_SUBDEVICE_DELTA66: @@ -734,6 +736,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice) case ICE1712_SUBDEVICE_DELTA66: case ICE1712_SUBDEVICE_VX442: case ICE1712_SUBDEVICE_DELTA66E: + case ICE1712_SUBDEVICE_EDIROLDA2496: err = snd_ice1712_akm4xxx_build_controls(ice); if (err < 0) return err; @@ -813,5 +816,12 @@ struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = { .chip_init = snd_ice1712_delta_init, .build_controls = snd_ice1712_delta_add_controls, }, + { + .subvendor = ICE1712_SUBDEVICE_EDIROLDA2496, + .name = "Edirol DA2496", + .model = "da2496", + .chip_init = snd_ice1712_delta_init, + .build_controls = snd_ice1712_delta_add_controls, + }, { } /* terminator */ }; diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h index f7f14df81f26..1a0ac6cd6501 100644 --- a/sound/pci/ice1712/delta.h +++ b/sound/pci/ice1712/delta.h @@ -34,7 +34,8 @@ "{MidiMan M Audio,Delta 410},"\ "{MidiMan M Audio,Audiophile 24/96},"\ "{Digigram,VX442},"\ - "{Lionstracs,Mediastation}," + "{Lionstracs,Mediastation},"\ + "{Edirol,DA2496}," #define ICE1712_SUBDEVICE_DELTA1010 0x121430d6 #define ICE1712_SUBDEVICE_DELTA1010E 0xff1430d6 @@ -47,6 +48,7 @@ #define ICE1712_SUBDEVICE_DELTA1010LT 0x12143bd6 #define ICE1712_SUBDEVICE_VX442 0x12143cd6 #define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100 +#define ICE1712_SUBDEVICE_EDIROLDA2496 0xce164010 /* entry point */ extern struct snd_ice1712_card_info snd_ice1712_delta_cards[]; -- cgit v1.2.3-59-g8ed1b From 21dc330157454046dd7c494961277d76e1c957fe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Aug 2010 00:13:46 -0700 Subject: net: Rename skb_has_frags to skb_has_frag_list SKBs can be "fragmented" in two ways, via a page array (called skb_shinfo(skb)->frags[]) and via a list of SKBs (called skb_shinfo(skb)->frag_list). Since skb_has_frags() tests the latter, it's name is confusing since it sounds more like it's testing the former. Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 +- include/linux/skbuff.h | 4 ++-- net/core/dev.c | 4 ++-- net/core/skbuff.c | 18 +++++++++--------- net/ipv4/ip_fragment.c | 2 +- net/ipv4/ip_output.c | 2 +- net/ipv6/ip6_output.c | 2 +- net/ipv6/netfilter/nf_conntrack_reasm.c | 2 +- net/ipv6/reassembly.c | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 46c36ffe20ee..ce2de8b64083 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2191,7 +2191,7 @@ static inline int net_gso_ok(int features, int gso_type) static inline int skb_gso_ok(struct sk_buff *skb, int features) { return net_gso_ok(features, skb_shinfo(skb)->gso_type) && - (!skb_has_frags(skb) || (features & NETIF_F_FRAGLIST)); + (!skb_has_frag_list(skb) || (features & NETIF_F_FRAGLIST)); } static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f067c95cf18a..f900ffcd847e 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1120,7 +1120,7 @@ extern void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, int size); #define SKB_PAGE_ASSERT(skb) BUG_ON(skb_shinfo(skb)->nr_frags) -#define SKB_FRAG_ASSERT(skb) BUG_ON(skb_has_frags(skb)) +#define SKB_FRAG_ASSERT(skb) BUG_ON(skb_has_frag_list(skb)) #define SKB_LINEAR_ASSERT(skb) BUG_ON(skb_is_nonlinear(skb)) #ifdef NET_SKBUFF_DATA_USES_OFFSET @@ -1784,7 +1784,7 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) skb = skb->prev) -static inline bool skb_has_frags(const struct sk_buff *skb) +static inline bool skb_has_frag_list(const struct sk_buff *skb) { return skb_shinfo(skb)->frag_list != NULL; } diff --git a/net/core/dev.c b/net/core/dev.c index d569f88bcf80..859e30ff044a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1930,7 +1930,7 @@ static inline int skb_needs_linearize(struct sk_buff *skb, struct net_device *dev) { return skb_is_nonlinear(skb) && - ((skb_has_frags(skb) && !(dev->features & NETIF_F_FRAGLIST)) || + ((skb_has_frag_list(skb) && !(dev->features & NETIF_F_FRAGLIST)) || (skb_shinfo(skb)->nr_frags && (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)))); } @@ -3090,7 +3090,7 @@ enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) if (!(skb->dev->features & NETIF_F_GRO) || netpoll_rx_on(skb)) goto normal; - if (skb_is_gso(skb) || skb_has_frags(skb)) + if (skb_is_gso(skb) || skb_has_frag_list(skb)) goto normal; rcu_read_lock(); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 99ef721f773d..e2535fb4985d 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -340,7 +340,7 @@ static void skb_release_data(struct sk_buff *skb) put_page(skb_shinfo(skb)->frags[i].page); } - if (skb_has_frags(skb)) + if (skb_has_frag_list(skb)) skb_drop_fraglist(skb); kfree(skb->head); @@ -759,7 +759,7 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask) skb_shinfo(n)->nr_frags = i; } - if (skb_has_frags(skb)) { + if (skb_has_frag_list(skb)) { skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list; skb_clone_fraglist(n); } @@ -822,7 +822,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) get_page(skb_shinfo(skb)->frags[i].page); - if (skb_has_frags(skb)) + if (skb_has_frag_list(skb)) skb_clone_fraglist(skb); skb_release_data(skb); @@ -1099,7 +1099,7 @@ drop_pages: for (; i < nfrags; i++) put_page(skb_shinfo(skb)->frags[i].page); - if (skb_has_frags(skb)) + if (skb_has_frag_list(skb)) skb_drop_fraglist(skb); goto done; } @@ -1194,7 +1194,7 @@ unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta) /* Optimization: no fragments, no reasons to preestimate * size of pulled pages. Superb. */ - if (!skb_has_frags(skb)) + if (!skb_has_frag_list(skb)) goto pull_pages; /* Estimate size of pulled pages. */ @@ -2323,7 +2323,7 @@ next_skb: st->frag_data = NULL; } - if (st->root_skb == st->cur_skb && skb_has_frags(st->root_skb)) { + if (st->root_skb == st->cur_skb && skb_has_frag_list(st->root_skb)) { st->cur_skb = skb_shinfo(st->root_skb)->frag_list; st->frag_idx = 0; goto next_skb; @@ -2889,7 +2889,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) return -ENOMEM; /* Easy case. Most of packets will go this way. */ - if (!skb_has_frags(skb)) { + if (!skb_has_frag_list(skb)) { /* A little of trouble, not enough of space for trailer. * This should not happen, when stack is tuned to generate * good frames. OK, on miss we reallocate and reserve even more @@ -2924,7 +2924,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) if (skb1->next == NULL && tailbits) { if (skb_shinfo(skb1)->nr_frags || - skb_has_frags(skb1) || + skb_has_frag_list(skb1) || skb_tailroom(skb1) < tailbits) ntail = tailbits + 128; } @@ -2933,7 +2933,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) skb_cloned(skb1) || ntail || skb_shinfo(skb1)->nr_frags || - skb_has_frags(skb1)) { + skb_has_frag_list(skb1)) { struct sk_buff *skb2; /* Fuck, we are miserable poor guys... */ diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index b7c41654dde5..f4dc879e258e 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -542,7 +542,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, /* If the first fragment is fragmented itself, we split * it to two chunks: the first with data and paged part * and the second, holding only fragments. */ - if (skb_has_frags(head)) { + if (skb_has_frag_list(head)) { struct sk_buff *clone; int i, plen = 0; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index e807492f1777..6d2753c7ffdd 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -487,7 +487,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) * LATER: this step can be merged to real generation of fragments, * we can switch to copy when see the first bad fragment. */ - if (skb_has_frags(skb)) { + if (skb_has_frag_list(skb)) { struct sk_buff *frag; int first_len = skb_pagelen(skb); int truesizes = 0; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d40b330c0ee6..1838927a2243 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -637,7 +637,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) } mtu -= hlen + sizeof(struct frag_hdr); - if (skb_has_frags(skb)) { + if (skb_has_frag_list(skb)) { int first_len = skb_pagelen(skb); int truesizes = 0; diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 13ef5bc05cf5..089c598773c7 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -413,7 +413,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) /* If the first fragment is fragmented itself, we split * it to two chunks: the first with data and paged part * and the second, holding only fragments. */ - if (skb_has_frags(head)) { + if (skb_has_frag_list(head)) { struct sk_buff *clone; int i, plen = 0; diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 545c4141b755..8aea3f3f18d7 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -499,7 +499,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, /* If the first fragment is fragmented itself, we split * it to two chunks: the first with data and paged part * and the second, holding only fragments. */ - if (skb_has_frags(head)) { + if (skb_has_frag_list(head)) { struct sk_buff *clone; int i, plen = 0; -- cgit v1.2.3-59-g8ed1b From 37b47656baa3e4e78d539db2531a75590652327b Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Aug 2010 10:38:40 +0300 Subject: ASoC: Fix tlv320aic3x GPIO initialization aic3x_init does a soft reset first and thus TLV320AIC3x GPIO setup must be done after doing the basic init. Before multi-component the init was done at i2c probe time and GPIO setup at soc probe time. Signed-off-by: Jarkko Nikula Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/tlv320aic3x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 43fd9c171742..0b80e242a66d 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1231,6 +1231,8 @@ static int aic3x_probe(struct snd_soc_codec *codec) codec->hw_write = (hw_write_t) i2c_master_send; codec->control_data = aic3x->control_data; + aic3x_init(codec); + if (aic3x->setup) { /* setup GPIO functions */ aic3x_write(codec, AIC3X_GPIO1_REG, @@ -1239,8 +1241,6 @@ static int aic3x_probe(struct snd_soc_codec *codec) (aic3x->setup->gpio_func[1] & 0xf) << 4); } - aic3x_init(codec); - snd_soc_add_controls(codec, aic3x_snd_controls, ARRAY_SIZE(aic3x_snd_controls)); -- cgit v1.2.3-59-g8ed1b From 4fff7a5ccc00832039ae1c5138f9030079b6604d Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Aug 2010 10:36:41 +0300 Subject: ASoC: omap: rx51: Use gpio_set_value_cansleep for speaker amp control Speaker amplifier is controlled by TWL4030 GPIO which may sleep. Therefore use gpio_set_value_cansleep to get rid of runtime warning that is introduced after the commit 9c4ba94 and to get a stack trace if ever executing this code in atomic context. Signed-off-by: Jarkko Nikula Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/omap/rx51.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index d1d8098923ce..04b5723bf89b 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -146,9 +146,9 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { if (SND_SOC_DAPM_EVENT_ON(event)) - gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 1); + gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 1); else - gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 0); + gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 0); return 0; } -- cgit v1.2.3-59-g8ed1b From a8165e0e6f0511d14132423b4bce2d285e890fc8 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Aug 2010 10:35:05 +0300 Subject: omap: rx51: Remove redefinition of rx51_aic3x_data Redefinition of rx51_aic3x_data got introduced when merging upstread changes for 2.6.36 and ASoC Multi-Component Support. This must go together with multi-component commit f0fba2a. Signed-off-by: Jarkko Nikula Cc: Tony Lindgren Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- arch/arm/mach-omap2/board-rx51-peripherals.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 897d960fe16f..11ce4b24befd 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -710,10 +710,6 @@ static struct twl4030_platform_data rx51_twldata __initdata = { .vio = &rx51_vio, }; -static struct aic3x_pdata rx51_aic3x_data __initdata = { - .gpio_reset = 60, -}; - static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata = { .id = TPA6130A2, .power_gpio = 98, -- cgit v1.2.3-59-g8ed1b From 7d83d2138390d499fccfde5c4975c66503d80704 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 23 Aug 2010 10:54:43 +0100 Subject: ASoC: Log WM8994 separate ADC LRCLKs every time we configure This makes it that little bit easier to spot the diagnostics in the logs. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8994.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 76a066e908ed..e03072cade7b 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3316,20 +3316,24 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, bclk_reg = WM8994_AIF1_BCLK; rate_reg = WM8994_AIF1_RATE; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - wm8994->lrclk_shared[0]) + wm8994->lrclk_shared[0]) { lrclk_reg = WM8994_AIF1DAC_LRCLK; - else + } else { lrclk_reg = WM8994_AIF1ADC_LRCLK; + dev_dbg(codec->dev, "AIF1 using split LRCLK\n"); + } break; case 2: aif1_reg = WM8994_AIF2_CONTROL_1; bclk_reg = WM8994_AIF2_BCLK; rate_reg = WM8994_AIF2_RATE; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - wm8994->lrclk_shared[1]) + wm8994->lrclk_shared[1]) { lrclk_reg = WM8994_AIF2DAC_LRCLK; - else + } else { lrclk_reg = WM8994_AIF2ADC_LRCLK; + dev_dbg(codec->dev, "AIF2 using split LRCLK\n"); + } break; default: return -EINVAL; -- cgit v1.2.3-59-g8ed1b From 49d7ad9d8a5546d96061f08de1fb30241140849c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 20 Aug 2010 17:24:51 +0100 Subject: ASoC: Add build infrastructure for WL1273 The Makefile and Kconfig updates for WL1273 appear to have been mising from the patch posted, add them. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/Kconfig | 4 ++++ sound/soc/codecs/Makefile | 2 ++ 2 files changed, 6 insertions(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index a3cfc184ee50..155c1276d1a1 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -41,6 +41,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TWL6040 if TWL4030_CORE select SND_SOC_UDA134X select SND_SOC_UDA1380 if I2C + select SND_SOC_WL1273 if WL1273_CORE select SND_SOC_WM2000 if I2C select SND_SOC_WM8350 if MFD_WM8350 select SND_SOC_WM8400 if MFD_WM8400 @@ -193,6 +194,9 @@ config SND_SOC_UDA134X config SND_SOC_UDA1380 tristate +config SND_SOC_WL1273 + tristate + config SND_SOC_WM8350 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index b9c43582c5bd..10d468e4a1ed 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -27,6 +27,7 @@ snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o +snd-soc-wl1273-objs := wl1273.o snd-soc-wm8350-objs := wm8350.o snd-soc-wm8400-objs := wm8400.o snd-soc-wm8510-objs := wm8510.o @@ -98,6 +99,7 @@ obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o +obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o -- cgit v1.2.3-59-g8ed1b From a2a0086d4b812dd5d44af84c43d6c6ba089e8210 Mon Sep 17 00:00:00 2001 From: Ian Lartey Date: Fri, 20 Aug 2010 17:18:43 +0100 Subject: ASoC: pxa2xx-i2s is the proper name of the I2S DAI, not pxa-i2s. Signed-off-by: Ian Lartey Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/pxa/imote2.c | 2 +- sound/soc/pxa/magician.c | 2 +- sound/soc/pxa/poodle.c | 2 +- sound/soc/pxa/z2.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c index 03765fc5ac74..154fc6f23438 100644 --- a/sound/soc/pxa/imote2.c +++ b/sound/soc/pxa/imote2.c @@ -63,7 +63,7 @@ static struct snd_soc_ops imote2_asoc_ops = { static struct snd_soc_dai_link imote2_dai = { .name = "WM8940", .stream_name = "WM8940", - .cpu_dai_name = "pxa-i2s", + .cpu_dai_name = "pxa2xx-i2s", .codec_dai_name = "wm8940-hifi", .platform_name = "pxa-pcm-audio", .codec_name = "wm8940-codec.0-0034", diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index 608bc3dd835f..b8207ced4072 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -437,7 +437,7 @@ static struct snd_soc_dai_link magician_dai[] = { { .name = "uda1380", .stream_name = "UDA1380 Capture", - .cpu_dai_name = "pxa-i2s", + .cpu_dai_name = "pxa2xx-i2s", .codec_dai_name = "uda1380-hifi-capture", .platform_name = "pxa-pcm-audio", .codec_name = "uda1380-codec.0-0018", diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index fa752f6ec37d..af84ee9c5e11 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -266,7 +266,7 @@ static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd) static struct snd_soc_dai_link poodle_dai = { .name = "WM8731", .stream_name = "WM8731", - .cpu_dai_name = "pxa-i2s", + .cpu_dai_name = "pxa2xx-i2s", .codec_dai_name = "wm8731-hifi", .platform_name = "pxa-pcm-audio", .codec_name = "wm8731-codec.0-001a", diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index 704f74b56ab6..4cc841b44182 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c @@ -189,7 +189,7 @@ static struct snd_soc_ops z2_ops = { static struct snd_soc_dai_link z2_dai = { .name = "wm8750", .stream_name = "WM8750", - .cpu_dai_name = "pxa-i2s", + .cpu_dai_name = "pxa2xx-i2s", .codec_dai_name = "wm8750-hifi", .platform_name = "pxa-pcm-audio", .codec_name = "wm8750-codec.0-001a", -- cgit v1.2.3-59-g8ed1b From 30e2d36885b3c989f58f9f87c27b4afed3683d6f Mon Sep 17 00:00:00 2001 From: Ian Lartey Date: Fri, 20 Aug 2010 17:18:44 +0100 Subject: ASoC: Make codec dai naming for WM8741 consistent Signed-off-by: Ian Lartey Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/wm8741.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 782fe539662b..fdd24da89a1e 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -311,7 +311,7 @@ static struct snd_soc_dai_ops wm8741_dai_ops = { }; static struct snd_soc_dai_driver wm8741_dai = { - .name = "WM8741", + .name = "wm8741", .playback = { .stream_name = "Playback", .channels_min = 2, /* Mono modes not yet supported */ -- cgit v1.2.3-59-g8ed1b From 72fba57931c703ad71849b2521226c9bcb7d6688 Mon Sep 17 00:00:00 2001 From: Ian Lartey Date: Fri, 20 Aug 2010 17:18:45 +0100 Subject: ASoC: Enable autoloading of pxa2xx CPU I2S driver with module alias Signed-off-by: Ian Lartey Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-i2s.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index d1b2ca69fd30..11be5952a506 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -398,3 +398,4 @@ module_exit(pxa2xx_i2s_exit); MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); MODULE_DESCRIPTION("pxa2xx I2S SoC Interface"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:pxa2xx-i2s"); -- cgit v1.2.3-59-g8ed1b From 72a46344867111c3e019b169ddfa9e1a1f55c759 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Fri, 20 Aug 2010 19:21:11 +0400 Subject: HID: add support for two Waltop tablets Add support for Waltop Slim Tablet 5.8 inch and Media Tablet 10.6 inch. These (and other Waltop) tablets are usually sold by different companies (such as Genius and Trust) and with different names, but with the same USB vendor/product IDs. Slim Tablet 5.8 inch is known to also be sold as Genius G-Pen F350 and Trust Widescreen Mini Tablet (item no 16485). Media Tablet 10.6 inch is known to also be sold as Genius G-Pen M609 and M609X. Of these only the latter is known to be supported. Signed-off-by: Nikolai Kondrashov Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 6 + drivers/hid/Makefile | 1 + drivers/hid/hid-core.c | 2 + drivers/hid/hid-ids.h | 4 + drivers/hid/hid-waltop.c | 558 ++++++++++++++++++++++++++++++++++++++++ drivers/hid/usbhid/hid-quirks.c | 1 + 6 files changed, 572 insertions(+) create mode 100644 drivers/hid/hid-waltop.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 34402bb5f6a0..4cae11e1ceb4 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -182,6 +182,12 @@ config HID_UCLOGIC ---help--- Support for UC-Logic tablets. +config HID_WALTOP + tristate "Waltop" + depends on USB_HID + ---help--- + Support for Waltop tablets. + config HID_GYRATION tristate "Gyration" depends on USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 8c4a5107df77..c46c7a158b1f 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o obj-$(CONFIG_HID_WACOM) += hid-wacom.o +obj-$(CONFIG_HID_WALTOP) += hid-waltop.o obj-$(CONFIG_USB_HID) += usbhid/ obj-$(CONFIG_USB_MOUSE) += usbhid/ diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7eb3b163406c..7bd5365bcc90 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1388,6 +1388,8 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b887e73da68a..5be629345cd8 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -519,6 +519,10 @@ #define USB_VENDOR_ID_WACOM 0x056a #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 +#define USB_VENDOR_ID_WALTOP 0x172f +#define USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH 0x0032 +#define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH 0x0501 + #define USB_VENDOR_ID_WISEGROUP 0x0925 #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 diff --git a/drivers/hid/hid-waltop.c b/drivers/hid/hid-waltop.c new file mode 100644 index 000000000000..81cb4edb6b6b --- /dev/null +++ b/drivers/hid/hid-waltop.c @@ -0,0 +1,558 @@ +/* + * HID driver for Waltop devices not fully compliant with HID standard + * + * Copyright (c) 2010 Nikolai Kondrashov + */ + +/* + * 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. + */ + +#include +#include +#include + +#include "hid-ids.h" + +/* + * Original Slim Tablet 5.8 inch report descriptor. + * + * All the reports except the report with ID 16 (the stylus) are unused, + * possibly because the tablet is not configured to, or because they were + * just copied from a more capable model. The purpose of features described + * for report ID 2 is unknown. + * + * The stylus buttons are described as three bit fields, whereas actually + * it's an "array", i.e. they're reported as button numbers (1, 2 and 3). + * The "eraser" field is not used. There is also a "push" without a "pop" in + * the stylus description. + * + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (Mouse), ; Mouse (02h, application collection) + * Collection (Application), + * Report ID (1), + * Usage (Pointer), ; Pointer (01h, physical collection) + * Collection (Physical), + * Usage Page (Button), ; Button (09h) + * Usage Minimum (01h), + * Usage Maximum (05h), + * Logical Minimum (0), + * Logical Maximum (1), + * Report Size (1), + * Report Count (5), + * Input (Variable), + * Report Size (3), + * Report Count (1), + * Input (Constant, Variable), + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (X), ; X (30h, dynamic value) + * Usage (Y), ; Y (31h, dynamic value) + * Usage (Wheel), ; Wheel (38h, dynamic value) + * Logical Minimum (-127), + * Logical Maximum (127), + * Report Size (8), + * Report Count (3), + * Input (Variable, Relative), + * End Collection, + * End Collection, + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Pen), ; Pen (02h, application collection) + * Collection (Application), + * Report ID (2), + * Usage (Stylus), ; Stylus (20h, logical collection) + * Collection (Physical), + * Usage (00h), + * Logical Minimum (0), + * Logical Maximum (255), + * Report Size (8), + * Report Count (7), + * Input (Variable), + * Usage (Azimuth), ; Azimuth (3Fh, dynamic value) + * Usage (Altitude), ; Altitude (40h, dynamic value) + * Logical Minimum (0), + * Logical Maximum (255), + * Report Size (8), + * Report Count (2), + * Feature (Variable), + * End Collection, + * Report ID (5), + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Stylus), ; Stylus (20h, logical collection) + * Collection (Physical), + * Usage (00h), + * Logical Minimum (0), + * Logical Maximum (255), + * Report Size (8), + * Report Count (7), + * Input (Variable), + * End Collection, + * Report ID (10), + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Stylus), ; Stylus (20h, logical collection) + * Collection (Physical), + * Usage (00h), + * Logical Minimum (0), + * Logical Maximum (255), + * Report Size (8), + * Report Count (3), + * Input (Variable), + * End Collection, + * Report ID (16), + * Usage (Stylus), ; Stylus (20h, logical collection) + * Collection (Physical), + * Usage (Tip Switch), ; Tip switch (42h, momentary control) + * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) + * Usage (Invert), ; Invert (3Ch, momentary control) + * Usage (Eraser), ; Eraser (45h, momentary control) + * Usage (In Range), ; In range (32h, momentary control) + * Logical Minimum (0), + * Logical Maximum (1), + * Report Size (1), + * Report Count (5), + * Input (Variable), + * Report Count (3), + * Input (Constant, Variable), + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (X), ; X (30h, dynamic value) + * Report Size (16), + * Report Count (1), + * Push, + * Unit Exponent (13), + * Unit (Inch^3), + * Logical Minimum (0), + * Logical Maximum (10000), + * Physical Minimum (0), + * Physical Maximum (10000), + * Input (Variable), + * Usage (Y), ; Y (31h, dynamic value) + * Logical Maximum (6000), + * Physical Maximum (6000), + * Input (Variable), + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) + * Logical Minimum (0), + * Logical Maximum (1023), + * Physical Minimum (0), + * Physical Maximum (1023), + * Input (Variable), + * End Collection, + * End Collection + */ + +/* Size of the original report descriptor of Slim Tablet 5.8 inch */ +#define SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE 222 + +/* + * Fixed Slim Tablet 5.8 inch descriptor. + * + * All the reports except the stylus report (ID 16) were removed as unused. + * The stylus buttons description was fixed. + */ +static __u8 slim_tablet_5_8_inch_rdesc_fixed[] = { + 0x05, 0x0D, /* Usage Page (Digitizer), */ + 0x09, 0x02, /* Usage (Pen), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x10, /* Report ID (16), */ + 0x09, 0x20, /* Usage (Stylus), */ + 0xA0, /* Collection (Physical), */ + 0x09, 0x42, /* Usage (Tip Switch), */ + 0x09, 0x44, /* Usage (Barrel Switch), */ + 0x09, 0x46, /* Usage (Tablet Pick), */ + 0x15, 0x01, /* Logical Minimum (1), */ + 0x25, 0x03, /* Logical Maximum (3), */ + 0x75, 0x04, /* Report Size (4), */ + 0x95, 0x01, /* Report Count (1), */ + 0x80, /* Input, */ + 0x09, 0x32, /* Usage (In Range), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x01, /* Report Count (1), */ + 0x14, /* Logical Minimum (0), */ + 0xA4, /* Push, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x65, 0x13, /* Unit (Inch), */ + 0x55, 0xFD, /* Unit Exponent (-3), */ + 0x34, /* Physical Minimum (0), */ + 0x09, 0x30, /* Usage (X), */ + 0x46, 0x88, 0x13, /* Physical Maximum (5000), */ + 0x26, 0x10, 0x27, /* Logical Maximum (10000), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x31, /* Usage (Y), */ + 0x46, 0xB8, 0x0B, /* Physical Maximum (3000), */ + 0x26, 0x70, 0x17, /* Logical Maximum (6000), */ + 0x81, 0x02, /* Input (Variable), */ + 0xB4, /* Pop, */ + 0x09, 0x30, /* Usage (Tip Pressure), */ + 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ + 0x81, 0x02, /* Input (Variable), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; + +/* + * Original Media Tablet 10.6 inch report descriptor. + * + * There are at least two versions of this model in the wild. They are + * represented by Genius G-Pen M609 (older version) and Genius G-Pen M609X + * (newer version). + * + * Both versions have the usual pen with two barrel buttons and two + * identical wheels with center buttons in the top corners of the tablet + * base. They also have buttons on the top, between the wheels, for + * selecting the wheels' functions and wide/standard mode. In the wide mode + * the whole working surface is sensed, in the standard mode a narrower area + * is sensed, but the logical report extents remain the same. These modes + * correspond roughly to 16:9 and 4:3 aspect ratios respectively. + * + * The older version has three wheel function buttons ("scroll", "zoom" and + * "volume") and two separate buttons for wide and standard mode. The newer + * version has four wheel function buttons (plus "brush") and only one + * button is used for selecting wide/standard mode. So, the total number of + * buttons remains the same, but one of the mode buttons is repurposed as a + * wheels' function button in the newer version. + * + * The wheel functions are: + * scroll - the wheels act as scroll wheels, the center buttons do nothing. + * zoom - the wheels zoom in/out, the buttons supposedly reset to 100%. + * volume - the wheels control the sound volume, the buttons mute. + * brush - the wheels are supposed to control brush width in a graphics + * editor, the buttons do nothing. + * + * Below is the newer version's report descriptor. It may very well be that + * the older version's descriptor is different and thus it won't be + * supported. + * + * The mouse report (ID 1) only uses the wheel field for reporting the tablet + * wheels' scroll mode. The keyboard report (ID 13) is used to report the + * wheels' zoom and brush control functions as key presses. The report ID 12 + * is used to report the wheels' volume control functions. The stylus report + * (ID 16) has the same problems as the Slim Tablet 5.8 inch report has. + * + * The rest of the reports are unused, at least in the default configuration. + * The purpose of the features is unknown. + * + * Usage Page (Desktop), + * Usage (Mouse), + * Collection (Application), + * Report ID (1), + * Usage (Pointer), + * Collection (Physical), + * Usage Page (Button), + * Usage Minimum (01h), + * Usage Maximum (05h), + * Logical Minimum (0), + * Logical Maximum (1), + * Report Size (1), + * Report Count (5), + * Input (Variable), + * Report Size (3), + * Report Count (1), + * Input (Constant, Variable), + * Usage Page (Desktop), + * Usage (X), + * Usage (Y), + * Usage (Wheel), + * Logical Minimum (-127), + * Logical Maximum (127), + * Report Size (8), + * Report Count (3), + * Input (Variable, Relative), + * End Collection, + * End Collection, + * Usage Page (Digitizer), + * Usage (Pen), + * Collection (Application), + * Report ID (2), + * Usage (Stylus), + * Collection (Physical), + * Usage (00h), + * Logical Minimum (0), + * Logical Maximum (255), + * Report Size (8), + * Report Count (7), + * Input (Variable), + * Usage (Azimuth), + * Usage (Altitude), + * Logical Minimum (0), + * Logical Maximum (255), + * Report Size (8), + * Report Count (2), + * Feature (Variable), + * End Collection, + * Report ID (5), + * Usage Page (Digitizer), + * Usage (Stylus), + * Collection (Physical), + * Usage (00h), + * Logical Minimum (0), + * Logical Maximum (255), + * Report Size (8), + * Report Count (7), + * Input (Variable), + * End Collection, + * Report ID (10), + * Usage Page (Digitizer), + * Usage (Stylus), + * Collection (Physical), + * Usage (00h), + * Logical Minimum (0), + * Logical Maximum (255), + * Report Size (8), + * Report Count (7), + * Input (Variable), + * End Collection, + * Report ID (16), + * Usage (Stylus), + * Collection (Physical), + * Usage (Tip Switch), + * Usage (Barrel Switch), + * Usage (Invert), + * Usage (Eraser), + * Usage (In Range), + * Logical Minimum (0), + * Logical Maximum (1), + * Report Size (1), + * Report Count (5), + * Input (Variable), + * Report Count (3), + * Input (Constant, Variable), + * Usage Page (Desktop), + * Usage (X), + * Report Size (16), + * Report Count (1), + * Push, + * Unit Exponent (13), + * Unit (Inch^3), + * Logical Minimum (0), + * Logical Maximum (18000), + * Physical Minimum (0), + * Physical Maximum (18000), + * Input (Variable), + * Usage (Y), + * Logical Maximum (11000), + * Physical Maximum (11000), + * Input (Variable), + * Usage Page (Digitizer), + * Usage (Tip Pressure), + * Logical Minimum (0), + * Logical Maximum (1023), + * Physical Minimum (0), + * Physical Maximum (1023), + * Input (Variable), + * End Collection, + * End Collection, + * Usage Page (Desktop), + * Usage (Keyboard), + * Collection (Application), + * Report ID (13), + * Usage Page (Keyboard), + * Usage Minimum (KB Leftcontrol), + * Usage Maximum (KB Right GUI), + * Logical Minimum (0), + * Logical Maximum (1), + * Report Size (1), + * Report Count (8), + * Input (Variable), + * Report Size (8), + * Report Count (1), + * Input (Constant), + * Usage Page (Keyboard), + * Usage Minimum (None), + * Usage Maximum (KB Application), + * Logical Minimum (0), + * Logical Maximum (101), + * Report Size (8), + * Report Count (5), + * Input, + * End Collection, + * Usage Page (Consumer), + * Usage (Consumer Control), + * Collection (Application), + * Report ID (12), + * Usage (Volume Inc), + * Usage (Volume Dec), + * Usage (Mute), + * Logical Minimum (0), + * Logical Maximum (1), + * Report Size (1), + * Report Count (3), + * Input (Variable, Relative), + * Report Size (5), + * Report Count (1), + * Input (Constant, Variable, Relative), + * End Collection + */ + +/* Size of the original report descriptor of Media Tablet 10.6 inch */ +#define MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE 300 + +/* + * Fixed Media Tablet 10.6 inch descriptor. + * + * The descriptions of reports unused in the default configuration are + * removed. The stylus report (ID 16) is fixed similarly to Slim Tablet 5.8 + * inch. The unused mouse report (ID 1) fields are replaced with constant + * padding. + * + * The keyboard report (ID 13) is hacked to instead have an "array" field + * reporting consumer page controls, and all the unused bits are masked out + * with constant padding. The "brush" wheels' function is represented as "Scan + * Previous/Next Track" controls due to the lack of brush controls in the + * usage tables specification. + */ +static __u8 media_tablet_10_6_inch_rdesc_fixed[] = { + 0x05, 0x0D, /* Usage Page (Digitizer), */ + 0x09, 0x02, /* Usage (Pen), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x10, /* Report ID (16), */ + 0x09, 0x20, /* Usage (Stylus), */ + 0xA0, /* Collection (Physical), */ + 0x09, 0x42, /* Usage (Tip Switch), */ + 0x09, 0x44, /* Usage (Barrel Switch), */ + 0x09, 0x46, /* Usage (Tablet Pick), */ + 0x15, 0x01, /* Logical Minimum (1), */ + 0x25, 0x03, /* Logical Maximum (3), */ + 0x75, 0x04, /* Report Size (4), */ + 0x95, 0x01, /* Report Count (1), */ + 0x80, /* Input, */ + 0x75, 0x01, /* Report Size (1), */ + 0x09, 0x32, /* Usage (In Range), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x01, /* Report Count (1), */ + 0x14, /* Logical Minimum (0), */ + 0xA4, /* Push, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x65, 0x13, /* Unit (Inch), */ + 0x55, 0xFD, /* Unit Exponent (-3), */ + 0x34, /* Physical Minimum (0), */ + 0x09, 0x30, /* Usage (X), */ + 0x46, 0x28, 0x23, /* Physical Maximum (9000), */ + 0x26, 0x50, 0x46, /* Logical Maximum (18000), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x31, /* Usage (Y), */ + 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */ + 0x26, 0xF8, 0x2A, /* Logical Maximum (11000), */ + 0x81, 0x02, /* Input (Variable), */ + 0xB4, /* Pop, */ + 0x09, 0x30, /* Usage (Tip Pressure), */ + 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ + 0x81, 0x02, /* Input (Variable), */ + 0xC0, /* End Collection, */ + 0xC0, /* End Collection, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x02, /* Usage (Mouse), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x01, /* Report ID (1), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xA0, /* Collection (Physical), */ + 0x95, 0x01, /* Report Count (1), */ + 0x75, 0x18, /* Report Size (24), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x38, /* Usage (Wheel), */ + 0x15, 0xFF, /* Logical Minimum (-1), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x75, 0x08, /* Report Size (8), */ + 0x81, 0x06, /* Input (Variable, Relative), */ + 0x75, 0x18, /* Report Size (24), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0xC0, /* End Collection, */ + 0xC0, /* End Collection, */ + 0x05, 0x0C, /* Usage Page (Consumer), */ + 0x09, 0x01, /* Usage (Consumer Control), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x0D, /* Report ID (13), */ + 0x95, 0x01, /* Report Count (1), */ + 0x75, 0x10, /* Report Size (16), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */ + 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ + 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ + 0x09, 0xB6, /* Usage (Scan Previous Track), */ + 0x09, 0xB5, /* Usage (Scan Next Track), */ + 0x15, 0x2C, /* Logical Minimum (44), */ + 0x25, 0x30, /* Logical Maximum (48), */ + 0x75, 0x08, /* Report Size (8), */ + 0x80, /* Input, */ + 0x75, 0x20, /* Report Size (32), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0xC0, /* End Collection, */ + 0x09, 0x01, /* Usage (Consumer Control), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x0C, /* Report ID (12), */ + 0x75, 0x01, /* Report Size (1), */ + 0x09, 0xE9, /* Usage (Volume Inc), */ + 0x09, 0xEA, /* Usage (Volume Dec), */ + 0x09, 0xE2, /* Usage (Mute), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x06, /* Input (Variable, Relative), */ + 0x95, 0x35, /* Report Count (53), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0xC0 /* End Collection */ +}; + +static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + switch (hdev->product) { + case USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH: + if (*rsize == SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE) { + rdesc = slim_tablet_5_8_inch_rdesc_fixed; + *rsize = sizeof(slim_tablet_5_8_inch_rdesc_fixed); + } + break; + case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH: + if (*rsize == MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE) { + rdesc = media_tablet_10_6_inch_rdesc_fixed; + *rsize = sizeof(media_tablet_10_6_inch_rdesc_fixed); + } + break; + } + return rdesc; +} + +static const struct hid_device_id waltop_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, + USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, + USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, + { } +}; +MODULE_DEVICE_TABLE(hid, waltop_devices); + +static struct hid_driver waltop_driver = { + .name = "waltop", + .id_table = waltop_devices, + .report_fixup = waltop_report_fixup, +}; + +static int __init waltop_init(void) +{ + return hid_register_driver(&waltop_driver); +} + +static void __exit waltop_exit(void) +{ + hid_unregister_driver(&waltop_driver); +} + +module_init(waltop_init); +module_exit(waltop_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 162aa4b40205..1b45fb747cf3 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -70,6 +70,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, -- cgit v1.2.3-59-g8ed1b From bd9033ebc15acd05c8df92b5fc7ecc9171d1087e Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Mon, 23 Aug 2010 15:09:00 +0400 Subject: HID: uclogic: fix coding style Fix minor coding style violations in the hid-uclogic driver. Signed-off-by: Nikolai Kondrashov Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c index 107aa9fb07f2..fe36303dfd95 100644 --- a/drivers/hid/hid-uclogic.c +++ b/drivers/hid/hid-uclogic.c @@ -343,26 +343,23 @@ static __u8 wp8060u_rdesc_fixed[] = { }; static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) + unsigned int *rsize) { switch (hdev->product) { case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U: - if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) - { + if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { rdesc = wp4030u_rdesc_fixed; *rsize = sizeof(wp4030u_rdesc_fixed); } break; case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U: - if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) - { + if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { rdesc = wp5540u_rdesc_fixed; *rsize = sizeof(wp5540u_rdesc_fixed); } break; case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U: - if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) - { + if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { rdesc = wp8060u_rdesc_fixed; *rsize = sizeof(wp8060u_rdesc_fixed); } -- cgit v1.2.3-59-g8ed1b From 41fa92302be7fa37c5c38e17e2097d3e5e9da13a Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Mon, 23 Aug 2010 15:09:01 +0400 Subject: HID: uclogic: add proper support for PF1209 This removes extra event device and fixes reported button codes of UC-Logic Tablet PF1209. This tablet is also sold as Genius PenSketch 12x9 (or 9x12) and possibly under other names. Signed-off-by: Nikolai Kondrashov Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-uclogic.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7eb3b163406c..7f26ffebfaf0 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1383,6 +1383,7 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c index fe36303dfd95..05fdc85a76e5 100644 --- a/drivers/hid/hid-uclogic.c +++ b/drivers/hid/hid-uclogic.c @@ -342,10 +342,230 @@ static __u8 wp8060u_rdesc_fixed[] = { 0xC0 /* End Collection */ }; +/* + * Original PF1209 report descriptor. + * + * The descriptor is similar to WPXXXXU descriptors, with an addition of a + * feature report (ID 4) of unknown purpose. + * + * Although the advertised resolution is 4000 LPI the unused report ID + * (taken from WPXXXXU, it seems) states 2000 LPI, but it is probably + * incorrect and is a result of blind copying without understanding. Anyway + * the real logical extents are always scaled to 0..32767, which IMHO spoils + * the precision. + * + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Pen), ; Pen (02h, application collection) + * Collection (Application), + * Report ID (7), + * Usage (Stylus), ; Stylus (20h, logical collection) + * Collection (Physical), + * Usage (Tip Switch), ; Tip switch (42h, momentary control) + * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) + * Usage (Eraser), ; Eraser (45h, momentary control) + * Logical Minimum (0), + * Logical Maximum (1), + * Report Size (1), + * Report Count (3), + * Input (Variable), + * Report Count (3), + * Input (Constant, Variable), + * Usage (In Range), ; In range (32h, momentary control) + * Report Count (1), + * Input (Variable), + * Report Count (1), + * Input (Constant, Variable), + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (X), ; X (30h, dynamic value) + * Report Size (16), + * Report Count (1), + * Push, + * Unit Exponent (13), + * Unit (Inch^3), + * Physical Minimum (0), + * Physical Maximum (12000), + * Logical Maximum (24000), + * Input (Variable), + * Usage (Y), ; Y (31h, dynamic value) + * Physical Maximum (9000), + * Logical Maximum (18000), + * Input (Variable), + * Pop, + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) + * Logical Maximum (1023), + * Input (Variable), + * Report Size (16), + * End Collection, + * End Collection, + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (Mouse), ; Mouse (02h, application collection) + * Collection (Application), + * Report ID (8), + * Usage (Pointer), ; Pointer (01h, physical collection) + * Collection (Physical), + * Usage Page (Button), ; Button (09h) + * Usage Minimum (01h), + * Usage Maximum (03h), + * Logical Minimum (0), + * Logical Maximum (1), + * Report Count (3), + * Report Size (1), + * Input (Variable), + * Report Count (5), + * Input (Constant), + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (X), ; X (30h, dynamic value) + * Usage (Y), ; Y (31h, dynamic value) + * Usage (Wheel), ; Wheel (38h, dynamic value) + * Usage (00h), + * Logical Minimum (-127), + * Logical Maximum (127), + * Report Size (8), + * Report Count (4), + * Input (Variable, Relative), + * End Collection, + * End Collection, + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (Mouse), ; Mouse (02h, application collection) + * Collection (Application), + * Report ID (9), + * Usage (Pointer), ; Pointer (01h, physical collection) + * Collection (Physical), + * Usage Page (Button), ; Button (09h) + * Usage Minimum (01h), + * Usage Maximum (03h), + * Logical Minimum (0), + * Logical Maximum (1), + * Report Count (3), + * Report Size (1), + * Input (Variable), + * Report Count (5), + * Input (Constant), + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (X), ; X (30h, dynamic value) + * Usage (Y), ; Y (31h, dynamic value) + * Logical Minimum (0), + * Logical Maximum (32767), + * Physical Minimum (0), + * Physical Maximum (32767), + * Report Count (2), + * Report Size (16), + * Input (Variable), + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) + * Logical Maximum (1023), + * Report Count (1), + * Report Size (16), + * Input (Variable), + * End Collection, + * End Collection, + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (00h), + * Collection (Application), + * Report ID (4), + * Logical Minimum (0), + * Logical Maximum (255), + * Usage (00h), + * Report Size (8), + * Report Count (3), + * Feature (Variable), + * End Collection + */ + +/* Size of the original descriptor of PF1209 tablet */ +#define PF1209_RDESC_ORIG_SIZE 234 + +/* + * Fixed PF1209 report descriptor + * + * The descriptor is fixed similarly to WP5540U and WP8060U, plus the + * feature report is removed, because its purpose is unknown and it is of no + * use to the generic HID driver anyway for now. + */ +static __u8 pf1209_rdesc_fixed[] = { + 0x05, 0x0D, /* Usage Page (Digitizer), */ + 0x09, 0x02, /* Usage (Pen), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x09, /* Report ID (9), */ + 0x09, 0x20, /* Usage (Stylus), */ + 0xA0, /* Collection (Physical), */ + 0x75, 0x01, /* Report Size (1), */ + 0x09, 0x42, /* Usage (Tip Switch), */ + 0x09, 0x44, /* Usage (Barrel Switch), */ + 0x09, 0x46, /* Usage (Tablet Pick), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x05, /* Report Count (5), */ + 0x81, 0x01, /* Input (Constant), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x01, /* Report Count (1), */ + 0x14, /* Logical Minimum (0), */ + 0xA4, /* Push, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x55, 0xFD, /* Unit Exponent (-3), */ + 0x65, 0x13, /* Unit (Inch), */ + 0x34, /* Physical Minimum (0), */ + 0x09, 0x30, /* Usage (X), */ + 0x46, 0xE0, 0x2E, /* Physical Maximum (12000), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x31, /* Usage (Y), */ + 0x46, 0x28, 0x23, /* Physical Maximum (9000), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ + 0x81, 0x02, /* Input (Variable), */ + 0xB4, /* Pop, */ + 0x09, 0x30, /* Usage (Tip Pressure), */ + 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ + 0x81, 0x02, /* Input (Variable), */ + 0xC0, /* End Collection, */ + 0xC0, /* End Collection, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x02, /* Usage (Mouse), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x08, /* Report ID (8), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xA0, /* Collection (Physical), */ + 0x75, 0x01, /* Report Size (1), */ + 0x05, 0x09, /* Usage Page (Button), */ + 0x19, 0x01, /* Usage Minimum (01h), */ + 0x29, 0x03, /* Usage Maximum (03h), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x05, /* Report Count (5), */ + 0x81, 0x01, /* Input (Constant), */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x75, 0x08, /* Report Size (8), */ + 0x09, 0x30, /* Usage (X), */ + 0x09, 0x31, /* Usage (Y), */ + 0x15, 0x81, /* Logical Minimum (-127), */ + 0x25, 0x7F, /* Logical Maximum (127), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x06, /* Input (Variable, Relative), */ + 0x09, 0x38, /* Usage (Wheel), */ + 0x15, 0xFF, /* Logical Minimum (-1), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x06, /* Input (Variable, Relative), */ + 0x81, 0x01, /* Input (Constant), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; + static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { switch (hdev->product) { + case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209: + if (*rsize == PF1209_RDESC_ORIG_SIZE) { + rdesc = pf1209_rdesc_fixed; + *rsize = sizeof(pf1209_rdesc_fixed); + } + break; case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U: if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { rdesc = wp4030u_rdesc_fixed; @@ -370,6 +590,8 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, } static const struct hid_device_id uclogic_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, + USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, -- cgit v1.2.3-59-g8ed1b From d8b187c6b5f4a7ed7f6888b9e2eca3f648648b41 Mon Sep 17 00:00:00 2001 From: Thomas Weber Date: Mon, 23 Aug 2010 11:20:34 +0200 Subject: Fix typo in Kconfig help text Fix the name of the sensor: BMP086 => BMP085 Signed-off-by: Thomas Weber Signed-off-by: Jiri Kosina --- drivers/misc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 0b591b658243..9df5b759a00b 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -385,7 +385,7 @@ config BMP085 depends on I2C && SYSFS help If you say yes here you get support for the Bosch Sensortec - BMP086 digital pressure sensor. + BMP085 digital pressure sensor. To compile this driver as a module, choose M here: the module will be called bmp085. -- cgit v1.2.3-59-g8ed1b From ee86273062cbb310665fe49e1f1937d2cf85b0b9 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Mon, 23 Aug 2010 15:16:00 +0200 Subject: loop: add some basic read-only sysfs attributes Create /sys/block/loopX/loop directory and provide these attributes: - backing_file - autoclear - offset - sizelimit This loop directory is present only if loop device is configured. To be used in util-linux-ng (and possibly elsewhere like udev rules) where code need to get loop attributes from kernel (and not store duplicate info in userspace). Moreover loop ioctls are not even able to provide full backing file info because of buffer limits. Signed-off-by: Milan Broz Signed-off-by: Jens Axboe --- drivers/block/loop.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index f3c636d23718..dc552308668e 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -74,6 +74,7 @@ #include #include #include +#include #include @@ -737,6 +738,103 @@ static inline int is_loop_device(struct file *file) return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR; } +/* loop sysfs attributes */ + +static ssize_t loop_attr_show(struct device *dev, char *page, + ssize_t (*callback)(struct loop_device *, char *)) +{ + struct loop_device *l, *lo = NULL; + + mutex_lock(&loop_devices_mutex); + list_for_each_entry(l, &loop_devices, lo_list) + if (disk_to_dev(l->lo_disk) == dev) { + lo = l; + break; + } + mutex_unlock(&loop_devices_mutex); + + return lo ? callback(lo, page) : -EIO; +} + +#define LOOP_ATTR_RO(_name) \ +static ssize_t loop_attr_##_name##_show(struct loop_device *, char *); \ +static ssize_t loop_attr_do_show_##_name(struct device *d, \ + struct device_attribute *attr, char *b) \ +{ \ + return loop_attr_show(d, b, loop_attr_##_name##_show); \ +} \ +static struct device_attribute loop_attr_##_name = \ + __ATTR(_name, S_IRUGO, loop_attr_do_show_##_name, NULL); + +static ssize_t loop_attr_backing_file_show(struct loop_device *lo, char *buf) +{ + ssize_t ret; + char *p = NULL; + + mutex_lock(&lo->lo_ctl_mutex); + if (lo->lo_backing_file) + p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1); + mutex_unlock(&lo->lo_ctl_mutex); + + if (IS_ERR_OR_NULL(p)) + ret = PTR_ERR(p); + else { + ret = strlen(p); + memmove(buf, p, ret); + buf[ret++] = '\n'; + buf[ret] = 0; + } + + return ret; +} + +static ssize_t loop_attr_offset_show(struct loop_device *lo, char *buf) +{ + return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_offset); +} + +static ssize_t loop_attr_sizelimit_show(struct loop_device *lo, char *buf) +{ + return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_sizelimit); +} + +static ssize_t loop_attr_autoclear_show(struct loop_device *lo, char *buf) +{ + int autoclear = (lo->lo_flags & LO_FLAGS_AUTOCLEAR); + + return sprintf(buf, "%s\n", autoclear ? "1" : "0"); +} + +LOOP_ATTR_RO(backing_file); +LOOP_ATTR_RO(offset); +LOOP_ATTR_RO(sizelimit); +LOOP_ATTR_RO(autoclear); + +static struct attribute *loop_attrs[] = { + &loop_attr_backing_file.attr, + &loop_attr_offset.attr, + &loop_attr_sizelimit.attr, + &loop_attr_autoclear.attr, + NULL, +}; + +static struct attribute_group loop_attribute_group = { + .name = "loop", + .attrs= loop_attrs, +}; + +static int loop_sysfs_init(struct loop_device *lo) +{ + return sysfs_create_group(&disk_to_dev(lo->lo_disk)->kobj, + &loop_attribute_group); +} + +static void loop_sysfs_exit(struct loop_device *lo) +{ + sysfs_remove_group(&disk_to_dev(lo->lo_disk)->kobj, + &loop_attribute_group); +} + static int loop_set_fd(struct loop_device *lo, fmode_t mode, struct block_device *bdev, unsigned int arg) { @@ -836,6 +934,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, set_capacity(lo->lo_disk, size); bd_set_size(bdev, size << 9); + loop_sysfs_init(lo); /* let user-space know about the new size */ kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE); @@ -854,6 +953,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, return 0; out_clr: + loop_sysfs_exit(lo); lo->lo_thread = NULL; lo->lo_device = NULL; lo->lo_backing_file = NULL; @@ -950,6 +1050,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) set_capacity(lo->lo_disk, 0); if (bdev) { bd_set_size(bdev, 0); + loop_sysfs_exit(lo); /* let user-space know about this change */ kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE); } -- cgit v1.2.3-59-g8ed1b From 681b3049dd13bc8ce579de3f017ff73deb658385 Mon Sep 17 00:00:00 2001 From: Stephan Sperber Date: Wed, 14 Jul 2010 11:23:08 +0200 Subject: Kconfig: delete duplicate word Deleted a word which apeared twice. Signed-off-by: Stephan Sperber Signed-off-by: Jiri Kosina --- init/Kconfig | 2 +- usr/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index 24932b9c03e8..2eec20cbe8ef 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -179,7 +179,7 @@ config KERNEL_LZO depends on HAVE_KERNEL_LZO help Its compression ratio is the poorest among the 4. The kernel - size is about about 10% bigger than gzip; however its speed + size is about 10% bigger than gzip; however its speed (both compression and decompression) is the fastest. endchoice diff --git a/usr/Kconfig b/usr/Kconfig index e2721f5a3504..c2c7fe2f717d 100644 --- a/usr/Kconfig +++ b/usr/Kconfig @@ -144,7 +144,7 @@ config INITRAMFS_COMPRESSION_LZO depends on RD_LZO help Its compression ratio is the poorest among the four. The kernel - size is about about 10% bigger than gzip; however its speed + size is about 10% bigger than gzip; however its speed (both compression and decompression) is the fastest. endchoice -- cgit v1.2.3-59-g8ed1b From 67b67e365f07d6dc70f3bb266af3268bac0a4836 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 22 Aug 2010 19:41:36 +0000 Subject: ccid: ccid-2/3 code cosmetics This patch collects cosmetics-only changes to separate these from code changes: * update with regard to CodingStyle and whitespace changes, * documentation: - adding/revising comments, - remove CCID-3 RX socket documentation which is either duplicate or refers to fields that no longer exist, * expand embedded tfrc_tx_info struct inline for consistency, removing indirections via #define. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/ccids/ccid2.c | 4 ++-- net/dccp/ccids/ccid3.c | 30 ++++++++++++++++++------------ net/dccp/ccids/ccid3.h | 19 +++++++------------ 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 9b3ae9922be1..f564211c3885 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -193,8 +193,8 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) hc->tx_ssthresh = hc->tx_cwnd / 2; if (hc->tx_ssthresh < 2) hc->tx_ssthresh = 2; - hc->tx_cwnd = 1; - hc->tx_pipe = 0; + hc->tx_cwnd = 1; + hc->tx_pipe = 0; /* clear state about stuff we sent */ hc->tx_seqt = hc->tx_seqh; diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 95f752986497..a666f3febf2b 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -218,9 +218,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) /* * Determine new allowed sending rate X as per draft rfc3448bis-00, 4.4 + * RTO is 0 if and only if no feedback has been received yet. */ - if (hc->tx_t_rto == 0 || /* no feedback received yet */ - hc->tx_p == 0) { + if (hc->tx_t_rto == 0 || hc->tx_p == 0) { /* halve send rate directly */ hc->tx_x = max(hc->tx_x / 2, @@ -256,7 +256,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) * Set new timeout for the nofeedback timer. * See comments in packet_recv() regarding the value of t_RTO. */ - if (unlikely(hc->tx_t_rto == 0)) /* no feedback yet */ + if (unlikely(hc->tx_t_rto == 0)) /* no feedback received yet */ t_nfb = TFRC_INITIAL_TIMEOUT; else t_nfb = max(hc->tx_t_rto, 2 * hc->tx_t_ipi); @@ -372,7 +372,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) { struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); - struct ccid3_options_received *opt_recv; + struct ccid3_options_received *opt_recv = &hc->tx_options_received; ktime_t now; unsigned long t_nfb; u32 pinv, r_sample; @@ -386,7 +386,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) hc->tx_state != TFRC_SSTATE_NO_FBACK) return; - opt_recv = &hc->tx_options_received; now = ktime_get_real(); /* Estimate RTT from history if ACK number is valid */ @@ -489,11 +488,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, int rc = 0; const struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); - struct ccid3_options_received *opt_recv; + struct ccid3_options_received *opt_recv = &hc->tx_options_received; __be32 opt_val; - opt_recv = &hc->tx_options_received; - if (opt_recv->ccid3or_seqno != dp->dccps_gsr) { opt_recv->ccid3or_seqno = dp->dccps_gsr; opt_recv->ccid3or_loss_event_rate = ~0; @@ -582,6 +579,7 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, u32 __user *optval, int __user *optlen) { const struct ccid3_hc_tx_sock *hc; + struct tfrc_tx_info tfrc; const void *val; /* Listen socks doesn't have a private CCID block */ @@ -591,10 +589,17 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, hc = ccid3_hc_tx_sk(sk); switch (optname) { case DCCP_SOCKOPT_CCID_TX_INFO: - if (len < sizeof(hc->tx_tfrc)) + if (len < sizeof(tfrc)) return -EINVAL; - len = sizeof(hc->tx_tfrc); - val = &hc->tx_tfrc; + tfrc.tfrctx_x = hc->tx_x; + tfrc.tfrctx_x_recv = hc->tx_x_recv; + tfrc.tfrctx_x_calc = hc->tx_x_calc; + tfrc.tfrctx_rtt = hc->tx_rtt; + tfrc.tfrctx_p = hc->tx_p; + tfrc.tfrctx_rto = hc->tx_t_rto; + tfrc.tfrctx_ipi = hc->tx_t_ipi; + len = sizeof(tfrc); + val = &tfrc; break; default: return -ENOPROTOOPT; @@ -749,10 +754,11 @@ static u32 ccid3_first_li(struct sock *sk) x_recv = scaled_div32(hc->rx_bytes_recv, delta); if (x_recv == 0) { /* would also trigger divide-by-zero */ DCCP_WARN("X_recv==0\n"); - if ((x_recv = hc->rx_x_recv) == 0) { + if (hc->rx_x_recv == 0) { DCCP_BUG("stored value of X_recv is zero"); return ~0U; } + x_recv = hc->rx_x_recv; } fval = scaled_div(hc->rx_s, hc->rx_rtt); diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 032635776653..b1864243be07 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -95,14 +95,13 @@ enum ccid3_hc_tx_states { * @tx_options_received: Parsed set of retrieved options */ struct ccid3_hc_tx_sock { - struct tfrc_tx_info tx_tfrc; -#define tx_x tx_tfrc.tfrctx_x -#define tx_x_recv tx_tfrc.tfrctx_x_recv -#define tx_x_calc tx_tfrc.tfrctx_x_calc -#define tx_rtt tx_tfrc.tfrctx_rtt -#define tx_p tx_tfrc.tfrctx_p -#define tx_t_rto tx_tfrc.tfrctx_rto -#define tx_t_ipi tx_tfrc.tfrctx_ipi + u64 tx_x; + u64 tx_x_recv; + u32 tx_x_calc; + u32 tx_rtt; + u32 tx_p; + u32 tx_t_rto; + u32 tx_t_ipi; u16 tx_s; enum ccid3_hc_tx_states tx_state:8; u8 tx_last_win_count; @@ -131,16 +130,12 @@ enum ccid3_hc_rx_states { /** * struct ccid3_hc_rx_sock - CCID3 receiver half-connection socket - * @rx_x_recv: Receiver estimate of send rate (RFC 3448 4.3) - * @rx_rtt: Receiver estimate of rtt (non-standard) - * @rx_p: Current loss event rate (RFC 3448 5.4) * @rx_last_counter: Tracks window counter (RFC 4342, 8.1) * @rx_state: Receiver state, one of %ccid3_hc_rx_states * @rx_bytes_recv: Total sum of DCCP payload bytes * @rx_x_recv: Receiver estimate of send rate (RFC 3448, sec. 4.3) * @rx_rtt: Receiver estimate of RTT * @rx_tstamp_last_feedback: Time at which last feedback was sent - * @rx_tstamp_last_ack: Time at which last feedback was sent * @rx_hist: Packet history (loss detection + RTT sampling) * @rx_li_hist: Loss Interval database * @rx_s: Received packet size in bytes -- cgit v1.2.3-59-g8ed1b From 51c22bb510fefbb1a87c02dbd835383e6e7e3d36 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 22 Aug 2010 19:41:37 +0000 Subject: dccp ccid-3: No more CCID control blocks in LISTEN state The CCIDs are activated as last of the features, at the end of the handshake, were the LISTEN state of the master socket is inherited into the server state of the child socket. Thus, the only states visible to CCIDs now are OPEN/PARTOPEN, and the closing states. This allows to remove tests which were previously necessary to protect against referencing a socket in the listening state (in CCID-3), but which now have become redundant. As a further byproduct of enabling the CCIDs only after the connection has been fully established, several typecast-initialisations of ccid3_hc_{rx,tx}_sock can now be eliminated: * the CCID is loaded, so it is not necessary to test if it is NULL, * if it is possible to load a CCID and leave the private area NULL, then this is a bug, which should crash loudly - and earlier, * the test for state==OPEN || state==PARTOPEN now reduces only to the closing phase (e.g. when the node has received an unexpected Reset). Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: David S. Miller --- net/dccp/ccids/ccid3.c | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index a666f3febf2b..4340672a817c 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -564,29 +564,17 @@ static void ccid3_hc_tx_exit(struct sock *sk) static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) { - struct ccid3_hc_tx_sock *hc; - - /* Listen socks doesn't have a private CCID block */ - if (sk->sk_state == DCCP_LISTEN) - return; - - hc = ccid3_hc_tx_sk(sk); - info->tcpi_rto = hc->tx_t_rto; - info->tcpi_rtt = hc->tx_rtt; + info->tcpi_rto = ccid3_hc_tx_sk(sk)->tx_t_rto; + info->tcpi_rtt = ccid3_hc_tx_sk(sk)->tx_rtt; } static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, u32 __user *optval, int __user *optlen) { - const struct ccid3_hc_tx_sock *hc; + const struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); struct tfrc_tx_info tfrc; const void *val; - /* Listen socks doesn't have a private CCID block */ - if (sk->sk_state == DCCP_LISTEN) - return -EINVAL; - - hc = ccid3_hc_tx_sk(sk); switch (optname) { case DCCP_SOCKOPT_CCID_TX_INFO: if (len < sizeof(tfrc)) @@ -706,14 +694,12 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk, static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) { - const struct ccid3_hc_rx_sock *hc; + const struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); __be32 x_recv, pinv; if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) return 0; - hc = ccid3_hc_rx_sk(sk); - if (dccp_packet_without_ack(skb)) return 0; @@ -876,30 +862,18 @@ static void ccid3_hc_rx_exit(struct sock *sk) static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) { - const struct ccid3_hc_rx_sock *hc; - - /* Listen socks doesn't have a private CCID block */ - if (sk->sk_state == DCCP_LISTEN) - return; - - hc = ccid3_hc_rx_sk(sk); - info->tcpi_ca_state = hc->rx_state; + info->tcpi_ca_state = ccid3_hc_rx_sk(sk)->rx_state; info->tcpi_options |= TCPI_OPT_TIMESTAMPS; - info->tcpi_rcv_rtt = hc->rx_rtt; + info->tcpi_rcv_rtt = ccid3_hc_rx_sk(sk)->rx_rtt; } static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len, u32 __user *optval, int __user *optlen) { - const struct ccid3_hc_rx_sock *hc; + const struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); struct tfrc_rx_info rx_info; const void *val; - /* Listen socks doesn't have a private CCID block */ - if (sk->sk_state == DCCP_LISTEN) - return -EINVAL; - - hc = ccid3_hc_rx_sk(sk); switch (optname) { case DCCP_SOCKOPT_CCID_RX_INFO: if (len < sizeof(rx_info)) -- cgit v1.2.3-59-g8ed1b From 30564e355511b434613aa42375317b5a07fc9f23 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 22 Aug 2010 19:41:38 +0000 Subject: dccp ccid-2: Remove redundant sanity tests This removes the ccid2_hc_tx_check_sanity function: it is redundant. Details: The tx_check_sanity function performs three tests: 1) it checks that the circular TX list is sorted - in ascending order of sequence number (ccid2s_seq) - and time (ccid2s_sent), - in the direction from `tail' (hctx_seqt) to `head' (hctx_seqh); 2) it ensures that the entire list has the length seqbufc * CCID2_SEQBUF_LEN; 3) it ensures that pipe equals the number of packets that were not marked `acked' (ccid2s_acked) between `tail' and `head'. The following argues that each of these tests is redundant, this can be verified by going through the code. (1) is not necessary, since both time and GSS increase from one packet to the next, so that subsequent insertions in tx_packet_sent (which advance the `head' pointer) will be in ascending order of time and sequence number. In (2), the length of the list is always equal to seqbufc times CCID2_SEQBUF_LEN (set to 1024) unless allocation caused an earlier failure, because: * at initialisation (tx_init), there is one chunk of size 1024 and seqbufc=1; * subsequent calls to tx_alloc_seq take place whenever head->next == tail in tx_packet_sent; then a new chunk of size 1024 is inserted between head and tail, and seqbufc is incremented by one. To show that (3) is redundant requires looking at two cases. The `pipe' variable of the TX socket is incremented only in tx_packet_sent, and decremented in tx_packet_recv. When head == tail (TX history empty) then pipe should be 0, which is the case directly after initialisation and after a retransmission timeout has occurred (ccid2_hc_tx_rto_expire). The first case involves parsing Ack Vectors for packets recorded in the live portion of the buffer, between tail and head. For each packet marked by the receiver as received (state 0) or ECN-marked (state 1), pipe is decremented by one, so for all such packets the BUG_ON in tx_check_sanity will not trigger. The second case is the loss detection in the second half of tx_packet_recv, below the comment "Check for NUMDUPACK". The first while-loop here ensures that the sequence number of `seqp' is either above or equal to `high_ack', or otherwise equal to the highest sequence number sent so far (of the entry head->prev, as head points to the next unsent entry). The next while-loop ("while (1)") counts the number of acked packets starting from that position of seqp, going backwards in the direction from head->prev to tail. If NUMDUPACK=3 such packets were counted within this loop, `seqp' points to the last acknowledged packet of these, and the "if (done == NUMDUPACK)" block is entered next. The while-loop contained within that block in turn traverses the list backwards, from head to tail; the position of `seqp' is saved in the variable `last_acked'. For each packet not marked as `acked', a congestion event is triggered within the loop, and pipe is decremented. The loop terminates when `seqp' has reached `tail', whereupon tail is set to the position previously stored in `last_acked'. Thus, between `last_acked' and the previous position of `tail', - pipe has been decremented earlier if the packet was marked as state 0 or 1; - pipe was decremented if the packet was not marked as acked. That is, pipe has been decremented by the number of packets between `last_acked' and the previous position of `tail'. As a consequence, pipe now again reflects the number of packets which have not (yet) been acked between the new position of tail (at `last_acked') and head->prev, or 0 if head==tail. The result is that the BUG_ON condition in check_sanity will also not be triggered, hence the test (3) is also redundant. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/ccids/ccid2.c | 52 -------------------------------------------------- 1 file changed, 52 deletions(-) diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index f564211c3885..28499e030f33 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -33,51 +33,8 @@ #ifdef CONFIG_IP_DCCP_CCID2_DEBUG static int ccid2_debug; #define ccid2_pr_debug(format, a...) DCCP_PR_DEBUG(ccid2_debug, format, ##a) - -static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hc) -{ - int len = 0; - int pipe = 0; - struct ccid2_seq *seqp = hc->tx_seqh; - - /* there is data in the chain */ - if (seqp != hc->tx_seqt) { - seqp = seqp->ccid2s_prev; - len++; - if (!seqp->ccid2s_acked) - pipe++; - - while (seqp != hc->tx_seqt) { - struct ccid2_seq *prev = seqp->ccid2s_prev; - - len++; - if (!prev->ccid2s_acked) - pipe++; - - /* packets are sent sequentially */ - BUG_ON(dccp_delta_seqno(seqp->ccid2s_seq, - prev->ccid2s_seq ) >= 0); - BUG_ON(time_before(seqp->ccid2s_sent, - prev->ccid2s_sent)); - - seqp = prev; - } - } - - BUG_ON(pipe != hc->tx_pipe); - ccid2_pr_debug("len of chain=%d\n", len); - - do { - seqp = seqp->ccid2s_prev; - len++; - } while (seqp != hc->tx_seqh); - - ccid2_pr_debug("total len=%d\n", len); - BUG_ON(len != hc->tx_seqbufc * CCID2_SEQBUF_LEN); -} #else #define ccid2_pr_debug(format, a...) -#define ccid2_hc_tx_check_sanity(hc) #endif static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hc) @@ -178,8 +135,6 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) ccid2_pr_debug("RTO_EXPIRE\n"); - ccid2_hc_tx_check_sanity(hc); - /* back-off timer */ hc->tx_rto <<= 1; @@ -204,7 +159,6 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) hc->tx_rpseq = 0; hc->tx_rpdupack = -1; ccid2_change_l_ack_ratio(sk, 1); - ccid2_hc_tx_check_sanity(hc); out: bh_unlock_sock(sk); sock_put(sk); @@ -312,7 +266,6 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) } } while (0); ccid2_pr_debug("=========\n"); - ccid2_hc_tx_check_sanity(hc); #endif } @@ -510,7 +463,6 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) int done = 0; unsigned int maxincr = 0; - ccid2_hc_tx_check_sanity(hc); /* check reverse path congestion */ seqno = DCCP_SKB_CB(skb)->dccpd_seq; @@ -694,8 +646,6 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) hc->tx_seqt = hc->tx_seqt->ccid2s_next; } - - ccid2_hc_tx_check_sanity(hc); } static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) @@ -730,8 +680,6 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) hc->tx_last_cong = jiffies; setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire, (unsigned long)sk); - - ccid2_hc_tx_check_sanity(hc); return 0; } -- cgit v1.2.3-59-g8ed1b From c38c92a84a9291a3d0eaf6a13650a11961ae964f Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 22 Aug 2010 19:41:39 +0000 Subject: dccp ccid-2: Simplify dec_pipe and rearming of RTO timer This removes the dec_pipe function and improves the way the RTO timer is rearmed when a new acknowledgment comes in. Details and justification for removal: -------------------------------------- 1) The BUG_ON in dec_pipe is never triggered: pipe is only decremented for TX history entries between tail and head, for which it had previously been incremented in tx_packet_sent; and it is not decremented twice for the same entry, since it is - either decremented when a corresponding Ack Vector cell in state 0 or 1 was received (and then ccid2s_acked==1), - or it is decremented when ccid2s_acked==0, as part of the loss detection in tx_packet_recv (and hence it can not have been decremented earlier). 2) Restarting the RTO timer happens for every single entry in each Ack Vector parsed by tx_packet_recv (according to RFC 4340, 11.4 this can happen up to 16192 times per Ack Vector). 3) The RTO timer should not be restarted when all outstanding data has been acknowledged. This is currently done similar to (2), in dec_pipe, when pipe has reached 0. The patch onsolidates the code which rearms the RTO timer, combining the segments from new_ack and dec_pipe. As a result, the code becomes clearer (compare with tcp_rearm_rto()). Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/ccids/ccid2.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 28499e030f33..f7f5069b1e84 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -413,23 +413,6 @@ static inline void ccid2_new_ack(struct sock *sk, hc->tx_srtt, hc->tx_rttvar, hc->tx_rto, HZ, r); } - - /* we got a new ack, so re-start RTO timer */ - ccid2_hc_tx_kill_rto_timer(sk); - ccid2_start_rto_timer(sk); -} - -static void ccid2_hc_tx_dec_pipe(struct sock *sk) -{ - struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); - - if (hc->tx_pipe == 0) - DCCP_BUG("pipe == 0"); - else - hc->tx_pipe--; - - if (hc->tx_pipe == 0) - ccid2_hc_tx_kill_rto_timer(sk); } static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp) @@ -572,7 +555,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) seqp->ccid2s_acked = 1; ccid2_pr_debug("Got ack for %llu\n", (unsigned long long)seqp->ccid2s_seq); - ccid2_hc_tx_dec_pipe(sk); + hc->tx_pipe--; } if (seqp == hc->tx_seqt) { done = 1; @@ -629,7 +612,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) * one ack vector. */ ccid2_congestion_event(sk, seqp); - ccid2_hc_tx_dec_pipe(sk); + hc->tx_pipe--; } if (seqp == hc->tx_seqt) break; @@ -646,6 +629,12 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) hc->tx_seqt = hc->tx_seqt->ccid2s_next; } + + /* restart RTO timer if not all outstanding data has been acked */ + if (hc->tx_pipe == 0) + sk_stop_timer(sk, &hc->tx_rtotimer); + else + sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); } static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) -- cgit v1.2.3-59-g8ed1b From 231cc2aaf14bad3b2325be0b19b8385ff5e75485 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 22 Aug 2010 19:41:40 +0000 Subject: dccp ccid-2: Replace broken RTT estimator with better algorithm The current CCID-2 RTT estimator code is in parts broken and lags behind the suggestions in RFC2988 of using scaled variants for SRTT/RTTVAR. That code is replaced by the present patch, which reuses the Linux TCP RTT estimator code. Further details: ---------------- 1. The minimum RTO of previously one second has been replaced with TCP's, since RFC4341, sec. 5 says that the minimum of 1 sec. (suggested in RFC2988, 2.4) is not necessary. Instead, the TCP_RTO_MIN is used, which agrees with DCCP's concept of a default RTT (RFC 4340, 3.4). 2. The maximum RTO has been set to DCCP_RTO_MAX (64 sec), which agrees with RFC2988, (2.5). 3. De-inlined the function ccid2_new_ack(). 4. Added a FIXME: the RTT is sampled several times per Ack Vector, which will give the wrong estimate. It should be replaced with one sample per Ack. However, at the moment this can not be resolved easily, since - it depends on TX history code (which also needs some work), - the cleanest solution is not to use the `sent' time at all (saves 4 bytes per entry) and use DCCP timestamps / elapsed time to estimated the RTT, which however is non-trivial to get right (but needs to be done). Reasons for reusing the Linux TCP estimator algorithm: ------------------------------------------------------ Some time was spent to find a better alternative, using basic RFC2988 as a first step. Further analysis and experimentation showed that the Linux TCP RTO estimator is superior to a basic RFC2988 implementation. A summary is on http://www.erg.abdn.ac.uk/users/gerrit/dccp/notes/ccid2/rto_estimator/ In addition, this estimator fared well in a recent empirical evaluation: Rewaskar, Sushant, Jasleen Kaur and F. Donelson Smith. A Performance Study of Loss Detection/Recovery in Real-world TCP Implementations. Proceedings of 15th IEEE International Conference on Network Protocols (ICNP-07), 2007. Thus there is significant benefit in reusing the existing TCP code. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/ccids/ccid2.c | 169 +++++++++++++++++++++++++++---------------------- net/dccp/ccids/ccid2.h | 20 ++++-- 2 files changed, 108 insertions(+), 81 deletions(-) diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index f7f5069b1e84..7af3106c1f94 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -113,19 +113,12 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val) dp->dccps_l_ack_ratio = val; } -static void ccid2_change_srtt(struct ccid2_hc_tx_sock *hc, long val) -{ - ccid2_pr_debug("change SRTT to %ld\n", val); - hc->tx_srtt = val; -} - static void ccid2_start_rto_timer(struct sock *sk); static void ccid2_hc_tx_rto_expire(unsigned long data) { struct sock *sk = (struct sock *)data; struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); - long s; bh_lock_sock(sk); if (sock_owned_by_user(sk)) { @@ -137,10 +130,8 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) /* back-off timer */ hc->tx_rto <<= 1; - - s = hc->tx_rto / HZ; - if (s > 60) - hc->tx_rto = 60 * HZ; + if (hc->tx_rto > DCCP_RTO_MAX) + hc->tx_rto = DCCP_RTO_MAX; ccid2_start_rto_timer(sk); @@ -168,7 +159,7 @@ static void ccid2_start_rto_timer(struct sock *sk) { struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); - ccid2_pr_debug("setting RTO timeout=%ld\n", hc->tx_rto); + ccid2_pr_debug("setting RTO timeout=%u\n", hc->tx_rto); BUG_ON(timer_pending(&hc->tx_rtotimer)); sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); @@ -339,9 +330,86 @@ static void ccid2_hc_tx_kill_rto_timer(struct sock *sk) ccid2_pr_debug("deleted RTO timer\n"); } -static inline void ccid2_new_ack(struct sock *sk, - struct ccid2_seq *seqp, - unsigned int *maxincr) +/** + * ccid2_rtt_estimator - Sample RTT and compute RTO using RFC2988 algorithm + * This code is almost identical with TCP's tcp_rtt_estimator(), since + * - it has a higher sampling frequency (recommended by RFC 1323), + * - the RTO does not collapse into RTT due to RTTVAR going towards zero, + * - it is simple (cf. more complex proposals such as Eifel timer or research + * which suggests that the gain should be set according to window size), + * - in tests it was found to work well with CCID2 [gerrit]. + */ +static void ccid2_rtt_estimator(struct sock *sk, const long mrtt) +{ + struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); + long m = mrtt ? : 1; + + if (hc->tx_srtt == 0) { + /* First measurement m */ + hc->tx_srtt = m << 3; + hc->tx_mdev = m << 1; + + hc->tx_mdev_max = max(TCP_RTO_MIN, hc->tx_mdev); + hc->tx_rttvar = hc->tx_mdev_max; + hc->tx_rtt_seq = dccp_sk(sk)->dccps_gss; + } else { + /* Update scaled SRTT as SRTT += 1/8 * (m - SRTT) */ + m -= (hc->tx_srtt >> 3); + hc->tx_srtt += m; + + /* Similarly, update scaled mdev with regard to |m| */ + if (m < 0) { + m = -m; + m -= (hc->tx_mdev >> 2); + /* + * This neutralises RTO increase when RTT < SRTT - mdev + * (see P. Sarolahti, A. Kuznetsov,"Congestion Control + * in Linux TCP", USENIX 2002, pp. 49-62). + */ + if (m > 0) + m >>= 3; + } else { + m -= (hc->tx_mdev >> 2); + } + hc->tx_mdev += m; + + if (hc->tx_mdev > hc->tx_mdev_max) { + hc->tx_mdev_max = hc->tx_mdev; + if (hc->tx_mdev_max > hc->tx_rttvar) + hc->tx_rttvar = hc->tx_mdev_max; + } + + /* + * Decay RTTVAR at most once per flight, exploiting that + * 1) pipe <= cwnd <= Sequence_Window = W (RFC 4340, 7.5.2) + * 2) AWL = GSS-W+1 <= GAR <= GSS (RFC 4340, 7.5.1) + * GAR is a useful bound for FlightSize = pipe. + * AWL is probably too low here, as it over-estimates pipe. + */ + if (after48(dccp_sk(sk)->dccps_gar, hc->tx_rtt_seq)) { + if (hc->tx_mdev_max < hc->tx_rttvar) + hc->tx_rttvar -= (hc->tx_rttvar - + hc->tx_mdev_max) >> 2; + hc->tx_rtt_seq = dccp_sk(sk)->dccps_gss; + hc->tx_mdev_max = TCP_RTO_MIN; + } + } + + /* + * Set RTO from SRTT and RTTVAR + * As in TCP, 4 * RTTVAR >= TCP_RTO_MIN, giving a minimum RTO of 200 ms. + * This agrees with RFC 4341, 5: + * "Because DCCP does not retransmit data, DCCP does not require + * TCP's recommended minimum timeout of one second". + */ + hc->tx_rto = (hc->tx_srtt >> 3) + hc->tx_rttvar; + + if (hc->tx_rto > DCCP_RTO_MAX) + hc->tx_rto = DCCP_RTO_MAX; +} + +static void ccid2_new_ack(struct sock *sk, struct ccid2_seq *seqp, + unsigned int *maxincr) { struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); @@ -355,64 +423,15 @@ static inline void ccid2_new_ack(struct sock *sk, hc->tx_cwnd += 1; hc->tx_packets_acked = 0; } - - /* update RTO */ - if (hc->tx_srtt == -1 || - time_after(jiffies, hc->tx_lastrtt + hc->tx_srtt)) { - unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent; - int s; - - /* first measurement */ - if (hc->tx_srtt == -1) { - ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", - r, jiffies, - (unsigned long long)seqp->ccid2s_seq); - ccid2_change_srtt(hc, r); - hc->tx_rttvar = r >> 1; - } else { - /* RTTVAR */ - long tmp = hc->tx_srtt - r; - long srtt; - - if (tmp < 0) - tmp *= -1; - - tmp >>= 2; - hc->tx_rttvar *= 3; - hc->tx_rttvar >>= 2; - hc->tx_rttvar += tmp; - - /* SRTT */ - srtt = hc->tx_srtt; - srtt *= 7; - srtt >>= 3; - tmp = r >> 3; - srtt += tmp; - ccid2_change_srtt(hc, srtt); - } - s = hc->tx_rttvar << 2; - /* clock granularity is 1 when based on jiffies */ - if (!s) - s = 1; - hc->tx_rto = hc->tx_srtt + s; - - /* must be at least a second */ - s = hc->tx_rto / HZ; - /* DCCP doesn't require this [but I like it cuz my code sux] */ -#if 1 - if (s < 1) - hc->tx_rto = HZ; -#endif - /* max 60 seconds */ - if (s > 60) - hc->tx_rto = HZ * 60; - - hc->tx_lastrtt = jiffies; - - ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n", - hc->tx_srtt, hc->tx_rttvar, - hc->tx_rto, HZ, r); - } + /* + * FIXME: RTT is sampled several times per acknowledgment (for each + * entry in the Ack Vector), instead of once per Ack (as in TCP SACK). + * This causes the RTT to be over-estimated, since the older entries + * in the Ack Vector have earlier sending times. + * The cleanest solution is to not use the ccid2s_sent field at all + * and instead use DCCP timestamps: requires changes in other places. + */ + ccid2_rtt_estimator(sk, jiffies - seqp->ccid2s_sent); } static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp) @@ -662,9 +681,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) if (ccid2_hc_tx_alloc_seq(hc)) return -ENOMEM; - hc->tx_rto = 3 * HZ; - ccid2_change_srtt(hc, -1); - hc->tx_rttvar = -1; + hc->tx_rto = DCCP_TIMEOUT_INIT; hc->tx_rpdupack = -1; hc->tx_last_cong = jiffies; setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire, diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h index 1ec6a30103bb..b017843ba44d 100644 --- a/net/dccp/ccids/ccid2.h +++ b/net/dccp/ccids/ccid2.h @@ -42,7 +42,12 @@ struct ccid2_seq { * struct ccid2_hc_tx_sock - CCID2 TX half connection * @tx_{cwnd,ssthresh,pipe}: as per RFC 4341, section 5 * @tx_packets_acked: Ack counter for deriving cwnd growth (RFC 3465) - * @tx_lastrtt: time RTT was last measured + * @tx_srtt: smoothed RTT estimate, scaled by 2^3 + * @tx_mdev: smoothed RTT variation, scaled by 2^2 + * @tx_mdev_max: maximum of @mdev during one flight + * @tx_rttvar: moving average/maximum of @mdev_max + * @tx_rto: RTO value deriving from SRTT and RTTVAR (RFC 2988) + * @tx_rtt_seq: to decay RTTVAR at most once per flight * @tx_rpseq: last consecutive seqno * @tx_rpdupack: dupacks since rpseq */ @@ -55,11 +60,16 @@ struct ccid2_hc_tx_sock { int tx_seqbufc; struct ccid2_seq *tx_seqh; struct ccid2_seq *tx_seqt; - long tx_rto; - long tx_srtt; - long tx_rttvar; - unsigned long tx_lastrtt; + + /* RTT measurement: variables/principles are the same as in TCP */ + u32 tx_srtt, + tx_mdev, + tx_mdev_max, + tx_rttvar, + tx_rto; + u64 tx_rtt_seq:48; struct timer_list tx_rtotimer; + u64 tx_rpseq; int tx_rpdupack; unsigned long tx_last_cong; -- cgit v1.2.3-59-g8ed1b From 8b230ed8ec96c933047dd0625cf95f739e4939a6 Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Mon, 23 Aug 2010 20:24:12 -0700 Subject: bna: Brocade 10Gb Ethernet device driver This is patch 1/6 which contains linux driver source for Brocade's BR1010/BR1020 10Gb CEE capable ethernet adapter. Signed-off-by: Debashis Dutt Signed-off-by: Rasesh Mody Signed-off-by: David S. Miller --- MAINTAINERS | 7 + drivers/net/Kconfig | 14 + drivers/net/Makefile | 1 + drivers/net/bna/Makefile | 11 + drivers/net/bna/bfa_cee.c | 407 ++++ drivers/net/bna/bfa_cee.h | 72 + drivers/net/bna/bfa_defs.h | 243 ++ drivers/net/bna/bfa_defs_cna.h | 223 ++ drivers/net/bna/bfa_defs_mfg_comm.h | 244 ++ drivers/net/bna/bfa_defs_status.h | 216 ++ drivers/net/bna/bfa_ioc.c | 1839 +++++++++++++++ drivers/net/bna/bfa_ioc.h | 343 +++ drivers/net/bna/bfa_ioc_ct.c | 391 ++++ drivers/net/bna/bfa_sm.h | 88 + drivers/net/bna/bfa_wc.h | 69 + drivers/net/bna/bfi.h | 392 ++++ drivers/net/bna/bfi_cna.h | 199 ++ drivers/net/bna/bfi_ctreg.h | 637 ++++++ drivers/net/bna/bfi_ll.h | 438 ++++ drivers/net/bna/bna.h | 654 ++++++ drivers/net/bna/bna_ctrl.c | 3626 ++++++++++++++++++++++++++++++ drivers/net/bna/bna_hw.h | 1491 +++++++++++++ drivers/net/bna/bna_txrx.c | 4209 +++++++++++++++++++++++++++++++++++ drivers/net/bna/bna_types.h | 1128 ++++++++++ drivers/net/bna/bnad.c | 3270 +++++++++++++++++++++++++++ drivers/net/bna/bnad.h | 334 +++ drivers/net/bna/bnad_ethtool.c | 1282 +++++++++++ drivers/net/bna/cna.h | 81 + drivers/net/bna/cna_fwimg.c | 64 + include/linux/pci_ids.h | 3 + 30 files changed, 21976 insertions(+) create mode 100644 drivers/net/bna/Makefile create mode 100644 drivers/net/bna/bfa_cee.c create mode 100644 drivers/net/bna/bfa_cee.h create mode 100644 drivers/net/bna/bfa_defs.h create mode 100644 drivers/net/bna/bfa_defs_cna.h create mode 100644 drivers/net/bna/bfa_defs_mfg_comm.h create mode 100644 drivers/net/bna/bfa_defs_status.h create mode 100644 drivers/net/bna/bfa_ioc.c create mode 100644 drivers/net/bna/bfa_ioc.h create mode 100644 drivers/net/bna/bfa_ioc_ct.c create mode 100644 drivers/net/bna/bfa_sm.h create mode 100644 drivers/net/bna/bfa_wc.h create mode 100644 drivers/net/bna/bfi.h create mode 100644 drivers/net/bna/bfi_cna.h create mode 100644 drivers/net/bna/bfi_ctreg.h create mode 100644 drivers/net/bna/bfi_ll.h create mode 100644 drivers/net/bna/bna.h create mode 100644 drivers/net/bna/bna_ctrl.c create mode 100644 drivers/net/bna/bna_hw.h create mode 100644 drivers/net/bna/bna_txrx.c create mode 100644 drivers/net/bna/bna_types.h create mode 100644 drivers/net/bna/bnad.c create mode 100644 drivers/net/bna/bnad.h create mode 100644 drivers/net/bna/bnad_ethtool.c create mode 100644 drivers/net/bna/cna.h create mode 100644 drivers/net/bna/cna_fwimg.c diff --git a/MAINTAINERS b/MAINTAINERS index 43c9efcd8e10..93198c1980a9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1387,6 +1387,13 @@ L: linux-scsi@vger.kernel.org S: Supported F: drivers/scsi/bfa/ +BROCADE BNA 10 GIGABIT ETHERNET DRIVER +M: Rasesh Mody +M: Debashis Dutt +L: netdev@vger.kernel.org +S: Supported +F: drivers/net/bna/ + BSG (block layer generic sg v4 driver) M: FUJITA Tomonori L: linux-scsi@vger.kernel.org diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 85485287192a..53c4810b119e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2869,6 +2869,20 @@ config QLGE To compile this driver as a module, choose M here: the module will be called qlge. +config BNA + tristate "Brocade 1010/1020 10Gb Ethernet Driver support" + depends on PCI + ---help--- + This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet + cards. + To compile this driver as a module, choose M here: the module + will be called bna. + + For general information and support, go to the Brocade support + website at: + + + source "drivers/net/sfc/Kconfig" source "drivers/net/benet/Kconfig" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f34b3baf7ee6..18a277709a2a 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_ENIC) += enic/ obj-$(CONFIG_JME) += jme.o obj-$(CONFIG_BE2NET) += benet/ obj-$(CONFIG_VMXNET3) += vmxnet3/ +obj-$(CONFIG_BNA) += bna/ gianfar_driver-objs := gianfar.o \ gianfar_ethtool.o \ diff --git a/drivers/net/bna/Makefile b/drivers/net/bna/Makefile new file mode 100644 index 000000000000..a5d604de7fea --- /dev/null +++ b/drivers/net/bna/Makefile @@ -0,0 +1,11 @@ +# +# Copyright (c) 2005-2010 Brocade Communications Systems, Inc. +# All rights reserved. +# + +obj-$(CONFIG_BNA) += bna.o + +bna-objs := bnad.o bnad_ethtool.o bna_ctrl.o bna_txrx.o +bna-objs += bfa_ioc.o bfa_ioc_ct.o bfa_cee.o cna_fwimg.o + +EXTRA_CFLAGS := -Idrivers/net/bna diff --git a/drivers/net/bna/bfa_cee.c b/drivers/net/bna/bfa_cee.c new file mode 100644 index 000000000000..1545fc9720f8 --- /dev/null +++ b/drivers/net/bna/bfa_cee.c @@ -0,0 +1,407 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +#include "bfa_defs_cna.h" +#include "cna.h" +#include "bfa_cee.h" +#include "bfi_cna.h" +#include "bfa_ioc.h" + +#define bfa_ioc_portid(__ioc) ((__ioc)->port_id) +#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc) + +static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg); +static void bfa_cee_format_cee_cfg(void *buffer); + +static void +bfa_cee_format_cee_cfg(void *buffer) +{ + struct bfa_cee_attr *cee_cfg = buffer; + bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote); +} + +static void +bfa_cee_stats_swap(struct bfa_cee_stats *stats) +{ + u32 *buffer = (u32 *)stats; + int i; + + for (i = 0; i < (sizeof(struct bfa_cee_stats) / sizeof(u32)); + i++) { + buffer[i] = ntohl(buffer[i]); + } +} + +static void +bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg) +{ + lldp_cfg->time_to_live = + ntohs(lldp_cfg->time_to_live); + lldp_cfg->enabled_system_cap = + ntohs(lldp_cfg->enabled_system_cap); +} + +/** + * bfa_cee_attr_meminfo() + * + * @brief Returns the size of the DMA memory needed by CEE attributes + * + * @param[in] void + * + * @return Size of DMA region + */ +static u32 +bfa_cee_attr_meminfo(void) +{ + return roundup(sizeof(struct bfa_cee_attr), BFA_DMA_ALIGN_SZ); +} +/** + * bfa_cee_stats_meminfo() + * + * @brief Returns the size of the DMA memory needed by CEE stats + * + * @param[in] void + * + * @return Size of DMA region + */ +static u32 +bfa_cee_stats_meminfo(void) +{ + return roundup(sizeof(struct bfa_cee_stats), BFA_DMA_ALIGN_SZ); +} + +/** + * bfa_cee_get_attr_isr() + * + * @brief CEE ISR for get-attributes responses from f/w + * + * @param[in] cee - Pointer to the CEE module + * status - Return status from the f/w + * + * @return void + */ +static void +bfa_cee_get_attr_isr(struct bfa_cee *cee, enum bfa_status status) +{ + cee->get_attr_status = status; + if (status == BFA_STATUS_OK) { + memcpy(cee->attr, cee->attr_dma.kva, + sizeof(struct bfa_cee_attr)); + bfa_cee_format_cee_cfg(cee->attr); + } + cee->get_attr_pending = false; + if (cee->cbfn.get_attr_cbfn) + cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status); +} + +/** + * bfa_cee_get_attr_isr() + * + * @brief CEE ISR for get-stats responses from f/w + * + * @param[in] cee - Pointer to the CEE module + * status - Return status from the f/w + * + * @return void + */ +static void +bfa_cee_get_stats_isr(struct bfa_cee *cee, enum bfa_status status) +{ + cee->get_stats_status = status; + if (status == BFA_STATUS_OK) { + memcpy(cee->stats, cee->stats_dma.kva, + sizeof(struct bfa_cee_stats)); + bfa_cee_stats_swap(cee->stats); + } + cee->get_stats_pending = false; + if (cee->cbfn.get_stats_cbfn) + cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status); +} + +/** + * bfa_cee_get_attr_isr() + * + * @brief CEE ISR for reset-stats responses from f/w + * + * @param[in] cee - Pointer to the CEE module + * status - Return status from the f/w + * + * @return void + */ +static void +bfa_cee_reset_stats_isr(struct bfa_cee *cee, enum bfa_status status) +{ + cee->reset_stats_status = status; + cee->reset_stats_pending = false; + if (cee->cbfn.reset_stats_cbfn) + cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status); +} +/** + * bfa_cee_meminfo() + * + * @brief Returns the size of the DMA memory needed by CEE module + * + * @param[in] void + * + * @return Size of DMA region + */ +u32 +bfa_cee_meminfo(void) +{ + return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo(); +} + +/** + * bfa_cee_mem_claim() + * + * @brief Initialized CEE DMA Memory + * + * @param[in] cee CEE module pointer + * dma_kva Kernel Virtual Address of CEE DMA Memory + * dma_pa Physical Address of CEE DMA Memory + * + * @return void + */ +void +bfa_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa) +{ + cee->attr_dma.kva = dma_kva; + cee->attr_dma.pa = dma_pa; + cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo(); + cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo(); + cee->attr = (struct bfa_cee_attr *) dma_kva; + cee->stats = (struct bfa_cee_stats *) + (dma_kva + bfa_cee_attr_meminfo()); +} + +/** + * bfa_cee_get_attr() + * + * @brief + * Send the request to the f/w to fetch CEE attributes. + * + * @param[in] Pointer to the CEE module data structure. + * + * @return Status + */ + +enum bfa_status +bfa_cee_get_attr(struct bfa_cee *cee, struct bfa_cee_attr *attr, + bfa_cee_get_attr_cbfn_t cbfn, void *cbarg) +{ + struct bfi_cee_get_req *cmd; + + BUG_ON(!((cee != NULL) && (cee->ioc != NULL))); + if (!bfa_ioc_is_operational(cee->ioc)) + return BFA_STATUS_IOC_FAILURE; + if (cee->get_attr_pending == true) + return BFA_STATUS_DEVBUSY; + cee->get_attr_pending = true; + cmd = (struct bfi_cee_get_req *) cee->get_cfg_mb.msg; + cee->attr = attr; + cee->cbfn.get_attr_cbfn = cbfn; + cee->cbfn.get_attr_cbarg = cbarg; + bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ, + bfa_ioc_portid(cee->ioc)); + bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa); + bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb); + + return BFA_STATUS_OK; +} + +/** + * bfa_cee_get_stats() + * + * @brief + * Send the request to the f/w to fetch CEE statistics. + * + * @param[in] Pointer to the CEE module data structure. + * + * @return Status + */ + +enum bfa_status +bfa_cee_get_stats(struct bfa_cee *cee, struct bfa_cee_stats *stats, + bfa_cee_get_stats_cbfn_t cbfn, void *cbarg) +{ + struct bfi_cee_get_req *cmd; + + BUG_ON(!((cee != NULL) && (cee->ioc != NULL))); + + if (!bfa_ioc_is_operational(cee->ioc)) + return BFA_STATUS_IOC_FAILURE; + if (cee->get_stats_pending == true) + return BFA_STATUS_DEVBUSY; + cee->get_stats_pending = true; + cmd = (struct bfi_cee_get_req *) cee->get_stats_mb.msg; + cee->stats = stats; + cee->cbfn.get_stats_cbfn = cbfn; + cee->cbfn.get_stats_cbarg = cbarg; + bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ, + bfa_ioc_portid(cee->ioc)); + bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa); + bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb); + + return BFA_STATUS_OK; +} + +/** + * bfa_cee_reset_stats() + * + * @brief Clears CEE Stats in the f/w. + * + * @param[in] Pointer to the CEE module data structure. + * + * @return Status + */ + +enum bfa_status +bfa_cee_reset_stats(struct bfa_cee *cee, bfa_cee_reset_stats_cbfn_t cbfn, + void *cbarg) +{ + struct bfi_cee_reset_stats *cmd; + + BUG_ON(!((cee != NULL) && (cee->ioc != NULL))); + if (!bfa_ioc_is_operational(cee->ioc)) + return BFA_STATUS_IOC_FAILURE; + if (cee->reset_stats_pending == true) + return BFA_STATUS_DEVBUSY; + cee->reset_stats_pending = true; + cmd = (struct bfi_cee_reset_stats *) cee->reset_stats_mb.msg; + cee->cbfn.reset_stats_cbfn = cbfn; + cee->cbfn.reset_stats_cbarg = cbarg; + bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS, + bfa_ioc_portid(cee->ioc)); + bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb); + return BFA_STATUS_OK; +} + +/** + * bfa_cee_isrs() + * + * @brief Handles Mail-box interrupts for CEE module. + * + * @param[in] Pointer to the CEE module data structure. + * + * @return void + */ + +void +bfa_cee_isr(void *cbarg, struct bfi_mbmsg *m) +{ + union bfi_cee_i2h_msg_u *msg; + struct bfi_cee_get_rsp *get_rsp; + struct bfa_cee *cee = (struct bfa_cee *) cbarg; + msg = (union bfi_cee_i2h_msg_u *) m; + get_rsp = (struct bfi_cee_get_rsp *) m; + switch (msg->mh.msg_id) { + case BFI_CEE_I2H_GET_CFG_RSP: + bfa_cee_get_attr_isr(cee, get_rsp->cmd_status); + break; + case BFI_CEE_I2H_GET_STATS_RSP: + bfa_cee_get_stats_isr(cee, get_rsp->cmd_status); + break; + case BFI_CEE_I2H_RESET_STATS_RSP: + bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status); + break; + default: + BUG_ON(1); + } +} + +/** + * bfa_cee_hbfail() + * + * @brief CEE module heart-beat failure handler. + * + * @param[in] Pointer to the CEE module data structure. + * + * @return void + */ + +void +bfa_cee_hbfail(void *arg) +{ + struct bfa_cee *cee; + cee = (struct bfa_cee *) arg; + + if (cee->get_attr_pending == true) { + cee->get_attr_status = BFA_STATUS_FAILED; + cee->get_attr_pending = false; + if (cee->cbfn.get_attr_cbfn) { + cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, + BFA_STATUS_FAILED); + } + } + if (cee->get_stats_pending == true) { + cee->get_stats_status = BFA_STATUS_FAILED; + cee->get_stats_pending = false; + if (cee->cbfn.get_stats_cbfn) { + cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, + BFA_STATUS_FAILED); + } + } + if (cee->reset_stats_pending == true) { + cee->reset_stats_status = BFA_STATUS_FAILED; + cee->reset_stats_pending = false; + if (cee->cbfn.reset_stats_cbfn) { + cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, + BFA_STATUS_FAILED); + } + } +} + +/** + * bfa_cee_attach() + * + * @brief CEE module-attach API + * + * @param[in] cee - Pointer to the CEE module data structure + * ioc - Pointer to the ioc module data structure + * dev - Pointer to the device driver module data structure + * The device driver specific mbox ISR functions have + * this pointer as one of the parameters. + * + * @return void + */ +void +bfa_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, + void *dev) +{ + BUG_ON(!(cee != NULL)); + cee->dev = dev; + cee->ioc = ioc; + + bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee); + bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee); + bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail); +} + +/** + * bfa_cee_detach() + * + * @brief CEE module-detach API + * + * @param[in] cee - Pointer to the CEE module data structure + * + * @return void + */ +void +bfa_cee_detach(struct bfa_cee *cee) +{ +} diff --git a/drivers/net/bna/bfa_cee.h b/drivers/net/bna/bfa_cee.h new file mode 100644 index 000000000000..1208cadeceed --- /dev/null +++ b/drivers/net/bna/bfa_cee.h @@ -0,0 +1,72 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +#ifndef __BFA_CEE_H__ +#define __BFA_CEE_H__ + +#include "bfa_defs_cna.h" +#include "bfa_ioc.h" + +typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, enum bfa_status status); +typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, enum bfa_status status); +typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, enum bfa_status status); +typedef void (*bfa_cee_hbfail_cbfn_t) (void *dev, enum bfa_status status); + +struct bfa_cee_cbfn { + bfa_cee_get_attr_cbfn_t get_attr_cbfn; + void *get_attr_cbarg; + bfa_cee_get_stats_cbfn_t get_stats_cbfn; + void *get_stats_cbarg; + bfa_cee_reset_stats_cbfn_t reset_stats_cbfn; + void *reset_stats_cbarg; +}; + +struct bfa_cee { + void *dev; + bool get_attr_pending; + bool get_stats_pending; + bool reset_stats_pending; + enum bfa_status get_attr_status; + enum bfa_status get_stats_status; + enum bfa_status reset_stats_status; + struct bfa_cee_cbfn cbfn; + struct bfa_ioc_hbfail_notify hbfail; + struct bfa_cee_attr *attr; + struct bfa_cee_stats *stats; + struct bfa_dma attr_dma; + struct bfa_dma stats_dma; + struct bfa_ioc *ioc; + struct bfa_mbox_cmd get_cfg_mb; + struct bfa_mbox_cmd get_stats_mb; + struct bfa_mbox_cmd reset_stats_mb; +}; + +u32 bfa_cee_meminfo(void); +void bfa_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, + u64 dma_pa); +void bfa_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, void *dev); +void bfa_cee_detach(struct bfa_cee *cee); +enum bfa_status bfa_cee_get_attr(struct bfa_cee *cee, + struct bfa_cee_attr *attr, bfa_cee_get_attr_cbfn_t cbfn, void *cbarg); +enum bfa_status bfa_cee_get_stats(struct bfa_cee *cee, + struct bfa_cee_stats *stats, bfa_cee_get_stats_cbfn_t cbfn, + void *cbarg); +enum bfa_status bfa_cee_reset_stats(struct bfa_cee *cee, + bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg); + +#endif /* __BFA_CEE_H__ */ diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h new file mode 100644 index 000000000000..29c1b8de2c2d --- /dev/null +++ b/drivers/net/bna/bfa_defs.h @@ -0,0 +1,243 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +#ifndef __BFA_DEFS_H__ +#define __BFA_DEFS_H__ + +#include "cna.h" +#include "bfa_defs_status.h" +#include "bfa_defs_mfg_comm.h" + +#define BFA_STRING_32 32 +#define BFA_VERSION_LEN 64 + +/** + * ---------------------- adapter definitions ------------ + */ + +/** + * BFA adapter level attributes. + */ +enum { + BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE), + /* + *!< adapter serial num length + */ + BFA_ADAPTER_MODEL_NAME_LEN = 16, /*!< model name length */ + BFA_ADAPTER_MODEL_DESCR_LEN = 128, /*!< model description length */ + BFA_ADAPTER_MFG_NAME_LEN = 8, /*!< manufacturer name length */ + BFA_ADAPTER_SYM_NAME_LEN = 64, /*!< adapter symbolic name length */ + BFA_ADAPTER_OS_TYPE_LEN = 64, /*!< adapter os type length */ +}; + +struct bfa_adapter_attr { + char manufacturer[BFA_ADAPTER_MFG_NAME_LEN]; + char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN]; + u32 card_type; + char model[BFA_ADAPTER_MODEL_NAME_LEN]; + char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN]; + u64 pwwn; + char node_symname[FC_SYMNAME_MAX]; + char hw_ver[BFA_VERSION_LEN]; + char fw_ver[BFA_VERSION_LEN]; + char optrom_ver[BFA_VERSION_LEN]; + char os_type[BFA_ADAPTER_OS_TYPE_LEN]; + struct bfa_mfg_vpd vpd; + struct mac mac; + + u8 nports; + u8 max_speed; + u8 prototype; + char asic_rev; + + u8 pcie_gen; + u8 pcie_lanes_orig; + u8 pcie_lanes; + u8 cna_capable; + + u8 is_mezz; + u8 trunk_capable; +}; + +/** + * ---------------------- IOC definitions ------------ + */ + +enum { + BFA_IOC_DRIVER_LEN = 16, + BFA_IOC_CHIP_REV_LEN = 8, +}; + +/** + * Driver and firmware versions. + */ +struct bfa_ioc_driver_attr { + char driver[BFA_IOC_DRIVER_LEN]; /*!< driver name */ + char driver_ver[BFA_VERSION_LEN]; /*!< driver version */ + char fw_ver[BFA_VERSION_LEN]; /*!< firmware version */ + char bios_ver[BFA_VERSION_LEN]; /*!< bios version */ + char efi_ver[BFA_VERSION_LEN]; /*!< EFI version */ + char ob_ver[BFA_VERSION_LEN]; /*!< openboot version */ +}; + +/** + * IOC PCI device attributes + */ +struct bfa_ioc_pci_attr { + u16 vendor_id; /*!< PCI vendor ID */ + u16 device_id; /*!< PCI device ID */ + u16 ssid; /*!< subsystem ID */ + u16 ssvid; /*!< subsystem vendor ID */ + u32 pcifn; /*!< PCI device function */ + u32 rsvd; /* padding */ + char chip_rev[BFA_IOC_CHIP_REV_LEN]; /*!< chip revision */ +}; + +/** + * IOC states + */ +enum bfa_ioc_state { + BFA_IOC_RESET = 1, /*!< IOC is in reset state */ + BFA_IOC_SEMWAIT = 2, /*!< Waiting for IOC h/w semaphore */ + BFA_IOC_HWINIT = 3, /*!< IOC h/w is being initialized */ + BFA_IOC_GETATTR = 4, /*!< IOC is being configured */ + BFA_IOC_OPERATIONAL = 5, /*!< IOC is operational */ + BFA_IOC_INITFAIL = 6, /*!< IOC hardware failure */ + BFA_IOC_HBFAIL = 7, /*!< IOC heart-beat failure */ + BFA_IOC_DISABLING = 8, /*!< IOC is being disabled */ + BFA_IOC_DISABLED = 9, /*!< IOC is disabled */ + BFA_IOC_FWMISMATCH = 10, /*!< IOC f/w different from drivers */ +}; + +/** + * IOC firmware stats + */ +struct bfa_fw_ioc_stats { + u32 enable_reqs; + u32 disable_reqs; + u32 get_attr_reqs; + u32 dbg_sync; + u32 dbg_dump; + u32 unknown_reqs; +}; + +/** + * IOC driver stats + */ +struct bfa_ioc_drv_stats { + u32 ioc_isrs; + u32 ioc_enables; + u32 ioc_disables; + u32 ioc_hbfails; + u32 ioc_boots; + u32 stats_tmos; + u32 hb_count; + u32 disable_reqs; + u32 enable_reqs; + u32 disable_replies; + u32 enable_replies; +}; + +/** + * IOC statistics + */ +struct bfa_ioc_stats { + struct bfa_ioc_drv_stats drv_stats; /*!< driver IOC stats */ + struct bfa_fw_ioc_stats fw_stats; /*!< firmware IOC stats */ +}; + +enum bfa_ioc_type { + BFA_IOC_TYPE_FC = 1, + BFA_IOC_TYPE_FCoE = 2, + BFA_IOC_TYPE_LL = 3, +}; + +/** + * IOC attributes returned in queries + */ +struct bfa_ioc_attr { + enum bfa_ioc_type ioc_type; + enum bfa_ioc_state state; /*!< IOC state */ + struct bfa_adapter_attr adapter_attr; /*!< HBA attributes */ + struct bfa_ioc_driver_attr driver_attr; /*!< driver attr */ + struct bfa_ioc_pci_attr pci_attr; + u8 port_id; /*!< port number */ + u8 rsvd[7]; /*!< 64bit align */ +}; + +/** + * ---------------------- mfg definitions ------------ + */ + +/** + * Checksum size + */ +#define BFA_MFG_CHKSUM_SIZE 16 + +#define BFA_MFG_PARTNUM_SIZE 14 +#define BFA_MFG_SUPPLIER_ID_SIZE 10 +#define BFA_MFG_SUPPLIER_PARTNUM_SIZE 20 +#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE 20 +#define BFA_MFG_SUPPLIER_REVISION_SIZE 4 + +#pragma pack(1) + +/** + * @brief BFA adapter manufacturing block definition. + * + * All numerical fields are in big-endian format. + */ +struct bfa_mfg_block { + u8 version; /*!< manufacturing block version */ + u8 mfg_sig[3]; /*!< characters 'M', 'F', 'G' */ + u16 mfgsize; /*!< mfg block size */ + u16 u16_chksum; /*!< old u16 checksum */ + char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)]; + char brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)]; + u8 mfg_day; /*!< manufacturing day */ + u8 mfg_month; /*!< manufacturing month */ + u16 mfg_year; /*!< manufacturing year */ + u64 mfg_wwn; /*!< wwn base for this adapter */ + u8 num_wwn; /*!< number of wwns assigned */ + u8 mfg_speeds; /*!< speeds allowed for this adapter */ + u8 rsv[2]; + char supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)]; + char supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)]; + char + supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)]; + char + supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)]; + mac_t mfg_mac; /*!< mac address */ + u8 num_mac; /*!< number of mac addresses */ + u8 rsv2; + u32 mfg_type; /*!< card type */ + u8 rsv3[108]; + u8 md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */ +}; + +#pragma pack() + +/** + * ---------------------- pci definitions ------------ + */ + +#define bfa_asic_id_ct(devid) \ + ((devid) == PCI_DEVICE_ID_BROCADE_CT || \ + (devid) == PCI_DEVICE_ID_BROCADE_CT_FC) + +#endif /* __BFA_DEFS_H__ */ diff --git a/drivers/net/bna/bfa_defs_cna.h b/drivers/net/bna/bfa_defs_cna.h new file mode 100644 index 000000000000..7e0a9187bdd5 --- /dev/null +++ b/drivers/net/bna/bfa_defs_cna.h @@ -0,0 +1,223 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +#ifndef __BFA_DEFS_CNA_H__ +#define __BFA_DEFS_CNA_H__ + +#include "bfa_defs.h" + +/** + * @brief + * FC physical port statistics. + */ +struct bfa_port_fc_stats { + u64 secs_reset; /*!< Seconds since stats is reset */ + u64 tx_frames; /*!< Tx frames */ + u64 tx_words; /*!< Tx words */ + u64 tx_lip; /*!< Tx LIP */ + u64 tx_nos; /*!< Tx NOS */ + u64 tx_ols; /*!< Tx OLS */ + u64 tx_lr; /*!< Tx LR */ + u64 tx_lrr; /*!< Tx LRR */ + u64 rx_frames; /*!< Rx frames */ + u64 rx_words; /*!< Rx words */ + u64 lip_count; /*!< Rx LIP */ + u64 nos_count; /*!< Rx NOS */ + u64 ols_count; /*!< Rx OLS */ + u64 lr_count; /*!< Rx LR */ + u64 lrr_count; /*!< Rx LRR */ + u64 invalid_crcs; /*!< Rx CRC err frames */ + u64 invalid_crc_gd_eof; /*!< Rx CRC err good EOF frames */ + u64 undersized_frm; /*!< Rx undersized frames */ + u64 oversized_frm; /*!< Rx oversized frames */ + u64 bad_eof_frm; /*!< Rx frames with bad EOF */ + u64 error_frames; /*!< Errored frames */ + u64 dropped_frames; /*!< Dropped frames */ + u64 link_failures; /*!< Link Failure (LF) count */ + u64 loss_of_syncs; /*!< Loss of sync count */ + u64 loss_of_signals; /*!< Loss of signal count */ + u64 primseq_errs; /*!< Primitive sequence protocol err. */ + u64 bad_os_count; /*!< Invalid ordered sets */ + u64 err_enc_out; /*!< Encoding err nonframe_8b10b */ + u64 err_enc; /*!< Encoding err frame_8b10b */ +}; + +/** + * @brief + * Eth Physical Port statistics. + */ +struct bfa_port_eth_stats { + u64 secs_reset; /*!< Seconds since stats is reset */ + u64 frame_64; /*!< Frames 64 bytes */ + u64 frame_65_127; /*!< Frames 65-127 bytes */ + u64 frame_128_255; /*!< Frames 128-255 bytes */ + u64 frame_256_511; /*!< Frames 256-511 bytes */ + u64 frame_512_1023; /*!< Frames 512-1023 bytes */ + u64 frame_1024_1518; /*!< Frames 1024-1518 bytes */ + u64 frame_1519_1522; /*!< Frames 1519-1522 bytes */ + u64 tx_bytes; /*!< Tx bytes */ + u64 tx_packets; /*!< Tx packets */ + u64 tx_mcast_packets; /*!< Tx multicast packets */ + u64 tx_bcast_packets; /*!< Tx broadcast packets */ + u64 tx_control_frame; /*!< Tx control frame */ + u64 tx_drop; /*!< Tx drops */ + u64 tx_jabber; /*!< Tx jabber */ + u64 tx_fcs_error; /*!< Tx FCS errors */ + u64 tx_fragments; /*!< Tx fragments */ + u64 rx_bytes; /*!< Rx bytes */ + u64 rx_packets; /*!< Rx packets */ + u64 rx_mcast_packets; /*!< Rx multicast packets */ + u64 rx_bcast_packets; /*!< Rx broadcast packets */ + u64 rx_control_frames; /*!< Rx control frames */ + u64 rx_unknown_opcode; /*!< Rx unknown opcode */ + u64 rx_drop; /*!< Rx drops */ + u64 rx_jabber; /*!< Rx jabber */ + u64 rx_fcs_error; /*!< Rx FCS errors */ + u64 rx_alignment_error; /*!< Rx alignment errors */ + u64 rx_frame_length_error; /*!< Rx frame len errors */ + u64 rx_code_error; /*!< Rx code errors */ + u64 rx_fragments; /*!< Rx fragments */ + u64 rx_pause; /*!< Rx pause */ + u64 rx_zero_pause; /*!< Rx zero pause */ + u64 tx_pause; /*!< Tx pause */ + u64 tx_zero_pause; /*!< Tx zero pause */ + u64 rx_fcoe_pause; /*!< Rx FCoE pause */ + u64 rx_fcoe_zero_pause; /*!< Rx FCoE zero pause */ + u64 tx_fcoe_pause; /*!< Tx FCoE pause */ + u64 tx_fcoe_zero_pause; /*!< Tx FCoE zero pause */ +}; + +/** + * @brief + * Port statistics. + */ +union bfa_port_stats_u { + struct bfa_port_fc_stats fc; + struct bfa_port_eth_stats eth; +}; + +#pragma pack(1) + +#define BFA_CEE_LLDP_MAX_STRING_LEN (128) +#define BFA_CEE_DCBX_MAX_PRIORITY (8) +#define BFA_CEE_DCBX_MAX_PGID (8) + +#define BFA_CEE_LLDP_SYS_CAP_OTHER 0x0001 +#define BFA_CEE_LLDP_SYS_CAP_REPEATER 0x0002 +#define BFA_CEE_LLDP_SYS_CAP_MAC_BRIDGE 0x0004 +#define BFA_CEE_LLDP_SYS_CAP_WLAN_AP 0x0008 +#define BFA_CEE_LLDP_SYS_CAP_ROUTER 0x0010 +#define BFA_CEE_LLDP_SYS_CAP_TELEPHONE 0x0020 +#define BFA_CEE_LLDP_SYS_CAP_DOCSIS_CD 0x0040 +#define BFA_CEE_LLDP_SYS_CAP_STATION 0x0080 +#define BFA_CEE_LLDP_SYS_CAP_CVLAN 0x0100 +#define BFA_CEE_LLDP_SYS_CAP_SVLAN 0x0200 +#define BFA_CEE_LLDP_SYS_CAP_TPMR 0x0400 + +/* LLDP string type */ +struct bfa_cee_lldp_str { + u8 sub_type; + u8 len; + u8 rsvd[2]; + u8 value[BFA_CEE_LLDP_MAX_STRING_LEN]; +}; + +/* LLDP paramters */ +struct bfa_cee_lldp_cfg { + struct bfa_cee_lldp_str chassis_id; + struct bfa_cee_lldp_str port_id; + struct bfa_cee_lldp_str port_desc; + struct bfa_cee_lldp_str sys_name; + struct bfa_cee_lldp_str sys_desc; + struct bfa_cee_lldp_str mgmt_addr; + u16 time_to_live; + u16 enabled_system_cap; +}; + +enum bfa_cee_dcbx_version { + DCBX_PROTOCOL_PRECEE = 1, + DCBX_PROTOCOL_CEE = 2, +}; + +enum bfa_cee_lls { + /* LLS is down because the TLV not sent by the peer */ + CEE_LLS_DOWN_NO_TLV = 0, + /* LLS is down as advertised by the peer */ + CEE_LLS_DOWN = 1, + CEE_LLS_UP = 2, +}; + +/* CEE/DCBX parameters */ +struct bfa_cee_dcbx_cfg { + u8 pgid[BFA_CEE_DCBX_MAX_PRIORITY]; + u8 pg_percentage[BFA_CEE_DCBX_MAX_PGID]; + u8 pfc_primap; /* bitmap of priorties with PFC enabled */ + u8 fcoe_primap; /* bitmap of priorities used for FcoE traffic */ + u8 iscsi_primap; /* bitmap of priorities used for iSCSI traffic */ + u8 dcbx_version; /* operating version:CEE or preCEE */ + u8 lls_fcoe; /* FCoE Logical Link Status */ + u8 lls_lan; /* LAN Logical Link Status */ + u8 rsvd[2]; +}; + +/* CEE status */ +/* Making this to tri-state for the benefit of port list command */ +enum bfa_cee_status { + CEE_UP = 0, + CEE_PHY_UP = 1, + CEE_LOOPBACK = 2, + CEE_PHY_DOWN = 3, +}; + +/* CEE Query */ +struct bfa_cee_attr { + u8 cee_status; + u8 error_reason; + struct bfa_cee_lldp_cfg lldp_remote; + struct bfa_cee_dcbx_cfg dcbx_remote; + mac_t src_mac; + u8 link_speed; + u8 nw_priority; + u8 filler[2]; +}; + +/* LLDP/DCBX/CEE Statistics */ +struct bfa_cee_stats { + u32 lldp_tx_frames; /*!< LLDP Tx Frames */ + u32 lldp_rx_frames; /*!< LLDP Rx Frames */ + u32 lldp_rx_frames_invalid; /*!< LLDP Rx Frames invalid */ + u32 lldp_rx_frames_new; /*!< LLDP Rx Frames new */ + u32 lldp_tlvs_unrecognized; /*!< LLDP Rx unrecognized TLVs */ + u32 lldp_rx_shutdown_tlvs; /*!< LLDP Rx shutdown TLVs */ + u32 lldp_info_aged_out; /*!< LLDP remote info aged out */ + u32 dcbx_phylink_ups; /*!< DCBX phy link ups */ + u32 dcbx_phylink_downs; /*!< DCBX phy link downs */ + u32 dcbx_rx_tlvs; /*!< DCBX Rx TLVs */ + u32 dcbx_rx_tlvs_invalid; /*!< DCBX Rx TLVs invalid */ + u32 dcbx_control_tlv_error; /*!< DCBX control TLV errors */ + u32 dcbx_feature_tlv_error; /*!< DCBX feature TLV errors */ + u32 dcbx_cee_cfg_new; /*!< DCBX new CEE cfg rcvd */ + u32 cee_status_down; /*!< CEE status down */ + u32 cee_status_up; /*!< CEE status up */ + u32 cee_hw_cfg_changed; /*!< CEE hw cfg changed */ + u32 cee_rx_invalid_cfg; /*!< CEE invalid cfg */ +}; + +#pragma pack() + +#endif /* __BFA_DEFS_CNA_H__ */ diff --git a/drivers/net/bna/bfa_defs_mfg_comm.h b/drivers/net/bna/bfa_defs_mfg_comm.h new file mode 100644 index 000000000000..987978fcb3fe --- /dev/null +++ b/drivers/net/bna/bfa_defs_mfg_comm.h @@ -0,0 +1,244 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ +#ifndef __BFA_DEFS_MFG_COMM_H__ +#define __BFA_DEFS_MFG_COMM_H__ + +#include "cna.h" + +/** + * Manufacturing block version + */ +#define BFA_MFG_VERSION 2 +#define BFA_MFG_VERSION_UNINIT 0xFF + +/** + * Manufacturing block encrypted version + */ +#define BFA_MFG_ENC_VER 2 + +/** + * Manufacturing block version 1 length + */ +#define BFA_MFG_VER1_LEN 128 + +/** + * Manufacturing block header length + */ +#define BFA_MFG_HDR_LEN 4 + +#define BFA_MFG_SERIALNUM_SIZE 11 +#define STRSZ(_n) (((_n) + 4) & ~3) + +/** + * Manufacturing card type + */ +enum { + BFA_MFG_TYPE_CB_MAX = 825, /*!< Crossbow card type max */ + BFA_MFG_TYPE_FC8P2 = 825, /*!< 8G 2port FC card */ + BFA_MFG_TYPE_FC8P1 = 815, /*!< 8G 1port FC card */ + BFA_MFG_TYPE_FC4P2 = 425, /*!< 4G 2port FC card */ + BFA_MFG_TYPE_FC4P1 = 415, /*!< 4G 1port FC card */ + BFA_MFG_TYPE_CNA10P2 = 1020, /*!< 10G 2port CNA card */ + BFA_MFG_TYPE_CNA10P1 = 1010, /*!< 10G 1port CNA card */ + BFA_MFG_TYPE_JAYHAWK = 804, /*!< Jayhawk mezz card */ + BFA_MFG_TYPE_WANCHESE = 1007, /*!< Wanchese mezz card */ + BFA_MFG_TYPE_ASTRA = 807, /*!< Astra mezz card */ + BFA_MFG_TYPE_LIGHTNING_P0 = 902, /*!< Lightning mezz card - old */ + BFA_MFG_TYPE_LIGHTNING = 1741, /*!< Lightning mezz card */ + BFA_MFG_TYPE_INVALID = 0, /*!< Invalid card type */ +}; + +#pragma pack(1) + +/** + * Check if 1-port card + */ +#define bfa_mfg_is_1port(type) (( \ + (type) == BFA_MFG_TYPE_FC8P1 || \ + (type) == BFA_MFG_TYPE_FC4P1 || \ + (type) == BFA_MFG_TYPE_CNA10P1)) + +/** + * Check if Mezz card + */ +#define bfa_mfg_is_mezz(type) (( \ + (type) == BFA_MFG_TYPE_JAYHAWK || \ + (type) == BFA_MFG_TYPE_WANCHESE || \ + (type) == BFA_MFG_TYPE_ASTRA || \ + (type) == BFA_MFG_TYPE_LIGHTNING_P0 || \ + (type) == BFA_MFG_TYPE_LIGHTNING)) + +/** + * Check if card type valid + */ +#define bfa_mfg_is_card_type_valid(type) (( \ + (type) == BFA_MFG_TYPE_FC8P2 || \ + (type) == BFA_MFG_TYPE_FC8P1 || \ + (type) == BFA_MFG_TYPE_FC4P2 || \ + (type) == BFA_MFG_TYPE_FC4P1 || \ + (type) == BFA_MFG_TYPE_CNA10P2 || \ + (type) == BFA_MFG_TYPE_CNA10P1 || \ + bfa_mfg_is_mezz(type))) + +/** + * Check if the card having old wwn/mac handling + */ +#define bfa_mfg_is_old_wwn_mac_model(type) (( \ + (type) == BFA_MFG_TYPE_FC8P2 || \ + (type) == BFA_MFG_TYPE_FC8P1 || \ + (type) == BFA_MFG_TYPE_FC4P2 || \ + (type) == BFA_MFG_TYPE_FC4P1 || \ + (type) == BFA_MFG_TYPE_CNA10P2 || \ + (type) == BFA_MFG_TYPE_CNA10P1 || \ + (type) == BFA_MFG_TYPE_JAYHAWK || \ + (type) == BFA_MFG_TYPE_WANCHESE)) + +#define bfa_mfg_increment_wwn_mac(m, i) \ +do { \ + u32 t = ((m)[0] << 16) | ((m)[1] << 8) | (m)[2]; \ + t += (i); \ + (m)[0] = (t >> 16) & 0xFF; \ + (m)[1] = (t >> 8) & 0xFF; \ + (m)[2] = t & 0xFF; \ +} while (0) + +#define bfa_mfg_adapter_prop_init_flash(card_type, prop) \ +do { \ + switch ((card_type)) { \ + case BFA_MFG_TYPE_FC8P2: \ + case BFA_MFG_TYPE_JAYHAWK: \ + case BFA_MFG_TYPE_ASTRA: \ + (prop) = BFI_ADAPTER_SETP(NPORTS, 2) | \ + BFI_ADAPTER_SETP(SPEED, 8); \ + break; \ + case BFA_MFG_TYPE_FC8P1: \ + (prop) = BFI_ADAPTER_SETP(NPORTS, 1) | \ + BFI_ADAPTER_SETP(SPEED, 8); \ + break; \ + case BFA_MFG_TYPE_FC4P2: \ + (prop) = BFI_ADAPTER_SETP(NPORTS, 2) | \ + BFI_ADAPTER_SETP(SPEED, 4); \ + break; \ + case BFA_MFG_TYPE_FC4P1: \ + (prop) = BFI_ADAPTER_SETP(NPORTS, 1) | \ + BFI_ADAPTER_SETP(SPEED, 4); \ + break; \ + case BFA_MFG_TYPE_CNA10P2: \ + case BFA_MFG_TYPE_WANCHESE: \ + case BFA_MFG_TYPE_LIGHTNING_P0: \ + case BFA_MFG_TYPE_LIGHTNING: \ + (prop) = BFI_ADAPTER_SETP(NPORTS, 2); \ + (prop) |= BFI_ADAPTER_SETP(SPEED, 10); \ + break; \ + case BFA_MFG_TYPE_CNA10P1: \ + (prop) = BFI_ADAPTER_SETP(NPORTS, 1); \ + (prop) |= BFI_ADAPTER_SETP(SPEED, 10); \ + break; \ + default: \ + (prop) = BFI_ADAPTER_UNSUPP; \ + } \ +} while (0) + +enum { + CB_GPIO_TTV = (1), /*!< TTV debug capable cards */ + CB_GPIO_FC8P2 = (2), /*!< 8G 2port FC card */ + CB_GPIO_FC8P1 = (3), /*!< 8G 1port FC card */ + CB_GPIO_FC4P2 = (4), /*!< 4G 2port FC card */ + CB_GPIO_FC4P1 = (5), /*!< 4G 1port FC card */ + CB_GPIO_DFLY = (6), /*!< 8G 2port FC mezzanine card */ + CB_GPIO_PROTO = (1 << 7) /*!< 8G 2port FC prototypes */ +}; + +#define bfa_mfg_adapter_prop_init_gpio(gpio, card_type, prop) \ +do { \ + if ((gpio) & CB_GPIO_PROTO) { \ + (prop) |= BFI_ADAPTER_PROTO; \ + (gpio) &= ~CB_GPIO_PROTO; \ + } \ + switch ((gpio)) { \ + case CB_GPIO_TTV: \ + (prop) |= BFI_ADAPTER_TTV; \ + case CB_GPIO_DFLY: \ + case CB_GPIO_FC8P2: \ + (prop) |= BFI_ADAPTER_SETP(NPORTS, 2); \ + (prop) |= BFI_ADAPTER_SETP(SPEED, 8); \ + (card_type) = BFA_MFG_TYPE_FC8P2; \ + break; \ + case CB_GPIO_FC8P1: \ + (prop) |= BFI_ADAPTER_SETP(NPORTS, 1); \ + (prop) |= BFI_ADAPTER_SETP(SPEED, 8); \ + (card_type) = BFA_MFG_TYPE_FC8P1; \ + break; \ + case CB_GPIO_FC4P2: \ + (prop) |= BFI_ADAPTER_SETP(NPORTS, 2); \ + (prop) |= BFI_ADAPTER_SETP(SPEED, 4); \ + (card_type) = BFA_MFG_TYPE_FC4P2; \ + break; \ + case CB_GPIO_FC4P1: \ + (prop) |= BFI_ADAPTER_SETP(NPORTS, 1); \ + (prop) |= BFI_ADAPTER_SETP(SPEED, 4); \ + (card_type) = BFA_MFG_TYPE_FC4P1; \ + break; \ + default: \ + (prop) |= BFI_ADAPTER_UNSUPP; \ + (card_type) = BFA_MFG_TYPE_INVALID; \ + } \ +} while (0) + +/** + * VPD data length + */ +#define BFA_MFG_VPD_LEN 512 +#define BFA_MFG_VPD_LEN_INVALID 0 + +#define BFA_MFG_VPD_PCI_HDR_OFF 137 +#define BFA_MFG_VPD_PCI_VER_MASK 0x07 /*!< version mask 3 bits */ +#define BFA_MFG_VPD_PCI_VDR_MASK 0xf8 /*!< vendor mask 5 bits */ + +/** + * VPD vendor tag + */ +enum { + BFA_MFG_VPD_UNKNOWN = 0, /*!< vendor unknown */ + BFA_MFG_VPD_IBM = 1, /*!< vendor IBM */ + BFA_MFG_VPD_HP = 2, /*!< vendor HP */ + BFA_MFG_VPD_DELL = 3, /*!< vendor DELL */ + BFA_MFG_VPD_PCI_IBM = 0x08, /*!< PCI VPD IBM */ + BFA_MFG_VPD_PCI_HP = 0x10, /*!< PCI VPD HP */ + BFA_MFG_VPD_PCI_DELL = 0x20, /*!< PCI VPD DELL */ + BFA_MFG_VPD_PCI_BRCD = 0xf8, /*!< PCI VPD Brocade */ +}; + +/** + * @brief BFA adapter flash vpd data definition. + * + * All numerical fields are in big-endian format. + */ +struct bfa_mfg_vpd { + u8 version; /*!< vpd data version */ + u8 vpd_sig[3]; /*!< characters 'V', 'P', 'D' */ + u8 chksum; /*!< u8 checksum */ + u8 vendor; /*!< vendor */ + u8 len; /*!< vpd data length excluding header */ + u8 rsv; + u8 data[BFA_MFG_VPD_LEN]; /*!< vpd data */ +}; + +#pragma pack() + +#endif /* __BFA_DEFS_MFG_H__ */ diff --git a/drivers/net/bna/bfa_defs_status.h b/drivers/net/bna/bfa_defs_status.h new file mode 100644 index 000000000000..af951126375c --- /dev/null +++ b/drivers/net/bna/bfa_defs_status.h @@ -0,0 +1,216 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ +#ifndef __BFA_DEFS_STATUS_H__ +#define __BFA_DEFS_STATUS_H__ + +/** + * API status return values + * + * NOTE: The error msgs are auto generated from the comments. Only singe line + * comments are supported + */ +enum bfa_status { + BFA_STATUS_OK = 0, + BFA_STATUS_FAILED = 1, + BFA_STATUS_EINVAL = 2, + BFA_STATUS_ENOMEM = 3, + BFA_STATUS_ENOSYS = 4, + BFA_STATUS_ETIMER = 5, + BFA_STATUS_EPROTOCOL = 6, + BFA_STATUS_ENOFCPORTS = 7, + BFA_STATUS_NOFLASH = 8, + BFA_STATUS_BADFLASH = 9, + BFA_STATUS_SFP_UNSUPP = 10, + BFA_STATUS_UNKNOWN_VFID = 11, + BFA_STATUS_DATACORRUPTED = 12, + BFA_STATUS_DEVBUSY = 13, + BFA_STATUS_ABORTED = 14, + BFA_STATUS_NODEV = 15, + BFA_STATUS_HDMA_FAILED = 16, + BFA_STATUS_FLASH_BAD_LEN = 17, + BFA_STATUS_UNKNOWN_LWWN = 18, + BFA_STATUS_UNKNOWN_RWWN = 19, + BFA_STATUS_FCPT_LS_RJT = 20, + BFA_STATUS_VPORT_EXISTS = 21, + BFA_STATUS_VPORT_MAX = 22, + BFA_STATUS_UNSUPP_SPEED = 23, + BFA_STATUS_INVLD_DFSZ = 24, + BFA_STATUS_CNFG_FAILED = 25, + BFA_STATUS_CMD_NOTSUPP = 26, + BFA_STATUS_NO_ADAPTER = 27, + BFA_STATUS_LINKDOWN = 28, + BFA_STATUS_FABRIC_RJT = 29, + BFA_STATUS_UNKNOWN_VWWN = 30, + BFA_STATUS_NSLOGIN_FAILED = 31, + BFA_STATUS_NO_RPORTS = 32, + BFA_STATUS_NSQUERY_FAILED = 33, + BFA_STATUS_PORT_OFFLINE = 34, + BFA_STATUS_RPORT_OFFLINE = 35, + BFA_STATUS_TGTOPEN_FAILED = 36, + BFA_STATUS_BAD_LUNS = 37, + BFA_STATUS_IO_FAILURE = 38, + BFA_STATUS_NO_FABRIC = 39, + BFA_STATUS_EBADF = 40, + BFA_STATUS_EINTR = 41, + BFA_STATUS_EIO = 42, + BFA_STATUS_ENOTTY = 43, + BFA_STATUS_ENXIO = 44, + BFA_STATUS_EFOPEN = 45, + BFA_STATUS_VPORT_WWN_BP = 46, + BFA_STATUS_PORT_NOT_DISABLED = 47, + BFA_STATUS_BADFRMHDR = 48, + BFA_STATUS_BADFRMSZ = 49, + BFA_STATUS_MISSINGFRM = 50, + BFA_STATUS_LINKTIMEOUT = 51, + BFA_STATUS_NO_FCPIM_NEXUS = 52, + BFA_STATUS_CHECKSUM_FAIL = 53, + BFA_STATUS_GZME_FAILED = 54, + BFA_STATUS_SCSISTART_REQD = 55, + BFA_STATUS_IOC_FAILURE = 56, + BFA_STATUS_INVALID_WWN = 57, + BFA_STATUS_MISMATCH = 58, + BFA_STATUS_IOC_ENABLED = 59, + BFA_STATUS_ADAPTER_ENABLED = 60, + BFA_STATUS_IOC_NON_OP = 61, + BFA_STATUS_ADDR_MAP_FAILURE = 62, + BFA_STATUS_SAME_NAME = 63, + BFA_STATUS_PENDING = 64, + BFA_STATUS_8G_SPD = 65, + BFA_STATUS_4G_SPD = 66, + BFA_STATUS_AD_IS_ENABLE = 67, + BFA_STATUS_EINVAL_TOV = 68, + BFA_STATUS_EINVAL_QDEPTH = 69, + BFA_STATUS_VERSION_FAIL = 70, + BFA_STATUS_DIAG_BUSY = 71, + BFA_STATUS_BEACON_ON = 72, + BFA_STATUS_BEACON_OFF = 73, + BFA_STATUS_LBEACON_ON = 74, + BFA_STATUS_LBEACON_OFF = 75, + BFA_STATUS_PORT_NOT_INITED = 76, + BFA_STATUS_RPSC_ENABLED = 77, + BFA_STATUS_ENOFSAVE = 78, + BFA_STATUS_BAD_FILE = 79, + BFA_STATUS_RLIM_EN = 80, + BFA_STATUS_RLIM_DIS = 81, + BFA_STATUS_IOC_DISABLED = 82, + BFA_STATUS_ADAPTER_DISABLED = 83, + BFA_STATUS_BIOS_DISABLED = 84, + BFA_STATUS_AUTH_ENABLED = 85, + BFA_STATUS_AUTH_DISABLED = 86, + BFA_STATUS_ERROR_TRL_ENABLED = 87, + BFA_STATUS_ERROR_QOS_ENABLED = 88, + BFA_STATUS_NO_SFP_DEV = 89, + BFA_STATUS_MEMTEST_FAILED = 90, + BFA_STATUS_INVALID_DEVID = 91, + BFA_STATUS_QOS_ENABLED = 92, + BFA_STATUS_QOS_DISABLED = 93, + BFA_STATUS_INCORRECT_DRV_CONFIG = 94, + BFA_STATUS_REG_FAIL = 95, + BFA_STATUS_IM_INV_CODE = 96, + BFA_STATUS_IM_INV_VLAN = 97, + BFA_STATUS_IM_INV_ADAPT_NAME = 98, + BFA_STATUS_IM_LOW_RESOURCES = 99, + BFA_STATUS_IM_VLANID_IS_PVID = 100, + BFA_STATUS_IM_VLANID_EXISTS = 101, + BFA_STATUS_IM_FW_UPDATE_FAIL = 102, + BFA_STATUS_PORTLOG_ENABLED = 103, + BFA_STATUS_PORTLOG_DISABLED = 104, + BFA_STATUS_FILE_NOT_FOUND = 105, + BFA_STATUS_QOS_FC_ONLY = 106, + BFA_STATUS_RLIM_FC_ONLY = 107, + BFA_STATUS_CT_SPD = 108, + BFA_STATUS_LEDTEST_OP = 109, + BFA_STATUS_CEE_NOT_DN = 110, + BFA_STATUS_10G_SPD = 111, + BFA_STATUS_IM_INV_TEAM_NAME = 112, + BFA_STATUS_IM_DUP_TEAM_NAME = 113, + BFA_STATUS_IM_ADAPT_ALREADY_IN_TEAM = 114, + BFA_STATUS_IM_ADAPT_HAS_VLANS = 115, + BFA_STATUS_IM_PVID_MISMATCH = 116, + BFA_STATUS_IM_LINK_SPEED_MISMATCH = 117, + BFA_STATUS_IM_MTU_MISMATCH = 118, + BFA_STATUS_IM_RSS_MISMATCH = 119, + BFA_STATUS_IM_HDS_MISMATCH = 120, + BFA_STATUS_IM_OFFLOAD_MISMATCH = 121, + BFA_STATUS_IM_PORT_PARAMS = 122, + BFA_STATUS_IM_PORT_NOT_IN_TEAM = 123, + BFA_STATUS_IM_CANNOT_REM_PRI = 124, + BFA_STATUS_IM_MAX_PORTS_REACHED = 125, + BFA_STATUS_IM_LAST_PORT_DELETE = 126, + BFA_STATUS_IM_NO_DRIVER = 127, + BFA_STATUS_IM_MAX_VLANS_REACHED = 128, + BFA_STATUS_TOMCAT_SPD_NOT_ALLOWED = 129, + BFA_STATUS_NO_MINPORT_DRIVER = 130, + BFA_STATUS_CARD_TYPE_MISMATCH = 131, + BFA_STATUS_BAD_ASICBLK = 132, + BFA_STATUS_NO_DRIVER = 133, + BFA_STATUS_INVALID_MAC = 134, + BFA_STATUS_IM_NO_VLAN = 135, + BFA_STATUS_IM_ETH_LB_FAILED = 136, + BFA_STATUS_IM_PVID_REMOVE = 137, + BFA_STATUS_IM_PVID_EDIT = 138, + BFA_STATUS_CNA_NO_BOOT = 139, + BFA_STATUS_IM_PVID_NON_ZERO = 140, + BFA_STATUS_IM_INETCFG_LOCK_FAILED = 141, + BFA_STATUS_IM_GET_INETCFG_FAILED = 142, + BFA_STATUS_IM_NOT_BOUND = 143, + BFA_STATUS_INSUFFICIENT_PERMS = 144, + BFA_STATUS_IM_INV_VLAN_NAME = 145, + BFA_STATUS_CMD_NOTSUPP_CNA = 146, + BFA_STATUS_IM_PASSTHRU_EDIT = 147, + BFA_STATUS_IM_BIND_FAILED = 148, + BFA_STATUS_IM_UNBIND_FAILED = 149, + BFA_STATUS_IM_PORT_IN_TEAM = 150, + BFA_STATUS_IM_VLAN_NOT_FOUND = 151, + BFA_STATUS_IM_TEAM_NOT_FOUND = 152, + BFA_STATUS_IM_TEAM_CFG_NOT_ALLOWED = 153, + BFA_STATUS_PBC = 154, + BFA_STATUS_DEVID_MISSING = 155, + BFA_STATUS_BAD_FWCFG = 156, + BFA_STATUS_CREATE_FILE = 157, + BFA_STATUS_INVALID_VENDOR = 158, + BFA_STATUS_SFP_NOT_READY = 159, + BFA_STATUS_FLASH_UNINIT = 160, + BFA_STATUS_FLASH_EMPTY = 161, + BFA_STATUS_FLASH_CKFAIL = 162, + BFA_STATUS_TRUNK_UNSUPP = 163, + BFA_STATUS_TRUNK_ENABLED = 164, + BFA_STATUS_TRUNK_DISABLED = 165, + BFA_STATUS_TRUNK_ERROR_TRL_ENABLED = 166, + BFA_STATUS_BOOT_CODE_UPDATED = 167, + BFA_STATUS_BOOT_VERSION = 168, + BFA_STATUS_CARDTYPE_MISSING = 169, + BFA_STATUS_INVALID_CARDTYPE = 170, + BFA_STATUS_NO_TOPOLOGY_FOR_CNA = 171, + BFA_STATUS_IM_VLAN_OVER_TEAM_DELETE_FAILED = 172, + BFA_STATUS_ETHBOOT_ENABLED = 173, + BFA_STATUS_ETHBOOT_DISABLED = 174, + BFA_STATUS_IOPROFILE_OFF = 175, + BFA_STATUS_NO_PORT_INSTANCE = 176, + BFA_STATUS_BOOT_CODE_TIMEDOUT = 177, + BFA_STATUS_NO_VPORT_LOCK = 178, + BFA_STATUS_VPORT_NO_CNFG = 179, + BFA_STATUS_MAX_VAL +}; + +enum bfa_eproto_status { + BFA_EPROTO_BAD_ACCEPT = 0, + BFA_EPROTO_UNKNOWN_RSP = 1 +}; + +#endif /* __BFA_DEFS_STATUS_H__ */ diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c new file mode 100644 index 000000000000..cdc2cb1597ec --- /dev/null +++ b/drivers/net/bna/bfa_ioc.c @@ -0,0 +1,1839 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +#include "bfa_ioc.h" +#include "cna.h" +#include "bfi.h" +#include "bfi_ctreg.h" +#include "bfa_defs.h" + +/** + * IOC local definitions + */ + +#define bfa_ioc_timer_start(__ioc) \ + mod_timer(&(__ioc)->ioc_timer, jiffies + \ + msecs_to_jiffies(BFA_IOC_TOV)) +#define bfa_ioc_timer_stop(__ioc) del_timer(&(__ioc)->ioc_timer) + +#define bfa_ioc_recovery_timer_start(__ioc) \ + mod_timer(&(__ioc)->ioc_timer, jiffies + \ + msecs_to_jiffies(BFA_IOC_TOV_RECOVER)) + +#define bfa_sem_timer_start(__ioc) \ + mod_timer(&(__ioc)->sem_timer, jiffies + \ + msecs_to_jiffies(BFA_IOC_HWSEM_TOV)) +#define bfa_sem_timer_stop(__ioc) del_timer(&(__ioc)->sem_timer) + +#define bfa_hb_timer_start(__ioc) \ + mod_timer(&(__ioc)->hb_timer, jiffies + \ + msecs_to_jiffies(BFA_IOC_HB_TOV)) +#define bfa_hb_timer_stop(__ioc) del_timer(&(__ioc)->hb_timer) + +/** + * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details. + */ + +#define bfa_ioc_firmware_lock(__ioc) \ + ((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc)) +#define bfa_ioc_firmware_unlock(__ioc) \ + ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc)) +#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc)) +#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) +#define bfa_ioc_notify_hbfail(__ioc) \ + ((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc)) + +#define bfa_ioc_is_optrom(__ioc) \ + (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ) + +#define bfa_ioc_mbox_cmd_pending(__ioc) \ + (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \ + readl((__ioc)->ioc_regs.hfn_mbox_cmd)) + +bool bfa_auto_recover = true; + +/* + * forward declarations + */ +static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc); +static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc); +static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force); +static void bfa_ioc_send_enable(struct bfa_ioc *ioc); +static void bfa_ioc_send_disable(struct bfa_ioc *ioc); +static void bfa_ioc_send_getattr(struct bfa_ioc *ioc); +static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc); +static void bfa_ioc_hb_stop(struct bfa_ioc *ioc); +static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force); +static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc); +static void bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc); +static void bfa_ioc_recover(struct bfa_ioc *ioc); +static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc); +static void bfa_ioc_disable_comp(struct bfa_ioc *ioc); +static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc); + +/** + * IOC state machine events + */ +enum ioc_event { + IOC_E_ENABLE = 1, /*!< IOC enable request */ + IOC_E_DISABLE = 2, /*!< IOC disable request */ + IOC_E_TIMEOUT = 3, /*!< f/w response timeout */ + IOC_E_FWREADY = 4, /*!< f/w initialization done */ + IOC_E_FWRSP_GETATTR = 5, /*!< IOC get attribute response */ + IOC_E_FWRSP_ENABLE = 6, /*!< enable f/w response */ + IOC_E_FWRSP_DISABLE = 7, /*!< disable f/w response */ + IOC_E_HBFAIL = 8, /*!< heartbeat failure */ + IOC_E_HWERROR = 9, /*!< hardware error interrupt */ + IOC_E_SEMLOCKED = 10, /*!< h/w semaphore is locked */ + IOC_E_DETACH = 11, /*!< driver detach cleanup */ +}; + +bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event); + +static struct bfa_sm_table ioc_sm_table[] = { + {BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET}, + {BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH}, + {BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH}, + {BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT}, + {BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT}, + {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT}, + {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR}, + {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL}, + {BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL}, + {BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL}, + {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING}, + {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED}, +}; + +/** + * Reset entry actions -- initialize state machine + */ +static void +bfa_ioc_sm_reset_entry(struct bfa_ioc *ioc) +{ + ioc->retry_count = 0; + ioc->auto_recover = bfa_auto_recover; +} + +/** + * Beginning state. IOC is in reset state. + */ +static void +bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + case IOC_E_ENABLE: + bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck); + break; + + case IOC_E_DISABLE: + bfa_ioc_disable_comp(ioc); + break; + + case IOC_E_DETACH: + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +/** + * Semaphore should be acquired for version check. + */ +static void +bfa_ioc_sm_fwcheck_entry(struct bfa_ioc *ioc) +{ + bfa_ioc_hw_sem_get(ioc); +} + +/** + * Awaiting h/w semaphore to continue with version check. + */ +static void +bfa_ioc_sm_fwcheck(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + case IOC_E_SEMLOCKED: + if (bfa_ioc_firmware_lock(ioc)) { + ioc->retry_count = 0; + bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit); + } else { + bfa_ioc_hw_sem_release(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch); + } + break; + + case IOC_E_DISABLE: + bfa_ioc_disable_comp(ioc); + /* fall through */ + + case IOC_E_DETACH: + bfa_ioc_hw_sem_get_cancel(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_reset); + break; + + case IOC_E_FWREADY: + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +/** + * Notify enable completion callback and generate mismatch AEN. + */ +static void +bfa_ioc_sm_mismatch_entry(struct bfa_ioc *ioc) +{ + /** + * Provide enable completion callback and AEN notification only once. + */ + if (ioc->retry_count == 0) + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); + ioc->retry_count++; + bfa_ioc_timer_start(ioc); +} + +/** + * Awaiting firmware version match. + */ +static void +bfa_ioc_sm_mismatch(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + case IOC_E_TIMEOUT: + bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck); + break; + + case IOC_E_DISABLE: + bfa_ioc_disable_comp(ioc); + /* fall through */ + + case IOC_E_DETACH: + bfa_ioc_timer_stop(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_reset); + break; + + case IOC_E_FWREADY: + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +/** + * Request for semaphore. + */ +static void +bfa_ioc_sm_semwait_entry(struct bfa_ioc *ioc) +{ + bfa_ioc_hw_sem_get(ioc); +} + +/** + * Awaiting semaphore for h/w initialzation. + */ +static void +bfa_ioc_sm_semwait(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + case IOC_E_SEMLOCKED: + ioc->retry_count = 0; + bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit); + break; + + case IOC_E_DISABLE: + bfa_ioc_hw_sem_get_cancel(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +static void +bfa_ioc_sm_hwinit_entry(struct bfa_ioc *ioc) +{ + bfa_ioc_timer_start(ioc); + bfa_ioc_reset(ioc, false); +} + +/** + * @brief + * Hardware is being initialized. Interrupts are enabled. + * Holding hardware semaphore lock. + */ +static void +bfa_ioc_sm_hwinit(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + case IOC_E_FWREADY: + bfa_ioc_timer_stop(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling); + break; + + case IOC_E_HWERROR: + bfa_ioc_timer_stop(ioc); + /* fall through */ + + case IOC_E_TIMEOUT: + ioc->retry_count++; + if (ioc->retry_count < BFA_IOC_HWINIT_MAX) { + bfa_ioc_timer_start(ioc); + bfa_ioc_reset(ioc, true); + break; + } + + bfa_ioc_hw_sem_release(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); + break; + + case IOC_E_DISABLE: + bfa_ioc_hw_sem_release(ioc); + bfa_ioc_timer_stop(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +static void +bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc) +{ + bfa_ioc_timer_start(ioc); + bfa_ioc_send_enable(ioc); +} + +/** + * Host IOC function is being enabled, awaiting response from firmware. + * Semaphore is acquired. + */ +static void +bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + case IOC_E_FWRSP_ENABLE: + bfa_ioc_timer_stop(ioc); + bfa_ioc_hw_sem_release(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); + break; + + case IOC_E_HWERROR: + bfa_ioc_timer_stop(ioc); + /* fall through */ + + case IOC_E_TIMEOUT: + ioc->retry_count++; + if (ioc->retry_count < BFA_IOC_HWINIT_MAX) { + writel(BFI_IOC_UNINIT, + ioc->ioc_regs.ioc_fwstate); + bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit); + break; + } + + bfa_ioc_hw_sem_release(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); + break; + + case IOC_E_DISABLE: + bfa_ioc_timer_stop(ioc); + bfa_ioc_hw_sem_release(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); + break; + + case IOC_E_FWREADY: + bfa_ioc_send_enable(ioc); + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +static void +bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc) +{ + bfa_ioc_timer_start(ioc); + bfa_ioc_send_getattr(ioc); +} + +/** + * @brief + * IOC configuration in progress. Timer is active. + */ +static void +bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + case IOC_E_FWRSP_GETATTR: + bfa_ioc_timer_stop(ioc); + bfa_ioc_check_attr_wwns(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_op); + break; + + case IOC_E_HWERROR: + bfa_ioc_timer_stop(ioc); + /* fall through */ + + case IOC_E_TIMEOUT: + bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); + break; + + case IOC_E_DISABLE: + bfa_ioc_timer_stop(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +static void +bfa_ioc_sm_op_entry(struct bfa_ioc *ioc) +{ + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK); + bfa_ioc_hb_monitor(ioc); +} + +static void +bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + case IOC_E_ENABLE: + break; + + case IOC_E_DISABLE: + bfa_ioc_hb_stop(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); + break; + + case IOC_E_HWERROR: + case IOC_E_FWREADY: + /** + * Hard error or IOC recovery by other function. + * Treat it same as heartbeat failure. + */ + bfa_ioc_hb_stop(ioc); + /* !!! fall through !!! */ + + case IOC_E_HBFAIL: + bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail); + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +static void +bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc) +{ + bfa_ioc_timer_start(ioc); + bfa_ioc_send_disable(ioc); +} + +/** + * IOC is being disabled + */ +static void +bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + case IOC_E_FWRSP_DISABLE: + bfa_ioc_timer_stop(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); + break; + + case IOC_E_HWERROR: + bfa_ioc_timer_stop(ioc); + /* + * !!! fall through !!! + */ + + case IOC_E_TIMEOUT: + writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); + bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +/** + * IOC disable completion entry. + */ +static void +bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc) +{ + bfa_ioc_disable_comp(ioc); +} + +static void +bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + case IOC_E_ENABLE: + bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait); + break; + + case IOC_E_DISABLE: + ioc->cbfn->disable_cbfn(ioc->bfa); + break; + + case IOC_E_FWREADY: + break; + + case IOC_E_DETACH: + bfa_ioc_firmware_unlock(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_reset); + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +static void +bfa_ioc_sm_initfail_entry(struct bfa_ioc *ioc) +{ + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); + bfa_ioc_timer_start(ioc); +} + +/** + * @brief + * Hardware initialization failed. + */ +static void +bfa_ioc_sm_initfail(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + case IOC_E_DISABLE: + bfa_ioc_timer_stop(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); + break; + + case IOC_E_DETACH: + bfa_ioc_timer_stop(ioc); + bfa_ioc_firmware_unlock(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_reset); + break; + + case IOC_E_TIMEOUT: + bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait); + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +static void +bfa_ioc_sm_hbfail_entry(struct bfa_ioc *ioc) +{ + struct list_head *qe; + struct bfa_ioc_hbfail_notify *notify; + + /** + * Mark IOC as failed in hardware and stop firmware. + */ + bfa_ioc_lpu_stop(ioc); + writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); + + /** + * Notify other functions on HB failure. + */ + bfa_ioc_notify_hbfail(ioc); + + /** + * Notify driver and common modules registered for notification. + */ + ioc->cbfn->hbfail_cbfn(ioc->bfa); + list_for_each(qe, &ioc->hb_notify_q) { + notify = (struct bfa_ioc_hbfail_notify *) qe; + notify->cbfn(notify->cbarg); + } + + /** + * Flush any queued up mailbox requests. + */ + bfa_ioc_mbox_hbfail(ioc); + + /** + * Trigger auto-recovery after a delay. + */ + if (ioc->auto_recover) + mod_timer(&ioc->ioc_timer, jiffies + + msecs_to_jiffies(BFA_IOC_TOV_RECOVER)); +} + +/** + * @brief + * IOC heartbeat failure. + */ +static void +bfa_ioc_sm_hbfail(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + + case IOC_E_ENABLE: + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); + break; + + case IOC_E_DISABLE: + if (ioc->auto_recover) + bfa_ioc_timer_stop(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); + break; + + case IOC_E_TIMEOUT: + bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait); + break; + + case IOC_E_FWREADY: + /** + * Recovery is already initiated by other function. + */ + break; + + case IOC_E_HWERROR: + /* + * HB failure notification, ignore. + */ + break; + default: + bfa_sm_fault(ioc, event); + } +} + +/** + * BFA IOC private functions + */ + +static void +bfa_ioc_disable_comp(struct bfa_ioc *ioc) +{ + struct list_head *qe; + struct bfa_ioc_hbfail_notify *notify; + + ioc->cbfn->disable_cbfn(ioc->bfa); + + /** + * Notify common modules registered for notification. + */ + list_for_each(qe, &ioc->hb_notify_q) { + notify = (struct bfa_ioc_hbfail_notify *) qe; + notify->cbfn(notify->cbarg); + } +} + +void +bfa_ioc_sem_timeout(void *ioc_arg) +{ + struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg; + + bfa_ioc_hw_sem_get(ioc); +} + +bool +bfa_ioc_sem_get(void __iomem *sem_reg) +{ + u32 r32; + int cnt = 0; +#define BFA_SEM_SPINCNT 3000 + + r32 = readl(sem_reg); + + while (r32 && (cnt < BFA_SEM_SPINCNT)) { + cnt++; + udelay(2); + r32 = readl(sem_reg); + } + + if (r32 == 0) + return true; + + BUG_ON(!(cnt < BFA_SEM_SPINCNT)); + return false; +} + +void +bfa_ioc_sem_release(void __iomem *sem_reg) +{ + writel(1, sem_reg); +} + +static void +bfa_ioc_hw_sem_get(struct bfa_ioc *ioc) +{ + u32 r32; + + /** + * First read to the semaphore register will return 0, subsequent reads + * will return 1. Semaphore is released by writing 1 to the register + */ + r32 = readl(ioc->ioc_regs.ioc_sem_reg); + if (r32 == 0) { + bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED); + return; + } + + mod_timer(&ioc->sem_timer, jiffies + + msecs_to_jiffies(BFA_IOC_HWSEM_TOV)); +} + +void +bfa_ioc_hw_sem_release(struct bfa_ioc *ioc) +{ + writel(1, ioc->ioc_regs.ioc_sem_reg); +} + +static void +bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc) +{ + del_timer(&ioc->sem_timer); +} + +/** + * @brief + * Initialize LPU local memory (aka secondary memory / SRAM) + */ +static void +bfa_ioc_lmem_init(struct bfa_ioc *ioc) +{ + u32 pss_ctl; + int i; +#define PSS_LMEM_INIT_TIME 10000 + + pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg); + pss_ctl &= ~__PSS_LMEM_RESET; + pss_ctl |= __PSS_LMEM_INIT_EN; + + /* + * i2c workaround 12.5khz clock + */ + pss_ctl |= __PSS_I2C_CLK_DIV(3UL); + writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg); + + /** + * wait for memory initialization to be complete + */ + i = 0; + do { + pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg); + i++; + } while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME)); + + /** + * If memory initialization is not successful, IOC timeout will catch + * such failures. + */ + BUG_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE)); + + pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN); + writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg); +} + +static void +bfa_ioc_lpu_start(struct bfa_ioc *ioc) +{ + u32 pss_ctl; + + /** + * Take processor out of reset. + */ + pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg); + pss_ctl &= ~__PSS_LPU0_RESET; + + writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg); +} + +static void +bfa_ioc_lpu_stop(struct bfa_ioc *ioc) +{ + u32 pss_ctl; + + /** + * Put processors in reset. + */ + pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg); + pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET); + + writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg); +} + +/** + * Get driver and firmware versions. + */ +void +bfa_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) +{ + u32 pgnum, pgoff; + u32 loff = 0; + int i; + u32 *fwsig = (u32 *) fwhdr; + + pgnum = bfa_ioc_smem_pgnum(ioc, loff); + pgoff = bfa_ioc_smem_pgoff(ioc, loff); + writel(pgnum, ioc->ioc_regs.host_page_num_fn); + + for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32)); + i++) { + fwsig[i] = + swab32(readl((loff) + (ioc->ioc_regs.smem_page_start))); + loff += sizeof(u32); + } +} + +/** + * Returns TRUE if same. + */ +bool +bfa_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) +{ + struct bfi_ioc_image_hdr *drv_fwhdr; + int i; + + drv_fwhdr = (struct bfi_ioc_image_hdr *) + bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0); + + for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) { + if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) + return false; + } + + return true; +} + +/** + * Return true if current running version is valid. Firmware signature and + * execution context (driver/bios) must match. + */ +static bool +bfa_ioc_fwver_valid(struct bfa_ioc *ioc) +{ + struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr; + + /** + * If bios/efi boot (flash based) -- return true + */ + if (bfa_ioc_is_optrom(ioc)) + return true; + + bfa_ioc_fwver_get(ioc, &fwhdr); + drv_fwhdr = (struct bfi_ioc_image_hdr *) + bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0); + + if (fwhdr.signature != drv_fwhdr->signature) + return false; + + if (fwhdr.exec != drv_fwhdr->exec) + return false; + + return bfa_ioc_fwver_cmp(ioc, &fwhdr); +} + +/** + * Conditionally flush any pending message from firmware at start. + */ +static void +bfa_ioc_msgflush(struct bfa_ioc *ioc) +{ + u32 r32; + + r32 = readl(ioc->ioc_regs.lpu_mbox_cmd); + if (r32) + writel(1, ioc->ioc_regs.lpu_mbox_cmd); +} + +/** + * @img ioc_init_logic.jpg + */ +static void +bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force) +{ + enum bfi_ioc_state ioc_fwstate; + bool fwvalid; + + ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate); + + if (force) + ioc_fwstate = BFI_IOC_UNINIT; + + /** + * check if firmware is valid + */ + fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ? + false : bfa_ioc_fwver_valid(ioc); + + if (!fwvalid) { + bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id); + return; + } + + /** + * If hardware initialization is in progress (initialized by other IOC), + * just wait for an initialization completion interrupt. + */ + if (ioc_fwstate == BFI_IOC_INITING) { + ioc->cbfn->reset_cbfn(ioc->bfa); + return; + } + + /** + * If IOC function is disabled and firmware version is same, + * just re-enable IOC. + * + * If option rom, IOC must not be in operational state. With + * convergence, IOC will be in operational state when 2nd driver + * is loaded. + */ + if (ioc_fwstate == BFI_IOC_DISABLED || + (!bfa_ioc_is_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) { + /** + * When using MSI-X any pending firmware ready event should + * be flushed. Otherwise MSI-X interrupts are not delivered. + */ + bfa_ioc_msgflush(ioc); + ioc->cbfn->reset_cbfn(ioc->bfa); + bfa_fsm_send_event(ioc, IOC_E_FWREADY); + return; + } + + /** + * Initialize the h/w for any other states. + */ + bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id); +} + +void +bfa_ioc_timeout(void *ioc_arg) +{ + struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg; + + bfa_fsm_send_event(ioc, IOC_E_TIMEOUT); +} + +void +bfa_ioc_mbox_send(struct bfa_ioc *ioc, void *ioc_msg, int len) +{ + u32 *msgp = (u32 *) ioc_msg; + u32 i; + + BUG_ON(!(len <= BFI_IOC_MSGLEN_MAX)); + + /* + * first write msg to mailbox registers + */ + for (i = 0; i < len / sizeof(u32); i++) + writel(cpu_to_le32(msgp[i]), + ioc->ioc_regs.hfn_mbox + i * sizeof(u32)); + + for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++) + writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32)); + + /* + * write 1 to mailbox CMD to trigger LPU event + */ + writel(1, ioc->ioc_regs.hfn_mbox_cmd); + (void) readl(ioc->ioc_regs.hfn_mbox_cmd); +} + +static void +bfa_ioc_send_enable(struct bfa_ioc *ioc) +{ + struct bfi_ioc_ctrl_req enable_req; + struct timeval tv; + + bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ, + bfa_ioc_portid(ioc)); + enable_req.ioc_class = ioc->ioc_mc; + do_gettimeofday(&tv); + enable_req.tv_sec = ntohl(tv.tv_sec); + bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req)); +} + +static void +bfa_ioc_send_disable(struct bfa_ioc *ioc) +{ + struct bfi_ioc_ctrl_req disable_req; + + bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ, + bfa_ioc_portid(ioc)); + bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req)); +} + +static void +bfa_ioc_send_getattr(struct bfa_ioc *ioc) +{ + struct bfi_ioc_getattr_req attr_req; + + bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ, + bfa_ioc_portid(ioc)); + bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa); + bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req)); +} + +void +bfa_ioc_hb_check(void *cbarg) +{ + struct bfa_ioc *ioc = cbarg; + u32 hb_count; + + hb_count = readl(ioc->ioc_regs.heartbeat); + if (ioc->hb_count == hb_count) { + pr_crit("Firmware heartbeat failure at %d", hb_count); + bfa_ioc_recover(ioc); + return; + } else { + ioc->hb_count = hb_count; + } + + bfa_ioc_mbox_poll(ioc); + mod_timer(&ioc->hb_timer, jiffies + + msecs_to_jiffies(BFA_IOC_HB_TOV)); +} + +static void +bfa_ioc_hb_monitor(struct bfa_ioc *ioc) +{ + ioc->hb_count = readl(ioc->ioc_regs.heartbeat); + mod_timer(&ioc->hb_timer, jiffies + + msecs_to_jiffies(BFA_IOC_HB_TOV)); +} + +static void +bfa_ioc_hb_stop(struct bfa_ioc *ioc) +{ + del_timer(&ioc->hb_timer); +} + +/** + * @brief + * Initiate a full firmware download. + */ +static void +bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type, + u32 boot_param) +{ + u32 *fwimg; + u32 pgnum, pgoff; + u32 loff = 0; + u32 chunkno = 0; + u32 i; + + /** + * Initialize LMEM first before code download + */ + bfa_ioc_lmem_init(ioc); + + /** + * Flash based firmware boot + */ + if (bfa_ioc_is_optrom(ioc)) + boot_type = BFI_BOOT_TYPE_FLASH; + fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno); + + pgnum = bfa_ioc_smem_pgnum(ioc, loff); + pgoff = bfa_ioc_smem_pgoff(ioc, loff); + + writel(pgnum, ioc->ioc_regs.host_page_num_fn); + + for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) { + if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) { + chunkno = BFA_IOC_FLASH_CHUNK_NO(i); + fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), + BFA_IOC_FLASH_CHUNK_ADDR(chunkno)); + } + + /** + * write smem + */ + writel((swab32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)])), + ((ioc->ioc_regs.smem_page_start) + (loff))); + + loff += sizeof(u32); + + /** + * handle page offset wrap around + */ + loff = PSS_SMEM_PGOFF(loff); + if (loff == 0) { + pgnum++; + writel(pgnum, + ioc->ioc_regs.host_page_num_fn); + } + } + + writel(bfa_ioc_smem_pgnum(ioc, 0), + ioc->ioc_regs.host_page_num_fn); + + /* + * Set boot type and boot param at the end. + */ + writel((swab32(swab32(boot_type))), ((ioc->ioc_regs.smem_page_start) + + (BFI_BOOT_TYPE_OFF))); + writel((swab32(swab32(boot_param))), ((ioc->ioc_regs.smem_page_start) + + (BFI_BOOT_PARAM_OFF))); +} + +static void +bfa_ioc_reset(struct bfa_ioc *ioc, bool force) +{ + bfa_ioc_hwinit(ioc, force); +} + +/** + * @brief + * Update BFA configuration from firmware configuration. + */ +static void +bfa_ioc_getattr_reply(struct bfa_ioc *ioc) +{ + struct bfi_ioc_attr *attr = ioc->attr; + + attr->adapter_prop = ntohl(attr->adapter_prop); + attr->card_type = ntohl(attr->card_type); + attr->maxfrsize = ntohs(attr->maxfrsize); + + bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR); +} + +/** + * Attach time initialization of mbox logic. + */ +static void +bfa_ioc_mbox_attach(struct bfa_ioc *ioc) +{ + struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; + int mc; + + INIT_LIST_HEAD(&mod->cmd_q); + for (mc = 0; mc < BFI_MC_MAX; mc++) { + mod->mbhdlr[mc].cbfn = NULL; + mod->mbhdlr[mc].cbarg = ioc->bfa; + } +} + +/** + * Mbox poll timer -- restarts any pending mailbox requests. + */ +static void +bfa_ioc_mbox_poll(struct bfa_ioc *ioc) +{ + struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; + struct bfa_mbox_cmd *cmd; + u32 stat; + + /** + * If no command pending, do nothing + */ + if (list_empty(&mod->cmd_q)) + return; + + /** + * If previous command is not yet fetched by firmware, do nothing + */ + stat = readl(ioc->ioc_regs.hfn_mbox_cmd); + if (stat) + return; + + /** + * Enqueue command to firmware. + */ + bfa_q_deq(&mod->cmd_q, &cmd); + bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg)); +} + +/** + * Cleanup any pending requests. + */ +static void +bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc) +{ + struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; + struct bfa_mbox_cmd *cmd; + + while (!list_empty(&mod->cmd_q)) + bfa_q_deq(&mod->cmd_q, &cmd); +} + +/** + * IOC public + */ +enum bfa_status +bfa_ioc_pll_init(struct bfa_ioc *ioc) +{ + /* + * Hold semaphore so that nobody can access the chip during init. + */ + bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg); + + bfa_ioc_pll_init_asic(ioc); + + ioc->pllinit = true; + /* + * release semaphore. + */ + bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); + + return BFA_STATUS_OK; +} + +/** + * Interface used by diag module to do firmware boot with memory test + * as the entry vector. + */ +void +bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param) +{ + void __iomem *rb; + + bfa_ioc_stats(ioc, ioc_boots); + + if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK) + return; + + /** + * Initialize IOC state of all functions on a chip reset. + */ + rb = ioc->pcidev.pci_bar_kva; + if (boot_param == BFI_BOOT_TYPE_MEMTEST) { + writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG)); + writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG)); + } else { + writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG)); + writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG)); + } + + bfa_ioc_msgflush(ioc); + bfa_ioc_download_fw(ioc, boot_type, boot_param); + + /** + * Enable interrupts just before starting LPU + */ + ioc->cbfn->reset_cbfn(ioc->bfa); + bfa_ioc_lpu_start(ioc); +} + +/** + * Enable/disable IOC failure auto recovery. + */ +void +bfa_ioc_auto_recover(bool auto_recover) +{ + bfa_auto_recover = auto_recover; +} + +bool +bfa_ioc_is_operational(struct bfa_ioc *ioc) +{ + return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op); +} + +bool +bfa_ioc_is_initialized(struct bfa_ioc *ioc) +{ + u32 r32 = readl(ioc->ioc_regs.ioc_fwstate); + + return ((r32 != BFI_IOC_UNINIT) && + (r32 != BFI_IOC_INITING) && + (r32 != BFI_IOC_MEMTEST)); +} + +void +bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg) +{ + u32 *msgp = mbmsg; + u32 r32; + int i; + + /** + * read the MBOX msg + */ + for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32)); + i++) { + r32 = readl(ioc->ioc_regs.lpu_mbox + + i * sizeof(u32)); + msgp[i] = htonl(r32); + } + + /** + * turn off mailbox interrupt by clearing mailbox status + */ + writel(1, ioc->ioc_regs.lpu_mbox_cmd); + readl(ioc->ioc_regs.lpu_mbox_cmd); +} + +void +bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m) +{ + union bfi_ioc_i2h_msg_u *msg; + + msg = (union bfi_ioc_i2h_msg_u *) m; + + bfa_ioc_stats(ioc, ioc_isrs); + + switch (msg->mh.msg_id) { + case BFI_IOC_I2H_HBEAT: + break; + + case BFI_IOC_I2H_READY_EVENT: + bfa_fsm_send_event(ioc, IOC_E_FWREADY); + break; + + case BFI_IOC_I2H_ENABLE_REPLY: + bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE); + break; + + case BFI_IOC_I2H_DISABLE_REPLY: + bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE); + break; + + case BFI_IOC_I2H_GETATTR_REPLY: + bfa_ioc_getattr_reply(ioc); + break; + + default: + BUG_ON(1); + } +} + +/** + * IOC attach time initialization and setup. + * + * @param[in] ioc memory for IOC + * @param[in] bfa driver instance structure + */ +void +bfa_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn) +{ + ioc->bfa = bfa; + ioc->cbfn = cbfn; + ioc->fcmode = false; + ioc->pllinit = false; + ioc->dbg_fwsave_once = true; + + bfa_ioc_mbox_attach(ioc); + INIT_LIST_HEAD(&ioc->hb_notify_q); + + bfa_fsm_set_state(ioc, bfa_ioc_sm_reset); +} + +/** + * Driver detach time IOC cleanup. + */ +void +bfa_ioc_detach(struct bfa_ioc *ioc) +{ + bfa_fsm_send_event(ioc, IOC_E_DETACH); +} + +/** + * Setup IOC PCI properties. + * + * @param[in] pcidev PCI device information for this IOC + */ +void +bfa_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, + enum bfi_mclass mc) +{ + ioc->ioc_mc = mc; + ioc->pcidev = *pcidev; + ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id); + ioc->cna = ioc->ctdev && !ioc->fcmode; + + bfa_ioc_set_ct_hwif(ioc); + + bfa_ioc_map_port(ioc); + bfa_ioc_reg_init(ioc); +} + +/** + * Initialize IOC dma memory + * + * @param[in] dm_kva kernel virtual address of IOC dma memory + * @param[in] dm_pa physical address of IOC dma memory + */ +void +bfa_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa) +{ + /** + * dma memory for firmware attribute + */ + ioc->attr_dma.kva = dm_kva; + ioc->attr_dma.pa = dm_pa; + ioc->attr = (struct bfi_ioc_attr *) dm_kva; +} + +/** + * Return size of dma memory required. + */ +u32 +bfa_ioc_meminfo(void) +{ + return roundup(sizeof(struct bfi_ioc_attr), BFA_DMA_ALIGN_SZ); +} + +void +bfa_ioc_enable(struct bfa_ioc *ioc) +{ + bfa_ioc_stats(ioc, ioc_enables); + ioc->dbg_fwsave_once = true; + + bfa_fsm_send_event(ioc, IOC_E_ENABLE); +} + +void +bfa_ioc_disable(struct bfa_ioc *ioc) +{ + bfa_ioc_stats(ioc, ioc_disables); + bfa_fsm_send_event(ioc, IOC_E_DISABLE); +} + +u32 +bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr) +{ + return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr); +} + +u32 +bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr) +{ + return PSS_SMEM_PGOFF(fmaddr); +} + +/** + * Register mailbox message handler functions + * + * @param[in] ioc IOC instance + * @param[in] mcfuncs message class handler functions + */ +void +bfa_ioc_mbox_register(struct bfa_ioc *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs) +{ + struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; + int mc; + + for (mc = 0; mc < BFI_MC_MAX; mc++) + mod->mbhdlr[mc].cbfn = mcfuncs[mc]; +} + +/** + * Register mailbox message handler function, to be called by common modules + */ +void +bfa_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, + bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg) +{ + struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; + + mod->mbhdlr[mc].cbfn = cbfn; + mod->mbhdlr[mc].cbarg = cbarg; +} + +/** + * Queue a mailbox command request to firmware. Waits if mailbox is busy. + * Responsibility of caller to serialize + * + * @param[in] ioc IOC instance + * @param[i] cmd Mailbox command + */ +void +bfa_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd) +{ + struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; + u32 stat; + + /** + * If a previous command is pending, queue new command + */ + if (!list_empty(&mod->cmd_q)) { + list_add_tail(&cmd->qe, &mod->cmd_q); + return; + } + + /** + * If mailbox is busy, queue command for poll timer + */ + stat = readl(ioc->ioc_regs.hfn_mbox_cmd); + if (stat) { + list_add_tail(&cmd->qe, &mod->cmd_q); + return; + } + + /** + * mailbox is free -- queue command to firmware + */ + bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg)); +} + +/** + * Handle mailbox interrupts + */ +void +bfa_ioc_mbox_isr(struct bfa_ioc *ioc) +{ + struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; + struct bfi_mbmsg m; + int mc; + + bfa_ioc_msgget(ioc, &m); + + /** + * Treat IOC message class as special. + */ + mc = m.mh.msg_class; + if (mc == BFI_MC_IOC) { + bfa_ioc_isr(ioc, &m); + return; + } + + if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL)) + return; + + mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m); +} + +void +bfa_ioc_error_isr(struct bfa_ioc *ioc) +{ + bfa_fsm_send_event(ioc, IOC_E_HWERROR); +} + +void +bfa_ioc_set_fcmode(struct bfa_ioc *ioc) +{ + ioc->fcmode = true; + ioc->port_id = bfa_ioc_pcifn(ioc); +} + +/** + * return true if IOC is disabled + */ +bool +bfa_ioc_is_disabled(struct bfa_ioc *ioc) +{ + return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) || + bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled); +} + +/** + * return true if IOC firmware is different. + */ +bool +bfa_ioc_fw_mismatch(struct bfa_ioc *ioc) +{ + return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) || + bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck) || + bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch); +} + +#define bfa_ioc_state_disabled(__sm) \ + (((__sm) == BFI_IOC_UNINIT) || \ + ((__sm) == BFI_IOC_INITING) || \ + ((__sm) == BFI_IOC_HWINIT) || \ + ((__sm) == BFI_IOC_DISABLED) || \ + ((__sm) == BFI_IOC_FAIL) || \ + ((__sm) == BFI_IOC_CFG_DISABLED)) + +/** + * Check if adapter is disabled -- both IOCs should be in a disabled + * state. + */ +bool +bfa_ioc_adapter_is_disabled(struct bfa_ioc *ioc) +{ + u32 ioc_state; + void __iomem *rb = ioc->pcidev.pci_bar_kva; + + if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled)) + return false; + + ioc_state = readl(rb + BFA_IOC0_STATE_REG); + if (!bfa_ioc_state_disabled(ioc_state)) + return false; + + if (ioc->pcidev.device_id != PCI_DEVICE_ID_BROCADE_FC_8G1P) { + ioc_state = readl(rb + BFA_IOC1_STATE_REG); + if (!bfa_ioc_state_disabled(ioc_state)) + return false; + } + + return true; +} + +/** + * Add to IOC heartbeat failure notification queue. To be used by common + * modules such as cee, port, diag. + */ +void +bfa_ioc_hbfail_register(struct bfa_ioc *ioc, + struct bfa_ioc_hbfail_notify *notify) +{ + list_add_tail(¬ify->qe, &ioc->hb_notify_q); +} + +#define BFA_MFG_NAME "Brocade" +void +bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc, + struct bfa_adapter_attr *ad_attr) +{ + struct bfi_ioc_attr *ioc_attr; + + ioc_attr = ioc->attr; + + bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num); + bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver); + bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver); + bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer); + memcpy(&ad_attr->vpd, &ioc_attr->vpd, + sizeof(struct bfa_mfg_vpd)); + + ad_attr->nports = bfa_ioc_get_nports(ioc); + ad_attr->max_speed = bfa_ioc_speed_sup(ioc); + + bfa_ioc_get_adapter_model(ioc, ad_attr->model); + /* For now, model descr uses same model string */ + bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr); + + ad_attr->card_type = ioc_attr->card_type; + ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type); + + if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop)) + ad_attr->prototype = 1; + else + ad_attr->prototype = 0; + + ad_attr->pwwn = bfa_ioc_get_pwwn(ioc); + ad_attr->mac = bfa_ioc_get_mac(ioc); + + ad_attr->pcie_gen = ioc_attr->pcie_gen; + ad_attr->pcie_lanes = ioc_attr->pcie_lanes; + ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig; + ad_attr->asic_rev = ioc_attr->asic_rev; + + bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver); + + ad_attr->cna_capable = ioc->cna; + ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna; +} + +enum bfa_ioc_type +bfa_ioc_get_type(struct bfa_ioc *ioc) +{ + if (!ioc->ctdev || ioc->fcmode) + return BFA_IOC_TYPE_FC; + else if (ioc->ioc_mc == BFI_MC_IOCFC) + return BFA_IOC_TYPE_FCoE; + else if (ioc->ioc_mc == BFI_MC_LL) + return BFA_IOC_TYPE_LL; + else { + BUG_ON(!(ioc->ioc_mc == BFI_MC_LL)); + return BFA_IOC_TYPE_LL; + } +} + +void +bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num) +{ + memset(serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN); + memcpy(serial_num, + (void *)ioc->attr->brcd_serialnum, + BFA_ADAPTER_SERIAL_NUM_LEN); +} + +void +bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver) +{ + memset(fw_ver, 0, BFA_VERSION_LEN); + memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN); +} + +void +bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev) +{ + BUG_ON(!(chip_rev)); + + memset(chip_rev, 0, BFA_IOC_CHIP_REV_LEN); + + chip_rev[0] = 'R'; + chip_rev[1] = 'e'; + chip_rev[2] = 'v'; + chip_rev[3] = '-'; + chip_rev[4] = ioc->attr->asic_rev; + chip_rev[5] = '\0'; +} + +void +bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver) +{ + memset(optrom_ver, 0, BFA_VERSION_LEN); + memcpy(optrom_ver, ioc->attr->optrom_version, + BFA_VERSION_LEN); +} + +void +bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer) +{ + memset(manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN); + memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); +} + +void +bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model) +{ + struct bfi_ioc_attr *ioc_attr; + + BUG_ON(!(model)); + memset(model, 0, BFA_ADAPTER_MODEL_NAME_LEN); + + ioc_attr = ioc->attr; + + /** + * model name + */ + snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u", + BFA_MFG_NAME, ioc_attr->card_type); +} + +enum bfa_ioc_state +bfa_ioc_get_state(struct bfa_ioc *ioc) +{ + return bfa_sm_to_state(ioc_sm_table, ioc->fsm); +} + +void +bfa_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr) +{ + memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr)); + + ioc_attr->state = bfa_ioc_get_state(ioc); + ioc_attr->port_id = ioc->port_id; + + ioc_attr->ioc_type = bfa_ioc_get_type(ioc); + + bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr); + + ioc_attr->pci_attr.device_id = ioc->pcidev.device_id; + ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func; + bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev); +} + +/** + * WWN public + */ +u64 +bfa_ioc_get_pwwn(struct bfa_ioc *ioc) +{ + return ioc->attr->pwwn; +} + +u64 +bfa_ioc_get_nwwn(struct bfa_ioc *ioc) +{ + return ioc->attr->nwwn; +} + +u64 +bfa_ioc_get_adid(struct bfa_ioc *ioc) +{ + return ioc->attr->mfg_pwwn; +} + +mac_t +bfa_ioc_get_mac(struct bfa_ioc *ioc) +{ + /* + * Currently mfg mac is used as FCoE enode mac (not configured by PBC) + */ + if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE) + return bfa_ioc_get_mfg_mac(ioc); + else + return ioc->attr->mac; +} + +u64 +bfa_ioc_get_mfg_pwwn(struct bfa_ioc *ioc) +{ + return ioc->attr->mfg_pwwn; +} + +u64 +bfa_ioc_get_mfg_nwwn(struct bfa_ioc *ioc) +{ + return ioc->attr->mfg_nwwn; +} + +mac_t +bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc) +{ + mac_t m; + + m = ioc->attr->mfg_mac; + if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type)) + m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc); + else + bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]), + bfa_ioc_pcifn(ioc)); + + return m; +} + +bool +bfa_ioc_get_fcmode(struct bfa_ioc *ioc) +{ + return ioc->fcmode || !bfa_asic_id_ct(ioc->pcidev.device_id); +} + +/** + * Firmware failure detected. Start recovery actions. + */ +static void +bfa_ioc_recover(struct bfa_ioc *ioc) +{ + bfa_ioc_stats(ioc, ioc_hbfails); + bfa_fsm_send_event(ioc, IOC_E_HBFAIL); +} + +static void +bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc) +{ + if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL) + return; + +} diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h new file mode 100644 index 000000000000..2e5c0adef899 --- /dev/null +++ b/drivers/net/bna/bfa_ioc.h @@ -0,0 +1,343 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +#ifndef __BFA_IOC_H__ +#define __BFA_IOC_H__ + +#include "bfa_sm.h" +#include "bfi.h" +#include "cna.h" + +#define BFA_IOC_TOV 3000 /* msecs */ +#define BFA_IOC_HWSEM_TOV 500 /* msecs */ +#define BFA_IOC_HB_TOV 500 /* msecs */ +#define BFA_IOC_HWINIT_MAX 2 +#define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV + +/** + * Generic Scatter Gather Element used by driver + */ +struct bfa_sge { + u32 sg_len; + void *sg_addr; +}; + +/** + * PCI device information required by IOC + */ +struct bfa_pcidev { + int pci_slot; + u8 pci_func; + u16 device_id; + void __iomem *pci_bar_kva; +}; + +/** + * Structure used to remember the DMA-able memory block's KVA and Physical + * Address + */ +struct bfa_dma { + void *kva; /* ! Kernel virtual address */ + u64 pa; /* ! Physical address */ +}; + +#define BFA_DMA_ALIGN_SZ 256 + +/** + * smem size for Crossbow and Catapult + */ +#define BFI_SMEM_CB_SIZE 0x200000U /* ! 2MB for crossbow */ +#define BFI_SMEM_CT_SIZE 0x280000U /* ! 2.5MB for catapult */ + +/** + * @brief BFA dma address assignment macro + */ +#define bfa_dma_addr_set(dma_addr, pa) \ + __bfa_dma_addr_set(&dma_addr, (u64)pa) + +static inline void +__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa) +{ + dma_addr->a32.addr_lo = (u32) pa; + dma_addr->a32.addr_hi = (u32) (upper_32_bits(pa)); +} + +/** + * @brief BFA dma address assignment macro. (big endian format) + */ +#define bfa_dma_be_addr_set(dma_addr, pa) \ + __bfa_dma_be_addr_set(&dma_addr, (u64)pa) +static inline void +__bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa) +{ + dma_addr->a32.addr_lo = (u32) htonl(pa); + dma_addr->a32.addr_hi = (u32) htonl(upper_32_bits(pa)); +} + +struct bfa_ioc_regs { + void __iomem *hfn_mbox_cmd; + void __iomem *hfn_mbox; + void __iomem *lpu_mbox_cmd; + void __iomem *lpu_mbox; + void __iomem *pss_ctl_reg; + void __iomem *pss_err_status_reg; + void __iomem *app_pll_fast_ctl_reg; + void __iomem *app_pll_slow_ctl_reg; + void __iomem *ioc_sem_reg; + void __iomem *ioc_usage_sem_reg; + void __iomem *ioc_init_sem_reg; + void __iomem *ioc_usage_reg; + void __iomem *host_page_num_fn; + void __iomem *heartbeat; + void __iomem *ioc_fwstate; + void __iomem *ll_halt; + void __iomem *err_set; + void __iomem *shirq_isr_next; + void __iomem *shirq_msk_next; + void __iomem *smem_page_start; + u32 smem_pg0; +}; + +/** + * IOC Mailbox structures + */ +struct bfa_mbox_cmd { + struct list_head qe; + u32 msg[BFI_IOC_MSGSZ]; +}; + +/** + * IOC mailbox module + */ +typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg *m); +struct bfa_ioc_mbox_mod { + struct list_head cmd_q; /*!< pending mbox queue */ + int nmclass; /*!< number of handlers */ + struct { + bfa_ioc_mbox_mcfunc_t cbfn; /*!< message handlers */ + void *cbarg; + } mbhdlr[BFI_MC_MAX]; +}; + +/** + * IOC callback function interfaces + */ +typedef void (*bfa_ioc_enable_cbfn_t)(void *bfa, enum bfa_status status); +typedef void (*bfa_ioc_disable_cbfn_t)(void *bfa); +typedef void (*bfa_ioc_hbfail_cbfn_t)(void *bfa); +typedef void (*bfa_ioc_reset_cbfn_t)(void *bfa); +struct bfa_ioc_cbfn { + bfa_ioc_enable_cbfn_t enable_cbfn; + bfa_ioc_disable_cbfn_t disable_cbfn; + bfa_ioc_hbfail_cbfn_t hbfail_cbfn; + bfa_ioc_reset_cbfn_t reset_cbfn; +}; + +/** + * Heartbeat failure notification queue element. + */ +struct bfa_ioc_hbfail_notify { + struct list_head qe; + bfa_ioc_hbfail_cbfn_t cbfn; + void *cbarg; +}; + +/** + * Initialize a heartbeat failure notification structure + */ +#define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do { \ + (__notify)->cbfn = (__cbfn); \ + (__notify)->cbarg = (__cbarg); \ +} while (0) + +struct bfa_ioc { + bfa_fsm_t fsm; + struct bfa *bfa; + struct bfa_pcidev pcidev; + struct bfa_timer_mod *timer_mod; + struct timer_list ioc_timer; + struct timer_list sem_timer; + struct timer_list hb_timer; + u32 hb_count; + u32 retry_count; + struct list_head hb_notify_q; + void *dbg_fwsave; + int dbg_fwsave_len; + bool dbg_fwsave_once; + enum bfi_mclass ioc_mc; + struct bfa_ioc_regs ioc_regs; + struct bfa_ioc_drv_stats stats; + bool auto_recover; + bool fcmode; + bool ctdev; + bool cna; + bool pllinit; + bool stats_busy; /*!< outstanding stats */ + u8 port_id; + + struct bfa_dma attr_dma; + struct bfi_ioc_attr *attr; + struct bfa_ioc_cbfn *cbfn; + struct bfa_ioc_mbox_mod mbox_mod; + struct bfa_ioc_hwif *ioc_hwif; +}; + +struct bfa_ioc_hwif { + enum bfa_status (*ioc_pll_init) (void __iomem *rb, bool fcmode); + bool (*ioc_firmware_lock) (struct bfa_ioc *ioc); + void (*ioc_firmware_unlock) (struct bfa_ioc *ioc); + void (*ioc_reg_init) (struct bfa_ioc *ioc); + void (*ioc_map_port) (struct bfa_ioc *ioc); + void (*ioc_isr_mode_set) (struct bfa_ioc *ioc, + bool msix); + void (*ioc_notify_hbfail) (struct bfa_ioc *ioc); + void (*ioc_ownership_reset) (struct bfa_ioc *ioc); +}; + +#define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func) +#define bfa_ioc_devid(__ioc) ((__ioc)->pcidev.device_id) +#define bfa_ioc_bar0(__ioc) ((__ioc)->pcidev.pci_bar_kva) +#define bfa_ioc_portid(__ioc) ((__ioc)->port_id) +#define bfa_ioc_fetch_stats(__ioc, __stats) \ + (((__stats)->drv_stats) = (__ioc)->stats) +#define bfa_ioc_clr_stats(__ioc) \ + memset(&(__ioc)->stats, 0, sizeof((__ioc)->stats)) +#define bfa_ioc_maxfrsize(__ioc) ((__ioc)->attr->maxfrsize) +#define bfa_ioc_rx_bbcredit(__ioc) ((__ioc)->attr->rx_bbcredit) +#define bfa_ioc_speed_sup(__ioc) \ + BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop) +#define bfa_ioc_get_nports(__ioc) \ + BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop) + +#define bfa_ioc_stats(_ioc, _stats) ((_ioc)->stats._stats++) +#define BFA_IOC_FWIMG_MINSZ (16 * 1024) +#define BFA_IOC_FWIMG_TYPE(__ioc) \ + (((__ioc)->ctdev) ? \ + (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) : \ + BFI_IMAGE_CB_FC) +#define BFA_IOC_FW_SMEM_SIZE(__ioc) \ + (((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE) +#define BFA_IOC_FLASH_CHUNK_NO(off) (off / BFI_FLASH_CHUNK_SZ_WORDS) +#define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS) +#define BFA_IOC_FLASH_CHUNK_ADDR(chunkno) (chunkno * BFI_FLASH_CHUNK_SZ_WORDS) + +/** + * IOC mailbox interface + */ +void bfa_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd); +void bfa_ioc_mbox_register(struct bfa_ioc *ioc, + bfa_ioc_mbox_mcfunc_t *mcfuncs); +void bfa_ioc_mbox_isr(struct bfa_ioc *ioc); +void bfa_ioc_mbox_send(struct bfa_ioc *ioc, void *ioc_msg, int len); +void bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg); +void bfa_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, + bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg); + +/** + * IOC interfaces + */ + +#define bfa_ioc_pll_init_asic(__ioc) \ + ((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \ + (__ioc)->fcmode)) + +enum bfa_status bfa_ioc_pll_init(struct bfa_ioc *ioc); +enum bfa_status bfa_ioc_cb_pll_init(void __iomem *rb, bool fcmode); +enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode); + +#define bfa_ioc_isr_mode_set(__ioc, __msix) \ + ((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix)) +#define bfa_ioc_ownership_reset(__ioc) \ + ((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc)) + +void bfa_ioc_set_ct_hwif(struct bfa_ioc *ioc); + +void bfa_ioc_attach(struct bfa_ioc *ioc, void *bfa, + struct bfa_ioc_cbfn *cbfn); +void bfa_ioc_auto_recover(bool auto_recover); +void bfa_ioc_detach(struct bfa_ioc *ioc); +void bfa_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, + enum bfi_mclass mc); +u32 bfa_ioc_meminfo(void); +void bfa_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa); +void bfa_ioc_enable(struct bfa_ioc *ioc); +void bfa_ioc_disable(struct bfa_ioc *ioc); +bool bfa_ioc_intx_claim(struct bfa_ioc *ioc); + +void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, + u32 boot_param); +void bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *msg); +void bfa_ioc_error_isr(struct bfa_ioc *ioc); +bool bfa_ioc_is_operational(struct bfa_ioc *ioc); +bool bfa_ioc_is_initialized(struct bfa_ioc *ioc); +bool bfa_ioc_is_disabled(struct bfa_ioc *ioc); +bool bfa_ioc_fw_mismatch(struct bfa_ioc *ioc); +bool bfa_ioc_adapter_is_disabled(struct bfa_ioc *ioc); +void bfa_ioc_cfg_complete(struct bfa_ioc *ioc); +enum bfa_ioc_type bfa_ioc_get_type(struct bfa_ioc *ioc); +void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num); +void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver); +void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver); +void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model); +void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, + char *manufacturer); +void bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev); +enum bfa_ioc_state bfa_ioc_get_state(struct bfa_ioc *ioc); + +void bfa_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr); +void bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc, + struct bfa_adapter_attr *ad_attr); +u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr); +u32 bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr); +void bfa_ioc_set_fcmode(struct bfa_ioc *ioc); +bool bfa_ioc_get_fcmode(struct bfa_ioc *ioc); +void bfa_ioc_hbfail_register(struct bfa_ioc *ioc, + struct bfa_ioc_hbfail_notify *notify); +bool bfa_ioc_sem_get(void __iomem *sem_reg); +void bfa_ioc_sem_release(void __iomem *sem_reg); +void bfa_ioc_hw_sem_release(struct bfa_ioc *ioc); +void bfa_ioc_fwver_get(struct bfa_ioc *ioc, + struct bfi_ioc_image_hdr *fwhdr); +bool bfa_ioc_fwver_cmp(struct bfa_ioc *ioc, + struct bfi_ioc_image_hdr *fwhdr); + +/* + * Timeout APIs + */ +void bfa_ioc_timeout(void *ioc); +void bfa_ioc_hb_check(void *ioc); +void bfa_ioc_sem_timeout(void *ioc); + +/* + * bfa mfg wwn API functions + */ +u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc); +u64 bfa_ioc_get_nwwn(struct bfa_ioc *ioc); +mac_t bfa_ioc_get_mac(struct bfa_ioc *ioc); +u64 bfa_ioc_get_mfg_pwwn(struct bfa_ioc *ioc); +u64 bfa_ioc_get_mfg_nwwn(struct bfa_ioc *ioc); +mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc); +u64 bfa_ioc_get_adid(struct bfa_ioc *ioc); + +/* + * F/W Image Size & Chunk + */ +u32 *bfa_cb_image_get_chunk(int type, u32 off); +u32 bfa_cb_image_get_size(int type); + +#endif /* __BFA_IOC_H__ */ diff --git a/drivers/net/bna/bfa_ioc_ct.c b/drivers/net/bna/bfa_ioc_ct.c new file mode 100644 index 000000000000..870046e32c8d --- /dev/null +++ b/drivers/net/bna/bfa_ioc_ct.c @@ -0,0 +1,391 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +#include "bfa_ioc.h" +#include "cna.h" +#include "bfi.h" +#include "bfi_ctreg.h" +#include "bfa_defs.h" + +/* + * forward declarations + */ +static bool bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc); +static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc); +static void bfa_ioc_ct_reg_init(struct bfa_ioc *ioc); +static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc); +static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix); +static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc); +static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc); + +struct bfa_ioc_hwif hwif_ct; + +/** + * Called from bfa_ioc_attach() to map asic specific calls. + */ +void +bfa_ioc_set_ct_hwif(struct bfa_ioc *ioc) +{ + hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init; + hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock; + hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock; + hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init; + hwif_ct.ioc_map_port = bfa_ioc_ct_map_port; + hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; + hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail; + hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; + + ioc->ioc_hwif = &hwif_ct; +} + +/** + * Return true if firmware of current driver matches the running firmware. + */ +static bool +bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc) +{ + enum bfi_ioc_state ioc_fwstate; + u32 usecnt; + struct bfi_ioc_image_hdr fwhdr; + + /** + * Firmware match check is relevant only for CNA. + */ + if (!ioc->cna) + return true; + + /** + * If bios boot (flash based) -- do not increment usage count + */ + if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < + BFA_IOC_FWIMG_MINSZ) + return true; + + bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); + usecnt = readl(ioc->ioc_regs.ioc_usage_reg); + + /** + * If usage count is 0, always return TRUE. + */ + if (usecnt == 0) { + writel(1, ioc->ioc_regs.ioc_usage_reg); + bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + return true; + } + + ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate); + + /** + * Use count cannot be non-zero and chip in uninitialized state. + */ + BUG_ON(!(ioc_fwstate != BFI_IOC_UNINIT)); + + /** + * Check if another driver with a different firmware is active + */ + bfa_ioc_fwver_get(ioc, &fwhdr); + if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) { + bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + return false; + } + + /** + * Same firmware version. Increment the reference count. + */ + usecnt++; + writel(usecnt, ioc->ioc_regs.ioc_usage_reg); + bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + return true; +} + +static void +bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc) +{ + u32 usecnt; + + /** + * Firmware lock is relevant only for CNA. + */ + if (!ioc->cna) + return; + + /** + * If bios boot (flash based) -- do not decrement usage count + */ + if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < + BFA_IOC_FWIMG_MINSZ) + return; + + /** + * decrement usage count + */ + bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); + usecnt = readl(ioc->ioc_regs.ioc_usage_reg); + BUG_ON(!(usecnt > 0)); + + usecnt--; + writel(usecnt, ioc->ioc_regs.ioc_usage_reg); + + bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); +} + +/** + * Notify other functions on HB failure. + */ +static void +bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc) +{ + if (ioc->cna) { + writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt); + /* Wait for halt to take effect */ + readl(ioc->ioc_regs.ll_halt); + } else { + writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set); + readl(ioc->ioc_regs.err_set); + } +} + +/** + * Host to LPU mailbox message addresses + */ +static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = { + { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 }, + { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 }, + { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 }, + { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 } +}; + +/** + * Host <-> LPU mailbox command/status registers - port 0 + */ +static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = { + { HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT }, + { HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT }, + { HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT }, + { HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT } +}; + +/** + * Host <-> LPU mailbox command/status registers - port 1 + */ +static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = { + { HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT }, + { HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT }, + { HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT }, + { HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT } +}; + +static void +bfa_ioc_ct_reg_init(struct bfa_ioc *ioc) +{ + void __iomem *rb; + int pcifn = bfa_ioc_pcifn(ioc); + + rb = bfa_ioc_bar0(ioc); + + ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox; + ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox; + ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn; + + if (ioc->port_id == 0) { + ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; + ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; + ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn; + ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu; + ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0; + } else { + ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); + ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); + ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn; + ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu; + ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1; + } + + /* + * PSS control registers + */ + ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); + ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); + ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG); + ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG); + + /* + * IOC semaphore registers and serialization + */ + ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG); + ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG); + ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG); + ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT); + + /** + * sram memory access + */ + ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); + ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT; + + /* + * err set reg : for notification of hb failure in fcmode + */ + ioc->ioc_regs.err_set = (rb + ERR_SET_REG); +} + +/** + * Initialize IOC to port mapping. + */ + +#define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8) +static void +bfa_ioc_ct_map_port(struct bfa_ioc *ioc) +{ + void __iomem *rb = ioc->pcidev.pci_bar_kva; + u32 r32; + + /** + * For catapult, base port id on personality register and IOC type + */ + r32 = readl(rb + FNC_PERS_REG); + r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)); + ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH; + +} + +/** + * Set interrupt mode for a function: INTX or MSIX + */ +static void +bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix) +{ + void __iomem *rb = ioc->pcidev.pci_bar_kva; + u32 r32, mode; + + r32 = readl(rb + FNC_PERS_REG); + + mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) & + __F0_INTX_STATUS; + + /** + * If already in desired mode, do not change anything + */ + if (!msix && mode) + return; + + if (msix) + mode = __F0_INTX_STATUS_MSIX; + else + mode = __F0_INTX_STATUS_INTA; + + r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); + r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); + + writel(r32, rb + FNC_PERS_REG); +} + +/** + * Cleanup hw semaphore and usecnt registers + */ +static void +bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc) +{ + if (ioc->cna) { + bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); + writel(0, ioc->ioc_regs.ioc_usage_reg); + bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + } + + /* + * Read the hw sem reg to make sure that it is locked + * before we clear it. If it is not locked, writing 1 + * will lock it instead of clearing it. + */ + readl(ioc->ioc_regs.ioc_sem_reg); + bfa_ioc_hw_sem_release(ioc); +} + +enum bfa_status +bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode) +{ + u32 pll_sclk, pll_fclk, r32; + + pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST | + __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) | + __APP_PLL_312_JITLMT0_1(3U) | + __APP_PLL_312_CNTLMT0_1(1U); + pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST | + __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) | + __APP_PLL_425_JITLMT0_1(3U) | + __APP_PLL_425_CNTLMT0_1(1U); + if (fcmode) { + writel(0, (rb + OP_MODE)); + writel(__APP_EMS_CMLCKSEL | + __APP_EMS_REFCKBUFEN2 | + __APP_EMS_CHANNEL_SEL, + (rb + ETH_MAC_SER_REG)); + } else { + writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE)); + writel(__APP_EMS_REFCKBUFEN1, + (rb + ETH_MAC_SER_REG)); + } + writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG)); + writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG)); + writel(0xffffffffU, (rb + HOSTFN0_INT_MSK)); + writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); + writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS)); + writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); + writel(0xffffffffU, (rb + HOSTFN0_INT_MSK)); + writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); + writel(pll_sclk | + __APP_PLL_312_LOGIC_SOFT_RESET, + rb + APP_PLL_312_CTL_REG); + writel(pll_fclk | + __APP_PLL_425_LOGIC_SOFT_RESET, + rb + APP_PLL_425_CTL_REG); + writel(pll_sclk | + __APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE, + rb + APP_PLL_312_CTL_REG); + writel(pll_fclk | + __APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE, + rb + APP_PLL_425_CTL_REG); + readl(rb + HOSTFN0_INT_MSK); + udelay(2000); + writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS)); + writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); + writel(pll_sclk | + __APP_PLL_312_ENABLE, + rb + APP_PLL_312_CTL_REG); + writel(pll_fclk | + __APP_PLL_425_ENABLE, + rb + APP_PLL_425_CTL_REG); + if (!fcmode) { + writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0)); + writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1)); + } + r32 = readl((rb + PSS_CTL_REG)); + r32 &= ~__PSS_LMEM_RESET; + writel(r32, (rb + PSS_CTL_REG)); + udelay(1000); + if (!fcmode) { + writel(0, (rb + PMM_1T_RESET_REG_P0)); + writel(0, (rb + PMM_1T_RESET_REG_P1)); + } + + writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG)); + udelay(1000); + r32 = readl((rb + MBIST_STAT_REG)); + writel(0, (rb + MBIST_CTL_REG)); + return BFA_STATUS_OK; +} diff --git a/drivers/net/bna/bfa_sm.h b/drivers/net/bna/bfa_sm.h new file mode 100644 index 000000000000..1d3d975d6f68 --- /dev/null +++ b/drivers/net/bna/bfa_sm.h @@ -0,0 +1,88 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +/** + * @file bfasm.h State machine defines + */ + +#ifndef __BFA_SM_H__ +#define __BFA_SM_H__ + +#include "cna.h" + +typedef void (*bfa_sm_t)(void *sm, int event); + +/** + * oc - object class eg. bfa_ioc + * st - state, eg. reset + * otype - object type, eg. struct bfa_ioc + * etype - object type, eg. enum ioc_event + */ +#define bfa_sm_state_decl(oc, st, otype, etype) \ + static void oc ## _sm_ ## st(otype * fsm, etype event) + +#define bfa_sm_set_state(_sm, _state) ((_sm)->sm = (bfa_sm_t)(_state)) +#define bfa_sm_send_event(_sm, _event) ((_sm)->sm((_sm), (_event))) +#define bfa_sm_get_state(_sm) ((_sm)->sm) +#define bfa_sm_cmp_state(_sm, _state) ((_sm)->sm == (bfa_sm_t)(_state)) + +/** + * For converting from state machine function to state encoding. + */ +struct bfa_sm_table { + bfa_sm_t sm; /*!< state machine function */ + int state; /*!< state machine encoding */ + char *name; /*!< state name for display */ +}; +#define BFA_SM(_sm) ((bfa_sm_t)(_sm)) + +/** + * State machine with entry actions. + */ +typedef void (*bfa_fsm_t)(void *fsm, int event); + +/** + * oc - object class eg. bfa_ioc + * st - state, eg. reset + * otype - object type, eg. struct bfa_ioc + * etype - object type, eg. enum ioc_event + */ +#define bfa_fsm_state_decl(oc, st, otype, etype) \ + static void oc ## _sm_ ## st(otype * fsm, etype event); \ + static void oc ## _sm_ ## st ## _entry(otype * fsm) + +#define bfa_fsm_set_state(_fsm, _state) do { \ + (_fsm)->fsm = (bfa_fsm_t)(_state); \ + _state ## _entry(_fsm); \ +} while (0) + +#define bfa_fsm_send_event(_fsm, _event) ((_fsm)->fsm((_fsm), (_event))) +#define bfa_fsm_get_state(_fsm) ((_fsm)->fsm) +#define bfa_fsm_cmp_state(_fsm, _state) \ + ((_fsm)->fsm == (bfa_fsm_t)(_state)) + +static inline int +bfa_sm_to_state(struct bfa_sm_table *smt, bfa_sm_t sm) +{ + int i = 0; + + while (smt[i].sm && smt[i].sm != sm) + i++; + return smt[i].state; +} +#endif diff --git a/drivers/net/bna/bfa_wc.h b/drivers/net/bna/bfa_wc.h new file mode 100644 index 000000000000..d0e4caee67b0 --- /dev/null +++ b/drivers/net/bna/bfa_wc.h @@ -0,0 +1,69 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +/** + * @file bfa_wc.h Generic wait counter. + */ + +#ifndef __BFA_WC_H__ +#define __BFA_WC_H__ + +typedef void (*bfa_wc_resume_t) (void *cbarg); + +struct bfa_wc { + bfa_wc_resume_t wc_resume; + void *wc_cbarg; + int wc_count; +}; + +static inline void +bfa_wc_up(struct bfa_wc *wc) +{ + wc->wc_count++; +} + +static inline void +bfa_wc_down(struct bfa_wc *wc) +{ + wc->wc_count--; + if (wc->wc_count == 0) + wc->wc_resume(wc->wc_cbarg); +} + +/** + * Initialize a waiting counter. + */ +static inline void +bfa_wc_init(struct bfa_wc *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg) +{ + wc->wc_resume = wc_resume; + wc->wc_cbarg = wc_cbarg; + wc->wc_count = 0; + bfa_wc_up(wc); +} + +/** + * Wait for counter to reach zero + */ +static inline void +bfa_wc_wait(struct bfa_wc *wc) +{ + bfa_wc_down(wc); +} + +#endif diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h new file mode 100644 index 000000000000..a97396811050 --- /dev/null +++ b/drivers/net/bna/bfi.h @@ -0,0 +1,392 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +#ifndef __BFI_H__ +#define __BFI_H__ + +#include "bfa_defs.h" + +#pragma pack(1) + +/** + * BFI FW image type + */ +#define BFI_FLASH_CHUNK_SZ 256 /*!< Flash chunk size */ +#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32)) +enum { + BFI_IMAGE_CB_FC, + BFI_IMAGE_CT_FC, + BFI_IMAGE_CT_CNA, + BFI_IMAGE_MAX, +}; + +/** + * Msg header common to all msgs + */ +struct bfi_mhdr { + u8 msg_class; /*!< @ref enum bfi_mclass */ + u8 msg_id; /*!< msg opcode with in the class */ + union { + struct { + u8 rsvd; + u8 lpu_id; /*!< msg destination */ + } h2i; + u16 i2htok; /*!< token in msgs to host */ + } mtag; +}; + +#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do { \ + (_mh).msg_class = (_mc); \ + (_mh).msg_id = (_op); \ + (_mh).mtag.h2i.lpu_id = (_lpuid); \ +} while (0) + +#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do { \ + (_mh).msg_class = (_mc); \ + (_mh).msg_id = (_op); \ + (_mh).mtag.i2htok = (_i2htok); \ +} while (0) + +/* + * Message opcodes: 0-127 to firmware, 128-255 to host + */ +#define BFI_I2H_OPCODE_BASE 128 +#define BFA_I2HM(_x) ((_x) + BFI_I2H_OPCODE_BASE) + +/** + **************************************************************************** + * + * Scatter Gather Element and Page definition + * + **************************************************************************** + */ + +#define BFI_SGE_INLINE 1 +#define BFI_SGE_INLINE_MAX (BFI_SGE_INLINE + 1) + +/** + * SG Flags + */ +enum { + BFI_SGE_DATA = 0, /*!< data address, not last */ + BFI_SGE_DATA_CPL = 1, /*!< data addr, last in current page */ + BFI_SGE_DATA_LAST = 3, /*!< data address, last */ + BFI_SGE_LINK = 2, /*!< link address */ + BFI_SGE_PGDLEN = 2, /*!< cumulative data length for page */ +}; + +/** + * DMA addresses + */ +union bfi_addr_u { + struct { + u32 addr_lo; + u32 addr_hi; + } a32; +}; + +/** + * Scatter Gather Element + */ +struct bfi_sge { +#ifdef __BIGENDIAN + u32 flags:2, + rsvd:2, + sg_len:28; +#else + u32 sg_len:28, + rsvd:2, + flags:2; +#endif + union bfi_addr_u sga; +}; + +/** + * Scatter Gather Page + */ +#define BFI_SGPG_DATA_SGES 7 +#define BFI_SGPG_SGES_MAX (BFI_SGPG_DATA_SGES + 1) +#define BFI_SGPG_RSVD_WD_LEN 8 +struct bfi_sgpg { + struct bfi_sge sges[BFI_SGPG_SGES_MAX]; + u32 rsvd[BFI_SGPG_RSVD_WD_LEN]; +}; + +/* + * Large Message structure - 128 Bytes size Msgs + */ +#define BFI_LMSG_SZ 128 +#define BFI_LMSG_PL_WSZ \ + ((BFI_LMSG_SZ - sizeof(struct bfi_mhdr)) / 4) + +struct bfi_msg { + struct bfi_mhdr mhdr; + u32 pl[BFI_LMSG_PL_WSZ]; +}; + +/** + * Mailbox message structure + */ +#define BFI_MBMSG_SZ 7 +struct bfi_mbmsg { + struct bfi_mhdr mh; + u32 pl[BFI_MBMSG_SZ]; +}; + +/** + * Message Classes + */ +enum bfi_mclass { + BFI_MC_IOC = 1, /*!< IO Controller (IOC) */ + BFI_MC_DIAG = 2, /*!< Diagnostic Msgs */ + BFI_MC_FLASH = 3, /*!< Flash message class */ + BFI_MC_CEE = 4, /*!< CEE */ + BFI_MC_FCPORT = 5, /*!< FC port */ + BFI_MC_IOCFC = 6, /*!< FC - IO Controller (IOC) */ + BFI_MC_LL = 7, /*!< Link Layer */ + BFI_MC_UF = 8, /*!< Unsolicited frame receive */ + BFI_MC_FCXP = 9, /*!< FC Transport */ + BFI_MC_LPS = 10, /*!< lport fc login services */ + BFI_MC_RPORT = 11, /*!< Remote port */ + BFI_MC_ITNIM = 12, /*!< I-T nexus (Initiator mode) */ + BFI_MC_IOIM_READ = 13, /*!< read IO (Initiator mode) */ + BFI_MC_IOIM_WRITE = 14, /*!< write IO (Initiator mode) */ + BFI_MC_IOIM_IO = 15, /*!< IO (Initiator mode) */ + BFI_MC_IOIM = 16, /*!< IO (Initiator mode) */ + BFI_MC_IOIM_IOCOM = 17, /*!< good IO completion */ + BFI_MC_TSKIM = 18, /*!< Initiator Task management */ + BFI_MC_SBOOT = 19, /*!< SAN boot services */ + BFI_MC_IPFC = 20, /*!< IP over FC Msgs */ + BFI_MC_PORT = 21, /*!< Physical port */ + BFI_MC_SFP = 22, /*!< SFP module */ + BFI_MC_MSGQ = 23, /*!< MSGQ */ + BFI_MC_ENET = 24, /*!< ENET commands/responses */ + BFI_MC_MAX = 32 +}; + +#define BFI_IOC_MAX_CQS 4 +#define BFI_IOC_MAX_CQS_ASIC 8 +#define BFI_IOC_MSGLEN_MAX 32 /* 32 bytes */ + +#define BFI_BOOT_TYPE_OFF 8 +#define BFI_BOOT_PARAM_OFF 12 + +#define BFI_BOOT_TYPE_NORMAL 0 /* param is device id */ +#define BFI_BOOT_TYPE_FLASH 1 +#define BFI_BOOT_TYPE_MEMTEST 2 + +#define BFI_BOOT_MEMTEST_RES_ADDR 0x900 +#define BFI_BOOT_MEMTEST_RES_SIG 0xA0A1A2A3 + +/** + *---------------------------------------------------------------------- + * IOC + *---------------------------------------------------------------------- + */ + +enum bfi_ioc_h2i_msgs { + BFI_IOC_H2I_ENABLE_REQ = 1, + BFI_IOC_H2I_DISABLE_REQ = 2, + BFI_IOC_H2I_GETATTR_REQ = 3, + BFI_IOC_H2I_DBG_SYNC = 4, + BFI_IOC_H2I_DBG_DUMP = 5, +}; + +enum bfi_ioc_i2h_msgs { + BFI_IOC_I2H_ENABLE_REPLY = BFA_I2HM(1), + BFI_IOC_I2H_DISABLE_REPLY = BFA_I2HM(2), + BFI_IOC_I2H_GETATTR_REPLY = BFA_I2HM(3), + BFI_IOC_I2H_READY_EVENT = BFA_I2HM(4), + BFI_IOC_I2H_HBEAT = BFA_I2HM(5), +}; + +/** + * BFI_IOC_H2I_GETATTR_REQ message + */ +struct bfi_ioc_getattr_req { + struct bfi_mhdr mh; + union bfi_addr_u attr_addr; +}; + +struct bfi_ioc_attr { + u64 mfg_pwwn; /*!< Mfg port wwn */ + u64 mfg_nwwn; /*!< Mfg node wwn */ + mac_t mfg_mac; /*!< Mfg mac */ + u16 rsvd_a; + u64 pwwn; + u64 nwwn; + mac_t mac; /*!< PBC or Mfg mac */ + u16 rsvd_b; + mac_t fcoe_mac; + u16 rsvd_c; + char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)]; + u8 pcie_gen; + u8 pcie_lanes_orig; + u8 pcie_lanes; + u8 rx_bbcredit; /*!< receive buffer credits */ + u32 adapter_prop; /*!< adapter properties */ + u16 maxfrsize; /*!< max receive frame size */ + char asic_rev; + u8 rsvd_d; + char fw_version[BFA_VERSION_LEN]; + char optrom_version[BFA_VERSION_LEN]; + struct bfa_mfg_vpd vpd; + u32 card_type; /*!< card type */ +}; + +/** + * BFI_IOC_I2H_GETATTR_REPLY message + */ +struct bfi_ioc_getattr_reply { + struct bfi_mhdr mh; /*!< Common msg header */ + u8 status; /*!< cfg reply status */ + u8 rsvd[3]; +}; + +/** + * Firmware memory page offsets + */ +#define BFI_IOC_SMEM_PG0_CB (0x40) +#define BFI_IOC_SMEM_PG0_CT (0x180) + +/** + * Firmware statistic offset + */ +#define BFI_IOC_FWSTATS_OFF (0x6B40) +#define BFI_IOC_FWSTATS_SZ (4096) + +/** + * Firmware trace offset + */ +#define BFI_IOC_TRC_OFF (0x4b00) +#define BFI_IOC_TRC_ENTS 256 + +#define BFI_IOC_FW_SIGNATURE (0xbfadbfad) +#define BFI_IOC_MD5SUM_SZ 4 +struct bfi_ioc_image_hdr { + u32 signature; /*!< constant signature */ + u32 rsvd_a; + u32 exec; /*!< exec vector */ + u32 param; /*!< parameters */ + u32 rsvd_b[4]; + u32 md5sum[BFI_IOC_MD5SUM_SZ]; +}; + +/** + * BFI_IOC_I2H_READY_EVENT message + */ +struct bfi_ioc_rdy_event { + struct bfi_mhdr mh; /*!< common msg header */ + u8 init_status; /*!< init event status */ + u8 rsvd[3]; +}; + +struct bfi_ioc_hbeat { + struct bfi_mhdr mh; /*!< common msg header */ + u32 hb_count; /*!< current heart beat count */ +}; + +/** + * IOC hardware/firmware state + */ +enum bfi_ioc_state { + BFI_IOC_UNINIT = 0, /*!< not initialized */ + BFI_IOC_INITING = 1, /*!< h/w is being initialized */ + BFI_IOC_HWINIT = 2, /*!< h/w is initialized */ + BFI_IOC_CFG = 3, /*!< IOC configuration in progress */ + BFI_IOC_OP = 4, /*!< IOC is operational */ + BFI_IOC_DISABLING = 5, /*!< IOC is being disabled */ + BFI_IOC_DISABLED = 6, /*!< IOC is disabled */ + BFI_IOC_CFG_DISABLED = 7, /*!< IOC is being disabled;transient */ + BFI_IOC_FAIL = 8, /*!< IOC heart-beat failure */ + BFI_IOC_MEMTEST = 9, /*!< IOC is doing memtest */ +}; + +#define BFI_IOC_ENDIAN_SIG 0x12345678 + +enum { + BFI_ADAPTER_TYPE_FC = 0x01, /*!< FC adapters */ + BFI_ADAPTER_TYPE_MK = 0x0f0000, /*!< adapter type mask */ + BFI_ADAPTER_TYPE_SH = 16, /*!< adapter type shift */ + BFI_ADAPTER_NPORTS_MK = 0xff00, /*!< number of ports mask */ + BFI_ADAPTER_NPORTS_SH = 8, /*!< number of ports shift */ + BFI_ADAPTER_SPEED_MK = 0xff, /*!< adapter speed mask */ + BFI_ADAPTER_SPEED_SH = 0, /*!< adapter speed shift */ + BFI_ADAPTER_PROTO = 0x100000, /*!< prototype adapaters */ + BFI_ADAPTER_TTV = 0x200000, /*!< TTV debug capable */ + BFI_ADAPTER_UNSUPP = 0x400000, /*!< unknown adapter type */ +}; + +#define BFI_ADAPTER_GETP(__prop, __adap_prop) \ + (((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >> \ + BFI_ADAPTER_ ## __prop ## _SH) +#define BFI_ADAPTER_SETP(__prop, __val) \ + ((__val) << BFI_ADAPTER_ ## __prop ## _SH) +#define BFI_ADAPTER_IS_PROTO(__adap_type) \ + ((__adap_type) & BFI_ADAPTER_PROTO) +#define BFI_ADAPTER_IS_TTV(__adap_type) \ + ((__adap_type) & BFI_ADAPTER_TTV) +#define BFI_ADAPTER_IS_UNSUPP(__adap_type) \ + ((__adap_type) & BFI_ADAPTER_UNSUPP) +#define BFI_ADAPTER_IS_SPECIAL(__adap_type) \ + ((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO | \ + BFI_ADAPTER_UNSUPP)) + +/** + * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages + */ +struct bfi_ioc_ctrl_req { + struct bfi_mhdr mh; + u8 ioc_class; + u8 rsvd[3]; + u32 tv_sec; +}; + +/** + * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages + */ +struct bfi_ioc_ctrl_reply { + struct bfi_mhdr mh; /*!< Common msg header */ + u8 status; /*!< enable/disable status */ + u8 rsvd[3]; +}; + +#define BFI_IOC_MSGSZ 8 +/** + * H2I Messages + */ +union bfi_ioc_h2i_msg_u { + struct bfi_mhdr mh; + struct bfi_ioc_ctrl_req enable_req; + struct bfi_ioc_ctrl_req disable_req; + struct bfi_ioc_getattr_req getattr_req; + u32 mboxmsg[BFI_IOC_MSGSZ]; +}; + +/** + * I2H Messages + */ +union bfi_ioc_i2h_msg_u { + struct bfi_mhdr mh; + struct bfi_ioc_rdy_event rdy_event; + u32 mboxmsg[BFI_IOC_MSGSZ]; +}; + +#pragma pack() + +#endif /* __BFI_H__ */ diff --git a/drivers/net/bna/bfi_cna.h b/drivers/net/bna/bfi_cna.h new file mode 100644 index 000000000000..4eecabea397b --- /dev/null +++ b/drivers/net/bna/bfi_cna.h @@ -0,0 +1,199 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ +#ifndef __BFI_CNA_H__ +#define __BFI_CNA_H__ + +#include "bfi.h" +#include "bfa_defs_cna.h" + +#pragma pack(1) + +enum bfi_port_h2i { + BFI_PORT_H2I_ENABLE_REQ = (1), + BFI_PORT_H2I_DISABLE_REQ = (2), + BFI_PORT_H2I_GET_STATS_REQ = (3), + BFI_PORT_H2I_CLEAR_STATS_REQ = (4), +}; + +enum bfi_port_i2h { + BFI_PORT_I2H_ENABLE_RSP = BFA_I2HM(1), + BFI_PORT_I2H_DISABLE_RSP = BFA_I2HM(2), + BFI_PORT_I2H_GET_STATS_RSP = BFA_I2HM(3), + BFI_PORT_I2H_CLEAR_STATS_RSP = BFA_I2HM(4), +}; + +/** + * Generic REQ type + */ +struct bfi_port_generic_req { + struct bfi_mhdr mh; /*!< msg header */ + u32 msgtag; /*!< msgtag for reply */ + u32 rsvd; +}; + +/** + * Generic RSP type + */ +struct bfi_port_generic_rsp { + struct bfi_mhdr mh; /*!< common msg header */ + u8 status; /*!< port enable status */ + u8 rsvd[3]; + u32 msgtag; /*!< msgtag for reply */ +}; + +/** + * @todo + * BFI_PORT_H2I_ENABLE_REQ + */ + +/** + * @todo + * BFI_PORT_I2H_ENABLE_RSP + */ + +/** + * BFI_PORT_H2I_DISABLE_REQ + */ + +/** + * BFI_PORT_I2H_DISABLE_RSP + */ + +/** + * BFI_PORT_H2I_GET_STATS_REQ + */ +struct bfi_port_get_stats_req { + struct bfi_mhdr mh; /*!< common msg header */ + union bfi_addr_u dma_addr; +}; + +/** + * BFI_PORT_I2H_GET_STATS_RSP + */ + +/** + * BFI_PORT_H2I_CLEAR_STATS_REQ + */ + +/** + * BFI_PORT_I2H_CLEAR_STATS_RSP + */ + +union bfi_port_h2i_msg_u { + struct bfi_mhdr mh; + struct bfi_port_generic_req enable_req; + struct bfi_port_generic_req disable_req; + struct bfi_port_get_stats_req getstats_req; + struct bfi_port_generic_req clearstats_req; +}; + +union bfi_port_i2h_msg_u { + struct bfi_mhdr mh; + struct bfi_port_generic_rsp enable_rsp; + struct bfi_port_generic_rsp disable_rsp; + struct bfi_port_generic_rsp getstats_rsp; + struct bfi_port_generic_rsp clearstats_rsp; +}; + +/* @brief Mailbox commands from host to (DCBX/LLDP) firmware */ +enum bfi_cee_h2i_msgs { + BFI_CEE_H2I_GET_CFG_REQ = 1, + BFI_CEE_H2I_RESET_STATS = 2, + BFI_CEE_H2I_GET_STATS_REQ = 3, +}; + +/* @brief Mailbox reply and AEN messages from DCBX/LLDP firmware to host */ +enum bfi_cee_i2h_msgs { + BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1), + BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2), + BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3), +}; + +/* Data structures */ + +/* + * @brief H2I command structure for resetting the stats. + * BFI_CEE_H2I_RESET_STATS + */ +struct bfi_lldp_reset_stats { + struct bfi_mhdr mh; +}; + +/* + * @brief H2I command structure for resetting the stats. + * BFI_CEE_H2I_RESET_STATS + */ +struct bfi_cee_reset_stats { + struct bfi_mhdr mh; +}; + +/* + * @brief get configuration command from host + * BFI_CEE_H2I_GET_CFG_REQ + */ +struct bfi_cee_get_req { + struct bfi_mhdr mh; + union bfi_addr_u dma_addr; +}; + +/* + * @brief reply message from firmware + * BFI_CEE_I2H_GET_CFG_RSP + */ +struct bfi_cee_get_rsp { + struct bfi_mhdr mh; + u8 cmd_status; + u8 rsvd[3]; +}; + +/* + * @brief get configuration command from host + * BFI_CEE_H2I_GET_STATS_REQ + */ +struct bfi_cee_stats_req { + struct bfi_mhdr mh; + union bfi_addr_u dma_addr; +}; + +/* + * @brief reply message from firmware + * BFI_CEE_I2H_GET_STATS_RSP + */ +struct bfi_cee_stats_rsp { + struct bfi_mhdr mh; + u8 cmd_status; + u8 rsvd[3]; +}; + +/* @brief mailbox command structures from host to firmware */ +union bfi_cee_h2i_msg_u { + struct bfi_mhdr mh; + struct bfi_cee_get_req get_req; + struct bfi_cee_stats_req stats_req; +}; + +/* @brief mailbox message structures from firmware to host */ +union bfi_cee_i2h_msg_u { + struct bfi_mhdr mh; + struct bfi_cee_get_rsp get_rsp; + struct bfi_cee_stats_rsp stats_rsp; +}; + +#pragma pack() + +#endif /* __BFI_CNA_H__ */ diff --git a/drivers/net/bna/bfi_ctreg.h b/drivers/net/bna/bfi_ctreg.h new file mode 100644 index 000000000000..404ea351d4a1 --- /dev/null +++ b/drivers/net/bna/bfi_ctreg.h @@ -0,0 +1,637 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +/* + * bfi_ctreg.h catapult host block register definitions + * + * !!! Do not edit. Auto generated. !!! + */ + +#ifndef __BFI_CTREG_H__ +#define __BFI_CTREG_H__ + +#define HOSTFN0_LPU_MBOX0_0 0x00019200 +#define HOSTFN1_LPU_MBOX0_8 0x00019260 +#define LPU_HOSTFN0_MBOX0_0 0x00019280 +#define LPU_HOSTFN1_MBOX0_8 0x000192e0 +#define HOSTFN2_LPU_MBOX0_0 0x00019400 +#define HOSTFN3_LPU_MBOX0_8 0x00019460 +#define LPU_HOSTFN2_MBOX0_0 0x00019480 +#define LPU_HOSTFN3_MBOX0_8 0x000194e0 +#define HOSTFN0_INT_STATUS 0x00014000 +#define __HOSTFN0_HALT_OCCURRED 0x01000000 +#define __HOSTFN0_INT_STATUS_LVL_MK 0x00f00000 +#define __HOSTFN0_INT_STATUS_LVL_SH 20 +#define __HOSTFN0_INT_STATUS_LVL(_v) ((_v) << __HOSTFN0_INT_STATUS_LVL_SH) +#define __HOSTFN0_INT_STATUS_P_MK 0x000f0000 +#define __HOSTFN0_INT_STATUS_P_SH 16 +#define __HOSTFN0_INT_STATUS_P(_v) ((_v) << __HOSTFN0_INT_STATUS_P_SH) +#define __HOSTFN0_INT_STATUS_F 0x0000ffff +#define HOSTFN0_INT_MSK 0x00014004 +#define HOST_PAGE_NUM_FN0 0x00014008 +#define __HOST_PAGE_NUM_FN 0x000001ff +#define HOST_MSIX_ERR_INDEX_FN0 0x0001400c +#define __MSIX_ERR_INDEX_FN 0x000001ff +#define HOSTFN1_INT_STATUS 0x00014100 +#define __HOSTFN1_HALT_OCCURRED 0x01000000 +#define __HOSTFN1_INT_STATUS_LVL_MK 0x00f00000 +#define __HOSTFN1_INT_STATUS_LVL_SH 20 +#define __HOSTFN1_INT_STATUS_LVL(_v) ((_v) << __HOSTFN1_INT_STATUS_LVL_SH) +#define __HOSTFN1_INT_STATUS_P_MK 0x000f0000 +#define __HOSTFN1_INT_STATUS_P_SH 16 +#define __HOSTFN1_INT_STATUS_P(_v) ((_v) << __HOSTFN1_INT_STATUS_P_SH) +#define __HOSTFN1_INT_STATUS_F 0x0000ffff +#define HOSTFN1_INT_MSK 0x00014104 +#define HOST_PAGE_NUM_FN1 0x00014108 +#define HOST_MSIX_ERR_INDEX_FN1 0x0001410c +#define APP_PLL_425_CTL_REG 0x00014204 +#define __P_425_PLL_LOCK 0x80000000 +#define __APP_PLL_425_SRAM_USE_100MHZ 0x00100000 +#define __APP_PLL_425_RESET_TIMER_MK 0x000e0000 +#define __APP_PLL_425_RESET_TIMER_SH 17 +#define __APP_PLL_425_RESET_TIMER(_v) ((_v) << __APP_PLL_425_RESET_TIMER_SH) +#define __APP_PLL_425_LOGIC_SOFT_RESET 0x00010000 +#define __APP_PLL_425_CNTLMT0_1_MK 0x0000c000 +#define __APP_PLL_425_CNTLMT0_1_SH 14 +#define __APP_PLL_425_CNTLMT0_1(_v) ((_v) << __APP_PLL_425_CNTLMT0_1_SH) +#define __APP_PLL_425_JITLMT0_1_MK 0x00003000 +#define __APP_PLL_425_JITLMT0_1_SH 12 +#define __APP_PLL_425_JITLMT0_1(_v) ((_v) << __APP_PLL_425_JITLMT0_1_SH) +#define __APP_PLL_425_HREF 0x00000800 +#define __APP_PLL_425_HDIV 0x00000400 +#define __APP_PLL_425_P0_1_MK 0x00000300 +#define __APP_PLL_425_P0_1_SH 8 +#define __APP_PLL_425_P0_1(_v) ((_v) << __APP_PLL_425_P0_1_SH) +#define __APP_PLL_425_Z0_2_MK 0x000000e0 +#define __APP_PLL_425_Z0_2_SH 5 +#define __APP_PLL_425_Z0_2(_v) ((_v) << __APP_PLL_425_Z0_2_SH) +#define __APP_PLL_425_RSEL200500 0x00000010 +#define __APP_PLL_425_ENARST 0x00000008 +#define __APP_PLL_425_BYPASS 0x00000004 +#define __APP_PLL_425_LRESETN 0x00000002 +#define __APP_PLL_425_ENABLE 0x00000001 +#define APP_PLL_312_CTL_REG 0x00014208 +#define __P_312_PLL_LOCK 0x80000000 +#define __ENABLE_MAC_AHB_1 0x00800000 +#define __ENABLE_MAC_AHB_0 0x00400000 +#define __ENABLE_MAC_1 0x00200000 +#define __ENABLE_MAC_0 0x00100000 +#define __APP_PLL_312_RESET_TIMER_MK 0x000e0000 +#define __APP_PLL_312_RESET_TIMER_SH 17 +#define __APP_PLL_312_RESET_TIMER(_v) ((_v) << __APP_PLL_312_RESET_TIMER_SH) +#define __APP_PLL_312_LOGIC_SOFT_RESET 0x00010000 +#define __APP_PLL_312_CNTLMT0_1_MK 0x0000c000 +#define __APP_PLL_312_CNTLMT0_1_SH 14 +#define __APP_PLL_312_CNTLMT0_1(_v) ((_v) << __APP_PLL_312_CNTLMT0_1_SH) +#define __APP_PLL_312_JITLMT0_1_MK 0x00003000 +#define __APP_PLL_312_JITLMT0_1_SH 12 +#define __APP_PLL_312_JITLMT0_1(_v) ((_v) << __APP_PLL_312_JITLMT0_1_SH) +#define __APP_PLL_312_HREF 0x00000800 +#define __APP_PLL_312_HDIV 0x00000400 +#define __APP_PLL_312_P0_1_MK 0x00000300 +#define __APP_PLL_312_P0_1_SH 8 +#define __APP_PLL_312_P0_1(_v) ((_v) << __APP_PLL_312_P0_1_SH) +#define __APP_PLL_312_Z0_2_MK 0x000000e0 +#define __APP_PLL_312_Z0_2_SH 5 +#define __APP_PLL_312_Z0_2(_v) ((_v) << __APP_PLL_312_Z0_2_SH) +#define __APP_PLL_312_RSEL200500 0x00000010 +#define __APP_PLL_312_ENARST 0x00000008 +#define __APP_PLL_312_BYPASS 0x00000004 +#define __APP_PLL_312_LRESETN 0x00000002 +#define __APP_PLL_312_ENABLE 0x00000001 +#define MBIST_CTL_REG 0x00014220 +#define __EDRAM_BISTR_START 0x00000004 +#define __MBIST_RESET 0x00000002 +#define __MBIST_START 0x00000001 +#define MBIST_STAT_REG 0x00014224 +#define __EDRAM_BISTR_STATUS 0x00000008 +#define __EDRAM_BISTR_DONE 0x00000004 +#define __MEM_BIT_STATUS 0x00000002 +#define __MBIST_DONE 0x00000001 +#define HOST_SEM0_REG 0x00014230 +#define __HOST_SEMAPHORE 0x00000001 +#define HOST_SEM1_REG 0x00014234 +#define HOST_SEM2_REG 0x00014238 +#define HOST_SEM3_REG 0x0001423c +#define HOST_SEM0_INFO_REG 0x00014240 +#define HOST_SEM1_INFO_REG 0x00014244 +#define HOST_SEM2_INFO_REG 0x00014248 +#define HOST_SEM3_INFO_REG 0x0001424c +#define ETH_MAC_SER_REG 0x00014288 +#define __APP_EMS_CKBUFAMPIN 0x00000020 +#define __APP_EMS_REFCLKSEL 0x00000010 +#define __APP_EMS_CMLCKSEL 0x00000008 +#define __APP_EMS_REFCKBUFEN2 0x00000004 +#define __APP_EMS_REFCKBUFEN1 0x00000002 +#define __APP_EMS_CHANNEL_SEL 0x00000001 +#define HOSTFN2_INT_STATUS 0x00014300 +#define __HOSTFN2_HALT_OCCURRED 0x01000000 +#define __HOSTFN2_INT_STATUS_LVL_MK 0x00f00000 +#define __HOSTFN2_INT_STATUS_LVL_SH 20 +#define __HOSTFN2_INT_STATUS_LVL(_v) ((_v) << __HOSTFN2_INT_STATUS_LVL_SH) +#define __HOSTFN2_INT_STATUS_P_MK 0x000f0000 +#define __HOSTFN2_INT_STATUS_P_SH 16 +#define __HOSTFN2_INT_STATUS_P(_v) ((_v) << __HOSTFN2_INT_STATUS_P_SH) +#define __HOSTFN2_INT_STATUS_F 0x0000ffff +#define HOSTFN2_INT_MSK 0x00014304 +#define HOST_PAGE_NUM_FN2 0x00014308 +#define HOST_MSIX_ERR_INDEX_FN2 0x0001430c +#define HOSTFN3_INT_STATUS 0x00014400 +#define __HALT_OCCURRED 0x01000000 +#define __HOSTFN3_INT_STATUS_LVL_MK 0x00f00000 +#define __HOSTFN3_INT_STATUS_LVL_SH 20 +#define __HOSTFN3_INT_STATUS_LVL(_v) ((_v) << __HOSTFN3_INT_STATUS_LVL_SH) +#define __HOSTFN3_INT_STATUS_P_MK 0x000f0000 +#define __HOSTFN3_INT_STATUS_P_SH 16 +#define __HOSTFN3_INT_STATUS_P(_v) ((_v) << __HOSTFN3_INT_STATUS_P_SH) +#define __HOSTFN3_INT_STATUS_F 0x0000ffff +#define HOSTFN3_INT_MSK 0x00014404 +#define HOST_PAGE_NUM_FN3 0x00014408 +#define HOST_MSIX_ERR_INDEX_FN3 0x0001440c +#define FNC_ID_REG 0x00014600 +#define __FUNCTION_NUMBER 0x00000007 +#define FNC_PERS_REG 0x00014604 +#define __F3_FUNCTION_ACTIVE 0x80000000 +#define __F3_FUNCTION_MODE 0x40000000 +#define __F3_PORT_MAP_MK 0x30000000 +#define __F3_PORT_MAP_SH 28 +#define __F3_PORT_MAP(_v) ((_v) << __F3_PORT_MAP_SH) +#define __F3_VM_MODE 0x08000000 +#define __F3_INTX_STATUS_MK 0x07000000 +#define __F3_INTX_STATUS_SH 24 +#define __F3_INTX_STATUS(_v) ((_v) << __F3_INTX_STATUS_SH) +#define __F2_FUNCTION_ACTIVE 0x00800000 +#define __F2_FUNCTION_MODE 0x00400000 +#define __F2_PORT_MAP_MK 0x00300000 +#define __F2_PORT_MAP_SH 20 +#define __F2_PORT_MAP(_v) ((_v) << __F2_PORT_MAP_SH) +#define __F2_VM_MODE 0x00080000 +#define __F2_INTX_STATUS_MK 0x00070000 +#define __F2_INTX_STATUS_SH 16 +#define __F2_INTX_STATUS(_v) ((_v) << __F2_INTX_STATUS_SH) +#define __F1_FUNCTION_ACTIVE 0x00008000 +#define __F1_FUNCTION_MODE 0x00004000 +#define __F1_PORT_MAP_MK 0x00003000 +#define __F1_PORT_MAP_SH 12 +#define __F1_PORT_MAP(_v) ((_v) << __F1_PORT_MAP_SH) +#define __F1_VM_MODE 0x00000800 +#define __F1_INTX_STATUS_MK 0x00000700 +#define __F1_INTX_STATUS_SH 8 +#define __F1_INTX_STATUS(_v) ((_v) << __F1_INTX_STATUS_SH) +#define __F0_FUNCTION_ACTIVE 0x00000080 +#define __F0_FUNCTION_MODE 0x00000040 +#define __F0_PORT_MAP_MK 0x00000030 +#define __F0_PORT_MAP_SH 4 +#define __F0_PORT_MAP(_v) ((_v) << __F0_PORT_MAP_SH) +#define __F0_VM_MODE 0x00000008 +#define __F0_INTX_STATUS 0x00000007 +enum { + __F0_INTX_STATUS_MSIX = 0x0, + __F0_INTX_STATUS_INTA = 0x1, + __F0_INTX_STATUS_INTB = 0x2, + __F0_INTX_STATUS_INTC = 0x3, + __F0_INTX_STATUS_INTD = 0x4, +}; +#define OP_MODE 0x0001460c +#define __APP_ETH_CLK_LOWSPEED 0x00000004 +#define __GLOBAL_CORECLK_HALFSPEED 0x00000002 +#define __GLOBAL_FCOE_MODE 0x00000001 +#define HOST_SEM4_REG 0x00014610 +#define HOST_SEM5_REG 0x00014614 +#define HOST_SEM6_REG 0x00014618 +#define HOST_SEM7_REG 0x0001461c +#define HOST_SEM4_INFO_REG 0x00014620 +#define HOST_SEM5_INFO_REG 0x00014624 +#define HOST_SEM6_INFO_REG 0x00014628 +#define HOST_SEM7_INFO_REG 0x0001462c +#define HOSTFN0_LPU0_MBOX0_CMD_STAT 0x00019000 +#define __HOSTFN0_LPU0_MBOX0_INFO_MK 0xfffffffe +#define __HOSTFN0_LPU0_MBOX0_INFO_SH 1 +#define __HOSTFN0_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH) +#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001 +#define HOSTFN0_LPU1_MBOX0_CMD_STAT 0x00019004 +#define __HOSTFN0_LPU1_MBOX0_INFO_MK 0xfffffffe +#define __HOSTFN0_LPU1_MBOX0_INFO_SH 1 +#define __HOSTFN0_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH) +#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001 +#define LPU0_HOSTFN0_MBOX0_CMD_STAT 0x00019008 +#define __LPU0_HOSTFN0_MBOX0_INFO_MK 0xfffffffe +#define __LPU0_HOSTFN0_MBOX0_INFO_SH 1 +#define __LPU0_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH) +#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001 +#define LPU1_HOSTFN0_MBOX0_CMD_STAT 0x0001900c +#define __LPU1_HOSTFN0_MBOX0_INFO_MK 0xfffffffe +#define __LPU1_HOSTFN0_MBOX0_INFO_SH 1 +#define __LPU1_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH) +#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001 +#define HOSTFN1_LPU0_MBOX0_CMD_STAT 0x00019010 +#define __HOSTFN1_LPU0_MBOX0_INFO_MK 0xfffffffe +#define __HOSTFN1_LPU0_MBOX0_INFO_SH 1 +#define __HOSTFN1_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH) +#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001 +#define HOSTFN1_LPU1_MBOX0_CMD_STAT 0x00019014 +#define __HOSTFN1_LPU1_MBOX0_INFO_MK 0xfffffffe +#define __HOSTFN1_LPU1_MBOX0_INFO_SH 1 +#define __HOSTFN1_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH) +#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001 +#define LPU0_HOSTFN1_MBOX0_CMD_STAT 0x00019018 +#define __LPU0_HOSTFN1_MBOX0_INFO_MK 0xfffffffe +#define __LPU0_HOSTFN1_MBOX0_INFO_SH 1 +#define __LPU0_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH) +#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001 +#define LPU1_HOSTFN1_MBOX0_CMD_STAT 0x0001901c +#define __LPU1_HOSTFN1_MBOX0_INFO_MK 0xfffffffe +#define __LPU1_HOSTFN1_MBOX0_INFO_SH 1 +#define __LPU1_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH) +#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001 +#define HOSTFN2_LPU0_MBOX0_CMD_STAT 0x00019150 +#define __HOSTFN2_LPU0_MBOX0_INFO_MK 0xfffffffe +#define __HOSTFN2_LPU0_MBOX0_INFO_SH 1 +#define __HOSTFN2_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH) +#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001 +#define HOSTFN2_LPU1_MBOX0_CMD_STAT 0x00019154 +#define __HOSTFN2_LPU1_MBOX0_INFO_MK 0xfffffffe +#define __HOSTFN2_LPU1_MBOX0_INFO_SH 1 +#define __HOSTFN2_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH) +#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001 +#define LPU0_HOSTFN2_MBOX0_CMD_STAT 0x00019158 +#define __LPU0_HOSTFN2_MBOX0_INFO_MK 0xfffffffe +#define __LPU0_HOSTFN2_MBOX0_INFO_SH 1 +#define __LPU0_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH) +#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001 +#define LPU1_HOSTFN2_MBOX0_CMD_STAT 0x0001915c +#define __LPU1_HOSTFN2_MBOX0_INFO_MK 0xfffffffe +#define __LPU1_HOSTFN2_MBOX0_INFO_SH 1 +#define __LPU1_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH) +#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001 +#define HOSTFN3_LPU0_MBOX0_CMD_STAT 0x00019160 +#define __HOSTFN3_LPU0_MBOX0_INFO_MK 0xfffffffe +#define __HOSTFN3_LPU0_MBOX0_INFO_SH 1 +#define __HOSTFN3_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH) +#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001 +#define HOSTFN3_LPU1_MBOX0_CMD_STAT 0x00019164 +#define __HOSTFN3_LPU1_MBOX0_INFO_MK 0xfffffffe +#define __HOSTFN3_LPU1_MBOX0_INFO_SH 1 +#define __HOSTFN3_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH) +#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001 +#define LPU0_HOSTFN3_MBOX0_CMD_STAT 0x00019168 +#define __LPU0_HOSTFN3_MBOX0_INFO_MK 0xfffffffe +#define __LPU0_HOSTFN3_MBOX0_INFO_SH 1 +#define __LPU0_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH) +#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001 +#define LPU1_HOSTFN3_MBOX0_CMD_STAT 0x0001916c +#define __LPU1_HOSTFN3_MBOX0_INFO_MK 0xfffffffe +#define __LPU1_HOSTFN3_MBOX0_INFO_SH 1 +#define __LPU1_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH) +#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS 0x00000001 +#define FW_INIT_HALT_P0 0x000191ac +#define __FW_INIT_HALT_P 0x00000001 +#define FW_INIT_HALT_P1 0x000191bc +#define CPE_PI_PTR_Q0 0x00038000 +#define __CPE_PI_UNUSED_MK 0xffff0000 +#define __CPE_PI_UNUSED_SH 16 +#define __CPE_PI_UNUSED(_v) ((_v) << __CPE_PI_UNUSED_SH) +#define __CPE_PI_PTR 0x0000ffff +#define CPE_PI_PTR_Q1 0x00038040 +#define CPE_CI_PTR_Q0 0x00038004 +#define __CPE_CI_UNUSED_MK 0xffff0000 +#define __CPE_CI_UNUSED_SH 16 +#define __CPE_CI_UNUSED(_v) ((_v) << __CPE_CI_UNUSED_SH) +#define __CPE_CI_PTR 0x0000ffff +#define CPE_CI_PTR_Q1 0x00038044 +#define CPE_DEPTH_Q0 0x00038008 +#define __CPE_DEPTH_UNUSED_MK 0xf8000000 +#define __CPE_DEPTH_UNUSED_SH 27 +#define __CPE_DEPTH_UNUSED(_v) ((_v) << __CPE_DEPTH_UNUSED_SH) +#define __CPE_MSIX_VEC_INDEX_MK 0x07ff0000 +#define __CPE_MSIX_VEC_INDEX_SH 16 +#define __CPE_MSIX_VEC_INDEX(_v) ((_v) << __CPE_MSIX_VEC_INDEX_SH) +#define __CPE_DEPTH 0x0000ffff +#define CPE_DEPTH_Q1 0x00038048 +#define CPE_QCTRL_Q0 0x0003800c +#define __CPE_CTRL_UNUSED30_MK 0xfc000000 +#define __CPE_CTRL_UNUSED30_SH 26 +#define __CPE_CTRL_UNUSED30(_v) ((_v) << __CPE_CTRL_UNUSED30_SH) +#define __CPE_FUNC_INT_CTRL_MK 0x03000000 +#define __CPE_FUNC_INT_CTRL_SH 24 +#define __CPE_FUNC_INT_CTRL(_v) ((_v) << __CPE_FUNC_INT_CTRL_SH) +enum { + __CPE_FUNC_INT_CTRL_DISABLE = 0x0, + __CPE_FUNC_INT_CTRL_F2NF = 0x1, + __CPE_FUNC_INT_CTRL_3QUART = 0x2, + __CPE_FUNC_INT_CTRL_HALF = 0x3, +}; +#define __CPE_CTRL_UNUSED20_MK 0x00f00000 +#define __CPE_CTRL_UNUSED20_SH 20 +#define __CPE_CTRL_UNUSED20(_v) ((_v) << __CPE_CTRL_UNUSED20_SH) +#define __CPE_SCI_TH_MK 0x000f0000 +#define __CPE_SCI_TH_SH 16 +#define __CPE_SCI_TH(_v) ((_v) << __CPE_SCI_TH_SH) +#define __CPE_CTRL_UNUSED10_MK 0x0000c000 +#define __CPE_CTRL_UNUSED10_SH 14 +#define __CPE_CTRL_UNUSED10(_v) ((_v) << __CPE_CTRL_UNUSED10_SH) +#define __CPE_ACK_PENDING 0x00002000 +#define __CPE_CTRL_UNUSED40_MK 0x00001c00 +#define __CPE_CTRL_UNUSED40_SH 10 +#define __CPE_CTRL_UNUSED40(_v) ((_v) << __CPE_CTRL_UNUSED40_SH) +#define __CPE_PCIEID_MK 0x00000300 +#define __CPE_PCIEID_SH 8 +#define __CPE_PCIEID(_v) ((_v) << __CPE_PCIEID_SH) +#define __CPE_CTRL_UNUSED00_MK 0x000000fe +#define __CPE_CTRL_UNUSED00_SH 1 +#define __CPE_CTRL_UNUSED00(_v) ((_v) << __CPE_CTRL_UNUSED00_SH) +#define __CPE_ESIZE 0x00000001 +#define CPE_QCTRL_Q1 0x0003804c +#define __CPE_CTRL_UNUSED31_MK 0xfc000000 +#define __CPE_CTRL_UNUSED31_SH 26 +#define __CPE_CTRL_UNUSED31(_v) ((_v) << __CPE_CTRL_UNUSED31_SH) +#define __CPE_CTRL_UNUSED21_MK 0x00f00000 +#define __CPE_CTRL_UNUSED21_SH 20 +#define __CPE_CTRL_UNUSED21(_v) ((_v) << __CPE_CTRL_UNUSED21_SH) +#define __CPE_CTRL_UNUSED11_MK 0x0000c000 +#define __CPE_CTRL_UNUSED11_SH 14 +#define __CPE_CTRL_UNUSED11(_v) ((_v) << __CPE_CTRL_UNUSED11_SH) +#define __CPE_CTRL_UNUSED41_MK 0x00001c00 +#define __CPE_CTRL_UNUSED41_SH 10 +#define __CPE_CTRL_UNUSED41(_v) ((_v) << __CPE_CTRL_UNUSED41_SH) +#define __CPE_CTRL_UNUSED01_MK 0x000000fe +#define __CPE_CTRL_UNUSED01_SH 1 +#define __CPE_CTRL_UNUSED01(_v) ((_v) << __CPE_CTRL_UNUSED01_SH) +#define RME_PI_PTR_Q0 0x00038020 +#define __LATENCY_TIME_STAMP_MK 0xffff0000 +#define __LATENCY_TIME_STAMP_SH 16 +#define __LATENCY_TIME_STAMP(_v) ((_v) << __LATENCY_TIME_STAMP_SH) +#define __RME_PI_PTR 0x0000ffff +#define RME_PI_PTR_Q1 0x00038060 +#define RME_CI_PTR_Q0 0x00038024 +#define __DELAY_TIME_STAMP_MK 0xffff0000 +#define __DELAY_TIME_STAMP_SH 16 +#define __DELAY_TIME_STAMP(_v) ((_v) << __DELAY_TIME_STAMP_SH) +#define __RME_CI_PTR 0x0000ffff +#define RME_CI_PTR_Q1 0x00038064 +#define RME_DEPTH_Q0 0x00038028 +#define __RME_DEPTH_UNUSED_MK 0xf8000000 +#define __RME_DEPTH_UNUSED_SH 27 +#define __RME_DEPTH_UNUSED(_v) ((_v) << __RME_DEPTH_UNUSED_SH) +#define __RME_MSIX_VEC_INDEX_MK 0x07ff0000 +#define __RME_MSIX_VEC_INDEX_SH 16 +#define __RME_MSIX_VEC_INDEX(_v) ((_v) << __RME_MSIX_VEC_INDEX_SH) +#define __RME_DEPTH 0x0000ffff +#define RME_DEPTH_Q1 0x00038068 +#define RME_QCTRL_Q0 0x0003802c +#define __RME_INT_LATENCY_TIMER_MK 0xff000000 +#define __RME_INT_LATENCY_TIMER_SH 24 +#define __RME_INT_LATENCY_TIMER(_v) ((_v) << __RME_INT_LATENCY_TIMER_SH) +#define __RME_INT_DELAY_TIMER_MK 0x00ff0000 +#define __RME_INT_DELAY_TIMER_SH 16 +#define __RME_INT_DELAY_TIMER(_v) ((_v) << __RME_INT_DELAY_TIMER_SH) +#define __RME_INT_DELAY_DISABLE 0x00008000 +#define __RME_DLY_DELAY_DISABLE 0x00004000 +#define __RME_ACK_PENDING 0x00002000 +#define __RME_FULL_INTERRUPT_DISABLE 0x00001000 +#define __RME_CTRL_UNUSED10_MK 0x00000c00 +#define __RME_CTRL_UNUSED10_SH 10 +#define __RME_CTRL_UNUSED10(_v) ((_v) << __RME_CTRL_UNUSED10_SH) +#define __RME_PCIEID_MK 0x00000300 +#define __RME_PCIEID_SH 8 +#define __RME_PCIEID(_v) ((_v) << __RME_PCIEID_SH) +#define __RME_CTRL_UNUSED00_MK 0x000000fe +#define __RME_CTRL_UNUSED00_SH 1 +#define __RME_CTRL_UNUSED00(_v) ((_v) << __RME_CTRL_UNUSED00_SH) +#define __RME_ESIZE 0x00000001 +#define RME_QCTRL_Q1 0x0003806c +#define __RME_CTRL_UNUSED11_MK 0x00000c00 +#define __RME_CTRL_UNUSED11_SH 10 +#define __RME_CTRL_UNUSED11(_v) ((_v) << __RME_CTRL_UNUSED11_SH) +#define __RME_CTRL_UNUSED01_MK 0x000000fe +#define __RME_CTRL_UNUSED01_SH 1 +#define __RME_CTRL_UNUSED01(_v) ((_v) << __RME_CTRL_UNUSED01_SH) +#define PSS_CTL_REG 0x00018800 +#define __PSS_I2C_CLK_DIV_MK 0x007f0000 +#define __PSS_I2C_CLK_DIV_SH 16 +#define __PSS_I2C_CLK_DIV(_v) ((_v) << __PSS_I2C_CLK_DIV_SH) +#define __PSS_LMEM_INIT_DONE 0x00001000 +#define __PSS_LMEM_RESET 0x00000200 +#define __PSS_LMEM_INIT_EN 0x00000100 +#define __PSS_LPU1_RESET 0x00000002 +#define __PSS_LPU0_RESET 0x00000001 +#define PSS_ERR_STATUS_REG 0x00018810 +#define __PSS_LPU1_TCM_READ_ERR 0x00200000 +#define __PSS_LPU0_TCM_READ_ERR 0x00100000 +#define __PSS_LMEM5_CORR_ERR 0x00080000 +#define __PSS_LMEM4_CORR_ERR 0x00040000 +#define __PSS_LMEM3_CORR_ERR 0x00020000 +#define __PSS_LMEM2_CORR_ERR 0x00010000 +#define __PSS_LMEM1_CORR_ERR 0x00008000 +#define __PSS_LMEM0_CORR_ERR 0x00004000 +#define __PSS_LMEM5_UNCORR_ERR 0x00002000 +#define __PSS_LMEM4_UNCORR_ERR 0x00001000 +#define __PSS_LMEM3_UNCORR_ERR 0x00000800 +#define __PSS_LMEM2_UNCORR_ERR 0x00000400 +#define __PSS_LMEM1_UNCORR_ERR 0x00000200 +#define __PSS_LMEM0_UNCORR_ERR 0x00000100 +#define __PSS_BAL_PERR 0x00000080 +#define __PSS_DIP_IF_ERR 0x00000040 +#define __PSS_IOH_IF_ERR 0x00000020 +#define __PSS_TDS_IF_ERR 0x00000010 +#define __PSS_RDS_IF_ERR 0x00000008 +#define __PSS_SGM_IF_ERR 0x00000004 +#define __PSS_LPU1_RAM_ERR 0x00000002 +#define __PSS_LPU0_RAM_ERR 0x00000001 +#define ERR_SET_REG 0x00018818 +#define __PSS_ERR_STATUS_SET 0x003fffff +#define PMM_1T_RESET_REG_P0 0x0002381c +#define __PMM_1T_RESET_P 0x00000001 +#define PMM_1T_RESET_REG_P1 0x00023c1c +#define HQM_QSET0_RXQ_DRBL_P0 0x00038000 +#define __RXQ0_ADD_VECTORS_P 0x80000000 +#define __RXQ0_STOP_P 0x40000000 +#define __RXQ0_PRD_PTR_P 0x0000ffff +#define HQM_QSET1_RXQ_DRBL_P0 0x00038080 +#define __RXQ1_ADD_VECTORS_P 0x80000000 +#define __RXQ1_STOP_P 0x40000000 +#define __RXQ1_PRD_PTR_P 0x0000ffff +#define HQM_QSET0_RXQ_DRBL_P1 0x0003c000 +#define HQM_QSET1_RXQ_DRBL_P1 0x0003c080 +#define HQM_QSET0_TXQ_DRBL_P0 0x00038020 +#define __TXQ0_ADD_VECTORS_P 0x80000000 +#define __TXQ0_STOP_P 0x40000000 +#define __TXQ0_PRD_PTR_P 0x0000ffff +#define HQM_QSET1_TXQ_DRBL_P0 0x000380a0 +#define __TXQ1_ADD_VECTORS_P 0x80000000 +#define __TXQ1_STOP_P 0x40000000 +#define __TXQ1_PRD_PTR_P 0x0000ffff +#define HQM_QSET0_TXQ_DRBL_P1 0x0003c020 +#define HQM_QSET1_TXQ_DRBL_P1 0x0003c0a0 +#define HQM_QSET0_IB_DRBL_1_P0 0x00038040 +#define __IB1_0_ACK_P 0x80000000 +#define __IB1_0_DISABLE_P 0x40000000 +#define __IB1_0_COALESCING_CFG_P_MK 0x00ff0000 +#define __IB1_0_COALESCING_CFG_P_SH 16 +#define __IB1_0_COALESCING_CFG_P(_v) ((_v) << __IB1_0_COALESCING_CFG_P_SH) +#define __IB1_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff +#define HQM_QSET1_IB_DRBL_1_P0 0x000380c0 +#define __IB1_1_ACK_P 0x80000000 +#define __IB1_1_DISABLE_P 0x40000000 +#define __IB1_1_COALESCING_CFG_P_MK 0x00ff0000 +#define __IB1_1_COALESCING_CFG_P_SH 16 +#define __IB1_1_COALESCING_CFG_P(_v) ((_v) << __IB1_1_COALESCING_CFG_P_SH) +#define __IB1_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff +#define HQM_QSET0_IB_DRBL_1_P1 0x0003c040 +#define HQM_QSET1_IB_DRBL_1_P1 0x0003c0c0 +#define HQM_QSET0_IB_DRBL_2_P0 0x00038060 +#define __IB2_0_ACK_P 0x80000000 +#define __IB2_0_DISABLE_P 0x40000000 +#define __IB2_0_COALESCING_CFG_P_MK 0x00ff0000 +#define __IB2_0_COALESCING_CFG_P_SH 16 +#define __IB2_0_COALESCING_CFG_P(_v) ((_v) << __IB2_0_COALESCING_CFG_P_SH) +#define __IB2_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff +#define HQM_QSET1_IB_DRBL_2_P0 0x000380e0 +#define __IB2_1_ACK_P 0x80000000 +#define __IB2_1_DISABLE_P 0x40000000 +#define __IB2_1_COALESCING_CFG_P_MK 0x00ff0000 +#define __IB2_1_COALESCING_CFG_P_SH 16 +#define __IB2_1_COALESCING_CFG_P(_v) ((_v) << __IB2_1_COALESCING_CFG_P_SH) +#define __IB2_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff +#define HQM_QSET0_IB_DRBL_2_P1 0x0003c060 +#define HQM_QSET1_IB_DRBL_2_P1 0x0003c0e0 + +/* + * These definitions are either in error/missing in spec. Its auto-generated + * from hard coded values in regparse.pl. + */ +#define __EMPHPOST_AT_4G_MK_FIX 0x0000001c +#define __EMPHPOST_AT_4G_SH_FIX 0x00000002 +#define __EMPHPRE_AT_4G_FIX 0x00000003 +#define __SFP_TXRATE_EN_FIX 0x00000100 +#define __SFP_RXRATE_EN_FIX 0x00000080 + +/* + * These register definitions are auto-generated from hard coded values + * in regparse.pl. + */ + +/* + * These register mapping definitions are auto-generated from mapping tables + * in regparse.pl. + */ +#define BFA_IOC0_HBEAT_REG HOST_SEM0_INFO_REG +#define BFA_IOC0_STATE_REG HOST_SEM1_INFO_REG +#define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG +#define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG +#define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG + +#define CPE_DEPTH_Q(__n) \ + (CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0)) +#define CPE_QCTRL_Q(__n) \ + (CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0)) +#define CPE_PI_PTR_Q(__n) \ + (CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0)) +#define CPE_CI_PTR_Q(__n) \ + (CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0)) +#define RME_DEPTH_Q(__n) \ + (RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0)) +#define RME_QCTRL_Q(__n) \ + (RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0)) +#define RME_PI_PTR_Q(__n) \ + (RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0)) +#define RME_CI_PTR_Q(__n) \ + (RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0)) +#define HQM_QSET_RXQ_DRBL_P0(__n) (HQM_QSET0_RXQ_DRBL_P0 + (__n) \ + * (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0)) +#define HQM_QSET_TXQ_DRBL_P0(__n) (HQM_QSET0_TXQ_DRBL_P0 + (__n) \ + * (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0)) +#define HQM_QSET_IB_DRBL_1_P0(__n) (HQM_QSET0_IB_DRBL_1_P0 + (__n) \ + * (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0)) +#define HQM_QSET_IB_DRBL_2_P0(__n) (HQM_QSET0_IB_DRBL_2_P0 + (__n) \ + * (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0)) +#define HQM_QSET_RXQ_DRBL_P1(__n) (HQM_QSET0_RXQ_DRBL_P1 + (__n) \ + * (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1)) +#define HQM_QSET_TXQ_DRBL_P1(__n) (HQM_QSET0_TXQ_DRBL_P1 + (__n) \ + * (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1)) +#define HQM_QSET_IB_DRBL_1_P1(__n) (HQM_QSET0_IB_DRBL_1_P1 + (__n) \ + * (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1)) +#define HQM_QSET_IB_DRBL_2_P1(__n) (HQM_QSET0_IB_DRBL_2_P1 + (__n) \ + * (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1)) + +#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q)) +#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q)) +#define CPE_Q_MASK(__q) ((__q) & 0x3) +#define RME_Q_MASK(__q) ((__q) & 0x3) + +/* + * PCI MSI-X vector defines + */ +enum { + BFA_MSIX_CPE_Q0 = 0, + BFA_MSIX_CPE_Q1 = 1, + BFA_MSIX_CPE_Q2 = 2, + BFA_MSIX_CPE_Q3 = 3, + BFA_MSIX_RME_Q0 = 4, + BFA_MSIX_RME_Q1 = 5, + BFA_MSIX_RME_Q2 = 6, + BFA_MSIX_RME_Q3 = 7, + BFA_MSIX_LPU_ERR = 8, + BFA_MSIX_CT_MAX = 9, +}; + +/* + * And corresponding host interrupt status bit field defines + */ +#define __HFN_INT_CPE_Q0 0x00000001U +#define __HFN_INT_CPE_Q1 0x00000002U +#define __HFN_INT_CPE_Q2 0x00000004U +#define __HFN_INT_CPE_Q3 0x00000008U +#define __HFN_INT_CPE_Q4 0x00000010U +#define __HFN_INT_CPE_Q5 0x00000020U +#define __HFN_INT_CPE_Q6 0x00000040U +#define __HFN_INT_CPE_Q7 0x00000080U +#define __HFN_INT_RME_Q0 0x00000100U +#define __HFN_INT_RME_Q1 0x00000200U +#define __HFN_INT_RME_Q2 0x00000400U +#define __HFN_INT_RME_Q3 0x00000800U +#define __HFN_INT_RME_Q4 0x00001000U +#define __HFN_INT_RME_Q5 0x00002000U +#define __HFN_INT_RME_Q6 0x00004000U +#define __HFN_INT_RME_Q7 0x00008000U +#define __HFN_INT_ERR_EMC 0x00010000U +#define __HFN_INT_ERR_LPU0 0x00020000U +#define __HFN_INT_ERR_LPU1 0x00040000U +#define __HFN_INT_ERR_PSS 0x00080000U +#define __HFN_INT_MBOX_LPU0 0x00100000U +#define __HFN_INT_MBOX_LPU1 0x00200000U +#define __HFN_INT_MBOX1_LPU0 0x00400000U +#define __HFN_INT_MBOX1_LPU1 0x00800000U +#define __HFN_INT_LL_HALT 0x01000000U +#define __HFN_INT_CPE_MASK 0x000000ffU +#define __HFN_INT_RME_MASK 0x0000ff00U + +/* + * catapult memory map. + */ +#define LL_PGN_HQM0 0x0096 +#define LL_PGN_HQM1 0x0097 +#define PSS_SMEM_PAGE_START 0x8000 +#define PSS_SMEM_PGNUM(_pg0, _ma) ((_pg0) + ((_ma) >> 15)) +#define PSS_SMEM_PGOFF(_ma) ((_ma) & 0x7fff) + +/* + * End of catapult memory map + */ + +#endif /* __BFI_CTREG_H__ */ diff --git a/drivers/net/bna/bfi_ll.h b/drivers/net/bna/bfi_ll.h new file mode 100644 index 000000000000..bee4d054066a --- /dev/null +++ b/drivers/net/bna/bfi_ll.h @@ -0,0 +1,438 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ +#ifndef __BFI_LL_H__ +#define __BFI_LL_H__ + +#include "bfi.h" + +#pragma pack(1) + +/** + * @brief + * "enums" for all LL mailbox messages other than IOC + */ +enum { + BFI_LL_H2I_MAC_UCAST_SET_REQ = 1, + BFI_LL_H2I_MAC_UCAST_ADD_REQ = 2, + BFI_LL_H2I_MAC_UCAST_DEL_REQ = 3, + + BFI_LL_H2I_MAC_MCAST_ADD_REQ = 4, + BFI_LL_H2I_MAC_MCAST_DEL_REQ = 5, + BFI_LL_H2I_MAC_MCAST_FILTER_REQ = 6, + BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ = 7, + + BFI_LL_H2I_PORT_ADMIN_REQ = 8, + BFI_LL_H2I_STATS_GET_REQ = 9, + BFI_LL_H2I_STATS_CLEAR_REQ = 10, + + BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ = 11, + BFI_LL_H2I_RXF_DEFAULT_SET_REQ = 12, + + BFI_LL_H2I_TXQ_STOP_REQ = 13, + BFI_LL_H2I_RXQ_STOP_REQ = 14, + + BFI_LL_H2I_DIAG_LOOPBACK_REQ = 15, + + BFI_LL_H2I_SET_PAUSE_REQ = 16, + BFI_LL_H2I_MTU_INFO_REQ = 17, + + BFI_LL_H2I_RX_REQ = 18, +} ; + +enum { + BFI_LL_I2H_MAC_UCAST_SET_RSP = BFA_I2HM(1), + BFI_LL_I2H_MAC_UCAST_ADD_RSP = BFA_I2HM(2), + BFI_LL_I2H_MAC_UCAST_DEL_RSP = BFA_I2HM(3), + + BFI_LL_I2H_MAC_MCAST_ADD_RSP = BFA_I2HM(4), + BFI_LL_I2H_MAC_MCAST_DEL_RSP = BFA_I2HM(5), + BFI_LL_I2H_MAC_MCAST_FILTER_RSP = BFA_I2HM(6), + BFI_LL_I2H_MAC_MCAST_DEL_ALL_RSP = BFA_I2HM(7), + + BFI_LL_I2H_PORT_ADMIN_RSP = BFA_I2HM(8), + BFI_LL_I2H_STATS_GET_RSP = BFA_I2HM(9), + BFI_LL_I2H_STATS_CLEAR_RSP = BFA_I2HM(10), + + BFI_LL_I2H_RXF_PROMISCUOUS_SET_RSP = BFA_I2HM(11), + BFI_LL_I2H_RXF_DEFAULT_SET_RSP = BFA_I2HM(12), + + BFI_LL_I2H_TXQ_STOP_RSP = BFA_I2HM(13), + BFI_LL_I2H_RXQ_STOP_RSP = BFA_I2HM(14), + + BFI_LL_I2H_DIAG_LOOPBACK_RSP = BFA_I2HM(15), + + BFI_LL_I2H_SET_PAUSE_RSP = BFA_I2HM(16), + + BFI_LL_I2H_MTU_INFO_RSP = BFA_I2HM(17), + BFI_LL_I2H_RX_RSP = BFA_I2HM(18), + + BFI_LL_I2H_LINK_DOWN_AEN = BFA_I2HM(19), + BFI_LL_I2H_LINK_UP_AEN = BFA_I2HM(20), + + BFI_LL_I2H_PORT_ENABLE_AEN = BFA_I2HM(21), + BFI_LL_I2H_PORT_DISABLE_AEN = BFA_I2HM(22), +} ; + +/** + * @brief bfi_ll_mac_addr_req is used by: + * BFI_LL_H2I_MAC_UCAST_SET_REQ + * BFI_LL_H2I_MAC_UCAST_ADD_REQ + * BFI_LL_H2I_MAC_UCAST_DEL_REQ + * BFI_LL_H2I_MAC_MCAST_ADD_REQ + * BFI_LL_H2I_MAC_MCAST_DEL_REQ + */ +struct bfi_ll_mac_addr_req { + struct bfi_mhdr mh; /*!< common msg header */ + u8 rxf_id; + u8 rsvd1[3]; + mac_t mac_addr; + u8 rsvd2[2]; +}; + +/** + * @brief bfi_ll_mcast_filter_req is used by: + * BFI_LL_H2I_MAC_MCAST_FILTER_REQ + */ +struct bfi_ll_mcast_filter_req { + struct bfi_mhdr mh; /*!< common msg header */ + u8 rxf_id; + u8 enable; + u8 rsvd[2]; +}; + +/** + * @brief bfi_ll_mcast_del_all is used by: + * BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ + */ +struct bfi_ll_mcast_del_all_req { + struct bfi_mhdr mh; /*!< common msg header */ + u8 rxf_id; + u8 rsvd[3]; +}; + +/** + * @brief bfi_ll_q_stop_req is used by: + * BFI_LL_H2I_TXQ_STOP_REQ + * BFI_LL_H2I_RXQ_STOP_REQ + */ +struct bfi_ll_q_stop_req { + struct bfi_mhdr mh; /*!< common msg header */ + u32 q_id_mask[2]; /* !< bit-mask for queue ids */ +}; + +/** + * @brief bfi_ll_stats_req is used by: + * BFI_LL_I2H_STATS_GET_REQ + * BFI_LL_I2H_STATS_CLEAR_REQ + */ +struct bfi_ll_stats_req { + struct bfi_mhdr mh; /*!< common msg header */ + u16 stats_mask; /* !< bit-mask for non-function statistics */ + u8 rsvd[2]; + u32 rxf_id_mask[2]; /* !< bit-mask for RxF Statistics */ + u32 txf_id_mask[2]; /* !< bit-mask for TxF Statistics */ + union bfi_addr_u host_buffer; /* !< where statistics are returned */ +}; + +/** + * @brief defines for "stats_mask" above. + */ +#define BFI_LL_STATS_MAC (1 << 0) /* !< MAC Statistics */ +#define BFI_LL_STATS_BPC (1 << 1) /* !< Pause Stats from BPC */ +#define BFI_LL_STATS_RAD (1 << 2) /* !< Rx Admission Statistics */ +#define BFI_LL_STATS_RX_FC (1 << 3) /* !< Rx FC Stats from RxA */ +#define BFI_LL_STATS_TX_FC (1 << 4) /* !< Tx FC Stats from TxA */ + +#define BFI_LL_STATS_ALL 0x1f + +/** + * @brief bfi_ll_port_admin_req + */ +struct bfi_ll_port_admin_req { + struct bfi_mhdr mh; /*!< common msg header */ + u8 up; + u8 rsvd[3]; +}; + +/** + * @brief bfi_ll_rxf_req is used by: + * BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ + * BFI_LL_H2I_RXF_DEFAULT_SET_REQ + */ +struct bfi_ll_rxf_req { + struct bfi_mhdr mh; /*!< common msg header */ + u8 rxf_id; + u8 enable; + u8 rsvd[2]; +}; + +/** + * @brief bfi_ll_rxf_multi_req is used by: + * BFI_LL_H2I_RX_REQ + */ +struct bfi_ll_rxf_multi_req { + struct bfi_mhdr mh; /*!< common msg header */ + u32 rxf_id_mask[2]; + u8 enable; + u8 rsvd[3]; +}; + +/** + * @brief enum for Loopback opmodes + */ +enum { + BFI_LL_DIAG_LB_OPMODE_EXT = 0, + BFI_LL_DIAG_LB_OPMODE_CBL = 1, +}; + +/** + * @brief bfi_ll_set_pause_req is used by: + * BFI_LL_H2I_SET_PAUSE_REQ + */ +struct bfi_ll_set_pause_req { + struct bfi_mhdr mh; + u8 tx_pause; /* 1 = enable, 0 = disable */ + u8 rx_pause; /* 1 = enable, 0 = disable */ + u8 rsvd[2]; +}; + +/** + * @brief bfi_ll_mtu_info_req is used by: + * BFI_LL_H2I_MTU_INFO_REQ + */ +struct bfi_ll_mtu_info_req { + struct bfi_mhdr mh; + u16 mtu; + u8 rsvd[2]; +}; + +/** + * @brief + * Response header format used by all responses + * For both responses and asynchronous notifications + */ +struct bfi_ll_rsp { + struct bfi_mhdr mh; /*!< common msg header */ + u8 error; + u8 rsvd[3]; +}; + +/** + * @brief bfi_ll_cee_aen is used by: + * BFI_LL_I2H_LINK_DOWN_AEN + * BFI_LL_I2H_LINK_UP_AEN + */ +struct bfi_ll_aen { + struct bfi_mhdr mh; /*!< common msg header */ + u32 reason; + u8 cee_linkup; + u8 prio_map; /*!< LL priority bit-map */ + u8 rsvd[2]; +}; + +/** + * @brief + * The following error codes can be returned + * by the mbox commands + */ +enum { + BFI_LL_CMD_OK = 0, + BFI_LL_CMD_FAIL = 1, + BFI_LL_CMD_DUP_ENTRY = 2, /* !< Duplicate entry in CAM */ + BFI_LL_CMD_CAM_FULL = 3, /* !< CAM is full */ + BFI_LL_CMD_NOT_OWNER = 4, /* !< Not permitted, b'cos not owner */ + BFI_LL_CMD_NOT_EXEC = 5, /* !< Was not sent to f/w at all */ + BFI_LL_CMD_WAITING = 6, /* !< Waiting for completion (VMware) */ + BFI_LL_CMD_PORT_DISABLED = 7, /* !< port in disabled state */ +} ; + +/* Statistics */ +#define BFI_LL_TXF_ID_MAX 64 +#define BFI_LL_RXF_ID_MAX 64 + +/* TxF Frame Statistics */ +struct bfi_ll_stats_txf { + u64 ucast_octets; + u64 ucast; + u64 ucast_vlan; + + u64 mcast_octets; + u64 mcast; + u64 mcast_vlan; + + u64 bcast_octets; + u64 bcast; + u64 bcast_vlan; + + u64 errors; + u64 filter_vlan; /* frames filtered due to VLAN */ + u64 filter_mac_sa; /* frames filtered due to SA check */ +}; + +/* RxF Frame Statistics */ +struct bfi_ll_stats_rxf { + u64 ucast_octets; + u64 ucast; + u64 ucast_vlan; + + u64 mcast_octets; + u64 mcast; + u64 mcast_vlan; + + u64 bcast_octets; + u64 bcast; + u64 bcast_vlan; + u64 frame_drops; +}; + +/* FC Tx Frame Statistics */ +struct bfi_ll_stats_fc_tx { + u64 txf_ucast_octets; + u64 txf_ucast; + u64 txf_ucast_vlan; + + u64 txf_mcast_octets; + u64 txf_mcast; + u64 txf_mcast_vlan; + + u64 txf_bcast_octets; + u64 txf_bcast; + u64 txf_bcast_vlan; + + u64 txf_parity_errors; + u64 txf_timeout; + u64 txf_fid_parity_errors; +}; + +/* FC Rx Frame Statistics */ +struct bfi_ll_stats_fc_rx { + u64 rxf_ucast_octets; + u64 rxf_ucast; + u64 rxf_ucast_vlan; + + u64 rxf_mcast_octets; + u64 rxf_mcast; + u64 rxf_mcast_vlan; + + u64 rxf_bcast_octets; + u64 rxf_bcast; + u64 rxf_bcast_vlan; +}; + +/* RAD Frame Statistics */ +struct bfi_ll_stats_rad { + u64 rx_frames; + u64 rx_octets; + u64 rx_vlan_frames; + + u64 rx_ucast; + u64 rx_ucast_octets; + u64 rx_ucast_vlan; + + u64 rx_mcast; + u64 rx_mcast_octets; + u64 rx_mcast_vlan; + + u64 rx_bcast; + u64 rx_bcast_octets; + u64 rx_bcast_vlan; + + u64 rx_drops; +}; + +/* BPC Tx Registers */ +struct bfi_ll_stats_bpc { + /* transmit stats */ + u64 tx_pause[8]; + u64 tx_zero_pause[8]; /*!< Pause cancellation */ + /*!timer_mod)) + +/* MBOX API for PORT, TX, RX */ +#define bna_mbox_qe_fill(_qe, _cmd, _cmd_len, _cbfn, _cbarg) \ +do { \ + memcpy(&((_qe)->cmd.msg[0]), (_cmd), (_cmd_len)); \ + (_qe)->cbfn = (_cbfn); \ + (_qe)->cbarg = (_cbarg); \ +} while (0) + +#define bna_is_small_rxq(rcb) ((rcb)->id == 1) + +#define BNA_MAC_IS_EQUAL(_mac1, _mac2) \ + (!memcmp((_mac1), (_mac2), sizeof(mac_t))) + +#define BNA_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) + +#define BNA_TO_POWER_OF_2(x) \ +do { \ + int _shift = 0; \ + while ((x) && (x) != 1) { \ + (x) >>= 1; \ + _shift++; \ + } \ + (x) <<= _shift; \ +} while (0) + +#define BNA_TO_POWER_OF_2_HIGH(x) \ +do { \ + int n = 1; \ + while (n < (x)) \ + n <<= 1; \ + (x) = n; \ +} while (0) + +/* + * input : _addr-> os dma addr in host endian format, + * output : _bna_dma_addr-> pointer to hw dma addr + */ +#define BNA_SET_DMA_ADDR(_addr, _bna_dma_addr) \ +do { \ + u64 tmp_addr = \ + cpu_to_be64((u64)(_addr)); \ + (_bna_dma_addr)->msb = ((struct bna_dma_addr *)&tmp_addr)->msb; \ + (_bna_dma_addr)->lsb = ((struct bna_dma_addr *)&tmp_addr)->lsb; \ +} while (0) + +/* + * input : _bna_dma_addr-> pointer to hw dma addr + * output : _addr-> os dma addr in host endian format + */ +#define BNA_GET_DMA_ADDR(_bna_dma_addr, _addr) \ +do { \ + (_addr) = ((((u64)ntohl((_bna_dma_addr)->msb))) << 32) \ + | ((ntohl((_bna_dma_addr)->lsb) & 0xffffffff)); \ +} while (0) + +#define containing_rec(addr, type, field) \ + ((type *)((unsigned char *)(addr) - \ + (unsigned char *)(&((type *)0)->field))) + +#define BNA_TXQ_WI_NEEDED(_vectors) (((_vectors) + 3) >> 2) + +/* TxQ element is 64 bytes */ +#define BNA_TXQ_PAGE_INDEX_MAX (PAGE_SIZE >> 6) +#define BNA_TXQ_PAGE_INDEX_MAX_SHIFT (PAGE_SHIFT - 6) + +#define BNA_TXQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range) \ +{ \ + unsigned int page_index; /* index within a page */ \ + void *page_addr; \ + page_index = (_qe_idx) & (BNA_TXQ_PAGE_INDEX_MAX - 1); \ + (_qe_ptr_range) = (BNA_TXQ_PAGE_INDEX_MAX - page_index); \ + page_addr = (_qpt_ptr)[((_qe_idx) >> BNA_TXQ_PAGE_INDEX_MAX_SHIFT)];\ + (_qe_ptr) = &((struct bna_txq_entry *)(page_addr))[page_index]; \ +} + +/* RxQ element is 8 bytes */ +#define BNA_RXQ_PAGE_INDEX_MAX (PAGE_SIZE >> 3) +#define BNA_RXQ_PAGE_INDEX_MAX_SHIFT (PAGE_SHIFT - 3) + +#define BNA_RXQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range) \ +{ \ + unsigned int page_index; /* index within a page */ \ + void *page_addr; \ + page_index = (_qe_idx) & (BNA_RXQ_PAGE_INDEX_MAX - 1); \ + (_qe_ptr_range) = (BNA_RXQ_PAGE_INDEX_MAX - page_index); \ + page_addr = (_qpt_ptr)[((_qe_idx) >> \ + BNA_RXQ_PAGE_INDEX_MAX_SHIFT)]; \ + (_qe_ptr) = &((struct bna_rxq_entry *)(page_addr))[page_index]; \ +} + +/* CQ element is 16 bytes */ +#define BNA_CQ_PAGE_INDEX_MAX (PAGE_SIZE >> 4) +#define BNA_CQ_PAGE_INDEX_MAX_SHIFT (PAGE_SHIFT - 4) + +#define BNA_CQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range) \ +{ \ + unsigned int page_index; /* index within a page */ \ + void *page_addr; \ + \ + page_index = (_qe_idx) & (BNA_CQ_PAGE_INDEX_MAX - 1); \ + (_qe_ptr_range) = (BNA_CQ_PAGE_INDEX_MAX - page_index); \ + page_addr = (_qpt_ptr)[((_qe_idx) >> \ + BNA_CQ_PAGE_INDEX_MAX_SHIFT)]; \ + (_qe_ptr) = &((struct bna_cq_entry *)(page_addr))[page_index];\ +} + +#define BNA_QE_INDX_2_PTR(_cast, _qe_idx, _q_base) \ + (&((_cast *)(_q_base))[(_qe_idx)]) + +#define BNA_QE_INDX_RANGE(_qe_idx, _q_depth) ((_q_depth) - (_qe_idx)) + +#define BNA_QE_INDX_ADD(_qe_idx, _qe_num, _q_depth) \ + ((_qe_idx) = ((_qe_idx) + (_qe_num)) & ((_q_depth) - 1)) + +#define BNA_Q_INDEX_CHANGE(_old_idx, _updated_idx, _q_depth) \ + (((_updated_idx) - (_old_idx)) & ((_q_depth) - 1)) + +#define BNA_QE_FREE_CNT(_q_ptr, _q_depth) \ + (((_q_ptr)->consumer_index - (_q_ptr)->producer_index - 1) & \ + ((_q_depth) - 1)) + +#define BNA_QE_IN_USE_CNT(_q_ptr, _q_depth) \ + ((((_q_ptr)->producer_index - (_q_ptr)->consumer_index)) & \ + (_q_depth - 1)) + +#define BNA_Q_GET_CI(_q_ptr) ((_q_ptr)->q.consumer_index) + +#define BNA_Q_GET_PI(_q_ptr) ((_q_ptr)->q.producer_index) + +#define BNA_Q_PI_ADD(_q_ptr, _num) \ + (_q_ptr)->q.producer_index = \ + (((_q_ptr)->q.producer_index + (_num)) & \ + ((_q_ptr)->q.q_depth - 1)) + +#define BNA_Q_CI_ADD(_q_ptr, _num) \ + (_q_ptr)->q.consumer_index = \ + (((_q_ptr)->q.consumer_index + (_num)) \ + & ((_q_ptr)->q.q_depth - 1)) + +#define BNA_Q_FREE_COUNT(_q_ptr) \ + (BNA_QE_FREE_CNT(&((_q_ptr)->q), (_q_ptr)->q.q_depth)) + +#define BNA_Q_IN_USE_COUNT(_q_ptr) \ + (BNA_QE_IN_USE_CNT(&(_q_ptr)->q, (_q_ptr)->q.q_depth)) + +/* These macros build the data portion of the TxQ/RxQ doorbell */ +#define BNA_DOORBELL_Q_PRD_IDX(_pi) (0x80000000 | (_pi)) +#define BNA_DOORBELL_Q_STOP (0x40000000) + +/* These macros build the data portion of the IB doorbell */ +#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \ + (0x80000000 | ((_timeout) << 16) | (_events)) +#define BNA_DOORBELL_IB_INT_DISABLE (0x40000000) + +/* Set the coalescing timer for the given ib */ +#define bna_ib_coalescing_timer_set(_i_dbell, _cls_timer) \ + ((_i_dbell)->doorbell_ack = BNA_DOORBELL_IB_INT_ACK((_cls_timer), 0)); + +/* Acks 'events' # of events for a given ib */ +#define bna_ib_ack(_i_dbell, _events) \ + (writel(((_i_dbell)->doorbell_ack | (_events)), \ + (_i_dbell)->doorbell_addr)); + +#define bna_txq_prod_indx_doorbell(_tcb) \ + (writel(BNA_DOORBELL_Q_PRD_IDX((_tcb)->producer_index), \ + (_tcb)->q_dbell)); + +#define bna_rxq_prod_indx_doorbell(_rcb) \ + (writel(BNA_DOORBELL_Q_PRD_IDX((_rcb)->producer_index), \ + (_rcb)->q_dbell)); + +#define BNA_LARGE_PKT_SIZE 1000 + +#define BNA_UPDATE_PKT_CNT(_pkt, _len) \ +do { \ + if ((_len) > BNA_LARGE_PKT_SIZE) { \ + (_pkt)->large_pkt_cnt++; \ + } else { \ + (_pkt)->small_pkt_cnt++; \ + } \ +} while (0) + +#define call_rxf_stop_cbfn(rxf, status) \ + if ((rxf)->stop_cbfn) { \ + (*(rxf)->stop_cbfn)((rxf)->stop_cbarg, (status)); \ + (rxf)->stop_cbfn = NULL; \ + (rxf)->stop_cbarg = NULL; \ + } + +#define call_rxf_start_cbfn(rxf, status) \ + if ((rxf)->start_cbfn) { \ + (*(rxf)->start_cbfn)((rxf)->start_cbarg, (status)); \ + (rxf)->start_cbfn = NULL; \ + (rxf)->start_cbarg = NULL; \ + } + +#define call_rxf_cam_fltr_cbfn(rxf, status) \ + if ((rxf)->cam_fltr_cbfn) { \ + (*(rxf)->cam_fltr_cbfn)((rxf)->cam_fltr_cbarg, rxf->rx, \ + (status)); \ + (rxf)->cam_fltr_cbfn = NULL; \ + (rxf)->cam_fltr_cbarg = NULL; \ + } + +#define call_rxf_pause_cbfn(rxf, status) \ + if ((rxf)->oper_state_cbfn) { \ + (*(rxf)->oper_state_cbfn)((rxf)->oper_state_cbarg, rxf->rx,\ + (status)); \ + (rxf)->rxf_flags &= ~BNA_RXF_FL_OPERSTATE_CHANGED; \ + (rxf)->oper_state_cbfn = NULL; \ + (rxf)->oper_state_cbarg = NULL; \ + } + +#define call_rxf_resume_cbfn(rxf, status) call_rxf_pause_cbfn(rxf, status) + +#define is_xxx_enable(mode, bitmask, xxx) ((bitmask & xxx) && (mode & xxx)) + +#define is_xxx_disable(mode, bitmask, xxx) ((bitmask & xxx) && !(mode & xxx)) + +#define xxx_enable(mode, bitmask, xxx) \ +do { \ + bitmask |= xxx; \ + mode |= xxx; \ +} while (0) + +#define xxx_disable(mode, bitmask, xxx) \ +do { \ + bitmask |= xxx; \ + mode &= ~xxx; \ +} while (0) + +#define xxx_inactive(mode, bitmask, xxx) \ +do { \ + bitmask &= ~xxx; \ + mode &= ~xxx; \ +} while (0) + +#define is_promisc_enable(mode, bitmask) \ + is_xxx_enable(mode, bitmask, BNA_RXMODE_PROMISC) + +#define is_promisc_disable(mode, bitmask) \ + is_xxx_disable(mode, bitmask, BNA_RXMODE_PROMISC) + +#define promisc_enable(mode, bitmask) \ + xxx_enable(mode, bitmask, BNA_RXMODE_PROMISC) + +#define promisc_disable(mode, bitmask) \ + xxx_disable(mode, bitmask, BNA_RXMODE_PROMISC) + +#define promisc_inactive(mode, bitmask) \ + xxx_inactive(mode, bitmask, BNA_RXMODE_PROMISC) + +#define is_default_enable(mode, bitmask) \ + is_xxx_enable(mode, bitmask, BNA_RXMODE_DEFAULT) + +#define is_default_disable(mode, bitmask) \ + is_xxx_disable(mode, bitmask, BNA_RXMODE_DEFAULT) + +#define default_enable(mode, bitmask) \ + xxx_enable(mode, bitmask, BNA_RXMODE_DEFAULT) + +#define default_disable(mode, bitmask) \ + xxx_disable(mode, bitmask, BNA_RXMODE_DEFAULT) + +#define default_inactive(mode, bitmask) \ + xxx_inactive(mode, bitmask, BNA_RXMODE_DEFAULT) + +#define is_allmulti_enable(mode, bitmask) \ + is_xxx_enable(mode, bitmask, BNA_RXMODE_ALLMULTI) + +#define is_allmulti_disable(mode, bitmask) \ + is_xxx_disable(mode, bitmask, BNA_RXMODE_ALLMULTI) + +#define allmulti_enable(mode, bitmask) \ + xxx_enable(mode, bitmask, BNA_RXMODE_ALLMULTI) + +#define allmulti_disable(mode, bitmask) \ + xxx_disable(mode, bitmask, BNA_RXMODE_ALLMULTI) + +#define allmulti_inactive(mode, bitmask) \ + xxx_inactive(mode, bitmask, BNA_RXMODE_ALLMULTI) + +#define GET_RXQS(rxp, q0, q1) do { \ + switch ((rxp)->type) { \ + case BNA_RXP_SINGLE: \ + (q0) = rxp->rxq.single.only; \ + (q1) = NULL; \ + break; \ + case BNA_RXP_SLR: \ + (q0) = rxp->rxq.slr.large; \ + (q1) = rxp->rxq.slr.small; \ + break; \ + case BNA_RXP_HDS: \ + (q0) = rxp->rxq.hds.data; \ + (q1) = rxp->rxq.hds.hdr; \ + break; \ + } \ +} while (0) + +/** + * + * Function prototypes + * + */ + +/** + * BNA + */ + +/* Internal APIs */ +void bna_adv_res_req(struct bna_res_info *res_info); + +/* APIs for BNAD */ +void bna_res_req(struct bna_res_info *res_info); +void bna_init(struct bna *bna, struct bnad *bnad, + struct bfa_pcidev *pcidev, + struct bna_res_info *res_info); +void bna_uninit(struct bna *bna); +void bna_stats_get(struct bna *bna); +void bna_stats_clr(struct bna *bna); +void bna_get_perm_mac(struct bna *bna, u8 *mac); + +/* APIs for Rx */ +int bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size); + +/* APIs for RxF */ +struct bna_mac *bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod); +void bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod, + struct bna_mac *mac); +struct bna_mac *bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod); +void bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod, + struct bna_mac *mac); +struct bna_rit_segment * +bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size); +void bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod, + struct bna_rit_segment *seg); + +/** + * DEVICE + */ + +/* Interanl APIs */ +void bna_adv_device_init(struct bna_device *device, struct bna *bna, + struct bna_res_info *res_info); + +/* APIs for BNA */ +void bna_device_init(struct bna_device *device, struct bna *bna, + struct bna_res_info *res_info); +void bna_device_uninit(struct bna_device *device); +void bna_device_cb_port_stopped(void *arg, enum bna_cb_status status); +int bna_device_status_get(struct bna_device *device); +int bna_device_state_get(struct bna_device *device); + +/* APIs for BNAD */ +void bna_device_enable(struct bna_device *device); +void bna_device_disable(struct bna_device *device, + enum bna_cleanup_type type); + +/** + * MBOX + */ + +/* APIs for DEVICE */ +void bna_mbox_mod_init(struct bna_mbox_mod *mbox_mod, struct bna *bna); +void bna_mbox_mod_uninit(struct bna_mbox_mod *mbox_mod); +void bna_mbox_mod_start(struct bna_mbox_mod *mbox_mod); +void bna_mbox_mod_stop(struct bna_mbox_mod *mbox_mod); + +/* APIs for PORT, TX, RX */ +void bna_mbox_handler(struct bna *bna, u32 intr_status); +void bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe); + +/** + * PORT + */ + +/* APIs for BNA */ +void bna_port_init(struct bna_port *port, struct bna *bna); +void bna_port_uninit(struct bna_port *port); +int bna_port_state_get(struct bna_port *port); +int bna_llport_state_get(struct bna_llport *llport); + +/* APIs for DEVICE */ +void bna_port_start(struct bna_port *port); +void bna_port_stop(struct bna_port *port); +void bna_port_fail(struct bna_port *port); + +/* API for RX */ +int bna_port_mtu_get(struct bna_port *port); +void bna_llport_admin_up(struct bna_llport *llport); +void bna_llport_admin_down(struct bna_llport *llport); + +/* API for BNAD */ +void bna_port_enable(struct bna_port *port); +void bna_port_disable(struct bna_port *port, enum bna_cleanup_type type, + void (*cbfn)(void *, enum bna_cb_status)); +void bna_port_pause_config(struct bna_port *port, + struct bna_pause_config *pause_config, + void (*cbfn)(struct bnad *, enum bna_cb_status)); +void bna_port_mtu_set(struct bna_port *port, int mtu, + void (*cbfn)(struct bnad *, enum bna_cb_status)); +void bna_port_mac_get(struct bna_port *port, mac_t *mac); +void bna_port_type_set(struct bna_port *port, enum bna_port_type type); +void bna_port_linkcbfn_set(struct bna_port *port, + void (*linkcbfn)(struct bnad *, + enum bna_link_status)); +void bna_port_admin_up(struct bna_port *port); +void bna_port_admin_down(struct bna_port *port); + +/* Callbacks for TX, RX */ +void bna_port_cb_tx_stopped(struct bna_port *port, + enum bna_cb_status status); +void bna_port_cb_rx_stopped(struct bna_port *port, + enum bna_cb_status status); + +/* Callbacks for MBOX */ +void bna_port_cb_link_up(struct bna_port *port, struct bfi_ll_aen *aen, + int status); +void bna_port_cb_link_down(struct bna_port *port, int status); + +/** + * IB + */ + +/* APIs for BNA */ +void bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna, + struct bna_res_info *res_info); +void bna_ib_mod_uninit(struct bna_ib_mod *ib_mod); + +/* APIs for TX, RX */ +struct bna_ib *bna_ib_get(struct bna_ib_mod *ib_mod, + enum bna_intr_type intr_type, int vector); +void bna_ib_put(struct bna_ib_mod *ib_mod, struct bna_ib *ib); +int bna_ib_reserve_idx(struct bna_ib *ib); +void bna_ib_release_idx(struct bna_ib *ib, int idx); +int bna_ib_config(struct bna_ib *ib, struct bna_ib_config *ib_config); +void bna_ib_start(struct bna_ib *ib); +void bna_ib_stop(struct bna_ib *ib); +void bna_ib_fail(struct bna_ib *ib); +void bna_ib_coalescing_timeo_set(struct bna_ib *ib, u8 coalescing_timeo); + +/** + * TX MODULE AND TX + */ + +/* Internal APIs */ +void bna_tx_prio_changed(struct bna_tx *tx, int prio); + +/* APIs for BNA */ +void bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna, + struct bna_res_info *res_info); +void bna_tx_mod_uninit(struct bna_tx_mod *tx_mod); +int bna_tx_state_get(struct bna_tx *tx); + +/* APIs for PORT */ +void bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type); +void bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type); +void bna_tx_mod_fail(struct bna_tx_mod *tx_mod); +void bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio); +void bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link); + +/* APIs for BNAD */ +void bna_tx_res_req(int num_txq, int txq_depth, + struct bna_res_info *res_info); +struct bna_tx *bna_tx_create(struct bna *bna, struct bnad *bnad, + struct bna_tx_config *tx_cfg, + struct bna_tx_event_cbfn *tx_cbfn, + struct bna_res_info *res_info, void *priv); +void bna_tx_destroy(struct bna_tx *tx); +void bna_tx_enable(struct bna_tx *tx); +void bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type, + void (*cbfn)(void *, struct bna_tx *, + enum bna_cb_status)); +enum bna_cb_status +bna_tx_prio_set(struct bna_tx *tx, int prio, + void (*cbfn)(struct bnad *, struct bna_tx *, + enum bna_cb_status)); +void bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo); + +/** + * RX MODULE, RX, RXF + */ + +/* Internal APIs */ +void rxf_cb_cam_fltr_mbox_cmd(void *arg, int status); +void rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd, + const struct bna_mac *mac_addr); +void __rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status); +void bna_rxf_adv_init(struct bna_rxf *rxf, + struct bna_rx *rx, + struct bna_rx_config *q_config); +int rxf_process_packet_filter_ucast(struct bna_rxf *rxf); +int rxf_process_packet_filter_promisc(struct bna_rxf *rxf); +int rxf_process_packet_filter_default(struct bna_rxf *rxf); +int rxf_process_packet_filter_allmulti(struct bna_rxf *rxf); +int rxf_clear_packet_filter_ucast(struct bna_rxf *rxf); +int rxf_clear_packet_filter_promisc(struct bna_rxf *rxf); +int rxf_clear_packet_filter_default(struct bna_rxf *rxf); +int rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf); +void rxf_reset_packet_filter_ucast(struct bna_rxf *rxf); +void rxf_reset_packet_filter_promisc(struct bna_rxf *rxf); +void rxf_reset_packet_filter_default(struct bna_rxf *rxf); +void rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf); + +/* APIs for BNA */ +void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna, + struct bna_res_info *res_info); +void bna_rx_mod_uninit(struct bna_rx_mod *rx_mod); +int bna_rx_state_get(struct bna_rx *rx); +int bna_rxf_state_get(struct bna_rxf *rxf); + +/* APIs for PORT */ +void bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type); +void bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type); +void bna_rx_mod_fail(struct bna_rx_mod *rx_mod); + +/* APIs for BNAD */ +void bna_rx_res_req(struct bna_rx_config *rx_config, + struct bna_res_info *res_info); +struct bna_rx *bna_rx_create(struct bna *bna, struct bnad *bnad, + struct bna_rx_config *rx_cfg, + struct bna_rx_event_cbfn *rx_cbfn, + struct bna_res_info *res_info, void *priv); +void bna_rx_destroy(struct bna_rx *rx); +void bna_rx_enable(struct bna_rx *rx); +void bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type, + void (*cbfn)(void *, struct bna_rx *, + enum bna_cb_status)); +void bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo); +void bna_rx_dim_reconfig(struct bna *bna, u32 vector[][BNA_BIAS_T_MAX]); +void bna_rx_dim_update(struct bna_ccb *ccb); +enum bna_cb_status +bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); +enum bna_cb_status +bna_rx_ucast_add(struct bna_rx *rx, u8* ucmac, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); +enum bna_cb_status +bna_rx_ucast_del(struct bna_rx *rx, u8 *ucmac, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); +enum bna_cb_status +bna_rx_mcast_add(struct bna_rx *rx, u8 *mcmac, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); +enum bna_cb_status +bna_rx_mcast_del(struct bna_rx *rx, u8 *mcmac, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); +enum bna_cb_status +bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mcmac, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); +void bna_rx_mcast_delall(struct bna_rx *rx, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); +enum bna_cb_status +bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode rxmode, + enum bna_rxmode bitmask, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); +void bna_rx_vlan_add(struct bna_rx *rx, int vlan_id); +void bna_rx_vlan_del(struct bna_rx *rx, int vlan_id); +void bna_rx_vlanfilter_enable(struct bna_rx *rx); +void bna_rx_vlanfilter_disable(struct bna_rx *rx); +void bna_rx_rss_enable(struct bna_rx *rx); +void bna_rx_rss_disable(struct bna_rx *rx); +void bna_rx_rss_reconfig(struct bna_rx *rx, struct bna_rxf_rss *rss_config); +void bna_rx_rss_rit_set(struct bna_rx *rx, unsigned int *vectors, + int nvectors); +void bna_rx_hds_enable(struct bna_rx *rx, struct bna_rxf_hds *hds_config, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); +void bna_rx_hds_disable(struct bna_rx *rx, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); +void bna_rx_receive_pause(struct bna_rx *rx, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); +void bna_rx_receive_resume(struct bna_rx *rx, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)); + +/* RxF APIs for RX */ +void bna_rxf_start(struct bna_rxf *rxf); +void bna_rxf_stop(struct bna_rxf *rxf); +void bna_rxf_fail(struct bna_rxf *rxf); +void bna_rxf_init(struct bna_rxf *rxf, struct bna_rx *rx, + struct bna_rx_config *q_config); +void bna_rxf_uninit(struct bna_rxf *rxf); + +/* Callback from RXF to RX */ +void bna_rx_cb_rxf_stopped(struct bna_rx *rx, enum bna_cb_status); +void bna_rx_cb_rxf_started(struct bna_rx *rx, enum bna_cb_status); + +/** + * BNAD + */ + +/* Callbacks for BNA */ +void bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status, + struct bna_stats *stats); +void bnad_cb_stats_clr(struct bnad *bnad); + +/* Callbacks for DEVICE */ +void bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status); +void bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status); +void bnad_cb_device_enable_mbox_intr(struct bnad *bnad); +void bnad_cb_device_disable_mbox_intr(struct bnad *bnad); + +/* Callbacks for port */ +void bnad_cb_port_link_status(struct bnad *bnad, + enum bna_link_status status); + +#endif /* __BNA_H__ */ diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c new file mode 100644 index 000000000000..9d41ebf41cf4 --- /dev/null +++ b/drivers/net/bna/bna_ctrl.c @@ -0,0 +1,3626 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ +#include "bna.h" +#include "bfa_sm.h" +#include "bfa_wc.h" + +/** + * MBOX + */ +static int +bna_is_aen(u8 msg_id) +{ + return (msg_id == BFI_LL_I2H_LINK_DOWN_AEN || + msg_id == BFI_LL_I2H_LINK_UP_AEN); +} + +static void +bna_mbox_aen_callback(struct bna *bna, struct bfi_mbmsg *msg) +{ + struct bfi_ll_aen *aen = (struct bfi_ll_aen *)(msg); + + switch (aen->mh.msg_id) { + case BFI_LL_I2H_LINK_UP_AEN: + bna_port_cb_link_up(&bna->port, aen, aen->reason); + break; + case BFI_LL_I2H_LINK_DOWN_AEN: + bna_port_cb_link_down(&bna->port, aen->reason); + break; + default: + break; + } +} + +static void +bna_ll_isr(void *llarg, struct bfi_mbmsg *msg) +{ + struct bna *bna = (struct bna *)(llarg); + struct bfi_ll_rsp *mb_rsp = (struct bfi_ll_rsp *)(msg); + struct bfi_mhdr *cmd_h, *rsp_h; + struct bna_mbox_qe *mb_qe = NULL; + int to_post = 0; + u8 aen = 0; + char message[BNA_MESSAGE_SIZE]; + + aen = bna_is_aen(mb_rsp->mh.msg_id); + + if (!aen) { + mb_qe = bfa_q_first(&bna->mbox_mod.posted_q); + cmd_h = (struct bfi_mhdr *)(&mb_qe->cmd.msg[0]); + rsp_h = (struct bfi_mhdr *)(&mb_rsp->mh); + + if ((BFA_I2HM(cmd_h->msg_id) == rsp_h->msg_id) && + (cmd_h->mtag.i2htok == rsp_h->mtag.i2htok)) { + /* Remove the request from posted_q, update state */ + list_del(&mb_qe->qe); + bna->mbox_mod.msg_pending--; + if (list_empty(&bna->mbox_mod.posted_q)) + bna->mbox_mod.state = BNA_MBOX_FREE; + else + to_post = 1; + + /* Dispatch the cbfn */ + if (mb_qe->cbfn) + mb_qe->cbfn(mb_qe->cbarg, mb_rsp->error); + + /* Post the next entry, if needed */ + if (to_post) { + mb_qe = bfa_q_first(&bna->mbox_mod.posted_q); + bfa_ioc_mbox_queue(&bna->device.ioc, + &mb_qe->cmd); + } + } else { + snprintf(message, BNA_MESSAGE_SIZE, + "No matching rsp for [%d:%d:%d]\n", + mb_rsp->mh.msg_class, mb_rsp->mh.msg_id, + mb_rsp->mh.mtag.i2htok); + pr_info("%s", message); + } + + } else + bna_mbox_aen_callback(bna, msg); +} + +void +bna_err_handler(struct bna *bna, u32 intr_status) +{ + u32 init_halt; + + if (intr_status & __HALT_STATUS_BITS) { + init_halt = readl(bna->device.ioc.ioc_regs.ll_halt); + init_halt &= ~__FW_INIT_HALT_P; + writel(init_halt, bna->device.ioc.ioc_regs.ll_halt); + } + + bfa_ioc_error_isr(&bna->device.ioc); +} + +void +bna_mbox_handler(struct bna *bna, u32 intr_status) +{ + if (BNA_IS_ERR_INTR(intr_status)) { + bna_err_handler(bna, intr_status); + return; + } + if (BNA_IS_MBOX_INTR(intr_status)) + bfa_ioc_mbox_isr(&bna->device.ioc); +} + +void +bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe) +{ + struct bfi_mhdr *mh; + + mh = (struct bfi_mhdr *)(&mbox_qe->cmd.msg[0]); + + mh->mtag.i2htok = htons(bna->mbox_mod.msg_ctr); + bna->mbox_mod.msg_ctr++; + bna->mbox_mod.msg_pending++; + if (bna->mbox_mod.state == BNA_MBOX_FREE) { + list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q); + bfa_ioc_mbox_queue(&bna->device.ioc, &mbox_qe->cmd); + bna->mbox_mod.state = BNA_MBOX_POSTED; + } else { + list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q); + } +} + +void +bna_mbox_flush_q(struct bna *bna, struct list_head *q) +{ + struct bna_mbox_qe *mb_qe = NULL; + struct bfi_mhdr *cmd_h; + struct list_head *mb_q; + void (*cbfn)(void *arg, int status); + void *cbarg; + + mb_q = &bna->mbox_mod.posted_q; + + while (!list_empty(mb_q)) { + bfa_q_deq(mb_q, &mb_qe); + cbfn = mb_qe->cbfn; + cbarg = mb_qe->cbarg; + bfa_q_qe_init(mb_qe); + bna->mbox_mod.msg_pending--; + + cmd_h = (struct bfi_mhdr *)(&mb_qe->cmd.msg[0]); + if (cbfn) + cbfn(cbarg, BNA_CB_NOT_EXEC); + } + + bna->mbox_mod.state = BNA_MBOX_FREE; +} + +void +bna_mbox_mod_start(struct bna_mbox_mod *mbox_mod) +{ +} + +void +bna_mbox_mod_stop(struct bna_mbox_mod *mbox_mod) +{ + bna_mbox_flush_q(mbox_mod->bna, &mbox_mod->posted_q); +} + +void +bna_mbox_mod_init(struct bna_mbox_mod *mbox_mod, struct bna *bna) +{ + bfa_ioc_mbox_regisr(&bna->device.ioc, BFI_MC_LL, bna_ll_isr, bna); + mbox_mod->state = BNA_MBOX_FREE; + mbox_mod->msg_ctr = mbox_mod->msg_pending = 0; + INIT_LIST_HEAD(&mbox_mod->posted_q); + mbox_mod->bna = bna; +} + +void +bna_mbox_mod_uninit(struct bna_mbox_mod *mbox_mod) +{ + mbox_mod->bna = NULL; +} + +/** + * LLPORT + */ +#define call_llport_stop_cbfn(llport, status)\ +do {\ + if ((llport)->stop_cbfn)\ + (llport)->stop_cbfn(&(llport)->bna->port, status);\ + (llport)->stop_cbfn = NULL;\ +} while (0) + +static void bna_fw_llport_up(struct bna_llport *llport); +static void bna_fw_cb_llport_up(void *arg, int status); +static void bna_fw_llport_down(struct bna_llport *llport); +static void bna_fw_cb_llport_down(void *arg, int status); +static void bna_llport_start(struct bna_llport *llport); +static void bna_llport_stop(struct bna_llport *llport); +static void bna_llport_fail(struct bna_llport *llport); + +enum bna_llport_event { + LLPORT_E_START = 1, + LLPORT_E_STOP = 2, + LLPORT_E_FAIL = 3, + LLPORT_E_UP = 4, + LLPORT_E_DOWN = 5, + LLPORT_E_FWRESP_UP = 6, + LLPORT_E_FWRESP_DOWN = 7 +}; + +enum bna_llport_state { + BNA_LLPORT_STOPPED = 1, + BNA_LLPORT_DOWN = 2, + BNA_LLPORT_UP_RESP_WAIT = 3, + BNA_LLPORT_DOWN_RESP_WAIT = 4, + BNA_LLPORT_UP = 5, + BNA_LLPORT_LAST_RESP_WAIT = 6 +}; + +bfa_fsm_state_decl(bna_llport, stopped, struct bna_llport, + enum bna_llport_event); +bfa_fsm_state_decl(bna_llport, down, struct bna_llport, + enum bna_llport_event); +bfa_fsm_state_decl(bna_llport, up_resp_wait, struct bna_llport, + enum bna_llport_event); +bfa_fsm_state_decl(bna_llport, down_resp_wait, struct bna_llport, + enum bna_llport_event); +bfa_fsm_state_decl(bna_llport, up, struct bna_llport, + enum bna_llport_event); +bfa_fsm_state_decl(bna_llport, last_resp_wait, struct bna_llport, + enum bna_llport_event); + +static struct bfa_sm_table llport_sm_table[] = { + {BFA_SM(bna_llport_sm_stopped), BNA_LLPORT_STOPPED}, + {BFA_SM(bna_llport_sm_down), BNA_LLPORT_DOWN}, + {BFA_SM(bna_llport_sm_up_resp_wait), BNA_LLPORT_UP_RESP_WAIT}, + {BFA_SM(bna_llport_sm_down_resp_wait), BNA_LLPORT_DOWN_RESP_WAIT}, + {BFA_SM(bna_llport_sm_up), BNA_LLPORT_UP}, + {BFA_SM(bna_llport_sm_last_resp_wait), BNA_LLPORT_LAST_RESP_WAIT} +}; + +static void +bna_llport_sm_stopped_entry(struct bna_llport *llport) +{ + llport->bna->port.link_cbfn((llport)->bna->bnad, BNA_LINK_DOWN); + call_llport_stop_cbfn(llport, BNA_CB_SUCCESS); +} + +static void +bna_llport_sm_stopped(struct bna_llport *llport, + enum bna_llport_event event) +{ + switch (event) { + case LLPORT_E_START: + bfa_fsm_set_state(llport, bna_llport_sm_down); + break; + + case LLPORT_E_STOP: + call_llport_stop_cbfn(llport, BNA_CB_SUCCESS); + break; + + case LLPORT_E_FAIL: + break; + + case LLPORT_E_DOWN: + /* This event is received due to Rx objects failing */ + /* No-op */ + break; + + case LLPORT_E_FWRESP_UP: + case LLPORT_E_FWRESP_DOWN: + /** + * These events are received due to flushing of mbox when + * device fails + */ + /* No-op */ + break; + + default: + bfa_sm_fault(llport->bna, event); + } +} + +static void +bna_llport_sm_down_entry(struct bna_llport *llport) +{ + bnad_cb_port_link_status((llport)->bna->bnad, BNA_LINK_DOWN); +} + +static void +bna_llport_sm_down(struct bna_llport *llport, + enum bna_llport_event event) +{ + switch (event) { + case LLPORT_E_STOP: + bfa_fsm_set_state(llport, bna_llport_sm_stopped); + break; + + case LLPORT_E_FAIL: + bfa_fsm_set_state(llport, bna_llport_sm_stopped); + break; + + case LLPORT_E_UP: + bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait); + bna_fw_llport_up(llport); + break; + + default: + bfa_sm_fault(llport->bna, event); + } +} + +static void +bna_llport_sm_up_resp_wait_entry(struct bna_llport *llport) +{ + /** + * NOTE: Do not call bna_fw_llport_up() here. That will over step + * mbox due to down_resp_wait -> up_resp_wait transition on event + * LLPORT_E_UP + */ +} + +static void +bna_llport_sm_up_resp_wait(struct bna_llport *llport, + enum bna_llport_event event) +{ + switch (event) { + case LLPORT_E_STOP: + bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait); + break; + + case LLPORT_E_FAIL: + bfa_fsm_set_state(llport, bna_llport_sm_stopped); + break; + + case LLPORT_E_DOWN: + bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait); + break; + + case LLPORT_E_FWRESP_UP: + bfa_fsm_set_state(llport, bna_llport_sm_up); + break; + + case LLPORT_E_FWRESP_DOWN: + /* down_resp_wait -> up_resp_wait transition on LLPORT_E_UP */ + bna_fw_llport_up(llport); + break; + + default: + bfa_sm_fault(llport->bna, event); + } +} + +static void +bna_llport_sm_down_resp_wait_entry(struct bna_llport *llport) +{ + /** + * NOTE: Do not call bna_fw_llport_down() here. That will over step + * mbox due to up_resp_wait -> down_resp_wait transition on event + * LLPORT_E_DOWN + */ +} + +static void +bna_llport_sm_down_resp_wait(struct bna_llport *llport, + enum bna_llport_event event) +{ + switch (event) { + case LLPORT_E_STOP: + bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait); + break; + + case LLPORT_E_FAIL: + bfa_fsm_set_state(llport, bna_llport_sm_stopped); + break; + + case LLPORT_E_UP: + bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait); + break; + + case LLPORT_E_FWRESP_UP: + /* up_resp_wait->down_resp_wait transition on LLPORT_E_DOWN */ + bna_fw_llport_down(llport); + break; + + case LLPORT_E_FWRESP_DOWN: + bfa_fsm_set_state(llport, bna_llport_sm_down); + break; + + default: + bfa_sm_fault(llport->bna, event); + } +} + +static void +bna_llport_sm_up_entry(struct bna_llport *llport) +{ +} + +static void +bna_llport_sm_up(struct bna_llport *llport, + enum bna_llport_event event) +{ + switch (event) { + case LLPORT_E_STOP: + bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait); + bna_fw_llport_down(llport); + break; + + case LLPORT_E_FAIL: + bfa_fsm_set_state(llport, bna_llport_sm_stopped); + break; + + case LLPORT_E_DOWN: + bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait); + bna_fw_llport_down(llport); + break; + + default: + bfa_sm_fault(llport->bna, event); + } +} + +static void +bna_llport_sm_last_resp_wait_entry(struct bna_llport *llport) +{ +} + +static void +bna_llport_sm_last_resp_wait(struct bna_llport *llport, + enum bna_llport_event event) +{ + switch (event) { + case LLPORT_E_FAIL: + bfa_fsm_set_state(llport, bna_llport_sm_stopped); + break; + + case LLPORT_E_DOWN: + /** + * This event is received due to Rx objects stopping in + * parallel to llport + */ + /* No-op */ + break; + + case LLPORT_E_FWRESP_UP: + /* up_resp_wait->last_resp_wait transition on LLPORT_T_STOP */ + bna_fw_llport_down(llport); + break; + + case LLPORT_E_FWRESP_DOWN: + bfa_fsm_set_state(llport, bna_llport_sm_stopped); + break; + + default: + bfa_sm_fault(llport->bna, event); + } +} + +static void +bna_fw_llport_admin_up(struct bna_llport *llport) +{ + struct bfi_ll_port_admin_req ll_req; + + memset(&ll_req, 0, sizeof(ll_req)); + ll_req.mh.msg_class = BFI_MC_LL; + ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ; + ll_req.mh.mtag.h2i.lpu_id = 0; + + ll_req.up = BNA_STATUS_T_ENABLED; + + bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req), + bna_fw_cb_llport_up, llport); + + bna_mbox_send(llport->bna, &llport->mbox_qe); +} + +static void +bna_fw_llport_up(struct bna_llport *llport) +{ + if (llport->type == BNA_PORT_T_REGULAR) + bna_fw_llport_admin_up(llport); +} + +static void +bna_fw_cb_llport_up(void *arg, int status) +{ + struct bna_llport *llport = (struct bna_llport *)arg; + + bfa_q_qe_init(&llport->mbox_qe.qe); + bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP); +} + +static void +bna_fw_llport_admin_down(struct bna_llport *llport) +{ + struct bfi_ll_port_admin_req ll_req; + + memset(&ll_req, 0, sizeof(ll_req)); + ll_req.mh.msg_class = BFI_MC_LL; + ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ; + ll_req.mh.mtag.h2i.lpu_id = 0; + + ll_req.up = BNA_STATUS_T_DISABLED; + + bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req), + bna_fw_cb_llport_down, llport); + + bna_mbox_send(llport->bna, &llport->mbox_qe); +} + +static void +bna_fw_llport_down(struct bna_llport *llport) +{ + if (llport->type == BNA_PORT_T_REGULAR) + bna_fw_llport_admin_down(llport); +} + +static void +bna_fw_cb_llport_down(void *arg, int status) +{ + struct bna_llport *llport = (struct bna_llport *)arg; + + bfa_q_qe_init(&llport->mbox_qe.qe); + bfa_fsm_send_event(llport, LLPORT_E_FWRESP_DOWN); +} + +void +bna_port_cb_llport_stopped(struct bna_port *port, + enum bna_cb_status status) +{ + bfa_wc_down(&port->chld_stop_wc); +} + +static void +bna_llport_init(struct bna_llport *llport, struct bna *bna) +{ + llport->flags |= BNA_LLPORT_F_ENABLED; + llport->type = BNA_PORT_T_REGULAR; + llport->bna = bna; + + llport->link_status = BNA_LINK_DOWN; + + llport->admin_up_count = 0; + + llport->stop_cbfn = NULL; + + bfa_q_qe_init(&llport->mbox_qe.qe); + + bfa_fsm_set_state(llport, bna_llport_sm_stopped); +} + +static void +bna_llport_uninit(struct bna_llport *llport) +{ + llport->flags &= ~BNA_LLPORT_F_ENABLED; + + llport->bna = NULL; +} + +static void +bna_llport_start(struct bna_llport *llport) +{ + bfa_fsm_send_event(llport, LLPORT_E_START); +} + +static void +bna_llport_stop(struct bna_llport *llport) +{ + llport->stop_cbfn = bna_port_cb_llport_stopped; + + bfa_fsm_send_event(llport, LLPORT_E_STOP); +} + +static void +bna_llport_fail(struct bna_llport *llport) +{ + bfa_fsm_send_event(llport, LLPORT_E_FAIL); +} + +int +bna_llport_state_get(struct bna_llport *llport) +{ + return bfa_sm_to_state(llport_sm_table, llport->fsm); +} + +void +bna_llport_admin_up(struct bna_llport *llport) +{ + llport->admin_up_count++; + + if (llport->admin_up_count == 1) { + llport->flags |= BNA_LLPORT_F_RX_ENABLED; + if (llport->flags & BNA_LLPORT_F_ENABLED) + bfa_fsm_send_event(llport, LLPORT_E_UP); + } +} + +void +bna_llport_admin_down(struct bna_llport *llport) +{ + llport->admin_up_count--; + + if (llport->admin_up_count == 0) { + llport->flags &= ~BNA_LLPORT_F_RX_ENABLED; + if (llport->flags & BNA_LLPORT_F_ENABLED) + bfa_fsm_send_event(llport, LLPORT_E_DOWN); + } +} + +/** + * PORT + */ +#define bna_port_chld_start(port)\ +do {\ + enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ + BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\ + enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ + BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\ + bna_llport_start(&(port)->llport);\ + bna_tx_mod_start(&(port)->bna->tx_mod, tx_type);\ + bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\ +} while (0) + +#define bna_port_chld_stop(port)\ +do {\ + enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ + BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\ + enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ + BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\ + bfa_wc_up(&(port)->chld_stop_wc);\ + bfa_wc_up(&(port)->chld_stop_wc);\ + bfa_wc_up(&(port)->chld_stop_wc);\ + bna_llport_stop(&(port)->llport);\ + bna_tx_mod_stop(&(port)->bna->tx_mod, tx_type);\ + bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\ +} while (0) + +#define bna_port_chld_fail(port)\ +do {\ + bna_llport_fail(&(port)->llport);\ + bna_tx_mod_fail(&(port)->bna->tx_mod);\ + bna_rx_mod_fail(&(port)->bna->rx_mod);\ +} while (0) + +#define bna_port_rx_start(port)\ +do {\ + enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ + BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\ + bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\ +} while (0) + +#define bna_port_rx_stop(port)\ +do {\ + enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ + BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\ + bfa_wc_up(&(port)->chld_stop_wc);\ + bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\ +} while (0) + +#define call_port_stop_cbfn(port, status)\ +do {\ + if ((port)->stop_cbfn)\ + (port)->stop_cbfn((port)->stop_cbarg, status);\ + (port)->stop_cbfn = NULL;\ + (port)->stop_cbarg = NULL;\ +} while (0) + +#define call_port_pause_cbfn(port, status)\ +do {\ + if ((port)->pause_cbfn)\ + (port)->pause_cbfn((port)->bna->bnad, status);\ + (port)->pause_cbfn = NULL;\ +} while (0) + +#define call_port_mtu_cbfn(port, status)\ +do {\ + if ((port)->mtu_cbfn)\ + (port)->mtu_cbfn((port)->bna->bnad, status);\ + (port)->mtu_cbfn = NULL;\ +} while (0) + +static void bna_fw_pause_set(struct bna_port *port); +static void bna_fw_cb_pause_set(void *arg, int status); +static void bna_fw_mtu_set(struct bna_port *port); +static void bna_fw_cb_mtu_set(void *arg, int status); + +enum bna_port_event { + PORT_E_START = 1, + PORT_E_STOP = 2, + PORT_E_FAIL = 3, + PORT_E_PAUSE_CFG = 4, + PORT_E_MTU_CFG = 5, + PORT_E_CHLD_STOPPED = 6, + PORT_E_FWRESP_PAUSE = 7, + PORT_E_FWRESP_MTU = 8 +}; + +enum bna_port_state { + BNA_PORT_STOPPED = 1, + BNA_PORT_MTU_INIT_WAIT = 2, + BNA_PORT_PAUSE_INIT_WAIT = 3, + BNA_PORT_LAST_RESP_WAIT = 4, + BNA_PORT_STARTED = 5, + BNA_PORT_PAUSE_CFG_WAIT = 6, + BNA_PORT_RX_STOP_WAIT = 7, + BNA_PORT_MTU_CFG_WAIT = 8, + BNA_PORT_CHLD_STOP_WAIT = 9 +}; + +bfa_fsm_state_decl(bna_port, stopped, struct bna_port, + enum bna_port_event); +bfa_fsm_state_decl(bna_port, mtu_init_wait, struct bna_port, + enum bna_port_event); +bfa_fsm_state_decl(bna_port, pause_init_wait, struct bna_port, + enum bna_port_event); +bfa_fsm_state_decl(bna_port, last_resp_wait, struct bna_port, + enum bna_port_event); +bfa_fsm_state_decl(bna_port, started, struct bna_port, + enum bna_port_event); +bfa_fsm_state_decl(bna_port, pause_cfg_wait, struct bna_port, + enum bna_port_event); +bfa_fsm_state_decl(bna_port, rx_stop_wait, struct bna_port, + enum bna_port_event); +bfa_fsm_state_decl(bna_port, mtu_cfg_wait, struct bna_port, + enum bna_port_event); +bfa_fsm_state_decl(bna_port, chld_stop_wait, struct bna_port, + enum bna_port_event); + +static struct bfa_sm_table port_sm_table[] = { + {BFA_SM(bna_port_sm_stopped), BNA_PORT_STOPPED}, + {BFA_SM(bna_port_sm_mtu_init_wait), BNA_PORT_MTU_INIT_WAIT}, + {BFA_SM(bna_port_sm_pause_init_wait), BNA_PORT_PAUSE_INIT_WAIT}, + {BFA_SM(bna_port_sm_last_resp_wait), BNA_PORT_LAST_RESP_WAIT}, + {BFA_SM(bna_port_sm_started), BNA_PORT_STARTED}, + {BFA_SM(bna_port_sm_pause_cfg_wait), BNA_PORT_PAUSE_CFG_WAIT}, + {BFA_SM(bna_port_sm_rx_stop_wait), BNA_PORT_RX_STOP_WAIT}, + {BFA_SM(bna_port_sm_mtu_cfg_wait), BNA_PORT_MTU_CFG_WAIT}, + {BFA_SM(bna_port_sm_chld_stop_wait), BNA_PORT_CHLD_STOP_WAIT} +}; + +static void +bna_port_sm_stopped_entry(struct bna_port *port) +{ + call_port_pause_cbfn(port, BNA_CB_SUCCESS); + call_port_mtu_cbfn(port, BNA_CB_SUCCESS); + call_port_stop_cbfn(port, BNA_CB_SUCCESS); +} + +static void +bna_port_sm_stopped(struct bna_port *port, enum bna_port_event event) +{ + switch (event) { + case PORT_E_START: + bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait); + break; + + case PORT_E_STOP: + call_port_stop_cbfn(port, BNA_CB_SUCCESS); + break; + + case PORT_E_FAIL: + /* No-op */ + break; + + case PORT_E_PAUSE_CFG: + call_port_pause_cbfn(port, BNA_CB_SUCCESS); + break; + + case PORT_E_MTU_CFG: + call_port_mtu_cbfn(port, BNA_CB_SUCCESS); + break; + + case PORT_E_CHLD_STOPPED: + /** + * This event is received due to LLPort, Tx and Rx objects + * failing + */ + /* No-op */ + break; + + case PORT_E_FWRESP_PAUSE: + case PORT_E_FWRESP_MTU: + /** + * These events are received due to flushing of mbox when + * device fails + */ + /* No-op */ + break; + + default: + bfa_sm_fault(port->bna, event); + } +} + +static void +bna_port_sm_mtu_init_wait_entry(struct bna_port *port) +{ + bna_fw_mtu_set(port); +} + +static void +bna_port_sm_mtu_init_wait(struct bna_port *port, enum bna_port_event event) +{ + switch (event) { + case PORT_E_STOP: + bfa_fsm_set_state(port, bna_port_sm_last_resp_wait); + break; + + case PORT_E_FAIL: + bfa_fsm_set_state(port, bna_port_sm_stopped); + break; + + case PORT_E_PAUSE_CFG: + /* No-op */ + break; + + case PORT_E_MTU_CFG: + port->flags |= BNA_PORT_F_MTU_CHANGED; + break; + + case PORT_E_FWRESP_MTU: + if (port->flags & BNA_PORT_F_MTU_CHANGED) { + port->flags &= ~BNA_PORT_F_MTU_CHANGED; + bna_fw_mtu_set(port); + } else { + bfa_fsm_set_state(port, bna_port_sm_pause_init_wait); + } + break; + + default: + bfa_sm_fault(port->bna, event); + } +} + +static void +bna_port_sm_pause_init_wait_entry(struct bna_port *port) +{ + bna_fw_pause_set(port); +} + +static void +bna_port_sm_pause_init_wait(struct bna_port *port, + enum bna_port_event event) +{ + switch (event) { + case PORT_E_STOP: + bfa_fsm_set_state(port, bna_port_sm_last_resp_wait); + break; + + case PORT_E_FAIL: + bfa_fsm_set_state(port, bna_port_sm_stopped); + break; + + case PORT_E_PAUSE_CFG: + port->flags |= BNA_PORT_F_PAUSE_CHANGED; + break; + + case PORT_E_MTU_CFG: + port->flags |= BNA_PORT_F_MTU_CHANGED; + break; + + case PORT_E_FWRESP_PAUSE: + if (port->flags & BNA_PORT_F_PAUSE_CHANGED) { + port->flags &= ~BNA_PORT_F_PAUSE_CHANGED; + bna_fw_pause_set(port); + } else if (port->flags & BNA_PORT_F_MTU_CHANGED) { + port->flags &= ~BNA_PORT_F_MTU_CHANGED; + bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait); + } else { + bfa_fsm_set_state(port, bna_port_sm_started); + bna_port_chld_start(port); + } + break; + + default: + bfa_sm_fault(port->bna, event); + } +} + +static void +bna_port_sm_last_resp_wait_entry(struct bna_port *port) +{ +} + +static void +bna_port_sm_last_resp_wait(struct bna_port *port, + enum bna_port_event event) +{ + switch (event) { + case PORT_E_FAIL: + case PORT_E_FWRESP_PAUSE: + case PORT_E_FWRESP_MTU: + bfa_fsm_set_state(port, bna_port_sm_stopped); + break; + + default: + bfa_sm_fault(port->bna, event); + } +} + +static void +bna_port_sm_started_entry(struct bna_port *port) +{ + /** + * NOTE: Do not call bna_port_chld_start() here, since it will be + * inadvertently called during pause_cfg_wait->started transition + * as well + */ + call_port_pause_cbfn(port, BNA_CB_SUCCESS); + call_port_mtu_cbfn(port, BNA_CB_SUCCESS); +} + +static void +bna_port_sm_started(struct bna_port *port, + enum bna_port_event event) +{ + switch (event) { + case PORT_E_STOP: + bfa_fsm_set_state(port, bna_port_sm_chld_stop_wait); + break; + + case PORT_E_FAIL: + bfa_fsm_set_state(port, bna_port_sm_stopped); + bna_port_chld_fail(port); + break; + + case PORT_E_PAUSE_CFG: + bfa_fsm_set_state(port, bna_port_sm_pause_cfg_wait); + break; + + case PORT_E_MTU_CFG: + bfa_fsm_set_state(port, bna_port_sm_rx_stop_wait); + break; + + default: + bfa_sm_fault(port->bna, event); + } +} + +static void +bna_port_sm_pause_cfg_wait_entry(struct bna_port *port) +{ + bna_fw_pause_set(port); +} + +static void +bna_port_sm_pause_cfg_wait(struct bna_port *port, + enum bna_port_event event) +{ + switch (event) { + case PORT_E_FAIL: + bfa_fsm_set_state(port, bna_port_sm_stopped); + bna_port_chld_fail(port); + break; + + case PORT_E_FWRESP_PAUSE: + bfa_fsm_set_state(port, bna_port_sm_started); + break; + + default: + bfa_sm_fault(port->bna, event); + } +} + +static void +bna_port_sm_rx_stop_wait_entry(struct bna_port *port) +{ + bna_port_rx_stop(port); +} + +static void +bna_port_sm_rx_stop_wait(struct bna_port *port, + enum bna_port_event event) +{ + switch (event) { + case PORT_E_FAIL: + bfa_fsm_set_state(port, bna_port_sm_stopped); + bna_port_chld_fail(port); + break; + + case PORT_E_CHLD_STOPPED: + bfa_fsm_set_state(port, bna_port_sm_mtu_cfg_wait); + break; + + default: + bfa_sm_fault(port->bna, event); + } +} + +static void +bna_port_sm_mtu_cfg_wait_entry(struct bna_port *port) +{ + bna_fw_mtu_set(port); +} + +static void +bna_port_sm_mtu_cfg_wait(struct bna_port *port, enum bna_port_event event) +{ + switch (event) { + case PORT_E_FAIL: + bfa_fsm_set_state(port, bna_port_sm_stopped); + bna_port_chld_fail(port); + break; + + case PORT_E_FWRESP_MTU: + bfa_fsm_set_state(port, bna_port_sm_started); + bna_port_rx_start(port); + break; + + default: + bfa_sm_fault(port->bna, event); + } +} + +static void +bna_port_sm_chld_stop_wait_entry(struct bna_port *port) +{ + bna_port_chld_stop(port); +} + +static void +bna_port_sm_chld_stop_wait(struct bna_port *port, + enum bna_port_event event) +{ + switch (event) { + case PORT_E_FAIL: + bfa_fsm_set_state(port, bna_port_sm_stopped); + bna_port_chld_fail(port); + break; + + case PORT_E_CHLD_STOPPED: + bfa_fsm_set_state(port, bna_port_sm_stopped); + break; + + default: + bfa_sm_fault(port->bna, event); + } +} + +static void +bna_fw_pause_set(struct bna_port *port) +{ + struct bfi_ll_set_pause_req ll_req; + + memset(&ll_req, 0, sizeof(ll_req)); + ll_req.mh.msg_class = BFI_MC_LL; + ll_req.mh.msg_id = BFI_LL_H2I_SET_PAUSE_REQ; + ll_req.mh.mtag.h2i.lpu_id = 0; + + ll_req.tx_pause = port->pause_config.tx_pause; + ll_req.rx_pause = port->pause_config.rx_pause; + + bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req), + bna_fw_cb_pause_set, port); + + bna_mbox_send(port->bna, &port->mbox_qe); +} + +static void +bna_fw_cb_pause_set(void *arg, int status) +{ + struct bna_port *port = (struct bna_port *)arg; + + bfa_q_qe_init(&port->mbox_qe.qe); + bfa_fsm_send_event(port, PORT_E_FWRESP_PAUSE); +} + +void +bna_fw_mtu_set(struct bna_port *port) +{ + struct bfi_ll_mtu_info_req ll_req; + + bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_MTU_INFO_REQ, 0); + ll_req.mtu = htons((u16)port->mtu); + + bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req), + bna_fw_cb_mtu_set, port); + bna_mbox_send(port->bna, &port->mbox_qe); +} + +void +bna_fw_cb_mtu_set(void *arg, int status) +{ + struct bna_port *port = (struct bna_port *)arg; + + bfa_q_qe_init(&port->mbox_qe.qe); + bfa_fsm_send_event(port, PORT_E_FWRESP_MTU); +} + +static void +bna_port_cb_chld_stopped(void *arg) +{ + struct bna_port *port = (struct bna_port *)arg; + + bfa_fsm_send_event(port, PORT_E_CHLD_STOPPED); +} + +void +bna_port_init(struct bna_port *port, struct bna *bna) +{ + port->bna = bna; + port->flags = 0; + port->mtu = 0; + port->type = BNA_PORT_T_REGULAR; + + port->link_cbfn = bnad_cb_port_link_status; + + port->chld_stop_wc.wc_resume = bna_port_cb_chld_stopped; + port->chld_stop_wc.wc_cbarg = port; + port->chld_stop_wc.wc_count = 0; + + port->stop_cbfn = NULL; + port->stop_cbarg = NULL; + + port->pause_cbfn = NULL; + + port->mtu_cbfn = NULL; + + bfa_q_qe_init(&port->mbox_qe.qe); + + bfa_fsm_set_state(port, bna_port_sm_stopped); + + bna_llport_init(&port->llport, bna); +} + +void +bna_port_uninit(struct bna_port *port) +{ + bna_llport_uninit(&port->llport); + + port->flags = 0; + + port->bna = NULL; +} + +int +bna_port_state_get(struct bna_port *port) +{ + return bfa_sm_to_state(port_sm_table, port->fsm); +} + +void +bna_port_start(struct bna_port *port) +{ + port->flags |= BNA_PORT_F_DEVICE_READY; + if (port->flags & BNA_PORT_F_ENABLED) + bfa_fsm_send_event(port, PORT_E_START); +} + +void +bna_port_stop(struct bna_port *port) +{ + port->stop_cbfn = bna_device_cb_port_stopped; + port->stop_cbarg = &port->bna->device; + + port->flags &= ~BNA_PORT_F_DEVICE_READY; + bfa_fsm_send_event(port, PORT_E_STOP); +} + +void +bna_port_fail(struct bna_port *port) +{ + port->flags &= ~BNA_PORT_F_DEVICE_READY; + bfa_fsm_send_event(port, PORT_E_FAIL); +} + +void +bna_port_cb_tx_stopped(struct bna_port *port, enum bna_cb_status status) +{ + bfa_wc_down(&port->chld_stop_wc); +} + +void +bna_port_cb_rx_stopped(struct bna_port *port, enum bna_cb_status status) +{ + bfa_wc_down(&port->chld_stop_wc); +} + +void +bna_port_cb_link_up(struct bna_port *port, struct bfi_ll_aen *aen, + int status) +{ + int i; + u8 prio_map; + + port->llport.link_status = BNA_LINK_UP; + if (aen->cee_linkup) + port->llport.link_status = BNA_CEE_UP; + + /* Compute the priority */ + prio_map = aen->prio_map; + if (prio_map) { + for (i = 0; i < 8; i++) { + if ((prio_map >> i) & 0x1) + break; + } + port->priority = i; + } else + port->priority = 0; + + /* Dispatch events */ + bna_tx_mod_cee_link_status(&port->bna->tx_mod, aen->cee_linkup); + bna_tx_mod_prio_changed(&port->bna->tx_mod, port->priority); + port->link_cbfn(port->bna->bnad, port->llport.link_status); +} + +void +bna_port_cb_link_down(struct bna_port *port, int status) +{ + port->llport.link_status = BNA_LINK_DOWN; + + /* Dispatch events */ + bna_tx_mod_cee_link_status(&port->bna->tx_mod, BNA_LINK_DOWN); + port->link_cbfn(port->bna->bnad, BNA_LINK_DOWN); +} + +int +bna_port_mtu_get(struct bna_port *port) +{ + return port->mtu; +} + +void +bna_port_enable(struct bna_port *port) +{ + if (port->fsm != (bfa_sm_t)bna_port_sm_stopped) + return; + + port->flags |= BNA_PORT_F_ENABLED; + + if (port->flags & BNA_PORT_F_DEVICE_READY) + bfa_fsm_send_event(port, PORT_E_START); +} + +void +bna_port_disable(struct bna_port *port, enum bna_cleanup_type type, + void (*cbfn)(void *, enum bna_cb_status)) +{ + if (type == BNA_SOFT_CLEANUP) { + (*cbfn)(port->bna->bnad, BNA_CB_SUCCESS); + return; + } + + port->stop_cbfn = cbfn; + port->stop_cbarg = port->bna->bnad; + + port->flags &= ~BNA_PORT_F_ENABLED; + + bfa_fsm_send_event(port, PORT_E_STOP); +} + +void +bna_port_pause_config(struct bna_port *port, + struct bna_pause_config *pause_config, + void (*cbfn)(struct bnad *, enum bna_cb_status)) +{ + port->pause_config = *pause_config; + + port->pause_cbfn = cbfn; + + bfa_fsm_send_event(port, PORT_E_PAUSE_CFG); +} + +void +bna_port_mtu_set(struct bna_port *port, int mtu, + void (*cbfn)(struct bnad *, enum bna_cb_status)) +{ + port->mtu = mtu; + + port->mtu_cbfn = cbfn; + + bfa_fsm_send_event(port, PORT_E_MTU_CFG); +} + +void +bna_port_mac_get(struct bna_port *port, mac_t *mac) +{ + *mac = bfa_ioc_get_mac(&port->bna->device.ioc); +} + +/** + * Should be called only when port is disabled + */ +void +bna_port_type_set(struct bna_port *port, enum bna_port_type type) +{ + port->type = type; + port->llport.type = type; +} + +/** + * Should be called only when port is disabled + */ +void +bna_port_linkcbfn_set(struct bna_port *port, + void (*linkcbfn)(struct bnad *, enum bna_link_status)) +{ + port->link_cbfn = linkcbfn; +} + +void +bna_port_admin_up(struct bna_port *port) +{ + struct bna_llport *llport = &port->llport; + + if (llport->flags & BNA_LLPORT_F_ENABLED) + return; + + llport->flags |= BNA_LLPORT_F_ENABLED; + + if (llport->flags & BNA_LLPORT_F_RX_ENABLED) + bfa_fsm_send_event(llport, LLPORT_E_UP); +} + +void +bna_port_admin_down(struct bna_port *port) +{ + struct bna_llport *llport = &port->llport; + + if (!(llport->flags & BNA_LLPORT_F_ENABLED)) + return; + + llport->flags &= ~BNA_LLPORT_F_ENABLED; + + if (llport->flags & BNA_LLPORT_F_RX_ENABLED) + bfa_fsm_send_event(llport, LLPORT_E_DOWN); +} + +/** + * DEVICE + */ +#define enable_mbox_intr(_device)\ +do {\ + u32 intr_status;\ + bna_intr_status_get((_device)->bna, intr_status);\ + bnad_cb_device_enable_mbox_intr((_device)->bna->bnad);\ + bna_mbox_intr_enable((_device)->bna);\ +} while (0) + +#define disable_mbox_intr(_device)\ +do {\ + bna_mbox_intr_disable((_device)->bna);\ + bnad_cb_device_disable_mbox_intr((_device)->bna->bnad);\ +} while (0) + +const struct bna_chip_regs_offset reg_offset[] = +{{HOST_PAGE_NUM_FN0, HOSTFN0_INT_STATUS, + HOSTFN0_INT_MASK, HOST_MSIX_ERR_INDEX_FN0}, +{HOST_PAGE_NUM_FN1, HOSTFN1_INT_STATUS, + HOSTFN1_INT_MASK, HOST_MSIX_ERR_INDEX_FN1}, +{HOST_PAGE_NUM_FN2, HOSTFN2_INT_STATUS, + HOSTFN2_INT_MASK, HOST_MSIX_ERR_INDEX_FN2}, +{HOST_PAGE_NUM_FN3, HOSTFN3_INT_STATUS, + HOSTFN3_INT_MASK, HOST_MSIX_ERR_INDEX_FN3}, +}; + +enum bna_device_event { + DEVICE_E_ENABLE = 1, + DEVICE_E_DISABLE = 2, + DEVICE_E_IOC_READY = 3, + DEVICE_E_IOC_FAILED = 4, + DEVICE_E_IOC_DISABLED = 5, + DEVICE_E_IOC_RESET = 6, + DEVICE_E_PORT_STOPPED = 7, +}; + +enum bna_device_state { + BNA_DEVICE_STOPPED = 1, + BNA_DEVICE_IOC_READY_WAIT = 2, + BNA_DEVICE_READY = 3, + BNA_DEVICE_PORT_STOP_WAIT = 4, + BNA_DEVICE_IOC_DISABLE_WAIT = 5, + BNA_DEVICE_FAILED = 6 +}; + +bfa_fsm_state_decl(bna_device, stopped, struct bna_device, + enum bna_device_event); +bfa_fsm_state_decl(bna_device, ioc_ready_wait, struct bna_device, + enum bna_device_event); +bfa_fsm_state_decl(bna_device, ready, struct bna_device, + enum bna_device_event); +bfa_fsm_state_decl(bna_device, port_stop_wait, struct bna_device, + enum bna_device_event); +bfa_fsm_state_decl(bna_device, ioc_disable_wait, struct bna_device, + enum bna_device_event); +bfa_fsm_state_decl(bna_device, failed, struct bna_device, + enum bna_device_event); + +static struct bfa_sm_table device_sm_table[] = { + {BFA_SM(bna_device_sm_stopped), BNA_DEVICE_STOPPED}, + {BFA_SM(bna_device_sm_ioc_ready_wait), BNA_DEVICE_IOC_READY_WAIT}, + {BFA_SM(bna_device_sm_ready), BNA_DEVICE_READY}, + {BFA_SM(bna_device_sm_port_stop_wait), BNA_DEVICE_PORT_STOP_WAIT}, + {BFA_SM(bna_device_sm_ioc_disable_wait), BNA_DEVICE_IOC_DISABLE_WAIT}, + {BFA_SM(bna_device_sm_failed), BNA_DEVICE_FAILED}, +}; + +static void +bna_device_sm_stopped_entry(struct bna_device *device) +{ + if (device->stop_cbfn) + device->stop_cbfn(device->stop_cbarg, BNA_CB_SUCCESS); + + device->stop_cbfn = NULL; + device->stop_cbarg = NULL; +} + +static void +bna_device_sm_stopped(struct bna_device *device, + enum bna_device_event event) +{ + switch (event) { + case DEVICE_E_ENABLE: + if (device->intr_type == BNA_INTR_T_MSIX) + bna_mbox_msix_idx_set(device); + bfa_ioc_enable(&device->ioc); + bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait); + break; + + case DEVICE_E_DISABLE: + bfa_fsm_set_state(device, bna_device_sm_stopped); + break; + + case DEVICE_E_IOC_RESET: + enable_mbox_intr(device); + break; + + case DEVICE_E_IOC_FAILED: + bfa_fsm_set_state(device, bna_device_sm_failed); + break; + + default: + bfa_sm_fault(device->bna, event); + } +} + +static void +bna_device_sm_ioc_ready_wait_entry(struct bna_device *device) +{ + /** + * Do not call bfa_ioc_enable() here. It must be called in the + * previous state due to failed -> ioc_ready_wait transition. + */ +} + +static void +bna_device_sm_ioc_ready_wait(struct bna_device *device, + enum bna_device_event event) +{ + switch (event) { + case DEVICE_E_DISABLE: + if (device->ready_cbfn) + device->ready_cbfn(device->ready_cbarg, + BNA_CB_INTERRUPT); + device->ready_cbfn = NULL; + device->ready_cbarg = NULL; + bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait); + break; + + case DEVICE_E_IOC_READY: + bfa_fsm_set_state(device, bna_device_sm_ready); + break; + + case DEVICE_E_IOC_FAILED: + bfa_fsm_set_state(device, bna_device_sm_failed); + break; + + case DEVICE_E_IOC_RESET: + enable_mbox_intr(device); + break; + + default: + bfa_sm_fault(device->bna, event); + } +} + +static void +bna_device_sm_ready_entry(struct bna_device *device) +{ + bna_mbox_mod_start(&device->bna->mbox_mod); + bna_port_start(&device->bna->port); + + if (device->ready_cbfn) + device->ready_cbfn(device->ready_cbarg, + BNA_CB_SUCCESS); + device->ready_cbfn = NULL; + device->ready_cbarg = NULL; +} + +static void +bna_device_sm_ready(struct bna_device *device, enum bna_device_event event) +{ + switch (event) { + case DEVICE_E_DISABLE: + bfa_fsm_set_state(device, bna_device_sm_port_stop_wait); + break; + + case DEVICE_E_IOC_FAILED: + bfa_fsm_set_state(device, bna_device_sm_failed); + break; + + default: + bfa_sm_fault(device->bna, event); + } +} + +static void +bna_device_sm_port_stop_wait_entry(struct bna_device *device) +{ + bna_port_stop(&device->bna->port); +} + +static void +bna_device_sm_port_stop_wait(struct bna_device *device, + enum bna_device_event event) +{ + switch (event) { + case DEVICE_E_PORT_STOPPED: + bna_mbox_mod_stop(&device->bna->mbox_mod); + bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait); + break; + + case DEVICE_E_IOC_FAILED: + disable_mbox_intr(device); + bna_port_fail(&device->bna->port); + break; + + default: + bfa_sm_fault(device->bna, event); + } +} + +static void +bna_device_sm_ioc_disable_wait_entry(struct bna_device *device) +{ + bfa_ioc_disable(&device->ioc); +} + +static void +bna_device_sm_ioc_disable_wait(struct bna_device *device, + enum bna_device_event event) +{ + switch (event) { + case DEVICE_E_IOC_DISABLED: + disable_mbox_intr(device); + bfa_fsm_set_state(device, bna_device_sm_stopped); + break; + + default: + bfa_sm_fault(device->bna, event); + } +} + +static void +bna_device_sm_failed_entry(struct bna_device *device) +{ + disable_mbox_intr(device); + bna_port_fail(&device->bna->port); + bna_mbox_mod_stop(&device->bna->mbox_mod); + + if (device->ready_cbfn) + device->ready_cbfn(device->ready_cbarg, + BNA_CB_FAIL); + device->ready_cbfn = NULL; + device->ready_cbarg = NULL; +} + +static void +bna_device_sm_failed(struct bna_device *device, + enum bna_device_event event) +{ + switch (event) { + case DEVICE_E_DISABLE: + bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait); + break; + + case DEVICE_E_IOC_RESET: + enable_mbox_intr(device); + bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait); + break; + + default: + bfa_sm_fault(device->bna, event); + } +} + +/* IOC callback functions */ + +static void +bna_device_cb_iocll_ready(void *dev, enum bfa_status error) +{ + struct bna_device *device = (struct bna_device *)dev; + + if (error) + bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED); + else + bfa_fsm_send_event(device, DEVICE_E_IOC_READY); +} + +static void +bna_device_cb_iocll_disabled(void *dev) +{ + struct bna_device *device = (struct bna_device *)dev; + + bfa_fsm_send_event(device, DEVICE_E_IOC_DISABLED); +} + +static void +bna_device_cb_iocll_failed(void *dev) +{ + struct bna_device *device = (struct bna_device *)dev; + + bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED); +} + +static void +bna_device_cb_iocll_reset(void *dev) +{ + struct bna_device *device = (struct bna_device *)dev; + + bfa_fsm_send_event(device, DEVICE_E_IOC_RESET); +} + +static struct bfa_ioc_cbfn bfa_iocll_cbfn = { + bna_device_cb_iocll_ready, + bna_device_cb_iocll_disabled, + bna_device_cb_iocll_failed, + bna_device_cb_iocll_reset +}; + +void +bna_device_init(struct bna_device *device, struct bna *bna, + struct bna_res_info *res_info) +{ + u64 dma; + + device->bna = bna; + + /** + * Attach IOC and claim: + * 1. DMA memory for IOC attributes + * 2. Kernel memory for FW trace + */ + bfa_ioc_attach(&device->ioc, device, &bfa_iocll_cbfn); + bfa_ioc_pci_init(&device->ioc, &bna->pcidev, BFI_MC_LL); + + BNA_GET_DMA_ADDR( + &res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].dma, dma); + bfa_ioc_mem_claim(&device->ioc, + res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].kva, + dma); + + bna_adv_device_init(device, bna, res_info); + /* + * Initialize mbox_mod only after IOC, so that mbox handler + * registration goes through + */ + device->intr_type = + res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type; + device->vector = + res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.idl[0].vector; + bna_mbox_mod_init(&bna->mbox_mod, bna); + + device->ready_cbfn = device->stop_cbfn = NULL; + device->ready_cbarg = device->stop_cbarg = NULL; + + bfa_fsm_set_state(device, bna_device_sm_stopped); +} + +void +bna_device_uninit(struct bna_device *device) +{ + bna_mbox_mod_uninit(&device->bna->mbox_mod); + + bfa_cee_detach(&device->bna->cee); + + bfa_ioc_detach(&device->ioc); + + device->bna = NULL; +} + +void +bna_device_cb_port_stopped(void *arg, enum bna_cb_status status) +{ + struct bna_device *device = (struct bna_device *)arg; + + bfa_fsm_send_event(device, DEVICE_E_PORT_STOPPED); +} + +int +bna_device_status_get(struct bna_device *device) +{ + return (device->fsm == (bfa_fsm_t)bna_device_sm_ready); +} + +void +bna_device_enable(struct bna_device *device) +{ + if (device->fsm != (bfa_fsm_t)bna_device_sm_stopped) { + bnad_cb_device_enabled(device->bna->bnad, BNA_CB_BUSY); + return; + } + + device->ready_cbfn = bnad_cb_device_enabled; + device->ready_cbarg = device->bna->bnad; + + bfa_fsm_send_event(device, DEVICE_E_ENABLE); +} + +void +bna_device_disable(struct bna_device *device, enum bna_cleanup_type type) +{ + if (type == BNA_SOFT_CLEANUP) { + bnad_cb_device_disabled(device->bna->bnad, BNA_CB_SUCCESS); + return; + } + + device->stop_cbfn = bnad_cb_device_disabled; + device->stop_cbarg = device->bna->bnad; + + bfa_fsm_send_event(device, DEVICE_E_DISABLE); +} + +int +bna_device_state_get(struct bna_device *device) +{ + return bfa_sm_to_state(device_sm_table, device->fsm); +} + +u32 bna_dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX] = { + {12, 20}, + {10, 18}, + {8, 16}, + {6, 12}, + {4, 8}, + {3, 6}, + {2, 4}, + {1, 2}, +}; + +u32 bna_napi_dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX] = { + {12, 12}, + {6, 10}, + {5, 10}, + {4, 8}, + {3, 6}, + {3, 6}, + {2, 4}, + {1, 2}, +}; + +/* device */ +void +bna_adv_device_init(struct bna_device *device, struct bna *bna, + struct bna_res_info *res_info) +{ + u8 *kva; + u64 dma; + + device->bna = bna; + + kva = res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mdl[0].kva; + + /** + * Attach common modules (Diag, SFP, CEE, Port) and claim respective + * DMA memory. + */ + BNA_GET_DMA_ADDR( + &res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].dma, dma); + kva = res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].kva; + + bfa_cee_attach(&bna->cee, &device->ioc, bna); + bfa_cee_mem_claim(&bna->cee, kva, dma); + kva += bfa_cee_meminfo(); + dma += bfa_cee_meminfo(); + +} + +/* utils */ + +void +bna_adv_res_req(struct bna_res_info *res_info) +{ + /* DMA memory for COMMON_MODULE */ + res_info[BNA_RES_MEM_T_COM].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mem_type = BNA_MEM_T_DMA; + res_info[BNA_RES_MEM_T_COM].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_COM].res_u.mem_info.len = ALIGN( + bfa_cee_meminfo(), PAGE_SIZE); + + /* Virtual memory for retreiving fw_trc */ + res_info[BNA_RES_MEM_T_FWTRC].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mem_type = BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.num = 0; + res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.len = 0; + + /* DMA memory for retreiving stats */ + res_info[BNA_RES_MEM_T_STATS].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mem_type = BNA_MEM_T_DMA; + res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.len = + ALIGN(BFI_HW_STATS_SIZE, PAGE_SIZE); + + /* Virtual memory for soft stats */ + res_info[BNA_RES_MEM_T_SWSTATS].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mem_type = BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.len = + sizeof(struct bna_sw_stats); +} + +static void +bna_sw_stats_get(struct bna *bna, struct bna_sw_stats *sw_stats) +{ + struct bna_tx *tx; + struct bna_txq *txq; + struct bna_rx *rx; + struct bna_rxp *rxp; + struct list_head *qe; + struct list_head *txq_qe; + struct list_head *rxp_qe; + struct list_head *mac_qe; + int i; + + sw_stats->device_state = bna_device_state_get(&bna->device); + sw_stats->port_state = bna_port_state_get(&bna->port); + sw_stats->port_flags = bna->port.flags; + sw_stats->llport_state = bna_llport_state_get(&bna->port.llport); + sw_stats->priority = bna->port.priority; + + i = 0; + list_for_each(qe, &bna->tx_mod.tx_active_q) { + tx = (struct bna_tx *)qe; + sw_stats->tx_stats[i].tx_state = bna_tx_state_get(tx); + sw_stats->tx_stats[i].tx_flags = tx->flags; + + sw_stats->tx_stats[i].num_txqs = 0; + sw_stats->tx_stats[i].txq_bmap[0] = 0; + sw_stats->tx_stats[i].txq_bmap[1] = 0; + list_for_each(txq_qe, &tx->txq_q) { + txq = (struct bna_txq *)txq_qe; + if (txq->txq_id < 32) + sw_stats->tx_stats[i].txq_bmap[0] |= + ((u32)1 << txq->txq_id); + else + sw_stats->tx_stats[i].txq_bmap[1] |= + ((u32) + 1 << (txq->txq_id - 32)); + sw_stats->tx_stats[i].num_txqs++; + } + + sw_stats->tx_stats[i].txf_id = tx->txf.txf_id; + + i++; + } + sw_stats->num_active_tx = i; + + i = 0; + list_for_each(qe, &bna->rx_mod.rx_active_q) { + rx = (struct bna_rx *)qe; + sw_stats->rx_stats[i].rx_state = bna_rx_state_get(rx); + sw_stats->rx_stats[i].rx_flags = rx->rx_flags; + + sw_stats->rx_stats[i].num_rxps = 0; + sw_stats->rx_stats[i].num_rxqs = 0; + sw_stats->rx_stats[i].rxq_bmap[0] = 0; + sw_stats->rx_stats[i].rxq_bmap[1] = 0; + sw_stats->rx_stats[i].cq_bmap[0] = 0; + sw_stats->rx_stats[i].cq_bmap[1] = 0; + list_for_each(rxp_qe, &rx->rxp_q) { + rxp = (struct bna_rxp *)rxp_qe; + + sw_stats->rx_stats[i].num_rxqs += 1; + + if (rxp->type == BNA_RXP_SINGLE) { + if (rxp->rxq.single.only->rxq_id < 32) { + sw_stats->rx_stats[i].rxq_bmap[0] |= + ((u32)1 << + rxp->rxq.single.only->rxq_id); + } else { + sw_stats->rx_stats[i].rxq_bmap[1] |= + ((u32)1 << + (rxp->rxq.single.only->rxq_id - 32)); + } + } else { + if (rxp->rxq.slr.large->rxq_id < 32) { + sw_stats->rx_stats[i].rxq_bmap[0] |= + ((u32)1 << + rxp->rxq.slr.large->rxq_id); + } else { + sw_stats->rx_stats[i].rxq_bmap[1] |= + ((u32)1 << + (rxp->rxq.slr.large->rxq_id - 32)); + } + + if (rxp->rxq.slr.small->rxq_id < 32) { + sw_stats->rx_stats[i].rxq_bmap[0] |= + ((u32)1 << + rxp->rxq.slr.small->rxq_id); + } else { + sw_stats->rx_stats[i].rxq_bmap[1] |= + ((u32)1 << + (rxp->rxq.slr.small->rxq_id - 32)); + } + sw_stats->rx_stats[i].num_rxqs += 1; + } + + if (rxp->cq.cq_id < 32) + sw_stats->rx_stats[i].cq_bmap[0] |= + (1 << rxp->cq.cq_id); + else + sw_stats->rx_stats[i].cq_bmap[1] |= + (1 << (rxp->cq.cq_id - 32)); + + sw_stats->rx_stats[i].num_rxps++; + } + + sw_stats->rx_stats[i].rxf_id = rx->rxf.rxf_id; + sw_stats->rx_stats[i].rxf_state = bna_rxf_state_get(&rx->rxf); + sw_stats->rx_stats[i].rxf_oper_state = rx->rxf.rxf_oper_state; + + sw_stats->rx_stats[i].num_active_ucast = 0; + if (rx->rxf.ucast_active_mac) + sw_stats->rx_stats[i].num_active_ucast++; + list_for_each(mac_qe, &rx->rxf.ucast_active_q) + sw_stats->rx_stats[i].num_active_ucast++; + + sw_stats->rx_stats[i].num_active_mcast = 0; + list_for_each(mac_qe, &rx->rxf.mcast_active_q) + sw_stats->rx_stats[i].num_active_mcast++; + + sw_stats->rx_stats[i].rxmode_active = rx->rxf.rxmode_active; + sw_stats->rx_stats[i].vlan_filter_status = + rx->rxf.vlan_filter_status; + memcpy(sw_stats->rx_stats[i].vlan_filter_table, + rx->rxf.vlan_filter_table, + sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32)); + + sw_stats->rx_stats[i].rss_status = rx->rxf.rss_status; + sw_stats->rx_stats[i].hds_status = rx->rxf.hds_status; + + i++; + } + sw_stats->num_active_rx = i; +} + +static void +bna_fw_cb_stats_get(void *arg, int status) +{ + struct bna *bna = (struct bna *)arg; + u64 *p_stats; + int i, count; + int rxf_count, txf_count; + u64 rxf_bmap, txf_bmap; + + bfa_q_qe_init(&bna->mbox_qe.qe); + + if (status == 0) { + p_stats = (u64 *)bna->stats.hw_stats; + count = sizeof(struct bfi_ll_stats) / sizeof(u64); + for (i = 0; i < count; i++) + p_stats[i] = cpu_to_be64(p_stats[i]); + + rxf_count = 0; + rxf_bmap = (u64)bna->stats.rxf_bmap[0] | + ((u64)bna->stats.rxf_bmap[1] << 32); + for (i = 0; i < BFI_LL_RXF_ID_MAX; i++) + if (rxf_bmap & ((u64)1 << i)) + rxf_count++; + + txf_count = 0; + txf_bmap = (u64)bna->stats.txf_bmap[0] | + ((u64)bna->stats.txf_bmap[1] << 32); + for (i = 0; i < BFI_LL_TXF_ID_MAX; i++) + if (txf_bmap & ((u64)1 << i)) + txf_count++; + + p_stats = (u64 *)&bna->stats.hw_stats->rxf_stats[0] + + ((rxf_count * sizeof(struct bfi_ll_stats_rxf) + + txf_count * sizeof(struct bfi_ll_stats_txf))/ + sizeof(u64)); + + /* Populate the TXF stats from the firmware DMAed copy */ + for (i = (BFI_LL_TXF_ID_MAX - 1); i >= 0; i--) + if (txf_bmap & ((u64)1 << i)) { + p_stats -= sizeof(struct bfi_ll_stats_txf)/ + sizeof(u64); + memcpy(&bna->stats.hw_stats->txf_stats[i], + p_stats, + sizeof(struct bfi_ll_stats_txf)); + } + + /* Populate the RXF stats from the firmware DMAed copy */ + for (i = (BFI_LL_RXF_ID_MAX - 1); i >= 0; i--) + if (rxf_bmap & ((u64)1 << i)) { + p_stats -= sizeof(struct bfi_ll_stats_rxf)/ + sizeof(u64); + memcpy(&bna->stats.hw_stats->rxf_stats[i], + p_stats, + sizeof(struct bfi_ll_stats_rxf)); + } + + bna_sw_stats_get(bna, bna->stats.sw_stats); + bnad_cb_stats_get(bna->bnad, BNA_CB_SUCCESS, &bna->stats); + } else + bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats); +} + +static void +bna_fw_stats_get(struct bna *bna) +{ + struct bfi_ll_stats_req ll_req; + + bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_GET_REQ, 0); + ll_req.stats_mask = htons(BFI_LL_STATS_ALL); + + ll_req.rxf_id_mask[0] = htonl(bna->rx_mod.rxf_bmap[0]); + ll_req.rxf_id_mask[1] = htonl(bna->rx_mod.rxf_bmap[1]); + ll_req.txf_id_mask[0] = htonl(bna->tx_mod.txf_bmap[0]); + ll_req.txf_id_mask[1] = htonl(bna->tx_mod.txf_bmap[1]); + + ll_req.host_buffer.a32.addr_hi = bna->hw_stats_dma.msb; + ll_req.host_buffer.a32.addr_lo = bna->hw_stats_dma.lsb; + + bna_mbox_qe_fill(&bna->mbox_qe, &ll_req, sizeof(ll_req), + bna_fw_cb_stats_get, bna); + bna_mbox_send(bna, &bna->mbox_qe); + + bna->stats.rxf_bmap[0] = bna->rx_mod.rxf_bmap[0]; + bna->stats.rxf_bmap[1] = bna->rx_mod.rxf_bmap[1]; + bna->stats.txf_bmap[0] = bna->tx_mod.txf_bmap[0]; + bna->stats.txf_bmap[1] = bna->tx_mod.txf_bmap[1]; +} + +static void +bna_fw_cb_stats_clr(void *arg, int status) +{ + struct bna *bna = (struct bna *)arg; + + bfa_q_qe_init(&bna->mbox_qe.qe); + + memset(bna->stats.sw_stats, 0, sizeof(struct bna_sw_stats)); + memset(bna->stats.hw_stats, 0, sizeof(struct bfi_ll_stats)); + + bnad_cb_stats_clr(bna->bnad); +} + +static void +bna_fw_stats_clr(struct bna *bna) +{ + struct bfi_ll_stats_req ll_req; + + bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0); + ll_req.stats_mask = htons(BFI_LL_STATS_ALL); + ll_req.rxf_id_mask[0] = htonl(0xffffffff); + ll_req.rxf_id_mask[1] = htonl(0xffffffff); + ll_req.txf_id_mask[0] = htonl(0xffffffff); + ll_req.txf_id_mask[1] = htonl(0xffffffff); + + bna_mbox_qe_fill(&bna->mbox_qe, &ll_req, sizeof(ll_req), + bna_fw_cb_stats_clr, bna); + bna_mbox_send(bna, &bna->mbox_qe); +} + +void +bna_stats_get(struct bna *bna) +{ + if (bna_device_status_get(&bna->device)) + bna_fw_stats_get(bna); + else + bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats); +} + +void +bna_stats_clr(struct bna *bna) +{ + if (bna_device_status_get(&bna->device)) + bna_fw_stats_clr(bna); + else { + memset(&bna->stats.sw_stats, 0, + sizeof(struct bna_sw_stats)); + memset(bna->stats.hw_stats, 0, + sizeof(struct bfi_ll_stats)); + bnad_cb_stats_clr(bna->bnad); + } +} + +/* IB */ +void +bna_ib_coalescing_timeo_set(struct bna_ib *ib, u8 coalescing_timeo) +{ + ib->ib_config.coalescing_timeo = coalescing_timeo; + + if (ib->start_count) + ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK( + (u32)ib->ib_config.coalescing_timeo, 0); +} + +/* RxF */ +void +bna_rxf_adv_init(struct bna_rxf *rxf, + struct bna_rx *rx, + struct bna_rx_config *q_config) +{ + switch (q_config->rxp_type) { + case BNA_RXP_SINGLE: + /* No-op */ + break; + case BNA_RXP_SLR: + rxf->ctrl_flags |= BNA_RXF_CF_SM_LG_RXQ; + break; + case BNA_RXP_HDS: + rxf->hds_cfg.hdr_type = q_config->hds_config.hdr_type; + rxf->hds_cfg.header_size = + q_config->hds_config.header_size; + rxf->forced_offset = 0; + break; + default: + break; + } + + if (q_config->rss_status == BNA_STATUS_T_ENABLED) { + rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE; + rxf->rss_cfg.hash_type = q_config->rss_config.hash_type; + rxf->rss_cfg.hash_mask = q_config->rss_config.hash_mask; + memcpy(&rxf->rss_cfg.toeplitz_hash_key[0], + &q_config->rss_config.toeplitz_hash_key[0], + sizeof(rxf->rss_cfg.toeplitz_hash_key)); + } +} + +static void +rxf_fltr_mbox_cmd(struct bna_rxf *rxf, u8 cmd, enum bna_status status) +{ + struct bfi_ll_rxf_req req; + + bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0); + + req.rxf_id = rxf->rxf_id; + req.enable = status; + + bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req), + rxf_cb_cam_fltr_mbox_cmd, rxf); + + bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe); +} + +void +__rxf_default_function_config(struct bna_rxf *rxf, enum bna_status status) +{ + struct bna_rx_fndb_ram *rx_fndb_ram; + u32 ctrl_flags; + int i; + + rx_fndb_ram = (struct bna_rx_fndb_ram *) + BNA_GET_MEM_BASE_ADDR(rxf->rx->bna->pcidev.pci_bar_kva, + RX_FNDB_RAM_BASE_OFFSET); + + for (i = 0; i < BFI_MAX_RXF; i++) { + if (status == BNA_STATUS_T_ENABLED) { + if (i == rxf->rxf_id) + continue; + + ctrl_flags = + readl(&rx_fndb_ram[i].control_flags); + ctrl_flags |= BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE; + writel(ctrl_flags, + &rx_fndb_ram[i].control_flags); + } else { + ctrl_flags = + readl(&rx_fndb_ram[i].control_flags); + ctrl_flags &= ~BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE; + writel(ctrl_flags, + &rx_fndb_ram[i].control_flags); + } + } +} + +int +rxf_process_packet_filter_ucast(struct bna_rxf *rxf) +{ + struct bna_mac *mac = NULL; + struct list_head *qe; + + /* Add additional MAC entries */ + if (!list_empty(&rxf->ucast_pending_add_q)) { + bfa_q_deq(&rxf->ucast_pending_add_q, &qe); + bfa_q_qe_init(qe); + mac = (struct bna_mac *)qe; + rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_ADD_REQ, mac); + list_add_tail(&mac->qe, &rxf->ucast_active_q); + return 1; + } + + /* Delete MAC addresses previousely added */ + if (!list_empty(&rxf->ucast_pending_del_q)) { + bfa_q_deq(&rxf->ucast_pending_del_q, &qe); + bfa_q_qe_init(qe); + mac = (struct bna_mac *)qe; + rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac); + bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac); + return 1; + } + + return 0; +} + +int +rxf_process_packet_filter_promisc(struct bna_rxf *rxf) +{ + struct bna *bna = rxf->rx->bna; + + /* Enable/disable promiscuous mode */ + if (is_promisc_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* move promisc configuration from pending -> active */ + promisc_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active |= BNA_RXMODE_PROMISC; + + /* Disable VLAN filter to allow all VLANs */ + __rxf_vlan_filter_set(rxf, BNA_STATUS_T_DISABLED); + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ, + BNA_STATUS_T_ENABLED); + return 1; + } else if (is_promisc_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* move promisc configuration from pending -> active */ + promisc_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_PROMISC; + bna->rxf_promisc_id = BFI_MAX_RXF; + + /* Revert VLAN filter */ + __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status); + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ, + BNA_STATUS_T_DISABLED); + return 1; + } + + return 0; +} + +int +rxf_process_packet_filter_default(struct bna_rxf *rxf) +{ + struct bna *bna = rxf->rx->bna; + + /* Enable/disable default mode */ + if (is_default_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* move default configuration from pending -> active */ + default_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active |= BNA_RXMODE_DEFAULT; + + /* Disable VLAN filter to allow all VLANs */ + __rxf_vlan_filter_set(rxf, BNA_STATUS_T_DISABLED); + /* Redirect all other RxF vlan filtering to this one */ + __rxf_default_function_config(rxf, BNA_STATUS_T_ENABLED); + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ, + BNA_STATUS_T_ENABLED); + return 1; + } else if (is_default_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* move default configuration from pending -> active */ + default_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT; + bna->rxf_default_id = BFI_MAX_RXF; + + /* Revert VLAN filter */ + __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status); + /* Stop RxF vlan filter table redirection */ + __rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED); + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ, + BNA_STATUS_T_DISABLED); + return 1; + } + + return 0; +} + +int +rxf_process_packet_filter_allmulti(struct bna_rxf *rxf) +{ + /* Enable/disable allmulti mode */ + if (is_allmulti_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* move allmulti configuration from pending -> active */ + allmulti_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active |= BNA_RXMODE_ALLMULTI; + + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ, + BNA_STATUS_T_ENABLED); + return 1; + } else if (is_allmulti_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* move allmulti configuration from pending -> active */ + allmulti_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI; + + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ, + BNA_STATUS_T_DISABLED); + return 1; + } + + return 0; +} + +int +rxf_clear_packet_filter_ucast(struct bna_rxf *rxf) +{ + struct bna_mac *mac = NULL; + struct list_head *qe; + + /* 1. delete pending ucast entries */ + if (!list_empty(&rxf->ucast_pending_del_q)) { + bfa_q_deq(&rxf->ucast_pending_del_q, &qe); + bfa_q_qe_init(qe); + mac = (struct bna_mac *)qe; + rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac); + bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac); + return 1; + } + + /* 2. clear active ucast entries; move them to pending_add_q */ + if (!list_empty(&rxf->ucast_active_q)) { + bfa_q_deq(&rxf->ucast_active_q, &qe); + bfa_q_qe_init(qe); + mac = (struct bna_mac *)qe; + rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac); + list_add_tail(&mac->qe, &rxf->ucast_pending_add_q); + return 1; + } + + return 0; +} + +int +rxf_clear_packet_filter_promisc(struct bna_rxf *rxf) +{ + struct bna *bna = rxf->rx->bna; + + /* 6. Execute pending promisc mode disable command */ + if (is_promisc_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* move promisc configuration from pending -> active */ + promisc_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_PROMISC; + bna->rxf_promisc_id = BFI_MAX_RXF; + + /* Revert VLAN filter */ + __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status); + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ, + BNA_STATUS_T_DISABLED); + return 1; + } + + /* 7. Clear active promisc mode; move it to pending enable */ + if (rxf->rxmode_active & BNA_RXMODE_PROMISC) { + /* move promisc configuration from active -> pending */ + promisc_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_PROMISC; + + /* Revert VLAN filter */ + __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status); + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ, + BNA_STATUS_T_DISABLED); + return 1; + } + + return 0; +} + +int +rxf_clear_packet_filter_default(struct bna_rxf *rxf) +{ + struct bna *bna = rxf->rx->bna; + + /* 8. Execute pending default mode disable command */ + if (is_default_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* move default configuration from pending -> active */ + default_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT; + bna->rxf_default_id = BFI_MAX_RXF; + + /* Revert VLAN filter */ + __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status); + /* Stop RxF vlan filter table redirection */ + __rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED); + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ, + BNA_STATUS_T_DISABLED); + return 1; + } + + /* 9. Clear active default mode; move it to pending enable */ + if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) { + /* move default configuration from active -> pending */ + default_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT; + + /* Revert VLAN filter */ + __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status); + /* Stop RxF vlan filter table redirection */ + __rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED); + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ, + BNA_STATUS_T_DISABLED); + return 1; + } + + return 0; +} + +int +rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf) +{ + /* 10. Execute pending allmulti mode disable command */ + if (is_allmulti_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* move allmulti configuration from pending -> active */ + allmulti_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI; + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ, + BNA_STATUS_T_DISABLED); + return 1; + } + + /* 11. Clear active allmulti mode; move it to pending enable */ + if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) { + /* move allmulti configuration from active -> pending */ + allmulti_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI; + rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ, + BNA_STATUS_T_DISABLED); + return 1; + } + + return 0; +} + +void +rxf_reset_packet_filter_ucast(struct bna_rxf *rxf) +{ + struct list_head *qe; + struct bna_mac *mac; + + /* 1. Move active ucast entries to pending_add_q */ + while (!list_empty(&rxf->ucast_active_q)) { + bfa_q_deq(&rxf->ucast_active_q, &qe); + bfa_q_qe_init(qe); + list_add_tail(qe, &rxf->ucast_pending_add_q); + } + + /* 2. Throw away delete pending ucast entries */ + while (!list_empty(&rxf->ucast_pending_del_q)) { + bfa_q_deq(&rxf->ucast_pending_del_q, &qe); + bfa_q_qe_init(qe); + mac = (struct bna_mac *)qe; + bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac); + } +} + +void +rxf_reset_packet_filter_promisc(struct bna_rxf *rxf) +{ + struct bna *bna = rxf->rx->bna; + + /* 6. Clear pending promisc mode disable */ + if (is_promisc_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + promisc_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_PROMISC; + bna->rxf_promisc_id = BFI_MAX_RXF; + } + + /* 7. Move promisc mode config from active -> pending */ + if (rxf->rxmode_active & BNA_RXMODE_PROMISC) { + promisc_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_PROMISC; + } + +} + +void +rxf_reset_packet_filter_default(struct bna_rxf *rxf) +{ + struct bna *bna = rxf->rx->bna; + + /* 8. Clear pending default mode disable */ + if (is_default_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + default_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT; + bna->rxf_default_id = BFI_MAX_RXF; + } + + /* 9. Move default mode config from active -> pending */ + if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) { + default_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT; + } +} + +void +rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf) +{ + /* 10. Clear pending allmulti mode disable */ + if (is_allmulti_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + allmulti_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI; + } + + /* 11. Move allmulti mode config from active -> pending */ + if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) { + allmulti_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI; + } +} + +/** + * Should only be called by bna_rxf_mode_set. + * Helps deciding if h/w configuration is needed or not. + * Returns: + * 0 = no h/w change + * 1 = need h/w change + */ +int +rxf_promisc_enable(struct bna_rxf *rxf) +{ + struct bna *bna = rxf->rx->bna; + int ret = 0; + + /* There can not be any pending disable command */ + + /* Do nothing if pending enable or already enabled */ + if (is_promisc_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask) || + (rxf->rxmode_active & BNA_RXMODE_PROMISC)) { + /* Schedule enable */ + } else { + /* Promisc mode should not be active in the system */ + promisc_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + bna->rxf_promisc_id = rxf->rxf_id; + ret = 1; + } + + return ret; +} + +/** + * Should only be called by bna_rxf_mode_set. + * Helps deciding if h/w configuration is needed or not. + * Returns: + * 0 = no h/w change + * 1 = need h/w change + */ +int +rxf_promisc_disable(struct bna_rxf *rxf) +{ + struct bna *bna = rxf->rx->bna; + int ret = 0; + + /* There can not be any pending disable */ + + /* Turn off pending enable command , if any */ + if (is_promisc_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* Promisc mode should not be active */ + /* system promisc state should be pending */ + promisc_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + /* Remove the promisc state from the system */ + bna->rxf_promisc_id = BFI_MAX_RXF; + + /* Schedule disable */ + } else if (rxf->rxmode_active & BNA_RXMODE_PROMISC) { + /* Promisc mode should be active in the system */ + promisc_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + ret = 1; + + /* Do nothing if already disabled */ + } else { + } + + return ret; +} + +/** + * Should only be called by bna_rxf_mode_set. + * Helps deciding if h/w configuration is needed or not. + * Returns: + * 0 = no h/w change + * 1 = need h/w change + */ +int +rxf_default_enable(struct bna_rxf *rxf) +{ + struct bna *bna = rxf->rx->bna; + int ret = 0; + + /* There can not be any pending disable command */ + + /* Do nothing if pending enable or already enabled */ + if (is_default_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask) || + (rxf->rxmode_active & BNA_RXMODE_DEFAULT)) { + /* Schedule enable */ + } else { + /* Default mode should not be active in the system */ + default_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + bna->rxf_default_id = rxf->rxf_id; + ret = 1; + } + + return ret; +} + +/** + * Should only be called by bna_rxf_mode_set. + * Helps deciding if h/w configuration is needed or not. + * Returns: + * 0 = no h/w change + * 1 = need h/w change + */ +int +rxf_default_disable(struct bna_rxf *rxf) +{ + struct bna *bna = rxf->rx->bna; + int ret = 0; + + /* There can not be any pending disable */ + + /* Turn off pending enable command , if any */ + if (is_default_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* Promisc mode should not be active */ + /* system default state should be pending */ + default_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + /* Remove the default state from the system */ + bna->rxf_default_id = BFI_MAX_RXF; + + /* Schedule disable */ + } else if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) { + /* Default mode should be active in the system */ + default_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + ret = 1; + + /* Do nothing if already disabled */ + } else { + } + + return ret; +} + +/** + * Should only be called by bna_rxf_mode_set. + * Helps deciding if h/w configuration is needed or not. + * Returns: + * 0 = no h/w change + * 1 = need h/w change + */ +int +rxf_allmulti_enable(struct bna_rxf *rxf) +{ + int ret = 0; + + /* There can not be any pending disable command */ + + /* Do nothing if pending enable or already enabled */ + if (is_allmulti_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask) || + (rxf->rxmode_active & BNA_RXMODE_ALLMULTI)) { + /* Schedule enable */ + } else { + allmulti_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + ret = 1; + } + + return ret; +} + +/** + * Should only be called by bna_rxf_mode_set. + * Helps deciding if h/w configuration is needed or not. + * Returns: + * 0 = no h/w change + * 1 = need h/w change + */ +int +rxf_allmulti_disable(struct bna_rxf *rxf) +{ + int ret = 0; + + /* There can not be any pending disable */ + + /* Turn off pending enable command , if any */ + if (is_allmulti_enable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask)) { + /* Allmulti mode should not be active */ + allmulti_inactive(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + + /* Schedule disable */ + } else if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) { + allmulti_disable(rxf->rxmode_pending, + rxf->rxmode_pending_bitmask); + ret = 1; + } + + return ret; +} + +/* RxF <- bnad */ +void +bna_rx_mcast_delall(struct bna_rx *rx, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)) +{ + struct bna_rxf *rxf = &rx->rxf; + struct list_head *qe; + struct bna_mac *mac; + int need_hw_config = 0; + + /* Purge all entries from pending_add_q */ + while (!list_empty(&rxf->mcast_pending_add_q)) { + bfa_q_deq(&rxf->mcast_pending_add_q, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac); + } + + /* Schedule all entries in active_q for deletion */ + while (!list_empty(&rxf->mcast_active_q)) { + bfa_q_deq(&rxf->mcast_active_q, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + list_add_tail(&mac->qe, &rxf->mcast_pending_del_q); + need_hw_config = 1; + } + + if (need_hw_config) { + rxf->cam_fltr_cbfn = cbfn; + rxf->cam_fltr_cbarg = rx->bna->bnad; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + return; + } + + if (cbfn) + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); +} + +/* RxF <- Rx */ +void +bna_rx_receive_resume(struct bna_rx *rx, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)) +{ + struct bna_rxf *rxf = &rx->rxf; + + if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED) { + rxf->oper_state_cbfn = cbfn; + rxf->oper_state_cbarg = rx->bna->bnad; + bfa_fsm_send_event(rxf, RXF_E_RESUME); + } else if (cbfn) + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); +} + +void +bna_rx_receive_pause(struct bna_rx *rx, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)) +{ + struct bna_rxf *rxf = &rx->rxf; + + if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_RUNNING) { + rxf->oper_state_cbfn = cbfn; + rxf->oper_state_cbarg = rx->bna->bnad; + bfa_fsm_send_event(rxf, RXF_E_PAUSE); + } else if (cbfn) + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); +} + +/* RxF <- bnad */ +enum bna_cb_status +bna_rx_ucast_add(struct bna_rx *rx, u8 *addr, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)) +{ + struct bna_rxf *rxf = &rx->rxf; + struct list_head *qe; + struct bna_mac *mac; + + /* Check if already added */ + list_for_each(qe, &rxf->ucast_active_q) { + mac = (struct bna_mac *)qe; + if (BNA_MAC_IS_EQUAL(mac->addr, addr)) { + if (cbfn) + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); + return BNA_CB_SUCCESS; + } + } + + /* Check if pending addition */ + list_for_each(qe, &rxf->ucast_pending_add_q) { + mac = (struct bna_mac *)qe; + if (BNA_MAC_IS_EQUAL(mac->addr, addr)) { + if (cbfn) + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); + return BNA_CB_SUCCESS; + } + } + + mac = bna_ucam_mod_mac_get(&rxf->rx->bna->ucam_mod); + if (mac == NULL) + return BNA_CB_UCAST_CAM_FULL; + bfa_q_qe_init(&mac->qe); + memcpy(mac->addr, addr, ETH_ALEN); + list_add_tail(&mac->qe, &rxf->ucast_pending_add_q); + + rxf->cam_fltr_cbfn = cbfn; + rxf->cam_fltr_cbarg = rx->bna->bnad; + + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + + return BNA_CB_SUCCESS; +} + +/* RxF <- bnad */ +enum bna_cb_status +bna_rx_ucast_del(struct bna_rx *rx, u8 *addr, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)) +{ + struct bna_rxf *rxf = &rx->rxf; + struct list_head *qe; + struct bna_mac *mac; + + list_for_each(qe, &rxf->ucast_pending_add_q) { + mac = (struct bna_mac *)qe; + if (BNA_MAC_IS_EQUAL(mac->addr, addr)) { + list_del(qe); + bfa_q_qe_init(qe); + bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac); + if (cbfn) + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); + return BNA_CB_SUCCESS; + } + } + + list_for_each(qe, &rxf->ucast_active_q) { + mac = (struct bna_mac *)qe; + if (BNA_MAC_IS_EQUAL(mac->addr, addr)) { + list_del(qe); + bfa_q_qe_init(qe); + list_add_tail(qe, &rxf->ucast_pending_del_q); + rxf->cam_fltr_cbfn = cbfn; + rxf->cam_fltr_cbarg = rx->bna->bnad; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + return BNA_CB_SUCCESS; + } + } + + return BNA_CB_INVALID_MAC; +} + +/* RxF <- bnad */ +enum bna_cb_status +bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode new_mode, + enum bna_rxmode bitmask, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)) +{ + struct bna_rxf *rxf = &rx->rxf; + int need_hw_config = 0; + + /* Error checks */ + + if (is_promisc_enable(new_mode, bitmask)) { + /* If promisc mode is already enabled elsewhere in the system */ + if ((rx->bna->rxf_promisc_id != BFI_MAX_RXF) && + (rx->bna->rxf_promisc_id != rxf->rxf_id)) + goto err_return; + + /* If default mode is already enabled in the system */ + if (rx->bna->rxf_default_id != BFI_MAX_RXF) + goto err_return; + + /* Trying to enable promiscuous and default mode together */ + if (is_default_enable(new_mode, bitmask)) + goto err_return; + } + + if (is_default_enable(new_mode, bitmask)) { + /* If default mode is already enabled elsewhere in the system */ + if ((rx->bna->rxf_default_id != BFI_MAX_RXF) && + (rx->bna->rxf_default_id != rxf->rxf_id)) { + goto err_return; + } + + /* If promiscuous mode is already enabled in the system */ + if (rx->bna->rxf_promisc_id != BFI_MAX_RXF) + goto err_return; + } + + /* Process the commands */ + + if (is_promisc_enable(new_mode, bitmask)) { + if (rxf_promisc_enable(rxf)) + need_hw_config = 1; + } else if (is_promisc_disable(new_mode, bitmask)) { + if (rxf_promisc_disable(rxf)) + need_hw_config = 1; + } + + if (is_default_enable(new_mode, bitmask)) { + if (rxf_default_enable(rxf)) + need_hw_config = 1; + } else if (is_default_disable(new_mode, bitmask)) { + if (rxf_default_disable(rxf)) + need_hw_config = 1; + } + + if (is_allmulti_enable(new_mode, bitmask)) { + if (rxf_allmulti_enable(rxf)) + need_hw_config = 1; + } else if (is_allmulti_disable(new_mode, bitmask)) { + if (rxf_allmulti_disable(rxf)) + need_hw_config = 1; + } + + /* Trigger h/w if needed */ + + if (need_hw_config) { + rxf->cam_fltr_cbfn = cbfn; + rxf->cam_fltr_cbarg = rx->bna->bnad; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + } else if (cbfn) + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); + + return BNA_CB_SUCCESS; + +err_return: + return BNA_CB_FAIL; +} + +/* RxF <- bnad */ +void +bna_rx_rss_enable(struct bna_rx *rx) +{ + struct bna_rxf *rxf = &rx->rxf; + + rxf->rxf_flags |= BNA_RXF_FL_RSS_CONFIG_PENDING; + rxf->rss_status = BNA_STATUS_T_ENABLED; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); +} + +/* RxF <- bnad */ +void +bna_rx_rss_disable(struct bna_rx *rx) +{ + struct bna_rxf *rxf = &rx->rxf; + + rxf->rxf_flags |= BNA_RXF_FL_RSS_CONFIG_PENDING; + rxf->rss_status = BNA_STATUS_T_DISABLED; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); +} + +/* RxF <- bnad */ +void +bna_rx_rss_reconfig(struct bna_rx *rx, struct bna_rxf_rss *rss_config) +{ + struct bna_rxf *rxf = &rx->rxf; + rxf->rxf_flags |= BNA_RXF_FL_RSS_CONFIG_PENDING; + rxf->rss_status = BNA_STATUS_T_ENABLED; + rxf->rss_cfg = *rss_config; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); +} + +void +/* RxF <- bnad */ +bna_rx_vlanfilter_enable(struct bna_rx *rx) +{ + struct bna_rxf *rxf = &rx->rxf; + + if (rxf->vlan_filter_status == BNA_STATUS_T_DISABLED) { + rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING; + rxf->vlan_filter_status = BNA_STATUS_T_ENABLED; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + } +} + +/* RxF <- bnad */ +void +bna_rx_vlanfilter_disable(struct bna_rx *rx) +{ + struct bna_rxf *rxf = &rx->rxf; + + if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) { + rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING; + rxf->vlan_filter_status = BNA_STATUS_T_DISABLED; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + } +} + +/* Rx */ + +struct bna_rxp * +bna_rx_get_rxp(struct bna_rx *rx, int vector) +{ + struct bna_rxp *rxp; + struct list_head *qe; + + list_for_each(qe, &rx->rxp_q) { + rxp = (struct bna_rxp *)qe; + if (rxp->vector == vector) + return rxp; + } + return NULL; +} + +/* + * bna_rx_rss_rit_set() + * Sets the Q ids for the specified msi-x vectors in the RIT. + * Maximum rit size supported is 64, which should be the max size of the + * vectors array. + */ + +void +bna_rx_rss_rit_set(struct bna_rx *rx, unsigned int *vectors, int nvectors) +{ + int i; + struct bna_rxp *rxp; + struct bna_rxq *q0 = NULL, *q1 = NULL; + struct bna *bna; + struct bna_rxf *rxf; + + /* Build the RIT contents for this RX */ + bna = rx->bna; + + rxf = &rx->rxf; + for (i = 0; i < nvectors; i++) { + rxp = bna_rx_get_rxp(rx, vectors[i]); + + GET_RXQS(rxp, q0, q1); + rxf->rit_segment->rit[i].large_rxq_id = q0->rxq_id; + rxf->rit_segment->rit[i].small_rxq_id = (q1 ? q1->rxq_id : 0); + } + + rxf->rit_segment->rit_size = nvectors; + + /* Subsequent call to enable/reconfig RSS will update the RIT in h/w */ +} + +/* Rx <- bnad */ +void +bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo) +{ + struct bna_rxp *rxp; + struct list_head *qe; + + list_for_each(qe, &rx->rxp_q) { + rxp = (struct bna_rxp *)qe; + rxp->cq.ccb->rx_coalescing_timeo = coalescing_timeo; + bna_ib_coalescing_timeo_set(rxp->cq.ib, coalescing_timeo); + } +} + +/* Rx <- bnad */ +void +bna_rx_dim_reconfig(struct bna *bna, u32 vector[][BNA_BIAS_T_MAX]) +{ + int i, j; + + for (i = 0; i < BNA_LOAD_T_MAX; i++) + for (j = 0; j < BNA_BIAS_T_MAX; j++) + bna->rx_mod.dim_vector[i][j] = vector[i][j]; +} + +/* Rx <- bnad */ +void +bna_rx_dim_update(struct bna_ccb *ccb) +{ + struct bna *bna = ccb->cq->rx->bna; + u32 load, bias; + u32 pkt_rt, small_rt, large_rt; + u8 coalescing_timeo; + + if ((ccb->pkt_rate.small_pkt_cnt == 0) && + (ccb->pkt_rate.large_pkt_cnt == 0)) + return; + + /* Arrive at preconfigured coalescing timeo value based on pkt rate */ + + small_rt = ccb->pkt_rate.small_pkt_cnt; + large_rt = ccb->pkt_rate.large_pkt_cnt; + + pkt_rt = small_rt + large_rt; + + if (pkt_rt < BNA_PKT_RATE_10K) + load = BNA_LOAD_T_LOW_4; + else if (pkt_rt < BNA_PKT_RATE_20K) + load = BNA_LOAD_T_LOW_3; + else if (pkt_rt < BNA_PKT_RATE_30K) + load = BNA_LOAD_T_LOW_2; + else if (pkt_rt < BNA_PKT_RATE_40K) + load = BNA_LOAD_T_LOW_1; + else if (pkt_rt < BNA_PKT_RATE_50K) + load = BNA_LOAD_T_HIGH_1; + else if (pkt_rt < BNA_PKT_RATE_60K) + load = BNA_LOAD_T_HIGH_2; + else if (pkt_rt < BNA_PKT_RATE_80K) + load = BNA_LOAD_T_HIGH_3; + else + load = BNA_LOAD_T_HIGH_4; + + if (small_rt > (large_rt << 1)) + bias = 0; + else + bias = 1; + + ccb->pkt_rate.small_pkt_cnt = 0; + ccb->pkt_rate.large_pkt_cnt = 0; + + coalescing_timeo = bna->rx_mod.dim_vector[load][bias]; + ccb->rx_coalescing_timeo = coalescing_timeo; + + /* Set it to IB */ + bna_ib_coalescing_timeo_set(ccb->cq->ib, coalescing_timeo); +} + +/* Tx */ +/* TX <- bnad */ +enum bna_cb_status +bna_tx_prio_set(struct bna_tx *tx, int prio, + void (*cbfn)(struct bnad *, struct bna_tx *, + enum bna_cb_status)) +{ + if (tx->flags & BNA_TX_F_PRIO_LOCK) + return BNA_CB_FAIL; + else { + tx->prio_change_cbfn = cbfn; + bna_tx_prio_changed(tx, prio); + } + + return BNA_CB_SUCCESS; +} + +/* TX <- bnad */ +void +bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo) +{ + struct bna_txq *txq; + struct list_head *qe; + + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + bna_ib_coalescing_timeo_set(txq->ib, coalescing_timeo); + } +} + +/* + * Private data + */ + +struct bna_ritseg_pool_cfg { + u32 pool_size; + u32 pool_entry_size; +}; +init_ritseg_pool(ritseg_pool_cfg); + +/* + * Private functions + */ +static void +bna_ucam_mod_init(struct bna_ucam_mod *ucam_mod, struct bna *bna, + struct bna_res_info *res_info) +{ + int i; + + ucam_mod->ucmac = (struct bna_mac *) + res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mdl[0].kva; + + INIT_LIST_HEAD(&ucam_mod->free_q); + for (i = 0; i < BFI_MAX_UCMAC; i++) { + bfa_q_qe_init(&ucam_mod->ucmac[i].qe); + list_add_tail(&ucam_mod->ucmac[i].qe, &ucam_mod->free_q); + } + + ucam_mod->bna = bna; +} + +static void +bna_ucam_mod_uninit(struct bna_ucam_mod *ucam_mod) +{ + struct list_head *qe; + int i = 0; + + list_for_each(qe, &ucam_mod->free_q) + i++; + + ucam_mod->bna = NULL; +} + +static void +bna_mcam_mod_init(struct bna_mcam_mod *mcam_mod, struct bna *bna, + struct bna_res_info *res_info) +{ + int i; + + mcam_mod->mcmac = (struct bna_mac *) + res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mdl[0].kva; + + INIT_LIST_HEAD(&mcam_mod->free_q); + for (i = 0; i < BFI_MAX_MCMAC; i++) { + bfa_q_qe_init(&mcam_mod->mcmac[i].qe); + list_add_tail(&mcam_mod->mcmac[i].qe, &mcam_mod->free_q); + } + + mcam_mod->bna = bna; +} + +static void +bna_mcam_mod_uninit(struct bna_mcam_mod *mcam_mod) +{ + struct list_head *qe; + int i = 0; + + list_for_each(qe, &mcam_mod->free_q) + i++; + + mcam_mod->bna = NULL; +} + +static void +bna_rit_mod_init(struct bna_rit_mod *rit_mod, + struct bna_res_info *res_info) +{ + int i; + int j; + int count; + int offset; + + rit_mod->rit = (struct bna_rit_entry *) + res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mdl[0].kva; + rit_mod->rit_segment = (struct bna_rit_segment *) + res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mdl[0].kva; + + count = 0; + offset = 0; + for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) { + INIT_LIST_HEAD(&rit_mod->rit_seg_pool[i]); + for (j = 0; j < ritseg_pool_cfg[i].pool_size; j++) { + bfa_q_qe_init(&rit_mod->rit_segment[count].qe); + rit_mod->rit_segment[count].max_rit_size = + ritseg_pool_cfg[i].pool_entry_size; + rit_mod->rit_segment[count].rit_offset = offset; + rit_mod->rit_segment[count].rit = + &rit_mod->rit[offset]; + list_add_tail(&rit_mod->rit_segment[count].qe, + &rit_mod->rit_seg_pool[i]); + count++; + offset += ritseg_pool_cfg[i].pool_entry_size; + } + } +} + +static void +bna_rit_mod_uninit(struct bna_rit_mod *rit_mod) +{ + struct bna_rit_segment *rit_segment; + struct list_head *qe; + int i; + int j; + + for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) { + j = 0; + list_for_each(qe, &rit_mod->rit_seg_pool[i]) { + rit_segment = (struct bna_rit_segment *)qe; + j++; + } + } +} + +/* + * Public functions + */ + +/* Called during probe(), before calling bna_init() */ +void +bna_res_req(struct bna_res_info *res_info) +{ + bna_adv_res_req(res_info); + + /* DMA memory for retrieving IOC attributes */ + res_info[BNA_RES_MEM_T_ATTR].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mem_type = BNA_MEM_T_DMA; + res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.len = + ALIGN(bfa_ioc_meminfo(), PAGE_SIZE); + + /* DMA memory for index segment of an IB */ + res_info[BNA_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mem_type = BNA_MEM_T_DMA; + res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.len = + BFI_IBIDX_SIZE * BFI_IBIDX_MAX_SEGSIZE; + res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.num = BFI_MAX_IB; + + /* Virtual memory for IB objects - stored by IB module */ + res_info[BNA_RES_MEM_T_IB_ARRAY].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.len = + BFI_MAX_IB * sizeof(struct bna_ib); + + /* Virtual memory for intr objects - stored by IB module */ + res_info[BNA_RES_MEM_T_INTR_ARRAY].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.len = + BFI_MAX_IB * sizeof(struct bna_intr); + + /* Virtual memory for idx_seg objects - stored by IB module */ + res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.len = + BFI_IBIDX_TOTAL_SEGS * sizeof(struct bna_ibidx_seg); + + /* Virtual memory for Tx objects - stored by Tx module */ + res_info[BNA_RES_MEM_T_TX_ARRAY].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.len = + BFI_MAX_TXQ * sizeof(struct bna_tx); + + /* Virtual memory for TxQ - stored by Tx module */ + res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.len = + BFI_MAX_TXQ * sizeof(struct bna_txq); + + /* Virtual memory for Rx objects - stored by Rx module */ + res_info[BNA_RES_MEM_T_RX_ARRAY].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.len = + BFI_MAX_RXQ * sizeof(struct bna_rx); + + /* Virtual memory for RxPath - stored by Rx module */ + res_info[BNA_RES_MEM_T_RXP_ARRAY].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.len = + BFI_MAX_RXQ * sizeof(struct bna_rxp); + + /* Virtual memory for RxQ - stored by Rx module */ + res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.len = + BFI_MAX_RXQ * sizeof(struct bna_rxq); + + /* Virtual memory for Unicast MAC address - stored by ucam module */ + res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.len = + BFI_MAX_UCMAC * sizeof(struct bna_mac); + + /* Virtual memory for Multicast MAC address - stored by mcam module */ + res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.len = + BFI_MAX_MCMAC * sizeof(struct bna_mac); + + /* Virtual memory for RIT entries */ + res_info[BNA_RES_MEM_T_RIT_ENTRY].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.len = + BFI_MAX_RIT_SIZE * sizeof(struct bna_rit_entry); + + /* Virtual memory for RIT segment table */ + res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_type = BNA_RES_T_MEM; + res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mem_type = + BNA_MEM_T_KVA; + res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.num = 1; + res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.len = + BFI_RIT_TOTAL_SEGS * sizeof(struct bna_rit_segment); + + /* Interrupt resource for mailbox interrupt */ + res_info[BNA_RES_INTR_T_MBOX].res_type = BNA_RES_T_INTR; + res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type = + BNA_INTR_T_MSIX; + res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.num = 1; +} + +/* Called during probe() */ +void +bna_init(struct bna *bna, struct bnad *bnad, struct bfa_pcidev *pcidev, + struct bna_res_info *res_info) +{ + bna->bnad = bnad; + bna->pcidev = *pcidev; + + bna->stats.hw_stats = (struct bfi_ll_stats *) + res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].kva; + bna->hw_stats_dma.msb = + res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.msb; + bna->hw_stats_dma.lsb = + res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.lsb; + bna->stats.sw_stats = (struct bna_sw_stats *) + res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mdl[0].kva; + + bna->regs.page_addr = bna->pcidev.pci_bar_kva + + reg_offset[bna->pcidev.pci_func].page_addr; + bna->regs.fn_int_status = bna->pcidev.pci_bar_kva + + reg_offset[bna->pcidev.pci_func].fn_int_status; + bna->regs.fn_int_mask = bna->pcidev.pci_bar_kva + + reg_offset[bna->pcidev.pci_func].fn_int_mask; + + if (bna->pcidev.pci_func < 3) + bna->port_num = 0; + else + bna->port_num = 1; + + /* Also initializes diag, cee, sfp, phy_port and mbox_mod */ + bna_device_init(&bna->device, bna, res_info); + + bna_port_init(&bna->port, bna); + + bna_tx_mod_init(&bna->tx_mod, bna, res_info); + + bna_rx_mod_init(&bna->rx_mod, bna, res_info); + + bna_ib_mod_init(&bna->ib_mod, bna, res_info); + + bna_rit_mod_init(&bna->rit_mod, res_info); + + bna_ucam_mod_init(&bna->ucam_mod, bna, res_info); + + bna_mcam_mod_init(&bna->mcam_mod, bna, res_info); + + bna->rxf_default_id = BFI_MAX_RXF; + bna->rxf_promisc_id = BFI_MAX_RXF; + + /* Mbox q element for posting stat request to f/w */ + bfa_q_qe_init(&bna->mbox_qe.qe); +} + +void +bna_uninit(struct bna *bna) +{ + bna_mcam_mod_uninit(&bna->mcam_mod); + + bna_ucam_mod_uninit(&bna->ucam_mod); + + bna_rit_mod_uninit(&bna->rit_mod); + + bna_ib_mod_uninit(&bna->ib_mod); + + bna_rx_mod_uninit(&bna->rx_mod); + + bna_tx_mod_uninit(&bna->tx_mod); + + bna_port_uninit(&bna->port); + + bna_device_uninit(&bna->device); + + bna->bnad = NULL; +} + +struct bna_mac * +bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod) +{ + struct list_head *qe; + + if (list_empty(&ucam_mod->free_q)) + return NULL; + + bfa_q_deq(&ucam_mod->free_q, &qe); + + return (struct bna_mac *)qe; +} + +void +bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod, struct bna_mac *mac) +{ + list_add_tail(&mac->qe, &ucam_mod->free_q); +} + +struct bna_mac * +bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod) +{ + struct list_head *qe; + + if (list_empty(&mcam_mod->free_q)) + return NULL; + + bfa_q_deq(&mcam_mod->free_q, &qe); + + return (struct bna_mac *)qe; +} + +void +bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod, struct bna_mac *mac) +{ + list_add_tail(&mac->qe, &mcam_mod->free_q); +} + +/** + * Note: This should be called in the same locking context as the call to + * bna_rit_mod_seg_get() + */ +int +bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size) +{ + int i; + + /* Select the pool for seg_size */ + for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) { + if (seg_size <= ritseg_pool_cfg[i].pool_entry_size) + break; + } + + if (i == BFI_RIT_SEG_TOTAL_POOLS) + return 0; + + if (list_empty(&rit_mod->rit_seg_pool[i])) + return 0; + + return 1; +} + +struct bna_rit_segment * +bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size) +{ + struct bna_rit_segment *seg; + struct list_head *qe; + int i; + + /* Select the pool for seg_size */ + for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) { + if (seg_size <= ritseg_pool_cfg[i].pool_entry_size) + break; + } + + if (i == BFI_RIT_SEG_TOTAL_POOLS) + return NULL; + + if (list_empty(&rit_mod->rit_seg_pool[i])) + return NULL; + + bfa_q_deq(&rit_mod->rit_seg_pool[i], &qe); + seg = (struct bna_rit_segment *)qe; + bfa_q_qe_init(&seg->qe); + seg->rit_size = seg_size; + + return seg; +} + +void +bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod, + struct bna_rit_segment *seg) +{ + int i; + + /* Select the pool for seg->max_rit_size */ + for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) { + if (seg->max_rit_size == ritseg_pool_cfg[i].pool_entry_size) + break; + } + + seg->rit_size = 0; + list_add_tail(&seg->qe, &rit_mod->rit_seg_pool[i]); +} diff --git a/drivers/net/bna/bna_hw.h b/drivers/net/bna/bna_hw.h new file mode 100644 index 000000000000..67eb376c5c7e --- /dev/null +++ b/drivers/net/bna/bna_hw.h @@ -0,0 +1,1491 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + * + * File for interrupt macros and functions + */ + +#ifndef __BNA_HW_H__ +#define __BNA_HW_H__ + +#include "bfi_ctreg.h" + +/** + * + * SW imposed limits + * + */ + +#ifndef BNA_BIOS_BUILD + +#define BFI_MAX_TXQ 64 +#define BFI_MAX_RXQ 64 +#define BFI_MAX_RXF 64 +#define BFI_MAX_IB 128 +#define BFI_MAX_RIT_SIZE 256 +#define BFI_RSS_RIT_SIZE 64 +#define BFI_NONRSS_RIT_SIZE 1 +#define BFI_MAX_UCMAC 256 +#define BFI_MAX_MCMAC 512 +#define BFI_IBIDX_SIZE 4 +#define BFI_MAX_VLAN 4095 + +/** + * There are 2 free IB index pools: + * pool1: 120 segments of 1 index each + * pool8: 1 segment of 8 indexes + */ +#define BFI_IBIDX_POOL1_SIZE 116 +#define BFI_IBIDX_POOL1_ENTRY_SIZE 1 +#define BFI_IBIDX_POOL2_SIZE 2 +#define BFI_IBIDX_POOL2_ENTRY_SIZE 2 +#define BFI_IBIDX_POOL8_SIZE 1 +#define BFI_IBIDX_POOL8_ENTRY_SIZE 8 +#define BFI_IBIDX_TOTAL_POOLS 3 +#define BFI_IBIDX_TOTAL_SEGS 119 /* (POOL1 + POOL2 + POOL8)_SIZE */ +#define BFI_IBIDX_MAX_SEGSIZE 8 +#define init_ibidx_pool(name) \ +static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] = \ +{ \ + { BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE }, \ + { BFI_IBIDX_POOL2_SIZE, BFI_IBIDX_POOL2_ENTRY_SIZE }, \ + { BFI_IBIDX_POOL8_SIZE, BFI_IBIDX_POOL8_ENTRY_SIZE } \ +} + +/** + * There are 2 free RIT segment pools: + * Pool1: 192 segments of 1 RIT entry each + * Pool2: 1 segment of 64 RIT entry + */ +#define BFI_RIT_SEG_POOL1_SIZE 192 +#define BFI_RIT_SEG_POOL1_ENTRY_SIZE 1 +#define BFI_RIT_SEG_POOLRSS_SIZE 1 +#define BFI_RIT_SEG_POOLRSS_ENTRY_SIZE 64 +#define BFI_RIT_SEG_TOTAL_POOLS 2 +#define BFI_RIT_TOTAL_SEGS 193 /* POOL1_SIZE + POOLRSS_SIZE */ +#define init_ritseg_pool(name) \ +static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] = \ +{ \ + { BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE }, \ + { BFI_RIT_SEG_POOLRSS_SIZE, BFI_RIT_SEG_POOLRSS_ENTRY_SIZE } \ +} + +#else /* BNA_BIOS_BUILD */ + +#define BFI_MAX_TXQ 1 +#define BFI_MAX_RXQ 1 +#define BFI_MAX_RXF 1 +#define BFI_MAX_IB 2 +#define BFI_MAX_RIT_SIZE 2 +#define BFI_RSS_RIT_SIZE 64 +#define BFI_NONRSS_RIT_SIZE 1 +#define BFI_MAX_UCMAC 1 +#define BFI_MAX_MCMAC 8 +#define BFI_IBIDX_SIZE 4 +#define BFI_MAX_VLAN 4095 +/* There is one free pool: 2 segments of 1 index each */ +#define BFI_IBIDX_POOL1_SIZE 2 +#define BFI_IBIDX_POOL1_ENTRY_SIZE 1 +#define BFI_IBIDX_TOTAL_POOLS 1 +#define BFI_IBIDX_TOTAL_SEGS 2 /* POOL1_SIZE */ +#define BFI_IBIDX_MAX_SEGSIZE 1 +#define init_ibidx_pool(name) \ +static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] = \ +{ \ + { BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE } \ +} + +#define BFI_RIT_SEG_POOL1_SIZE 1 +#define BFI_RIT_SEG_POOL1_ENTRY_SIZE 1 +#define BFI_RIT_SEG_TOTAL_POOLS 1 +#define BFI_RIT_TOTAL_SEGS 1 /* POOL1_SIZE */ +#define init_ritseg_pool(name) \ +static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] = \ +{ \ + { BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE } \ +} + +#endif /* BNA_BIOS_BUILD */ + +#define BFI_RSS_HASH_KEY_LEN 10 + +#define BFI_COALESCING_TIMER_UNIT 5 /* 5us */ +#define BFI_MAX_COALESCING_TIMEO 0xFF /* in 5us units */ +#define BFI_MAX_INTERPKT_COUNT 0xFF +#define BFI_MAX_INTERPKT_TIMEO 0xF /* in 0.5us units */ +#define BFI_TX_COALESCING_TIMEO 20 /* 20 * 5 = 100us */ +#define BFI_TX_INTERPKT_COUNT 32 +#define BFI_RX_COALESCING_TIMEO 12 /* 12 * 5 = 60us */ +#define BFI_RX_INTERPKT_COUNT 6 /* Pkt Cnt = 6 */ +#define BFI_RX_INTERPKT_TIMEO 3 /* 3 * 0.5 = 1.5us */ + +#define BFI_TXQ_WI_SIZE 64 /* bytes */ +#define BFI_RXQ_WI_SIZE 8 /* bytes */ +#define BFI_CQ_WI_SIZE 16 /* bytes */ +#define BFI_TX_MAX_WRR_QUOTA 0xFFF + +#define BFI_TX_MAX_VECTORS_PER_WI 4 +#define BFI_TX_MAX_VECTORS_PER_PKT 0xFF +#define BFI_TX_MAX_DATA_PER_VECTOR 0xFFFF +#define BFI_TX_MAX_DATA_PER_PKT 0xFFFFFF + +/* Small Q buffer size */ +#define BFI_SMALL_RXBUF_SIZE 128 + +/* Defined separately since BFA_FLASH_DMA_BUF_SZ is in bfa_flash.c */ +#define BFI_FLASH_DMA_BUF_SZ 0x010000 /* 64K DMA */ +#define BFI_HW_STATS_SIZE 0x4000 /* 16K DMA */ + +/** + * + * HW register offsets, macros + * + */ + +/* DMA Block Register Host Window Start Address */ +#define DMA_BLK_REG_ADDR 0x00013000 + +/* DMA Block Internal Registers */ +#define DMA_CTRL_REG0 (DMA_BLK_REG_ADDR + 0x000) +#define DMA_CTRL_REG1 (DMA_BLK_REG_ADDR + 0x004) +#define DMA_ERR_INT_STATUS (DMA_BLK_REG_ADDR + 0x008) +#define DMA_ERR_INT_ENABLE (DMA_BLK_REG_ADDR + 0x00c) +#define DMA_ERR_INT_STATUS_SET (DMA_BLK_REG_ADDR + 0x010) + +/* APP Block Register Address Offset from BAR0 */ +#define APP_BLK_REG_ADDR 0x00014000 + +/* Host Function Interrupt Mask Registers */ +#define HOSTFN0_INT_MASK (APP_BLK_REG_ADDR + 0x004) +#define HOSTFN1_INT_MASK (APP_BLK_REG_ADDR + 0x104) +#define HOSTFN2_INT_MASK (APP_BLK_REG_ADDR + 0x304) +#define HOSTFN3_INT_MASK (APP_BLK_REG_ADDR + 0x404) + +/** + * Host Function PCIe Error Registers + * Duplicates "Correctable" & "Uncorrectable" + * registers in PCIe Config space. + */ +#define FN0_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x014) +#define FN1_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x114) +#define FN2_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x314) +#define FN3_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x414) + +/* Host Function Error Type Status Registers */ +#define FN0_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x018) +#define FN1_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x118) +#define FN2_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x318) +#define FN3_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x418) + +/* Host Function Error Type Mask Registers */ +#define FN0_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x01c) +#define FN1_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x11c) +#define FN2_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x31c) +#define FN3_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x41c) + +/* Catapult Host Semaphore Status Registers (App block) */ +#define HOST_SEM_STS0_REG (APP_BLK_REG_ADDR + 0x630) +#define HOST_SEM_STS1_REG (APP_BLK_REG_ADDR + 0x634) +#define HOST_SEM_STS2_REG (APP_BLK_REG_ADDR + 0x638) +#define HOST_SEM_STS3_REG (APP_BLK_REG_ADDR + 0x63c) +#define HOST_SEM_STS4_REG (APP_BLK_REG_ADDR + 0x640) +#define HOST_SEM_STS5_REG (APP_BLK_REG_ADDR + 0x644) +#define HOST_SEM_STS6_REG (APP_BLK_REG_ADDR + 0x648) +#define HOST_SEM_STS7_REG (APP_BLK_REG_ADDR + 0x64c) + +/* PCIe Misc Register */ +#define PCIE_MISC_REG (APP_BLK_REG_ADDR + 0x200) + +/* Temp Sensor Control Registers */ +#define TEMPSENSE_CNTL_REG (APP_BLK_REG_ADDR + 0x250) +#define TEMPSENSE_STAT_REG (APP_BLK_REG_ADDR + 0x254) + +/* APP Block local error registers */ +#define APP_LOCAL_ERR_STAT (APP_BLK_REG_ADDR + 0x258) +#define APP_LOCAL_ERR_MSK (APP_BLK_REG_ADDR + 0x25c) + +/* PCIe Link Error registers */ +#define PCIE_LNK_ERR_STAT (APP_BLK_REG_ADDR + 0x260) +#define PCIE_LNK_ERR_MSK (APP_BLK_REG_ADDR + 0x264) + +/** + * FCoE/FIP Ethertype Register + * 31:16 -- Chip wide value for FIP type + * 15:0 -- Chip wide value for FCoE type + */ +#define FCOE_FIP_ETH_TYPE (APP_BLK_REG_ADDR + 0x280) + +/** + * Reserved Ethertype Register + * 31:16 -- Reserved + * 15:0 -- Other ethertype + */ +#define RESV_ETH_TYPE (APP_BLK_REG_ADDR + 0x284) + +/** + * Host Command Status Registers + * Each set consists of 3 registers : + * clear, set, cmd + * 16 such register sets in all + * See catapult_spec.pdf for detailed functionality + * Put each type in a single macro accessed by _num ? + */ +#define HOST_CMDSTS0_CLR_REG (APP_BLK_REG_ADDR + 0x500) +#define HOST_CMDSTS0_SET_REG (APP_BLK_REG_ADDR + 0x504) +#define HOST_CMDSTS0_REG (APP_BLK_REG_ADDR + 0x508) +#define HOST_CMDSTS1_CLR_REG (APP_BLK_REG_ADDR + 0x510) +#define HOST_CMDSTS1_SET_REG (APP_BLK_REG_ADDR + 0x514) +#define HOST_CMDSTS1_REG (APP_BLK_REG_ADDR + 0x518) +#define HOST_CMDSTS2_CLR_REG (APP_BLK_REG_ADDR + 0x520) +#define HOST_CMDSTS2_SET_REG (APP_BLK_REG_ADDR + 0x524) +#define HOST_CMDSTS2_REG (APP_BLK_REG_ADDR + 0x528) +#define HOST_CMDSTS3_CLR_REG (APP_BLK_REG_ADDR + 0x530) +#define HOST_CMDSTS3_SET_REG (APP_BLK_REG_ADDR + 0x534) +#define HOST_CMDSTS3_REG (APP_BLK_REG_ADDR + 0x538) +#define HOST_CMDSTS4_CLR_REG (APP_BLK_REG_ADDR + 0x540) +#define HOST_CMDSTS4_SET_REG (APP_BLK_REG_ADDR + 0x544) +#define HOST_CMDSTS4_REG (APP_BLK_REG_ADDR + 0x548) +#define HOST_CMDSTS5_CLR_REG (APP_BLK_REG_ADDR + 0x550) +#define HOST_CMDSTS5_SET_REG (APP_BLK_REG_ADDR + 0x554) +#define HOST_CMDSTS5_REG (APP_BLK_REG_ADDR + 0x558) +#define HOST_CMDSTS6_CLR_REG (APP_BLK_REG_ADDR + 0x560) +#define HOST_CMDSTS6_SET_REG (APP_BLK_REG_ADDR + 0x564) +#define HOST_CMDSTS6_REG (APP_BLK_REG_ADDR + 0x568) +#define HOST_CMDSTS7_CLR_REG (APP_BLK_REG_ADDR + 0x570) +#define HOST_CMDSTS7_SET_REG (APP_BLK_REG_ADDR + 0x574) +#define HOST_CMDSTS7_REG (APP_BLK_REG_ADDR + 0x578) +#define HOST_CMDSTS8_CLR_REG (APP_BLK_REG_ADDR + 0x580) +#define HOST_CMDSTS8_SET_REG (APP_BLK_REG_ADDR + 0x584) +#define HOST_CMDSTS8_REG (APP_BLK_REG_ADDR + 0x588) +#define HOST_CMDSTS9_CLR_REG (APP_BLK_REG_ADDR + 0x590) +#define HOST_CMDSTS9_SET_REG (APP_BLK_REG_ADDR + 0x594) +#define HOST_CMDSTS9_REG (APP_BLK_REG_ADDR + 0x598) +#define HOST_CMDSTS10_CLR_REG (APP_BLK_REG_ADDR + 0x5A0) +#define HOST_CMDSTS10_SET_REG (APP_BLK_REG_ADDR + 0x5A4) +#define HOST_CMDSTS10_REG (APP_BLK_REG_ADDR + 0x5A8) +#define HOST_CMDSTS11_CLR_REG (APP_BLK_REG_ADDR + 0x5B0) +#define HOST_CMDSTS11_SET_REG (APP_BLK_REG_ADDR + 0x5B4) +#define HOST_CMDSTS11_REG (APP_BLK_REG_ADDR + 0x5B8) +#define HOST_CMDSTS12_CLR_REG (APP_BLK_REG_ADDR + 0x5C0) +#define HOST_CMDSTS12_SET_REG (APP_BLK_REG_ADDR + 0x5C4) +#define HOST_CMDSTS12_REG (APP_BLK_REG_ADDR + 0x5C8) +#define HOST_CMDSTS13_CLR_REG (APP_BLK_REG_ADDR + 0x5D0) +#define HOST_CMDSTS13_SET_REG (APP_BLK_REG_ADDR + 0x5D4) +#define HOST_CMDSTS13_REG (APP_BLK_REG_ADDR + 0x5D8) +#define HOST_CMDSTS14_CLR_REG (APP_BLK_REG_ADDR + 0x5E0) +#define HOST_CMDSTS14_SET_REG (APP_BLK_REG_ADDR + 0x5E4) +#define HOST_CMDSTS14_REG (APP_BLK_REG_ADDR + 0x5E8) +#define HOST_CMDSTS15_CLR_REG (APP_BLK_REG_ADDR + 0x5F0) +#define HOST_CMDSTS15_SET_REG (APP_BLK_REG_ADDR + 0x5F4) +#define HOST_CMDSTS15_REG (APP_BLK_REG_ADDR + 0x5F8) + +/** + * LPU0 Block Register Address Offset from BAR0 + * Range 0x18000 - 0x18033 + */ +#define LPU0_BLK_REG_ADDR 0x00018000 + +/** + * LPU0 Registers + * Should they be directly used from host, + * except for diagnostics ? + * CTL_REG : Control register + * CMD_REG : Triggers exec. of cmd. in + * Mailbox memory + */ +#define LPU0_MBOX_CTL_REG (LPU0_BLK_REG_ADDR + 0x000) +#define LPU0_MBOX_CMD_REG (LPU0_BLK_REG_ADDR + 0x004) +#define LPU0_MBOX_LINK_0REG (LPU0_BLK_REG_ADDR + 0x008) +#define LPU1_MBOX_LINK_0REG (LPU0_BLK_REG_ADDR + 0x00c) +#define LPU0_MBOX_STATUS_0REG (LPU0_BLK_REG_ADDR + 0x010) +#define LPU1_MBOX_STATUS_0REG (LPU0_BLK_REG_ADDR + 0x014) +#define LPU0_ERR_STATUS_REG (LPU0_BLK_REG_ADDR + 0x018) +#define LPU0_ERR_SET_REG (LPU0_BLK_REG_ADDR + 0x020) + +/** + * LPU1 Block Register Address Offset from BAR0 + * Range 0x18400 - 0x18433 + */ +#define LPU1_BLK_REG_ADDR 0x00018400 + +/** + * LPU1 Registers + * Same as LPU0 registers above + */ +#define LPU1_MBOX_CTL_REG (LPU1_BLK_REG_ADDR + 0x000) +#define LPU1_MBOX_CMD_REG (LPU1_BLK_REG_ADDR + 0x004) +#define LPU0_MBOX_LINK_1REG (LPU1_BLK_REG_ADDR + 0x008) +#define LPU1_MBOX_LINK_1REG (LPU1_BLK_REG_ADDR + 0x00c) +#define LPU0_MBOX_STATUS_1REG (LPU1_BLK_REG_ADDR + 0x010) +#define LPU1_MBOX_STATUS_1REG (LPU1_BLK_REG_ADDR + 0x014) +#define LPU1_ERR_STATUS_REG (LPU1_BLK_REG_ADDR + 0x018) +#define LPU1_ERR_SET_REG (LPU1_BLK_REG_ADDR + 0x020) + +/** + * PSS Block Register Address Offset from BAR0 + * Range 0x18800 - 0x188DB + */ +#define PSS_BLK_REG_ADDR 0x00018800 + +/** + * PSS Registers + * For details, see catapult_spec.pdf + * ERR_STATUS_REG : Indicates error in PSS module + * RAM_ERR_STATUS_REG : Indicates RAM module that detected error + */ +#define ERR_STATUS_SET (PSS_BLK_REG_ADDR + 0x018) +#define PSS_RAM_ERR_STATUS_REG (PSS_BLK_REG_ADDR + 0x01C) + +/** + * PSS Semaphore Lock Registers, total 16 + * First read when unlocked returns 0, + * and is set to 1, atomically. + * Subsequent reads returns 1. + * To clear set the value to 0. + * Range : 0x20 to 0x5c + */ +#define PSS_SEM_LOCK_REG(_num) \ + (PSS_BLK_REG_ADDR + 0x020 + ((_num) << 2)) + +/** + * PSS Semaphore Status Registers, + * corresponding to the lock registers above + */ +#define PSS_SEM_STATUS_REG(_num) \ + (PSS_BLK_REG_ADDR + 0x060 + ((_num) << 2)) + +/** + * Catapult CPQ Registers + * Defines for Mailbox Registers + * Used to send mailbox commands to firmware from + * host. The data part is written to the MBox + * memory, registers are used to indicate that + * a commnad is resident in memory. + * + * Note : LPU0<->LPU1 mailboxes are not listed here + */ +#define CPQ_BLK_REG_ADDR 0x00019000 + +#define HOSTFN0_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x130) +#define HOSTFN0_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x134) +#define LPU0_HOSTFN0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x138) +#define LPU1_HOSTFN0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x13C) + +#define HOSTFN1_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x140) +#define HOSTFN1_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x144) +#define LPU0_HOSTFN1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x148) +#define LPU1_HOSTFN1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x14C) + +#define HOSTFN2_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x170) +#define HOSTFN2_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x174) +#define LPU0_HOSTFN2_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x178) +#define LPU1_HOSTFN2_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x17C) + +#define HOSTFN3_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x180) +#define HOSTFN3_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x184) +#define LPU0_HOSTFN3_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x188) +#define LPU1_HOSTFN3_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x18C) + +/* Host Function Force Parity Error Registers */ +#define HOSTFN0_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x120) +#define HOSTFN1_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x124) +#define HOSTFN2_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x128) +#define HOSTFN3_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x12C) + +/* LL Port[0|1] Halt Mask Registers */ +#define LL_HALT_MSK_P0 (CPQ_BLK_REG_ADDR + 0x1A0) +#define LL_HALT_MSK_P1 (CPQ_BLK_REG_ADDR + 0x1B0) + +/* LL Port[0|1] Error Mask Registers */ +#define LL_ERR_MSK_P0 (CPQ_BLK_REG_ADDR + 0x1D0) +#define LL_ERR_MSK_P1 (CPQ_BLK_REG_ADDR + 0x1D4) + +/* EMC FLI (Flash Controller) Block Register Address Offset from BAR0 */ +#define FLI_BLK_REG_ADDR 0x0001D000 + +/* EMC FLI Registers */ +#define FLI_CMD_REG (FLI_BLK_REG_ADDR + 0x000) +#define FLI_ADDR_REG (FLI_BLK_REG_ADDR + 0x004) +#define FLI_CTL_REG (FLI_BLK_REG_ADDR + 0x008) +#define FLI_WRDATA_REG (FLI_BLK_REG_ADDR + 0x00C) +#define FLI_RDDATA_REG (FLI_BLK_REG_ADDR + 0x010) +#define FLI_DEV_STATUS_REG (FLI_BLK_REG_ADDR + 0x014) +#define FLI_SIG_WD_REG (FLI_BLK_REG_ADDR + 0x018) + +/** + * RO register + * 31:16 -- Vendor Id + * 15:0 -- Device Id + */ +#define FLI_DEV_VENDOR_REG (FLI_BLK_REG_ADDR + 0x01C) +#define FLI_ERR_STATUS_REG (FLI_BLK_REG_ADDR + 0x020) + +/** + * RAD (RxAdm) Block Register Address Offset from BAR0 + * RAD0 Range : 0x20000 - 0x203FF + * RAD1 Range : 0x20400 - 0x207FF + */ +#define RAD0_BLK_REG_ADDR 0x00020000 +#define RAD1_BLK_REG_ADDR 0x00020400 + +/* RAD0 Registers */ +#define RAD0_CTL_REG (RAD0_BLK_REG_ADDR + 0x000) +#define RAD0_PE_PARM_REG (RAD0_BLK_REG_ADDR + 0x004) +#define RAD0_BCN_REG (RAD0_BLK_REG_ADDR + 0x008) + +/* Default function ID register */ +#define RAD0_DEFAULT_REG (RAD0_BLK_REG_ADDR + 0x00C) + +/* Default promiscuous ID register */ +#define RAD0_PROMISC_REG (RAD0_BLK_REG_ADDR + 0x010) + +#define RAD0_BCNQ_REG (RAD0_BLK_REG_ADDR + 0x014) + +/* + * This register selects 1 of 8 PM Q's using + * VLAN pri, for non-BCN packets without a VLAN tag + */ +#define RAD0_DEFAULTQ_REG (RAD0_BLK_REG_ADDR + 0x018) + +#define RAD0_ERR_STS (RAD0_BLK_REG_ADDR + 0x01C) +#define RAD0_SET_ERR_STS (RAD0_BLK_REG_ADDR + 0x020) +#define RAD0_ERR_INT_EN (RAD0_BLK_REG_ADDR + 0x024) +#define RAD0_FIRST_ERR (RAD0_BLK_REG_ADDR + 0x028) +#define RAD0_FORCE_ERR (RAD0_BLK_REG_ADDR + 0x02C) + +#define RAD0_IF_RCVD (RAD0_BLK_REG_ADDR + 0x030) +#define RAD0_IF_RCVD_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x034) +#define RAD0_IF_RCVD_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x038) +#define RAD0_IF_RCVD_VLAN (RAD0_BLK_REG_ADDR + 0x03C) +#define RAD0_IF_RCVD_UCAST (RAD0_BLK_REG_ADDR + 0x040) +#define RAD0_IF_RCVD_UCAST_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x044) +#define RAD0_IF_RCVD_UCAST_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x048) +#define RAD0_IF_RCVD_UCAST_VLAN (RAD0_BLK_REG_ADDR + 0x04C) +#define RAD0_IF_RCVD_MCAST (RAD0_BLK_REG_ADDR + 0x050) +#define RAD0_IF_RCVD_MCAST_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x054) +#define RAD0_IF_RCVD_MCAST_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x058) +#define RAD0_IF_RCVD_MCAST_VLAN (RAD0_BLK_REG_ADDR + 0x05C) +#define RAD0_IF_RCVD_BCAST (RAD0_BLK_REG_ADDR + 0x060) +#define RAD0_IF_RCVD_BCAST_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x064) +#define RAD0_IF_RCVD_BCAST_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x068) +#define RAD0_IF_RCVD_BCAST_VLAN (RAD0_BLK_REG_ADDR + 0x06C) +#define RAD0_DROPPED_FRAMES (RAD0_BLK_REG_ADDR + 0x070) + +#define RAD0_MAC_MAN_1H (RAD0_BLK_REG_ADDR + 0x080) +#define RAD0_MAC_MAN_1L (RAD0_BLK_REG_ADDR + 0x084) +#define RAD0_MAC_MAN_2H (RAD0_BLK_REG_ADDR + 0x088) +#define RAD0_MAC_MAN_2L (RAD0_BLK_REG_ADDR + 0x08C) +#define RAD0_MAC_MAN_3H (RAD0_BLK_REG_ADDR + 0x090) +#define RAD0_MAC_MAN_3L (RAD0_BLK_REG_ADDR + 0x094) +#define RAD0_MAC_MAN_4H (RAD0_BLK_REG_ADDR + 0x098) +#define RAD0_MAC_MAN_4L (RAD0_BLK_REG_ADDR + 0x09C) + +#define RAD0_LAST4_IP (RAD0_BLK_REG_ADDR + 0x100) + +/* RAD1 Registers */ +#define RAD1_CTL_REG (RAD1_BLK_REG_ADDR + 0x000) +#define RAD1_PE_PARM_REG (RAD1_BLK_REG_ADDR + 0x004) +#define RAD1_BCN_REG (RAD1_BLK_REG_ADDR + 0x008) + +/* Default function ID register */ +#define RAD1_DEFAULT_REG (RAD1_BLK_REG_ADDR + 0x00C) + +/* Promiscuous function ID register */ +#define RAD1_PROMISC_REG (RAD1_BLK_REG_ADDR + 0x010) + +#define RAD1_BCNQ_REG (RAD1_BLK_REG_ADDR + 0x014) + +/* + * This register selects 1 of 8 PM Q's using + * VLAN pri, for non-BCN packets without a VLAN tag + */ +#define RAD1_DEFAULTQ_REG (RAD1_BLK_REG_ADDR + 0x018) + +#define RAD1_ERR_STS (RAD1_BLK_REG_ADDR + 0x01C) +#define RAD1_SET_ERR_STS (RAD1_BLK_REG_ADDR + 0x020) +#define RAD1_ERR_INT_EN (RAD1_BLK_REG_ADDR + 0x024) + +/** + * TXA Block Register Address Offset from BAR0 + * TXA0 Range : 0x21000 - 0x213FF + * TXA1 Range : 0x21400 - 0x217FF + */ +#define TXA0_BLK_REG_ADDR 0x00021000 +#define TXA1_BLK_REG_ADDR 0x00021400 + +/* TXA Registers */ +#define TXA0_CTRL_REG (TXA0_BLK_REG_ADDR + 0x000) +#define TXA1_CTRL_REG (TXA1_BLK_REG_ADDR + 0x000) + +/** + * TSO Sequence # Registers (RO) + * Total 8 (for 8 queues) + * Holds the last seq.# for TSO frames + * See catapult_spec.pdf for more details + */ +#define TXA0_TSO_TCP_SEQ_REG(_num) \ + (TXA0_BLK_REG_ADDR + 0x020 + ((_num) << 2)) + +#define TXA1_TSO_TCP_SEQ_REG(_num) \ + (TXA1_BLK_REG_ADDR + 0x020 + ((_num) << 2)) + +/** + * TSO IP ID # Registers (RO) + * Total 8 (for 8 queues) + * Holds the last IP ID for TSO frames + * See catapult_spec.pdf for more details + */ +#define TXA0_TSO_IP_INFO_REG(_num) \ + (TXA0_BLK_REG_ADDR + 0x040 + ((_num) << 2)) + +#define TXA1_TSO_IP_INFO_REG(_num) \ + (TXA1_BLK_REG_ADDR + 0x040 + ((_num) << 2)) + +/** + * RXA Block Register Address Offset from BAR0 + * RXA0 Range : 0x21800 - 0x21BFF + * RXA1 Range : 0x21C00 - 0x21FFF + */ +#define RXA0_BLK_REG_ADDR 0x00021800 +#define RXA1_BLK_REG_ADDR 0x00021C00 + +/* RXA Registers */ +#define RXA0_CTL_REG (RXA0_BLK_REG_ADDR + 0x040) +#define RXA1_CTL_REG (RXA1_BLK_REG_ADDR + 0x040) + +/** + * PPLB Block Register Address Offset from BAR0 + * PPLB0 Range : 0x22000 - 0x223FF + * PPLB1 Range : 0x22400 - 0x227FF + */ +#define PLB0_BLK_REG_ADDR 0x00022000 +#define PLB1_BLK_REG_ADDR 0x00022400 + +/** + * PLB Registers + * Holds RL timer used time stamps in RLT tagged frames + */ +#define PLB0_ECM_TIMER_REG (PLB0_BLK_REG_ADDR + 0x05C) +#define PLB1_ECM_TIMER_REG (PLB1_BLK_REG_ADDR + 0x05C) + +/* Controls the rate-limiter on each of the priority class */ +#define PLB0_RL_CTL (PLB0_BLK_REG_ADDR + 0x060) +#define PLB1_RL_CTL (PLB1_BLK_REG_ADDR + 0x060) + +/** + * Max byte register, total 8, 0-7 + * see catapult_spec.pdf for details + */ +#define PLB0_RL_MAX_BC(_num) \ + (PLB0_BLK_REG_ADDR + 0x064 + ((_num) << 2)) +#define PLB1_RL_MAX_BC(_num) \ + (PLB1_BLK_REG_ADDR + 0x064 + ((_num) << 2)) + +/** + * RL Time Unit Register for priority 0-7 + * 4 bits per priority + * (2^rl_unit)*1us is the actual time period + */ +#define PLB0_RL_TU_PRIO (PLB0_BLK_REG_ADDR + 0x084) +#define PLB1_RL_TU_PRIO (PLB1_BLK_REG_ADDR + 0x084) + +/** + * RL byte count register, + * bytes transmitted in (rl_unit*1)us time period + * 1 per priority, 8 in all, 0-7. + */ +#define PLB0_RL_BYTE_CNT(_num) \ + (PLB0_BLK_REG_ADDR + 0x088 + ((_num) << 2)) +#define PLB1_RL_BYTE_CNT(_num) \ + (PLB1_BLK_REG_ADDR + 0x088 + ((_num) << 2)) + +/** + * RL Min factor register + * 2 bits per priority, + * 4 factors possible: 1, 0.5, 0.25, 0 + * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1 + */ +#define PLB0_RL_MIN_REG (PLB0_BLK_REG_ADDR + 0x0A8) +#define PLB1_RL_MIN_REG (PLB1_BLK_REG_ADDR + 0x0A8) + +/** + * RL Max factor register + * 2 bits per priority, + * 4 factors possible: 1, 0.5, 0.25, 0 + * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1 + */ +#define PLB0_RL_MAX_REG (PLB0_BLK_REG_ADDR + 0x0AC) +#define PLB1_RL_MAX_REG (PLB1_BLK_REG_ADDR + 0x0AC) + +/* MAC SERDES Address Paging register */ +#define PLB0_EMS_ADD_REG (PLB0_BLK_REG_ADDR + 0xD0) +#define PLB1_EMS_ADD_REG (PLB1_BLK_REG_ADDR + 0xD0) + +/* LL EMS Registers */ +#define LL_EMS0_BLK_REG_ADDR 0x00026800 +#define LL_EMS1_BLK_REG_ADDR 0x00026C00 + +/** + * BPC Block Register Address Offset from BAR0 + * BPC0 Range : 0x23000 - 0x233FF + * BPC1 Range : 0x23400 - 0x237FF + */ +#define BPC0_BLK_REG_ADDR 0x00023000 +#define BPC1_BLK_REG_ADDR 0x00023400 + +/** + * PMM Block Register Address Offset from BAR0 + * PMM0 Range : 0x23800 - 0x23BFF + * PMM1 Range : 0x23C00 - 0x23FFF + */ +#define PMM0_BLK_REG_ADDR 0x00023800 +#define PMM1_BLK_REG_ADDR 0x00023C00 + +/** + * HQM Block Register Address Offset from BAR0 + * HQM0 Range : 0x24000 - 0x243FF + * HQM1 Range : 0x24400 - 0x247FF + */ +#define HQM0_BLK_REG_ADDR 0x00024000 +#define HQM1_BLK_REG_ADDR 0x00024400 + +/** + * HQM Control Register + * Controls some aspects of IB + * See catapult_spec.pdf for details + */ +#define HQM0_CTL_REG (HQM0_BLK_REG_ADDR + 0x000) +#define HQM1_CTL_REG (HQM1_BLK_REG_ADDR + 0x000) + +/** + * HQM Stop Q Semaphore Registers. + * Only one Queue resource can be stopped at + * any given time. This register controls access + * to the single stop Q resource. + * See catapult_spec.pdf for details + */ +#define HQM0_RXQ_STOP_SEM (HQM0_BLK_REG_ADDR + 0x028) +#define HQM0_TXQ_STOP_SEM (HQM0_BLK_REG_ADDR + 0x02C) +#define HQM1_RXQ_STOP_SEM (HQM1_BLK_REG_ADDR + 0x028) +#define HQM1_TXQ_STOP_SEM (HQM1_BLK_REG_ADDR + 0x02C) + +/** + * LUT Block Register Address Offset from BAR0 + * LUT0 Range : 0x25800 - 0x25BFF + * LUT1 Range : 0x25C00 - 0x25FFF + */ +#define LUT0_BLK_REG_ADDR 0x00025800 +#define LUT1_BLK_REG_ADDR 0x00025C00 + +/** + * LUT Registers + * See catapult_spec.pdf for details + */ +#define LUT0_ERR_STS (LUT0_BLK_REG_ADDR + 0x000) +#define LUT1_ERR_STS (LUT1_BLK_REG_ADDR + 0x000) +#define LUT0_SET_ERR_STS (LUT0_BLK_REG_ADDR + 0x004) +#define LUT1_SET_ERR_STS (LUT1_BLK_REG_ADDR + 0x004) + +/** + * TRC (Debug/Trace) Register Offset from BAR0 + * Range : 0x26000 -- 0x263FFF + */ +#define TRC_BLK_REG_ADDR 0x00026000 + +/** + * TRC Registers + * See catapult_spec.pdf for details of each + */ +#define TRC_CTL_REG (TRC_BLK_REG_ADDR + 0x000) +#define TRC_MODS_REG (TRC_BLK_REG_ADDR + 0x004) +#define TRC_TRGC_REG (TRC_BLK_REG_ADDR + 0x008) +#define TRC_CNT1_REG (TRC_BLK_REG_ADDR + 0x010) +#define TRC_CNT2_REG (TRC_BLK_REG_ADDR + 0x014) +#define TRC_NXTS_REG (TRC_BLK_REG_ADDR + 0x018) +#define TRC_DIRR_REG (TRC_BLK_REG_ADDR + 0x01C) + +/** + * TRC Trigger match filters, total 10 + * Determines the trigger condition + */ +#define TRC_TRGM_REG(_num) \ + (TRC_BLK_REG_ADDR + 0x040 + ((_num) << 2)) + +/** + * TRC Next State filters, total 10 + * Determines the next state conditions + */ +#define TRC_NXTM_REG(_num) \ + (TRC_BLK_REG_ADDR + 0x080 + ((_num) << 2)) + +/** + * TRC Store Match filters, total 10 + * Determines the store conditions + */ +#define TRC_STRM_REG(_num) \ + (TRC_BLK_REG_ADDR + 0x0C0 + ((_num) << 2)) + +/* DOORBELLS ACCESS */ + +/** + * Catapult doorbells + * Each doorbell-queue set has + * 1 RxQ, 1 TxQ, 2 IBs in that order + * Size of each entry in 32 bytes, even though only 1 word + * is used. For Non-VM case each doorbell-q set is + * separated by 128 bytes, for VM case it is separated + * by 4K bytes + * Non VM case Range : 0x38000 - 0x39FFF + * VM case Range : 0x100000 - 0x11FFFF + * The range applies to both HQMs + */ +#define HQM_DOORBELL_BLK_BASE_ADDR 0x00038000 +#define HQM_DOORBELL_VM_BLK_BASE_ADDR 0x00100000 + +/* MEMORY ACCESS */ + +/** + * Catapult H/W Block Memory Access Address + * To the host a memory space of 32K (page) is visible + * at a time. The address range is from 0x08000 to 0x0FFFF + */ +#define HW_BLK_HOST_MEM_ADDR 0x08000 + +/** + * Catapult LUT Memory Access Page Numbers + * Range : LUT0 0xa0-0xa1 + * LUT1 0xa2-0xa3 + */ +#define LUT0_MEM_BLK_BASE_PG_NUM 0x000000A0 +#define LUT1_MEM_BLK_BASE_PG_NUM 0x000000A2 + +/** + * Catapult RxFn Database Memory Block Base Offset + * + * The Rx function database exists in LUT block. + * In PCIe space this is accessible as a 256x32 + * bit block. Each entry in this database is 4 + * (4 byte) words. Max. entries is 64. + * Address of an entry corresponding to a function + * = base_addr + (function_no. * 16) + */ +#define RX_FNDB_RAM_BASE_OFFSET 0x0000B400 + +/** + * Catapult TxFn Database Memory Block Base Offset Address + * + * The Tx function database exists in LUT block. + * In PCIe space this is accessible as a 64x32 + * bit block. Each entry in this database is 1 + * (4 byte) word. Max. entries is 64. + * Address of an entry corresponding to a function + * = base_addr + (function_no. * 4) + */ +#define TX_FNDB_RAM_BASE_OFFSET 0x0000B800 + +/** + * Catapult Unicast CAM Base Offset Address + * + * Exists in LUT memory space. + * Shared by both the LL & FCoE driver. + * Size is 256x48 bits; mapped to PCIe space + * 512x32 bit blocks. For each address, bits + * are written in the order : [47:32] and then + * [31:0]. + */ +#define UCAST_CAM_BASE_OFFSET 0x0000A800 + +/** + * Catapult Unicast RAM Base Offset Address + * + * Exists in LUT memory space. + * Shared by both the LL & FCoE driver. + * Size is 256x9 bits. + */ +#define UCAST_RAM_BASE_OFFSET 0x0000B000 + +/** + * Catapult Mulicast CAM Base Offset Address + * + * Exists in LUT memory space. + * Shared by both the LL & FCoE driver. + * Size is 256x48 bits; mapped to PCIe space + * 512x32 bit blocks. For each address, bits + * are written in the order : [47:32] and then + * [31:0]. + */ +#define MCAST_CAM_BASE_OFFSET 0x0000A000 + +/** + * Catapult VLAN RAM Base Offset Address + * + * Exists in LUT memory space. + * Size is 4096x66 bits; mapped to PCIe space as + * 8192x32 bit blocks. + * All the 4K entries are within the address range + * 0x0000 to 0x8000, so in the first LUT page. + */ +#define VLAN_RAM_BASE_OFFSET 0x00000000 + +/** + * Catapult Tx Stats RAM Base Offset Address + * + * Exists in LUT memory space. + * Size is 1024x33 bits; + * Each Tx function has 64 bytes of space + */ +#define TX_STATS_RAM_BASE_OFFSET 0x00009000 + +/** + * Catapult Rx Stats RAM Base Offset Address + * + * Exists in LUT memory space. + * Size is 1024x33 bits; + * Each Rx function has 64 bytes of space + */ +#define RX_STATS_RAM_BASE_OFFSET 0x00008000 + +/* Catapult RXA Memory Access Page Numbers */ +#define RXA0_MEM_BLK_BASE_PG_NUM 0x0000008C +#define RXA1_MEM_BLK_BASE_PG_NUM 0x0000008D + +/** + * Catapult Multicast Vector Table Base Offset Address + * + * Exists in RxA memory space. + * Organized as 512x65 bit block. + * However for each entry 16 bytes allocated (power of 2) + * Total size 512*16 bytes. + * There are two logical divisions, 256 entries each : + * a) Entries 0x00 to 0xff (256) -- Approx. MVT + * Offset 0x000 to 0xFFF + * b) Entries 0x100 to 0x1ff (256) -- Exact MVT + * Offsets 0x1000 to 0x1FFF + */ +#define MCAST_APPROX_MVT_BASE_OFFSET 0x00000000 +#define MCAST_EXACT_MVT_BASE_OFFSET 0x00001000 + +/** + * Catapult RxQ Translate Table (RIT) Base Offset Address + * + * Exists in RxA memory space + * Total no. of entries 64 + * Each entry is 1 (4 byte) word. + * 31:12 -- Reserved + * 11:0 -- Two 6 bit RxQ Ids + */ +#define FUNCTION_TO_RXQ_TRANSLATE 0x00002000 + +/* Catapult RxAdm (RAD) Memory Access Page Numbers */ +#define RAD0_MEM_BLK_BASE_PG_NUM 0x00000086 +#define RAD1_MEM_BLK_BASE_PG_NUM 0x00000087 + +/** + * Catapult RSS Table Base Offset Address + * + * Exists in RAD memory space. + * Each entry is 352 bits, but alligned on + * 64 byte (512 bit) boundary. Accessed + * 4 byte words, the whole entry can be + * broken into 11 word accesses. + */ +#define RSS_TABLE_BASE_OFFSET 0x00000800 + +/** + * Catapult CPQ Block Page Number + * This value is written to the page number registers + * to access the memory associated with the mailboxes. + */ +#define CPQ_BLK_PG_NUM 0x00000005 + +/** + * Clarification : + * LL functions are 2 & 3; can HostFn0/HostFn1 + * <-> LPU0/LPU1 memories be used ? + */ +/** + * Catapult HostFn0/HostFn1 to LPU0/LPU1 Mbox memory + * Per catapult_spec.pdf, the offset of the mbox + * memory is in the register space at an offset of 0x200 + */ +#define CPQ_BLK_REG_MBOX_ADDR (CPQ_BLK_REG_ADDR + 0x200) + +#define HOSTFN_LPU_MBOX (CPQ_BLK_REG_MBOX_ADDR + 0x000) + +/* Catapult LPU0/LPU1 to HostFn0/HostFn1 Mbox memory */ +#define LPU_HOSTFN_MBOX (CPQ_BLK_REG_MBOX_ADDR + 0x080) + +/** + * Catapult HQM Block Page Number + * This is written to the page number register for + * the appropriate function to access the memory + * associated with HQM + */ +#define HQM0_BLK_PG_NUM 0x00000096 +#define HQM1_BLK_PG_NUM 0x00000097 + +/** + * Note that TxQ and RxQ entries are interlaced + * the HQM memory, i.e RXQ0, TXQ0, RXQ1, TXQ1.. etc. + */ + +#define HQM_RXTX_Q_RAM_BASE_OFFSET 0x00004000 + +/** + * CQ Memory + * Exists in HQM Memory space + * Each entry is 16 (4 byte) words of which + * only 12 words are used for configuration + * Total 64 entries per HQM memory space + */ +#define HQM_CQ_RAM_BASE_OFFSET 0x00006000 + +/** + * Interrupt Block (IB) Memory + * Exists in HQM Memory space + * Each entry is 8 (4 byte) words of which + * only 5 words are used for configuration + * Total 128 entries per HQM memory space + */ +#define HQM_IB_RAM_BASE_OFFSET 0x00001000 + +/** + * Index Table (IT) Memory + * Exists in HQM Memory space + * Each entry is 1 (4 byte) word which + * is used for configuration + * Total 128 entries per HQM memory space + */ +#define HQM_INDX_TBL_RAM_BASE_OFFSET 0x00002000 + +/** + * PSS Block Memory Page Number + * This is written to the appropriate page number + * register to access the CPU memory. + * Also known as the PSS secondary memory (SMEM). + * Range : 0x180 to 0x1CF + * See catapult_spec.pdf for details + */ +#define PSS_BLK_PG_NUM 0x00000180 + +/** + * Offsets of different instances of PSS SMEM + * 2.5M of continuous 1T memory space : 2 blocks + * of 1M each (32 pages each, page=32KB) and 4 smaller + * blocks of 128K each (4 pages each, page=32KB) + * PSS_LMEM_INST0 is used for firmware download + */ +#define PSS_LMEM_INST0 0x00000000 +#define PSS_LMEM_INST1 0x00100000 +#define PSS_LMEM_INST2 0x00200000 +#define PSS_LMEM_INST3 0x00220000 +#define PSS_LMEM_INST4 0x00240000 +#define PSS_LMEM_INST5 0x00260000 + +#define BNA_PCI_REG_CT_ADDRSZ (0x40000) + +#define BNA_GET_PAGE_NUM(_base_page, _offset) \ + ((_base_page) + ((_offset) >> 15)) + +#define BNA_GET_PAGE_OFFSET(_offset) \ + ((_offset) & 0x7fff) + +#define BNA_GET_MEM_BASE_ADDR(_bar0, _base_offset) \ + ((_bar0) + HW_BLK_HOST_MEM_ADDR \ + + BNA_GET_PAGE_OFFSET((_base_offset))) + +#define BNA_GET_VLAN_MEM_ENTRY_ADDR(_bar0, _fn_id, _vlan_id)\ + (_bar0 + (HW_BLK_HOST_MEM_ADDR) \ + + (BNA_GET_PAGE_OFFSET(VLAN_RAM_BASE_OFFSET)) \ + + (((_fn_id) & 0x3f) << 9) \ + + (((_vlan_id) & 0xfe0) >> 3)) + +/** + * + * Interrupt related bits, flags and macros + * + */ + +#define __LPU02HOST_MBOX0_STATUS_BITS 0x00100000 +#define __LPU12HOST_MBOX0_STATUS_BITS 0x00200000 +#define __LPU02HOST_MBOX1_STATUS_BITS 0x00400000 +#define __LPU12HOST_MBOX1_STATUS_BITS 0x00800000 + +#define __LPU02HOST_MBOX0_MASK_BITS 0x00100000 +#define __LPU12HOST_MBOX0_MASK_BITS 0x00200000 +#define __LPU02HOST_MBOX1_MASK_BITS 0x00400000 +#define __LPU12HOST_MBOX1_MASK_BITS 0x00800000 + +#define __LPU2HOST_MBOX_MASK_BITS \ + (__LPU02HOST_MBOX0_MASK_BITS | __LPU02HOST_MBOX1_MASK_BITS | \ + __LPU12HOST_MBOX0_MASK_BITS | __LPU12HOST_MBOX1_MASK_BITS) + +#define __LPU2HOST_IB_STATUS_BITS 0x0000ffff + +#define BNA_IS_LPU0_MBOX_INTR(_intr_status) \ + ((_intr_status) & (__LPU02HOST_MBOX0_STATUS_BITS | \ + __LPU02HOST_MBOX1_STATUS_BITS)) + +#define BNA_IS_LPU1_MBOX_INTR(_intr_status) \ + ((_intr_status) & (__LPU12HOST_MBOX0_STATUS_BITS | \ + __LPU12HOST_MBOX1_STATUS_BITS)) + +#define BNA_IS_MBOX_INTR(_intr_status) \ + ((_intr_status) & \ + (__LPU02HOST_MBOX0_STATUS_BITS | \ + __LPU02HOST_MBOX1_STATUS_BITS | \ + __LPU12HOST_MBOX0_STATUS_BITS | \ + __LPU12HOST_MBOX1_STATUS_BITS)) + +#define __EMC_ERROR_STATUS_BITS 0x00010000 +#define __LPU0_ERROR_STATUS_BITS 0x00020000 +#define __LPU1_ERROR_STATUS_BITS 0x00040000 +#define __PSS_ERROR_STATUS_BITS 0x00080000 + +#define __HALT_STATUS_BITS 0x01000000 + +#define __EMC_ERROR_MASK_BITS 0x00010000 +#define __LPU0_ERROR_MASK_BITS 0x00020000 +#define __LPU1_ERROR_MASK_BITS 0x00040000 +#define __PSS_ERROR_MASK_BITS 0x00080000 + +#define __HALT_MASK_BITS 0x01000000 + +#define __ERROR_MASK_BITS \ + (__EMC_ERROR_MASK_BITS | __LPU0_ERROR_MASK_BITS | \ + __LPU1_ERROR_MASK_BITS | __PSS_ERROR_MASK_BITS | \ + __HALT_MASK_BITS) + +#define BNA_IS_ERR_INTR(_intr_status) \ + ((_intr_status) & \ + (__EMC_ERROR_STATUS_BITS | \ + __LPU0_ERROR_STATUS_BITS | \ + __LPU1_ERROR_STATUS_BITS | \ + __PSS_ERROR_STATUS_BITS | \ + __HALT_STATUS_BITS)) + +#define BNA_IS_MBOX_ERR_INTR(_intr_status) \ + (BNA_IS_MBOX_INTR((_intr_status)) | \ + BNA_IS_ERR_INTR((_intr_status))) + +#define BNA_IS_INTX_DATA_INTR(_intr_status) \ + ((_intr_status) & __LPU2HOST_IB_STATUS_BITS) + +#define BNA_INTR_STATUS_MBOX_CLR(_intr_status) \ +do { \ + (_intr_status) &= ~(__LPU02HOST_MBOX0_STATUS_BITS | \ + __LPU02HOST_MBOX1_STATUS_BITS | \ + __LPU12HOST_MBOX0_STATUS_BITS | \ + __LPU12HOST_MBOX1_STATUS_BITS); \ +} while (0) + +#define BNA_INTR_STATUS_ERR_CLR(_intr_status) \ +do { \ + (_intr_status) &= ~(__EMC_ERROR_STATUS_BITS | \ + __LPU0_ERROR_STATUS_BITS | \ + __LPU1_ERROR_STATUS_BITS | \ + __PSS_ERROR_STATUS_BITS | \ + __HALT_STATUS_BITS); \ +} while (0) + +#define bna_intx_disable(_bna, _cur_mask) \ +{ \ + (_cur_mask) = readl((_bna)->regs.fn_int_mask);\ + writel(0xffffffff, (_bna)->regs.fn_int_mask);\ +} + +#define bna_intx_enable(bna, new_mask) \ + writel((new_mask), (bna)->regs.fn_int_mask) + +#define bna_mbox_intr_disable(bna) \ + writel((readl((bna)->regs.fn_int_mask) | \ + (__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \ + (bna)->regs.fn_int_mask) + +#define bna_mbox_intr_enable(bna) \ + writel((readl((bna)->regs.fn_int_mask) & \ + ~(__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \ + (bna)->regs.fn_int_mask) + +#define bna_intr_status_get(_bna, _status) \ +{ \ + (_status) = readl((_bna)->regs.fn_int_status); \ + if ((_status)) { \ + writel((_status) & ~(__LPU02HOST_MBOX0_STATUS_BITS |\ + __LPU02HOST_MBOX1_STATUS_BITS |\ + __LPU12HOST_MBOX0_STATUS_BITS |\ + __LPU12HOST_MBOX1_STATUS_BITS), \ + (_bna)->regs.fn_int_status);\ + } \ +} + +#define bna_intr_status_get_no_clr(_bna, _status) \ + (_status) = readl((_bna)->regs.fn_int_status) + +#define bna_intr_mask_get(bna, mask) \ + (*mask) = readl((bna)->regs.fn_int_mask) + +#define bna_intr_ack(bna, intr_bmap) \ + writel((intr_bmap), (bna)->regs.fn_int_status) + +#define bna_ib_intx_disable(bna, ib_id) \ + writel(readl((bna)->regs.fn_int_mask) | \ + (1 << (ib_id)), \ + (bna)->regs.fn_int_mask) + +#define bna_ib_intx_enable(bna, ib_id) \ + writel(readl((bna)->regs.fn_int_mask) & \ + ~(1 << (ib_id)), \ + (bna)->regs.fn_int_mask) + +#define bna_mbox_msix_idx_set(_device) \ +do {\ + writel(((_device)->vector & 0x000001FF), \ + (_device)->bna->pcidev.pci_bar_kva + \ + reg_offset[(_device)->bna->pcidev.pci_func].msix_idx);\ +} while (0) + +/** + * + * TxQ, RxQ, CQ related bits, offsets, macros + * + */ + +#define BNA_Q_IDLE_STATE 0x00008001 + +#define BNA_GET_DOORBELL_BASE_ADDR(_bar0) \ + ((_bar0) + HQM_DOORBELL_BLK_BASE_ADDR) + +#define BNA_GET_DOORBELL_ENTRY_OFFSET(_entry) \ + ((HQM_DOORBELL_BLK_BASE_ADDR) \ + + (_entry << 7)) + +#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \ + (0x80000000 | ((_timeout) << 16) | (_events)) + +#define BNA_DOORBELL_IB_INT_DISABLE (0x40000000) + +/* TxQ Entry Opcodes */ +#define BNA_TXQ_WI_SEND (0x402) /* Single Frame Transmission */ +#define BNA_TXQ_WI_SEND_LSO (0x403) /* Multi-Frame Transmission */ +#define BNA_TXQ_WI_EXTENSION (0x104) /* Extension WI */ + +/* TxQ Entry Control Flags */ +#define BNA_TXQ_WI_CF_FCOE_CRC (1 << 8) +#define BNA_TXQ_WI_CF_IPID_MODE (1 << 5) +#define BNA_TXQ_WI_CF_INS_PRIO (1 << 4) +#define BNA_TXQ_WI_CF_INS_VLAN (1 << 3) +#define BNA_TXQ_WI_CF_UDP_CKSUM (1 << 2) +#define BNA_TXQ_WI_CF_TCP_CKSUM (1 << 1) +#define BNA_TXQ_WI_CF_IP_CKSUM (1 << 0) + +#define BNA_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \ + (((_hdr_size) << 10) | ((_offset) & 0x3FF)) + +/* + * Completion Q defines + */ +/* CQ Entry Flags */ +#define BNA_CQ_EF_MAC_ERROR (1 << 0) +#define BNA_CQ_EF_FCS_ERROR (1 << 1) +#define BNA_CQ_EF_TOO_LONG (1 << 2) +#define BNA_CQ_EF_FC_CRC_OK (1 << 3) + +#define BNA_CQ_EF_RSVD1 (1 << 4) +#define BNA_CQ_EF_L4_CKSUM_OK (1 << 5) +#define BNA_CQ_EF_L3_CKSUM_OK (1 << 6) +#define BNA_CQ_EF_HDS_HEADER (1 << 7) + +#define BNA_CQ_EF_UDP (1 << 8) +#define BNA_CQ_EF_TCP (1 << 9) +#define BNA_CQ_EF_IP_OPTIONS (1 << 10) +#define BNA_CQ_EF_IPV6 (1 << 11) + +#define BNA_CQ_EF_IPV4 (1 << 12) +#define BNA_CQ_EF_VLAN (1 << 13) +#define BNA_CQ_EF_RSS (1 << 14) +#define BNA_CQ_EF_RSVD2 (1 << 15) + +#define BNA_CQ_EF_MCAST_MATCH (1 << 16) +#define BNA_CQ_EF_MCAST (1 << 17) +#define BNA_CQ_EF_BCAST (1 << 18) +#define BNA_CQ_EF_REMOTE (1 << 19) + +#define BNA_CQ_EF_LOCAL (1 << 20) + +/** + * + * Data structures + * + */ + +enum txf_flags { + BFI_TXF_CF_ENABLE = 1 << 0, + BFI_TXF_CF_VLAN_FILTER = 1 << 8, + BFI_TXF_CF_VLAN_ADMIT = 1 << 9, + BFI_TXF_CF_VLAN_INSERT = 1 << 10, + BFI_TXF_CF_RSVD1 = 1 << 11, + BFI_TXF_CF_MAC_SA_CHECK = 1 << 12, + BFI_TXF_CF_VLAN_WI_BASED = 1 << 13, + BFI_TXF_CF_VSWITCH_MCAST = 1 << 14, + BFI_TXF_CF_VSWITCH_UCAST = 1 << 15, + BFI_TXF_CF_RSVD2 = 0x7F << 1 +}; + +enum ib_flags { + BFI_IB_CF_MASTER_ENABLE = (1 << 0), + BFI_IB_CF_MSIX_MODE = (1 << 1), + BFI_IB_CF_COALESCING_MODE = (1 << 2), + BFI_IB_CF_INTER_PKT_ENABLE = (1 << 3), + BFI_IB_CF_INT_ENABLE = (1 << 4), + BFI_IB_CF_INTER_PKT_DMA = (1 << 5), + BFI_IB_CF_ACK_PENDING = (1 << 6), + BFI_IB_CF_RESERVED1 = (1 << 7) +}; + +enum rss_hash_type { + BFI_RSS_T_V4_TCP = (1 << 11), + BFI_RSS_T_V4_IP = (1 << 10), + BFI_RSS_T_V6_TCP = (1 << 9), + BFI_RSS_T_V6_IP = (1 << 8) +}; +enum hds_header_type { + BNA_HDS_T_V4_TCP = (1 << 11), + BNA_HDS_T_V4_UDP = (1 << 10), + BNA_HDS_T_V6_TCP = (1 << 9), + BNA_HDS_T_V6_UDP = (1 << 8), + BNA_HDS_FORCED = (1 << 7), +}; +enum rxf_flags { + BNA_RXF_CF_SM_LG_RXQ = (1 << 15), + BNA_RXF_CF_DEFAULT_VLAN = (1 << 14), + BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE = (1 << 13), + BNA_RXF_CF_VLAN_STRIP = (1 << 12), + BNA_RXF_CF_RSS_ENABLE = (1 << 8) +}; +struct bna_chip_regs_offset { + u32 page_addr; + u32 fn_int_status; + u32 fn_int_mask; + u32 msix_idx; +}; +extern const struct bna_chip_regs_offset reg_offset[]; + +struct bna_chip_regs { + void __iomem *page_addr; + void __iomem *fn_int_status; + void __iomem *fn_int_mask; +}; + +struct bna_txq_mem { + u32 pg_tbl_addr_lo; + u32 pg_tbl_addr_hi; + u32 cur_q_entry_lo; + u32 cur_q_entry_hi; + u32 reserved1; + u32 reserved2; + u32 pg_cnt_n_prd_ptr; /* 31:16->total page count */ + /* 15:0 ->producer pointer (index?) */ + u32 entry_n_pg_size; /* 31:16->entry size */ + /* 15:0 ->page size */ + u32 int_blk_n_cns_ptr; /* 31:24->Int Blk Id; */ + /* 23:16->Int Blk Offset */ + /* 15:0 ->consumer pointer(index?) */ + u32 cns_ptr2_n_q_state; /* 31:16->cons. ptr 2; 15:0-> Q state */ + u32 nxt_qid_n_fid_n_pri; /* 17:10->next */ + /* QId;9:3->FID;2:0->Priority */ + u32 wvc_n_cquota_n_rquota; /* 31:24->WI Vector Count; */ + /* 23:12->Cfg Quota; */ + /* 11:0 ->Run Quota */ + u32 reserved3[4]; +}; + +struct bna_rxq_mem { + u32 pg_tbl_addr_lo; + u32 pg_tbl_addr_hi; + u32 cur_q_entry_lo; + u32 cur_q_entry_hi; + u32 reserved1; + u32 reserved2; + u32 pg_cnt_n_prd_ptr; /* 31:16->total page count */ + /* 15:0 ->producer pointer (index?) */ + u32 entry_n_pg_size; /* 31:16->entry size */ + /* 15:0 ->page size */ + u32 sg_n_cq_n_cns_ptr; /* 31:28->reserved; 27:24->sg count */ + /* 23:16->CQ; */ + /* 15:0->consumer pointer(index?) */ + u32 buf_sz_n_q_state; /* 31:16->buffer size; 15:0-> Q state */ + u32 next_qid; /* 17:10->next QId */ + u32 reserved3; + u32 reserved4[4]; +}; + +struct bna_rxtx_q_mem { + struct bna_rxq_mem rxq; + struct bna_txq_mem txq; +}; + +struct bna_cq_mem { + u32 pg_tbl_addr_lo; + u32 pg_tbl_addr_hi; + u32 cur_q_entry_lo; + u32 cur_q_entry_hi; + + u32 reserved1; + u32 reserved2; + u32 pg_cnt_n_prd_ptr; /* 31:16->total page count */ + /* 15:0 ->producer pointer (index?) */ + u32 entry_n_pg_size; /* 31:16->entry size */ + /* 15:0 ->page size */ + u32 int_blk_n_cns_ptr; /* 31:24->Int Blk Id; */ + /* 23:16->Int Blk Offset */ + /* 15:0 ->consumer pointer(index?) */ + u32 q_state; /* 31:16->reserved; 15:0-> Q state */ + u32 reserved3[2]; + u32 reserved4[4]; +}; + +struct bna_ib_blk_mem { + u32 host_addr_lo; + u32 host_addr_hi; + u32 clsc_n_ctrl_n_msix; /* 31:24->coalescing; */ + /* 23:16->coalescing cfg; */ + /* 15:8 ->control; */ + /* 7:0 ->msix; */ + u32 ipkt_n_ent_n_idxof; + u32 ipkt_cnt_cfg_n_unacked; + + u32 reserved[3]; +}; + +struct bna_idx_tbl_mem { + u32 idx; /* !< 31:16->res;15:0->idx; */ +}; + +struct bna_doorbell_qset { + u32 rxq[0x20 >> 2]; + u32 txq[0x20 >> 2]; + u32 ib0[0x20 >> 2]; + u32 ib1[0x20 >> 2]; +}; + +struct bna_rx_fndb_ram { + u32 rss_prop; + u32 size_routing_props; + u32 rit_hds_mcastq; + u32 control_flags; +}; + +struct bna_tx_fndb_ram { + u32 vlan_n_ctrl_flags; +}; + +/** + * @brief + * Structure which maps to RxFn Indirection Table (RIT) + * Size : 1 word + * See catapult_spec.pdf, RxA for details + */ +struct bna_rit_mem { + u32 rxq_ids; /* !< 31:12->res;11:0->two 6 bit RxQ Ids */ +}; + +/** + * @brief + * Structure which maps to RSS Table entry + * Size : 16 words + * See catapult_spec.pdf, RAD for details + */ +struct bna_rss_mem { + /* + * 31:12-> res + * 11:8 -> protocol type + * 7:0 -> hash index + */ + u32 type_n_hash; + u32 hash_key[10]; /* !< 40 byte Toeplitz hash key */ + u32 reserved[5]; +}; + +/* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */ +struct bna_dma_addr { + u32 msb; + u32 lsb; +}; + +struct bna_txq_wi_vector { + u16 reserved; + u16 length; /* Only 14 LSB are valid */ + struct bna_dma_addr host_addr; /* Tx-Buf DMA addr */ +}; + +typedef u16 bna_txq_wi_opcode_t; + +typedef u16 bna_txq_wi_ctrl_flag_t; + +/** + * TxQ Entry Structure + * + * BEWARE: Load values into this structure with correct endianess. + */ +struct bna_txq_entry { + union { + struct { + u8 reserved; + u8 num_vectors; /* number of vectors present */ + bna_txq_wi_opcode_t opcode; /* Either */ + /* BNA_TXQ_WI_SEND or */ + /* BNA_TXQ_WI_SEND_LSO */ + bna_txq_wi_ctrl_flag_t flags; /* OR of all the flags */ + u16 l4_hdr_size_n_offset; + u16 vlan_tag; + u16 lso_mss; /* Only 14 LSB are valid */ + u32 frame_length; /* Only 24 LSB are valid */ + } wi; + + struct { + u16 reserved; + bna_txq_wi_opcode_t opcode; /* Must be */ + /* BNA_TXQ_WI_EXTENSION */ + u32 reserved2[3]; /* Place holder for */ + /* removed vector (12 bytes) */ + } wi_ext; + } hdr; + struct bna_txq_wi_vector vector[4]; +}; +#define wi_hdr hdr.wi +#define wi_ext_hdr hdr.wi_ext + +/* RxQ Entry Structure */ +struct bna_rxq_entry { /* Rx-Buffer */ + struct bna_dma_addr host_addr; /* Rx-Buffer DMA address */ +}; + +typedef u32 bna_cq_e_flag_t; + +/* CQ Entry Structure */ +struct bna_cq_entry { + bna_cq_e_flag_t flags; + u16 vlan_tag; + u16 length; + u32 rss_hash; + u8 valid; + u8 reserved1; + u8 reserved2; + u8 rxq_id; +}; + +#endif /* __BNA_HW_H__ */ diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c new file mode 100644 index 000000000000..890846d55502 --- /dev/null +++ b/drivers/net/bna/bna_txrx.c @@ -0,0 +1,4209 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ +#include "bna.h" +#include "bfa_sm.h" +#include "bfi.h" + +/** + * IB + */ +#define bna_ib_find_free_ibidx(_mask, _pos)\ +do {\ + (_pos) = 0;\ + while (((_pos) < (BFI_IBIDX_MAX_SEGSIZE)) &&\ + ((1 << (_pos)) & (_mask)))\ + (_pos)++;\ +} while (0) + +#define bna_ib_count_ibidx(_mask, _count)\ +do {\ + int pos = 0;\ + (_count) = 0;\ + while (pos < (BFI_IBIDX_MAX_SEGSIZE)) {\ + if ((1 << pos) & (_mask))\ + (_count) = pos + 1;\ + pos++;\ + } \ +} while (0) + +#define bna_ib_select_segpool(_count, _q_idx)\ +do {\ + int i;\ + (_q_idx) = -1;\ + for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {\ + if ((_count <= ibidx_pool[i].pool_entry_size)) {\ + (_q_idx) = i;\ + break;\ + } \ + } \ +} while (0) + +struct bna_ibidx_pool { + int pool_size; + int pool_entry_size; +}; +init_ibidx_pool(ibidx_pool); + +static struct bna_intr * +bna_intr_get(struct bna_ib_mod *ib_mod, enum bna_intr_type intr_type, + int vector) +{ + struct bna_intr *intr; + struct list_head *qe; + + list_for_each(qe, &ib_mod->intr_active_q) { + intr = (struct bna_intr *)qe; + + if ((intr->intr_type == intr_type) && + (intr->vector == vector)) { + intr->ref_count++; + return intr; + } + } + + if (list_empty(&ib_mod->intr_free_q)) + return NULL; + + bfa_q_deq(&ib_mod->intr_free_q, &intr); + bfa_q_qe_init(&intr->qe); + + intr->ref_count = 1; + intr->intr_type = intr_type; + intr->vector = vector; + + list_add_tail(&intr->qe, &ib_mod->intr_active_q); + + return intr; +} + +static void +bna_intr_put(struct bna_ib_mod *ib_mod, + struct bna_intr *intr) +{ + intr->ref_count--; + + if (intr->ref_count == 0) { + intr->ib = NULL; + list_del(&intr->qe); + bfa_q_qe_init(&intr->qe); + list_add_tail(&intr->qe, &ib_mod->intr_free_q); + } +} + +void +bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna, + struct bna_res_info *res_info) +{ + int i; + int j; + int count; + u8 offset; + struct bna_doorbell_qset *qset; + unsigned long off; + + ib_mod->bna = bna; + + ib_mod->ib = (struct bna_ib *) + res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mdl[0].kva; + ib_mod->intr = (struct bna_intr *) + res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mdl[0].kva; + ib_mod->idx_seg = (struct bna_ibidx_seg *) + res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mdl[0].kva; + + INIT_LIST_HEAD(&ib_mod->ib_free_q); + INIT_LIST_HEAD(&ib_mod->intr_free_q); + INIT_LIST_HEAD(&ib_mod->intr_active_q); + + for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) + INIT_LIST_HEAD(&ib_mod->ibidx_seg_pool[i]); + + for (i = 0; i < BFI_MAX_IB; i++) { + ib_mod->ib[i].ib_id = i; + + ib_mod->ib[i].ib_seg_host_addr_kva = + res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].kva; + ib_mod->ib[i].ib_seg_host_addr.lsb = + res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.lsb; + ib_mod->ib[i].ib_seg_host_addr.msb = + res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.msb; + + qset = (struct bna_doorbell_qset *)0; + off = (unsigned long)(&qset[i >> 1].ib0[(i & 0x1) + * (0x20 >> 2)]); + ib_mod->ib[i].door_bell.doorbell_addr = off + + BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva); + + bfa_q_qe_init(&ib_mod->ib[i].qe); + list_add_tail(&ib_mod->ib[i].qe, &ib_mod->ib_free_q); + + bfa_q_qe_init(&ib_mod->intr[i].qe); + list_add_tail(&ib_mod->intr[i].qe, &ib_mod->intr_free_q); + } + + count = 0; + offset = 0; + for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) { + for (j = 0; j < ibidx_pool[i].pool_size; j++) { + bfa_q_qe_init(&ib_mod->idx_seg[count]); + ib_mod->idx_seg[count].ib_seg_size = + ibidx_pool[i].pool_entry_size; + ib_mod->idx_seg[count].ib_idx_tbl_offset = offset; + list_add_tail(&ib_mod->idx_seg[count].qe, + &ib_mod->ibidx_seg_pool[i]); + count++; + offset += ibidx_pool[i].pool_entry_size; + } + } +} + +void +bna_ib_mod_uninit(struct bna_ib_mod *ib_mod) +{ + int i; + int j; + struct list_head *qe; + + i = 0; + list_for_each(qe, &ib_mod->ib_free_q) + i++; + + i = 0; + list_for_each(qe, &ib_mod->intr_free_q) + i++; + + for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) { + j = 0; + list_for_each(qe, &ib_mod->ibidx_seg_pool[i]) + j++; + } + + ib_mod->bna = NULL; +} + +struct bna_ib * +bna_ib_get(struct bna_ib_mod *ib_mod, + enum bna_intr_type intr_type, + int vector) +{ + struct bna_ib *ib; + struct bna_intr *intr; + + if (intr_type == BNA_INTR_T_INTX) + vector = (1 << vector); + + intr = bna_intr_get(ib_mod, intr_type, vector); + if (intr == NULL) + return NULL; + + if (intr->ib) { + if (intr->ib->ref_count == BFI_IBIDX_MAX_SEGSIZE) { + bna_intr_put(ib_mod, intr); + return NULL; + } + intr->ib->ref_count++; + return intr->ib; + } + + if (list_empty(&ib_mod->ib_free_q)) { + bna_intr_put(ib_mod, intr); + return NULL; + } + + bfa_q_deq(&ib_mod->ib_free_q, &ib); + bfa_q_qe_init(&ib->qe); + + ib->ref_count = 1; + ib->start_count = 0; + ib->idx_mask = 0; + + ib->intr = intr; + ib->idx_seg = NULL; + intr->ib = ib; + + ib->bna = ib_mod->bna; + + return ib; +} + +void +bna_ib_put(struct bna_ib_mod *ib_mod, struct bna_ib *ib) +{ + bna_intr_put(ib_mod, ib->intr); + + ib->ref_count--; + + if (ib->ref_count == 0) { + ib->intr = NULL; + ib->bna = NULL; + list_add_tail(&ib->qe, &ib_mod->ib_free_q); + } +} + +/* Returns index offset - starting from 0 */ +int +bna_ib_reserve_idx(struct bna_ib *ib) +{ + struct bna_ib_mod *ib_mod = &ib->bna->ib_mod; + struct bna_ibidx_seg *idx_seg; + int idx; + int num_idx; + int q_idx; + + /* Find the first free index position */ + bna_ib_find_free_ibidx(ib->idx_mask, idx); + if (idx == BFI_IBIDX_MAX_SEGSIZE) + return -1; + + /* + * Calculate the total number of indexes held by this IB, + * including the index newly reserved above. + */ + bna_ib_count_ibidx((ib->idx_mask | (1 << idx)), num_idx); + + /* See if there is a free space in the index segment held by this IB */ + if (ib->idx_seg && (num_idx <= ib->idx_seg->ib_seg_size)) { + ib->idx_mask |= (1 << idx); + return idx; + } + + if (ib->start_count) + return -1; + + /* Allocate a new segment */ + bna_ib_select_segpool(num_idx, q_idx); + while (1) { + if (q_idx == BFI_IBIDX_TOTAL_POOLS) + return -1; + if (!list_empty(&ib_mod->ibidx_seg_pool[q_idx])) + break; + q_idx++; + } + bfa_q_deq(&ib_mod->ibidx_seg_pool[q_idx], &idx_seg); + bfa_q_qe_init(&idx_seg->qe); + + /* Free the old segment */ + if (ib->idx_seg) { + bna_ib_select_segpool(ib->idx_seg->ib_seg_size, q_idx); + list_add_tail(&ib->idx_seg->qe, &ib_mod->ibidx_seg_pool[q_idx]); + } + + ib->idx_seg = idx_seg; + + ib->idx_mask |= (1 << idx); + + return idx; +} + +void +bna_ib_release_idx(struct bna_ib *ib, int idx) +{ + struct bna_ib_mod *ib_mod = &ib->bna->ib_mod; + struct bna_ibidx_seg *idx_seg; + int num_idx; + int cur_q_idx; + int new_q_idx; + + ib->idx_mask &= ~(1 << idx); + + if (ib->start_count) + return; + + bna_ib_count_ibidx(ib->idx_mask, num_idx); + + /* + * Free the segment, if there are no more indexes in the segment + * held by this IB + */ + if (!num_idx) { + bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx); + list_add_tail(&ib->idx_seg->qe, + &ib_mod->ibidx_seg_pool[cur_q_idx]); + ib->idx_seg = NULL; + return; + } + + /* See if we can move to a smaller segment */ + bna_ib_select_segpool(num_idx, new_q_idx); + bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx); + while (new_q_idx < cur_q_idx) { + if (!list_empty(&ib_mod->ibidx_seg_pool[new_q_idx])) + break; + new_q_idx++; + } + if (new_q_idx < cur_q_idx) { + /* Select the new smaller segment */ + bfa_q_deq(&ib_mod->ibidx_seg_pool[new_q_idx], &idx_seg); + bfa_q_qe_init(&idx_seg->qe); + /* Free the old segment */ + list_add_tail(&ib->idx_seg->qe, + &ib_mod->ibidx_seg_pool[cur_q_idx]); + ib->idx_seg = idx_seg; + } +} + +int +bna_ib_config(struct bna_ib *ib, struct bna_ib_config *ib_config) +{ + if (ib->start_count) + return -1; + + ib->ib_config.coalescing_timeo = ib_config->coalescing_timeo; + ib->ib_config.interpkt_timeo = ib_config->interpkt_timeo; + ib->ib_config.interpkt_count = ib_config->interpkt_count; + ib->ib_config.ctrl_flags = ib_config->ctrl_flags; + + ib->ib_config.ctrl_flags |= BFI_IB_CF_MASTER_ENABLE; + if (ib->intr->intr_type == BNA_INTR_T_MSIX) + ib->ib_config.ctrl_flags |= BFI_IB_CF_MSIX_MODE; + + return 0; +} + +void +bna_ib_start(struct bna_ib *ib) +{ + struct bna_ib_blk_mem ib_cfg; + struct bna_ib_blk_mem *ib_mem; + u32 pg_num; + u32 intx_mask; + int i; + void __iomem *base_addr; + unsigned long off; + + ib->start_count++; + + if (ib->start_count > 1) + return; + + ib_cfg.host_addr_lo = (u32)(ib->ib_seg_host_addr.lsb); + ib_cfg.host_addr_hi = (u32)(ib->ib_seg_host_addr.msb); + + ib_cfg.clsc_n_ctrl_n_msix = (((u32) + ib->ib_config.coalescing_timeo << 16) | + ((u32)ib->ib_config.ctrl_flags << 8) | + (ib->intr->vector)); + ib_cfg.ipkt_n_ent_n_idxof = + ((u32) + (ib->ib_config.interpkt_timeo & 0xf) << 16) | + ((u32)ib->idx_seg->ib_seg_size << 8) | + (ib->idx_seg->ib_idx_tbl_offset); + ib_cfg.ipkt_cnt_cfg_n_unacked = ((u32) + ib->ib_config.interpkt_count << 24); + + pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num, + HQM_IB_RAM_BASE_OFFSET); + writel(pg_num, ib->bna->regs.page_addr); + + base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva, + HQM_IB_RAM_BASE_OFFSET); + + ib_mem = (struct bna_ib_blk_mem *)0; + off = (unsigned long)&ib_mem[ib->ib_id].host_addr_lo; + writel(htonl(ib_cfg.host_addr_lo), base_addr + off); + + off = (unsigned long)&ib_mem[ib->ib_id].host_addr_hi; + writel(htonl(ib_cfg.host_addr_hi), base_addr + off); + + off = (unsigned long)&ib_mem[ib->ib_id].clsc_n_ctrl_n_msix; + writel(ib_cfg.clsc_n_ctrl_n_msix, base_addr + off); + + off = (unsigned long)&ib_mem[ib->ib_id].ipkt_n_ent_n_idxof; + writel(ib_cfg.ipkt_n_ent_n_idxof, base_addr + off); + + off = (unsigned long)&ib_mem[ib->ib_id].ipkt_cnt_cfg_n_unacked; + writel(ib_cfg.ipkt_cnt_cfg_n_unacked, base_addr + off); + + ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK( + (u32)ib->ib_config.coalescing_timeo, 0); + + pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num, + HQM_INDX_TBL_RAM_BASE_OFFSET); + writel(pg_num, ib->bna->regs.page_addr); + + base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva, + HQM_INDX_TBL_RAM_BASE_OFFSET); + for (i = 0; i < ib->idx_seg->ib_seg_size; i++) { + off = (unsigned long) + ((ib->idx_seg->ib_idx_tbl_offset + i) * BFI_IBIDX_SIZE); + writel(0, base_addr + off); + } + + if (ib->intr->intr_type == BNA_INTR_T_INTX) { + bna_intx_disable(ib->bna, intx_mask); + intx_mask &= ~(ib->intr->vector); + bna_intx_enable(ib->bna, intx_mask); + } +} + +void +bna_ib_stop(struct bna_ib *ib) +{ + u32 intx_mask; + + ib->start_count--; + + if (ib->start_count == 0) { + writel(BNA_DOORBELL_IB_INT_DISABLE, + ib->door_bell.doorbell_addr); + if (ib->intr->intr_type == BNA_INTR_T_INTX) { + bna_intx_disable(ib->bna, intx_mask); + intx_mask |= (ib->intr->vector); + bna_intx_enable(ib->bna, intx_mask); + } + } +} + +void +bna_ib_fail(struct bna_ib *ib) +{ + ib->start_count = 0; +} + +/** + * RXF + */ +static void rxf_enable(struct bna_rxf *rxf); +static void rxf_disable(struct bna_rxf *rxf); +static void __rxf_config_set(struct bna_rxf *rxf); +static void __rxf_rit_set(struct bna_rxf *rxf); +static void __bna_rxf_stat_clr(struct bna_rxf *rxf); +static int rxf_process_packet_filter(struct bna_rxf *rxf); +static int rxf_clear_packet_filter(struct bna_rxf *rxf); +static void rxf_reset_packet_filter(struct bna_rxf *rxf); +static void rxf_cb_enabled(void *arg, int status); +static void rxf_cb_disabled(void *arg, int status); +static void bna_rxf_cb_stats_cleared(void *arg, int status); +static void __rxf_enable(struct bna_rxf *rxf); +static void __rxf_disable(struct bna_rxf *rxf); + +bfa_fsm_state_decl(bna_rxf, stopped, struct bna_rxf, + enum bna_rxf_event); +bfa_fsm_state_decl(bna_rxf, start_wait, struct bna_rxf, + enum bna_rxf_event); +bfa_fsm_state_decl(bna_rxf, cam_fltr_mod_wait, struct bna_rxf, + enum bna_rxf_event); +bfa_fsm_state_decl(bna_rxf, started, struct bna_rxf, + enum bna_rxf_event); +bfa_fsm_state_decl(bna_rxf, cam_fltr_clr_wait, struct bna_rxf, + enum bna_rxf_event); +bfa_fsm_state_decl(bna_rxf, stop_wait, struct bna_rxf, + enum bna_rxf_event); +bfa_fsm_state_decl(bna_rxf, pause_wait, struct bna_rxf, + enum bna_rxf_event); +bfa_fsm_state_decl(bna_rxf, resume_wait, struct bna_rxf, + enum bna_rxf_event); +bfa_fsm_state_decl(bna_rxf, stat_clr_wait, struct bna_rxf, + enum bna_rxf_event); + +static struct bfa_sm_table rxf_sm_table[] = { + {BFA_SM(bna_rxf_sm_stopped), BNA_RXF_STOPPED}, + {BFA_SM(bna_rxf_sm_start_wait), BNA_RXF_START_WAIT}, + {BFA_SM(bna_rxf_sm_cam_fltr_mod_wait), BNA_RXF_CAM_FLTR_MOD_WAIT}, + {BFA_SM(bna_rxf_sm_started), BNA_RXF_STARTED}, + {BFA_SM(bna_rxf_sm_cam_fltr_clr_wait), BNA_RXF_CAM_FLTR_CLR_WAIT}, + {BFA_SM(bna_rxf_sm_stop_wait), BNA_RXF_STOP_WAIT}, + {BFA_SM(bna_rxf_sm_pause_wait), BNA_RXF_PAUSE_WAIT}, + {BFA_SM(bna_rxf_sm_resume_wait), BNA_RXF_RESUME_WAIT}, + {BFA_SM(bna_rxf_sm_stat_clr_wait), BNA_RXF_STAT_CLR_WAIT} +}; + +static void +bna_rxf_sm_stopped_entry(struct bna_rxf *rxf) +{ + call_rxf_stop_cbfn(rxf, BNA_CB_SUCCESS); +} + +static void +bna_rxf_sm_stopped(struct bna_rxf *rxf, enum bna_rxf_event event) +{ + switch (event) { + case RXF_E_START: + bfa_fsm_set_state(rxf, bna_rxf_sm_start_wait); + break; + + case RXF_E_STOP: + bfa_fsm_set_state(rxf, bna_rxf_sm_stopped); + break; + + case RXF_E_FAIL: + /* No-op */ + break; + + case RXF_E_CAM_FLTR_MOD: + call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS); + break; + + case RXF_E_STARTED: + case RXF_E_STOPPED: + case RXF_E_CAM_FLTR_RESP: + /** + * These events are received due to flushing of mbox + * when device fails + */ + /* No-op */ + break; + + case RXF_E_PAUSE: + rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED; + call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS); + break; + + case RXF_E_RESUME: + rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING; + call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS); + break; + + default: + bfa_sm_fault(rxf->rx->bna, event); + } +} + +static void +bna_rxf_sm_start_wait_entry(struct bna_rxf *rxf) +{ + __rxf_config_set(rxf); + __rxf_rit_set(rxf); + rxf_enable(rxf); +} + +static void +bna_rxf_sm_start_wait(struct bna_rxf *rxf, enum bna_rxf_event event) +{ + switch (event) { + case RXF_E_STOP: + /** + * STOP is originated from bnad. When this happens, + * it can not be waiting for filter update + */ + call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT); + bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait); + break; + + case RXF_E_FAIL: + call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS); + call_rxf_start_cbfn(rxf, BNA_CB_FAIL); + bfa_fsm_set_state(rxf, bna_rxf_sm_stopped); + break; + + case RXF_E_CAM_FLTR_MOD: + /* No-op */ + break; + + case RXF_E_STARTED: + /** + * Force rxf_process_filter() to go through initial + * config + */ + if ((rxf->ucast_active_mac != NULL) && + (rxf->ucast_pending_set == 0)) + rxf->ucast_pending_set = 1; + + if (rxf->rss_status == BNA_STATUS_T_ENABLED) + rxf->rxf_flags |= BNA_RXF_FL_RSS_CONFIG_PENDING; + + rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING; + + bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait); + break; + + case RXF_E_PAUSE: + case RXF_E_RESUME: + rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED; + break; + + default: + bfa_sm_fault(rxf->rx->bna, event); + } +} + +static void +bna_rxf_sm_cam_fltr_mod_wait_entry(struct bna_rxf *rxf) +{ + if (!rxf_process_packet_filter(rxf)) { + /* No more pending CAM entries to update */ + bfa_fsm_set_state(rxf, bna_rxf_sm_started); + } +} + +static void +bna_rxf_sm_cam_fltr_mod_wait(struct bna_rxf *rxf, enum bna_rxf_event event) +{ + switch (event) { + case RXF_E_STOP: + /** + * STOP is originated from bnad. When this happens, + * it can not be waiting for filter update + */ + call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT); + bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait); + break; + + case RXF_E_FAIL: + rxf_reset_packet_filter(rxf); + call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS); + call_rxf_start_cbfn(rxf, BNA_CB_FAIL); + bfa_fsm_set_state(rxf, bna_rxf_sm_stopped); + break; + + case RXF_E_CAM_FLTR_MOD: + /* No-op */ + break; + + case RXF_E_CAM_FLTR_RESP: + if (!rxf_process_packet_filter(rxf)) { + /* No more pending CAM entries to update */ + call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS); + bfa_fsm_set_state(rxf, bna_rxf_sm_started); + } + break; + + case RXF_E_PAUSE: + case RXF_E_RESUME: + rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED; + break; + + default: + bfa_sm_fault(rxf->rx->bna, event); + } +} + +static void +bna_rxf_sm_started_entry(struct bna_rxf *rxf) +{ + call_rxf_start_cbfn(rxf, BNA_CB_SUCCESS); + + if (rxf->rxf_flags & BNA_RXF_FL_OPERSTATE_CHANGED) { + if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED) + bfa_fsm_send_event(rxf, RXF_E_PAUSE); + else + bfa_fsm_send_event(rxf, RXF_E_RESUME); + } + +} + +static void +bna_rxf_sm_started(struct bna_rxf *rxf, enum bna_rxf_event event) +{ + switch (event) { + case RXF_E_STOP: + bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait); + /* Hack to get FSM start clearing CAM entries */ + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP); + break; + + case RXF_E_FAIL: + rxf_reset_packet_filter(rxf); + bfa_fsm_set_state(rxf, bna_rxf_sm_stopped); + break; + + case RXF_E_CAM_FLTR_MOD: + bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait); + break; + + case RXF_E_PAUSE: + bfa_fsm_set_state(rxf, bna_rxf_sm_pause_wait); + break; + + case RXF_E_RESUME: + bfa_fsm_set_state(rxf, bna_rxf_sm_resume_wait); + break; + + default: + bfa_sm_fault(rxf->rx->bna, event); + } +} + +static void +bna_rxf_sm_cam_fltr_clr_wait_entry(struct bna_rxf *rxf) +{ + /** + * Note: Do not add rxf_clear_packet_filter here. + * It will overstep mbox when this transition happens: + * cam_fltr_mod_wait -> cam_fltr_clr_wait on RXF_E_STOP event + */ +} + +static void +bna_rxf_sm_cam_fltr_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event) +{ + switch (event) { + case RXF_E_FAIL: + /** + * FSM was in the process of stopping, initiated by + * bnad. When this happens, no one can be waiting for + * start or filter update + */ + rxf_reset_packet_filter(rxf); + bfa_fsm_set_state(rxf, bna_rxf_sm_stopped); + break; + + case RXF_E_CAM_FLTR_RESP: + if (!rxf_clear_packet_filter(rxf)) { + /* No more pending CAM entries to clear */ + bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait); + rxf_disable(rxf); + } + break; + + default: + bfa_sm_fault(rxf->rx->bna, event); + } +} + +static void +bna_rxf_sm_stop_wait_entry(struct bna_rxf *rxf) +{ + /** + * NOTE: Do not add rxf_disable here. + * It will overstep mbox when this transition happens: + * start_wait -> stop_wait on RXF_E_STOP event + */ +} + +static void +bna_rxf_sm_stop_wait(struct bna_rxf *rxf, enum bna_rxf_event event) +{ + switch (event) { + case RXF_E_FAIL: + /** + * FSM was in the process of stopping, initiated by + * bnad. When this happens, no one can be waiting for + * start or filter update + */ + bfa_fsm_set_state(rxf, bna_rxf_sm_stopped); + break; + + case RXF_E_STARTED: + /** + * This event is received due to abrupt transition from + * bna_rxf_sm_start_wait state on receiving + * RXF_E_STOP event + */ + rxf_disable(rxf); + break; + + case RXF_E_STOPPED: + /** + * FSM was in the process of stopping, initiated by + * bnad. When this happens, no one can be waiting for + * start or filter update + */ + bfa_fsm_set_state(rxf, bna_rxf_sm_stat_clr_wait); + break; + + case RXF_E_PAUSE: + rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED; + break; + + case RXF_E_RESUME: + rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING; + break; + + default: + bfa_sm_fault(rxf->rx->bna, event); + } +} + +static void +bna_rxf_sm_pause_wait_entry(struct bna_rxf *rxf) +{ + rxf->rxf_flags &= + ~(BNA_RXF_FL_OPERSTATE_CHANGED | BNA_RXF_FL_RXF_ENABLED); + __rxf_disable(rxf); +} + +static void +bna_rxf_sm_pause_wait(struct bna_rxf *rxf, enum bna_rxf_event event) +{ + switch (event) { + case RXF_E_FAIL: + /** + * FSM was in the process of disabling rxf, initiated by + * bnad. + */ + call_rxf_pause_cbfn(rxf, BNA_CB_FAIL); + bfa_fsm_set_state(rxf, bna_rxf_sm_stopped); + break; + + case RXF_E_STOPPED: + rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED; + call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS); + bfa_fsm_set_state(rxf, bna_rxf_sm_started); + break; + + /* + * Since PAUSE/RESUME can only be sent by bnad, we don't expect + * any other event during these states + */ + default: + bfa_sm_fault(rxf->rx->bna, event); + } +} + +static void +bna_rxf_sm_resume_wait_entry(struct bna_rxf *rxf) +{ + rxf->rxf_flags &= ~(BNA_RXF_FL_OPERSTATE_CHANGED); + rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED; + __rxf_enable(rxf); +} + +static void +bna_rxf_sm_resume_wait(struct bna_rxf *rxf, enum bna_rxf_event event) +{ + switch (event) { + case RXF_E_FAIL: + /** + * FSM was in the process of disabling rxf, initiated by + * bnad. + */ + call_rxf_resume_cbfn(rxf, BNA_CB_FAIL); + bfa_fsm_set_state(rxf, bna_rxf_sm_stopped); + break; + + case RXF_E_STARTED: + rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING; + call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS); + bfa_fsm_set_state(rxf, bna_rxf_sm_started); + break; + + /* + * Since PAUSE/RESUME can only be sent by bnad, we don't expect + * any other event during these states + */ + default: + bfa_sm_fault(rxf->rx->bna, event); + } +} + +static void +bna_rxf_sm_stat_clr_wait_entry(struct bna_rxf *rxf) +{ + __bna_rxf_stat_clr(rxf); +} + +static void +bna_rxf_sm_stat_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event) +{ + switch (event) { + case RXF_E_FAIL: + case RXF_E_STAT_CLEARED: + bfa_fsm_set_state(rxf, bna_rxf_sm_stopped); + break; + + default: + bfa_sm_fault(rxf->rx->bna, event); + } +} + +static void +__rxf_enable(struct bna_rxf *rxf) +{ + struct bfi_ll_rxf_multi_req ll_req; + u32 bm[2] = {0, 0}; + + if (rxf->rxf_id < 32) + bm[0] = 1 << rxf->rxf_id; + else + bm[1] = 1 << (rxf->rxf_id - 32); + + bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0); + ll_req.rxf_id_mask[0] = htonl(bm[0]); + ll_req.rxf_id_mask[1] = htonl(bm[1]); + ll_req.enable = 1; + + bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req), + rxf_cb_enabled, rxf); + + bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe); +} + +static void +__rxf_disable(struct bna_rxf *rxf) +{ + struct bfi_ll_rxf_multi_req ll_req; + u32 bm[2] = {0, 0}; + + if (rxf->rxf_id < 32) + bm[0] = 1 << rxf->rxf_id; + else + bm[1] = 1 << (rxf->rxf_id - 32); + + bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0); + ll_req.rxf_id_mask[0] = htonl(bm[0]); + ll_req.rxf_id_mask[1] = htonl(bm[1]); + ll_req.enable = 0; + + bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req), + rxf_cb_disabled, rxf); + + bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe); +} + +static void +__rxf_config_set(struct bna_rxf *rxf) +{ + u32 i; + struct bna_rss_mem *rss_mem; + struct bna_rx_fndb_ram *rx_fndb_ram; + struct bna *bna = rxf->rx->bna; + void __iomem *base_addr; + unsigned long off; + + base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva, + RSS_TABLE_BASE_OFFSET); + + rss_mem = (struct bna_rss_mem *)0; + + /* Configure RSS if required */ + if (rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE) { + /* configure RSS Table */ + writel(BNA_GET_PAGE_NUM(RAD0_MEM_BLK_BASE_PG_NUM + + bna->port_num, RSS_TABLE_BASE_OFFSET), + bna->regs.page_addr); + + /* temporarily disable RSS, while hash value is written */ + off = (unsigned long)&rss_mem[0].type_n_hash; + writel(0, base_addr + off); + + for (i = 0; i < BFI_RSS_HASH_KEY_LEN; i++) { + off = (unsigned long) + &rss_mem[0].hash_key[(BFI_RSS_HASH_KEY_LEN - 1) - i]; + writel(htonl(rxf->rss_cfg.toeplitz_hash_key[i]), + base_addr + off); + } + + off = (unsigned long)&rss_mem[0].type_n_hash; + writel(rxf->rss_cfg.hash_type | rxf->rss_cfg.hash_mask, + base_addr + off); + } + + /* Configure RxF */ + writel(BNA_GET_PAGE_NUM( + LUT0_MEM_BLK_BASE_PG_NUM + (bna->port_num * 2), + RX_FNDB_RAM_BASE_OFFSET), + bna->regs.page_addr); + + base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva, + RX_FNDB_RAM_BASE_OFFSET); + + rx_fndb_ram = (struct bna_rx_fndb_ram *)0; + + /* We always use RSS table 0 */ + off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rss_prop; + writel(rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE, + base_addr + off); + + /* small large buffer enable/disable */ + off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].size_routing_props; + writel((rxf->ctrl_flags & BNA_RXF_CF_SM_LG_RXQ) | 0x80, + base_addr + off); + + /* RIT offset, HDS forced offset, multicast RxQ Id */ + off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rit_hds_mcastq; + writel((rxf->rit_segment->rit_offset << 16) | + (rxf->forced_offset << 8) | + (rxf->hds_cfg.hdr_type & BNA_HDS_FORCED) | rxf->mcast_rxq_id, + base_addr + off); + + /* + * default vlan tag, default function enable, strip vlan bytes, + * HDS type, header size + */ + + off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].control_flags; + writel(((u32)rxf->default_vlan_tag << 16) | + (rxf->ctrl_flags & + (BNA_RXF_CF_DEFAULT_VLAN | + BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE | + BNA_RXF_CF_VLAN_STRIP)) | + (rxf->hds_cfg.hdr_type & ~BNA_HDS_FORCED) | + rxf->hds_cfg.header_size, + base_addr + off); +} + +void +__rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status) +{ + struct bna *bna = rxf->rx->bna; + int i; + + writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM + + (bna->port_num * 2), VLAN_RAM_BASE_OFFSET), + bna->regs.page_addr); + + if (status == BNA_STATUS_T_ENABLED) { + /* enable VLAN filtering on this function */ + for (i = 0; i <= BFI_MAX_VLAN / 32; i++) { + writel(rxf->vlan_filter_table[i], + BNA_GET_VLAN_MEM_ENTRY_ADDR + (bna->pcidev.pci_bar_kva, rxf->rxf_id, + i * 32)); + } + } else { + /* disable VLAN filtering on this function */ + for (i = 0; i <= BFI_MAX_VLAN / 32; i++) { + writel(0xffffffff, + BNA_GET_VLAN_MEM_ENTRY_ADDR + (bna->pcidev.pci_bar_kva, rxf->rxf_id, + i * 32)); + } + } +} + +static void +__rxf_rit_set(struct bna_rxf *rxf) +{ + struct bna *bna = rxf->rx->bna; + struct bna_rit_mem *rit_mem; + int i; + void __iomem *base_addr; + unsigned long off; + + base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva, + FUNCTION_TO_RXQ_TRANSLATE); + + rit_mem = (struct bna_rit_mem *)0; + + writel(BNA_GET_PAGE_NUM(RXA0_MEM_BLK_BASE_PG_NUM + bna->port_num, + FUNCTION_TO_RXQ_TRANSLATE), + bna->regs.page_addr); + + for (i = 0; i < rxf->rit_segment->rit_size; i++) { + off = (unsigned long)&rit_mem[i + rxf->rit_segment->rit_offset]; + writel(rxf->rit_segment->rit[i].large_rxq_id << 6 | + rxf->rit_segment->rit[i].small_rxq_id, + base_addr + off); + } +} + +static void +__bna_rxf_stat_clr(struct bna_rxf *rxf) +{ + struct bfi_ll_stats_req ll_req; + u32 bm[2] = {0, 0}; + + if (rxf->rxf_id < 32) + bm[0] = 1 << rxf->rxf_id; + else + bm[1] = 1 << (rxf->rxf_id - 32); + + bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0); + ll_req.stats_mask = 0; + ll_req.txf_id_mask[0] = 0; + ll_req.txf_id_mask[1] = 0; + + ll_req.rxf_id_mask[0] = htonl(bm[0]); + ll_req.rxf_id_mask[1] = htonl(bm[1]); + + bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req), + bna_rxf_cb_stats_cleared, rxf); + bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe); +} + +static void +rxf_enable(struct bna_rxf *rxf) +{ + if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED) + bfa_fsm_send_event(rxf, RXF_E_STARTED); + else { + rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED; + __rxf_enable(rxf); + } +} + +static void +rxf_cb_enabled(void *arg, int status) +{ + struct bna_rxf *rxf = (struct bna_rxf *)arg; + + bfa_q_qe_init(&rxf->mbox_qe.qe); + bfa_fsm_send_event(rxf, RXF_E_STARTED); +} + +static void +rxf_disable(struct bna_rxf *rxf) +{ + if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED) + bfa_fsm_send_event(rxf, RXF_E_STOPPED); + else + rxf->rxf_flags &= ~BNA_RXF_FL_RXF_ENABLED; + __rxf_disable(rxf); +} + +static void +rxf_cb_disabled(void *arg, int status) +{ + struct bna_rxf *rxf = (struct bna_rxf *)arg; + + bfa_q_qe_init(&rxf->mbox_qe.qe); + bfa_fsm_send_event(rxf, RXF_E_STOPPED); +} + +void +rxf_cb_cam_fltr_mbox_cmd(void *arg, int status) +{ + struct bna_rxf *rxf = (struct bna_rxf *)arg; + + bfa_q_qe_init(&rxf->mbox_qe.qe); + + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP); +} + +static void +bna_rxf_cb_stats_cleared(void *arg, int status) +{ + struct bna_rxf *rxf = (struct bna_rxf *)arg; + + bfa_q_qe_init(&rxf->mbox_qe.qe); + bfa_fsm_send_event(rxf, RXF_E_STAT_CLEARED); +} + +void +rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd, + const struct bna_mac *mac_addr) +{ + struct bfi_ll_mac_addr_req req; + + bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0); + + req.rxf_id = rxf->rxf_id; + memcpy(&req.mac_addr, (void *)&mac_addr->addr, ETH_ALEN); + + bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req), + rxf_cb_cam_fltr_mbox_cmd, rxf); + + bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe); +} + +static int +rxf_process_packet_filter_mcast(struct bna_rxf *rxf) +{ + struct bna_mac *mac = NULL; + struct list_head *qe; + + /* Add multicast entries */ + if (!list_empty(&rxf->mcast_pending_add_q)) { + bfa_q_deq(&rxf->mcast_pending_add_q, &qe); + bfa_q_qe_init(qe); + mac = (struct bna_mac *)qe; + rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_ADD_REQ, mac); + list_add_tail(&mac->qe, &rxf->mcast_active_q); + return 1; + } + + /* Delete multicast entries previousely added */ + if (!list_empty(&rxf->mcast_pending_del_q)) { + bfa_q_deq(&rxf->mcast_pending_del_q, &qe); + bfa_q_qe_init(qe); + mac = (struct bna_mac *)qe; + rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac); + bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac); + return 1; + } + + return 0; +} + +static int +rxf_process_packet_filter_vlan(struct bna_rxf *rxf) +{ + /* Apply the VLAN filter */ + if (rxf->rxf_flags & BNA_RXF_FL_VLAN_CONFIG_PENDING) { + rxf->rxf_flags &= ~BNA_RXF_FL_VLAN_CONFIG_PENDING; + if (!(rxf->rxmode_active & BNA_RXMODE_PROMISC) && + !(rxf->rxmode_active & BNA_RXMODE_DEFAULT)) + __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status); + } + + /* Apply RSS configuration */ + if (rxf->rxf_flags & BNA_RXF_FL_RSS_CONFIG_PENDING) { + rxf->rxf_flags &= ~BNA_RXF_FL_RSS_CONFIG_PENDING; + if (rxf->rss_status == BNA_STATUS_T_DISABLED) { + /* RSS is being disabled */ + rxf->ctrl_flags &= ~BNA_RXF_CF_RSS_ENABLE; + __rxf_rit_set(rxf); + __rxf_config_set(rxf); + } else { + /* RSS is being enabled or reconfigured */ + rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE; + __rxf_rit_set(rxf); + __rxf_config_set(rxf); + } + } + + return 0; +} + +/** + * Processes pending ucast, mcast entry addition/deletion and issues mailbox + * command. Also processes pending filter configuration - promiscuous mode, + * default mode, allmutli mode and issues mailbox command or directly applies + * to h/w + */ +static int +rxf_process_packet_filter(struct bna_rxf *rxf) +{ + /* Set the default MAC first */ + if (rxf->ucast_pending_set > 0) { + rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_SET_REQ, + rxf->ucast_active_mac); + rxf->ucast_pending_set--; + return 1; + } + + if (rxf_process_packet_filter_ucast(rxf)) + return 1; + + if (rxf_process_packet_filter_mcast(rxf)) + return 1; + + if (rxf_process_packet_filter_promisc(rxf)) + return 1; + + if (rxf_process_packet_filter_default(rxf)) + return 1; + + if (rxf_process_packet_filter_allmulti(rxf)) + return 1; + + if (rxf_process_packet_filter_vlan(rxf)) + return 1; + + return 0; +} + +static int +rxf_clear_packet_filter_mcast(struct bna_rxf *rxf) +{ + struct bna_mac *mac = NULL; + struct list_head *qe; + + /* 3. delete pending mcast entries */ + if (!list_empty(&rxf->mcast_pending_del_q)) { + bfa_q_deq(&rxf->mcast_pending_del_q, &qe); + bfa_q_qe_init(qe); + mac = (struct bna_mac *)qe; + rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac); + bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac); + return 1; + } + + /* 4. clear active mcast entries; move them to pending_add_q */ + if (!list_empty(&rxf->mcast_active_q)) { + bfa_q_deq(&rxf->mcast_active_q, &qe); + bfa_q_qe_init(qe); + mac = (struct bna_mac *)qe; + rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac); + list_add_tail(&mac->qe, &rxf->mcast_pending_add_q); + return 1; + } + + return 0; +} + +/** + * In the rxf stop path, processes pending ucast/mcast delete queue and issues + * the mailbox command. Moves the active ucast/mcast entries to pending add q, + * so that they are added to CAM again in the rxf start path. Moves the current + * filter settings - promiscuous, default, allmutli - to pending filter + * configuration + */ +static int +rxf_clear_packet_filter(struct bna_rxf *rxf) +{ + if (rxf_clear_packet_filter_ucast(rxf)) + return 1; + + if (rxf_clear_packet_filter_mcast(rxf)) + return 1; + + /* 5. clear active default MAC in the CAM */ + if (rxf->ucast_pending_set > 0) + rxf->ucast_pending_set = 0; + + if (rxf_clear_packet_filter_promisc(rxf)) + return 1; + + if (rxf_clear_packet_filter_default(rxf)) + return 1; + + if (rxf_clear_packet_filter_allmulti(rxf)) + return 1; + + return 0; +} + +static void +rxf_reset_packet_filter_mcast(struct bna_rxf *rxf) +{ + struct list_head *qe; + struct bna_mac *mac; + + /* 3. Move active mcast entries to pending_add_q */ + while (!list_empty(&rxf->mcast_active_q)) { + bfa_q_deq(&rxf->mcast_active_q, &qe); + bfa_q_qe_init(qe); + list_add_tail(qe, &rxf->mcast_pending_add_q); + } + + /* 4. Throw away delete pending mcast entries */ + while (!list_empty(&rxf->mcast_pending_del_q)) { + bfa_q_deq(&rxf->mcast_pending_del_q, &qe); + bfa_q_qe_init(qe); + mac = (struct bna_mac *)qe; + bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac); + } +} + +/** + * In the rxf fail path, throws away the ucast/mcast entries pending for + * deletion, moves all active ucast/mcast entries to pending queue so that + * they are added back to CAM in the rxf start path. Also moves the current + * filter configuration to pending filter configuration. + */ +static void +rxf_reset_packet_filter(struct bna_rxf *rxf) +{ + rxf_reset_packet_filter_ucast(rxf); + + rxf_reset_packet_filter_mcast(rxf); + + /* 5. Turn off ucast set flag */ + rxf->ucast_pending_set = 0; + + rxf_reset_packet_filter_promisc(rxf); + + rxf_reset_packet_filter_default(rxf); + + rxf_reset_packet_filter_allmulti(rxf); +} + +void +bna_rxf_init(struct bna_rxf *rxf, + struct bna_rx *rx, + struct bna_rx_config *q_config) +{ + struct list_head *qe; + struct bna_rxp *rxp; + + /* rxf_id is initialized during rx_mod init */ + rxf->rx = rx; + + INIT_LIST_HEAD(&rxf->ucast_pending_add_q); + INIT_LIST_HEAD(&rxf->ucast_pending_del_q); + rxf->ucast_pending_set = 0; + INIT_LIST_HEAD(&rxf->ucast_active_q); + rxf->ucast_active_mac = NULL; + + INIT_LIST_HEAD(&rxf->mcast_pending_add_q); + INIT_LIST_HEAD(&rxf->mcast_pending_del_q); + INIT_LIST_HEAD(&rxf->mcast_active_q); + + bfa_q_qe_init(&rxf->mbox_qe.qe); + + if (q_config->vlan_strip_status == BNA_STATUS_T_ENABLED) + rxf->ctrl_flags |= BNA_RXF_CF_VLAN_STRIP; + + rxf->rxf_oper_state = (q_config->paused) ? + BNA_RXF_OPER_STATE_PAUSED : BNA_RXF_OPER_STATE_RUNNING; + + bna_rxf_adv_init(rxf, rx, q_config); + + rxf->rit_segment = bna_rit_mod_seg_get(&rxf->rx->bna->rit_mod, + q_config->num_paths); + + list_for_each(qe, &rx->rxp_q) { + rxp = (struct bna_rxp *)qe; + if (q_config->rxp_type == BNA_RXP_SINGLE) + rxf->mcast_rxq_id = rxp->rxq.single.only->rxq_id; + else + rxf->mcast_rxq_id = rxp->rxq.slr.large->rxq_id; + break; + } + + rxf->vlan_filter_status = BNA_STATUS_T_DISABLED; + memset(rxf->vlan_filter_table, 0, + (sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32))); + + bfa_fsm_set_state(rxf, bna_rxf_sm_stopped); +} + +void +bna_rxf_uninit(struct bna_rxf *rxf) +{ + struct bna_mac *mac; + + bna_rit_mod_seg_put(&rxf->rx->bna->rit_mod, rxf->rit_segment); + rxf->rit_segment = NULL; + + rxf->ucast_pending_set = 0; + + while (!list_empty(&rxf->ucast_pending_add_q)) { + bfa_q_deq(&rxf->ucast_pending_add_q, &mac); + bfa_q_qe_init(&mac->qe); + bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac); + } + + if (rxf->ucast_active_mac) { + bfa_q_qe_init(&rxf->ucast_active_mac->qe); + bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, + rxf->ucast_active_mac); + rxf->ucast_active_mac = NULL; + } + + while (!list_empty(&rxf->mcast_pending_add_q)) { + bfa_q_deq(&rxf->mcast_pending_add_q, &mac); + bfa_q_qe_init(&mac->qe); + bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac); + } + + rxf->rx = NULL; +} + +void +bna_rxf_start(struct bna_rxf *rxf) +{ + rxf->start_cbfn = bna_rx_cb_rxf_started; + rxf->start_cbarg = rxf->rx; + rxf->rxf_flags &= ~BNA_RXF_FL_FAILED; + bfa_fsm_send_event(rxf, RXF_E_START); +} + +void +bna_rxf_stop(struct bna_rxf *rxf) +{ + rxf->stop_cbfn = bna_rx_cb_rxf_stopped; + rxf->stop_cbarg = rxf->rx; + bfa_fsm_send_event(rxf, RXF_E_STOP); +} + +void +bna_rxf_fail(struct bna_rxf *rxf) +{ + rxf->rxf_flags |= BNA_RXF_FL_FAILED; + bfa_fsm_send_event(rxf, RXF_E_FAIL); +} + +int +bna_rxf_state_get(struct bna_rxf *rxf) +{ + return bfa_sm_to_state(rxf_sm_table, rxf->fsm); +} + +enum bna_cb_status +bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)) +{ + struct bna_rxf *rxf = &rx->rxf; + + if (rxf->ucast_active_mac == NULL) { + rxf->ucast_active_mac = + bna_ucam_mod_mac_get(&rxf->rx->bna->ucam_mod); + if (rxf->ucast_active_mac == NULL) + return BNA_CB_UCAST_CAM_FULL; + bfa_q_qe_init(&rxf->ucast_active_mac->qe); + } + + memcpy(rxf->ucast_active_mac->addr, ucmac, ETH_ALEN); + rxf->ucast_pending_set++; + rxf->cam_fltr_cbfn = cbfn; + rxf->cam_fltr_cbarg = rx->bna->bnad; + + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + + return BNA_CB_SUCCESS; +} + +enum bna_cb_status +bna_rx_mcast_add(struct bna_rx *rx, u8 *addr, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)) +{ + struct bna_rxf *rxf = &rx->rxf; + struct list_head *qe; + struct bna_mac *mac; + + /* Check if already added */ + list_for_each(qe, &rxf->mcast_active_q) { + mac = (struct bna_mac *)qe; + if (BNA_MAC_IS_EQUAL(mac->addr, addr)) { + if (cbfn) + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); + return BNA_CB_SUCCESS; + } + } + + /* Check if pending addition */ + list_for_each(qe, &rxf->mcast_pending_add_q) { + mac = (struct bna_mac *)qe; + if (BNA_MAC_IS_EQUAL(mac->addr, addr)) { + if (cbfn) + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); + return BNA_CB_SUCCESS; + } + } + + mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod); + if (mac == NULL) + return BNA_CB_MCAST_LIST_FULL; + bfa_q_qe_init(&mac->qe); + memcpy(mac->addr, addr, ETH_ALEN); + list_add_tail(&mac->qe, &rxf->mcast_pending_add_q); + + rxf->cam_fltr_cbfn = cbfn; + rxf->cam_fltr_cbarg = rx->bna->bnad; + + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + + return BNA_CB_SUCCESS; +} + +enum bna_cb_status +bna_rx_mcast_del(struct bna_rx *rx, u8 *addr, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)) +{ + struct bna_rxf *rxf = &rx->rxf; + struct list_head *qe; + struct bna_mac *mac; + + list_for_each(qe, &rxf->mcast_pending_add_q) { + mac = (struct bna_mac *)qe; + if (BNA_MAC_IS_EQUAL(mac->addr, addr)) { + list_del(qe); + bfa_q_qe_init(qe); + bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac); + if (cbfn) + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); + return BNA_CB_SUCCESS; + } + } + + list_for_each(qe, &rxf->mcast_active_q) { + mac = (struct bna_mac *)qe; + if (BNA_MAC_IS_EQUAL(mac->addr, addr)) { + list_del(qe); + bfa_q_qe_init(qe); + list_add_tail(qe, &rxf->mcast_pending_del_q); + rxf->cam_fltr_cbfn = cbfn; + rxf->cam_fltr_cbarg = rx->bna->bnad; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + return BNA_CB_SUCCESS; + } + } + + return BNA_CB_INVALID_MAC; +} + +enum bna_cb_status +bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist, + void (*cbfn)(struct bnad *, struct bna_rx *, + enum bna_cb_status)) +{ + struct bna_rxf *rxf = &rx->rxf; + struct list_head list_head; + struct list_head *qe; + u8 *mcaddr; + struct bna_mac *mac; + struct bna_mac *mac1; + int skip; + int delete; + int need_hw_config = 0; + int i; + + /* Allocate nodes */ + INIT_LIST_HEAD(&list_head); + for (i = 0, mcaddr = mclist; i < count; i++) { + mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod); + if (mac == NULL) + goto err_return; + bfa_q_qe_init(&mac->qe); + memcpy(mac->addr, mcaddr, ETH_ALEN); + list_add_tail(&mac->qe, &list_head); + + mcaddr += ETH_ALEN; + } + + /* Schedule for addition */ + while (!list_empty(&list_head)) { + bfa_q_deq(&list_head, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + + skip = 0; + + /* Skip if already added */ + list_for_each(qe, &rxf->mcast_active_q) { + mac1 = (struct bna_mac *)qe; + if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) { + bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, + mac); + skip = 1; + break; + } + } + + if (skip) + continue; + + /* Skip if pending addition */ + list_for_each(qe, &rxf->mcast_pending_add_q) { + mac1 = (struct bna_mac *)qe; + if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) { + bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, + mac); + skip = 1; + break; + } + } + + if (skip) + continue; + + need_hw_config = 1; + list_add_tail(&mac->qe, &rxf->mcast_pending_add_q); + } + + /** + * Delete the entries that are in the pending_add_q but not + * in the new list + */ + while (!list_empty(&rxf->mcast_pending_add_q)) { + bfa_q_deq(&rxf->mcast_pending_add_q, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) { + if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) { + delete = 0; + break; + } + mcaddr += ETH_ALEN; + } + if (delete) + bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac); + else + list_add_tail(&mac->qe, &list_head); + } + while (!list_empty(&list_head)) { + bfa_q_deq(&list_head, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + list_add_tail(&mac->qe, &rxf->mcast_pending_add_q); + } + + /** + * Schedule entries for deletion that are in the active_q but not + * in the new list + */ + while (!list_empty(&rxf->mcast_active_q)) { + bfa_q_deq(&rxf->mcast_active_q, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) { + if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) { + delete = 0; + break; + } + mcaddr += ETH_ALEN; + } + if (delete) { + list_add_tail(&mac->qe, &rxf->mcast_pending_del_q); + need_hw_config = 1; + } else { + list_add_tail(&mac->qe, &list_head); + } + } + while (!list_empty(&list_head)) { + bfa_q_deq(&list_head, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + list_add_tail(&mac->qe, &rxf->mcast_active_q); + } + + if (need_hw_config) { + rxf->cam_fltr_cbfn = cbfn; + rxf->cam_fltr_cbarg = rx->bna->bnad; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + } else if (cbfn) + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); + + return BNA_CB_SUCCESS; + +err_return: + while (!list_empty(&list_head)) { + bfa_q_deq(&list_head, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac); + } + + return BNA_CB_MCAST_LIST_FULL; +} + +void +bna_rx_vlan_add(struct bna_rx *rx, int vlan_id) +{ + struct bna_rxf *rxf = &rx->rxf; + int index = (vlan_id >> 5); + int bit = (1 << (vlan_id & 0x1F)); + + rxf->vlan_filter_table[index] |= bit; + if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) { + rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + } +} + +void +bna_rx_vlan_del(struct bna_rx *rx, int vlan_id) +{ + struct bna_rxf *rxf = &rx->rxf; + int index = (vlan_id >> 5); + int bit = (1 << (vlan_id & 0x1F)); + + rxf->vlan_filter_table[index] &= ~bit; + if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) { + rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING; + bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD); + } +} + +/** + * RX + */ +#define RXQ_RCB_INIT(q, rxp, qdepth, bna, _id, unmapq_mem) do { \ + struct bna_doorbell_qset *_qset; \ + unsigned long off; \ + (q)->rcb->producer_index = (q)->rcb->consumer_index = 0; \ + (q)->rcb->q_depth = (qdepth); \ + (q)->rcb->unmap_q = unmapq_mem; \ + (q)->rcb->rxq = (q); \ + (q)->rcb->cq = &(rxp)->cq; \ + (q)->rcb->bnad = (bna)->bnad; \ + _qset = (struct bna_doorbell_qset *)0; \ + off = (unsigned long)&_qset[(q)->rxq_id].rxq[0]; \ + (q)->rcb->q_dbell = off + \ + BNA_GET_DOORBELL_BASE_ADDR((bna)->pcidev.pci_bar_kva); \ + (q)->rcb->id = _id; \ +} while (0) + +#define BNA_GET_RXQS(qcfg) (((qcfg)->rxp_type == BNA_RXP_SINGLE) ? \ + (qcfg)->num_paths : ((qcfg)->num_paths * 2)) + +#define SIZE_TO_PAGES(size) (((size) >> PAGE_SHIFT) + ((((size) &\ + (PAGE_SIZE - 1)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)) + +#define call_rx_stop_callback(rx, status) \ + if ((rx)->stop_cbfn) { \ + (*(rx)->stop_cbfn)((rx)->stop_cbarg, rx, (status)); \ + (rx)->stop_cbfn = NULL; \ + (rx)->stop_cbarg = NULL; \ + } + +/* + * Since rx_enable is synchronous callback, there is no start_cbfn required. + * Instead, we'll call bnad_rx_post(rxp) so that bnad can post the buffers + * for each rxpath. + */ + +#define call_rx_disable_cbfn(rx, status) \ + if ((rx)->disable_cbfn) { \ + (*(rx)->disable_cbfn)((rx)->disable_cbarg, \ + status); \ + (rx)->disable_cbfn = NULL; \ + (rx)->disable_cbarg = NULL; \ + } \ + +#define rxqs_reqd(type, num_rxqs) \ + (((type) == BNA_RXP_SINGLE) ? (num_rxqs) : ((num_rxqs) * 2)) + +#define rx_ib_fail(rx) \ +do { \ + struct bna_rxp *rxp; \ + struct list_head *qe; \ + list_for_each(qe, &(rx)->rxp_q) { \ + rxp = (struct bna_rxp *)qe; \ + bna_ib_fail(rxp->cq.ib); \ + } \ +} while (0) + +static void __bna_multi_rxq_stop(struct bna_rxp *, u32 *); +static void __bna_rxq_start(struct bna_rxq *rxq); +static void __bna_cq_start(struct bna_cq *cq); +static void bna_rit_create(struct bna_rx *rx); +static void bna_rx_cb_multi_rxq_stopped(void *arg, int status); +static void bna_rx_cb_rxq_stopped_all(void *arg); + +bfa_fsm_state_decl(bna_rx, stopped, + struct bna_rx, enum bna_rx_event); +bfa_fsm_state_decl(bna_rx, rxf_start_wait, + struct bna_rx, enum bna_rx_event); +bfa_fsm_state_decl(bna_rx, started, + struct bna_rx, enum bna_rx_event); +bfa_fsm_state_decl(bna_rx, rxf_stop_wait, + struct bna_rx, enum bna_rx_event); +bfa_fsm_state_decl(bna_rx, rxq_stop_wait, + struct bna_rx, enum bna_rx_event); + +static struct bfa_sm_table rx_sm_table[] = { + {BFA_SM(bna_rx_sm_stopped), BNA_RX_STOPPED}, + {BFA_SM(bna_rx_sm_rxf_start_wait), BNA_RX_RXF_START_WAIT}, + {BFA_SM(bna_rx_sm_started), BNA_RX_STARTED}, + {BFA_SM(bna_rx_sm_rxf_stop_wait), BNA_RX_RXF_STOP_WAIT}, + {BFA_SM(bna_rx_sm_rxq_stop_wait), BNA_RX_RXQ_STOP_WAIT}, +}; + +static void bna_rx_sm_stopped_entry(struct bna_rx *rx) +{ + struct bna_rxp *rxp; + struct list_head *qe_rxp; + + list_for_each(qe_rxp, &rx->rxp_q) { + rxp = (struct bna_rxp *)qe_rxp; + rx->rx_cleanup_cbfn(rx->bna->bnad, rxp->cq.ccb); + } + + call_rx_stop_callback(rx, BNA_CB_SUCCESS); +} + +static void bna_rx_sm_stopped(struct bna_rx *rx, + enum bna_rx_event event) +{ + switch (event) { + case RX_E_START: + bfa_fsm_set_state(rx, bna_rx_sm_rxf_start_wait); + break; + case RX_E_STOP: + call_rx_stop_callback(rx, BNA_CB_SUCCESS); + break; + case RX_E_FAIL: + /* no-op */ + break; + default: + bfa_sm_fault(rx->bna, event); + break; + } + +} + +static void bna_rx_sm_rxf_start_wait_entry(struct bna_rx *rx) +{ + struct bna_rxp *rxp; + struct list_head *qe_rxp; + struct bna_rxq *q0 = NULL, *q1 = NULL; + + /* Setup the RIT */ + bna_rit_create(rx); + + list_for_each(qe_rxp, &rx->rxp_q) { + rxp = (struct bna_rxp *)qe_rxp; + bna_ib_start(rxp->cq.ib); + GET_RXQS(rxp, q0, q1); + q0->buffer_size = bna_port_mtu_get(&rx->bna->port); + __bna_rxq_start(q0); + rx->rx_post_cbfn(rx->bna->bnad, q0->rcb); + if (q1) { + __bna_rxq_start(q1); + rx->rx_post_cbfn(rx->bna->bnad, q1->rcb); + } + __bna_cq_start(&rxp->cq); + } + + bna_rxf_start(&rx->rxf); +} + +static void bna_rx_sm_rxf_start_wait(struct bna_rx *rx, + enum bna_rx_event event) +{ + switch (event) { + case RX_E_STOP: + bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait); + break; + case RX_E_FAIL: + bfa_fsm_set_state(rx, bna_rx_sm_stopped); + rx_ib_fail(rx); + bna_rxf_fail(&rx->rxf); + break; + case RX_E_RXF_STARTED: + bfa_fsm_set_state(rx, bna_rx_sm_started); + break; + default: + bfa_sm_fault(rx->bna, event); + break; + } +} + +void +bna_rx_sm_started_entry(struct bna_rx *rx) +{ + struct bna_rxp *rxp; + struct list_head *qe_rxp; + + /* Start IB */ + list_for_each(qe_rxp, &rx->rxp_q) { + rxp = (struct bna_rxp *)qe_rxp; + bna_ib_ack(&rxp->cq.ib->door_bell, 0); + } + + bna_llport_admin_up(&rx->bna->port.llport); +} + +void +bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event) +{ + switch (event) { + case RX_E_FAIL: + bna_llport_admin_down(&rx->bna->port.llport); + bfa_fsm_set_state(rx, bna_rx_sm_stopped); + rx_ib_fail(rx); + bna_rxf_fail(&rx->rxf); + break; + case RX_E_STOP: + bna_llport_admin_down(&rx->bna->port.llport); + bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait); + break; + default: + bfa_sm_fault(rx->bna, event); + break; + } +} + +void +bna_rx_sm_rxf_stop_wait_entry(struct bna_rx *rx) +{ + bna_rxf_stop(&rx->rxf); +} + +void +bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event) +{ + switch (event) { + case RX_E_RXF_STOPPED: + bfa_fsm_set_state(rx, bna_rx_sm_rxq_stop_wait); + break; + case RX_E_RXF_STARTED: + /** + * RxF was in the process of starting up when + * RXF_E_STOP was issued. Ignore this event + */ + break; + case RX_E_FAIL: + bfa_fsm_set_state(rx, bna_rx_sm_stopped); + rx_ib_fail(rx); + bna_rxf_fail(&rx->rxf); + break; + default: + bfa_sm_fault(rx->bna, event); + break; + } + +} + +void +bna_rx_sm_rxq_stop_wait_entry(struct bna_rx *rx) +{ + struct bna_rxp *rxp = NULL; + struct bna_rxq *q0 = NULL; + struct bna_rxq *q1 = NULL; + struct list_head *qe; + u32 rxq_mask[2] = {0, 0}; + + /* Only one call to multi-rxq-stop for all RXPs in this RX */ + bfa_wc_up(&rx->rxq_stop_wc); + list_for_each(qe, &rx->rxp_q) { + rxp = (struct bna_rxp *)qe; + GET_RXQS(rxp, q0, q1); + if (q0->rxq_id < 32) + rxq_mask[0] |= ((u32)1 << q0->rxq_id); + else + rxq_mask[1] |= ((u32)1 << (q0->rxq_id - 32)); + if (q1) { + if (q1->rxq_id < 32) + rxq_mask[0] |= ((u32)1 << q1->rxq_id); + else + rxq_mask[1] |= ((u32) + 1 << (q1->rxq_id - 32)); + } + } + + __bna_multi_rxq_stop(rxp, rxq_mask); +} + +void +bna_rx_sm_rxq_stop_wait(struct bna_rx *rx, enum bna_rx_event event) +{ + struct bna_rxp *rxp = NULL; + struct list_head *qe; + + switch (event) { + case RX_E_RXQ_STOPPED: + list_for_each(qe, &rx->rxp_q) { + rxp = (struct bna_rxp *)qe; + bna_ib_stop(rxp->cq.ib); + } + /* Fall through */ + case RX_E_FAIL: + bfa_fsm_set_state(rx, bna_rx_sm_stopped); + break; + default: + bfa_sm_fault(rx->bna, event); + break; + } +} + +void +__bna_multi_rxq_stop(struct bna_rxp *rxp, u32 * rxq_id_mask) +{ + struct bfi_ll_q_stop_req ll_req; + + bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RXQ_STOP_REQ, 0); + ll_req.q_id_mask[0] = htonl(rxq_id_mask[0]); + ll_req.q_id_mask[1] = htonl(rxq_id_mask[1]); + bna_mbox_qe_fill(&rxp->mbox_qe, &ll_req, sizeof(ll_req), + bna_rx_cb_multi_rxq_stopped, rxp); + bna_mbox_send(rxp->rx->bna, &rxp->mbox_qe); +} + +void +__bna_rxq_start(struct bna_rxq *rxq) +{ + struct bna_rxtx_q_mem *q_mem; + struct bna_rxq_mem rxq_cfg, *rxq_mem; + struct bna_dma_addr cur_q_addr; + /* struct bna_doorbell_qset *qset; */ + struct bna_qpt *qpt; + u32 pg_num; + struct bna *bna = rxq->rx->bna; + void __iomem *base_addr; + unsigned long off; + + qpt = &rxq->qpt; + cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr)); + + rxq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb; + rxq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb; + rxq_cfg.cur_q_entry_lo = cur_q_addr.lsb; + rxq_cfg.cur_q_entry_hi = cur_q_addr.msb; + + rxq_cfg.pg_cnt_n_prd_ptr = ((u32)qpt->page_count << 16) | 0x0; + rxq_cfg.entry_n_pg_size = ((u32)(BFI_RXQ_WI_SIZE >> 2) << 16) | + (qpt->page_size >> 2); + rxq_cfg.sg_n_cq_n_cns_ptr = + ((u32)(rxq->rxp->cq.cq_id & 0xff) << 16) | 0x0; + rxq_cfg.buf_sz_n_q_state = ((u32)rxq->buffer_size << 16) | + BNA_Q_IDLE_STATE; + rxq_cfg.next_qid = 0x0 | (0x3 << 8); + + /* Write the page number register */ + pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num, + HQM_RXTX_Q_RAM_BASE_OFFSET); + writel(pg_num, bna->regs.page_addr); + + /* Write to h/w */ + base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva, + HQM_RXTX_Q_RAM_BASE_OFFSET); + + q_mem = (struct bna_rxtx_q_mem *)0; + rxq_mem = &q_mem[rxq->rxq_id].rxq; + + off = (unsigned long)&rxq_mem->pg_tbl_addr_lo; + writel(htonl(rxq_cfg.pg_tbl_addr_lo), base_addr + off); + + off = (unsigned long)&rxq_mem->pg_tbl_addr_hi; + writel(htonl(rxq_cfg.pg_tbl_addr_hi), base_addr + off); + + off = (unsigned long)&rxq_mem->cur_q_entry_lo; + writel(htonl(rxq_cfg.cur_q_entry_lo), base_addr + off); + + off = (unsigned long)&rxq_mem->cur_q_entry_hi; + writel(htonl(rxq_cfg.cur_q_entry_hi), base_addr + off); + + off = (unsigned long)&rxq_mem->pg_cnt_n_prd_ptr; + writel(rxq_cfg.pg_cnt_n_prd_ptr, base_addr + off); + + off = (unsigned long)&rxq_mem->entry_n_pg_size; + writel(rxq_cfg.entry_n_pg_size, base_addr + off); + + off = (unsigned long)&rxq_mem->sg_n_cq_n_cns_ptr; + writel(rxq_cfg.sg_n_cq_n_cns_ptr, base_addr + off); + + off = (unsigned long)&rxq_mem->buf_sz_n_q_state; + writel(rxq_cfg.buf_sz_n_q_state, base_addr + off); + + off = (unsigned long)&rxq_mem->next_qid; + writel(rxq_cfg.next_qid, base_addr + off); + + rxq->rcb->producer_index = 0; + rxq->rcb->consumer_index = 0; +} + +void +__bna_cq_start(struct bna_cq *cq) +{ + struct bna_cq_mem cq_cfg, *cq_mem; + const struct bna_qpt *qpt; + struct bna_dma_addr cur_q_addr; + u32 pg_num; + struct bna *bna = cq->rx->bna; + void __iomem *base_addr; + unsigned long off; + + qpt = &cq->qpt; + cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr)); + + /* + * Fill out structure, to be subsequently written + * to hardware + */ + cq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb; + cq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb; + cq_cfg.cur_q_entry_lo = cur_q_addr.lsb; + cq_cfg.cur_q_entry_hi = cur_q_addr.msb; + + cq_cfg.pg_cnt_n_prd_ptr = (qpt->page_count << 16) | 0x0; + cq_cfg.entry_n_pg_size = + ((u32)(BFI_CQ_WI_SIZE >> 2) << 16) | (qpt->page_size >> 2); + cq_cfg.int_blk_n_cns_ptr = ((((u32)cq->ib_seg_offset) << 24) | + ((u32)(cq->ib->ib_id & 0xff) << 16) | 0x0); + cq_cfg.q_state = BNA_Q_IDLE_STATE; + + /* Write the page number register */ + pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num, + HQM_CQ_RAM_BASE_OFFSET); + + writel(pg_num, bna->regs.page_addr); + + /* H/W write */ + base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva, + HQM_CQ_RAM_BASE_OFFSET); + + cq_mem = (struct bna_cq_mem *)0; + + off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_lo; + writel(htonl(cq_cfg.pg_tbl_addr_lo), base_addr + off); + + off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_hi; + writel(htonl(cq_cfg.pg_tbl_addr_hi), base_addr + off); + + off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_lo; + writel(htonl(cq_cfg.cur_q_entry_lo), base_addr + off); + + off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_hi; + writel(htonl(cq_cfg.cur_q_entry_hi), base_addr + off); + + off = (unsigned long)&cq_mem[cq->cq_id].pg_cnt_n_prd_ptr; + writel(cq_cfg.pg_cnt_n_prd_ptr, base_addr + off); + + off = (unsigned long)&cq_mem[cq->cq_id].entry_n_pg_size; + writel(cq_cfg.entry_n_pg_size, base_addr + off); + + off = (unsigned long)&cq_mem[cq->cq_id].int_blk_n_cns_ptr; + writel(cq_cfg.int_blk_n_cns_ptr, base_addr + off); + + off = (unsigned long)&cq_mem[cq->cq_id].q_state; + writel(cq_cfg.q_state, base_addr + off); + + cq->ccb->producer_index = 0; + *(cq->ccb->hw_producer_index) = 0; +} + +void +bna_rit_create(struct bna_rx *rx) +{ + struct list_head *qe_rxp; + struct bna *bna; + struct bna_rxp *rxp; + struct bna_rxq *q0 = NULL; + struct bna_rxq *q1 = NULL; + int offset; + + bna = rx->bna; + + offset = 0; + list_for_each(qe_rxp, &rx->rxp_q) { + rxp = (struct bna_rxp *)qe_rxp; + GET_RXQS(rxp, q0, q1); + rx->rxf.rit_segment->rit[offset].large_rxq_id = q0->rxq_id; + rx->rxf.rit_segment->rit[offset].small_rxq_id = + (q1 ? q1->rxq_id : 0); + offset++; + } +} + +int +_rx_can_satisfy(struct bna_rx_mod *rx_mod, + struct bna_rx_config *rx_cfg) +{ + if ((rx_mod->rx_free_count == 0) || + (rx_mod->rxp_free_count == 0) || + (rx_mod->rxq_free_count == 0)) + return 0; + + if (rx_cfg->rxp_type == BNA_RXP_SINGLE) { + if ((rx_mod->rxp_free_count < rx_cfg->num_paths) || + (rx_mod->rxq_free_count < rx_cfg->num_paths)) + return 0; + } else { + if ((rx_mod->rxp_free_count < rx_cfg->num_paths) || + (rx_mod->rxq_free_count < (2 * rx_cfg->num_paths))) + return 0; + } + + if (!bna_rit_mod_can_satisfy(&rx_mod->bna->rit_mod, rx_cfg->num_paths)) + return 0; + + return 1; +} + +struct bna_rxq * +_get_free_rxq(struct bna_rx_mod *rx_mod) +{ + struct bna_rxq *rxq = NULL; + struct list_head *qe = NULL; + + bfa_q_deq(&rx_mod->rxq_free_q, &qe); + if (qe) { + rx_mod->rxq_free_count--; + rxq = (struct bna_rxq *)qe; + } + return rxq; +} + +void +_put_free_rxq(struct bna_rx_mod *rx_mod, struct bna_rxq *rxq) +{ + bfa_q_qe_init(&rxq->qe); + list_add_tail(&rxq->qe, &rx_mod->rxq_free_q); + rx_mod->rxq_free_count++; +} + +struct bna_rxp * +_get_free_rxp(struct bna_rx_mod *rx_mod) +{ + struct list_head *qe = NULL; + struct bna_rxp *rxp = NULL; + + bfa_q_deq(&rx_mod->rxp_free_q, &qe); + if (qe) { + rx_mod->rxp_free_count--; + + rxp = (struct bna_rxp *)qe; + } + + return rxp; +} + +void +_put_free_rxp(struct bna_rx_mod *rx_mod, struct bna_rxp *rxp) +{ + bfa_q_qe_init(&rxp->qe); + list_add_tail(&rxp->qe, &rx_mod->rxp_free_q); + rx_mod->rxp_free_count++; +} + +struct bna_rx * +_get_free_rx(struct bna_rx_mod *rx_mod) +{ + struct list_head *qe = NULL; + struct bna_rx *rx = NULL; + + bfa_q_deq(&rx_mod->rx_free_q, &qe); + if (qe) { + rx_mod->rx_free_count--; + + rx = (struct bna_rx *)qe; + bfa_q_qe_init(qe); + list_add_tail(&rx->qe, &rx_mod->rx_active_q); + } + + return rx; +} + +void +_put_free_rx(struct bna_rx_mod *rx_mod, struct bna_rx *rx) +{ + bfa_q_qe_init(&rx->qe); + list_add_tail(&rx->qe, &rx_mod->rx_free_q); + rx_mod->rx_free_count++; +} + +void +_rx_init(struct bna_rx *rx, struct bna *bna) +{ + rx->bna = bna; + rx->rx_flags = 0; + + INIT_LIST_HEAD(&rx->rxp_q); + + rx->rxq_stop_wc.wc_resume = bna_rx_cb_rxq_stopped_all; + rx->rxq_stop_wc.wc_cbarg = rx; + rx->rxq_stop_wc.wc_count = 0; + + rx->stop_cbfn = NULL; + rx->stop_cbarg = NULL; +} + +void +_rxp_add_rxqs(struct bna_rxp *rxp, + struct bna_rxq *q0, + struct bna_rxq *q1) +{ + switch (rxp->type) { + case BNA_RXP_SINGLE: + rxp->rxq.single.only = q0; + rxp->rxq.single.reserved = NULL; + break; + case BNA_RXP_SLR: + rxp->rxq.slr.large = q0; + rxp->rxq.slr.small = q1; + break; + case BNA_RXP_HDS: + rxp->rxq.hds.data = q0; + rxp->rxq.hds.hdr = q1; + break; + default: + break; + } +} + +void +_rxq_qpt_init(struct bna_rxq *rxq, + struct bna_rxp *rxp, + u32 page_count, + u32 page_size, + struct bna_mem_descr *qpt_mem, + struct bna_mem_descr *swqpt_mem, + struct bna_mem_descr *page_mem) +{ + int i; + + rxq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb; + rxq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb; + rxq->qpt.kv_qpt_ptr = qpt_mem->kva; + rxq->qpt.page_count = page_count; + rxq->qpt.page_size = page_size; + + rxq->rcb->sw_qpt = (void **) swqpt_mem->kva; + + for (i = 0; i < rxq->qpt.page_count; i++) { + rxq->rcb->sw_qpt[i] = page_mem[i].kva; + ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].lsb = + page_mem[i].dma.lsb; + ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].msb = + page_mem[i].dma.msb; + + } +} + +void +_rxp_cqpt_setup(struct bna_rxp *rxp, + u32 page_count, + u32 page_size, + struct bna_mem_descr *qpt_mem, + struct bna_mem_descr *swqpt_mem, + struct bna_mem_descr *page_mem) +{ + int i; + + rxp->cq.qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb; + rxp->cq.qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb; + rxp->cq.qpt.kv_qpt_ptr = qpt_mem->kva; + rxp->cq.qpt.page_count = page_count; + rxp->cq.qpt.page_size = page_size; + + rxp->cq.ccb->sw_qpt = (void **) swqpt_mem->kva; + + for (i = 0; i < rxp->cq.qpt.page_count; i++) { + rxp->cq.ccb->sw_qpt[i] = page_mem[i].kva; + + ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].lsb = + page_mem[i].dma.lsb; + ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].msb = + page_mem[i].dma.msb; + + } +} + +void +_rx_add_rxp(struct bna_rx *rx, struct bna_rxp *rxp) +{ + list_add_tail(&rxp->qe, &rx->rxp_q); +} + +void +_init_rxmod_queues(struct bna_rx_mod *rx_mod) +{ + INIT_LIST_HEAD(&rx_mod->rx_free_q); + INIT_LIST_HEAD(&rx_mod->rxq_free_q); + INIT_LIST_HEAD(&rx_mod->rxp_free_q); + INIT_LIST_HEAD(&rx_mod->rx_active_q); + + rx_mod->rx_free_count = 0; + rx_mod->rxq_free_count = 0; + rx_mod->rxp_free_count = 0; +} + +void +_rx_ctor(struct bna_rx *rx, int id) +{ + bfa_q_qe_init(&rx->qe); + INIT_LIST_HEAD(&rx->rxp_q); + rx->bna = NULL; + + rx->rxf.rxf_id = id; + + /* FIXME: mbox_qe ctor()?? */ + bfa_q_qe_init(&rx->mbox_qe.qe); + + rx->stop_cbfn = NULL; + rx->stop_cbarg = NULL; +} + +void +bna_rx_cb_multi_rxq_stopped(void *arg, int status) +{ + struct bna_rxp *rxp = (struct bna_rxp *)arg; + + bfa_wc_down(&rxp->rx->rxq_stop_wc); +} + +void +bna_rx_cb_rxq_stopped_all(void *arg) +{ + struct bna_rx *rx = (struct bna_rx *)arg; + + bfa_fsm_send_event(rx, RX_E_RXQ_STOPPED); +} + +void +bna_rx_mod_cb_rx_stopped(void *arg, struct bna_rx *rx, + enum bna_cb_status status) +{ + struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg; + + bfa_wc_down(&rx_mod->rx_stop_wc); +} + +void +bna_rx_mod_cb_rx_stopped_all(void *arg) +{ + struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg; + + if (rx_mod->stop_cbfn) + rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS); + rx_mod->stop_cbfn = NULL; +} + +void +bna_rx_start(struct bna_rx *rx) +{ + rx->rx_flags |= BNA_RX_F_PORT_ENABLED; + if (rx->rx_flags & BNA_RX_F_ENABLE) + bfa_fsm_send_event(rx, RX_E_START); +} + +void +bna_rx_stop(struct bna_rx *rx) +{ + rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED; + if (rx->fsm == (bfa_fsm_t) bna_rx_sm_stopped) + bna_rx_mod_cb_rx_stopped(&rx->bna->rx_mod, rx, BNA_CB_SUCCESS); + else { + rx->stop_cbfn = bna_rx_mod_cb_rx_stopped; + rx->stop_cbarg = &rx->bna->rx_mod; + bfa_fsm_send_event(rx, RX_E_STOP); + } +} + +void +bna_rx_fail(struct bna_rx *rx) +{ + /* Indicate port is not enabled, and failed */ + rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED; + rx->rx_flags |= BNA_RX_F_PORT_FAILED; + bfa_fsm_send_event(rx, RX_E_FAIL); +} + +void +bna_rx_cb_rxf_started(struct bna_rx *rx, enum bna_cb_status status) +{ + bfa_fsm_send_event(rx, RX_E_RXF_STARTED); + if (rx->rxf.rxf_id < 32) + rx->bna->rx_mod.rxf_bmap[0] |= ((u32)1 << rx->rxf.rxf_id); + else + rx->bna->rx_mod.rxf_bmap[1] |= ((u32) + 1 << (rx->rxf.rxf_id - 32)); +} + +void +bna_rx_cb_rxf_stopped(struct bna_rx *rx, enum bna_cb_status status) +{ + bfa_fsm_send_event(rx, RX_E_RXF_STOPPED); + if (rx->rxf.rxf_id < 32) + rx->bna->rx_mod.rxf_bmap[0] &= ~(u32)1 << rx->rxf.rxf_id; + else + rx->bna->rx_mod.rxf_bmap[1] &= ~(u32) + 1 << (rx->rxf.rxf_id - 32); +} + +void +bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type) +{ + struct bna_rx *rx; + struct list_head *qe; + + rx_mod->flags |= BNA_RX_MOD_F_PORT_STARTED; + if (type == BNA_RX_T_LOOPBACK) + rx_mod->flags |= BNA_RX_MOD_F_PORT_LOOPBACK; + + list_for_each(qe, &rx_mod->rx_active_q) { + rx = (struct bna_rx *)qe; + if (rx->type == type) + bna_rx_start(rx); + } +} + +void +bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type) +{ + struct bna_rx *rx; + struct list_head *qe; + + rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED; + rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK; + + rx_mod->stop_cbfn = bna_port_cb_rx_stopped; + + /** + * Before calling bna_rx_stop(), increment rx_stop_wc as many times + * as we are going to call bna_rx_stop + */ + list_for_each(qe, &rx_mod->rx_active_q) { + rx = (struct bna_rx *)qe; + if (rx->type == type) + bfa_wc_up(&rx_mod->rx_stop_wc); + } + + if (rx_mod->rx_stop_wc.wc_count == 0) { + rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS); + rx_mod->stop_cbfn = NULL; + return; + } + + list_for_each(qe, &rx_mod->rx_active_q) { + rx = (struct bna_rx *)qe; + if (rx->type == type) + bna_rx_stop(rx); + } +} + +void +bna_rx_mod_fail(struct bna_rx_mod *rx_mod) +{ + struct bna_rx *rx; + struct list_head *qe; + + rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED; + rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK; + + list_for_each(qe, &rx_mod->rx_active_q) { + rx = (struct bna_rx *)qe; + bna_rx_fail(rx); + } +} + +void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna, + struct bna_res_info *res_info) +{ + int index; + struct bna_rx *rx_ptr; + struct bna_rxp *rxp_ptr; + struct bna_rxq *rxq_ptr; + + rx_mod->bna = bna; + rx_mod->flags = 0; + + rx_mod->rx = (struct bna_rx *) + res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mdl[0].kva; + rx_mod->rxp = (struct bna_rxp *) + res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mdl[0].kva; + rx_mod->rxq = (struct bna_rxq *) + res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mdl[0].kva; + + /* Initialize the queues */ + _init_rxmod_queues(rx_mod); + + /* Build RX queues */ + for (index = 0; index < BFI_MAX_RXQ; index++) { + rx_ptr = &rx_mod->rx[index]; + _rx_ctor(rx_ptr, index); + list_add_tail(&rx_ptr->qe, &rx_mod->rx_free_q); + rx_mod->rx_free_count++; + } + + /* build RX-path queue */ + for (index = 0; index < BFI_MAX_RXQ; index++) { + rxp_ptr = &rx_mod->rxp[index]; + rxp_ptr->cq.cq_id = index; + bfa_q_qe_init(&rxp_ptr->qe); + list_add_tail(&rxp_ptr->qe, &rx_mod->rxp_free_q); + rx_mod->rxp_free_count++; + } + + /* build RXQ queue */ + for (index = 0; index < BFI_MAX_RXQ; index++) { + rxq_ptr = &rx_mod->rxq[index]; + rxq_ptr->rxq_id = index; + + bfa_q_qe_init(&rxq_ptr->qe); + list_add_tail(&rxq_ptr->qe, &rx_mod->rxq_free_q); + rx_mod->rxq_free_count++; + } + + rx_mod->rx_stop_wc.wc_resume = bna_rx_mod_cb_rx_stopped_all; + rx_mod->rx_stop_wc.wc_cbarg = rx_mod; + rx_mod->rx_stop_wc.wc_count = 0; +} + +void +bna_rx_mod_uninit(struct bna_rx_mod *rx_mod) +{ + struct list_head *qe; + int i; + + i = 0; + list_for_each(qe, &rx_mod->rx_free_q) + i++; + + i = 0; + list_for_each(qe, &rx_mod->rxp_free_q) + i++; + + i = 0; + list_for_each(qe, &rx_mod->rxq_free_q) + i++; + + rx_mod->bna = NULL; +} + +int +bna_rx_state_get(struct bna_rx *rx) +{ + return bfa_sm_to_state(rx_sm_table, rx->fsm); +} + +void +bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info) +{ + u32 cq_size, hq_size, dq_size; + u32 cpage_count, hpage_count, dpage_count; + struct bna_mem_info *mem_info; + u32 cq_depth; + u32 hq_depth; + u32 dq_depth; + + dq_depth = q_cfg->q_depth; + hq_depth = ((q_cfg->rxp_type == BNA_RXP_SINGLE) ? 0 : q_cfg->q_depth); + cq_depth = dq_depth + hq_depth; + + BNA_TO_POWER_OF_2_HIGH(cq_depth); + cq_size = cq_depth * BFI_CQ_WI_SIZE; + cq_size = ALIGN(cq_size, PAGE_SIZE); + cpage_count = SIZE_TO_PAGES(cq_size); + + BNA_TO_POWER_OF_2_HIGH(dq_depth); + dq_size = dq_depth * BFI_RXQ_WI_SIZE; + dq_size = ALIGN(dq_size, PAGE_SIZE); + dpage_count = SIZE_TO_PAGES(dq_size); + + if (BNA_RXP_SINGLE != q_cfg->rxp_type) { + BNA_TO_POWER_OF_2_HIGH(hq_depth); + hq_size = hq_depth * BFI_RXQ_WI_SIZE; + hq_size = ALIGN(hq_size, PAGE_SIZE); + hpage_count = SIZE_TO_PAGES(hq_size); + } else { + hpage_count = 0; + } + + /* CCB structures */ + res_info[BNA_RX_RES_MEM_T_CCB].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_KVA; + mem_info->len = sizeof(struct bna_ccb); + mem_info->num = q_cfg->num_paths; + + /* RCB structures */ + res_info[BNA_RX_RES_MEM_T_RCB].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_KVA; + mem_info->len = sizeof(struct bna_rcb); + mem_info->num = BNA_GET_RXQS(q_cfg); + + /* Completion QPT */ + res_info[BNA_RX_RES_MEM_T_CQPT].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_DMA; + mem_info->len = cpage_count * sizeof(struct bna_dma_addr); + mem_info->num = q_cfg->num_paths; + + /* Completion s/w QPT */ + res_info[BNA_RX_RES_MEM_T_CSWQPT].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_KVA; + mem_info->len = cpage_count * sizeof(void *); + mem_info->num = q_cfg->num_paths; + + /* Completion QPT pages */ + res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_DMA; + mem_info->len = PAGE_SIZE; + mem_info->num = cpage_count * q_cfg->num_paths; + + /* Data QPTs */ + res_info[BNA_RX_RES_MEM_T_DQPT].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_DMA; + mem_info->len = dpage_count * sizeof(struct bna_dma_addr); + mem_info->num = q_cfg->num_paths; + + /* Data s/w QPTs */ + res_info[BNA_RX_RES_MEM_T_DSWQPT].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_KVA; + mem_info->len = dpage_count * sizeof(void *); + mem_info->num = q_cfg->num_paths; + + /* Data QPT pages */ + res_info[BNA_RX_RES_MEM_T_DPAGE].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_DMA; + mem_info->len = PAGE_SIZE; + mem_info->num = dpage_count * q_cfg->num_paths; + + /* Hdr QPTs */ + res_info[BNA_RX_RES_MEM_T_HQPT].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_DMA; + mem_info->len = hpage_count * sizeof(struct bna_dma_addr); + mem_info->num = (hpage_count ? q_cfg->num_paths : 0); + + /* Hdr s/w QPTs */ + res_info[BNA_RX_RES_MEM_T_HSWQPT].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_KVA; + mem_info->len = hpage_count * sizeof(void *); + mem_info->num = (hpage_count ? q_cfg->num_paths : 0); + + /* Hdr QPT pages */ + res_info[BNA_RX_RES_MEM_T_HPAGE].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_DMA; + mem_info->len = (hpage_count ? PAGE_SIZE : 0); + mem_info->num = (hpage_count ? (hpage_count * q_cfg->num_paths) : 0); + + /* RX Interrupts */ + res_info[BNA_RX_RES_T_INTR].res_type = BNA_RES_T_INTR; + res_info[BNA_RX_RES_T_INTR].res_u.intr_info.intr_type = BNA_INTR_T_MSIX; + res_info[BNA_RX_RES_T_INTR].res_u.intr_info.num = q_cfg->num_paths; +} + +struct bna_rx * +bna_rx_create(struct bna *bna, struct bnad *bnad, + struct bna_rx_config *rx_cfg, + struct bna_rx_event_cbfn *rx_cbfn, + struct bna_res_info *res_info, + void *priv) +{ + struct bna_rx_mod *rx_mod = &bna->rx_mod; + struct bna_rx *rx; + struct bna_rxp *rxp; + struct bna_rxq *q0; + struct bna_rxq *q1; + struct bna_intr_info *intr_info; + u32 page_count; + struct bna_mem_descr *ccb_mem; + struct bna_mem_descr *rcb_mem; + struct bna_mem_descr *unmapq_mem; + struct bna_mem_descr *cqpt_mem; + struct bna_mem_descr *cswqpt_mem; + struct bna_mem_descr *cpage_mem; + struct bna_mem_descr *hqpt_mem; /* Header/Small Q qpt */ + struct bna_mem_descr *dqpt_mem; /* Data/Large Q qpt */ + struct bna_mem_descr *hsqpt_mem; /* s/w qpt for hdr */ + struct bna_mem_descr *dsqpt_mem; /* s/w qpt for data */ + struct bna_mem_descr *hpage_mem; /* hdr page mem */ + struct bna_mem_descr *dpage_mem; /* data page mem */ + int i, cpage_idx = 0, dpage_idx = 0, hpage_idx = 0, ret; + int dpage_count, hpage_count, rcb_idx; + struct bna_ib_config ibcfg; + /* Fail if we don't have enough RXPs, RXQs */ + if (!_rx_can_satisfy(rx_mod, rx_cfg)) + return NULL; + + /* Initialize resource pointers */ + intr_info = &res_info[BNA_RX_RES_T_INTR].res_u.intr_info; + ccb_mem = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info.mdl[0]; + rcb_mem = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info.mdl[0]; + unmapq_mem = &res_info[BNA_RX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[0]; + cqpt_mem = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info.mdl[0]; + cswqpt_mem = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info.mdl[0]; + cpage_mem = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.mdl[0]; + hqpt_mem = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info.mdl[0]; + dqpt_mem = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info.mdl[0]; + hsqpt_mem = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info.mdl[0]; + dsqpt_mem = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info.mdl[0]; + hpage_mem = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.mdl[0]; + dpage_mem = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.mdl[0]; + + /* Compute q depth & page count */ + page_count = res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.num / + rx_cfg->num_paths; + + dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.num / + rx_cfg->num_paths; + + hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.num / + rx_cfg->num_paths; + /* Get RX pointer */ + rx = _get_free_rx(rx_mod); + _rx_init(rx, bna); + rx->priv = priv; + rx->type = rx_cfg->rx_type; + + rx->rcb_setup_cbfn = rx_cbfn->rcb_setup_cbfn; + rx->rcb_destroy_cbfn = rx_cbfn->rcb_destroy_cbfn; + rx->ccb_setup_cbfn = rx_cbfn->ccb_setup_cbfn; + rx->ccb_destroy_cbfn = rx_cbfn->ccb_destroy_cbfn; + /* Following callbacks are mandatory */ + rx->rx_cleanup_cbfn = rx_cbfn->rx_cleanup_cbfn; + rx->rx_post_cbfn = rx_cbfn->rx_post_cbfn; + + if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_STARTED) { + switch (rx->type) { + case BNA_RX_T_REGULAR: + if (!(rx->bna->rx_mod.flags & + BNA_RX_MOD_F_PORT_LOOPBACK)) + rx->rx_flags |= BNA_RX_F_PORT_ENABLED; + break; + case BNA_RX_T_LOOPBACK: + if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_LOOPBACK) + rx->rx_flags |= BNA_RX_F_PORT_ENABLED; + break; + } + } + + for (i = 0, rcb_idx = 0; i < rx_cfg->num_paths; i++) { + rxp = _get_free_rxp(rx_mod); + rxp->type = rx_cfg->rxp_type; + rxp->rx = rx; + rxp->cq.rx = rx; + + /* Get required RXQs, and queue them to rx-path */ + q0 = _get_free_rxq(rx_mod); + if (BNA_RXP_SINGLE == rx_cfg->rxp_type) + q1 = NULL; + else + q1 = _get_free_rxq(rx_mod); + + /* Initialize IB */ + if (1 == intr_info->num) { + rxp->cq.ib = bna_ib_get(&bna->ib_mod, + intr_info->intr_type, + intr_info->idl[0].vector); + rxp->vector = intr_info->idl[0].vector; + } else { + rxp->cq.ib = bna_ib_get(&bna->ib_mod, + intr_info->intr_type, + intr_info->idl[i].vector); + + /* Map the MSI-x vector used for this RXP */ + rxp->vector = intr_info->idl[i].vector; + } + + rxp->cq.ib_seg_offset = bna_ib_reserve_idx(rxp->cq.ib); + + ibcfg.coalescing_timeo = BFI_RX_COALESCING_TIMEO; + ibcfg.interpkt_count = BFI_RX_INTERPKT_COUNT; + ibcfg.interpkt_timeo = BFI_RX_INTERPKT_TIMEO; + ibcfg.ctrl_flags = BFI_IB_CF_INT_ENABLE; + + ret = bna_ib_config(rxp->cq.ib, &ibcfg); + + /* Link rxqs to rxp */ + _rxp_add_rxqs(rxp, q0, q1); + + /* Link rxp to rx */ + _rx_add_rxp(rx, rxp); + + q0->rx = rx; + q0->rxp = rxp; + + /* Initialize RCB for the large / data q */ + q0->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva; + RXQ_RCB_INIT(q0, rxp, rx_cfg->q_depth, bna, 0, + (void *)unmapq_mem[rcb_idx].kva); + rcb_idx++; + (q0)->rx_packets = (q0)->rx_bytes = 0; + (q0)->rx_packets_with_error = (q0)->rxbuf_alloc_failed = 0; + + /* Initialize RXQs */ + _rxq_qpt_init(q0, rxp, dpage_count, PAGE_SIZE, + &dqpt_mem[i], &dsqpt_mem[i], &dpage_mem[dpage_idx]); + q0->rcb->page_idx = dpage_idx; + q0->rcb->page_count = dpage_count; + dpage_idx += dpage_count; + + /* Call bnad to complete rcb setup */ + if (rx->rcb_setup_cbfn) + rx->rcb_setup_cbfn(bnad, q0->rcb); + + if (q1) { + q1->rx = rx; + q1->rxp = rxp; + + q1->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva; + RXQ_RCB_INIT(q1, rxp, rx_cfg->q_depth, bna, 1, + (void *)unmapq_mem[rcb_idx].kva); + rcb_idx++; + (q1)->buffer_size = (rx_cfg)->small_buff_size; + (q1)->rx_packets = (q1)->rx_bytes = 0; + (q1)->rx_packets_with_error = + (q1)->rxbuf_alloc_failed = 0; + + _rxq_qpt_init(q1, rxp, hpage_count, PAGE_SIZE, + &hqpt_mem[i], &hsqpt_mem[i], + &hpage_mem[hpage_idx]); + q1->rcb->page_idx = hpage_idx; + q1->rcb->page_count = hpage_count; + hpage_idx += hpage_count; + + /* Call bnad to complete rcb setup */ + if (rx->rcb_setup_cbfn) + rx->rcb_setup_cbfn(bnad, q1->rcb); + } + /* Setup RXP::CQ */ + rxp->cq.ccb = (struct bna_ccb *) ccb_mem[i].kva; + _rxp_cqpt_setup(rxp, page_count, PAGE_SIZE, + &cqpt_mem[i], &cswqpt_mem[i], &cpage_mem[cpage_idx]); + rxp->cq.ccb->page_idx = cpage_idx; + rxp->cq.ccb->page_count = page_count; + cpage_idx += page_count; + + rxp->cq.ccb->pkt_rate.small_pkt_cnt = 0; + rxp->cq.ccb->pkt_rate.large_pkt_cnt = 0; + + rxp->cq.ccb->producer_index = 0; + rxp->cq.ccb->q_depth = rx_cfg->q_depth + + ((rx_cfg->rxp_type == BNA_RXP_SINGLE) ? + 0 : rx_cfg->q_depth); + rxp->cq.ccb->i_dbell = &rxp->cq.ib->door_bell; + rxp->cq.ccb->rcb[0] = q0->rcb; + if (q1) + rxp->cq.ccb->rcb[1] = q1->rcb; + rxp->cq.ccb->cq = &rxp->cq; + rxp->cq.ccb->bnad = bna->bnad; + rxp->cq.ccb->hw_producer_index = + ((volatile u32 *)rxp->cq.ib->ib_seg_host_addr_kva + + (rxp->cq.ib_seg_offset * BFI_IBIDX_SIZE)); + *(rxp->cq.ccb->hw_producer_index) = 0; + rxp->cq.ccb->intr_type = intr_info->intr_type; + rxp->cq.ccb->intr_vector = (intr_info->num == 1) ? + intr_info->idl[0].vector : + intr_info->idl[i].vector; + rxp->cq.ccb->rx_coalescing_timeo = + rxp->cq.ib->ib_config.coalescing_timeo; + rxp->cq.ccb->id = i; + + /* Call bnad to complete CCB setup */ + if (rx->ccb_setup_cbfn) + rx->ccb_setup_cbfn(bnad, rxp->cq.ccb); + + } /* for each rx-path */ + + bna_rxf_init(&rx->rxf, rx, rx_cfg); + + bfa_fsm_set_state(rx, bna_rx_sm_stopped); + + return rx; +} + +void +bna_rx_destroy(struct bna_rx *rx) +{ + struct bna_rx_mod *rx_mod = &rx->bna->rx_mod; + struct bna_ib_mod *ib_mod = &rx->bna->ib_mod; + struct bna_rxq *q0 = NULL; + struct bna_rxq *q1 = NULL; + struct bna_rxp *rxp; + struct list_head *qe; + + bna_rxf_uninit(&rx->rxf); + + while (!list_empty(&rx->rxp_q)) { + bfa_q_deq(&rx->rxp_q, &rxp); + GET_RXQS(rxp, q0, q1); + /* Callback to bnad for destroying RCB */ + if (rx->rcb_destroy_cbfn) + rx->rcb_destroy_cbfn(rx->bna->bnad, q0->rcb); + q0->rcb = NULL; + q0->rxp = NULL; + q0->rx = NULL; + _put_free_rxq(rx_mod, q0); + if (q1) { + /* Callback to bnad for destroying RCB */ + if (rx->rcb_destroy_cbfn) + rx->rcb_destroy_cbfn(rx->bna->bnad, q1->rcb); + q1->rcb = NULL; + q1->rxp = NULL; + q1->rx = NULL; + _put_free_rxq(rx_mod, q1); + } + rxp->rxq.slr.large = NULL; + rxp->rxq.slr.small = NULL; + if (rxp->cq.ib) { + if (rxp->cq.ib_seg_offset != 0xff) + bna_ib_release_idx(rxp->cq.ib, + rxp->cq.ib_seg_offset); + bna_ib_put(ib_mod, rxp->cq.ib); + rxp->cq.ib = NULL; + } + /* Callback to bnad for destroying CCB */ + if (rx->ccb_destroy_cbfn) + rx->ccb_destroy_cbfn(rx->bna->bnad, rxp->cq.ccb); + rxp->cq.ccb = NULL; + rxp->rx = NULL; + _put_free_rxp(rx_mod, rxp); + } + + list_for_each(qe, &rx_mod->rx_active_q) { + if (qe == &rx->qe) { + list_del(&rx->qe); + bfa_q_qe_init(&rx->qe); + break; + } + } + + rx->bna = NULL; + rx->priv = NULL; + _put_free_rx(rx_mod, rx); +} + +void +bna_rx_enable(struct bna_rx *rx) +{ + if (rx->fsm != (bfa_sm_t)bna_rx_sm_stopped) + return; + + rx->rx_flags |= BNA_RX_F_ENABLE; + if (rx->rx_flags & BNA_RX_F_PORT_ENABLED) + bfa_fsm_send_event(rx, RX_E_START); +} + +void +bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type, + void (*cbfn)(void *, struct bna_rx *, + enum bna_cb_status)) +{ + if (type == BNA_SOFT_CLEANUP) { + /* h/w should not be accessed. Treat we're stopped */ + (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS); + } else { + rx->stop_cbfn = cbfn; + rx->stop_cbarg = rx->bna->bnad; + + rx->rx_flags &= ~BNA_RX_F_ENABLE; + + bfa_fsm_send_event(rx, RX_E_STOP); + } +} + +/** + * TX + */ +#define call_tx_stop_cbfn(tx, status)\ +do {\ + if ((tx)->stop_cbfn)\ + (tx)->stop_cbfn((tx)->stop_cbarg, (tx), status);\ + (tx)->stop_cbfn = NULL;\ + (tx)->stop_cbarg = NULL;\ +} while (0) + +#define call_tx_prio_change_cbfn(tx, status)\ +do {\ + if ((tx)->prio_change_cbfn)\ + (tx)->prio_change_cbfn((tx)->bna->bnad, (tx), status);\ + (tx)->prio_change_cbfn = NULL;\ +} while (0) + +static void bna_tx_mod_cb_tx_stopped(void *tx_mod, struct bna_tx *tx, + enum bna_cb_status status); +static void bna_tx_cb_txq_stopped(void *arg, int status); +static void bna_tx_cb_stats_cleared(void *arg, int status); +static void __bna_tx_stop(struct bna_tx *tx); +static void __bna_tx_start(struct bna_tx *tx); +static void __bna_txf_stat_clr(struct bna_tx *tx); + +enum bna_tx_event { + TX_E_START = 1, + TX_E_STOP = 2, + TX_E_FAIL = 3, + TX_E_TXQ_STOPPED = 4, + TX_E_PRIO_CHANGE = 5, + TX_E_STAT_CLEARED = 6, +}; + +enum bna_tx_state { + BNA_TX_STOPPED = 1, + BNA_TX_STARTED = 2, + BNA_TX_TXQ_STOP_WAIT = 3, + BNA_TX_PRIO_STOP_WAIT = 4, + BNA_TX_STAT_CLR_WAIT = 5, +}; + +bfa_fsm_state_decl(bna_tx, stopped, struct bna_tx, + enum bna_tx_event); +bfa_fsm_state_decl(bna_tx, started, struct bna_tx, + enum bna_tx_event); +bfa_fsm_state_decl(bna_tx, txq_stop_wait, struct bna_tx, + enum bna_tx_event); +bfa_fsm_state_decl(bna_tx, prio_stop_wait, struct bna_tx, + enum bna_tx_event); +bfa_fsm_state_decl(bna_tx, stat_clr_wait, struct bna_tx, + enum bna_tx_event); + +static struct bfa_sm_table tx_sm_table[] = { + {BFA_SM(bna_tx_sm_stopped), BNA_TX_STOPPED}, + {BFA_SM(bna_tx_sm_started), BNA_TX_STARTED}, + {BFA_SM(bna_tx_sm_txq_stop_wait), BNA_TX_TXQ_STOP_WAIT}, + {BFA_SM(bna_tx_sm_prio_stop_wait), BNA_TX_PRIO_STOP_WAIT}, + {BFA_SM(bna_tx_sm_stat_clr_wait), BNA_TX_STAT_CLR_WAIT}, +}; + +static void +bna_tx_sm_stopped_entry(struct bna_tx *tx) +{ + struct bna_txq *txq; + struct list_head *qe; + + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + (tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb); + } + + call_tx_stop_cbfn(tx, BNA_CB_SUCCESS); +} + +static void +bna_tx_sm_stopped(struct bna_tx *tx, enum bna_tx_event event) +{ + switch (event) { + case TX_E_START: + bfa_fsm_set_state(tx, bna_tx_sm_started); + break; + + case TX_E_STOP: + bfa_fsm_set_state(tx, bna_tx_sm_stopped); + break; + + case TX_E_FAIL: + /* No-op */ + break; + + case TX_E_PRIO_CHANGE: + call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS); + break; + + case TX_E_TXQ_STOPPED: + /** + * This event is received due to flushing of mbox when + * device fails + */ + /* No-op */ + break; + + default: + bfa_sm_fault(tx->bna, event); + } +} + +static void +bna_tx_sm_started_entry(struct bna_tx *tx) +{ + struct bna_txq *txq; + struct list_head *qe; + + __bna_tx_start(tx); + + /* Start IB */ + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + bna_ib_ack(&txq->ib->door_bell, 0); + } +} + +static void +bna_tx_sm_started(struct bna_tx *tx, enum bna_tx_event event) +{ + struct bna_txq *txq; + struct list_head *qe; + + switch (event) { + case TX_E_STOP: + bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait); + __bna_tx_stop(tx); + break; + + case TX_E_FAIL: + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + bna_ib_fail(txq->ib); + (tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb); + } + bfa_fsm_set_state(tx, bna_tx_sm_stopped); + break; + + case TX_E_PRIO_CHANGE: + bfa_fsm_set_state(tx, bna_tx_sm_prio_stop_wait); + break; + + default: + bfa_sm_fault(tx->bna, event); + } +} + +static void +bna_tx_sm_txq_stop_wait_entry(struct bna_tx *tx) +{ +} + +static void +bna_tx_sm_txq_stop_wait(struct bna_tx *tx, enum bna_tx_event event) +{ + struct bna_txq *txq; + struct list_head *qe; + + switch (event) { + case TX_E_FAIL: + bfa_fsm_set_state(tx, bna_tx_sm_stopped); + break; + + case TX_E_TXQ_STOPPED: + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + bna_ib_stop(txq->ib); + } + bfa_fsm_set_state(tx, bna_tx_sm_stat_clr_wait); + break; + + case TX_E_PRIO_CHANGE: + /* No-op */ + break; + + default: + bfa_sm_fault(tx->bna, event); + } +} + +static void +bna_tx_sm_prio_stop_wait_entry(struct bna_tx *tx) +{ + __bna_tx_stop(tx); +} + +static void +bna_tx_sm_prio_stop_wait(struct bna_tx *tx, enum bna_tx_event event) +{ + struct bna_txq *txq; + struct list_head *qe; + + switch (event) { + case TX_E_STOP: + bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait); + break; + + case TX_E_FAIL: + call_tx_prio_change_cbfn(tx, BNA_CB_FAIL); + bfa_fsm_set_state(tx, bna_tx_sm_stopped); + break; + + case TX_E_TXQ_STOPPED: + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + bna_ib_stop(txq->ib); + (tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb); + } + call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS); + bfa_fsm_set_state(tx, bna_tx_sm_started); + break; + + case TX_E_PRIO_CHANGE: + /* No-op */ + break; + + default: + bfa_sm_fault(tx->bna, event); + } +} + +static void +bna_tx_sm_stat_clr_wait_entry(struct bna_tx *tx) +{ + __bna_txf_stat_clr(tx); +} + +static void +bna_tx_sm_stat_clr_wait(struct bna_tx *tx, enum bna_tx_event event) +{ + switch (event) { + case TX_E_FAIL: + case TX_E_STAT_CLEARED: + bfa_fsm_set_state(tx, bna_tx_sm_stopped); + break; + + default: + bfa_sm_fault(tx->bna, event); + } +} + +static void +__bna_txq_start(struct bna_tx *tx, struct bna_txq *txq) +{ + struct bna_rxtx_q_mem *q_mem; + struct bna_txq_mem txq_cfg; + struct bna_txq_mem *txq_mem; + struct bna_dma_addr cur_q_addr; + u32 pg_num; + void __iomem *base_addr; + unsigned long off; + + /* Fill out structure, to be subsequently written to hardware */ + txq_cfg.pg_tbl_addr_lo = txq->qpt.hw_qpt_ptr.lsb; + txq_cfg.pg_tbl_addr_hi = txq->qpt.hw_qpt_ptr.msb; + cur_q_addr = *((struct bna_dma_addr *)(txq->qpt.kv_qpt_ptr)); + txq_cfg.cur_q_entry_lo = cur_q_addr.lsb; + txq_cfg.cur_q_entry_hi = cur_q_addr.msb; + + txq_cfg.pg_cnt_n_prd_ptr = (txq->qpt.page_count << 16) | 0x0; + + txq_cfg.entry_n_pg_size = ((u32)(BFI_TXQ_WI_SIZE >> 2) << 16) | + (txq->qpt.page_size >> 2); + txq_cfg.int_blk_n_cns_ptr = ((((u32)txq->ib_seg_offset) << 24) | + ((u32)(txq->ib->ib_id & 0xff) << 16) | 0x0); + + txq_cfg.cns_ptr2_n_q_state = BNA_Q_IDLE_STATE; + txq_cfg.nxt_qid_n_fid_n_pri = (((tx->txf.txf_id & 0x3f) << 3) | + (txq->priority & 0x3)); + txq_cfg.wvc_n_cquota_n_rquota = + ((((u32)BFI_TX_MAX_WRR_QUOTA & 0xfff) << 12) | + (BFI_TX_MAX_WRR_QUOTA & 0xfff)); + + /* Setup the page and write to H/W */ + + pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + tx->bna->port_num, + HQM_RXTX_Q_RAM_BASE_OFFSET); + writel(pg_num, tx->bna->regs.page_addr); + + base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva, + HQM_RXTX_Q_RAM_BASE_OFFSET); + q_mem = (struct bna_rxtx_q_mem *)0; + txq_mem = &q_mem[txq->txq_id].txq; + + /* + * The following 4 lines, is a hack b'cos the H/W needs to read + * these DMA addresses as little endian + */ + + off = (unsigned long)&txq_mem->pg_tbl_addr_lo; + writel(htonl(txq_cfg.pg_tbl_addr_lo), base_addr + off); + + off = (unsigned long)&txq_mem->pg_tbl_addr_hi; + writel(htonl(txq_cfg.pg_tbl_addr_hi), base_addr + off); + + off = (unsigned long)&txq_mem->cur_q_entry_lo; + writel(htonl(txq_cfg.cur_q_entry_lo), base_addr + off); + + off = (unsigned long)&txq_mem->cur_q_entry_hi; + writel(htonl(txq_cfg.cur_q_entry_hi), base_addr + off); + + off = (unsigned long)&txq_mem->pg_cnt_n_prd_ptr; + writel(txq_cfg.pg_cnt_n_prd_ptr, base_addr + off); + + off = (unsigned long)&txq_mem->entry_n_pg_size; + writel(txq_cfg.entry_n_pg_size, base_addr + off); + + off = (unsigned long)&txq_mem->int_blk_n_cns_ptr; + writel(txq_cfg.int_blk_n_cns_ptr, base_addr + off); + + off = (unsigned long)&txq_mem->cns_ptr2_n_q_state; + writel(txq_cfg.cns_ptr2_n_q_state, base_addr + off); + + off = (unsigned long)&txq_mem->nxt_qid_n_fid_n_pri; + writel(txq_cfg.nxt_qid_n_fid_n_pri, base_addr + off); + + off = (unsigned long)&txq_mem->wvc_n_cquota_n_rquota; + writel(txq_cfg.wvc_n_cquota_n_rquota, base_addr + off); + + txq->tcb->producer_index = 0; + txq->tcb->consumer_index = 0; + *(txq->tcb->hw_consumer_index) = 0; + +} + +static void +__bna_txq_stop(struct bna_tx *tx, struct bna_txq *txq) +{ + struct bfi_ll_q_stop_req ll_req; + u32 bit_mask[2] = {0, 0}; + if (txq->txq_id < 32) + bit_mask[0] = (u32)1 << txq->txq_id; + else + bit_mask[1] = (u32)1 << (txq->txq_id - 32); + + memset(&ll_req, 0, sizeof(ll_req)); + ll_req.mh.msg_class = BFI_MC_LL; + ll_req.mh.msg_id = BFI_LL_H2I_TXQ_STOP_REQ; + ll_req.mh.mtag.h2i.lpu_id = 0; + ll_req.q_id_mask[0] = htonl(bit_mask[0]); + ll_req.q_id_mask[1] = htonl(bit_mask[1]); + + bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req), + bna_tx_cb_txq_stopped, tx); + + bna_mbox_send(tx->bna, &tx->mbox_qe); +} + +static void +__bna_txf_start(struct bna_tx *tx) +{ + struct bna_tx_fndb_ram *tx_fndb; + struct bna_txf *txf = &tx->txf; + void __iomem *base_addr; + unsigned long off; + + writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM + + (tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET), + tx->bna->regs.page_addr); + + base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva, + TX_FNDB_RAM_BASE_OFFSET); + + tx_fndb = (struct bna_tx_fndb_ram *)0; + off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags; + + writel(((u32)txf->vlan << 16) | txf->ctrl_flags, + base_addr + off); + + if (tx->txf.txf_id < 32) + tx->bna->tx_mod.txf_bmap[0] |= ((u32)1 << tx->txf.txf_id); + else + tx->bna->tx_mod.txf_bmap[1] |= ((u32) + 1 << (tx->txf.txf_id - 32)); +} + +static void +__bna_txf_stop(struct bna_tx *tx) +{ + struct bna_tx_fndb_ram *tx_fndb; + u32 page_num; + u32 ctl_flags; + struct bna_txf *txf = &tx->txf; + void __iomem *base_addr; + unsigned long off; + + /* retrieve the running txf_flags & turn off enable bit */ + page_num = BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM + + (tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET); + writel(page_num, tx->bna->regs.page_addr); + + base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva, + TX_FNDB_RAM_BASE_OFFSET); + tx_fndb = (struct bna_tx_fndb_ram *)0; + off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags; + + ctl_flags = readl(base_addr + off); + ctl_flags &= ~BFI_TXF_CF_ENABLE; + + writel(ctl_flags, base_addr + off); + + if (tx->txf.txf_id < 32) + tx->bna->tx_mod.txf_bmap[0] &= ~((u32)1 << tx->txf.txf_id); + else + tx->bna->tx_mod.txf_bmap[0] &= ~((u32) + 1 << (tx->txf.txf_id - 32)); +} + +static void +__bna_txf_stat_clr(struct bna_tx *tx) +{ + struct bfi_ll_stats_req ll_req; + u32 txf_bmap[2] = {0, 0}; + if (tx->txf.txf_id < 32) + txf_bmap[0] = ((u32)1 << tx->txf.txf_id); + else + txf_bmap[1] = ((u32)1 << (tx->txf.txf_id - 32)); + bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0); + ll_req.stats_mask = 0; + ll_req.rxf_id_mask[0] = 0; + ll_req.rxf_id_mask[1] = 0; + ll_req.txf_id_mask[0] = htonl(txf_bmap[0]); + ll_req.txf_id_mask[1] = htonl(txf_bmap[1]); + + bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req), + bna_tx_cb_stats_cleared, tx); + bna_mbox_send(tx->bna, &tx->mbox_qe); +} + +static void +__bna_tx_start(struct bna_tx *tx) +{ + struct bna_txq *txq; + struct list_head *qe; + + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + bna_ib_start(txq->ib); + __bna_txq_start(tx, txq); + } + + __bna_txf_start(tx); + + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + txq->tcb->priority = txq->priority; + (tx->tx_resume_cbfn)(tx->bna->bnad, txq->tcb); + } +} + +static void +__bna_tx_stop(struct bna_tx *tx) +{ + struct bna_txq *txq; + struct list_head *qe; + + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + (tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb); + } + + __bna_txf_stop(tx); + + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + bfa_wc_up(&tx->txq_stop_wc); + } + + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + __bna_txq_stop(tx, txq); + } +} + +static void +bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size, + struct bna_mem_descr *qpt_mem, + struct bna_mem_descr *swqpt_mem, + struct bna_mem_descr *page_mem) +{ + int i; + + txq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb; + txq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb; + txq->qpt.kv_qpt_ptr = qpt_mem->kva; + txq->qpt.page_count = page_count; + txq->qpt.page_size = page_size; + + txq->tcb->sw_qpt = (void **) swqpt_mem->kva; + + for (i = 0; i < page_count; i++) { + txq->tcb->sw_qpt[i] = page_mem[i].kva; + + ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].lsb = + page_mem[i].dma.lsb; + ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].msb = + page_mem[i].dma.msb; + + } +} + +static void +bna_tx_free(struct bna_tx *tx) +{ + struct bna_tx_mod *tx_mod = &tx->bna->tx_mod; + struct bna_txq *txq; + struct bna_ib_mod *ib_mod = &tx->bna->ib_mod; + struct list_head *qe; + + while (!list_empty(&tx->txq_q)) { + bfa_q_deq(&tx->txq_q, &txq); + bfa_q_qe_init(&txq->qe); + if (txq->ib) { + if (txq->ib_seg_offset != -1) + bna_ib_release_idx(txq->ib, + txq->ib_seg_offset); + bna_ib_put(ib_mod, txq->ib); + txq->ib = NULL; + } + txq->tcb = NULL; + txq->tx = NULL; + list_add_tail(&txq->qe, &tx_mod->txq_free_q); + } + + list_for_each(qe, &tx_mod->tx_active_q) { + if (qe == &tx->qe) { + list_del(&tx->qe); + bfa_q_qe_init(&tx->qe); + break; + } + } + + tx->bna = NULL; + tx->priv = NULL; + list_add_tail(&tx->qe, &tx_mod->tx_free_q); +} + +static void +bna_tx_cb_txq_stopped(void *arg, int status) +{ + struct bna_tx *tx = (struct bna_tx *)arg; + + bfa_q_qe_init(&tx->mbox_qe.qe); + bfa_wc_down(&tx->txq_stop_wc); +} + +static void +bna_tx_cb_txq_stopped_all(void *arg) +{ + struct bna_tx *tx = (struct bna_tx *)arg; + + bfa_fsm_send_event(tx, TX_E_TXQ_STOPPED); +} + +static void +bna_tx_cb_stats_cleared(void *arg, int status) +{ + struct bna_tx *tx = (struct bna_tx *)arg; + + bfa_q_qe_init(&tx->mbox_qe.qe); + + bfa_fsm_send_event(tx, TX_E_STAT_CLEARED); +} + +static void +bna_tx_start(struct bna_tx *tx) +{ + tx->flags |= BNA_TX_F_PORT_STARTED; + if (tx->flags & BNA_TX_F_ENABLED) + bfa_fsm_send_event(tx, TX_E_START); +} + +static void +bna_tx_stop(struct bna_tx *tx) +{ + tx->stop_cbfn = bna_tx_mod_cb_tx_stopped; + tx->stop_cbarg = &tx->bna->tx_mod; + + tx->flags &= ~BNA_TX_F_PORT_STARTED; + bfa_fsm_send_event(tx, TX_E_STOP); +} + +static void +bna_tx_fail(struct bna_tx *tx) +{ + tx->flags &= ~BNA_TX_F_PORT_STARTED; + bfa_fsm_send_event(tx, TX_E_FAIL); +} + +void +bna_tx_prio_changed(struct bna_tx *tx, int prio) +{ + struct bna_txq *txq; + struct list_head *qe; + + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + txq->priority = prio; + } + + bfa_fsm_send_event(tx, TX_E_PRIO_CHANGE); +} + +static void +bna_tx_cee_link_status(struct bna_tx *tx, int cee_link) +{ + if (cee_link) + tx->flags |= BNA_TX_F_PRIO_LOCK; + else + tx->flags &= ~BNA_TX_F_PRIO_LOCK; +} + +static void +bna_tx_mod_cb_tx_stopped(void *arg, struct bna_tx *tx, + enum bna_cb_status status) +{ + struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg; + + bfa_wc_down(&tx_mod->tx_stop_wc); +} + +static void +bna_tx_mod_cb_tx_stopped_all(void *arg) +{ + struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg; + + if (tx_mod->stop_cbfn) + tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS); + tx_mod->stop_cbfn = NULL; +} + +void +bna_tx_res_req(int num_txq, int txq_depth, struct bna_res_info *res_info) +{ + u32 q_size; + u32 page_count; + struct bna_mem_info *mem_info; + + res_info[BNA_TX_RES_MEM_T_TCB].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_KVA; + mem_info->len = sizeof(struct bna_tcb); + mem_info->num = num_txq; + + q_size = txq_depth * BFI_TXQ_WI_SIZE; + q_size = ALIGN(q_size, PAGE_SIZE); + page_count = q_size >> PAGE_SHIFT; + + res_info[BNA_TX_RES_MEM_T_QPT].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_DMA; + mem_info->len = page_count * sizeof(struct bna_dma_addr); + mem_info->num = num_txq; + + res_info[BNA_TX_RES_MEM_T_SWQPT].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_KVA; + mem_info->len = page_count * sizeof(void *); + mem_info->num = num_txq; + + res_info[BNA_TX_RES_MEM_T_PAGE].res_type = BNA_RES_T_MEM; + mem_info = &res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info; + mem_info->mem_type = BNA_MEM_T_DMA; + mem_info->len = PAGE_SIZE; + mem_info->num = num_txq * page_count; + + res_info[BNA_TX_RES_INTR_T_TXCMPL].res_type = BNA_RES_T_INTR; + res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.intr_type = + BNA_INTR_T_MSIX; + res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.num = num_txq; +} + +struct bna_tx * +bna_tx_create(struct bna *bna, struct bnad *bnad, + struct bna_tx_config *tx_cfg, + struct bna_tx_event_cbfn *tx_cbfn, + struct bna_res_info *res_info, void *priv) +{ + struct bna_intr_info *intr_info; + struct bna_tx_mod *tx_mod = &bna->tx_mod; + struct bna_tx *tx; + struct bna_txq *txq; + struct list_head *qe; + struct bna_ib_mod *ib_mod = &bna->ib_mod; + struct bna_doorbell_qset *qset; + struct bna_ib_config ib_config; + int page_count; + int page_size; + int page_idx; + int i; + unsigned long off; + + intr_info = &res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info; + page_count = (res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.num) / + tx_cfg->num_txq; + page_size = res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.len; + + /** + * Get resources + */ + + if ((intr_info->num != 1) && (intr_info->num != tx_cfg->num_txq)) + return NULL; + + /* Tx */ + + if (list_empty(&tx_mod->tx_free_q)) + return NULL; + bfa_q_deq(&tx_mod->tx_free_q, &tx); + bfa_q_qe_init(&tx->qe); + + /* TxQs */ + + INIT_LIST_HEAD(&tx->txq_q); + for (i = 0; i < tx_cfg->num_txq; i++) { + if (list_empty(&tx_mod->txq_free_q)) + goto err_return; + + bfa_q_deq(&tx_mod->txq_free_q, &txq); + bfa_q_qe_init(&txq->qe); + list_add_tail(&txq->qe, &tx->txq_q); + txq->ib = NULL; + txq->ib_seg_offset = -1; + txq->tx = tx; + } + + /* IBs */ + i = 0; + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + + if (intr_info->num == 1) + txq->ib = bna_ib_get(ib_mod, intr_info->intr_type, + intr_info->idl[0].vector); + else + txq->ib = bna_ib_get(ib_mod, intr_info->intr_type, + intr_info->idl[i].vector); + + if (txq->ib == NULL) + goto err_return; + + txq->ib_seg_offset = bna_ib_reserve_idx(txq->ib); + if (txq->ib_seg_offset == -1) + goto err_return; + + i++; + } + + /* + * Initialize + */ + + /* Tx */ + + tx->tcb_setup_cbfn = tx_cbfn->tcb_setup_cbfn; + tx->tcb_destroy_cbfn = tx_cbfn->tcb_destroy_cbfn; + /* Following callbacks are mandatory */ + tx->tx_stall_cbfn = tx_cbfn->tx_stall_cbfn; + tx->tx_resume_cbfn = tx_cbfn->tx_resume_cbfn; + tx->tx_cleanup_cbfn = tx_cbfn->tx_cleanup_cbfn; + + list_add_tail(&tx->qe, &tx_mod->tx_active_q); + tx->bna = bna; + tx->priv = priv; + tx->txq_stop_wc.wc_resume = bna_tx_cb_txq_stopped_all; + tx->txq_stop_wc.wc_cbarg = tx; + tx->txq_stop_wc.wc_count = 0; + + tx->type = tx_cfg->tx_type; + + tx->flags = 0; + if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_STARTED) { + switch (tx->type) { + case BNA_TX_T_REGULAR: + if (!(tx->bna->tx_mod.flags & + BNA_TX_MOD_F_PORT_LOOPBACK)) + tx->flags |= BNA_TX_F_PORT_STARTED; + break; + case BNA_TX_T_LOOPBACK: + if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_LOOPBACK) + tx->flags |= BNA_TX_F_PORT_STARTED; + break; + } + } + if (tx->bna->tx_mod.cee_link) + tx->flags |= BNA_TX_F_PRIO_LOCK; + + /* TxQ */ + + i = 0; + page_idx = 0; + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + txq->priority = tx_mod->priority; + txq->tcb = (struct bna_tcb *) + res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info.mdl[i].kva; + txq->tx_packets = 0; + txq->tx_bytes = 0; + + /* IB */ + + ib_config.coalescing_timeo = BFI_TX_COALESCING_TIMEO; + ib_config.interpkt_timeo = 0; /* Not used */ + ib_config.interpkt_count = BFI_TX_INTERPKT_COUNT; + ib_config.ctrl_flags = (BFI_IB_CF_INTER_PKT_DMA | + BFI_IB_CF_INT_ENABLE | + BFI_IB_CF_COALESCING_MODE); + bna_ib_config(txq->ib, &ib_config); + + /* TCB */ + + txq->tcb->producer_index = 0; + txq->tcb->consumer_index = 0; + txq->tcb->hw_consumer_index = (volatile u32 *) + ((volatile u8 *)txq->ib->ib_seg_host_addr_kva + + (txq->ib_seg_offset * BFI_IBIDX_SIZE)); + *(txq->tcb->hw_consumer_index) = 0; + txq->tcb->q_depth = tx_cfg->txq_depth; + txq->tcb->unmap_q = (void *) + res_info[BNA_TX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[i].kva; + qset = (struct bna_doorbell_qset *)0; + off = (unsigned long)&qset[txq->txq_id].txq[0]; + txq->tcb->q_dbell = off + + BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva); + txq->tcb->i_dbell = &txq->ib->door_bell; + txq->tcb->intr_type = intr_info->intr_type; + txq->tcb->intr_vector = (intr_info->num == 1) ? + intr_info->idl[0].vector : + intr_info->idl[i].vector; + txq->tcb->txq = txq; + txq->tcb->bnad = bnad; + txq->tcb->id = i; + + /* QPT, SWQPT, Pages */ + bna_txq_qpt_setup(txq, page_count, page_size, + &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info.mdl[i], + &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info.mdl[i], + &res_info[BNA_TX_RES_MEM_T_PAGE]. + res_u.mem_info.mdl[page_idx]); + txq->tcb->page_idx = page_idx; + txq->tcb->page_count = page_count; + page_idx += page_count; + + /* Callback to bnad for setting up TCB */ + if (tx->tcb_setup_cbfn) + (tx->tcb_setup_cbfn)(bna->bnad, txq->tcb); + + i++; + } + + /* TxF */ + + tx->txf.ctrl_flags = BFI_TXF_CF_ENABLE | BFI_TXF_CF_VLAN_WI_BASED; + tx->txf.vlan = 0; + + /* Mbox element */ + bfa_q_qe_init(&tx->mbox_qe.qe); + + bfa_fsm_set_state(tx, bna_tx_sm_stopped); + + return tx; + +err_return: + bna_tx_free(tx); + return NULL; +} + +void +bna_tx_destroy(struct bna_tx *tx) +{ + /* Callback to bnad for destroying TCB */ + if (tx->tcb_destroy_cbfn) { + struct bna_txq *txq; + struct list_head *qe; + + list_for_each(qe, &tx->txq_q) { + txq = (struct bna_txq *)qe; + (tx->tcb_destroy_cbfn)(tx->bna->bnad, txq->tcb); + } + } + + bna_tx_free(tx); +} + +void +bna_tx_enable(struct bna_tx *tx) +{ + if (tx->fsm != (bfa_sm_t)bna_tx_sm_stopped) + return; + + tx->flags |= BNA_TX_F_ENABLED; + + if (tx->flags & BNA_TX_F_PORT_STARTED) + bfa_fsm_send_event(tx, TX_E_START); +} + +void +bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type, + void (*cbfn)(void *, struct bna_tx *, enum bna_cb_status)) +{ + if (type == BNA_SOFT_CLEANUP) { + (*cbfn)(tx->bna->bnad, tx, BNA_CB_SUCCESS); + return; + } + + tx->stop_cbfn = cbfn; + tx->stop_cbarg = tx->bna->bnad; + + tx->flags &= ~BNA_TX_F_ENABLED; + + bfa_fsm_send_event(tx, TX_E_STOP); +} + +int +bna_tx_state_get(struct bna_tx *tx) +{ + return bfa_sm_to_state(tx_sm_table, tx->fsm); +} + +void +bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna, + struct bna_res_info *res_info) +{ + int i; + + tx_mod->bna = bna; + tx_mod->flags = 0; + + tx_mod->tx = (struct bna_tx *) + res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mdl[0].kva; + tx_mod->txq = (struct bna_txq *) + res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mdl[0].kva; + + INIT_LIST_HEAD(&tx_mod->tx_free_q); + INIT_LIST_HEAD(&tx_mod->tx_active_q); + + INIT_LIST_HEAD(&tx_mod->txq_free_q); + + for (i = 0; i < BFI_MAX_TXQ; i++) { + tx_mod->tx[i].txf.txf_id = i; + bfa_q_qe_init(&tx_mod->tx[i].qe); + list_add_tail(&tx_mod->tx[i].qe, &tx_mod->tx_free_q); + + tx_mod->txq[i].txq_id = i; + bfa_q_qe_init(&tx_mod->txq[i].qe); + list_add_tail(&tx_mod->txq[i].qe, &tx_mod->txq_free_q); + } + + tx_mod->tx_stop_wc.wc_resume = bna_tx_mod_cb_tx_stopped_all; + tx_mod->tx_stop_wc.wc_cbarg = tx_mod; + tx_mod->tx_stop_wc.wc_count = 0; +} + +void +bna_tx_mod_uninit(struct bna_tx_mod *tx_mod) +{ + struct list_head *qe; + int i; + + i = 0; + list_for_each(qe, &tx_mod->tx_free_q) + i++; + + i = 0; + list_for_each(qe, &tx_mod->txq_free_q) + i++; + + tx_mod->bna = NULL; +} + +void +bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type) +{ + struct bna_tx *tx; + struct list_head *qe; + + tx_mod->flags |= BNA_TX_MOD_F_PORT_STARTED; + if (type == BNA_TX_T_LOOPBACK) + tx_mod->flags |= BNA_TX_MOD_F_PORT_LOOPBACK; + + list_for_each(qe, &tx_mod->tx_active_q) { + tx = (struct bna_tx *)qe; + if (tx->type == type) + bna_tx_start(tx); + } +} + +void +bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type) +{ + struct bna_tx *tx; + struct list_head *qe; + + tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED; + tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK; + + tx_mod->stop_cbfn = bna_port_cb_tx_stopped; + + /** + * Before calling bna_tx_stop(), increment tx_stop_wc as many times + * as we are going to call bna_tx_stop + */ + list_for_each(qe, &tx_mod->tx_active_q) { + tx = (struct bna_tx *)qe; + if (tx->type == type) + bfa_wc_up(&tx_mod->tx_stop_wc); + } + + if (tx_mod->tx_stop_wc.wc_count == 0) { + tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS); + tx_mod->stop_cbfn = NULL; + return; + } + + list_for_each(qe, &tx_mod->tx_active_q) { + tx = (struct bna_tx *)qe; + if (tx->type == type) + bna_tx_stop(tx); + } +} + +void +bna_tx_mod_fail(struct bna_tx_mod *tx_mod) +{ + struct bna_tx *tx; + struct list_head *qe; + + tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED; + tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK; + + list_for_each(qe, &tx_mod->tx_active_q) { + tx = (struct bna_tx *)qe; + bna_tx_fail(tx); + } +} + +void +bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio) +{ + struct bna_tx *tx; + struct list_head *qe; + + if (prio != tx_mod->priority) { + tx_mod->priority = prio; + + list_for_each(qe, &tx_mod->tx_active_q) { + tx = (struct bna_tx *)qe; + bna_tx_prio_changed(tx, prio); + } + } +} + +void +bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link) +{ + struct bna_tx *tx; + struct list_head *qe; + + tx_mod->cee_link = cee_link; + + list_for_each(qe, &tx_mod->tx_active_q) { + tx = (struct bna_tx *)qe; + bna_tx_cee_link_status(tx, cee_link); + } +} diff --git a/drivers/net/bna/bna_types.h b/drivers/net/bna/bna_types.h new file mode 100644 index 000000000000..6877310f6ef4 --- /dev/null +++ b/drivers/net/bna/bna_types.h @@ -0,0 +1,1128 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ +#ifndef __BNA_TYPES_H__ +#define __BNA_TYPES_H__ + +#include "cna.h" +#include "bna_hw.h" +#include "bfa_cee.h" + +/** + * + * Forward declarations + * + */ + +struct bna_txq; +struct bna_tx; +struct bna_rxq; +struct bna_cq; +struct bna_rx; +struct bna_rxf; +struct bna_port; +struct bna; +struct bnad; + +/** + * + * Enums, primitive data types + * + */ + +enum bna_status { + BNA_STATUS_T_DISABLED = 0, + BNA_STATUS_T_ENABLED = 1 +}; + +enum bna_cleanup_type { + BNA_HARD_CLEANUP = 0, + BNA_SOFT_CLEANUP = 1 +}; + +enum bna_cb_status { + BNA_CB_SUCCESS = 0, + BNA_CB_FAIL = 1, + BNA_CB_INTERRUPT = 2, + BNA_CB_BUSY = 3, + BNA_CB_INVALID_MAC = 4, + BNA_CB_MCAST_LIST_FULL = 5, + BNA_CB_UCAST_CAM_FULL = 6, + BNA_CB_WAITING = 7, + BNA_CB_NOT_EXEC = 8 +}; + +enum bna_res_type { + BNA_RES_T_MEM = 1, + BNA_RES_T_INTR = 2 +}; + +enum bna_mem_type { + BNA_MEM_T_KVA = 1, + BNA_MEM_T_DMA = 2 +}; + +enum bna_intr_type { + BNA_INTR_T_INTX = 1, + BNA_INTR_T_MSIX = 2 +}; + +enum bna_res_req_type { + BNA_RES_MEM_T_COM = 0, + BNA_RES_MEM_T_ATTR = 1, + BNA_RES_MEM_T_FWTRC = 2, + BNA_RES_MEM_T_STATS = 3, + BNA_RES_MEM_T_SWSTATS = 4, + BNA_RES_MEM_T_IBIDX = 5, + BNA_RES_MEM_T_IB_ARRAY = 6, + BNA_RES_MEM_T_INTR_ARRAY = 7, + BNA_RES_MEM_T_IDXSEG_ARRAY = 8, + BNA_RES_MEM_T_TX_ARRAY = 9, + BNA_RES_MEM_T_TXQ_ARRAY = 10, + BNA_RES_MEM_T_RX_ARRAY = 11, + BNA_RES_MEM_T_RXP_ARRAY = 12, + BNA_RES_MEM_T_RXQ_ARRAY = 13, + BNA_RES_MEM_T_UCMAC_ARRAY = 14, + BNA_RES_MEM_T_MCMAC_ARRAY = 15, + BNA_RES_MEM_T_RIT_ENTRY = 16, + BNA_RES_MEM_T_RIT_SEGMENT = 17, + BNA_RES_INTR_T_MBOX = 18, + BNA_RES_T_MAX +}; + +enum bna_tx_res_req_type { + BNA_TX_RES_MEM_T_TCB = 0, + BNA_TX_RES_MEM_T_UNMAPQ = 1, + BNA_TX_RES_MEM_T_QPT = 2, + BNA_TX_RES_MEM_T_SWQPT = 3, + BNA_TX_RES_MEM_T_PAGE = 4, + BNA_TX_RES_INTR_T_TXCMPL = 5, + BNA_TX_RES_T_MAX, +}; + +enum bna_rx_mem_type { + BNA_RX_RES_MEM_T_CCB = 0, /* CQ context */ + BNA_RX_RES_MEM_T_RCB = 1, /* CQ context */ + BNA_RX_RES_MEM_T_UNMAPQ = 2, /* UnmapQ for RxQs */ + BNA_RX_RES_MEM_T_CQPT = 3, /* CQ QPT */ + BNA_RX_RES_MEM_T_CSWQPT = 4, /* S/W QPT */ + BNA_RX_RES_MEM_T_CQPT_PAGE = 5, /* CQPT page */ + BNA_RX_RES_MEM_T_HQPT = 6, /* RX QPT */ + BNA_RX_RES_MEM_T_DQPT = 7, /* RX QPT */ + BNA_RX_RES_MEM_T_HSWQPT = 8, /* RX s/w QPT */ + BNA_RX_RES_MEM_T_DSWQPT = 9, /* RX s/w QPT */ + BNA_RX_RES_MEM_T_DPAGE = 10, /* RX s/w QPT */ + BNA_RX_RES_MEM_T_HPAGE = 11, /* RX s/w QPT */ + BNA_RX_RES_T_INTR = 12, /* Rx interrupts */ + BNA_RX_RES_T_MAX = 13 +}; + +enum bna_mbox_state { + BNA_MBOX_FREE = 0, + BNA_MBOX_POSTED = 1 +}; + +enum bna_tx_type { + BNA_TX_T_REGULAR = 0, + BNA_TX_T_LOOPBACK = 1, +}; + +enum bna_tx_flags { + BNA_TX_F_PORT_STARTED = 1, + BNA_TX_F_ENABLED = 2, + BNA_TX_F_PRIO_LOCK = 4, +}; + +enum bna_tx_mod_flags { + BNA_TX_MOD_F_PORT_STARTED = 1, + BNA_TX_MOD_F_PORT_LOOPBACK = 2, +}; + +enum bna_rx_type { + BNA_RX_T_REGULAR = 0, + BNA_RX_T_LOOPBACK = 1, +}; + +enum bna_rxp_type { + BNA_RXP_SINGLE = 1, + BNA_RXP_SLR = 2, + BNA_RXP_HDS = 3 +}; + +enum bna_rxmode { + BNA_RXMODE_PROMISC = 1, + BNA_RXMODE_DEFAULT = 2, + BNA_RXMODE_ALLMULTI = 4 +}; + +enum bna_rx_event { + RX_E_START = 1, + RX_E_STOP = 2, + RX_E_FAIL = 3, + RX_E_RXF_STARTED = 4, + RX_E_RXF_STOPPED = 5, + RX_E_RXQ_STOPPED = 6, +}; + +enum bna_rx_state { + BNA_RX_STOPPED = 1, + BNA_RX_RXF_START_WAIT = 2, + BNA_RX_STARTED = 3, + BNA_RX_RXF_STOP_WAIT = 4, + BNA_RX_RXQ_STOP_WAIT = 5, +}; + +enum bna_rx_flags { + BNA_RX_F_ENABLE = 0x01, /* bnad enabled rxf */ + BNA_RX_F_PORT_ENABLED = 0x02, /* Port object is enabled */ + BNA_RX_F_PORT_FAILED = 0x04, /* Port in failed state */ +}; + +enum bna_rx_mod_flags { + BNA_RX_MOD_F_PORT_STARTED = 1, + BNA_RX_MOD_F_PORT_LOOPBACK = 2, +}; + +enum bna_rxf_oper_state { + BNA_RXF_OPER_STATE_RUNNING = 0x01, /* rxf operational */ + BNA_RXF_OPER_STATE_PAUSED = 0x02, /* rxf in PAUSED state */ +}; + +enum bna_rxf_flags { + BNA_RXF_FL_STOP_PENDING = 0x01, + BNA_RXF_FL_FAILED = 0x02, + BNA_RXF_FL_RSS_CONFIG_PENDING = 0x04, + BNA_RXF_FL_OPERSTATE_CHANGED = 0x08, + BNA_RXF_FL_RXF_ENABLED = 0x10, + BNA_RXF_FL_VLAN_CONFIG_PENDING = 0x20, +}; + +enum bna_rxf_event { + RXF_E_START = 1, + RXF_E_STOP = 2, + RXF_E_FAIL = 3, + RXF_E_CAM_FLTR_MOD = 4, + RXF_E_STARTED = 5, + RXF_E_STOPPED = 6, + RXF_E_CAM_FLTR_RESP = 7, + RXF_E_PAUSE = 8, + RXF_E_RESUME = 9, + RXF_E_STAT_CLEARED = 10, +}; + +enum bna_rxf_state { + BNA_RXF_STOPPED = 1, + BNA_RXF_START_WAIT = 2, + BNA_RXF_CAM_FLTR_MOD_WAIT = 3, + BNA_RXF_STARTED = 4, + BNA_RXF_CAM_FLTR_CLR_WAIT = 5, + BNA_RXF_STOP_WAIT = 6, + BNA_RXF_PAUSE_WAIT = 7, + BNA_RXF_RESUME_WAIT = 8, + BNA_RXF_STAT_CLR_WAIT = 9, +}; + +enum bna_port_type { + BNA_PORT_T_REGULAR = 0, + BNA_PORT_T_LOOPBACK_INTERNAL = 1, + BNA_PORT_T_LOOPBACK_EXTERNAL = 2, +}; + +enum bna_link_status { + BNA_LINK_DOWN = 0, + BNA_LINK_UP = 1, + BNA_CEE_UP = 2 +}; + +enum bna_llport_flags { + BNA_LLPORT_F_ENABLED = 1, + BNA_LLPORT_F_RX_ENABLED = 2 +}; + +enum bna_port_flags { + BNA_PORT_F_DEVICE_READY = 1, + BNA_PORT_F_ENABLED = 2, + BNA_PORT_F_PAUSE_CHANGED = 4, + BNA_PORT_F_MTU_CHANGED = 8 +}; + +enum bna_pkt_rates { + BNA_PKT_RATE_10K = 10000, + BNA_PKT_RATE_20K = 20000, + BNA_PKT_RATE_30K = 30000, + BNA_PKT_RATE_40K = 40000, + BNA_PKT_RATE_50K = 50000, + BNA_PKT_RATE_60K = 60000, + BNA_PKT_RATE_70K = 70000, + BNA_PKT_RATE_80K = 80000, +}; + +enum bna_dim_load_types { + BNA_LOAD_T_HIGH_4 = 0, /* 80K <= r */ + BNA_LOAD_T_HIGH_3 = 1, /* 60K <= r < 80K */ + BNA_LOAD_T_HIGH_2 = 2, /* 50K <= r < 60K */ + BNA_LOAD_T_HIGH_1 = 3, /* 40K <= r < 50K */ + BNA_LOAD_T_LOW_1 = 4, /* 30K <= r < 40K */ + BNA_LOAD_T_LOW_2 = 5, /* 20K <= r < 30K */ + BNA_LOAD_T_LOW_3 = 6, /* 10K <= r < 20K */ + BNA_LOAD_T_LOW_4 = 7, /* r < 10K */ + BNA_LOAD_T_MAX = 8 +}; + +enum bna_dim_bias_types { + BNA_BIAS_T_SMALL = 0, /* small pkts > (large pkts * 2) */ + BNA_BIAS_T_LARGE = 1, /* Not BNA_BIAS_T_SMALL */ + BNA_BIAS_T_MAX = 2 +}; + +struct bna_mac { + /* This should be the first one */ + struct list_head qe; + u8 addr[ETH_ALEN]; +}; + +struct bna_mem_descr { + u32 len; + void *kva; + struct bna_dma_addr dma; +}; + +struct bna_mem_info { + enum bna_mem_type mem_type; + u32 len; + u32 num; + u32 align_sz; /* 0/1 = no alignment */ + struct bna_mem_descr *mdl; + void *cookie; /* For bnad to unmap dma later */ +}; + +struct bna_intr_descr { + int vector; +}; + +struct bna_intr_info { + enum bna_intr_type intr_type; + int num; + struct bna_intr_descr *idl; +}; + +union bna_res_u { + struct bna_mem_info mem_info; + struct bna_intr_info intr_info; +}; + +struct bna_res_info { + enum bna_res_type res_type; + union bna_res_u res_u; +}; + +/* HW QPT */ +struct bna_qpt { + struct bna_dma_addr hw_qpt_ptr; + void *kv_qpt_ptr; + u32 page_count; + u32 page_size; +}; + +/** + * + * Device + * + */ + +struct bna_device { + bfa_fsm_t fsm; + struct bfa_ioc ioc; + + enum bna_intr_type intr_type; + int vector; + + void (*ready_cbfn)(struct bnad *bnad, enum bna_cb_status status); + struct bnad *ready_cbarg; + + void (*stop_cbfn)(struct bnad *bnad, enum bna_cb_status status); + struct bnad *stop_cbarg; + + struct bna *bna; +}; + +/** + * + * Mail box + * + */ + +struct bna_mbox_qe { + /* This should be the first one */ + struct list_head qe; + + struct bfa_mbox_cmd cmd; + u32 cmd_len; + /* Callback for port, tx, rx, rxf */ + void (*cbfn)(void *arg, int status); + void *cbarg; +}; + +struct bna_mbox_mod { + enum bna_mbox_state state; + struct list_head posted_q; + u32 msg_pending; + u32 msg_ctr; + struct bna *bna; +}; + +/** + * + * Port + * + */ + +/* Pause configuration */ +struct bna_pause_config { + enum bna_status tx_pause; + enum bna_status rx_pause; +}; + +struct bna_llport { + bfa_fsm_t fsm; + enum bna_llport_flags flags; + + enum bna_port_type type; + + enum bna_link_status link_status; + + int admin_up_count; + + void (*stop_cbfn)(struct bna_port *, enum bna_cb_status); + + struct bna_mbox_qe mbox_qe; + + struct bna *bna; +}; + +struct bna_port { + bfa_fsm_t fsm; + enum bna_port_flags flags; + + enum bna_port_type type; + + struct bna_llport llport; + + struct bna_pause_config pause_config; + u8 priority; + int mtu; + + /* Callback for bna_port_disable(), port_stop() */ + void (*stop_cbfn)(void *, enum bna_cb_status); + void *stop_cbarg; + + /* Callback for bna_port_pause_config() */ + void (*pause_cbfn)(struct bnad *, enum bna_cb_status); + + /* Callback for bna_port_mtu_set() */ + void (*mtu_cbfn)(struct bnad *, enum bna_cb_status); + + void (*link_cbfn)(struct bnad *, enum bna_link_status); + + struct bfa_wc chld_stop_wc; + + struct bna_mbox_qe mbox_qe; + + struct bna *bna; +}; + +/** + * + * Interrupt Block + * + */ + +/* IB index segment structure */ +struct bna_ibidx_seg { + /* This should be the first one */ + struct list_head qe; + + u8 ib_seg_size; + u8 ib_idx_tbl_offset; +}; + +/* Interrupt structure */ +struct bna_intr { + /* This should be the first one */ + struct list_head qe; + int ref_count; + + enum bna_intr_type intr_type; + int vector; + + struct bna_ib *ib; +}; + +/* Doorbell structure */ +struct bna_ib_dbell { + void *__iomem doorbell_addr; + u32 doorbell_ack; +}; + +/* Interrupt timer configuration */ +struct bna_ib_config { + u8 coalescing_timeo; /* Unit is 5usec. */ + + int interpkt_count; + int interpkt_timeo; + + enum ib_flags ctrl_flags; +}; + +/* IB structure */ +struct bna_ib { + /* This should be the first one */ + struct list_head qe; + + int ib_id; + + int ref_count; + int start_count; + + struct bna_dma_addr ib_seg_host_addr; + void *ib_seg_host_addr_kva; + u32 idx_mask; /* Size >= BNA_IBIDX_MAX_SEGSIZE */ + + struct bna_ibidx_seg *idx_seg; + + struct bna_ib_dbell door_bell; + + struct bna_intr *intr; + + struct bna_ib_config ib_config; + + struct bna *bna; +}; + +/* IB module - keeps track of IBs and interrupts */ +struct bna_ib_mod { + struct bna_ib *ib; /* BFI_MAX_IB entries */ + struct bna_intr *intr; /* BFI_MAX_IB entries */ + struct bna_ibidx_seg *idx_seg; /* BNA_IBIDX_TOTAL_SEGS */ + + struct list_head ib_free_q; + + struct list_head ibidx_seg_pool[BFI_IBIDX_TOTAL_POOLS]; + + struct list_head intr_free_q; + struct list_head intr_active_q; + + struct bna *bna; +}; + +/** + * + * Tx object + * + */ + +/* Tx datapath control structure */ +#define BNA_Q_NAME_SIZE 16 +struct bna_tcb { + /* Fast path */ + void **sw_qpt; + void *unmap_q; + u32 producer_index; + u32 consumer_index; + volatile u32 *hw_consumer_index; + u32 q_depth; + void *__iomem q_dbell; + struct bna_ib_dbell *i_dbell; + int page_idx; + int page_count; + /* Control path */ + struct bna_txq *txq; + struct bnad *bnad; + enum bna_intr_type intr_type; + int intr_vector; + u8 priority; /* Current priority */ + unsigned long flags; /* Used by bnad as required */ + int id; + char name[BNA_Q_NAME_SIZE]; +}; + +/* TxQ QPT and configuration */ +struct bna_txq { + /* This should be the first one */ + struct list_head qe; + + int txq_id; + + u8 priority; + + struct bna_qpt qpt; + struct bna_tcb *tcb; + struct bna_ib *ib; + int ib_seg_offset; + + struct bna_tx *tx; + + u64 tx_packets; + u64 tx_bytes; +}; + +/* TxF structure (hardware Tx Function) */ +struct bna_txf { + int txf_id; + enum txf_flags ctrl_flags; + u16 vlan; +}; + +/* Tx object */ +struct bna_tx { + /* This should be the first one */ + struct list_head qe; + + bfa_fsm_t fsm; + enum bna_tx_flags flags; + + enum bna_tx_type type; + + struct list_head txq_q; + struct bna_txf txf; + + /* Tx event handlers */ + void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *); + void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *); + void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *); + void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *); + void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *); + + /* callback for bna_tx_disable(), bna_tx_stop() */ + void (*stop_cbfn)(void *arg, struct bna_tx *tx, + enum bna_cb_status status); + void *stop_cbarg; + + /* callback for bna_tx_prio_set() */ + void (*prio_change_cbfn)(struct bnad *bnad, struct bna_tx *tx, + enum bna_cb_status status); + + struct bfa_wc txq_stop_wc; + + struct bna_mbox_qe mbox_qe; + + struct bna *bna; + void *priv; /* bnad's cookie */ +}; + +struct bna_tx_config { + int num_txq; + int txq_depth; + enum bna_tx_type tx_type; +}; + +struct bna_tx_event_cbfn { + /* Optional */ + void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *); + void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *); + /* Mandatory */ + void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *); + void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *); + void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *); +}; + +/* Tx module - keeps track of free, active tx objects */ +struct bna_tx_mod { + struct bna_tx *tx; /* BFI_MAX_TXQ entries */ + struct bna_txq *txq; /* BFI_MAX_TXQ entries */ + + struct list_head tx_free_q; + struct list_head tx_active_q; + + struct list_head txq_free_q; + + /* callback for bna_tx_mod_stop() */ + void (*stop_cbfn)(struct bna_port *port, + enum bna_cb_status status); + + struct bfa_wc tx_stop_wc; + + enum bna_tx_mod_flags flags; + + int priority; + int cee_link; + + u32 txf_bmap[2]; + + struct bna *bna; +}; + +/** + * + * Receive Indirection Table + * + */ + +/* One row of RIT table */ +struct bna_rit_entry { + u8 large_rxq_id; /* used for either large or data buffers */ + u8 small_rxq_id; /* used for either small or header buffers */ +}; + +/* RIT segment */ +struct bna_rit_segment { + struct list_head qe; + + u32 rit_offset; + u32 rit_size; + /** + * max_rit_size: Varies per RIT segment depending on how RIT is + * partitioned + */ + u32 max_rit_size; + + struct bna_rit_entry *rit; +}; + +struct bna_rit_mod { + struct bna_rit_entry *rit; + struct bna_rit_segment *rit_segment; + + struct list_head rit_seg_pool[BFI_RIT_SEG_TOTAL_POOLS]; +}; + +/** + * + * Rx object + * + */ + +/* Rx datapath control structure */ +struct bna_rcb { + /* Fast path */ + void **sw_qpt; + void *unmap_q; + u32 producer_index; + u32 consumer_index; + u32 q_depth; + void *__iomem q_dbell; + int page_idx; + int page_count; + /* Control path */ + struct bna_rxq *rxq; + struct bna_cq *cq; + struct bnad *bnad; + unsigned long flags; + int id; +}; + +/* RxQ structure - QPT, configuration */ +struct bna_rxq { + struct list_head qe; + int rxq_id; + + int buffer_size; + int q_depth; + + struct bna_qpt qpt; + struct bna_rcb *rcb; + + struct bna_rxp *rxp; + struct bna_rx *rx; + + u64 rx_packets; + u64 rx_bytes; + u64 rx_packets_with_error; + u64 rxbuf_alloc_failed; +}; + +/* RxQ pair */ +union bna_rxq_u { + struct { + struct bna_rxq *hdr; + struct bna_rxq *data; + } hds; + struct { + struct bna_rxq *small; + struct bna_rxq *large; + } slr; + struct { + struct bna_rxq *only; + struct bna_rxq *reserved; + } single; +}; + +/* Packet rate for Dynamic Interrupt Moderation */ +struct bna_pkt_rate { + u32 small_pkt_cnt; + u32 large_pkt_cnt; +}; + +/* Completion control structure */ +struct bna_ccb { + /* Fast path */ + void **sw_qpt; + u32 producer_index; + volatile u32 *hw_producer_index; + u32 q_depth; + struct bna_ib_dbell *i_dbell; + struct bna_rcb *rcb[2]; + void *ctrl; /* For bnad */ + struct bna_pkt_rate pkt_rate; + int page_idx; + int page_count; + + /* Control path */ + struct bna_cq *cq; + struct bnad *bnad; + enum bna_intr_type intr_type; + int intr_vector; + u8 rx_coalescing_timeo; /* For NAPI */ + int id; + char name[BNA_Q_NAME_SIZE]; +}; + +/* CQ QPT, configuration */ +struct bna_cq { + int cq_id; + + struct bna_qpt qpt; + struct bna_ccb *ccb; + + struct bna_ib *ib; + u8 ib_seg_offset; + + struct bna_rx *rx; +}; + +struct bna_rss_config { + enum rss_hash_type hash_type; + u8 hash_mask; + u32 toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN]; +}; + +struct bna_hds_config { + enum hds_header_type hdr_type; + int header_size; +}; + +/* This structure is used during RX creation */ +struct bna_rx_config { + enum bna_rx_type rx_type; + int num_paths; + enum bna_rxp_type rxp_type; + int paused; + int q_depth; + /* + * Small/Large (or Header/Data) buffer size to be configured + * for SLR and HDS queue type. Large buffer size comes from + * port->mtu. + */ + int small_buff_size; + + enum bna_status rss_status; + struct bna_rss_config rss_config; + + enum bna_status hds_status; + struct bna_hds_config hds_config; + + enum bna_status vlan_strip_status; +}; + +/* Rx Path structure - one per MSIX vector/CPU */ +struct bna_rxp { + /* This should be the first one */ + struct list_head qe; + + enum bna_rxp_type type; + union bna_rxq_u rxq; + struct bna_cq cq; + + struct bna_rx *rx; + + /* MSI-x vector number for configuring RSS */ + int vector; + + struct bna_mbox_qe mbox_qe; +}; + +/* HDS configuration structure */ +struct bna_rxf_hds { + enum hds_header_type hdr_type; + int header_size; +}; + +/* RSS configuration structure */ +struct bna_rxf_rss { + enum rss_hash_type hash_type; + u8 hash_mask; + u32 toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN]; +}; + +/* RxF structure (hardware Rx Function) */ +struct bna_rxf { + bfa_fsm_t fsm; + int rxf_id; + enum rxf_flags ctrl_flags; + u16 default_vlan_tag; + enum bna_rxf_oper_state rxf_oper_state; + enum bna_status hds_status; + struct bna_rxf_hds hds_cfg; + enum bna_status rss_status; + struct bna_rxf_rss rss_cfg; + struct bna_rit_segment *rit_segment; + struct bna_rx *rx; + u32 forced_offset; + struct bna_mbox_qe mbox_qe; + int mcast_rxq_id; + + /* callback for bna_rxf_start() */ + void (*start_cbfn) (struct bna_rx *rx, enum bna_cb_status status); + struct bna_rx *start_cbarg; + + /* callback for bna_rxf_stop() */ + void (*stop_cbfn) (struct bna_rx *rx, enum bna_cb_status status); + struct bna_rx *stop_cbarg; + + /* callback for bna_rxf_receive_enable() / bna_rxf_receive_disable() */ + void (*oper_state_cbfn) (struct bnad *bnad, struct bna_rx *rx, + enum bna_cb_status status); + struct bnad *oper_state_cbarg; + + /** + * callback for: + * bna_rxf_ucast_set() + * bna_rxf_{ucast/mcast}_add(), + * bna_rxf_{ucast/mcast}_del(), + * bna_rxf_mode_set() + */ + void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx, + enum bna_cb_status status); + struct bnad *cam_fltr_cbarg; + + enum bna_rxf_flags rxf_flags; + + /* List of unicast addresses yet to be applied to h/w */ + struct list_head ucast_pending_add_q; + struct list_head ucast_pending_del_q; + int ucast_pending_set; + /* ucast addresses applied to the h/w */ + struct list_head ucast_active_q; + struct bna_mac *ucast_active_mac; + + /* List of multicast addresses yet to be applied to h/w */ + struct list_head mcast_pending_add_q; + struct list_head mcast_pending_del_q; + /* multicast addresses applied to the h/w */ + struct list_head mcast_active_q; + + /* Rx modes yet to be applied to h/w */ + enum bna_rxmode rxmode_pending; + enum bna_rxmode rxmode_pending_bitmask; + /* Rx modes applied to h/w */ + enum bna_rxmode rxmode_active; + + enum bna_status vlan_filter_status; + u32 vlan_filter_table[(BFI_MAX_VLAN + 1) / 32]; +}; + +/* Rx object */ +struct bna_rx { + /* This should be the first one */ + struct list_head qe; + + bfa_fsm_t fsm; + + enum bna_rx_type type; + + /* list-head for RX path objects */ + struct list_head rxp_q; + + struct bna_rxf rxf; + + enum bna_rx_flags rx_flags; + + struct bna_mbox_qe mbox_qe; + + struct bfa_wc rxq_stop_wc; + + /* Rx event handlers */ + void (*rcb_setup_cbfn)(struct bnad *, struct bna_rcb *); + void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *); + void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *); + void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *); + void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *); + void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *); + + /* callback for bna_rx_disable(), bna_rx_stop() */ + void (*stop_cbfn)(void *arg, struct bna_rx *rx, + enum bna_cb_status status); + void *stop_cbarg; + + struct bna *bna; + void *priv; /* bnad's cookie */ +}; + +struct bna_rx_event_cbfn { + /* Optional */ + void (*rcb_setup_cbfn)(struct bnad *, struct bna_rcb *); + void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *); + void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *); + void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *); + /* Mandatory */ + void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *); + void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *); +}; + +/* Rx module - keeps track of free, active rx objects */ +struct bna_rx_mod { + struct bna *bna; /* back pointer to parent */ + struct bna_rx *rx; /* BFI_MAX_RXQ entries */ + struct bna_rxp *rxp; /* BFI_MAX_RXQ entries */ + struct bna_rxq *rxq; /* BFI_MAX_RXQ entries */ + + struct list_head rx_free_q; + struct list_head rx_active_q; + int rx_free_count; + + struct list_head rxp_free_q; + int rxp_free_count; + + struct list_head rxq_free_q; + int rxq_free_count; + + enum bna_rx_mod_flags flags; + + /* callback for bna_rx_mod_stop() */ + void (*stop_cbfn)(struct bna_port *port, + enum bna_cb_status status); + + struct bfa_wc rx_stop_wc; + u32 dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX]; + u32 rxf_bmap[2]; +}; + +/** + * + * CAM + * + */ + +struct bna_ucam_mod { + struct bna_mac *ucmac; /* BFI_MAX_UCMAC entries */ + struct list_head free_q; + + struct bna *bna; +}; + +struct bna_mcam_mod { + struct bna_mac *mcmac; /* BFI_MAX_MCMAC entries */ + struct list_head free_q; + + struct bna *bna; +}; + +/** + * + * Statistics + * + */ + +struct bna_tx_stats { + int tx_state; + int tx_flags; + int num_txqs; + u32 txq_bmap[2]; + int txf_id; +}; + +struct bna_rx_stats { + int rx_state; + int rx_flags; + int num_rxps; + int num_rxqs; + u32 rxq_bmap[2]; + u32 cq_bmap[2]; + int rxf_id; + int rxf_state; + int rxf_oper_state; + int num_active_ucast; + int num_active_mcast; + int rxmode_active; + int vlan_filter_status; + u32 vlan_filter_table[(BFI_MAX_VLAN + 1) / 32]; + int rss_status; + int hds_status; +}; + +struct bna_sw_stats { + int device_state; + int port_state; + int port_flags; + int llport_state; + int priority; + int num_active_tx; + int num_active_rx; + struct bna_tx_stats tx_stats[BFI_MAX_TXQ]; + struct bna_rx_stats rx_stats[BFI_MAX_RXQ]; +}; + +struct bna_stats { + u32 txf_bmap[2]; + u32 rxf_bmap[2]; + struct bfi_ll_stats *hw_stats; + struct bna_sw_stats *sw_stats; +}; + +/** + * + * BNA + * + */ + +struct bna { + struct bfa_pcidev pcidev; + + int port_num; + + struct bna_chip_regs regs; + + struct bna_dma_addr hw_stats_dma; + struct bna_stats stats; + + struct bna_device device; + struct bfa_cee cee; + + struct bna_mbox_mod mbox_mod; + + struct bna_port port; + + struct bna_tx_mod tx_mod; + + struct bna_rx_mod rx_mod; + + struct bna_ib_mod ib_mod; + + struct bna_ucam_mod ucam_mod; + struct bna_mcam_mod mcam_mod; + + struct bna_rit_mod rit_mod; + + int rxf_default_id; + int rxf_promisc_id; + + struct bna_mbox_qe mbox_qe; + + struct bnad *bnad; +}; + +#endif /* __BNA_TYPES_H__ */ diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c new file mode 100644 index 000000000000..491d148f88ae --- /dev/null +++ b/drivers/net/bna/bnad.c @@ -0,0 +1,3270 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bnad.h" +#include "bna.h" +#include "cna.h" + +DEFINE_MUTEX(bnad_fwimg_mutex); + +/* + * Module params + */ +static uint bnad_msix_disable; +module_param(bnad_msix_disable, uint, 0444); +MODULE_PARM_DESC(bnad_msix_disable, "Disable MSIX mode"); + +static uint bnad_ioc_auto_recover = 1; +module_param(bnad_ioc_auto_recover, uint, 0444); +MODULE_PARM_DESC(bnad_ioc_auto_recover, "Enable / Disable auto recovery"); + +/* + * Global variables + */ +u32 bnad_rxqs_per_cq = 2; + +const u8 bnad_bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +/* + * Local MACROS + */ +#define BNAD_TX_UNMAPQ_DEPTH (bnad->txq_depth * 2) + +#define BNAD_RX_UNMAPQ_DEPTH (bnad->rxq_depth) + +#define BNAD_GET_MBOX_IRQ(_bnad) \ + (((_bnad)->cfg_flags & BNAD_CF_MSIX) ? \ + ((_bnad)->msix_table[(_bnad)->msix_num - 1].vector) : \ + ((_bnad)->pcidev->irq)) + +#define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _depth) \ +do { \ + (_res_info)->res_type = BNA_RES_T_MEM; \ + (_res_info)->res_u.mem_info.mem_type = BNA_MEM_T_KVA; \ + (_res_info)->res_u.mem_info.num = (_num); \ + (_res_info)->res_u.mem_info.len = \ + sizeof(struct bnad_unmap_q) + \ + (sizeof(struct bnad_skb_unmap) * ((_depth) - 1)); \ +} while (0) + +/* + * Reinitialize completions in CQ, once Rx is taken down + */ +static void +bnad_cq_cmpl_init(struct bnad *bnad, struct bna_ccb *ccb) +{ + struct bna_cq_entry *cmpl, *next_cmpl; + unsigned int wi_range, wis = 0, ccb_prod = 0; + int i; + + BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt, cmpl, + wi_range); + + for (i = 0; i < ccb->q_depth; i++) { + wis++; + if (likely(--wi_range)) + next_cmpl = cmpl + 1; + else { + BNA_QE_INDX_ADD(ccb_prod, wis, ccb->q_depth); + wis = 0; + BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt, + next_cmpl, wi_range); + } + cmpl->valid = 0; + cmpl = next_cmpl; + } +} + +/* + * Frees all pending Tx Bufs + * At this point no activity is expected on the Q, + * so DMA unmap & freeing is fine. + */ +static void +bnad_free_all_txbufs(struct bnad *bnad, + struct bna_tcb *tcb) +{ + u16 unmap_cons; + struct bnad_unmap_q *unmap_q = tcb->unmap_q; + struct bnad_skb_unmap *unmap_array; + struct sk_buff *skb = NULL; + int i; + + unmap_array = unmap_q->unmap_array; + + unmap_cons = 0; + while (unmap_cons < unmap_q->q_depth) { + skb = unmap_array[unmap_cons].skb; + if (!skb) { + unmap_cons++; + continue; + } + unmap_array[unmap_cons].skb = NULL; + + pci_unmap_single(bnad->pcidev, + pci_unmap_addr(&unmap_array[unmap_cons], + dma_addr), skb_headlen(skb), + PCI_DMA_TODEVICE); + + pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0); + unmap_cons++; + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + pci_unmap_page(bnad->pcidev, + pci_unmap_addr(&unmap_array[unmap_cons], + dma_addr), + skb_shinfo(skb)->frags[i].size, + PCI_DMA_TODEVICE); + pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, + 0); + unmap_cons++; + } + dev_kfree_skb_any(skb); + } +} + +/* Data Path Handlers */ + +/* + * bnad_free_txbufs : Frees the Tx bufs on Tx completion + * Can be called in a) Interrupt context + * b) Sending context + * c) Tasklet context + */ +static u32 +bnad_free_txbufs(struct bnad *bnad, + struct bna_tcb *tcb) +{ + u32 sent_packets = 0, sent_bytes = 0; + u16 wis, unmap_cons, updated_hw_cons; + struct bnad_unmap_q *unmap_q = tcb->unmap_q; + struct bnad_skb_unmap *unmap_array; + struct sk_buff *skb; + int i; + + /* + * Just return if TX is stopped. This check is useful + * when bnad_free_txbufs() runs out of a tasklet scheduled + * before bnad_cb_tx_cleanup() cleared BNAD_RF_TX_STARTED bit + * but this routine runs actually after the cleanup has been + * executed. + */ + if (!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags)) + return 0; + + updated_hw_cons = *(tcb->hw_consumer_index); + + wis = BNA_Q_INDEX_CHANGE(tcb->consumer_index, + updated_hw_cons, tcb->q_depth); + + BUG_ON(!(wis <= BNA_QE_IN_USE_CNT(tcb, tcb->q_depth))); + + unmap_array = unmap_q->unmap_array; + unmap_cons = unmap_q->consumer_index; + + prefetch(&unmap_array[unmap_cons + 1]); + while (wis) { + skb = unmap_array[unmap_cons].skb; + + unmap_array[unmap_cons].skb = NULL; + + sent_packets++; + sent_bytes += skb->len; + wis -= BNA_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags); + + pci_unmap_single(bnad->pcidev, + pci_unmap_addr(&unmap_array[unmap_cons], + dma_addr), skb_headlen(skb), + PCI_DMA_TODEVICE); + pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0); + BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth); + + prefetch(&unmap_array[unmap_cons + 1]); + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + prefetch(&unmap_array[unmap_cons + 1]); + + pci_unmap_page(bnad->pcidev, + pci_unmap_addr(&unmap_array[unmap_cons], + dma_addr), + skb_shinfo(skb)->frags[i].size, + PCI_DMA_TODEVICE); + pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, + 0); + BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth); + } + dev_kfree_skb_any(skb); + } + + /* Update consumer pointers. */ + tcb->consumer_index = updated_hw_cons; + unmap_q->consumer_index = unmap_cons; + + tcb->txq->tx_packets += sent_packets; + tcb->txq->tx_bytes += sent_bytes; + + return sent_packets; +} + +/* Tx Free Tasklet function */ +/* Frees for all the tcb's in all the Tx's */ +/* + * Scheduled from sending context, so that + * the fat Tx lock is not held for too long + * in the sending context. + */ +static void +bnad_tx_free_tasklet(unsigned long bnad_ptr) +{ + struct bnad *bnad = (struct bnad *)bnad_ptr; + struct bna_tcb *tcb; + u32 acked; + int i, j; + + for (i = 0; i < bnad->num_tx; i++) { + for (j = 0; j < bnad->num_txq_per_tx; j++) { + tcb = bnad->tx_info[i].tcb[j]; + if (!tcb) + continue; + if (((u16) (*tcb->hw_consumer_index) != + tcb->consumer_index) && + (!test_and_set_bit(BNAD_TXQ_FREE_SENT, + &tcb->flags))) { + acked = bnad_free_txbufs(bnad, tcb); + bna_ib_ack(tcb->i_dbell, acked); + smp_mb__before_clear_bit(); + clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags); + } + } + } +} + +static u32 +bnad_tx(struct bnad *bnad, struct bna_tcb *tcb) +{ + struct net_device *netdev = bnad->netdev; + u32 sent; + + if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) + return 0; + + sent = bnad_free_txbufs(bnad, tcb); + if (sent) { + if (netif_queue_stopped(netdev) && + netif_carrier_ok(netdev) && + BNA_QE_FREE_CNT(tcb, tcb->q_depth) >= + BNAD_NETIF_WAKE_THRESHOLD) { + netif_wake_queue(netdev); + BNAD_UPDATE_CTR(bnad, netif_queue_wakeup); + } + bna_ib_ack(tcb->i_dbell, sent); + } else + bna_ib_ack(tcb->i_dbell, 0); + + smp_mb__before_clear_bit(); + clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags); + + return sent; +} + +/* MSIX Tx Completion Handler */ +static irqreturn_t +bnad_msix_tx(int irq, void *data) +{ + struct bna_tcb *tcb = (struct bna_tcb *)data; + struct bnad *bnad = tcb->bnad; + + bnad_tx(bnad, tcb); + + return IRQ_HANDLED; +} + +static void +bnad_reset_rcb(struct bnad *bnad, struct bna_rcb *rcb) +{ + struct bnad_unmap_q *unmap_q = rcb->unmap_q; + + rcb->producer_index = 0; + rcb->consumer_index = 0; + + unmap_q->producer_index = 0; + unmap_q->consumer_index = 0; +} + +static void +bnad_free_rxbufs(struct bnad *bnad, struct bna_rcb *rcb) +{ + struct bnad_unmap_q *unmap_q; + struct sk_buff *skb; + + unmap_q = rcb->unmap_q; + while (BNA_QE_IN_USE_CNT(unmap_q, unmap_q->q_depth)) { + skb = unmap_q->unmap_array[unmap_q->consumer_index].skb; + BUG_ON(!(skb)); + unmap_q->unmap_array[unmap_q->consumer_index].skb = NULL; + pci_unmap_single(bnad->pcidev, pci_unmap_addr(&unmap_q-> + unmap_array[unmap_q->consumer_index], + dma_addr), rcb->rxq->buffer_size + + NET_IP_ALIGN, PCI_DMA_FROMDEVICE); + dev_kfree_skb(skb); + BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth); + BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth); + } + + bnad_reset_rcb(bnad, rcb); +} + +static void +bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb) +{ + u16 to_alloc, alloced, unmap_prod, wi_range; + struct bnad_unmap_q *unmap_q = rcb->unmap_q; + struct bnad_skb_unmap *unmap_array; + struct bna_rxq_entry *rxent; + struct sk_buff *skb; + dma_addr_t dma_addr; + + alloced = 0; + to_alloc = + BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth); + + unmap_array = unmap_q->unmap_array; + unmap_prod = unmap_q->producer_index; + + BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent, wi_range); + + while (to_alloc--) { + if (!wi_range) { + BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent, + wi_range); + } + skb = alloc_skb(rcb->rxq->buffer_size + NET_IP_ALIGN, + GFP_ATOMIC); + if (unlikely(!skb)) { + BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed); + goto finishing; + } + skb->dev = bnad->netdev; + skb_reserve(skb, NET_IP_ALIGN); + unmap_array[unmap_prod].skb = skb; + dma_addr = pci_map_single(bnad->pcidev, skb->data, + rcb->rxq->buffer_size, PCI_DMA_FROMDEVICE); + pci_unmap_addr_set(&unmap_array[unmap_prod], dma_addr, + dma_addr); + BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr); + BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth); + + rxent++; + wi_range--; + alloced++; + } + +finishing: + if (likely(alloced)) { + unmap_q->producer_index = unmap_prod; + rcb->producer_index = unmap_prod; + smp_mb(); + bna_rxq_prod_indx_doorbell(rcb); + } +} + +/* + * Locking is required in the enable path + * because it is called from a napi poll + * context, where the bna_lock is not held + * unlike the IRQ context. + */ +static void +bnad_enable_txrx_irqs(struct bnad *bnad) +{ + struct bna_tcb *tcb; + struct bna_ccb *ccb; + int i, j; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + for (i = 0; i < bnad->num_tx; i++) { + for (j = 0; j < bnad->num_txq_per_tx; j++) { + tcb = bnad->tx_info[i].tcb[j]; + bna_ib_coalescing_timer_set(tcb->i_dbell, + tcb->txq->ib->ib_config.coalescing_timeo); + bna_ib_ack(tcb->i_dbell, 0); + } + } + + for (i = 0; i < bnad->num_rx; i++) { + for (j = 0; j < bnad->num_rxp_per_rx; j++) { + ccb = bnad->rx_info[i].rx_ctrl[j].ccb; + bnad_enable_rx_irq_unsafe(ccb); + } + } + spin_unlock_irqrestore(&bnad->bna_lock, flags); +} + +static inline void +bnad_refill_rxq(struct bnad *bnad, struct bna_rcb *rcb) +{ + struct bnad_unmap_q *unmap_q = rcb->unmap_q; + + if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) { + if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth) + >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT) + bnad_alloc_n_post_rxbufs(bnad, rcb); + smp_mb__before_clear_bit(); + clear_bit(BNAD_RXQ_REFILL, &rcb->flags); + } +} + +static u32 +bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget) +{ + struct bna_cq_entry *cmpl, *next_cmpl; + struct bna_rcb *rcb = NULL; + unsigned int wi_range, packets = 0, wis = 0; + struct bnad_unmap_q *unmap_q; + struct sk_buff *skb; + u32 flags; + u32 qid0 = ccb->rcb[0]->rxq->rxq_id; + struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate; + + prefetch(bnad->netdev); + BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl, + wi_range); + BUG_ON(!(wi_range <= ccb->q_depth)); + while (cmpl->valid && packets < budget) { + packets++; + BNA_UPDATE_PKT_CNT(pkt_rt, ntohs(cmpl->length)); + + if (qid0 == cmpl->rxq_id) + rcb = ccb->rcb[0]; + else + rcb = ccb->rcb[1]; + + unmap_q = rcb->unmap_q; + + skb = unmap_q->unmap_array[unmap_q->consumer_index].skb; + BUG_ON(!(skb)); + unmap_q->unmap_array[unmap_q->consumer_index].skb = NULL; + pci_unmap_single(bnad->pcidev, + pci_unmap_addr(&unmap_q-> + unmap_array[unmap_q-> + consumer_index], + dma_addr), + rcb->rxq->buffer_size, + PCI_DMA_FROMDEVICE); + BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth); + + /* Should be more efficient ? Performance ? */ + BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth); + + wis++; + if (likely(--wi_range)) + next_cmpl = cmpl + 1; + else { + BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth); + wis = 0; + BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, + next_cmpl, wi_range); + BUG_ON(!(wi_range <= ccb->q_depth)); + } + prefetch(next_cmpl); + + flags = ntohl(cmpl->flags); + if (unlikely + (flags & + (BNA_CQ_EF_MAC_ERROR | BNA_CQ_EF_FCS_ERROR | + BNA_CQ_EF_TOO_LONG))) { + dev_kfree_skb_any(skb); + rcb->rxq->rx_packets_with_error++; + goto next; + } + + skb_put(skb, ntohs(cmpl->length)); + if (likely + (bnad->rx_csum && + (((flags & BNA_CQ_EF_IPV4) && + (flags & BNA_CQ_EF_L3_CKSUM_OK)) || + (flags & BNA_CQ_EF_IPV6)) && + (flags & (BNA_CQ_EF_TCP | BNA_CQ_EF_UDP)) && + (flags & BNA_CQ_EF_L4_CKSUM_OK))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + + rcb->rxq->rx_packets++; + rcb->rxq->rx_bytes += skb->len; + skb->protocol = eth_type_trans(skb, bnad->netdev); + + if (bnad->vlan_grp && (flags & BNA_CQ_EF_VLAN)) { + struct bnad_rx_ctrl *rx_ctrl = + (struct bnad_rx_ctrl *)ccb->ctrl; + if (skb->ip_summed == CHECKSUM_UNNECESSARY) + vlan_gro_receive(&rx_ctrl->napi, bnad->vlan_grp, + ntohs(cmpl->vlan_tag), skb); + else + vlan_hwaccel_receive_skb(skb, + bnad->vlan_grp, + ntohs(cmpl->vlan_tag)); + + } else { /* Not VLAN tagged/stripped */ + struct bnad_rx_ctrl *rx_ctrl = + (struct bnad_rx_ctrl *)ccb->ctrl; + if (skb->ip_summed == CHECKSUM_UNNECESSARY) + napi_gro_receive(&rx_ctrl->napi, skb); + else + netif_receive_skb(skb); + } + +next: + cmpl->valid = 0; + cmpl = next_cmpl; + } + + BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth); + + if (likely(ccb)) { + bna_ib_ack(ccb->i_dbell, packets); + bnad_refill_rxq(bnad, ccb->rcb[0]); + if (ccb->rcb[1]) + bnad_refill_rxq(bnad, ccb->rcb[1]); + } else + bna_ib_ack(ccb->i_dbell, 0); + + return packets; +} + +static void +bnad_disable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb) +{ + bna_ib_coalescing_timer_set(ccb->i_dbell, 0); + bna_ib_ack(ccb->i_dbell, 0); +} + +static void +bnad_enable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb) +{ + spin_lock_irq(&bnad->bna_lock); /* Because of polling context */ + bnad_enable_rx_irq_unsafe(ccb); + spin_unlock_irq(&bnad->bna_lock); +} + +static void +bnad_netif_rx_schedule_poll(struct bnad *bnad, struct bna_ccb *ccb) +{ + struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl); + if (likely(napi_schedule_prep((&rx_ctrl->napi)))) { + bnad_disable_rx_irq(bnad, ccb); + __napi_schedule((&rx_ctrl->napi)); + } + BNAD_UPDATE_CTR(bnad, netif_rx_schedule); +} + +/* MSIX Rx Path Handler */ +static irqreturn_t +bnad_msix_rx(int irq, void *data) +{ + struct bna_ccb *ccb = (struct bna_ccb *)data; + struct bnad *bnad = ccb->bnad; + + bnad_netif_rx_schedule_poll(bnad, ccb); + + return IRQ_HANDLED; +} + +/* Interrupt handlers */ + +/* Mbox Interrupt Handlers */ +static irqreturn_t +bnad_msix_mbox_handler(int irq, void *data) +{ + u32 intr_status; + unsigned long flags; + struct net_device *netdev = data; + struct bnad *bnad; + + bnad = netdev_priv(netdev); + + /* BNA_ISR_GET(bnad); Inc Ref count */ + spin_lock_irqsave(&bnad->bna_lock, flags); + + bna_intr_status_get(&bnad->bna, intr_status); + + if (BNA_IS_MBOX_ERR_INTR(intr_status)) + bna_mbox_handler(&bnad->bna, intr_status); + + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + /* BNAD_ISR_PUT(bnad); Dec Ref count */ + return IRQ_HANDLED; +} + +static irqreturn_t +bnad_isr(int irq, void *data) +{ + int i, j; + u32 intr_status; + unsigned long flags; + struct net_device *netdev = data; + struct bnad *bnad = netdev_priv(netdev); + struct bnad_rx_info *rx_info; + struct bnad_rx_ctrl *rx_ctrl; + + spin_lock_irqsave(&bnad->bna_lock, flags); + + bna_intr_status_get(&bnad->bna, intr_status); + if (!intr_status) { + spin_unlock_irqrestore(&bnad->bna_lock, flags); + return IRQ_NONE; + } + + if (BNA_IS_MBOX_ERR_INTR(intr_status)) { + bna_mbox_handler(&bnad->bna, intr_status); + if (!BNA_IS_INTX_DATA_INTR(intr_status)) { + spin_unlock_irqrestore(&bnad->bna_lock, flags); + goto done; + } + } + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + /* Process data interrupts */ + for (i = 0; i < bnad->num_rx; i++) { + rx_info = &bnad->rx_info[i]; + if (!rx_info->rx) + continue; + for (j = 0; j < bnad->num_rxp_per_rx; j++) { + rx_ctrl = &rx_info->rx_ctrl[j]; + if (rx_ctrl->ccb) + bnad_netif_rx_schedule_poll(bnad, + rx_ctrl->ccb); + } + } +done: + return IRQ_HANDLED; +} + +/* + * Called in interrupt / callback context + * with bna_lock held, so cfg_flags access is OK + */ +static void +bnad_enable_mbox_irq(struct bnad *bnad) +{ + int irq = BNAD_GET_MBOX_IRQ(bnad); + + if (!(bnad->cfg_flags & BNAD_CF_MSIX)) + return; + + if (test_and_clear_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)) + enable_irq(irq); + BNAD_UPDATE_CTR(bnad, mbox_intr_enabled); +} + +/* + * Called with bnad->bna_lock held b'cos of + * bnad->cfg_flags access. + */ +void +bnad_disable_mbox_irq(struct bnad *bnad) +{ + int irq = BNAD_GET_MBOX_IRQ(bnad); + + if (!(bnad->cfg_flags & BNAD_CF_MSIX)) + return; + + if (!test_and_set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)) + disable_irq_nosync(irq); + BNAD_UPDATE_CTR(bnad, mbox_intr_disabled); +} + +/* Control Path Handlers */ + +/* Callbacks */ +void +bnad_cb_device_enable_mbox_intr(struct bnad *bnad) +{ + bnad_enable_mbox_irq(bnad); +} + +void +bnad_cb_device_disable_mbox_intr(struct bnad *bnad) +{ + bnad_disable_mbox_irq(bnad); +} + +void +bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status) +{ + complete(&bnad->bnad_completions.ioc_comp); + bnad->bnad_completions.ioc_comp_status = status; +} + +void +bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status) +{ + complete(&bnad->bnad_completions.ioc_comp); + bnad->bnad_completions.ioc_comp_status = status; +} + +static void +bnad_cb_port_disabled(void *arg, enum bna_cb_status status) +{ + struct bnad *bnad = (struct bnad *)arg; + + complete(&bnad->bnad_completions.port_comp); + + netif_carrier_off(bnad->netdev); +} + +void +bnad_cb_port_link_status(struct bnad *bnad, + enum bna_link_status link_status) +{ + bool link_up = 0; + + link_up = (link_status == BNA_LINK_UP) || (link_status == BNA_CEE_UP); + + if (link_status == BNA_CEE_UP) { + set_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags); + BNAD_UPDATE_CTR(bnad, cee_up); + } else + clear_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags); + + if (link_up) { + if (!netif_carrier_ok(bnad->netdev)) { + pr_warn("bna: %s link up\n", + bnad->netdev->name); + netif_carrier_on(bnad->netdev); + BNAD_UPDATE_CTR(bnad, link_toggle); + if (test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags)) { + /* Force an immediate Transmit Schedule */ + pr_info("bna: %s TX_STARTED\n", + bnad->netdev->name); + netif_wake_queue(bnad->netdev); + BNAD_UPDATE_CTR(bnad, netif_queue_wakeup); + } else { + netif_stop_queue(bnad->netdev); + BNAD_UPDATE_CTR(bnad, netif_queue_stop); + } + } + } else { + if (netif_carrier_ok(bnad->netdev)) { + pr_warn("bna: %s link down\n", + bnad->netdev->name); + netif_carrier_off(bnad->netdev); + BNAD_UPDATE_CTR(bnad, link_toggle); + } + } +} + +static void +bnad_cb_tx_disabled(void *arg, struct bna_tx *tx, + enum bna_cb_status status) +{ + struct bnad *bnad = (struct bnad *)arg; + + complete(&bnad->bnad_completions.tx_comp); +} + +static void +bnad_cb_tcb_setup(struct bnad *bnad, struct bna_tcb *tcb) +{ + struct bnad_tx_info *tx_info = + (struct bnad_tx_info *)tcb->txq->tx->priv; + struct bnad_unmap_q *unmap_q = tcb->unmap_q; + + tx_info->tcb[tcb->id] = tcb; + unmap_q->producer_index = 0; + unmap_q->consumer_index = 0; + unmap_q->q_depth = BNAD_TX_UNMAPQ_DEPTH; +} + +static void +bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb) +{ + struct bnad_tx_info *tx_info = + (struct bnad_tx_info *)tcb->txq->tx->priv; + + tx_info->tcb[tcb->id] = NULL; +} + +static void +bnad_cb_rcb_setup(struct bnad *bnad, struct bna_rcb *rcb) +{ + struct bnad_unmap_q *unmap_q = rcb->unmap_q; + + unmap_q->producer_index = 0; + unmap_q->consumer_index = 0; + unmap_q->q_depth = BNAD_RX_UNMAPQ_DEPTH; +} + +static void +bnad_cb_ccb_setup(struct bnad *bnad, struct bna_ccb *ccb) +{ + struct bnad_rx_info *rx_info = + (struct bnad_rx_info *)ccb->cq->rx->priv; + + rx_info->rx_ctrl[ccb->id].ccb = ccb; + ccb->ctrl = &rx_info->rx_ctrl[ccb->id]; +} + +static void +bnad_cb_ccb_destroy(struct bnad *bnad, struct bna_ccb *ccb) +{ + struct bnad_rx_info *rx_info = + (struct bnad_rx_info *)ccb->cq->rx->priv; + + rx_info->rx_ctrl[ccb->id].ccb = NULL; +} + +static void +bnad_cb_tx_stall(struct bnad *bnad, struct bna_tcb *tcb) +{ + struct bnad_tx_info *tx_info = + (struct bnad_tx_info *)tcb->txq->tx->priv; + + if (tx_info != &bnad->tx_info[0]) + return; + + clear_bit(BNAD_RF_TX_STARTED, &bnad->run_flags); + netif_stop_queue(bnad->netdev); + pr_info("bna: %s TX_STOPPED\n", bnad->netdev->name); +} + +static void +bnad_cb_tx_resume(struct bnad *bnad, struct bna_tcb *tcb) +{ + if (test_and_set_bit(BNAD_RF_TX_STARTED, &bnad->run_flags)) + return; + + if (netif_carrier_ok(bnad->netdev)) { + pr_info("bna: %s TX_STARTED\n", bnad->netdev->name); + netif_wake_queue(bnad->netdev); + BNAD_UPDATE_CTR(bnad, netif_queue_wakeup); + } +} + +static void +bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb) +{ + struct bnad_unmap_q *unmap_q = tcb->unmap_q; + + if (!tcb || (!tcb->unmap_q)) + return; + + if (!unmap_q->unmap_array) + return; + + if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) + return; + + bnad_free_all_txbufs(bnad, tcb); + + unmap_q->producer_index = 0; + unmap_q->consumer_index = 0; + + smp_mb__before_clear_bit(); + clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags); +} + +static void +bnad_cb_rx_cleanup(struct bnad *bnad, + struct bna_ccb *ccb) +{ + bnad_cq_cmpl_init(bnad, ccb); + + bnad_free_rxbufs(bnad, ccb->rcb[0]); + clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags); + + if (ccb->rcb[1]) { + bnad_free_rxbufs(bnad, ccb->rcb[1]); + clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags); + } +} + +static void +bnad_cb_rx_post(struct bnad *bnad, struct bna_rcb *rcb) +{ + struct bnad_unmap_q *unmap_q = rcb->unmap_q; + + set_bit(BNAD_RXQ_STARTED, &rcb->flags); + + /* Now allocate & post buffers for this RCB */ + /* !!Allocation in callback context */ + if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) { + if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth) + >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT) + bnad_alloc_n_post_rxbufs(bnad, rcb); + smp_mb__before_clear_bit(); + clear_bit(BNAD_RXQ_REFILL, &rcb->flags); + } +} + +static void +bnad_cb_rx_disabled(void *arg, struct bna_rx *rx, + enum bna_cb_status status) +{ + struct bnad *bnad = (struct bnad *)arg; + + complete(&bnad->bnad_completions.rx_comp); +} + +static void +bnad_cb_rx_mcast_add(struct bnad *bnad, struct bna_rx *rx, + enum bna_cb_status status) +{ + bnad->bnad_completions.mcast_comp_status = status; + complete(&bnad->bnad_completions.mcast_comp); +} + +void +bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status, + struct bna_stats *stats) +{ + if (status == BNA_CB_SUCCESS) + BNAD_UPDATE_CTR(bnad, hw_stats_updates); + + if (!netif_running(bnad->netdev) || + !test_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags)) + return; + + mod_timer(&bnad->stats_timer, + jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ)); +} + +void +bnad_cb_stats_clr(struct bnad *bnad) +{ +} + +/* Resource allocation, free functions */ + +static void +bnad_mem_free(struct bnad *bnad, + struct bna_mem_info *mem_info) +{ + int i; + dma_addr_t dma_pa; + + if (mem_info->mdl == NULL) + return; + + for (i = 0; i < mem_info->num; i++) { + if (mem_info->mdl[i].kva != NULL) { + if (mem_info->mem_type == BNA_MEM_T_DMA) { + BNA_GET_DMA_ADDR(&(mem_info->mdl[i].dma), + dma_pa); + pci_free_consistent(bnad->pcidev, + mem_info->mdl[i].len, + mem_info->mdl[i].kva, dma_pa); + } else + kfree(mem_info->mdl[i].kva); + } + } + kfree(mem_info->mdl); + mem_info->mdl = NULL; +} + +static int +bnad_mem_alloc(struct bnad *bnad, + struct bna_mem_info *mem_info) +{ + int i; + dma_addr_t dma_pa; + + if ((mem_info->num == 0) || (mem_info->len == 0)) { + mem_info->mdl = NULL; + return 0; + } + + mem_info->mdl = kcalloc(mem_info->num, sizeof(struct bna_mem_descr), + GFP_KERNEL); + if (mem_info->mdl == NULL) + return -ENOMEM; + + if (mem_info->mem_type == BNA_MEM_T_DMA) { + for (i = 0; i < mem_info->num; i++) { + mem_info->mdl[i].len = mem_info->len; + mem_info->mdl[i].kva = + pci_alloc_consistent(bnad->pcidev, + mem_info->len, &dma_pa); + + if (mem_info->mdl[i].kva == NULL) + goto err_return; + + BNA_SET_DMA_ADDR(dma_pa, + &(mem_info->mdl[i].dma)); + } + } else { + for (i = 0; i < mem_info->num; i++) { + mem_info->mdl[i].len = mem_info->len; + mem_info->mdl[i].kva = kzalloc(mem_info->len, + GFP_KERNEL); + if (mem_info->mdl[i].kva == NULL) + goto err_return; + } + } + + return 0; + +err_return: + bnad_mem_free(bnad, mem_info); + return -ENOMEM; +} + +/* Free IRQ for Mailbox */ +static void +bnad_mbox_irq_free(struct bnad *bnad, + struct bna_intr_info *intr_info) +{ + int irq; + unsigned long flags; + + if (intr_info->idl == NULL) + return; + + spin_lock_irqsave(&bnad->bna_lock, flags); + + bnad_disable_mbox_irq(bnad); + + irq = BNAD_GET_MBOX_IRQ(bnad); + free_irq(irq, bnad->netdev); + + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + kfree(intr_info->idl); +} + +/* + * Allocates IRQ for Mailbox, but keep it disabled + * This will be enabled once we get the mbox enable callback + * from bna + */ +static int +bnad_mbox_irq_alloc(struct bnad *bnad, + struct bna_intr_info *intr_info) +{ + int err; + unsigned long flags; + u32 irq; + irq_handler_t irq_handler; + + /* Mbox should use only 1 vector */ + + intr_info->idl = kzalloc(sizeof(*(intr_info->idl)), GFP_KERNEL); + if (!intr_info->idl) + return -ENOMEM; + + spin_lock_irqsave(&bnad->bna_lock, flags); + if (bnad->cfg_flags & BNAD_CF_MSIX) { + irq_handler = (irq_handler_t)bnad_msix_mbox_handler; + irq = bnad->msix_table[bnad->msix_num - 1].vector; + flags = 0; + intr_info->intr_type = BNA_INTR_T_MSIX; + intr_info->idl[0].vector = bnad->msix_num - 1; + } else { + irq_handler = (irq_handler_t)bnad_isr; + irq = bnad->pcidev->irq; + flags = IRQF_SHARED; + intr_info->intr_type = BNA_INTR_T_INTX; + /* intr_info->idl.vector = 0 ? */ + } + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + sprintf(bnad->mbox_irq_name, "%s", BNAD_NAME); + + err = request_irq(irq, irq_handler, flags, + bnad->mbox_irq_name, bnad->netdev); + if (err) { + kfree(intr_info->idl); + intr_info->idl = NULL; + return err; + } + + spin_lock_irqsave(&bnad->bna_lock, flags); + bnad_disable_mbox_irq(bnad); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + return 0; +} + +static void +bnad_txrx_irq_free(struct bnad *bnad, struct bna_intr_info *intr_info) +{ + kfree(intr_info->idl); + intr_info->idl = NULL; +} + +/* Allocates Interrupt Descriptor List for MSIX/INT-X vectors */ +static int +bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src, + uint txrx_id, struct bna_intr_info *intr_info) +{ + int i, vector_start = 0; + u32 cfg_flags; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + cfg_flags = bnad->cfg_flags; + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + if (cfg_flags & BNAD_CF_MSIX) { + intr_info->intr_type = BNA_INTR_T_MSIX; + intr_info->idl = kcalloc(intr_info->num, + sizeof(struct bna_intr_descr), + GFP_KERNEL); + if (!intr_info->idl) + return -ENOMEM; + + switch (src) { + case BNAD_INTR_TX: + vector_start = txrx_id; + break; + + case BNAD_INTR_RX: + vector_start = bnad->num_tx * bnad->num_txq_per_tx + + txrx_id; + break; + + default: + BUG(); + } + + for (i = 0; i < intr_info->num; i++) + intr_info->idl[i].vector = vector_start + i; + } else { + intr_info->intr_type = BNA_INTR_T_INTX; + intr_info->num = 1; + intr_info->idl = kcalloc(intr_info->num, + sizeof(struct bna_intr_descr), + GFP_KERNEL); + if (!intr_info->idl) + return -ENOMEM; + + switch (src) { + case BNAD_INTR_TX: + intr_info->idl[0].vector = 0x1; /* Bit mask : Tx IB */ + break; + + case BNAD_INTR_RX: + intr_info->idl[0].vector = 0x2; /* Bit mask : Rx IB */ + break; + } + } + return 0; +} + +/** + * NOTE: Should be called for MSIX only + * Unregisters Tx MSIX vector(s) from the kernel + */ +static void +bnad_tx_msix_unregister(struct bnad *bnad, struct bnad_tx_info *tx_info, + int num_txqs) +{ + int i; + int vector_num; + + for (i = 0; i < num_txqs; i++) { + if (tx_info->tcb[i] == NULL) + continue; + + vector_num = tx_info->tcb[i]->intr_vector; + free_irq(bnad->msix_table[vector_num].vector, tx_info->tcb[i]); + } +} + +/** + * NOTE: Should be called for MSIX only + * Registers Tx MSIX vector(s) and ISR(s), cookie with the kernel + */ +static int +bnad_tx_msix_register(struct bnad *bnad, struct bnad_tx_info *tx_info, + uint tx_id, int num_txqs) +{ + int i; + int err; + int vector_num; + + for (i = 0; i < num_txqs; i++) { + vector_num = tx_info->tcb[i]->intr_vector; + sprintf(tx_info->tcb[i]->name, "%s TXQ %d", bnad->netdev->name, + tx_id + tx_info->tcb[i]->id); + err = request_irq(bnad->msix_table[vector_num].vector, + (irq_handler_t)bnad_msix_tx, 0, + tx_info->tcb[i]->name, + tx_info->tcb[i]); + if (err) + goto err_return; + } + + return 0; + +err_return: + if (i > 0) + bnad_tx_msix_unregister(bnad, tx_info, (i - 1)); + return -1; +} + +/** + * NOTE: Should be called for MSIX only + * Unregisters Rx MSIX vector(s) from the kernel + */ +static void +bnad_rx_msix_unregister(struct bnad *bnad, struct bnad_rx_info *rx_info, + int num_rxps) +{ + int i; + int vector_num; + + for (i = 0; i < num_rxps; i++) { + if (rx_info->rx_ctrl[i].ccb == NULL) + continue; + + vector_num = rx_info->rx_ctrl[i].ccb->intr_vector; + free_irq(bnad->msix_table[vector_num].vector, + rx_info->rx_ctrl[i].ccb); + } +} + +/** + * NOTE: Should be called for MSIX only + * Registers Tx MSIX vector(s) and ISR(s), cookie with the kernel + */ +static int +bnad_rx_msix_register(struct bnad *bnad, struct bnad_rx_info *rx_info, + uint rx_id, int num_rxps) +{ + int i; + int err; + int vector_num; + + for (i = 0; i < num_rxps; i++) { + vector_num = rx_info->rx_ctrl[i].ccb->intr_vector; + sprintf(rx_info->rx_ctrl[i].ccb->name, "%s CQ %d", + bnad->netdev->name, + rx_id + rx_info->rx_ctrl[i].ccb->id); + err = request_irq(bnad->msix_table[vector_num].vector, + (irq_handler_t)bnad_msix_rx, 0, + rx_info->rx_ctrl[i].ccb->name, + rx_info->rx_ctrl[i].ccb); + if (err) + goto err_return; + } + + return 0; + +err_return: + if (i > 0) + bnad_rx_msix_unregister(bnad, rx_info, (i - 1)); + return -1; +} + +/* Free Tx object Resources */ +static void +bnad_tx_res_free(struct bnad *bnad, struct bna_res_info *res_info) +{ + int i; + + for (i = 0; i < BNA_TX_RES_T_MAX; i++) { + if (res_info[i].res_type == BNA_RES_T_MEM) + bnad_mem_free(bnad, &res_info[i].res_u.mem_info); + else if (res_info[i].res_type == BNA_RES_T_INTR) + bnad_txrx_irq_free(bnad, &res_info[i].res_u.intr_info); + } +} + +/* Allocates memory and interrupt resources for Tx object */ +static int +bnad_tx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info, + uint tx_id) +{ + int i, err = 0; + + for (i = 0; i < BNA_TX_RES_T_MAX; i++) { + if (res_info[i].res_type == BNA_RES_T_MEM) + err = bnad_mem_alloc(bnad, + &res_info[i].res_u.mem_info); + else if (res_info[i].res_type == BNA_RES_T_INTR) + err = bnad_txrx_irq_alloc(bnad, BNAD_INTR_TX, tx_id, + &res_info[i].res_u.intr_info); + if (err) + goto err_return; + } + return 0; + +err_return: + bnad_tx_res_free(bnad, res_info); + return err; +} + +/* Free Rx object Resources */ +static void +bnad_rx_res_free(struct bnad *bnad, struct bna_res_info *res_info) +{ + int i; + + for (i = 0; i < BNA_RX_RES_T_MAX; i++) { + if (res_info[i].res_type == BNA_RES_T_MEM) + bnad_mem_free(bnad, &res_info[i].res_u.mem_info); + else if (res_info[i].res_type == BNA_RES_T_INTR) + bnad_txrx_irq_free(bnad, &res_info[i].res_u.intr_info); + } +} + +/* Allocates memory and interrupt resources for Rx object */ +static int +bnad_rx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info, + uint rx_id) +{ + int i, err = 0; + + /* All memory needs to be allocated before setup_ccbs */ + for (i = 0; i < BNA_RX_RES_T_MAX; i++) { + if (res_info[i].res_type == BNA_RES_T_MEM) + err = bnad_mem_alloc(bnad, + &res_info[i].res_u.mem_info); + else if (res_info[i].res_type == BNA_RES_T_INTR) + err = bnad_txrx_irq_alloc(bnad, BNAD_INTR_RX, rx_id, + &res_info[i].res_u.intr_info); + if (err) + goto err_return; + } + return 0; + +err_return: + bnad_rx_res_free(bnad, res_info); + return err; +} + +/* Timer callbacks */ +/* a) IOC timer */ +static void +bnad_ioc_timeout(unsigned long data) +{ + struct bnad *bnad = (struct bnad *)data; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + bfa_ioc_timeout((void *) &bnad->bna.device.ioc); + spin_unlock_irqrestore(&bnad->bna_lock, flags); +} + +static void +bnad_ioc_hb_check(unsigned long data) +{ + struct bnad *bnad = (struct bnad *)data; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + bfa_ioc_hb_check((void *) &bnad->bna.device.ioc); + spin_unlock_irqrestore(&bnad->bna_lock, flags); +} + +static void +bnad_ioc_sem_timeout(unsigned long data) +{ + struct bnad *bnad = (struct bnad *)data; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + bfa_ioc_sem_timeout((void *) &bnad->bna.device.ioc); + spin_unlock_irqrestore(&bnad->bna_lock, flags); +} + +/* + * All timer routines use bnad->bna_lock to protect against + * the following race, which may occur in case of no locking: + * Time CPU m CPU n + * 0 1 = test_bit + * 1 clear_bit + * 2 del_timer_sync + * 3 mod_timer + */ + +/* b) Dynamic Interrupt Moderation Timer */ +static void +bnad_dim_timeout(unsigned long data) +{ + struct bnad *bnad = (struct bnad *)data; + struct bnad_rx_info *rx_info; + struct bnad_rx_ctrl *rx_ctrl; + int i, j; + unsigned long flags; + + if (!netif_carrier_ok(bnad->netdev)) + return; + + spin_lock_irqsave(&bnad->bna_lock, flags); + for (i = 0; i < bnad->num_rx; i++) { + rx_info = &bnad->rx_info[i]; + if (!rx_info->rx) + continue; + for (j = 0; j < bnad->num_rxp_per_rx; j++) { + rx_ctrl = &rx_info->rx_ctrl[j]; + if (!rx_ctrl->ccb) + continue; + bna_rx_dim_update(rx_ctrl->ccb); + } + } + + /* Check for BNAD_CF_DIM_ENABLED, does not eleminate a race */ + if (test_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags)) + mod_timer(&bnad->dim_timer, + jiffies + msecs_to_jiffies(BNAD_DIM_TIMER_FREQ)); + spin_unlock_irqrestore(&bnad->bna_lock, flags); +} + +/* c) Statistics Timer */ +static void +bnad_stats_timeout(unsigned long data) +{ + struct bnad *bnad = (struct bnad *)data; + unsigned long flags; + + if (!netif_running(bnad->netdev) || + !test_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags)) + return; + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_stats_get(&bnad->bna); + spin_unlock_irqrestore(&bnad->bna_lock, flags); +} + +/* + * Set up timer for DIM + * Called with bnad->bna_lock held + */ +void +bnad_dim_timer_start(struct bnad *bnad) +{ + if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED && + !test_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags)) { + setup_timer(&bnad->dim_timer, bnad_dim_timeout, + (unsigned long)bnad); + set_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags); + mod_timer(&bnad->dim_timer, + jiffies + msecs_to_jiffies(BNAD_DIM_TIMER_FREQ)); + } +} + +/* + * Set up timer for statistics + * Called with mutex_lock(&bnad->conf_mutex) held + */ +static void +bnad_stats_timer_start(struct bnad *bnad) +{ + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + if (!test_and_set_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags)) { + setup_timer(&bnad->stats_timer, bnad_stats_timeout, + (unsigned long)bnad); + mod_timer(&bnad->stats_timer, + jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ)); + } + spin_unlock_irqrestore(&bnad->bna_lock, flags); + +} + +/* + * Stops the stats timer + * Called with mutex_lock(&bnad->conf_mutex) held + */ +static void +bnad_stats_timer_stop(struct bnad *bnad) +{ + int to_del = 0; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + if (test_and_clear_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags)) + to_del = 1; + spin_unlock_irqrestore(&bnad->bna_lock, flags); + if (to_del) + del_timer_sync(&bnad->stats_timer); +} + +/* Utilities */ + +static void +bnad_netdev_mc_list_get(struct net_device *netdev, u8 *mc_list) +{ + int i = 1; /* Index 0 has broadcast address */ + struct netdev_hw_addr *mc_addr; + + netdev_for_each_mc_addr(mc_addr, netdev) { + memcpy(&mc_list[i * ETH_ALEN], &mc_addr->addr[0], + ETH_ALEN); + i++; + } +} + +static int +bnad_napi_poll_rx(struct napi_struct *napi, int budget) +{ + struct bnad_rx_ctrl *rx_ctrl = + container_of(napi, struct bnad_rx_ctrl, napi); + struct bna_ccb *ccb; + struct bnad *bnad; + int rcvd = 0; + + ccb = rx_ctrl->ccb; + + bnad = ccb->bnad; + + if (!netif_carrier_ok(bnad->netdev)) + goto poll_exit; + + rcvd = bnad_poll_cq(bnad, ccb, budget); + if (rcvd == budget) + return rcvd; + +poll_exit: + napi_complete((napi)); + + BNAD_UPDATE_CTR(bnad, netif_rx_complete); + + bnad_enable_rx_irq(bnad, ccb); + return rcvd; +} + +static int +bnad_napi_poll_txrx(struct napi_struct *napi, int budget) +{ + struct bnad_rx_ctrl *rx_ctrl = + container_of(napi, struct bnad_rx_ctrl, napi); + struct bna_ccb *ccb; + struct bnad *bnad; + int rcvd = 0; + int i, j; + + ccb = rx_ctrl->ccb; + + bnad = ccb->bnad; + + if (!netif_carrier_ok(bnad->netdev)) + goto poll_exit; + + /* Handle Tx Completions, if any */ + for (i = 0; i < bnad->num_tx; i++) { + for (j = 0; j < bnad->num_txq_per_tx; j++) + bnad_tx(bnad, bnad->tx_info[i].tcb[j]); + } + + /* Handle Rx Completions */ + rcvd = bnad_poll_cq(bnad, ccb, budget); + if (rcvd == budget) + return rcvd; +poll_exit: + napi_complete((napi)); + + BNAD_UPDATE_CTR(bnad, netif_rx_complete); + + bnad_enable_txrx_irqs(bnad); + return rcvd; +} + +static void +bnad_napi_enable(struct bnad *bnad, u32 rx_id) +{ + int (*napi_poll) (struct napi_struct *, int); + struct bnad_rx_ctrl *rx_ctrl; + int i; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + if (bnad->cfg_flags & BNAD_CF_MSIX) + napi_poll = bnad_napi_poll_rx; + else + napi_poll = bnad_napi_poll_txrx; + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + /* Initialize & enable NAPI */ + for (i = 0; i < bnad->num_rxp_per_rx; i++) { + rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i]; + netif_napi_add(bnad->netdev, &rx_ctrl->napi, + napi_poll, 64); + napi_enable(&rx_ctrl->napi); + } +} + +static void +bnad_napi_disable(struct bnad *bnad, u32 rx_id) +{ + int i; + + /* First disable and then clean up */ + for (i = 0; i < bnad->num_rxp_per_rx; i++) { + napi_disable(&bnad->rx_info[rx_id].rx_ctrl[i].napi); + netif_napi_del(&bnad->rx_info[rx_id].rx_ctrl[i].napi); + } +} + +/* Should be held with conf_lock held */ +void +bnad_cleanup_tx(struct bnad *bnad, uint tx_id) +{ + struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id]; + struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0]; + unsigned long flags; + + if (!tx_info->tx) + return; + + init_completion(&bnad->bnad_completions.tx_comp); + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_tx_disable(tx_info->tx, BNA_HARD_CLEANUP, bnad_cb_tx_disabled); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + wait_for_completion(&bnad->bnad_completions.tx_comp); + + if (tx_info->tcb[0]->intr_type == BNA_INTR_T_MSIX) + bnad_tx_msix_unregister(bnad, tx_info, + bnad->num_txq_per_tx); + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_tx_destroy(tx_info->tx); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + tx_info->tx = NULL; + + if (0 == tx_id) + tasklet_kill(&bnad->tx_free_tasklet); + + bnad_tx_res_free(bnad, res_info); +} + +/* Should be held with conf_lock held */ +int +bnad_setup_tx(struct bnad *bnad, uint tx_id) +{ + int err; + struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id]; + struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0]; + struct bna_intr_info *intr_info = + &res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info; + struct bna_tx_config *tx_config = &bnad->tx_config[tx_id]; + struct bna_tx_event_cbfn tx_cbfn; + struct bna_tx *tx; + unsigned long flags; + + /* Initialize the Tx object configuration */ + tx_config->num_txq = bnad->num_txq_per_tx; + tx_config->txq_depth = bnad->txq_depth; + tx_config->tx_type = BNA_TX_T_REGULAR; + + /* Initialize the tx event handlers */ + tx_cbfn.tcb_setup_cbfn = bnad_cb_tcb_setup; + tx_cbfn.tcb_destroy_cbfn = bnad_cb_tcb_destroy; + tx_cbfn.tx_stall_cbfn = bnad_cb_tx_stall; + tx_cbfn.tx_resume_cbfn = bnad_cb_tx_resume; + tx_cbfn.tx_cleanup_cbfn = bnad_cb_tx_cleanup; + + /* Get BNA's resource requirement for one tx object */ + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_tx_res_req(bnad->num_txq_per_tx, + bnad->txq_depth, res_info); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + /* Fill Unmap Q memory requirements */ + BNAD_FILL_UNMAPQ_MEM_REQ( + &res_info[BNA_TX_RES_MEM_T_UNMAPQ], + bnad->num_txq_per_tx, + BNAD_TX_UNMAPQ_DEPTH); + + /* Allocate resources */ + err = bnad_tx_res_alloc(bnad, res_info, tx_id); + if (err) + return err; + + /* Ask BNA to create one Tx object, supplying required resources */ + spin_lock_irqsave(&bnad->bna_lock, flags); + tx = bna_tx_create(&bnad->bna, bnad, tx_config, &tx_cbfn, res_info, + tx_info); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + if (!tx) + goto err_return; + tx_info->tx = tx; + + /* Register ISR for the Tx object */ + if (intr_info->intr_type == BNA_INTR_T_MSIX) { + err = bnad_tx_msix_register(bnad, tx_info, + tx_id, bnad->num_txq_per_tx); + if (err) + goto err_return; + } + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_tx_enable(tx); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + return 0; + +err_return: + bnad_tx_res_free(bnad, res_info); + return err; +} + +/* Setup the rx config for bna_rx_create */ +/* bnad decides the configuration */ +static void +bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config) +{ + rx_config->rx_type = BNA_RX_T_REGULAR; + rx_config->num_paths = bnad->num_rxp_per_rx; + + if (bnad->num_rxp_per_rx > 1) { + rx_config->rss_status = BNA_STATUS_T_ENABLED; + rx_config->rss_config.hash_type = + (BFI_RSS_T_V4_TCP | + BFI_RSS_T_V6_TCP | + BFI_RSS_T_V4_IP | + BFI_RSS_T_V6_IP); + rx_config->rss_config.hash_mask = + bnad->num_rxp_per_rx - 1; + get_random_bytes(rx_config->rss_config.toeplitz_hash_key, + sizeof(rx_config->rss_config.toeplitz_hash_key)); + } else { + rx_config->rss_status = BNA_STATUS_T_DISABLED; + memset(&rx_config->rss_config, 0, + sizeof(rx_config->rss_config)); + } + rx_config->rxp_type = BNA_RXP_SLR; + rx_config->q_depth = bnad->rxq_depth; + + rx_config->small_buff_size = BFI_SMALL_RXBUF_SIZE; + + rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED; +} + +/* Called with mutex_lock(&bnad->conf_mutex) held */ +void +bnad_cleanup_rx(struct bnad *bnad, uint rx_id) +{ + struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id]; + struct bna_rx_config *rx_config = &bnad->rx_config[rx_id]; + struct bna_res_info *res_info = &bnad->rx_res_info[rx_id].res_info[0]; + unsigned long flags; + int dim_timer_del = 0; + + if (!rx_info->rx) + return; + + if (0 == rx_id) { + spin_lock_irqsave(&bnad->bna_lock, flags); + dim_timer_del = bnad_dim_timer_running(bnad); + if (dim_timer_del) + clear_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + if (dim_timer_del) + del_timer_sync(&bnad->dim_timer); + } + + bnad_napi_disable(bnad, rx_id); + + init_completion(&bnad->bnad_completions.rx_comp); + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_rx_disable(rx_info->rx, BNA_HARD_CLEANUP, bnad_cb_rx_disabled); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + wait_for_completion(&bnad->bnad_completions.rx_comp); + + if (rx_info->rx_ctrl[0].ccb->intr_type == BNA_INTR_T_MSIX) + bnad_rx_msix_unregister(bnad, rx_info, rx_config->num_paths); + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_rx_destroy(rx_info->rx); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + rx_info->rx = NULL; + + bnad_rx_res_free(bnad, res_info); +} + +/* Called with mutex_lock(&bnad->conf_mutex) held */ +int +bnad_setup_rx(struct bnad *bnad, uint rx_id) +{ + int err; + struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id]; + struct bna_res_info *res_info = &bnad->rx_res_info[rx_id].res_info[0]; + struct bna_intr_info *intr_info = + &res_info[BNA_RX_RES_T_INTR].res_u.intr_info; + struct bna_rx_config *rx_config = &bnad->rx_config[rx_id]; + struct bna_rx_event_cbfn rx_cbfn; + struct bna_rx *rx; + unsigned long flags; + + /* Initialize the Rx object configuration */ + bnad_init_rx_config(bnad, rx_config); + + /* Initialize the Rx event handlers */ + rx_cbfn.rcb_setup_cbfn = bnad_cb_rcb_setup; + rx_cbfn.rcb_destroy_cbfn = NULL; + rx_cbfn.ccb_setup_cbfn = bnad_cb_ccb_setup; + rx_cbfn.ccb_destroy_cbfn = bnad_cb_ccb_destroy; + rx_cbfn.rx_cleanup_cbfn = bnad_cb_rx_cleanup; + rx_cbfn.rx_post_cbfn = bnad_cb_rx_post; + + /* Get BNA's resource requirement for one Rx object */ + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_rx_res_req(rx_config, res_info); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + /* Fill Unmap Q memory requirements */ + BNAD_FILL_UNMAPQ_MEM_REQ( + &res_info[BNA_RX_RES_MEM_T_UNMAPQ], + rx_config->num_paths + + ((rx_config->rxp_type == BNA_RXP_SINGLE) ? 0 : + rx_config->num_paths), BNAD_RX_UNMAPQ_DEPTH); + + /* Allocate resource */ + err = bnad_rx_res_alloc(bnad, res_info, rx_id); + if (err) + return err; + + /* Ask BNA to create one Rx object, supplying required resources */ + spin_lock_irqsave(&bnad->bna_lock, flags); + rx = bna_rx_create(&bnad->bna, bnad, rx_config, &rx_cbfn, res_info, + rx_info); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + if (!rx) + goto err_return; + rx_info->rx = rx; + + /* Register ISR for the Rx object */ + if (intr_info->intr_type == BNA_INTR_T_MSIX) { + err = bnad_rx_msix_register(bnad, rx_info, rx_id, + rx_config->num_paths); + if (err) + goto err_return; + } + + /* Enable NAPI */ + bnad_napi_enable(bnad, rx_id); + + spin_lock_irqsave(&bnad->bna_lock, flags); + if (0 == rx_id) { + /* Set up Dynamic Interrupt Moderation Vector */ + if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) + bna_rx_dim_reconfig(&bnad->bna, bna_napi_dim_vector); + + /* Enable VLAN filtering only on the default Rx */ + bna_rx_vlanfilter_enable(rx); + + /* Start the DIM timer */ + bnad_dim_timer_start(bnad); + } + + bna_rx_enable(rx); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + return 0; + +err_return: + bnad_cleanup_rx(bnad, rx_id); + return err; +} + +/* Called with conf_lock & bnad->bna_lock held */ +void +bnad_tx_coalescing_timeo_set(struct bnad *bnad) +{ + struct bnad_tx_info *tx_info; + + tx_info = &bnad->tx_info[0]; + if (!tx_info->tx) + return; + + bna_tx_coalescing_timeo_set(tx_info->tx, bnad->tx_coalescing_timeo); +} + +/* Called with conf_lock & bnad->bna_lock held */ +void +bnad_rx_coalescing_timeo_set(struct bnad *bnad) +{ + struct bnad_rx_info *rx_info; + int i; + + for (i = 0; i < bnad->num_rx; i++) { + rx_info = &bnad->rx_info[i]; + if (!rx_info->rx) + continue; + bna_rx_coalescing_timeo_set(rx_info->rx, + bnad->rx_coalescing_timeo); + } +} + +/* + * Called with bnad->bna_lock held + */ +static int +bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr) +{ + int ret; + + if (!is_valid_ether_addr(mac_addr)) + return -EADDRNOTAVAIL; + + /* If datapath is down, pretend everything went through */ + if (!bnad->rx_info[0].rx) + return 0; + + ret = bna_rx_ucast_set(bnad->rx_info[0].rx, mac_addr, NULL); + if (ret != BNA_CB_SUCCESS) + return -EADDRNOTAVAIL; + + return 0; +} + +/* Should be called with conf_lock held */ +static int +bnad_enable_default_bcast(struct bnad *bnad) +{ + struct bnad_rx_info *rx_info = &bnad->rx_info[0]; + int ret; + unsigned long flags; + + init_completion(&bnad->bnad_completions.mcast_comp); + + spin_lock_irqsave(&bnad->bna_lock, flags); + ret = bna_rx_mcast_add(rx_info->rx, (u8 *)bnad_bcast_addr, + bnad_cb_rx_mcast_add); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + if (ret == BNA_CB_SUCCESS) + wait_for_completion(&bnad->bnad_completions.mcast_comp); + else + return -ENODEV; + + if (bnad->bnad_completions.mcast_comp_status != BNA_CB_SUCCESS) + return -ENODEV; + + return 0; +} + +/* Statistics utilities */ +void +bnad_netdev_qstats_fill(struct bnad *bnad) +{ + struct net_device_stats *net_stats = &bnad->net_stats; + int i, j; + + for (i = 0; i < bnad->num_rx; i++) { + for (j = 0; j < bnad->num_rxp_per_rx; j++) { + if (bnad->rx_info[i].rx_ctrl[j].ccb) { + net_stats->rx_packets += bnad->rx_info[i]. + rx_ctrl[j].ccb->rcb[0]->rxq->rx_packets; + net_stats->rx_bytes += bnad->rx_info[i]. + rx_ctrl[j].ccb->rcb[0]->rxq->rx_bytes; + if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] && + bnad->rx_info[i].rx_ctrl[j].ccb-> + rcb[1]->rxq) { + net_stats->rx_packets += + bnad->rx_info[i].rx_ctrl[j]. + ccb->rcb[1]->rxq->rx_packets; + net_stats->rx_bytes += + bnad->rx_info[i].rx_ctrl[j]. + ccb->rcb[1]->rxq->rx_bytes; + } + } + } + } + for (i = 0; i < bnad->num_tx; i++) { + for (j = 0; j < bnad->num_txq_per_tx; j++) { + if (bnad->tx_info[i].tcb[j]) { + net_stats->tx_packets += + bnad->tx_info[i].tcb[j]->txq->tx_packets; + net_stats->tx_bytes += + bnad->tx_info[i].tcb[j]->txq->tx_bytes; + } + } + } +} + +/* + * Must be called with the bna_lock held. + */ +void +bnad_netdev_hwstats_fill(struct bnad *bnad) +{ + struct bfi_ll_stats_mac *mac_stats; + struct net_device_stats *net_stats = &bnad->net_stats; + u64 bmap; + int i; + + mac_stats = &bnad->stats.bna_stats->hw_stats->mac_stats; + net_stats->rx_errors = + mac_stats->rx_fcs_error + mac_stats->rx_alignment_error + + mac_stats->rx_frame_length_error + mac_stats->rx_code_error + + mac_stats->rx_undersize; + net_stats->tx_errors = mac_stats->tx_fcs_error + + mac_stats->tx_undersize; + net_stats->rx_dropped = mac_stats->rx_drop; + net_stats->tx_dropped = mac_stats->tx_drop; + net_stats->multicast = mac_stats->rx_multicast; + net_stats->collisions = mac_stats->tx_total_collision; + + net_stats->rx_length_errors = mac_stats->rx_frame_length_error; + + /* receive ring buffer overflow ?? */ + + net_stats->rx_crc_errors = mac_stats->rx_fcs_error; + net_stats->rx_frame_errors = mac_stats->rx_alignment_error; + /* recv'r fifo overrun */ + bmap = (u64)bnad->stats.bna_stats->rxf_bmap[0] | + ((u64)bnad->stats.bna_stats->rxf_bmap[1] << 32); + for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) { + if (bmap & 1) { + net_stats->rx_fifo_errors = + bnad->stats.bna_stats-> + hw_stats->rxf_stats[i].frame_drops; + break; + } + bmap >>= 1; + } +} + +static void +bnad_mbox_irq_sync(struct bnad *bnad) +{ + u32 irq; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + if (bnad->cfg_flags & BNAD_CF_MSIX) + irq = bnad->msix_table[bnad->msix_num - 1].vector; + else + irq = bnad->pcidev->irq; + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + synchronize_irq(irq); +} + +/* Utility used by bnad_start_xmit, for doing TSO */ +static int +bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb) +{ + int err; + + /* SKB_GSO_TCPV4 and SKB_GSO_TCPV6 is defined since 2.6.18. */ + BUG_ON(!(skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4 || + skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6)); + if (skb_header_cloned(skb)) { + err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); + if (err) { + BNAD_UPDATE_CTR(bnad, tso_err); + return err; + } + } + + /* + * For TSO, the TCP checksum field is seeded with pseudo-header sum + * excluding the length field. + */ + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *iph = ip_hdr(skb); + + /* Do we really need these? */ + iph->tot_len = 0; + iph->check = 0; + + tcp_hdr(skb)->check = + ~csum_tcpudp_magic(iph->saddr, iph->daddr, 0, + IPPROTO_TCP, 0); + BNAD_UPDATE_CTR(bnad, tso4); + } else { + struct ipv6hdr *ipv6h = ipv6_hdr(skb); + + BUG_ON(!(skb->protocol == htons(ETH_P_IPV6))); + ipv6h->payload_len = 0; + tcp_hdr(skb)->check = + ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 0, + IPPROTO_TCP, 0); + BNAD_UPDATE_CTR(bnad, tso6); + } + + return 0; +} + +/* + * Initialize Q numbers depending on Rx Paths + * Called with bnad->bna_lock held, because of cfg_flags + * access. + */ +static void +bnad_q_num_init(struct bnad *bnad) +{ + int rxps; + + rxps = min((uint)num_online_cpus(), + (uint)(BNAD_MAX_RXS * BNAD_MAX_RXPS_PER_RX)); + + if (!(bnad->cfg_flags & BNAD_CF_MSIX)) + rxps = 1; /* INTx */ + + bnad->num_rx = 1; + bnad->num_tx = 1; + bnad->num_rxp_per_rx = rxps; + bnad->num_txq_per_tx = BNAD_TXQ_NUM; +} + +/* + * Adjusts the Q numbers, given a number of msix vectors + * Give preference to RSS as opposed to Tx priority Queues, + * in such a case, just use 1 Tx Q + * Called with bnad->bna_lock held b'cos of cfg_flags access + */ +static void +bnad_q_num_adjust(struct bnad *bnad, int msix_vectors) +{ + bnad->num_txq_per_tx = 1; + if ((msix_vectors >= (bnad->num_tx * bnad->num_txq_per_tx) + + bnad_rxqs_per_cq + BNAD_MAILBOX_MSIX_VECTORS) && + (bnad->cfg_flags & BNAD_CF_MSIX)) { + bnad->num_rxp_per_rx = msix_vectors - + (bnad->num_tx * bnad->num_txq_per_tx) - + BNAD_MAILBOX_MSIX_VECTORS; + } else + bnad->num_rxp_per_rx = 1; +} + +static void +bnad_set_netdev_perm_addr(struct bnad *bnad) +{ + struct net_device *netdev = bnad->netdev; + + memcpy(netdev->perm_addr, &bnad->perm_addr, netdev->addr_len); + if (is_zero_ether_addr(netdev->dev_addr)) + memcpy(netdev->dev_addr, &bnad->perm_addr, netdev->addr_len); +} + +/* Enable / disable device */ +static void +bnad_device_disable(struct bnad *bnad) +{ + unsigned long flags; + + init_completion(&bnad->bnad_completions.ioc_comp); + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_device_disable(&bnad->bna.device, BNA_HARD_CLEANUP); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + wait_for_completion(&bnad->bnad_completions.ioc_comp); + +} + +static int +bnad_device_enable(struct bnad *bnad) +{ + int err = 0; + unsigned long flags; + + init_completion(&bnad->bnad_completions.ioc_comp); + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_device_enable(&bnad->bna.device); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + wait_for_completion(&bnad->bnad_completions.ioc_comp); + + if (bnad->bnad_completions.ioc_comp_status) + err = bnad->bnad_completions.ioc_comp_status; + + return err; +} + +/* Free BNA resources */ +static void +bnad_res_free(struct bnad *bnad) +{ + int i; + struct bna_res_info *res_info = &bnad->res_info[0]; + + for (i = 0; i < BNA_RES_T_MAX; i++) { + if (res_info[i].res_type == BNA_RES_T_MEM) + bnad_mem_free(bnad, &res_info[i].res_u.mem_info); + else + bnad_mbox_irq_free(bnad, &res_info[i].res_u.intr_info); + } +} + +/* Allocates memory and interrupt resources for BNA */ +static int +bnad_res_alloc(struct bnad *bnad) +{ + int i, err; + struct bna_res_info *res_info = &bnad->res_info[0]; + + for (i = 0; i < BNA_RES_T_MAX; i++) { + if (res_info[i].res_type == BNA_RES_T_MEM) + err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info); + else + err = bnad_mbox_irq_alloc(bnad, + &res_info[i].res_u.intr_info); + if (err) + goto err_return; + } + return 0; + +err_return: + bnad_res_free(bnad); + return err; +} + +/* Interrupt enable / disable */ +static void +bnad_enable_msix(struct bnad *bnad) +{ + int i, ret; + u32 tot_msix_num; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + if (!(bnad->cfg_flags & BNAD_CF_MSIX)) { + spin_unlock_irqrestore(&bnad->bna_lock, flags); + return; + } + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + if (bnad->msix_table) + return; + + tot_msix_num = bnad->msix_num + bnad->msix_diag_num; + + bnad->msix_table = + kcalloc(tot_msix_num, sizeof(struct msix_entry), GFP_KERNEL); + + if (!bnad->msix_table) + goto intx_mode; + + for (i = 0; i < tot_msix_num; i++) + bnad->msix_table[i].entry = i; + + ret = pci_enable_msix(bnad->pcidev, bnad->msix_table, tot_msix_num); + if (ret > 0) { + /* Not enough MSI-X vectors. */ + + spin_lock_irqsave(&bnad->bna_lock, flags); + /* ret = #of vectors that we got */ + bnad_q_num_adjust(bnad, ret); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx) + + (bnad->num_rx + * bnad->num_rxp_per_rx) + + BNAD_MAILBOX_MSIX_VECTORS; + tot_msix_num = bnad->msix_num + bnad->msix_diag_num; + + /* Try once more with adjusted numbers */ + /* If this fails, fall back to INTx */ + ret = pci_enable_msix(bnad->pcidev, bnad->msix_table, + tot_msix_num); + if (ret) + goto intx_mode; + + } else if (ret < 0) + goto intx_mode; + return; + +intx_mode: + + kfree(bnad->msix_table); + bnad->msix_table = NULL; + bnad->msix_num = 0; + bnad->msix_diag_num = 0; + spin_lock_irqsave(&bnad->bna_lock, flags); + bnad->cfg_flags &= ~BNAD_CF_MSIX; + bnad_q_num_init(bnad); + spin_unlock_irqrestore(&bnad->bna_lock, flags); +} + +static void +bnad_disable_msix(struct bnad *bnad) +{ + u32 cfg_flags; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + cfg_flags = bnad->cfg_flags; + if (bnad->cfg_flags & BNAD_CF_MSIX) + bnad->cfg_flags &= ~BNAD_CF_MSIX; + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + if (cfg_flags & BNAD_CF_MSIX) { + pci_disable_msix(bnad->pcidev); + kfree(bnad->msix_table); + bnad->msix_table = NULL; + } +} + +/* Netdev entry points */ +static int +bnad_open(struct net_device *netdev) +{ + int err; + struct bnad *bnad = netdev_priv(netdev); + struct bna_pause_config pause_config; + int mtu; + unsigned long flags; + + mutex_lock(&bnad->conf_mutex); + + /* Tx */ + err = bnad_setup_tx(bnad, 0); + if (err) + goto err_return; + + /* Rx */ + err = bnad_setup_rx(bnad, 0); + if (err) + goto cleanup_tx; + + /* Port */ + pause_config.tx_pause = 0; + pause_config.rx_pause = 0; + + mtu = ETH_HLEN + bnad->netdev->mtu + ETH_FCS_LEN; + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_port_mtu_set(&bnad->bna.port, mtu, NULL); + bna_port_pause_config(&bnad->bna.port, &pause_config, NULL); + bna_port_enable(&bnad->bna.port); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + /* Enable broadcast */ + bnad_enable_default_bcast(bnad); + + /* Set the UCAST address */ + spin_lock_irqsave(&bnad->bna_lock, flags); + bnad_mac_addr_set_locked(bnad, netdev->dev_addr); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + /* Start the stats timer */ + bnad_stats_timer_start(bnad); + + mutex_unlock(&bnad->conf_mutex); + + return 0; + +cleanup_tx: + bnad_cleanup_tx(bnad, 0); + +err_return: + mutex_unlock(&bnad->conf_mutex); + return err; +} + +static int +bnad_stop(struct net_device *netdev) +{ + struct bnad *bnad = netdev_priv(netdev); + unsigned long flags; + + mutex_lock(&bnad->conf_mutex); + + /* Stop the stats timer */ + bnad_stats_timer_stop(bnad); + + init_completion(&bnad->bnad_completions.port_comp); + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_port_disable(&bnad->bna.port, BNA_HARD_CLEANUP, + bnad_cb_port_disabled); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + wait_for_completion(&bnad->bnad_completions.port_comp); + + bnad_cleanup_tx(bnad, 0); + bnad_cleanup_rx(bnad, 0); + + /* Synchronize mailbox IRQ */ + bnad_mbox_irq_sync(bnad); + + mutex_unlock(&bnad->conf_mutex); + + return 0; +} + +/* TX */ +/* + * bnad_start_xmit : Netdev entry point for Transmit + * Called under lock held by net_device + */ +static netdev_tx_t +bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct bnad *bnad = netdev_priv(netdev); + + u16 txq_prod, vlan_tag = 0; + u32 unmap_prod, wis, wis_used, wi_range; + u32 vectors, vect_id, i, acked; + u32 tx_id; + int err; + + struct bnad_tx_info *tx_info; + struct bna_tcb *tcb; + struct bnad_unmap_q *unmap_q; + dma_addr_t dma_addr; + struct bna_txq_entry *txqent; + bna_txq_wi_ctrl_flag_t flags; + + if (unlikely + (skb->len <= ETH_HLEN || skb->len > BFI_TX_MAX_DATA_PER_PKT)) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + /* + * Takes care of the Tx that is scheduled between clearing the flag + * and the netif_stop_queue() call. + */ + if (unlikely(!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + tx_id = 0; + + tx_info = &bnad->tx_info[tx_id]; + tcb = tx_info->tcb[tx_id]; + unmap_q = tcb->unmap_q; + + vectors = 1 + skb_shinfo(skb)->nr_frags; + if (vectors > BFI_TX_MAX_VECTORS_PER_PKT) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + wis = BNA_TXQ_WI_NEEDED(vectors); /* 4 vectors per work item */ + acked = 0; + if (unlikely + (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) || + vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) { + if ((u16) (*tcb->hw_consumer_index) != + tcb->consumer_index && + !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) { + acked = bnad_free_txbufs(bnad, tcb); + bna_ib_ack(tcb->i_dbell, acked); + smp_mb__before_clear_bit(); + clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags); + } else { + netif_stop_queue(netdev); + BNAD_UPDATE_CTR(bnad, netif_queue_stop); + } + + smp_mb(); + /* + * Check again to deal with race condition between + * netif_stop_queue here, and netif_wake_queue in + * interrupt handler which is not inside netif tx lock. + */ + if (likely + (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) || + vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) { + BNAD_UPDATE_CTR(bnad, netif_queue_stop); + return NETDEV_TX_BUSY; + } else { + netif_wake_queue(netdev); + BNAD_UPDATE_CTR(bnad, netif_queue_wakeup); + } + } + + unmap_prod = unmap_q->producer_index; + wis_used = 1; + vect_id = 0; + flags = 0; + + txq_prod = tcb->producer_index; + BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt, txqent, wi_range); + BUG_ON(!(wi_range <= tcb->q_depth)); + txqent->hdr.wi.reserved = 0; + txqent->hdr.wi.num_vectors = vectors; + txqent->hdr.wi.opcode = + htons((skb_is_gso(skb) ? BNA_TXQ_WI_SEND_LSO : + BNA_TXQ_WI_SEND)); + + if (bnad->vlan_grp && vlan_tx_tag_present(skb)) { + vlan_tag = (u16) vlan_tx_tag_get(skb); + flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN); + } + if (test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags)) { + vlan_tag = + (tcb->priority & 0x7) << 13 | (vlan_tag & 0x1fff); + flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN); + } + + txqent->hdr.wi.vlan_tag = htons(vlan_tag); + + if (skb_is_gso(skb)) { + err = bnad_tso_prepare(bnad, skb); + if (err) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + txqent->hdr.wi.lso_mss = htons(skb_is_gso(skb)); + flags |= (BNA_TXQ_WI_CF_IP_CKSUM | BNA_TXQ_WI_CF_TCP_CKSUM); + txqent->hdr.wi.l4_hdr_size_n_offset = + htons(BNA_TXQ_WI_L4_HDR_N_OFFSET + (tcp_hdrlen(skb) >> 2, + skb_transport_offset(skb))); + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + u8 proto = 0; + + txqent->hdr.wi.lso_mss = 0; + + if (skb->protocol == htons(ETH_P_IP)) + proto = ip_hdr(skb)->protocol; + else if (skb->protocol == htons(ETH_P_IPV6)) { + /* nexthdr may not be TCP immediately. */ + proto = ipv6_hdr(skb)->nexthdr; + } + if (proto == IPPROTO_TCP) { + flags |= BNA_TXQ_WI_CF_TCP_CKSUM; + txqent->hdr.wi.l4_hdr_size_n_offset = + htons(BNA_TXQ_WI_L4_HDR_N_OFFSET + (0, skb_transport_offset(skb))); + + BNAD_UPDATE_CTR(bnad, tcpcsum_offload); + + BUG_ON(!(skb_headlen(skb) >= + skb_transport_offset(skb) + tcp_hdrlen(skb))); + + } else if (proto == IPPROTO_UDP) { + flags |= BNA_TXQ_WI_CF_UDP_CKSUM; + txqent->hdr.wi.l4_hdr_size_n_offset = + htons(BNA_TXQ_WI_L4_HDR_N_OFFSET + (0, skb_transport_offset(skb))); + + BNAD_UPDATE_CTR(bnad, udpcsum_offload); + + BUG_ON(!(skb_headlen(skb) >= + skb_transport_offset(skb) + + sizeof(struct udphdr))); + } else { + err = skb_checksum_help(skb); + BNAD_UPDATE_CTR(bnad, csum_help); + if (err) { + dev_kfree_skb(skb); + BNAD_UPDATE_CTR(bnad, csum_help_err); + return NETDEV_TX_OK; + } + } + } else { + txqent->hdr.wi.lso_mss = 0; + txqent->hdr.wi.l4_hdr_size_n_offset = 0; + } + + txqent->hdr.wi.flags = htons(flags); + + txqent->hdr.wi.frame_length = htonl(skb->len); + + unmap_q->unmap_array[unmap_prod].skb = skb; + BUG_ON(!(skb_headlen(skb) <= BFI_TX_MAX_DATA_PER_VECTOR)); + txqent->vector[vect_id].length = htons(skb_headlen(skb)); + dma_addr = pci_map_single(bnad->pcidev, skb->data, skb_headlen(skb), + PCI_DMA_TODEVICE); + pci_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr, + dma_addr); + + BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr); + BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth); + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + u32 size = frag->size; + + if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) { + vect_id = 0; + if (--wi_range) + txqent++; + else { + BNA_QE_INDX_ADD(txq_prod, wis_used, + tcb->q_depth); + wis_used = 0; + BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt, + txqent, wi_range); + BUG_ON(!(wi_range <= tcb->q_depth)); + } + wis_used++; + txqent->hdr.wi_ext.opcode = htons(BNA_TXQ_WI_EXTENSION); + } + + BUG_ON(!(size <= BFI_TX_MAX_DATA_PER_VECTOR)); + txqent->vector[vect_id].length = htons(size); + dma_addr = + pci_map_page(bnad->pcidev, frag->page, + frag->page_offset, size, + PCI_DMA_TODEVICE); + pci_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr, + dma_addr); + BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr); + BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth); + } + + unmap_q->producer_index = unmap_prod; + BNA_QE_INDX_ADD(txq_prod, wis_used, tcb->q_depth); + tcb->producer_index = txq_prod; + + smp_mb(); + bna_txq_prod_indx_doorbell(tcb); + + if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index) + tasklet_schedule(&bnad->tx_free_tasklet); + + return NETDEV_TX_OK; +} + +/* + * Used spin_lock to synchronize reading of stats structures, which + * is written by BNA under the same lock. + */ +static struct net_device_stats * +bnad_get_netdev_stats(struct net_device *netdev) +{ + struct bnad *bnad = netdev_priv(netdev); + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + + memset(&bnad->net_stats, 0, sizeof(struct net_device_stats)); + + bnad_netdev_qstats_fill(bnad); + bnad_netdev_hwstats_fill(bnad); + + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + return &bnad->net_stats; +} + +static void +bnad_set_rx_mode(struct net_device *netdev) +{ + struct bnad *bnad = netdev_priv(netdev); + u32 new_mask, valid_mask; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + + new_mask = valid_mask = 0; + + if (netdev->flags & IFF_PROMISC) { + if (!(bnad->cfg_flags & BNAD_CF_PROMISC)) { + new_mask = BNAD_RXMODE_PROMISC_DEFAULT; + valid_mask = BNAD_RXMODE_PROMISC_DEFAULT; + bnad->cfg_flags |= BNAD_CF_PROMISC; + } + } else { + if (bnad->cfg_flags & BNAD_CF_PROMISC) { + new_mask = ~BNAD_RXMODE_PROMISC_DEFAULT; + valid_mask = BNAD_RXMODE_PROMISC_DEFAULT; + bnad->cfg_flags &= ~BNAD_CF_PROMISC; + } + } + + if (netdev->flags & IFF_ALLMULTI) { + if (!(bnad->cfg_flags & BNAD_CF_ALLMULTI)) { + new_mask |= BNA_RXMODE_ALLMULTI; + valid_mask |= BNA_RXMODE_ALLMULTI; + bnad->cfg_flags |= BNAD_CF_ALLMULTI; + } + } else { + if (bnad->cfg_flags & BNAD_CF_ALLMULTI) { + new_mask &= ~BNA_RXMODE_ALLMULTI; + valid_mask |= BNA_RXMODE_ALLMULTI; + bnad->cfg_flags &= ~BNAD_CF_ALLMULTI; + } + } + + bna_rx_mode_set(bnad->rx_info[0].rx, new_mask, valid_mask, NULL); + + if (!netdev_mc_empty(netdev)) { + u8 *mcaddr_list; + int mc_count = netdev_mc_count(netdev); + + /* Index 0 holds the broadcast address */ + mcaddr_list = + kzalloc((mc_count + 1) * ETH_ALEN, + GFP_ATOMIC); + if (!mcaddr_list) + return; + + memcpy(&mcaddr_list[0], &bnad_bcast_addr[0], ETH_ALEN); + + /* Copy rest of the MC addresses */ + bnad_netdev_mc_list_get(netdev, mcaddr_list); + + bna_rx_mcast_listset(bnad->rx_info[0].rx, mc_count + 1, + mcaddr_list, NULL); + + /* Should we enable BNAD_CF_ALLMULTI for err != 0 ? */ + kfree(mcaddr_list); + } + spin_unlock_irqrestore(&bnad->bna_lock, flags); +} + +/* + * bna_lock is used to sync writes to netdev->addr + * conf_lock cannot be used since this call may be made + * in a non-blocking context. + */ +static int +bnad_set_mac_address(struct net_device *netdev, void *mac_addr) +{ + int err; + struct bnad *bnad = netdev_priv(netdev); + struct sockaddr *sa = (struct sockaddr *)mac_addr; + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + + err = bnad_mac_addr_set_locked(bnad, sa->sa_data); + + if (!err) + memcpy(netdev->dev_addr, sa->sa_data, netdev->addr_len); + + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + return err; +} + +static int +bnad_change_mtu(struct net_device *netdev, int new_mtu) +{ + int mtu, err = 0; + unsigned long flags; + + struct bnad *bnad = netdev_priv(netdev); + + if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU) + return -EINVAL; + + mutex_lock(&bnad->conf_mutex); + + netdev->mtu = new_mtu; + + mtu = ETH_HLEN + new_mtu + ETH_FCS_LEN; + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_port_mtu_set(&bnad->bna.port, mtu, NULL); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + mutex_unlock(&bnad->conf_mutex); + return err; +} + +static void +bnad_vlan_rx_register(struct net_device *netdev, + struct vlan_group *vlan_grp) +{ + struct bnad *bnad = netdev_priv(netdev); + + mutex_lock(&bnad->conf_mutex); + bnad->vlan_grp = vlan_grp; + mutex_unlock(&bnad->conf_mutex); +} + +static void +bnad_vlan_rx_add_vid(struct net_device *netdev, + unsigned short vid) +{ + struct bnad *bnad = netdev_priv(netdev); + unsigned long flags; + + if (!bnad->rx_info[0].rx) + return; + + mutex_lock(&bnad->conf_mutex); + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_rx_vlan_add(bnad->rx_info[0].rx, vid); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + mutex_unlock(&bnad->conf_mutex); +} + +static void +bnad_vlan_rx_kill_vid(struct net_device *netdev, + unsigned short vid) +{ + struct bnad *bnad = netdev_priv(netdev); + unsigned long flags; + + if (!bnad->rx_info[0].rx) + return; + + mutex_lock(&bnad->conf_mutex); + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_rx_vlan_del(bnad->rx_info[0].rx, vid); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + mutex_unlock(&bnad->conf_mutex); +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void +bnad_netpoll(struct net_device *netdev) +{ + struct bnad *bnad = netdev_priv(netdev); + struct bnad_rx_info *rx_info; + struct bnad_rx_ctrl *rx_ctrl; + u32 curr_mask; + int i, j; + + if (!(bnad->cfg_flags & BNAD_CF_MSIX)) { + bna_intx_disable(&bnad->bna, curr_mask); + bnad_isr(bnad->pcidev->irq, netdev); + bna_intx_enable(&bnad->bna, curr_mask); + } else { + for (i = 0; i < bnad->num_rx; i++) { + rx_info = &bnad->rx_info[i]; + if (!rx_info->rx) + continue; + for (j = 0; j < bnad->num_rxp_per_rx; j++) { + rx_ctrl = &rx_info->rx_ctrl[j]; + if (rx_ctrl->ccb) { + bnad_disable_rx_irq(bnad, + rx_ctrl->ccb); + bnad_netif_rx_schedule_poll(bnad, + rx_ctrl->ccb); + } + } + } + } +} +#endif + +static const struct net_device_ops bnad_netdev_ops = { + .ndo_open = bnad_open, + .ndo_stop = bnad_stop, + .ndo_start_xmit = bnad_start_xmit, + .ndo_get_stats = bnad_get_netdev_stats, + .ndo_set_rx_mode = bnad_set_rx_mode, + .ndo_set_multicast_list = bnad_set_rx_mode, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = bnad_set_mac_address, + .ndo_change_mtu = bnad_change_mtu, + .ndo_vlan_rx_register = bnad_vlan_rx_register, + .ndo_vlan_rx_add_vid = bnad_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = bnad_vlan_rx_kill_vid, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = bnad_netpoll +#endif +}; + +static void +bnad_netdev_init(struct bnad *bnad, bool using_dac) +{ + struct net_device *netdev = bnad->netdev; + + netdev->features |= NETIF_F_IPV6_CSUM; + netdev->features |= NETIF_F_TSO; + netdev->features |= NETIF_F_TSO6; + + netdev->features |= NETIF_F_GRO; + pr_warn("bna: GRO enabled, using kernel stack GRO\n"); + + netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + + if (using_dac) + netdev->features |= NETIF_F_HIGHDMA; + + netdev->features |= + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | + NETIF_F_HW_VLAN_FILTER; + + netdev->vlan_features = netdev->features; + netdev->mem_start = bnad->mmio_start; + netdev->mem_end = bnad->mmio_start + bnad->mmio_len - 1; + + netdev->netdev_ops = &bnad_netdev_ops; + bnad_set_ethtool_ops(netdev); +} + +/* + * 1. Initialize the bnad structure + * 2. Setup netdev pointer in pci_dev + * 3. Initialze Tx free tasklet + * 4. Initialize no. of TxQ & CQs & MSIX vectors + */ +static int +bnad_init(struct bnad *bnad, + struct pci_dev *pdev, struct net_device *netdev) +{ + unsigned long flags; + + SET_NETDEV_DEV(netdev, &pdev->dev); + pci_set_drvdata(pdev, netdev); + + bnad->netdev = netdev; + bnad->pcidev = pdev; + bnad->mmio_start = pci_resource_start(pdev, 0); + bnad->mmio_len = pci_resource_len(pdev, 0); + bnad->bar0 = ioremap_nocache(bnad->mmio_start, bnad->mmio_len); + if (!bnad->bar0) { + dev_err(&pdev->dev, "ioremap for bar0 failed\n"); + pci_set_drvdata(pdev, NULL); + return -ENOMEM; + } + pr_info("bar0 mapped to %p, len %llu\n", bnad->bar0, + (unsigned long long) bnad->mmio_len); + + spin_lock_irqsave(&bnad->bna_lock, flags); + if (!bnad_msix_disable) + bnad->cfg_flags = BNAD_CF_MSIX; + + bnad->cfg_flags |= BNAD_CF_DIM_ENABLED; + + bnad_q_num_init(bnad); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx) + + (bnad->num_rx * bnad->num_rxp_per_rx) + + BNAD_MAILBOX_MSIX_VECTORS; + bnad->msix_diag_num = 2; /* 1 for Tx, 1 for Rx */ + + bnad->txq_depth = BNAD_TXQ_DEPTH; + bnad->rxq_depth = BNAD_RXQ_DEPTH; + bnad->rx_csum = true; + + bnad->tx_coalescing_timeo = BFI_TX_COALESCING_TIMEO; + bnad->rx_coalescing_timeo = BFI_RX_COALESCING_TIMEO; + + tasklet_init(&bnad->tx_free_tasklet, bnad_tx_free_tasklet, + (unsigned long)bnad); + + return 0; +} + +/* + * Must be called after bnad_pci_uninit() + * so that iounmap() and pci_set_drvdata(NULL) + * happens only after PCI uninitialization. + */ +static void +bnad_uninit(struct bnad *bnad) +{ + if (bnad->bar0) + iounmap(bnad->bar0); + pci_set_drvdata(bnad->pcidev, NULL); +} + +/* + * Initialize locks + a) Per device mutes used for serializing configuration + changes from OS interface + b) spin lock used to protect bna state machine + */ +static void +bnad_lock_init(struct bnad *bnad) +{ + spin_lock_init(&bnad->bna_lock); + mutex_init(&bnad->conf_mutex); +} + +static void +bnad_lock_uninit(struct bnad *bnad) +{ + mutex_destroy(&bnad->conf_mutex); +} + +/* PCI Initialization */ +static int +bnad_pci_init(struct bnad *bnad, + struct pci_dev *pdev, bool *using_dac) +{ + int err; + + err = pci_enable_device(pdev); + if (err) + return err; + err = pci_request_regions(pdev, BNAD_NAME); + if (err) + goto disable_device; + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && + !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { + *using_dac = 1; + } else { + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { + err = pci_set_consistent_dma_mask(pdev, + DMA_BIT_MASK(32)); + if (err) + goto release_regions; + } + *using_dac = 0; + } + pci_set_master(pdev); + return 0; + +release_regions: + pci_release_regions(pdev); +disable_device: + pci_disable_device(pdev); + + return err; +} + +static void +bnad_pci_uninit(struct pci_dev *pdev) +{ + pci_release_regions(pdev); + pci_disable_device(pdev); +} + +static int __devinit +bnad_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *pcidev_id) +{ + bool using_dac; + int err; + struct bnad *bnad; + struct bna *bna; + struct net_device *netdev; + struct bfa_pcidev pcidev_info; + unsigned long flags; + + pr_info("bnad_pci_probe : (0x%p, 0x%p) PCI Func : (%d)\n", + pdev, pcidev_id, PCI_FUNC(pdev->devfn)); + + mutex_lock(&bnad_fwimg_mutex); + if (!cna_get_firmware_buf(pdev)) { + mutex_unlock(&bnad_fwimg_mutex); + pr_warn("Failed to load Firmware Image!\n"); + return -ENODEV; + } + mutex_unlock(&bnad_fwimg_mutex); + + /* + * Allocates sizeof(struct net_device + struct bnad) + * bnad = netdev->priv + */ + netdev = alloc_etherdev(sizeof(struct bnad)); + if (!netdev) { + dev_err(&pdev->dev, "alloc_etherdev failed\n"); + err = -ENOMEM; + return err; + } + bnad = netdev_priv(netdev); + + + /* + * PCI initialization + * Output : using_dac = 1 for 64 bit DMA + * = 0 for 32 bit DMA + */ + err = bnad_pci_init(bnad, pdev, &using_dac); + if (err) + goto free_netdev; + + bnad_lock_init(bnad); + /* + * Initialize bnad structure + * Setup relation between pci_dev & netdev + * Init Tx free tasklet + */ + err = bnad_init(bnad, pdev, netdev); + if (err) + goto pci_uninit; + /* Initialize netdev structure, set up ethtool ops */ + bnad_netdev_init(bnad, using_dac); + + bnad_enable_msix(bnad); + + /* Get resource requirement form bna */ + bna_res_req(&bnad->res_info[0]); + + /* Allocate resources from bna */ + err = bnad_res_alloc(bnad); + if (err) + goto free_netdev; + + bna = &bnad->bna; + + /* Setup pcidev_info for bna_init() */ + pcidev_info.pci_slot = PCI_SLOT(bnad->pcidev->devfn); + pcidev_info.pci_func = PCI_FUNC(bnad->pcidev->devfn); + pcidev_info.device_id = bnad->pcidev->device; + pcidev_info.pci_bar_kva = bnad->bar0; + + mutex_lock(&bnad->conf_mutex); + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_init(bna, bnad, &pcidev_info, &bnad->res_info[0]); + + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + bnad->stats.bna_stats = &bna->stats; + + /* Set up timers */ + setup_timer(&bnad->bna.device.ioc.ioc_timer, bnad_ioc_timeout, + ((unsigned long)bnad)); + setup_timer(&bnad->bna.device.ioc.hb_timer, bnad_ioc_hb_check, + ((unsigned long)bnad)); + setup_timer(&bnad->bna.device.ioc.sem_timer, bnad_ioc_sem_timeout, + ((unsigned long)bnad)); + + /* Now start the timer before calling IOC */ + mod_timer(&bnad->bna.device.ioc.ioc_timer, + jiffies + msecs_to_jiffies(BNA_IOC_TIMER_FREQ)); + + /* + * Start the chip + * Don't care even if err != 0, bna state machine will + * deal with it + */ + err = bnad_device_enable(bnad); + + /* Get the burnt-in mac */ + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_port_mac_get(&bna->port, &bnad->perm_addr); + bnad_set_netdev_perm_addr(bnad); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + mutex_unlock(&bnad->conf_mutex); + + /* + * Make sure the link appears down to the stack + */ + netif_carrier_off(netdev); + + /* Finally, reguister with net_device layer */ + err = register_netdev(netdev); + if (err) { + pr_err("BNA : Registering with netdev failed\n"); + goto disable_device; + } + + return 0; + +disable_device: + mutex_lock(&bnad->conf_mutex); + bnad_device_disable(bnad); + del_timer_sync(&bnad->bna.device.ioc.ioc_timer); + del_timer_sync(&bnad->bna.device.ioc.sem_timer); + del_timer_sync(&bnad->bna.device.ioc.hb_timer); + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_uninit(bna); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + mutex_unlock(&bnad->conf_mutex); + + bnad_res_free(bnad); + bnad_disable_msix(bnad); +pci_uninit: + bnad_pci_uninit(pdev); + bnad_lock_uninit(bnad); + bnad_uninit(bnad); +free_netdev: + free_netdev(netdev); + return err; +} + +static void __devexit +bnad_pci_remove(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct bnad *bnad; + struct bna *bna; + unsigned long flags; + + if (!netdev) + return; + + pr_info("%s bnad_pci_remove\n", netdev->name); + bnad = netdev_priv(netdev); + bna = &bnad->bna; + + unregister_netdev(netdev); + + mutex_lock(&bnad->conf_mutex); + bnad_device_disable(bnad); + del_timer_sync(&bnad->bna.device.ioc.ioc_timer); + del_timer_sync(&bnad->bna.device.ioc.sem_timer); + del_timer_sync(&bnad->bna.device.ioc.hb_timer); + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_uninit(bna); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + mutex_unlock(&bnad->conf_mutex); + + bnad_res_free(bnad); + bnad_disable_msix(bnad); + bnad_pci_uninit(pdev); + bnad_lock_uninit(bnad); + bnad_uninit(bnad); + free_netdev(netdev); +} + +const struct pci_device_id bnad_pci_id_table[] = { + { + PCI_DEVICE(PCI_VENDOR_ID_BROCADE, + PCI_DEVICE_ID_BROCADE_CT), + .class = PCI_CLASS_NETWORK_ETHERNET << 8, + .class_mask = 0xffff00 + }, {0, } +}; + +MODULE_DEVICE_TABLE(pci, bnad_pci_id_table); + +static struct pci_driver bnad_pci_driver = { + .name = BNAD_NAME, + .id_table = bnad_pci_id_table, + .probe = bnad_pci_probe, + .remove = __devexit_p(bnad_pci_remove), +}; + +static int __init +bnad_module_init(void) +{ + int err; + + pr_info("Brocade 10G Ethernet driver\n"); + + bfa_ioc_auto_recover(bnad_ioc_auto_recover); + + err = pci_register_driver(&bnad_pci_driver); + if (err < 0) { + pr_err("bna : PCI registration failed in module init " + "(%d)\n", err); + return err; + } + + return 0; +} + +static void __exit +bnad_module_exit(void) +{ + pci_unregister_driver(&bnad_pci_driver); + + if (bfi_fw) + release_firmware(bfi_fw); +} + +module_init(bnad_module_init); +module_exit(bnad_module_exit); + +MODULE_AUTHOR("Brocade"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Brocade 10G PCIe Ethernet driver"); +MODULE_VERSION(BNAD_VERSION); +MODULE_FIRMWARE(CNA_FW_FILE_CT); diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h new file mode 100644 index 000000000000..3261401e35cb --- /dev/null +++ b/drivers/net/bna/bnad.h @@ -0,0 +1,334 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ +#ifndef __BNAD_H__ +#define __BNAD_H__ + +#include +#include +#include +#include +#include +#include + +/* Fix for IA64 */ +#include +#include + +#include +#include + +#include "bna.h" + +#define BNAD_TXQ_DEPTH 2048 +#define BNAD_RXQ_DEPTH 2048 + +#define BNAD_MAX_TXS 1 +#define BNAD_MAX_TXQ_PER_TX 8 /* 8 priority queues */ +#define BNAD_TXQ_NUM 1 + +#define BNAD_MAX_RXS 1 +#define BNAD_MAX_RXPS_PER_RX 16 + +/* + * Control structure pointed to ccb->ctrl, which + * determines the NAPI / LRO behavior CCB + * There is 1:1 corres. between ccb & ctrl + */ +struct bnad_rx_ctrl { + struct bna_ccb *ccb; + struct napi_struct napi; +}; + +#define BNAD_RXMODE_PROMISC_DEFAULT BNA_RXMODE_PROMISC + +#define BNAD_GET_TX_ID(_skb) (0) + +/* + * GLOBAL #defines (CONSTANTS) + */ +#define BNAD_NAME "bna" +#define BNAD_NAME_LEN 64 + +#define BNAD_VERSION "2.3.2.0" + +#define BNAD_MAILBOX_MSIX_VECTORS 1 + +#define BNAD_STATS_TIMER_FREQ 1000 /* in msecs */ +#define BNAD_DIM_TIMER_FREQ 1000 /* in msecs */ + +#define BNAD_MAX_Q_DEPTH 0x10000 +#define BNAD_MIN_Q_DEPTH 0x200 + +#define BNAD_JUMBO_MTU 9000 + +#define BNAD_NETIF_WAKE_THRESHOLD 8 + +#define BNAD_RXQ_REFILL_THRESHOLD_SHIFT 3 + +/* Bit positions for tcb->flags */ +#define BNAD_TXQ_FREE_SENT 0 + +/* Bit positions for rcb->flags */ +#define BNAD_RXQ_REFILL 0 +#define BNAD_RXQ_STARTED 1 + +/* + * DATA STRUCTURES + */ + +/* enums */ +enum bnad_intr_source { + BNAD_INTR_TX = 1, + BNAD_INTR_RX = 2 +}; + +enum bnad_link_state { + BNAD_LS_DOWN = 0, + BNAD_LS_UP = 1 +}; + +struct bnad_completion { + struct completion ioc_comp; + struct completion ucast_comp; + struct completion mcast_comp; + struct completion tx_comp; + struct completion rx_comp; + struct completion stats_comp; + struct completion port_comp; + + u8 ioc_comp_status; + u8 ucast_comp_status; + u8 mcast_comp_status; + u8 tx_comp_status; + u8 rx_comp_status; + u8 stats_comp_status; + u8 port_comp_status; +}; + +/* Tx Rx Control Stats */ +struct bnad_drv_stats { + u64 netif_queue_stop; + u64 netif_queue_wakeup; + u64 tso4; + u64 tso6; + u64 tso_err; + u64 tcpcsum_offload; + u64 udpcsum_offload; + u64 csum_help; + u64 csum_help_err; + + u64 hw_stats_updates; + u64 netif_rx_schedule; + u64 netif_rx_complete; + u64 netif_rx_dropped; + + u64 link_toggle; + u64 cee_up; + + u64 rxp_info_alloc_failed; + u64 mbox_intr_disabled; + u64 mbox_intr_enabled; + u64 tx_unmap_q_alloc_failed; + u64 rx_unmap_q_alloc_failed; + + u64 rxbuf_alloc_failed; +}; + +/* Complete driver stats */ +struct bnad_stats { + struct bnad_drv_stats drv_stats; + struct bna_stats *bna_stats; +}; + +/* Tx / Rx Resources */ +struct bnad_tx_res_info { + struct bna_res_info res_info[BNA_TX_RES_T_MAX]; +}; + +struct bnad_rx_res_info { + struct bna_res_info res_info[BNA_RX_RES_T_MAX]; +}; + +struct bnad_tx_info { + struct bna_tx *tx; /* 1:1 between tx_info & tx */ + struct bna_tcb *tcb[BNAD_MAX_TXQ_PER_TX]; +} ____cacheline_aligned; + +struct bnad_rx_info { + struct bna_rx *rx; /* 1:1 between rx_info & rx */ + + struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXPS_PER_RX]; +} ____cacheline_aligned; + +/* Unmap queues for Tx / Rx cleanup */ +struct bnad_skb_unmap { + struct sk_buff *skb; + DECLARE_PCI_UNMAP_ADDR(dma_addr) +}; + +struct bnad_unmap_q { + u32 producer_index; + u32 consumer_index; + u32 q_depth; + /* This should be the last one */ + struct bnad_skb_unmap unmap_array[1]; +}; + +/* Bit mask values for bnad->cfg_flags */ +#define BNAD_CF_DIM_ENABLED 0x01 /* DIM */ +#define BNAD_CF_PROMISC 0x02 +#define BNAD_CF_ALLMULTI 0x04 +#define BNAD_CF_MSIX 0x08 /* If in MSIx mode */ + +/* Defines for run_flags bit-mask */ +/* Set, tested & cleared using xxx_bit() functions */ +/* Values indicated bit positions */ +#define BNAD_RF_CEE_RUNNING 1 +#define BNAD_RF_HW_ERROR 2 +#define BNAD_RF_MBOX_IRQ_DISABLED 3 +#define BNAD_RF_TX_STARTED 4 +#define BNAD_RF_RX_STARTED 5 +#define BNAD_RF_DIM_TIMER_RUNNING 6 +#define BNAD_RF_STATS_TIMER_RUNNING 7 + +struct bnad { + struct net_device *netdev; + + /* Data path */ + struct bnad_tx_info tx_info[BNAD_MAX_TXS]; + struct bnad_rx_info rx_info[BNAD_MAX_RXS]; + + struct vlan_group *vlan_grp; + /* + * These q numbers are global only because + * they are used to calculate MSIx vectors. + * Actually the exact # of queues are per Tx/Rx + * object. + */ + u32 num_tx; + u32 num_rx; + u32 num_txq_per_tx; + u32 num_rxp_per_rx; + + u32 txq_depth; + u32 rxq_depth; + + u8 tx_coalescing_timeo; + u8 rx_coalescing_timeo; + + struct bna_rx_config rx_config[BNAD_MAX_RXS]; + struct bna_tx_config tx_config[BNAD_MAX_TXS]; + + u32 rx_csum; + + void __iomem *bar0; /* BAR0 address */ + + struct bna bna; + + u32 cfg_flags; + unsigned long run_flags; + + struct pci_dev *pcidev; + u64 mmio_start; + u64 mmio_len; + + u32 msix_num; + u32 msix_diag_num; + struct msix_entry *msix_table; + + struct mutex conf_mutex; + spinlock_t bna_lock ____cacheline_aligned; + + /* Timers */ + struct timer_list ioc_timer; + struct timer_list dim_timer; + struct timer_list stats_timer; + + /* Control path resources, memory & irq */ + struct bna_res_info res_info[BNA_RES_T_MAX]; + struct bnad_tx_res_info tx_res_info[BNAD_MAX_TXS]; + struct bnad_rx_res_info rx_res_info[BNAD_MAX_RXS]; + + struct bnad_completion bnad_completions; + + /* Burnt in MAC address */ + mac_t perm_addr; + + struct tasklet_struct tx_free_tasklet; + + /* Statistics */ + struct bnad_stats stats; + struct net_device_stats net_stats; + + struct bnad_diag *diag; + + char adapter_name[BNAD_NAME_LEN]; + char port_name[BNAD_NAME_LEN]; + char mbox_irq_name[BNAD_NAME_LEN]; +}; + +/* + * EXTERN VARIABLES + */ +extern struct firmware *bfi_fw; +extern u32 bnad_rxqs_per_cq; + +/* + * EXTERN PROTOTYPES + */ +extern u32 *cna_get_firmware_buf(struct pci_dev *pdev); +/* Netdev entry point prototypes */ +extern void bnad_set_ethtool_ops(struct net_device *netdev); + +/* Configuration & setup */ +extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad); +extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad); + +extern int bnad_setup_rx(struct bnad *bnad, uint rx_id); +extern int bnad_setup_tx(struct bnad *bnad, uint tx_id); +extern void bnad_cleanup_tx(struct bnad *bnad, uint tx_id); +extern void bnad_cleanup_rx(struct bnad *bnad, uint rx_id); + +/* Timer start/stop protos */ +extern void bnad_dim_timer_start(struct bnad *bnad); + +/* Statistics */ +extern void bnad_netdev_qstats_fill(struct bnad *bnad); +extern void bnad_netdev_hwstats_fill(struct bnad *bnad); + +/** + * MACROS + */ +/* To set & get the stats counters */ +#define BNAD_UPDATE_CTR(_bnad, _ctr) \ + (((_bnad)->stats.drv_stats._ctr)++) + +#define BNAD_GET_CTR(_bnad, _ctr) ((_bnad)->stats.drv_stats._ctr) + +#define bnad_enable_rx_irq_unsafe(_ccb) \ +{ \ + bna_ib_coalescing_timer_set((_ccb)->i_dbell, \ + (_ccb)->rx_coalescing_timeo); \ + bna_ib_ack((_ccb)->i_dbell, 0); \ +} + +#define bnad_dim_timer_running(_bnad) \ + (((_bnad)->cfg_flags & BNAD_CF_DIM_ENABLED) && \ + (test_bit(BNAD_RF_DIM_TIMER_RUNNING, &((_bnad)->run_flags)))) + +#endif /* __BNAD_H__ */ diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c new file mode 100644 index 000000000000..e982785b6b25 --- /dev/null +++ b/drivers/net/bna/bnad_ethtool.c @@ -0,0 +1,1282 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +#include "cna.h" + +#include +#include +#include +#include + +#include "bna.h" + +#include "bnad.h" + +#define BNAD_NUM_TXF_COUNTERS 12 +#define BNAD_NUM_RXF_COUNTERS 10 +#define BNAD_NUM_CQ_COUNTERS 3 +#define BNAD_NUM_RXQ_COUNTERS 6 +#define BNAD_NUM_TXQ_COUNTERS 5 + +#define BNAD_ETHTOOL_STATS_NUM \ + (sizeof(struct net_device_stats) / sizeof(unsigned long) + \ + sizeof(struct bnad_drv_stats) / sizeof(u64) + \ + offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64)) + +static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = { + "rx_packets", + "tx_packets", + "rx_bytes", + "tx_bytes", + "rx_errors", + "tx_errors", + "rx_dropped", + "tx_dropped", + "multicast", + "collisions", + + "rx_length_errors", + "rx_over_errors", + "rx_crc_errors", + "rx_frame_errors", + "rx_fifo_errors", + "rx_missed_errors", + + "tx_aborted_errors", + "tx_carrier_errors", + "tx_fifo_errors", + "tx_heartbeat_errors", + "tx_window_errors", + + "rx_compressed", + "tx_compressed", + + "netif_queue_stop", + "netif_queue_wakeup", + "tso4", + "tso6", + "tso_err", + "tcpcsum_offload", + "udpcsum_offload", + "csum_help", + "csum_help_err", + "hw_stats_updates", + "netif_rx_schedule", + "netif_rx_complete", + "netif_rx_dropped", + + "link_toggle", + "cee_up", + + "rxp_info_alloc_failed", + "mbox_intr_disabled", + "mbox_intr_enabled", + "tx_unmap_q_alloc_failed", + "rx_unmap_q_alloc_failed", + "rxbuf_alloc_failed", + + "mac_frame_64", + "mac_frame_65_127", + "mac_frame_128_255", + "mac_frame_256_511", + "mac_frame_512_1023", + "mac_frame_1024_1518", + "mac_frame_1518_1522", + "mac_rx_bytes", + "mac_rx_packets", + "mac_rx_fcs_error", + "mac_rx_multicast", + "mac_rx_broadcast", + "mac_rx_control_frames", + "mac_rx_pause", + "mac_rx_unknown_opcode", + "mac_rx_alignment_error", + "mac_rx_frame_length_error", + "mac_rx_code_error", + "mac_rx_carrier_sense_error", + "mac_rx_undersize", + "mac_rx_oversize", + "mac_rx_fragments", + "mac_rx_jabber", + "mac_rx_drop", + + "mac_tx_bytes", + "mac_tx_packets", + "mac_tx_multicast", + "mac_tx_broadcast", + "mac_tx_pause", + "mac_tx_deferral", + "mac_tx_excessive_deferral", + "mac_tx_single_collision", + "mac_tx_muliple_collision", + "mac_tx_late_collision", + "mac_tx_excessive_collision", + "mac_tx_total_collision", + "mac_tx_pause_honored", + "mac_tx_drop", + "mac_tx_jabber", + "mac_tx_fcs_error", + "mac_tx_control_frame", + "mac_tx_oversize", + "mac_tx_undersize", + "mac_tx_fragments", + + "bpc_tx_pause_0", + "bpc_tx_pause_1", + "bpc_tx_pause_2", + "bpc_tx_pause_3", + "bpc_tx_pause_4", + "bpc_tx_pause_5", + "bpc_tx_pause_6", + "bpc_tx_pause_7", + "bpc_tx_zero_pause_0", + "bpc_tx_zero_pause_1", + "bpc_tx_zero_pause_2", + "bpc_tx_zero_pause_3", + "bpc_tx_zero_pause_4", + "bpc_tx_zero_pause_5", + "bpc_tx_zero_pause_6", + "bpc_tx_zero_pause_7", + "bpc_tx_first_pause_0", + "bpc_tx_first_pause_1", + "bpc_tx_first_pause_2", + "bpc_tx_first_pause_3", + "bpc_tx_first_pause_4", + "bpc_tx_first_pause_5", + "bpc_tx_first_pause_6", + "bpc_tx_first_pause_7", + + "bpc_rx_pause_0", + "bpc_rx_pause_1", + "bpc_rx_pause_2", + "bpc_rx_pause_3", + "bpc_rx_pause_4", + "bpc_rx_pause_5", + "bpc_rx_pause_6", + "bpc_rx_pause_7", + "bpc_rx_zero_pause_0", + "bpc_rx_zero_pause_1", + "bpc_rx_zero_pause_2", + "bpc_rx_zero_pause_3", + "bpc_rx_zero_pause_4", + "bpc_rx_zero_pause_5", + "bpc_rx_zero_pause_6", + "bpc_rx_zero_pause_7", + "bpc_rx_first_pause_0", + "bpc_rx_first_pause_1", + "bpc_rx_first_pause_2", + "bpc_rx_first_pause_3", + "bpc_rx_first_pause_4", + "bpc_rx_first_pause_5", + "bpc_rx_first_pause_6", + "bpc_rx_first_pause_7", + + "rad_rx_frames", + "rad_rx_octets", + "rad_rx_vlan_frames", + "rad_rx_ucast", + "rad_rx_ucast_octets", + "rad_rx_ucast_vlan", + "rad_rx_mcast", + "rad_rx_mcast_octets", + "rad_rx_mcast_vlan", + "rad_rx_bcast", + "rad_rx_bcast_octets", + "rad_rx_bcast_vlan", + "rad_rx_drops", + + "fc_rx_ucast_octets", + "fc_rx_ucast", + "fc_rx_ucast_vlan", + "fc_rx_mcast_octets", + "fc_rx_mcast", + "fc_rx_mcast_vlan", + "fc_rx_bcast_octets", + "fc_rx_bcast", + "fc_rx_bcast_vlan", + + "fc_tx_ucast_octets", + "fc_tx_ucast", + "fc_tx_ucast_vlan", + "fc_tx_mcast_octets", + "fc_tx_mcast", + "fc_tx_mcast_vlan", + "fc_tx_bcast_octets", + "fc_tx_bcast", + "fc_tx_bcast_vlan", + "fc_tx_parity_errors", + "fc_tx_timeout", + "fc_tx_fid_parity_errors", +}; + +static int +bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) +{ + cmd->supported = SUPPORTED_10000baseT_Full; + cmd->advertising = ADVERTISED_10000baseT_Full; + cmd->autoneg = AUTONEG_DISABLE; + cmd->supported |= SUPPORTED_FIBRE; + cmd->advertising |= ADVERTISED_FIBRE; + cmd->port = PORT_FIBRE; + cmd->phy_address = 0; + + if (netif_carrier_ok(netdev)) { + cmd->speed = SPEED_10000; + cmd->duplex = DUPLEX_FULL; + } else { + cmd->speed = -1; + cmd->duplex = -1; + } + cmd->transceiver = XCVR_EXTERNAL; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; + + return 0; +} + +static int +bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) +{ + /* 10G full duplex setting supported only */ + if (cmd->autoneg == AUTONEG_ENABLE) + return -EOPNOTSUPP; else { + if ((cmd->speed == SPEED_10000) && (cmd->duplex == DUPLEX_FULL)) + return 0; + } + + return -EOPNOTSUPP; +} + +static void +bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) +{ + struct bnad *bnad = netdev_priv(netdev); + struct bfa_ioc_attr *ioc_attr; + unsigned long flags; + + strcpy(drvinfo->driver, BNAD_NAME); + strcpy(drvinfo->version, BNAD_VERSION); + + ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL); + if (ioc_attr) { + memset(ioc_attr, 0, sizeof(*ioc_attr)); + spin_lock_irqsave(&bnad->bna_lock, flags); + bfa_ioc_get_attr(&bnad->bna.device.ioc, ioc_attr); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + strncpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver, + sizeof(drvinfo->fw_version) - 1); + kfree(ioc_attr); + } + + strncpy(drvinfo->bus_info, pci_name(bnad->pcidev), ETHTOOL_BUSINFO_LEN); +} + +static int +get_regs(struct bnad *bnad, u32 * regs) +{ + int num = 0, i; + u32 reg_addr; + unsigned long flags; + +#define BNAD_GET_REG(addr) \ +do { \ + if (regs) \ + regs[num++] = readl(bnad->bar0 + (addr)); \ + else \ + num++; \ +} while (0) + + spin_lock_irqsave(&bnad->bna_lock, flags); + + /* DMA Block Internal Registers */ + BNAD_GET_REG(DMA_CTRL_REG0); + BNAD_GET_REG(DMA_CTRL_REG1); + BNAD_GET_REG(DMA_ERR_INT_STATUS); + BNAD_GET_REG(DMA_ERR_INT_ENABLE); + BNAD_GET_REG(DMA_ERR_INT_STATUS_SET); + + /* APP Block Register Address Offset from BAR0 */ + BNAD_GET_REG(HOSTFN0_INT_STATUS); + BNAD_GET_REG(HOSTFN0_INT_MASK); + BNAD_GET_REG(HOST_PAGE_NUM_FN0); + BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN0); + BNAD_GET_REG(FN0_PCIE_ERR_REG); + BNAD_GET_REG(FN0_ERR_TYPE_STATUS_REG); + BNAD_GET_REG(FN0_ERR_TYPE_MSK_STATUS_REG); + + BNAD_GET_REG(HOSTFN1_INT_STATUS); + BNAD_GET_REG(HOSTFN1_INT_MASK); + BNAD_GET_REG(HOST_PAGE_NUM_FN1); + BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN1); + BNAD_GET_REG(FN1_PCIE_ERR_REG); + BNAD_GET_REG(FN1_ERR_TYPE_STATUS_REG); + BNAD_GET_REG(FN1_ERR_TYPE_MSK_STATUS_REG); + + BNAD_GET_REG(PCIE_MISC_REG); + + BNAD_GET_REG(HOST_SEM0_REG); + BNAD_GET_REG(HOST_SEM1_REG); + BNAD_GET_REG(HOST_SEM2_REG); + BNAD_GET_REG(HOST_SEM3_REG); + BNAD_GET_REG(HOST_SEM0_INFO_REG); + BNAD_GET_REG(HOST_SEM1_INFO_REG); + BNAD_GET_REG(HOST_SEM2_INFO_REG); + BNAD_GET_REG(HOST_SEM3_INFO_REG); + + BNAD_GET_REG(TEMPSENSE_CNTL_REG); + BNAD_GET_REG(TEMPSENSE_STAT_REG); + + BNAD_GET_REG(APP_LOCAL_ERR_STAT); + BNAD_GET_REG(APP_LOCAL_ERR_MSK); + + BNAD_GET_REG(PCIE_LNK_ERR_STAT); + BNAD_GET_REG(PCIE_LNK_ERR_MSK); + + BNAD_GET_REG(FCOE_FIP_ETH_TYPE); + BNAD_GET_REG(RESV_ETH_TYPE); + + BNAD_GET_REG(HOSTFN2_INT_STATUS); + BNAD_GET_REG(HOSTFN2_INT_MASK); + BNAD_GET_REG(HOST_PAGE_NUM_FN2); + BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN2); + BNAD_GET_REG(FN2_PCIE_ERR_REG); + BNAD_GET_REG(FN2_ERR_TYPE_STATUS_REG); + BNAD_GET_REG(FN2_ERR_TYPE_MSK_STATUS_REG); + + BNAD_GET_REG(HOSTFN3_INT_STATUS); + BNAD_GET_REG(HOSTFN3_INT_MASK); + BNAD_GET_REG(HOST_PAGE_NUM_FN3); + BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN3); + BNAD_GET_REG(FN3_PCIE_ERR_REG); + BNAD_GET_REG(FN3_ERR_TYPE_STATUS_REG); + BNAD_GET_REG(FN3_ERR_TYPE_MSK_STATUS_REG); + + /* Host Command Status Registers */ + reg_addr = HOST_CMDSTS0_CLR_REG; + for (i = 0; i < 16; i++) { + BNAD_GET_REG(reg_addr); + BNAD_GET_REG(reg_addr + 4); + BNAD_GET_REG(reg_addr + 8); + reg_addr += 0x10; + } + + /* Function ID register */ + BNAD_GET_REG(FNC_ID_REG); + + /* Function personality register */ + BNAD_GET_REG(FNC_PERS_REG); + + /* Operation mode register */ + BNAD_GET_REG(OP_MODE); + + /* LPU0 Registers */ + BNAD_GET_REG(LPU0_MBOX_CTL_REG); + BNAD_GET_REG(LPU0_MBOX_CMD_REG); + BNAD_GET_REG(LPU0_MBOX_LINK_0REG); + BNAD_GET_REG(LPU1_MBOX_LINK_0REG); + BNAD_GET_REG(LPU0_MBOX_STATUS_0REG); + BNAD_GET_REG(LPU1_MBOX_STATUS_0REG); + BNAD_GET_REG(LPU0_ERR_STATUS_REG); + BNAD_GET_REG(LPU0_ERR_SET_REG); + + /* LPU1 Registers */ + BNAD_GET_REG(LPU1_MBOX_CTL_REG); + BNAD_GET_REG(LPU1_MBOX_CMD_REG); + BNAD_GET_REG(LPU0_MBOX_LINK_1REG); + BNAD_GET_REG(LPU1_MBOX_LINK_1REG); + BNAD_GET_REG(LPU0_MBOX_STATUS_1REG); + BNAD_GET_REG(LPU1_MBOX_STATUS_1REG); + BNAD_GET_REG(LPU1_ERR_STATUS_REG); + BNAD_GET_REG(LPU1_ERR_SET_REG); + + /* PSS Registers */ + BNAD_GET_REG(PSS_CTL_REG); + BNAD_GET_REG(PSS_ERR_STATUS_REG); + BNAD_GET_REG(ERR_STATUS_SET); + BNAD_GET_REG(PSS_RAM_ERR_STATUS_REG); + + /* Catapult CPQ Registers */ + BNAD_GET_REG(HOSTFN0_LPU0_MBOX0_CMD_STAT); + BNAD_GET_REG(HOSTFN0_LPU1_MBOX0_CMD_STAT); + BNAD_GET_REG(LPU0_HOSTFN0_MBOX0_CMD_STAT); + BNAD_GET_REG(LPU1_HOSTFN0_MBOX0_CMD_STAT); + + BNAD_GET_REG(HOSTFN0_LPU0_MBOX1_CMD_STAT); + BNAD_GET_REG(HOSTFN0_LPU1_MBOX1_CMD_STAT); + BNAD_GET_REG(LPU0_HOSTFN0_MBOX1_CMD_STAT); + BNAD_GET_REG(LPU1_HOSTFN0_MBOX1_CMD_STAT); + + BNAD_GET_REG(HOSTFN1_LPU0_MBOX0_CMD_STAT); + BNAD_GET_REG(HOSTFN1_LPU1_MBOX0_CMD_STAT); + BNAD_GET_REG(LPU0_HOSTFN1_MBOX0_CMD_STAT); + BNAD_GET_REG(LPU1_HOSTFN1_MBOX0_CMD_STAT); + + BNAD_GET_REG(HOSTFN1_LPU0_MBOX1_CMD_STAT); + BNAD_GET_REG(HOSTFN1_LPU1_MBOX1_CMD_STAT); + BNAD_GET_REG(LPU0_HOSTFN1_MBOX1_CMD_STAT); + BNAD_GET_REG(LPU1_HOSTFN1_MBOX1_CMD_STAT); + + BNAD_GET_REG(HOSTFN2_LPU0_MBOX0_CMD_STAT); + BNAD_GET_REG(HOSTFN2_LPU1_MBOX0_CMD_STAT); + BNAD_GET_REG(LPU0_HOSTFN2_MBOX0_CMD_STAT); + BNAD_GET_REG(LPU1_HOSTFN2_MBOX0_CMD_STAT); + + BNAD_GET_REG(HOSTFN2_LPU0_MBOX1_CMD_STAT); + BNAD_GET_REG(HOSTFN2_LPU1_MBOX1_CMD_STAT); + BNAD_GET_REG(LPU0_HOSTFN2_MBOX1_CMD_STAT); + BNAD_GET_REG(LPU1_HOSTFN2_MBOX1_CMD_STAT); + + BNAD_GET_REG(HOSTFN3_LPU0_MBOX0_CMD_STAT); + BNAD_GET_REG(HOSTFN3_LPU1_MBOX0_CMD_STAT); + BNAD_GET_REG(LPU0_HOSTFN3_MBOX0_CMD_STAT); + BNAD_GET_REG(LPU1_HOSTFN3_MBOX0_CMD_STAT); + + BNAD_GET_REG(HOSTFN3_LPU0_MBOX1_CMD_STAT); + BNAD_GET_REG(HOSTFN3_LPU1_MBOX1_CMD_STAT); + BNAD_GET_REG(LPU0_HOSTFN3_MBOX1_CMD_STAT); + BNAD_GET_REG(LPU1_HOSTFN3_MBOX1_CMD_STAT); + + /* Host Function Force Parity Error Registers */ + BNAD_GET_REG(HOSTFN0_LPU_FORCE_PERR); + BNAD_GET_REG(HOSTFN1_LPU_FORCE_PERR); + BNAD_GET_REG(HOSTFN2_LPU_FORCE_PERR); + BNAD_GET_REG(HOSTFN3_LPU_FORCE_PERR); + + /* LL Port[0|1] Halt Mask Registers */ + BNAD_GET_REG(LL_HALT_MSK_P0); + BNAD_GET_REG(LL_HALT_MSK_P1); + + /* LL Port[0|1] Error Mask Registers */ + BNAD_GET_REG(LL_ERR_MSK_P0); + BNAD_GET_REG(LL_ERR_MSK_P1); + + /* EMC FLI Registers */ + BNAD_GET_REG(FLI_CMD_REG); + BNAD_GET_REG(FLI_ADDR_REG); + BNAD_GET_REG(FLI_CTL_REG); + BNAD_GET_REG(FLI_WRDATA_REG); + BNAD_GET_REG(FLI_RDDATA_REG); + BNAD_GET_REG(FLI_DEV_STATUS_REG); + BNAD_GET_REG(FLI_SIG_WD_REG); + + BNAD_GET_REG(FLI_DEV_VENDOR_REG); + BNAD_GET_REG(FLI_ERR_STATUS_REG); + + /* RxAdm 0 Registers */ + BNAD_GET_REG(RAD0_CTL_REG); + BNAD_GET_REG(RAD0_PE_PARM_REG); + BNAD_GET_REG(RAD0_BCN_REG); + BNAD_GET_REG(RAD0_DEFAULT_REG); + BNAD_GET_REG(RAD0_PROMISC_REG); + BNAD_GET_REG(RAD0_BCNQ_REG); + BNAD_GET_REG(RAD0_DEFAULTQ_REG); + + BNAD_GET_REG(RAD0_ERR_STS); + BNAD_GET_REG(RAD0_SET_ERR_STS); + BNAD_GET_REG(RAD0_ERR_INT_EN); + BNAD_GET_REG(RAD0_FIRST_ERR); + BNAD_GET_REG(RAD0_FORCE_ERR); + + BNAD_GET_REG(RAD0_MAC_MAN_1H); + BNAD_GET_REG(RAD0_MAC_MAN_1L); + BNAD_GET_REG(RAD0_MAC_MAN_2H); + BNAD_GET_REG(RAD0_MAC_MAN_2L); + BNAD_GET_REG(RAD0_MAC_MAN_3H); + BNAD_GET_REG(RAD0_MAC_MAN_3L); + BNAD_GET_REG(RAD0_MAC_MAN_4H); + BNAD_GET_REG(RAD0_MAC_MAN_4L); + + BNAD_GET_REG(RAD0_LAST4_IP); + + /* RxAdm 1 Registers */ + BNAD_GET_REG(RAD1_CTL_REG); + BNAD_GET_REG(RAD1_PE_PARM_REG); + BNAD_GET_REG(RAD1_BCN_REG); + BNAD_GET_REG(RAD1_DEFAULT_REG); + BNAD_GET_REG(RAD1_PROMISC_REG); + BNAD_GET_REG(RAD1_BCNQ_REG); + BNAD_GET_REG(RAD1_DEFAULTQ_REG); + + BNAD_GET_REG(RAD1_ERR_STS); + BNAD_GET_REG(RAD1_SET_ERR_STS); + BNAD_GET_REG(RAD1_ERR_INT_EN); + + /* TxA0 Registers */ + BNAD_GET_REG(TXA0_CTRL_REG); + /* TxA0 TSO Sequence # Registers (RO) */ + for (i = 0; i < 8; i++) { + BNAD_GET_REG(TXA0_TSO_TCP_SEQ_REG(i)); + BNAD_GET_REG(TXA0_TSO_IP_INFO_REG(i)); + } + + /* TxA1 Registers */ + BNAD_GET_REG(TXA1_CTRL_REG); + /* TxA1 TSO Sequence # Registers (RO) */ + for (i = 0; i < 8; i++) { + BNAD_GET_REG(TXA1_TSO_TCP_SEQ_REG(i)); + BNAD_GET_REG(TXA1_TSO_IP_INFO_REG(i)); + } + + /* RxA Registers */ + BNAD_GET_REG(RXA0_CTL_REG); + BNAD_GET_REG(RXA1_CTL_REG); + + /* PLB0 Registers */ + BNAD_GET_REG(PLB0_ECM_TIMER_REG); + BNAD_GET_REG(PLB0_RL_CTL); + for (i = 0; i < 8; i++) + BNAD_GET_REG(PLB0_RL_MAX_BC(i)); + BNAD_GET_REG(PLB0_RL_TU_PRIO); + for (i = 0; i < 8; i++) + BNAD_GET_REG(PLB0_RL_BYTE_CNT(i)); + BNAD_GET_REG(PLB0_RL_MIN_REG); + BNAD_GET_REG(PLB0_RL_MAX_REG); + BNAD_GET_REG(PLB0_EMS_ADD_REG); + + /* PLB1 Registers */ + BNAD_GET_REG(PLB1_ECM_TIMER_REG); + BNAD_GET_REG(PLB1_RL_CTL); + for (i = 0; i < 8; i++) + BNAD_GET_REG(PLB1_RL_MAX_BC(i)); + BNAD_GET_REG(PLB1_RL_TU_PRIO); + for (i = 0; i < 8; i++) + BNAD_GET_REG(PLB1_RL_BYTE_CNT(i)); + BNAD_GET_REG(PLB1_RL_MIN_REG); + BNAD_GET_REG(PLB1_RL_MAX_REG); + BNAD_GET_REG(PLB1_EMS_ADD_REG); + + /* HQM Control Register */ + BNAD_GET_REG(HQM0_CTL_REG); + BNAD_GET_REG(HQM0_RXQ_STOP_SEM); + BNAD_GET_REG(HQM0_TXQ_STOP_SEM); + BNAD_GET_REG(HQM1_CTL_REG); + BNAD_GET_REG(HQM1_RXQ_STOP_SEM); + BNAD_GET_REG(HQM1_TXQ_STOP_SEM); + + /* LUT Registers */ + BNAD_GET_REG(LUT0_ERR_STS); + BNAD_GET_REG(LUT0_SET_ERR_STS); + BNAD_GET_REG(LUT1_ERR_STS); + BNAD_GET_REG(LUT1_SET_ERR_STS); + + /* TRC Registers */ + BNAD_GET_REG(TRC_CTL_REG); + BNAD_GET_REG(TRC_MODS_REG); + BNAD_GET_REG(TRC_TRGC_REG); + BNAD_GET_REG(TRC_CNT1_REG); + BNAD_GET_REG(TRC_CNT2_REG); + BNAD_GET_REG(TRC_NXTS_REG); + BNAD_GET_REG(TRC_DIRR_REG); + for (i = 0; i < 10; i++) + BNAD_GET_REG(TRC_TRGM_REG(i)); + for (i = 0; i < 10; i++) + BNAD_GET_REG(TRC_NXTM_REG(i)); + for (i = 0; i < 10; i++) + BNAD_GET_REG(TRC_STRM_REG(i)); + + spin_unlock_irqrestore(&bnad->bna_lock, flags); +#undef BNAD_GET_REG + return num; +} +static int +bnad_get_regs_len(struct net_device *netdev) +{ + int ret = get_regs(netdev_priv(netdev), NULL) * sizeof(u32); + return ret; +} + +static void +bnad_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf) +{ + memset(buf, 0, bnad_get_regs_len(netdev)); + get_regs(netdev_priv(netdev), buf); +} + +static void +bnad_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo) +{ + wolinfo->supported = 0; + wolinfo->wolopts = 0; +} + +static int +bnad_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +{ + struct bnad *bnad = netdev_priv(netdev); + unsigned long flags; + + /* Lock rqd. to access bnad->bna_lock */ + spin_lock_irqsave(&bnad->bna_lock, flags); + coalesce->use_adaptive_rx_coalesce = + (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) ? true : false; + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + coalesce->rx_coalesce_usecs = bnad->rx_coalescing_timeo * + BFI_COALESCING_TIMER_UNIT; + coalesce->tx_coalesce_usecs = bnad->tx_coalescing_timeo * + BFI_COALESCING_TIMER_UNIT; + coalesce->tx_max_coalesced_frames = BFI_TX_INTERPKT_COUNT; + + return 0; +} + +static int +bnad_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +{ + struct bnad *bnad = netdev_priv(netdev); + unsigned long flags; + int dim_timer_del = 0; + + if (coalesce->rx_coalesce_usecs == 0 || + coalesce->rx_coalesce_usecs > + BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT) + return -EINVAL; + + if (coalesce->tx_coalesce_usecs == 0 || + coalesce->tx_coalesce_usecs > + BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT) + return -EINVAL; + + mutex_lock(&bnad->conf_mutex); + /* + * Do not need to store rx_coalesce_usecs here + * Every time DIM is disabled, we can get it from the + * stack. + */ + spin_lock_irqsave(&bnad->bna_lock, flags); + if (coalesce->use_adaptive_rx_coalesce) { + if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED)) { + bnad->cfg_flags |= BNAD_CF_DIM_ENABLED; + bnad_dim_timer_start(bnad); + } + } else { + if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) { + bnad->cfg_flags &= ~BNAD_CF_DIM_ENABLED; + dim_timer_del = bnad_dim_timer_running(bnad); + if (dim_timer_del) { + clear_bit(BNAD_RF_DIM_TIMER_RUNNING, + &bnad->run_flags); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + del_timer_sync(&bnad->dim_timer); + spin_lock_irqsave(&bnad->bna_lock, flags); + } + bnad_rx_coalescing_timeo_set(bnad); + } + } + if (bnad->tx_coalescing_timeo != coalesce->tx_coalesce_usecs / + BFI_COALESCING_TIMER_UNIT) { + bnad->tx_coalescing_timeo = coalesce->tx_coalesce_usecs / + BFI_COALESCING_TIMER_UNIT; + bnad_tx_coalescing_timeo_set(bnad); + } + + if (bnad->rx_coalescing_timeo != coalesce->rx_coalesce_usecs / + BFI_COALESCING_TIMER_UNIT) { + bnad->rx_coalescing_timeo = coalesce->rx_coalesce_usecs / + BFI_COALESCING_TIMER_UNIT; + + if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED)) + bnad_rx_coalescing_timeo_set(bnad); + + } + + /* Add Tx Inter-pkt DMA count? */ + + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + mutex_unlock(&bnad->conf_mutex); + return 0; +} + +static void +bnad_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ringparam) +{ + struct bnad *bnad = netdev_priv(netdev); + + ringparam->rx_max_pending = BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq; + ringparam->rx_mini_max_pending = 0; + ringparam->rx_jumbo_max_pending = 0; + ringparam->tx_max_pending = BNAD_MAX_Q_DEPTH; + + ringparam->rx_pending = bnad->rxq_depth; + ringparam->rx_mini_max_pending = 0; + ringparam->rx_jumbo_max_pending = 0; + ringparam->tx_pending = bnad->txq_depth; +} + +static int +bnad_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ringparam) +{ + int i, current_err, err = 0; + struct bnad *bnad = netdev_priv(netdev); + + mutex_lock(&bnad->conf_mutex); + if (ringparam->rx_pending == bnad->rxq_depth && + ringparam->tx_pending == bnad->txq_depth) { + mutex_unlock(&bnad->conf_mutex); + return 0; + } + + if (ringparam->rx_pending < BNAD_MIN_Q_DEPTH || + ringparam->rx_pending > BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq || + !BNA_POWER_OF_2(ringparam->rx_pending)) { + mutex_unlock(&bnad->conf_mutex); + return -EINVAL; + } + if (ringparam->tx_pending < BNAD_MIN_Q_DEPTH || + ringparam->tx_pending > BNAD_MAX_Q_DEPTH || + !BNA_POWER_OF_2(ringparam->tx_pending)) { + mutex_unlock(&bnad->conf_mutex); + return -EINVAL; + } + + if (ringparam->rx_pending != bnad->rxq_depth) { + bnad->rxq_depth = ringparam->rx_pending; + for (i = 0; i < bnad->num_rx; i++) { + if (!bnad->rx_info[i].rx) + continue; + bnad_cleanup_rx(bnad, i); + current_err = bnad_setup_rx(bnad, i); + if (current_err && !err) + err = current_err; + } + } + if (ringparam->tx_pending != bnad->txq_depth) { + bnad->txq_depth = ringparam->tx_pending; + for (i = 0; i < bnad->num_tx; i++) { + if (!bnad->tx_info[i].tx) + continue; + bnad_cleanup_tx(bnad, i); + current_err = bnad_setup_tx(bnad, i); + if (current_err && !err) + err = current_err; + } + } + + mutex_unlock(&bnad->conf_mutex); + return err; +} + +static void +bnad_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pauseparam) +{ + struct bnad *bnad = netdev_priv(netdev); + + pauseparam->autoneg = 0; + pauseparam->rx_pause = bnad->bna.port.pause_config.rx_pause; + pauseparam->tx_pause = bnad->bna.port.pause_config.tx_pause; +} + +static int +bnad_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pauseparam) +{ + struct bnad *bnad = netdev_priv(netdev); + struct bna_pause_config pause_config; + unsigned long flags; + + if (pauseparam->autoneg == AUTONEG_ENABLE) + return -EINVAL; + + mutex_lock(&bnad->conf_mutex); + if (pauseparam->rx_pause != bnad->bna.port.pause_config.rx_pause || + pauseparam->tx_pause != bnad->bna.port.pause_config.tx_pause) { + pause_config.rx_pause = pauseparam->rx_pause; + pause_config.tx_pause = pauseparam->tx_pause; + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_port_pause_config(&bnad->bna.port, &pause_config, NULL); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + } + mutex_unlock(&bnad->conf_mutex); + return 0; +} + +static u32 +bnad_get_rx_csum(struct net_device *netdev) +{ + u32 rx_csum; + struct bnad *bnad = netdev_priv(netdev); + + rx_csum = bnad->rx_csum; + return rx_csum; +} + +static int +bnad_set_rx_csum(struct net_device *netdev, u32 rx_csum) +{ + struct bnad *bnad = netdev_priv(netdev); + + mutex_lock(&bnad->conf_mutex); + bnad->rx_csum = rx_csum; + mutex_unlock(&bnad->conf_mutex); + return 0; +} + +static int +bnad_set_tx_csum(struct net_device *netdev, u32 tx_csum) +{ + struct bnad *bnad = netdev_priv(netdev); + + mutex_lock(&bnad->conf_mutex); + if (tx_csum) { + netdev->features |= NETIF_F_IP_CSUM; + netdev->features |= NETIF_F_IPV6_CSUM; + } else { + netdev->features &= ~NETIF_F_IP_CSUM; + netdev->features &= ~NETIF_F_IPV6_CSUM; + } + mutex_unlock(&bnad->conf_mutex); + return 0; +} + +static int +bnad_set_tso(struct net_device *netdev, u32 tso) +{ + struct bnad *bnad = netdev_priv(netdev); + + mutex_lock(&bnad->conf_mutex); + if (tso) { + netdev->features |= NETIF_F_TSO; + netdev->features |= NETIF_F_TSO6; + } else { + netdev->features &= ~NETIF_F_TSO; + netdev->features &= ~NETIF_F_TSO6; + } + mutex_unlock(&bnad->conf_mutex); + return 0; +} + +static void +bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string) +{ + struct bnad *bnad = netdev_priv(netdev); + int i, j, q_num; + u64 bmap; + + mutex_lock(&bnad->conf_mutex); + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < BNAD_ETHTOOL_STATS_NUM; i++) { + BUG_ON(!(strlen(bnad_net_stats_strings[i]) < + ETH_GSTRING_LEN)); + memcpy(string, bnad_net_stats_strings[i], + ETH_GSTRING_LEN); + string += ETH_GSTRING_LEN; + } + bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] | + ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32); + for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) { + if (bmap & 1) { + sprintf(string, "txf%d_ucast_octets", i); + string += ETH_GSTRING_LEN; + sprintf(string, "txf%d_ucast", i); + string += ETH_GSTRING_LEN; + sprintf(string, "txf%d_ucast_vlan", i); + string += ETH_GSTRING_LEN; + sprintf(string, "txf%d_mcast_octets", i); + string += ETH_GSTRING_LEN; + sprintf(string, "txf%d_mcast", i); + string += ETH_GSTRING_LEN; + sprintf(string, "txf%d_mcast_vlan", i); + string += ETH_GSTRING_LEN; + sprintf(string, "txf%d_bcast_octets", i); + string += ETH_GSTRING_LEN; + sprintf(string, "txf%d_bcast", i); + string += ETH_GSTRING_LEN; + sprintf(string, "txf%d_bcast_vlan", i); + string += ETH_GSTRING_LEN; + sprintf(string, "txf%d_errors", i); + string += ETH_GSTRING_LEN; + sprintf(string, "txf%d_filter_vlan", i); + string += ETH_GSTRING_LEN; + sprintf(string, "txf%d_filter_mac_sa", i); + string += ETH_GSTRING_LEN; + } + bmap >>= 1; + } + + bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] | + ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32); + for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) { + if (bmap & 1) { + sprintf(string, "rxf%d_ucast_octets", i); + string += ETH_GSTRING_LEN; + sprintf(string, "rxf%d_ucast", i); + string += ETH_GSTRING_LEN; + sprintf(string, "rxf%d_ucast_vlan", i); + string += ETH_GSTRING_LEN; + sprintf(string, "rxf%d_mcast_octets", i); + string += ETH_GSTRING_LEN; + sprintf(string, "rxf%d_mcast", i); + string += ETH_GSTRING_LEN; + sprintf(string, "rxf%d_mcast_vlan", i); + string += ETH_GSTRING_LEN; + sprintf(string, "rxf%d_bcast_octets", i); + string += ETH_GSTRING_LEN; + sprintf(string, "rxf%d_bcast", i); + string += ETH_GSTRING_LEN; + sprintf(string, "rxf%d_bcast_vlan", i); + string += ETH_GSTRING_LEN; + sprintf(string, "rxf%d_frame_drops", i); + string += ETH_GSTRING_LEN; + } + bmap >>= 1; + } + + q_num = 0; + for (i = 0; i < bnad->num_rx; i++) { + if (!bnad->rx_info[i].rx) + continue; + for (j = 0; j < bnad->num_rxp_per_rx; j++) { + sprintf(string, "cq%d_producer_index", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "cq%d_consumer_index", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "cq%d_hw_producer_index", + q_num); + string += ETH_GSTRING_LEN; + q_num++; + } + } + + q_num = 0; + for (i = 0; i < bnad->num_rx; i++) { + if (!bnad->rx_info[i].rx) + continue; + for (j = 0; j < bnad->num_rxp_per_rx; j++) { + sprintf(string, "rxq%d_packets", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "rxq%d_bytes", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "rxq%d_packets_with_error", + q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "rxq%d_allocbuf_failed", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "rxq%d_producer_index", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "rxq%d_consumer_index", q_num); + string += ETH_GSTRING_LEN; + q_num++; + if (bnad->rx_info[i].rx_ctrl[j].ccb && + bnad->rx_info[i].rx_ctrl[j].ccb-> + rcb[1] && + bnad->rx_info[i].rx_ctrl[j].ccb-> + rcb[1]->rxq) { + sprintf(string, "rxq%d_packets", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "rxq%d_bytes", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, + "rxq%d_packets_with_error", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "rxq%d_allocbuf_failed", + q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "rxq%d_producer_index", + q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "rxq%d_consumer_index", + q_num); + string += ETH_GSTRING_LEN; + q_num++; + } + } + } + + q_num = 0; + for (i = 0; i < bnad->num_tx; i++) { + if (!bnad->tx_info[i].tx) + continue; + for (j = 0; j < bnad->num_txq_per_tx; j++) { + sprintf(string, "txq%d_packets", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "txq%d_bytes", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "txq%d_producer_index", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "txq%d_consumer_index", q_num); + string += ETH_GSTRING_LEN; + sprintf(string, "txq%d_hw_consumer_index", + q_num); + string += ETH_GSTRING_LEN; + q_num++; + } + } + + break; + + default: + break; + } + + mutex_unlock(&bnad->conf_mutex); +} + +static int +bnad_get_stats_count_locked(struct net_device *netdev) +{ + struct bnad *bnad = netdev_priv(netdev); + int i, j, count, rxf_active_num = 0, txf_active_num = 0; + u64 bmap; + + bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] | + ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32); + for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) { + if (bmap & 1) + txf_active_num++; + bmap >>= 1; + } + bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] | + ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32); + for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) { + if (bmap & 1) + rxf_active_num++; + bmap >>= 1; + } + count = BNAD_ETHTOOL_STATS_NUM + + txf_active_num * BNAD_NUM_TXF_COUNTERS + + rxf_active_num * BNAD_NUM_RXF_COUNTERS; + + for (i = 0; i < bnad->num_rx; i++) { + if (!bnad->rx_info[i].rx) + continue; + count += bnad->num_rxp_per_rx * BNAD_NUM_CQ_COUNTERS; + count += bnad->num_rxp_per_rx * BNAD_NUM_RXQ_COUNTERS; + for (j = 0; j < bnad->num_rxp_per_rx; j++) + if (bnad->rx_info[i].rx_ctrl[j].ccb && + bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] && + bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1]->rxq) + count += BNAD_NUM_RXQ_COUNTERS; + } + + for (i = 0; i < bnad->num_tx; i++) { + if (!bnad->tx_info[i].tx) + continue; + count += bnad->num_txq_per_tx * BNAD_NUM_TXQ_COUNTERS; + } + return count; +} + +static int +bnad_per_q_stats_fill(struct bnad *bnad, u64 *buf, int bi) +{ + int i, j; + struct bna_rcb *rcb = NULL; + struct bna_tcb *tcb = NULL; + + for (i = 0; i < bnad->num_rx; i++) { + if (!bnad->rx_info[i].rx) + continue; + for (j = 0; j < bnad->num_rxp_per_rx; j++) + if (bnad->rx_info[i].rx_ctrl[j].ccb && + bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] && + bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0]->rxq) { + buf[bi++] = bnad->rx_info[i].rx_ctrl[j]. + ccb->producer_index; + buf[bi++] = 0; /* ccb->consumer_index */ + buf[bi++] = *(bnad->rx_info[i].rx_ctrl[j]. + ccb->hw_producer_index); + } + } + for (i = 0; i < bnad->num_rx; i++) { + if (!bnad->rx_info[i].rx) + continue; + for (j = 0; j < bnad->num_rxp_per_rx; j++) + if (bnad->rx_info[i].rx_ctrl[j].ccb) { + if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] && + bnad->rx_info[i].rx_ctrl[j].ccb-> + rcb[0]->rxq) { + rcb = bnad->rx_info[i].rx_ctrl[j]. + ccb->rcb[0]; + buf[bi++] = rcb->rxq->rx_packets; + buf[bi++] = rcb->rxq->rx_bytes; + buf[bi++] = rcb->rxq-> + rx_packets_with_error; + buf[bi++] = rcb->rxq-> + rxbuf_alloc_failed; + buf[bi++] = rcb->producer_index; + buf[bi++] = rcb->consumer_index; + } + if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] && + bnad->rx_info[i].rx_ctrl[j].ccb-> + rcb[1]->rxq) { + rcb = bnad->rx_info[i].rx_ctrl[j]. + ccb->rcb[1]; + buf[bi++] = rcb->rxq->rx_packets; + buf[bi++] = rcb->rxq->rx_bytes; + buf[bi++] = rcb->rxq-> + rx_packets_with_error; + buf[bi++] = rcb->rxq-> + rxbuf_alloc_failed; + buf[bi++] = rcb->producer_index; + buf[bi++] = rcb->consumer_index; + } + } + } + + for (i = 0; i < bnad->num_tx; i++) { + if (!bnad->tx_info[i].tx) + continue; + for (j = 0; j < bnad->num_txq_per_tx; j++) + if (bnad->tx_info[i].tcb[j] && + bnad->tx_info[i].tcb[j]->txq) { + tcb = bnad->tx_info[i].tcb[j]; + buf[bi++] = tcb->txq->tx_packets; + buf[bi++] = tcb->txq->tx_bytes; + buf[bi++] = tcb->producer_index; + buf[bi++] = tcb->consumer_index; + buf[bi++] = *(tcb->hw_consumer_index); + } + } + + return bi; +} + +static void +bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, + u64 *buf) +{ + struct bnad *bnad = netdev_priv(netdev); + int i, j, bi; + unsigned long *net_stats, flags; + u64 *stats64; + u64 bmap; + + mutex_lock(&bnad->conf_mutex); + if (bnad_get_stats_count_locked(netdev) != stats->n_stats) { + mutex_unlock(&bnad->conf_mutex); + return; + } + + /* + * Used bna_lock to sync reads from bna_stats, which is written + * under the same lock + */ + spin_lock_irqsave(&bnad->bna_lock, flags); + bi = 0; + memset(buf, 0, stats->n_stats * sizeof(u64)); + memset(&bnad->net_stats, 0, sizeof(struct net_device_stats)); + + bnad_netdev_qstats_fill(bnad); + bnad_netdev_hwstats_fill(bnad); + + /* Fill net_stats into ethtool buffers */ + net_stats = (unsigned long *)&bnad->net_stats; + for (i = 0; i < sizeof(struct net_device_stats) / sizeof(unsigned long); + i++) + buf[bi++] = net_stats[i]; + + /* Fill driver stats into ethtool buffers */ + stats64 = (u64 *)&bnad->stats.drv_stats; + for (i = 0; i < sizeof(struct bnad_drv_stats) / sizeof(u64); i++) + buf[bi++] = stats64[i]; + + /* Fill hardware stats excluding the rxf/txf into ethtool bufs */ + stats64 = (u64 *) bnad->stats.bna_stats->hw_stats; + for (i = 0; + i < offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64); + i++) + buf[bi++] = stats64[i]; + + /* Fill txf stats into ethtool buffers */ + bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] | + ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32); + for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) { + if (bmap & 1) { + stats64 = (u64 *)&bnad->stats.bna_stats-> + hw_stats->txf_stats[i]; + for (j = 0; j < sizeof(struct bfi_ll_stats_txf) / + sizeof(u64); j++) + buf[bi++] = stats64[j]; + } + bmap >>= 1; + } + + /* Fill rxf stats into ethtool buffers */ + bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] | + ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32); + for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) { + if (bmap & 1) { + stats64 = (u64 *)&bnad->stats.bna_stats-> + hw_stats->rxf_stats[i]; + for (j = 0; j < sizeof(struct bfi_ll_stats_rxf) / + sizeof(u64); j++) + buf[bi++] = stats64[j]; + } + bmap >>= 1; + } + + /* Fill per Q stats into ethtool buffers */ + bi = bnad_per_q_stats_fill(bnad, buf, bi); + + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + mutex_unlock(&bnad->conf_mutex); +} + +static int +bnad_get_sset_count(struct net_device *netdev, int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return bnad_get_stats_count_locked(netdev); + default: + return -EOPNOTSUPP; + } +} + +static struct ethtool_ops bnad_ethtool_ops = { + .get_settings = bnad_get_settings, + .set_settings = bnad_set_settings, + .get_drvinfo = bnad_get_drvinfo, + .get_regs_len = bnad_get_regs_len, + .get_regs = bnad_get_regs, + .get_wol = bnad_get_wol, + .get_link = ethtool_op_get_link, + .get_coalesce = bnad_get_coalesce, + .set_coalesce = bnad_set_coalesce, + .get_ringparam = bnad_get_ringparam, + .set_ringparam = bnad_set_ringparam, + .get_pauseparam = bnad_get_pauseparam, + .set_pauseparam = bnad_set_pauseparam, + .get_rx_csum = bnad_get_rx_csum, + .set_rx_csum = bnad_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = bnad_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = bnad_set_tso, + .get_flags = ethtool_op_get_flags, + .set_flags = ethtool_op_set_flags, + .get_strings = bnad_get_strings, + .get_ethtool_stats = bnad_get_ethtool_stats, + .get_sset_count = bnad_get_sset_count +}; + +void +bnad_set_ethtool_ops(struct net_device *netdev) +{ + SET_ETHTOOL_OPS(netdev, &bnad_ethtool_ops); +} diff --git a/drivers/net/bna/cna.h b/drivers/net/bna/cna.h new file mode 100644 index 000000000000..bbd39dc65972 --- /dev/null +++ b/drivers/net/bna/cna.h @@ -0,0 +1,81 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2006-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ + +#ifndef __CNA_H__ +#define __CNA_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define bfa_sm_fault(__mod, __event) do { \ + pr_err("SM Assertion failure: %s: %d: event = %d", __FILE__, __LINE__, \ + __event); \ +} while (0) + +extern char bfa_version[]; + +#define CNA_FW_FILE_CT "ctfw_cna.bin" +#define FC_SYMNAME_MAX 256 /*!< max name server symbolic name size */ + +#pragma pack(1) + +#define MAC_ADDRLEN (6) +typedef struct mac { u8 mac[MAC_ADDRLEN]; } mac_t; + +#pragma pack() + +#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next)) +#define bfa_q_next(_qe) (((struct list_head *) (_qe))->next) +#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev) + +/* + * bfa_q_qe_init - to initialize a queue element + */ +#define bfa_q_qe_init(_qe) { \ + bfa_q_next(_qe) = (struct list_head *) NULL; \ + bfa_q_prev(_qe) = (struct list_head *) NULL; \ +} + +/* + * bfa_q_deq - dequeue an element from head of the queue + */ +#define bfa_q_deq(_q, _qe) { \ + if (!list_empty(_q)) { \ + (*((struct list_head **) (_qe))) = bfa_q_next(_q); \ + bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) = \ + (struct list_head *) (_q); \ + bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \ + bfa_q_qe_init(*((struct list_head **) _qe)); \ + } else { \ + *((struct list_head **) (_qe)) = (struct list_head *) NULL; \ + } \ +} + +#endif /* __CNA_H__ */ diff --git a/drivers/net/bna/cna_fwimg.c b/drivers/net/bna/cna_fwimg.c new file mode 100644 index 000000000000..0bd1d3790a27 --- /dev/null +++ b/drivers/net/bna/cna_fwimg.c @@ -0,0 +1,64 @@ +/* + * Linux network driver for Brocade Converged Network Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * 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. + */ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + */ +#include +#include "cna.h" + +const struct firmware *bfi_fw; +static u32 *bfi_image_ct_cna; +static u32 bfi_image_ct_cna_size; + +u32 * +cna_read_firmware(struct pci_dev *pdev, u32 **bfi_image, + u32 *bfi_image_size, char *fw_name) +{ + const struct firmware *fw; + + if (request_firmware(&fw, fw_name, &pdev->dev)) { + pr_alert("Can't locate firmware %s\n", fw_name); + goto error; + } + + *bfi_image = (u32 *)fw->data; + *bfi_image_size = fw->size/sizeof(u32); + bfi_fw = fw; + + return *bfi_image; +error: + return NULL; +} + +u32 * +cna_get_firmware_buf(struct pci_dev *pdev) +{ + if (bfi_image_ct_cna_size == 0) + cna_read_firmware(pdev, &bfi_image_ct_cna, + &bfi_image_ct_cna_size, CNA_FW_FILE_CT); + return bfi_image_ct_cna; +} + +u32 * +bfa_cb_image_get_chunk(int type, u32 off) +{ + return (u32 *)(bfi_image_ct_cna + off); +} + +u32 +bfa_cb_image_get_size(int type) +{ + return bfi_image_ct_cna_size; +} diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f6a3b2d36cad..1f730de0df06 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2189,6 +2189,9 @@ #define PCI_VENDOR_ID_ARIMA 0x161f #define PCI_VENDOR_ID_BROCADE 0x1657 +#define PCI_DEVICE_ID_BROCADE_CT 0x0014 +#define PCI_DEVICE_ID_BROCADE_FC_8G1P 0x0017 +#define PCI_DEVICE_ID_BROCADE_CT_FC 0x0021 #define PCI_VENDOR_ID_SIBYTE 0x166d #define PCI_DEVICE_ID_BCM1250_PCI 0x0001 -- cgit v1.2.3-59-g8ed1b From f04b4dd2b1f533cef0507e0410ffc6732d21a272 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Aug 2010 20:34:51 -0700 Subject: bna: Delete get_flags and set_flags ethtool methods. This driver doesn't support LRO, NTUPLE, or the RXHASH features. So it should not set these ethtool operations. This also fixes the warning: drivers/net/bna/bnad_ethtool.c:1272: warning: initialization from incompatible pointer type Signed-off-by: David S. Miller --- drivers/net/bna/bnad_ethtool.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c index e982785b6b25..7e630f5e8e03 100644 --- a/drivers/net/bna/bnad_ethtool.c +++ b/drivers/net/bna/bnad_ethtool.c @@ -1268,8 +1268,6 @@ static struct ethtool_ops bnad_ethtool_ops = { .set_sg = ethtool_op_set_sg, .get_tso = ethtool_op_get_tso, .set_tso = bnad_set_tso, - .get_flags = ethtool_op_get_flags, - .set_flags = ethtool_op_set_flags, .get_strings = bnad_get_strings, .get_ethtool_stats = bnad_get_ethtool_stats, .get_sset_count = bnad_get_sset_count -- cgit v1.2.3-59-g8ed1b From e46dab4d4be87769b09404135bc34f89e2e155d8 Mon Sep 17 00:00:00 2001 From: Dimitris Michailidis Date: Mon, 23 Aug 2010 17:20:58 +0000 Subject: cxgb4: handle Rx/Tx queue ranges not starting at 0 Currently the driver assumes that queue IDs start at 0 but that's true only for function 0. To support operation on other functions get the start of the queue ranges from FW and offset accordingly. Signed-off-by: Dimitris Michailidis Signed-off-by: David S. Miller --- drivers/net/cxgb4/cxgb4.h | 2 ++ drivers/net/cxgb4/cxgb4_main.c | 24 +++++++++++++++++++----- drivers/net/cxgb4/sge.c | 15 +++++++++------ drivers/net/cxgb4/t4fw_api.h | 5 +++++ 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h index 6e562c0dad7d..3ece9f5069fa 100644 --- a/drivers/net/cxgb4/cxgb4.h +++ b/drivers/net/cxgb4/cxgb4.h @@ -463,6 +463,8 @@ struct sge { u8 counter_val[SGE_NCOUNTERS]; unsigned int starve_thres; u8 idma_state[2]; + unsigned int egr_start; + unsigned int ingr_start; void *egr_map[MAX_EGRQ]; /* qid->queue egress queue map */ struct sge_rspq *ingr_map[MAX_INGQ]; /* qid->queue ingress queue map */ DECLARE_BITMAP(starving_fl, MAX_EGRQ); diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index c327527fbbc8..6e08e2d8eb3e 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -423,10 +423,11 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, if (likely(opcode == CPL_SGE_EGR_UPDATE)) { const struct cpl_sge_egr_update *p = (void *)rsp; unsigned int qid = EGR_QID(ntohl(p->opcode_qid)); - struct sge_txq *txq = q->adap->sge.egr_map[qid]; + struct sge_txq *txq; + txq = q->adap->sge.egr_map[qid - q->adap->sge.egr_start]; txq->restarts++; - if ((u8 *)txq < (u8 *)q->adap->sge.ethrxq) { + if ((u8 *)txq < (u8 *)q->adap->sge.ofldtxq) { struct sge_eth_txq *eq; eq = container_of(txq, struct sge_eth_txq, q); @@ -657,6 +658,15 @@ static int setup_rss(struct adapter *adap) return 0; } +/* + * Return the channel of the ingress queue with the given qid. + */ +static unsigned int rxq_to_chan(const struct sge *p, unsigned int qid) +{ + qid -= p->ingr_start; + return netdev2pinfo(p->ingr_map[qid]->netdev)->tx_chan; +} + /* * Wait until all NAPI handlers are descheduled. */ @@ -2304,7 +2314,7 @@ int cxgb4_create_server(const struct net_device *dev, unsigned int stid, req->peer_port = htons(0); req->local_ip = sip; req->peer_ip = htonl(0); - chan = netdev2pinfo(adap->sge.ingr_map[queue]->netdev)->tx_chan; + chan = rxq_to_chan(&adap->sge, queue); req->opt0 = cpu_to_be64(TX_CHAN(chan)); req->opt1 = cpu_to_be64(CONN_POLICY_ASK | SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue)); @@ -2346,7 +2356,7 @@ int cxgb4_create_server6(const struct net_device *dev, unsigned int stid, req->local_ip_lo = *(__be64 *)(sip->s6_addr + 8); req->peer_ip_hi = cpu_to_be64(0); req->peer_ip_lo = cpu_to_be64(0); - chan = netdev2pinfo(adap->sge.ingr_map[queue]->netdev)->tx_chan; + chan = rxq_to_chan(&adap->sge, queue); req->opt0 = cpu_to_be64(TX_CHAN(chan)); req->opt1 = cpu_to_be64(CONN_POLICY_ASK | SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue)); @@ -3061,12 +3071,16 @@ static int adap_init0(struct adapter *adap) params[2] = FW_PARAM_PFVF(L2T_END); params[3] = FW_PARAM_PFVF(FILTER_START); params[4] = FW_PARAM_PFVF(FILTER_END); - ret = t4_query_params(adap, adap->fn, adap->fn, 0, 5, params, val); + params[5] = FW_PARAM_PFVF(IQFLINT_START); + params[6] = FW_PARAM_PFVF(EQ_START); + ret = t4_query_params(adap, adap->fn, adap->fn, 0, 7, params, val); if (ret < 0) goto bye; port_vec = val[0]; adap->tids.ftid_base = val[3]; adap->tids.nftids = val[4] - val[3] + 1; + adap->sge.ingr_start = val[5]; + adap->sge.egr_start = val[6]; if (c.ofldcaps) { /* query offload-related parameters */ diff --git a/drivers/net/cxgb4/sge.c b/drivers/net/cxgb4/sge.c index bf38cfc57565..44c2e6c9f073 100644 --- a/drivers/net/cxgb4/sge.c +++ b/drivers/net/cxgb4/sge.c @@ -557,7 +557,8 @@ out: cred = q->avail - cred; if (unlikely(fl_starving(q))) { smp_wmb(); - set_bit(q->cntxt_id, adap->sge.starving_fl); + set_bit(q->cntxt_id - adap->sge.egr_start, + adap->sge.starving_fl); } return cred; @@ -1213,7 +1214,8 @@ static void txq_stop_maperr(struct sge_ofld_txq *q) { q->mapping_err++; q->q.stops++; - set_bit(q->q.cntxt_id, q->adap->sge.txq_maperr); + set_bit(q->q.cntxt_id - q->adap->sge.egr_start, + q->adap->sge.txq_maperr); } /** @@ -1835,6 +1837,7 @@ static unsigned int process_intrq(struct adapter *adap) if (RSPD_TYPE(rc->type_gen) == RSP_TYPE_INTR) { unsigned int qid = ntohl(rc->pldbuflen_qid); + qid -= adap->sge.ingr_start; napi_schedule(&adap->sge.ingr_map[qid]->napi); } @@ -2050,14 +2053,14 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, /* set offset to -1 to distinguish ingress queues without FL */ iq->offset = fl ? 0 : -1; - adap->sge.ingr_map[iq->cntxt_id] = iq; + adap->sge.ingr_map[iq->cntxt_id - adap->sge.ingr_start] = iq; if (fl) { fl->cntxt_id = ntohs(c.fl0id); fl->avail = fl->pend_cred = 0; fl->pidx = fl->cidx = 0; fl->alloc_failed = fl->large_alloc_failed = fl->starving = 0; - adap->sge.egr_map[fl->cntxt_id] = fl; + adap->sge.egr_map[fl->cntxt_id - adap->sge.egr_start] = fl; refill_fl(adap, fl, fl_cap(fl), GFP_KERNEL); } return 0; @@ -2087,7 +2090,7 @@ static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id) q->stops = q->restarts = 0; q->stat = (void *)&q->desc[q->size]; q->cntxt_id = id; - adap->sge.egr_map[id] = q; + adap->sge.egr_map[id - adap->sge.egr_start] = q; } int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, @@ -2259,7 +2262,7 @@ static void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, { unsigned int fl_id = fl ? fl->cntxt_id : 0xffff; - adap->sge.ingr_map[rq->cntxt_id] = NULL; + adap->sge.ingr_map[rq->cntxt_id - adap->sge.ingr_start] = NULL; t4_iq_free(adap, adap->fn, adap->fn, 0, FW_IQ_TYPE_FL_INT_CAP, rq->cntxt_id, fl_id, 0xffff); dma_free_coherent(adap->pdev_dev, (rq->size + 1) * rq->iqe_len, diff --git a/drivers/net/cxgb4/t4fw_api.h b/drivers/net/cxgb4/t4fw_api.h index 0969f2fbc1b0..940584a8a640 100644 --- a/drivers/net/cxgb4/t4fw_api.h +++ b/drivers/net/cxgb4/t4fw_api.h @@ -487,6 +487,11 @@ enum fw_params_param_pfvf { FW_PARAMS_PARAM_PFVF_CPMASK = 0x25, FW_PARAMS_PARAM_PFVF_OCQ_START = 0x26, FW_PARAMS_PARAM_PFVF_OCQ_END = 0x27, + FW_PARAMS_PARAM_PFVF_CONM_MAP = 0x28, + FW_PARAMS_PARAM_PFVF_IQFLINT_START = 0x29, + FW_PARAMS_PARAM_PFVF_IQFLINT_END = 0x2A, + FW_PARAMS_PARAM_PFVF_EQ_START = 0x2B, + FW_PARAMS_PARAM_PFVF_EQ_END = 0x2C, }; /* -- cgit v1.2.3-59-g8ed1b From 1478b3ee931e83c7a94f61376e962574b28d23d6 Mon Sep 17 00:00:00 2001 From: Dimitris Michailidis Date: Mon, 23 Aug 2010 17:20:59 +0000 Subject: cxgb4: support eeprom read/write on functions other than 0 Extend the address translation for eeprom read/write (code used by ethtool -[eE]) to functions other than 0. Signed-off-by: Dimitris Michailidis Signed-off-by: David S. Miller --- drivers/net/cxgb4/cxgb4_main.c | 40 +++++++++++++++++++++++++++++++--------- drivers/net/cxgb4/t4_hw.h | 1 + 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index 6e08e2d8eb3e..7552d8df55ed 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -1681,27 +1681,41 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) return 0; } -/* - * Translate a physical EEPROM address to virtual. The first 1K is accessed - * through virtual addresses starting at 31K, the rest is accessed through - * virtual addresses starting at 0. This mapping is correct only for PF0. +/** + * eeprom_ptov - translate a physical EEPROM address to virtual + * @phys_addr: the physical EEPROM address + * @fn: the PCI function number + * @sz: size of function-specific area + * + * Translate a physical EEPROM address to virtual. The first 1K is + * accessed through virtual addresses starting at 31K, the rest is + * accessed through virtual addresses starting at 0. + * + * The mapping is as follows: + * [0..1K) -> [31K..32K) + * [1K..1K+A) -> [31K-A..31K) + * [1K+A..ES) -> [0..ES-A-1K) + * + * where A = @fn * @sz, and ES = EEPROM size. */ -static int eeprom_ptov(unsigned int phys_addr) +static int eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz) { + fn *= sz; if (phys_addr < 1024) return phys_addr + (31 << 10); + if (phys_addr < 1024 + fn) + return 31744 - fn + phys_addr - 1024; if (phys_addr < EEPROMSIZE) - return phys_addr - 1024; + return phys_addr - 1024 - fn; return -EINVAL; } /* * The next two routines implement eeprom read/write from physical addresses. - * The physical->virtual translation is correct only for PF0. */ static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v) { - int vaddr = eeprom_ptov(phys_addr); + int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE); if (vaddr >= 0) vaddr = pci_read_vpd(adap->pdev, vaddr, sizeof(u32), v); @@ -1710,7 +1724,7 @@ static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v) static int eeprom_wr_phys(struct adapter *adap, unsigned int phys_addr, u32 v) { - int vaddr = eeprom_ptov(phys_addr); + int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE); if (vaddr >= 0) vaddr = pci_write_vpd(adap->pdev, vaddr, sizeof(u32), &v); @@ -1753,6 +1767,14 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, aligned_offset = eeprom->offset & ~3; aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3; + if (adapter->fn > 0) { + u32 start = 1024 + adapter->fn * EEPROMPFSIZE; + + if (aligned_offset < start || + aligned_offset + aligned_len > start + EEPROMPFSIZE) + return -EPERM; + } + if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) { /* * RMW possibly needed for first or last words. diff --git a/drivers/net/cxgb4/t4_hw.h b/drivers/net/cxgb4/t4_hw.h index 10a055565776..c26b455f37de 100644 --- a/drivers/net/cxgb4/t4_hw.h +++ b/drivers/net/cxgb4/t4_hw.h @@ -42,6 +42,7 @@ enum { MAX_MTU = 9600, /* max MAC MTU, excluding header + FCS */ EEPROMSIZE = 17408, /* Serial EEPROM physical size */ EEPROMVSIZE = 32768, /* Serial EEPROM virtual address space size */ + EEPROMPFSIZE = 1024, /* EEPROM writable area size for PFn, n>0 */ RSS_NENTRIES = 2048, /* # of entries in RSS mapping table */ TCB_SIZE = 128, /* TCB size */ NMTUS = 16, /* size of MTU table */ -- cgit v1.2.3-59-g8ed1b From 1707aec9ac884de9e3358a8e564bbce91e4346f7 Mon Sep 17 00:00:00 2001 From: Dimitris Michailidis Date: Mon, 23 Aug 2010 17:21:00 +0000 Subject: cxgb4: fix setting of the function number in transmit descriptors Signed-off-by: Dimitris Michailidis Signed-off-by: David S. Miller --- drivers/net/cxgb4/sge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/cxgb4/sge.c b/drivers/net/cxgb4/sge.c index 44c2e6c9f073..6ddb3bb0ce67 100644 --- a/drivers/net/cxgb4/sge.c +++ b/drivers/net/cxgb4/sge.c @@ -975,7 +975,7 @@ out_free: dev_kfree_skb(skb); } cpl->ctrl0 = htonl(TXPKT_OPCODE(CPL_TX_PKT_XT) | - TXPKT_INTF(pi->tx_chan) | TXPKT_PF(0)); + TXPKT_INTF(pi->tx_chan) | TXPKT_PF(adap->fn)); cpl->pack = htons(0); cpl->len = htons(skb->len); cpl->ctrl1 = cpu_to_be64(cntrl); -- cgit v1.2.3-59-g8ed1b From ccea790ef033cc890ca4b416a783e9f9dffe556e Mon Sep 17 00:00:00 2001 From: Dimitris Michailidis Date: Mon, 23 Aug 2010 17:21:01 +0000 Subject: cxgb4: update PCI ids Signed-off-by: Dimitris Michailidis Signed-off-by: David S. Miller --- drivers/net/cxgb4/cxgb4_main.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index 7552d8df55ed..75b9401fd484 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -175,16 +175,26 @@ enum { static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = { CH_DEVICE(0xa000, 0), /* PE10K */ - CH_DEVICE(0x4001, 0), - CH_DEVICE(0x4002, 0), - CH_DEVICE(0x4003, 0), - CH_DEVICE(0x4004, 0), - CH_DEVICE(0x4005, 0), - CH_DEVICE(0x4006, 0), - CH_DEVICE(0x4007, 0), - CH_DEVICE(0x4008, 0), - CH_DEVICE(0x4009, 0), - CH_DEVICE(0x400a, 0), + CH_DEVICE(0x4001, -1), + CH_DEVICE(0x4002, -1), + CH_DEVICE(0x4003, -1), + CH_DEVICE(0x4004, -1), + CH_DEVICE(0x4005, -1), + CH_DEVICE(0x4006, -1), + CH_DEVICE(0x4007, -1), + CH_DEVICE(0x4008, -1), + CH_DEVICE(0x4009, -1), + CH_DEVICE(0x400a, -1), + CH_DEVICE(0x4401, 4), + CH_DEVICE(0x4402, 4), + CH_DEVICE(0x4403, 4), + CH_DEVICE(0x4404, 4), + CH_DEVICE(0x4405, 4), + CH_DEVICE(0x4406, 4), + CH_DEVICE(0x4407, 4), + CH_DEVICE(0x4408, 4), + CH_DEVICE(0x4409, 4), + CH_DEVICE(0x440a, 4), { 0, } }; -- cgit v1.2.3-59-g8ed1b From 7abac686026ec1af38f6e766369dbfe4007949b6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Aug 2010 20:42:11 -0700 Subject: pkt_sched: Make act_csum depend upon INET. It uses ip_send_check() and stuff like that. Reported-by: Randy Dunlap Signed-off-by: David S. Miller --- net/sched/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 522d5a9a2825..a36270a994d7 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -520,7 +520,7 @@ config NET_ACT_SKBEDIT config NET_ACT_CSUM tristate "Checksum Updating" - depends on NET_CLS_ACT + depends on NET_CLS_ACT && INET ---help--- Say Y here to update some common checksum after some direct packet alterations. -- cgit v1.2.3-59-g8ed1b From 0eec32ff350348e635b3b8d87b989117ce045d25 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Mon, 23 Aug 2010 03:27:58 +0000 Subject: net_sched: act_csum: coding style cleanup Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- net/sched/act_csum.c | 77 ++++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index be41f1cc10ee..67dc7ce9b63a 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c @@ -42,9 +42,9 @@ static u32 csum_idx_gen; static DEFINE_RWLOCK(csum_lock); static struct tcf_hashinfo csum_hash_info = { - .htab = tcf_csum_ht, - .hmask = CSUM_TAB_MASK, - .lock = &csum_lock, + .htab = tcf_csum_ht, + .hmask = CSUM_TAB_MASK, + .lock = &csum_lock, }; static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = { @@ -73,7 +73,8 @@ static int tcf_csum_init(struct nlattr *nla, struct nlattr *est, pc = tcf_hash_check(parm->index, a, bind, &csum_hash_info); if (!pc) { - pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind, &csum_idx_gen, &csum_hash_info); + pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind, + &csum_idx_gen, &csum_hash_info); if (IS_ERR(pc)) return PTR_ERR(pc); p = to_tcf_csum(pc); @@ -230,8 +231,9 @@ static int tcf_csum_ipv4_udp(struct sk_buff *skb, struct iphdr *iph, struct udphdr *udph; u16 ul; - /* Support both UDP and UDPLITE checksum algorithms, - * Don't use udph->len to get the real length without any protocol check, + /* + * Support both UDP and UDPLITE checksum algorithms, Don't use + * udph->len to get the real length without any protocol check, * UDPLITE uses udph->len for another thing, * Use iph->tot_len, or just ipl. */ @@ -249,10 +251,8 @@ static int tcf_csum_ipv4_udp(struct sk_buff *skb, struct iphdr *iph, if (udplite) { if (ul == 0) skb->csum = csum_partial(udph, ipl - ihl, 0); - else if ((ul >= sizeof(*udph)) && (ul <= ipl - ihl)) skb->csum = csum_partial(udph, ul, 0); - else goto ignore_obscure_skb; } else { @@ -282,8 +282,9 @@ static int tcf_csum_ipv6_udp(struct sk_buff *skb, struct ipv6hdr *ip6h, struct udphdr *udph; u16 ul; - /* Support both UDP and UDPLITE checksum algorithms, - * Don't use udph->len to get the real length without any protocol check, + /* + * Support both UDP and UDPLITE checksum algorithms, Don't use + * udph->len to get the real length without any protocol check, * UDPLITE uses udph->len for another thing, * Use ip6h->payload_len + sizeof(*ip6h) ... , or just ipl. */ @@ -340,32 +341,32 @@ static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags) switch (iph->frag_off & htons(IP_OFFSET) ? 0 : iph->protocol) { case IPPROTO_ICMP: if (update_flags & TCA_CSUM_UPDATE_FLAG_ICMP) - if (!tcf_csum_ipv4_icmp(skb, - iph->ihl * 4, ntohs(iph->tot_len))) + if (!tcf_csum_ipv4_icmp(skb, iph->ihl * 4, + ntohs(iph->tot_len))) goto fail; break; case IPPROTO_IGMP: if (update_flags & TCA_CSUM_UPDATE_FLAG_IGMP) - if (!tcf_csum_ipv4_igmp(skb, - iph->ihl * 4, ntohs(iph->tot_len))) + if (!tcf_csum_ipv4_igmp(skb, iph->ihl * 4, + ntohs(iph->tot_len))) goto fail; break; case IPPROTO_TCP: if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP) - if (!tcf_csum_ipv4_tcp(skb, iph, - iph->ihl * 4, ntohs(iph->tot_len))) + if (!tcf_csum_ipv4_tcp(skb, iph, iph->ihl * 4, + ntohs(iph->tot_len))) goto fail; break; case IPPROTO_UDP: if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP) - if (!tcf_csum_ipv4_udp(skb, iph, - iph->ihl * 4, ntohs(iph->tot_len), 0)) + if (!tcf_csum_ipv4_udp(skb, iph, iph->ihl * 4, + ntohs(iph->tot_len), 0)) goto fail; break; case IPPROTO_UDPLITE: if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE) - if (!tcf_csum_ipv4_udp(skb, iph, - iph->ihl * 4, ntohs(iph->tot_len), 1)) + if (!tcf_csum_ipv4_udp(skb, iph, iph->ihl * 4, + ntohs(iph->tot_len), 1)) goto fail; break; } @@ -386,7 +387,7 @@ fail: } static int tcf_csum_ipv6_hopopts(struct ipv6_opt_hdr *ip6xh, - unsigned int ixhl, unsigned int *pl) + unsigned int ixhl, unsigned int *pl) { int off, len, optlen; unsigned char *xh = (void *)ip6xh; @@ -395,8 +396,7 @@ static int tcf_csum_ipv6_hopopts(struct ipv6_opt_hdr *ip6xh, len = ixhl - off; while (len > 1) { - switch (xh[off]) - { + switch (xh[off]) { case IPV6_TLV_PAD0: optlen = 1; break; @@ -476,14 +476,14 @@ static int tcf_csum_ipv6(struct sk_buff *skb, u32 update_flags) goto done; case IPPROTO_UDP: if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP) - if (!tcf_csum_ipv6_udp(skb, ip6h, - hl, pl + sizeof(*ip6h), 0)) + if (!tcf_csum_ipv6_udp(skb, ip6h, hl, + pl + sizeof(*ip6h), 0)) goto fail; goto done; case IPPROTO_UDPLITE: if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE) - if (!tcf_csum_ipv6_udp(skb, ip6h, - hl, pl + sizeof(*ip6h), 1)) + if (!tcf_csum_ipv6_udp(skb, ip6h, hl, + pl + sizeof(*ip6h), 1)) goto fail; goto done; default: @@ -544,7 +544,6 @@ static int tcf_csum_dump(struct sk_buff *skb, struct tcf_csum *p = a->priv; struct tc_csum opt = { .update_flags = p->update_flags, - .index = p->tcf_index, .action = p->tcf_action, .refcnt = p->tcf_refcnt - ref, @@ -566,17 +565,17 @@ nla_put_failure: } static struct tc_action_ops act_csum_ops = { - .kind = "csum", - .hinfo = &csum_hash_info, - .type = TCA_ACT_CSUM, - .capab = TCA_CAP_NONE, - .owner = THIS_MODULE, - .act = tcf_csum, - .dump = tcf_csum_dump, - .cleanup = tcf_csum_cleanup, - .lookup = tcf_hash_search, - .init = tcf_csum_init, - .walk = tcf_generic_walker + .kind = "csum", + .hinfo = &csum_hash_info, + .type = TCA_ACT_CSUM, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_csum, + .dump = tcf_csum_dump, + .cleanup = tcf_csum_cleanup, + .lookup = tcf_hash_search, + .init = tcf_csum_init, + .walk = tcf_generic_walker }; MODULE_DESCRIPTION("Checksum updating actions"); -- cgit v1.2.3-59-g8ed1b From afdcba371f9748ac91608bb6c57f170aab7085b4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 23 Aug 2010 07:14:36 +0000 Subject: net: copy_rtnl_link_stats64() simplification No need to use a temporary struct rtnl_link_stats64 variable, just copy the source to skb buffer. Signed-off-by: Eric Dumazet Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index f78d821bd935..b2a718dfd720 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -612,36 +612,7 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, static void copy_rtnl_link_stats64(void *v, const struct rtnl_link_stats64 *b) { - struct rtnl_link_stats64 a; - - a.rx_packets = b->rx_packets; - a.tx_packets = b->tx_packets; - a.rx_bytes = b->rx_bytes; - a.tx_bytes = b->tx_bytes; - a.rx_errors = b->rx_errors; - a.tx_errors = b->tx_errors; - a.rx_dropped = b->rx_dropped; - a.tx_dropped = b->tx_dropped; - - a.multicast = b->multicast; - a.collisions = b->collisions; - - a.rx_length_errors = b->rx_length_errors; - a.rx_over_errors = b->rx_over_errors; - a.rx_crc_errors = b->rx_crc_errors; - a.rx_frame_errors = b->rx_frame_errors; - a.rx_fifo_errors = b->rx_fifo_errors; - a.rx_missed_errors = b->rx_missed_errors; - - a.tx_aborted_errors = b->tx_aborted_errors; - a.tx_carrier_errors = b->tx_carrier_errors; - a.tx_fifo_errors = b->tx_fifo_errors; - a.tx_heartbeat_errors = b->tx_heartbeat_errors; - a.tx_window_errors = b->tx_window_errors; - - a.rx_compressed = b->rx_compressed; - a.tx_compressed = b->tx_compressed; - memcpy(v, &a, sizeof(a)); + memcpy(v, b, sizeof(*b)); } /* All VF info */ -- cgit v1.2.3-59-g8ed1b From 0fdc100bdc4b7ab61ed632962c76dfe539047296 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 23 Aug 2010 10:24:18 +0000 Subject: ethtool: allow non-netadmin to query settings The SNMP daemon uses ethtool to determine the speed of network interfaces. This fails on Debian (and probably elsewhere) because for security SNMP daemon runs as non-root user (snmp). Note: A similar patch was rejected previously because of a concern about the possibility that on some hardware querying the ethtool settings requires access to the PHY and could slow the machine down. But the security risk of requiring SNMP daemon (and related services) to run as root far out weighs the risk of denial-of-service. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/core/ethtool.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index d2c4da5a6a4f..970eb9817bbc 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1423,6 +1423,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) /* Allow some commands to be done by anyone */ switch (ethcmd) { + case ETHTOOL_GSET: case ETHTOOL_GDRVINFO: case ETHTOOL_GMSGLVL: case ETHTOOL_GCOALESCE: -- cgit v1.2.3-59-g8ed1b From 1726442e115a9e58f40747d009a5b4f303e0840a Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 23 Aug 2010 16:26:41 +0000 Subject: net: increase the size of priv_flags and add IFF_OVS_DATAPATH IFF_OVS_DATAPATH is a place-holder for the Open vSwitch datapath which I am preparing to submit for merging. As all 16 bits of priv_flags are already assigned flags, also increase the size of priv_flags to 32 bits. Unfortunately, by my calculations this increases the size of struct net_device by 4 bytes on 32bit architectures and 8 bytes on 64 bit architectures. I couldn't see an obvious way to avoid that. Cc: Jesse Gross Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- include/linux/if.h | 2 ++ include/linux/netdevice.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/linux/if.h b/include/linux/if.h index 53558ec59e1b..6ed43c1f07ab 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -75,6 +75,8 @@ #define IFF_DISABLE_NETPOLL 0x2000 /* disable netpoll at run-time */ #define IFF_MACVLAN_PORT 0x4000 /* device used as macvlan port */ #define IFF_BRIDGE_PORT 0x8000 /* device used as bridge port */ +#define IFF_OVS_DATAPATH 0x10000 /* device used as Open vSwitch + * dapath port */ #define IF_GET_IFACE 0x0001 /* for querying only */ #define IF_GET_PROTO 0x0002 diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ce2de8b64083..59962dbc2758 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -901,7 +901,7 @@ struct net_device { unsigned int flags; /* interface flags (a la BSD) */ unsigned short gflags; - unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */ + unsigned int priv_flags; /* Like 'flags' but invisible to userspace. */ unsigned short padded; /* How much padding added by alloc_netdev() */ unsigned char operstate; /* RFC2863 operstate */ -- cgit v1.2.3-59-g8ed1b From 6c8e4c92baaa5dc05ec7555e45711ff47adbc73c Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Mon, 23 Aug 2010 17:20:52 +0100 Subject: parport_pc: show the detection of a 2 serial port ITE8874 chip The printk message for the 2 serial port version is obscured with a debug macro, unlike all other versions of the card. It should be changed to make the output equal for all detected models. Reference: https://bugzilla.redhat.com/show_bug.cgi?id=578616#c1 CC: Joe Krahn Signed-off-by: Niels de Vos Signed-off-by: Jiri Kosina --- drivers/parport/parport_pc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 0950fa40684f..8d62fb76cd41 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -2599,7 +2599,7 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, printk(KERN_INFO "parport_pc: ITE8873 found (1S)\n"); return 0; case 0x8: - DPRINTK(KERN_DEBUG "parport_pc: ITE8874 found (2S)\n"); + printk(KERN_INFO "parport_pc: ITE8874 found (2S)\n"); return 0; default: printk(KERN_INFO "parport_pc: unknown ITE887x\n"); -- cgit v1.2.3-59-g8ed1b From b4ddf4b3331f0f2195bd0ab5e8b50080ba93af87 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 24 Aug 2010 12:22:13 -0700 Subject: be2net: get rid of be_get_stats() drivers can avoid implementing ndo_get_stats method if using netdevice stats structure. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 74e146f470c6..b89bae029620 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -365,11 +365,6 @@ static void be_rx_eqd_update(struct be_adapter *adapter) rx_eq->cur_eqd = eqd; } -static struct net_device_stats *be_get_stats(struct net_device *dev) -{ - return &dev->stats; -} - static u32 be_calc_rate(u64 bytes, unsigned long ticks) { u64 rate = bytes; @@ -2399,7 +2394,6 @@ static struct net_device_ops be_netdev_ops = { .ndo_open = be_open, .ndo_stop = be_close, .ndo_start_xmit = be_xmit, - .ndo_get_stats = be_get_stats, .ndo_set_rx_mode = be_set_multicast_list, .ndo_set_mac_address = be_mac_addr_set, .ndo_change_mtu = be_change_mtu, -- cgit v1.2.3-59-g8ed1b From 6abc2376809497b04feee554240e158ac2072587 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 24 Aug 2010 12:23:01 -0700 Subject: ethoc: get rid of ethoc_stats() drivers can avoid implementing ndo_get_stats method if using netdevice stats structure. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/ethoc.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index 6d653c459c1f..c5a2fe099a8d 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -806,11 +806,6 @@ static void ethoc_tx_timeout(struct net_device *dev) ethoc_interrupt(dev->irq, dev); } -static struct net_device_stats *ethoc_stats(struct net_device *dev) -{ - return &dev->stats; -} - static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ethoc *priv = netdev_priv(dev); @@ -863,7 +858,6 @@ static const struct net_device_ops ethoc_netdev_ops = { .ndo_set_multicast_list = ethoc_set_multicast_list, .ndo_change_mtu = ethoc_change_mtu, .ndo_tx_timeout = ethoc_tx_timeout, - .ndo_get_stats = ethoc_stats, .ndo_start_xmit = ethoc_start_xmit, }; -- cgit v1.2.3-59-g8ed1b From c32d83c0420950754cca01557bc5802793948d66 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 24 Aug 2010 12:24:07 -0700 Subject: bcm63xx_enet: use netdev stats Use integrated net_device stats instead of a private one Get rid of bcm_enet_get_stats() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/bcm63xx_enet.c | 60 +++++++++++++++++++++------------------------- drivers/net/bcm63xx_enet.h | 1 - 2 files changed, 27 insertions(+), 34 deletions(-) diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index 0d2c5da08937..e2f70c3d7be4 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -293,22 +293,22 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget) /* if the packet does not have start of packet _and_ * end of packet flag set, then just recycle it */ if ((len_stat & DMADESC_ESOP_MASK) != DMADESC_ESOP_MASK) { - priv->stats.rx_dropped++; + dev->stats.rx_dropped++; continue; } /* recycle packet if it's marked as bad */ if (unlikely(len_stat & DMADESC_ERR_MASK)) { - priv->stats.rx_errors++; + dev->stats.rx_errors++; if (len_stat & DMADESC_OVSIZE_MASK) - priv->stats.rx_length_errors++; + dev->stats.rx_length_errors++; if (len_stat & DMADESC_CRC_MASK) - priv->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; if (len_stat & DMADESC_UNDER_MASK) - priv->stats.rx_frame_errors++; + dev->stats.rx_frame_errors++; if (len_stat & DMADESC_OV_MASK) - priv->stats.rx_fifo_errors++; + dev->stats.rx_fifo_errors++; continue; } @@ -324,7 +324,7 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget) nskb = netdev_alloc_skb_ip_align(dev, len); if (!nskb) { /* forget packet, just rearm desc */ - priv->stats.rx_dropped++; + dev->stats.rx_dropped++; continue; } @@ -342,8 +342,8 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget) skb_put(skb, len); skb->protocol = eth_type_trans(skb, dev); - priv->stats.rx_packets++; - priv->stats.rx_bytes += len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; netif_receive_skb(skb); } while (--budget > 0); @@ -403,7 +403,7 @@ static int bcm_enet_tx_reclaim(struct net_device *dev, int force) spin_unlock(&priv->tx_lock); if (desc->len_stat & DMADESC_UNDER_MASK) - priv->stats.tx_errors++; + dev->stats.tx_errors++; dev_kfree_skb(skb); released++; @@ -563,8 +563,8 @@ static int bcm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) if (!priv->tx_desc_count) netif_stop_queue(dev); - priv->stats.tx_bytes += skb->len; - priv->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + dev->stats.tx_packets++; ret = NETDEV_TX_OK; out_unlock: @@ -1140,17 +1140,6 @@ static int bcm_enet_stop(struct net_device *dev) return 0; } -/* - * core request to return device rx/tx stats - */ -static struct net_device_stats *bcm_enet_get_stats(struct net_device *dev) -{ - struct bcm_enet_priv *priv; - - priv = netdev_priv(dev); - return &priv->stats; -} - /* * ethtool callbacks */ @@ -1163,16 +1152,18 @@ struct bcm_enet_stats { #define GEN_STAT(m) sizeof(((struct bcm_enet_priv *)0)->m), \ offsetof(struct bcm_enet_priv, m) +#define DEV_STAT(m) sizeof(((struct net_device_stats *)0)->m), \ + offsetof(struct net_device_stats, m) static const struct bcm_enet_stats bcm_enet_gstrings_stats[] = { - { "rx_packets", GEN_STAT(stats.rx_packets), -1 }, - { "tx_packets", GEN_STAT(stats.tx_packets), -1 }, - { "rx_bytes", GEN_STAT(stats.rx_bytes), -1 }, - { "tx_bytes", GEN_STAT(stats.tx_bytes), -1 }, - { "rx_errors", GEN_STAT(stats.rx_errors), -1 }, - { "tx_errors", GEN_STAT(stats.tx_errors), -1 }, - { "rx_dropped", GEN_STAT(stats.rx_dropped), -1 }, - { "tx_dropped", GEN_STAT(stats.tx_dropped), -1 }, + { "rx_packets", DEV_STAT(rx_packets), -1 }, + { "tx_packets", DEV_STAT(tx_packets), -1 }, + { "rx_bytes", DEV_STAT(rx_bytes), -1 }, + { "tx_bytes", DEV_STAT(tx_bytes), -1 }, + { "rx_errors", DEV_STAT(rx_errors), -1 }, + { "tx_errors", DEV_STAT(tx_errors), -1 }, + { "rx_dropped", DEV_STAT(rx_dropped), -1 }, + { "tx_dropped", DEV_STAT(tx_dropped), -1 }, { "rx_good_octets", GEN_STAT(mib.rx_gd_octets), ETH_MIB_RX_GD_OCTETS}, { "rx_good_pkts", GEN_STAT(mib.rx_gd_pkts), ETH_MIB_RX_GD_PKTS }, @@ -1328,7 +1319,11 @@ static void bcm_enet_get_ethtool_stats(struct net_device *netdev, char *p; s = &bcm_enet_gstrings_stats[i]; - p = (char *)priv + s->stat_offset; + if (s->mib_reg == -1) + p = (char *)&netdev->stats; + else + p = (char *)priv; + p += s->stat_offset; data[i] = (s->sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } @@ -1605,7 +1600,6 @@ static const struct net_device_ops bcm_enet_ops = { .ndo_open = bcm_enet_open, .ndo_stop = bcm_enet_stop, .ndo_start_xmit = bcm_enet_start_xmit, - .ndo_get_stats = bcm_enet_get_stats, .ndo_set_mac_address = bcm_enet_set_mac_address, .ndo_set_multicast_list = bcm_enet_set_multicast_list, .ndo_do_ioctl = bcm_enet_ioctl, diff --git a/drivers/net/bcm63xx_enet.h b/drivers/net/bcm63xx_enet.h index bd3684d42d74..0e3048b788c2 100644 --- a/drivers/net/bcm63xx_enet.h +++ b/drivers/net/bcm63xx_enet.h @@ -274,7 +274,6 @@ struct bcm_enet_priv { int pause_tx; /* stats */ - struct net_device_stats stats; struct bcm_enet_mib_counters mib; /* after mib interrupt, mib registers update is done in this -- cgit v1.2.3-59-g8ed1b From 633adf1ad1c92c02bd3f10bbd73737a969179378 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 Aug 2010 14:49:58 +0200 Subject: cfg80211: mark ieee80211_hdrlen const This function analyses only its single, value-passed argument, and has no side effects. Thus it can be const, which makes mac80211 smaller, for example: text data bss dec hex filename 362518 16720 884 380122 5ccda mac80211.ko (before) 362358 16720 884 379962 5cc3a mac80211.ko (after) a 160 byte saving in text size, and an optimisation because the function won't be called as often. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 2 +- net/wireless/util.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2fd06c60ffbb..2b403c7ee32e 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1715,7 +1715,7 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); * ieee80211_hdrlen - get header length in bytes from frame control * @fc: frame control field in little-endian format */ -unsigned int ieee80211_hdrlen(__le16 fc); +unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); /** * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3 diff --git a/net/wireless/util.c b/net/wireless/util.c index 0c8a1e8b7690..1eb24162be61 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -221,7 +221,7 @@ const unsigned char bridge_tunnel_header[] __aligned(2) = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; EXPORT_SYMBOL(bridge_tunnel_header); -unsigned int ieee80211_hdrlen(__le16 fc) +unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc) { unsigned int hdrlen = 24; -- cgit v1.2.3-59-g8ed1b From ac4c977d16d843f12901595c91773dddb65768a9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 Aug 2010 15:37:29 +0200 Subject: mac80211: remove unused don't-encrypt flag When MFP is disabled, action frames will not be encrypted since they are management frames and the only management frames that can then be encrypted are authentication frames. Therefore, setting the don't-encrypt flag on action frames is unnecessary. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9a35d9e7efd7..f9a317766136 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1555,8 +1555,6 @@ static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, return -ENOLINK; break; case NL80211_IFTYPE_STATION: - if (!(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED)) - flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; break; default: return -EOPNOTSUPP; -- cgit v1.2.3-59-g8ed1b From 2e161f78e5f63a7f9fd25a766bb7f816a01eb14a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 Aug 2010 15:38:38 +0200 Subject: cfg80211/mac80211: extensible frame processing Allow userspace to register for more than just action frames by giving the frame subtype, and make it possible to use this in various modes as well. With some tweaks and some added functionality this will, in the future, also be usable in AP mode and be able to replace the cooked monitor interface currently used in that case. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 93 +++++++++++++++++++++++------ include/net/cfg80211.h | 56 +++++++++++------- net/mac80211/cfg.c | 12 ++-- net/mac80211/ieee80211_i.h | 1 + net/mac80211/iface.c | 6 +- net/mac80211/main.c | 37 ++++++++++++ net/mac80211/rx.c | 137 +++++++++++++++++++++++++++++------------- net/mac80211/status.c | 2 +- net/mac80211/util.c | 6 +- net/wireless/core.c | 8 +-- net/wireless/core.h | 21 +++---- net/wireless/mlme.c | 144 +++++++++++++++++++++++++++++---------------- net/wireless/nl80211.c | 108 +++++++++++++++++++++++++--------- net/wireless/nl80211.h | 14 ++--- net/wireless/util.c | 2 +- 15 files changed, 452 insertions(+), 195 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 2c8701687336..8af1e66c3cf9 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -39,6 +39,43 @@ * TODO: need more info? */ +/** + * DOC: Frame transmission/registration support + * + * Frame transmission and registration support exists to allow userspace + * management entities such as wpa_supplicant react to management frames + * that are not being handled by the kernel. This includes, for example, + * certain classes of action frames that cannot be handled in the kernel + * for various reasons. + * + * Frame registration is done on a per-interface basis and registrations + * cannot be removed other than by closing the socket. It is possible to + * specify a registration filter to register, for example, only for a + * certain type of action frame. In particular with action frames, those + * that userspace registers for will not be returned as unhandled by the + * driver, so that the registered application has to take responsibility + * for doing that. + * + * The type of frame that can be registered for is also dependent on the + * driver and interface type. The frame types are advertised in wiphy + * attributes so applications know what to expect. + * + * NOTE: When an interface changes type while registrations are active, + * these registrations are ignored until the interface type is + * changed again. This means that changing the interface type can + * lead to a situation that couldn't otherwise be produced, but + * any such registrations will be dormant in the sense that they + * will not be serviced, i.e. they will not receive any frames. + * + * Frame transmission allows userspace to send for example the required + * responses to action frames. It is subject to some sanity checking, + * but many frames can be transmitted. When a frame was transmitted, its + * status is indicated to the sending socket. + * + * For more technical details, see the corresponding command descriptions + * below. + */ + /** * enum nl80211_commands - supported nl80211 commands * @@ -301,16 +338,18 @@ * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface * and @NL80211_ATTR_TX_RATES the set of allowed rates. * - * @NL80211_CMD_REGISTER_ACTION: Register for receiving certain action frames - * (via @NL80211_CMD_ACTION) for processing in userspace. This command - * requires an interface index and a match attribute containing the first - * few bytes of the frame that should match, e.g. a single byte for only - * a category match or four bytes for vendor frames including the OUI. - * The registration cannot be dropped, but is removed automatically - * when the netlink socket is closed. Multiple registrations can be made. - * @NL80211_CMD_ACTION: Action frame TX request and RX notification. This - * command is used both as a request to transmit an Action frame and as an - * event indicating reception of an Action frame that was not processed in + * @NL80211_CMD_REGISTER_FRAME: Register for receiving certain mgmt frames + * (via @NL80211_CMD_FRAME) for processing in userspace. This command + * requires an interface index, a frame type attribute (optional for + * backward compatibility reasons, if not given assumes action frames) + * and a match attribute containing the first few bytes of the frame + * that should match, e.g. a single byte for only a category match or + * four bytes for vendor frames including the OUI. The registration + * cannot be dropped, but is removed automatically when the netlink + * socket is closed. Multiple registrations can be made. + * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This + * command is used both as a request to transmit a management frame and + * as an event indicating reception of a frame that was not processed in * kernel code, but is for us (i.e., which may need to be processed in a * user space application). %NL80211_ATTR_FRAME is used to specify the * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and @@ -320,8 +359,8 @@ * operational channel). When called, this operation returns a cookie * (%NL80211_ATTR_COOKIE) that will be included with the TX status event * pertaining to the TX request. - * @NL80211_CMD_ACTION_TX_STATUS: Report TX status of an Action frame - * transmitted with %NL80211_CMD_ACTION. %NL80211_ATTR_COOKIE identifies + * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame + * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies * the TX command and %NL80211_ATTR_FRAME includes the contents of the * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged * the frame. @@ -429,9 +468,12 @@ enum nl80211_commands { NL80211_CMD_SET_TX_BITRATE_MASK, - NL80211_CMD_REGISTER_ACTION, - NL80211_CMD_ACTION, - NL80211_CMD_ACTION_TX_STATUS, + NL80211_CMD_REGISTER_FRAME, + NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME, + NL80211_CMD_FRAME, + NL80211_CMD_ACTION = NL80211_CMD_FRAME, + NL80211_CMD_FRAME_TX_STATUS, + NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS, NL80211_CMD_SET_POWER_SAVE, NL80211_CMD_GET_POWER_SAVE, @@ -708,7 +750,16 @@ enum nl80211_commands { * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. * * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain - * at least one byte, currently used with @NL80211_CMD_REGISTER_ACTION. + * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. + * @NL80211_ATTR_FRAME_TYPE: A u16 indicating the frame type/subtype for the + * @NL80211_CMD_REGISTER_FRAME command. + * @NL80211_ATTR_TX_FRAME_TYPES: wiphy capability attribute, which is a + * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing + * information about which frame types can be transmitted with + * %NL80211_CMD_FRAME. + * @NL80211_ATTR_RX_FRAME_TYPES: wiphy capability attribute, which is a + * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing + * information about which frame types can be registered for RX. * * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was * acknowledged by the recipient. @@ -891,6 +942,10 @@ enum nl80211_attrs { NL80211_ATTR_WIPHY_TX_POWER_SETTING, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, + NL80211_ATTR_TX_FRAME_TYPES, + NL80211_ATTR_RX_FRAME_TYPES, + NL80211_ATTR_FRAME_TYPE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -947,7 +1002,7 @@ enum nl80211_attrs { * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames * @NL80211_IFTYPE_MESH_POINT: mesh point * @NL80211_IFTYPE_MAX: highest interface type number currently defined - * @__NL80211_IFTYPE_AFTER_LAST: internal use + * @NUM_NL80211_IFTYPES: number of defined interface types * * These values are used with the %NL80211_ATTR_IFTYPE * to set the type of an interface. @@ -964,8 +1019,8 @@ enum nl80211_iftype { NL80211_IFTYPE_MESH_POINT, /* keep last */ - __NL80211_IFTYPE_AFTER_LAST, - NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1 + NUM_NL80211_IFTYPES, + NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1 }; /** diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2b403c7ee32e..6a98b1b3bfde 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1020,7 +1020,7 @@ struct cfg80211_pmksa { * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. * This allows the operation to be terminated prior to timeout based on * the duration value. - * @action: Transmit an action frame + * @mgmt_tx: Transmit a management frame * * @testmode_cmd: run a test mode command * @@ -1172,7 +1172,7 @@ struct cfg80211_ops { struct net_device *dev, u64 cookie); - int (*action)(struct wiphy *wiphy, struct net_device *dev, + int (*mgmt_tx)(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, bool channel_type_valid, @@ -1236,6 +1236,10 @@ struct mac_address { u8 addr[ETH_ALEN]; }; +struct ieee80211_txrx_stypes { + u16 tx, rx; +}; + /** * struct wiphy - wireless hardware description * @reg_notifier: the driver's regulatory notification callback @@ -1286,6 +1290,10 @@ struct mac_address { * @privid: a pointer that drivers can use to identify if an arbitrary * wiphy is theirs, e.g. in global notifiers * @bands: information about bands/channels supported by this device + * + * @mgmt_stypes: bitmasks of frame subtypes that can be subscribed to or + * transmitted through nl80211, points to an array indexed by interface + * type */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -1294,9 +1302,12 @@ struct wiphy { u8 perm_addr[ETH_ALEN]; u8 addr_mask[ETH_ALEN]; - u16 n_addresses; struct mac_address *addresses; + const struct ieee80211_txrx_stypes *mgmt_stypes; + + u16 n_addresses; + /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ u16 interface_modes; @@ -1492,8 +1503,8 @@ struct cfg80211_cached_keys; * set by driver (if supported) on add_interface BEFORE registering the * netdev and may otherwise be used by driver read-only, will be update * by cfg80211 on change_interface - * @action_registrations: list of registrations for action frames - * @action_registrations_lock: lock for the list + * @mgmt_registrations: list of registrations for management frames + * @mgmt_registrations_lock: lock for the list * @mtx: mutex used to lock data in this struct * @cleanup_work: work struct used for cleanup that can't be done directly */ @@ -1505,8 +1516,8 @@ struct wireless_dev { struct list_head list; struct net_device *netdev; - struct list_head action_registrations; - spinlock_t action_registrations_lock; + struct list_head mgmt_registrations; + spinlock_t mgmt_registrations_lock; struct mutex mtx; @@ -2373,38 +2384,39 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, struct station_info *sinfo, gfp_t gfp); /** - * cfg80211_rx_action - notification of received, unprocessed Action frame + * cfg80211_rx_mgmt - notification of received, unprocessed management frame * @dev: network device * @freq: Frequency on which the frame was received in MHz - * @buf: Action frame (header + body) + * @buf: Management frame (header + body) * @len: length of the frame data * @gfp: context flags - * Returns %true if a user space application is responsible for rejecting the - * unrecognized Action frame; %false if no such application is registered - * (i.e., the driver is responsible for rejecting the unrecognized Action - * frame) + * + * Returns %true if a user space application has registered for this frame. + * For action frames, that makes it responsible for rejecting unrecognized + * action frames; %false otherwise, in which case for action frames the + * driver is responsible for rejecting the frame. * * This function is called whenever an Action frame is received for a station * mode interface, but is not processed in kernel. */ -bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, - size_t len, gfp_t gfp); +bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, + size_t len, gfp_t gfp); /** - * cfg80211_action_tx_status - notification of TX status for Action frame + * cfg80211_mgmt_tx_status - notification of TX status for management frame * @dev: network device - * @cookie: Cookie returned by cfg80211_ops::action() - * @buf: Action frame (header + body) + * @cookie: Cookie returned by cfg80211_ops::mgmt_tx() + * @buf: Management frame (header + body) * @len: length of the frame data * @ack: Whether frame was acknowledged * @gfp: context flags * - * This function is called whenever an Action frame was requested to be - * transmitted with cfg80211_ops::action() to report the TX status of the + * This function is called whenever a management frame was requested to be + * transmitted with cfg80211_ops::mgmt_tx() to report the TX status of the * transmission attempt. */ -void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, - const u8 *buf, size_t len, bool ack, gfp_t gfp); +void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie, + const u8 *buf, size_t len, bool ack, gfp_t gfp); /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f9a317766136..94787d21282c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1521,11 +1521,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); } -static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type, - bool channel_type_valid, - const u8 *buf, size_t len, u64 *cookie) +static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, + const u8 *buf, size_t len, u64 *cookie) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; @@ -1625,6 +1625,6 @@ struct cfg80211_ops mac80211_config_ops = { .set_bitrate_mask = ieee80211_set_bitrate_mask, .remain_on_channel = ieee80211_remain_on_channel, .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, - .action = ieee80211_action, + .mgmt_tx = ieee80211_mgmt_tx, .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, }; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 1bf05bfd149d..e73ae51dc036 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -170,6 +170,7 @@ typedef unsigned __bitwise__ ieee80211_rx_result; #define IEEE80211_RX_RA_MATCH BIT(1) #define IEEE80211_RX_AMSDU BIT(2) #define IEEE80211_RX_FRAGMENTED BIT(3) +#define IEEE80211_MALFORMED_ACTION_FRM BIT(4) /* only add flags here that do not change with subframes of an aMPDU */ struct ieee80211_rx_data { diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 9459aeee0ddc..86f434f234ae 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -177,7 +177,7 @@ static int ieee80211_open(struct net_device *dev) /* no special treatment */ break; case NL80211_IFTYPE_UNSPECIFIED: - case __NL80211_IFTYPE_AFTER_LAST: + case NUM_NL80211_IFTYPES: /* cannot happen */ WARN_ON(1); break; @@ -634,7 +634,7 @@ static void ieee80211_teardown_sdata(struct net_device *dev) case NL80211_IFTYPE_MONITOR: break; case NL80211_IFTYPE_UNSPECIFIED: - case __NL80211_IFTYPE_AFTER_LAST: + case NUM_NL80211_IFTYPES: BUG(); break; } @@ -886,7 +886,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, case NL80211_IFTYPE_AP_VLAN: break; case NL80211_IFTYPE_UNSPECIFIED: - case __NL80211_IFTYPE_AFTER_LAST: + case NUM_NL80211_IFTYPES: BUG(); break; } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0afccda42a24..a53feac4618c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -417,6 +417,41 @@ void ieee80211_napi_complete(struct ieee80211_hw *hw) } EXPORT_SYMBOL(ieee80211_napi_complete); +/* There isn't a lot of sense in it, but you can transmit anything you like */ +static const struct ieee80211_txrx_stypes +ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_ADHOC] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4), + }, + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4), + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4), + }, + [NL80211_IFTYPE_AP_VLAN] = { + /* copy AP */ + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4), + }, +}; + struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, const struct ieee80211_ops *ops) { @@ -446,6 +481,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, if (!wiphy) return NULL; + wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; + wiphy->flags |= WIPHY_FLAG_NETNS_OK | WIPHY_FLAG_4ADDR_AP | WIPHY_FLAG_4ADDR_STATION; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 4fdbed58ca2f..aa41e382bbb3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1939,14 +1939,37 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, ieee80211_tx_skb(sdata, skb); } +static ieee80211_rx_result debug_noinline +ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) +{ + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; + + /* + * From here on, look only at management frames. + * Data and control frames are already handled, + * and unknown (reserved) frames are useless. + */ + if (rx->skb->len < 24) + return RX_DROP_MONITOR; + + if (!ieee80211_is_mgmt(mgmt->frame_control)) + return RX_DROP_MONITOR; + + if (!(rx->flags & IEEE80211_RX_RA_MATCH)) + return RX_DROP_MONITOR; + + if (ieee80211_drop_unencrypted_mgmt(rx)) + return RX_DROP_UNUSABLE; + + return RX_CONTINUE; +} + static ieee80211_rx_result debug_noinline ieee80211_rx_h_action(struct ieee80211_rx_data *rx) { struct ieee80211_local *local = rx->local; struct ieee80211_sub_if_data *sdata = rx->sdata; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; - struct sk_buff *nskb; - struct ieee80211_rx_status *status; int len = rx->skb->len; if (!ieee80211_is_action(mgmt->frame_control)) @@ -1962,9 +1985,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_UNUSABLE; - if (ieee80211_drop_unencrypted_mgmt(rx)) - return RX_DROP_UNUSABLE; - switch (mgmt->u.action.category) { case WLAN_CATEGORY_BACK: /* @@ -2055,17 +2075,36 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) goto queue; } + return RX_CONTINUE; + invalid: - /* - * For AP mode, hostapd is responsible for handling any action - * frames that we didn't handle, including returning unknown - * ones. For all other modes we will return them to the sender, - * setting the 0x80 bit in the action category, as required by - * 802.11-2007 7.3.1.11. - */ - if (sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - return RX_DROP_MONITOR; + rx->flags |= IEEE80211_MALFORMED_ACTION_FRM; + /* will return in the next handlers */ + return RX_CONTINUE; + + handled: + if (rx->sta) + rx->sta->rx_packets++; + dev_kfree_skb(rx->skb); + return RX_QUEUED; + + queue: + rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; + skb_queue_tail(&sdata->skb_queue, rx->skb); + ieee80211_queue_work(&local->hw, &sdata->work); + if (rx->sta) + rx->sta->rx_packets++; + return RX_QUEUED; +} + +static ieee80211_rx_result debug_noinline +ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) +{ + struct ieee80211_rx_status *status; + + /* skip known-bad action frames and return them in the next handler */ + if (rx->flags & IEEE80211_MALFORMED_ACTION_FRM) + return RX_CONTINUE; /* * Getting here means the kernel doesn't know how to handle @@ -2075,10 +2114,44 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) */ status = IEEE80211_SKB_RXCB(rx->skb); - if (cfg80211_rx_action(rx->sdata->dev, status->freq, - rx->skb->data, rx->skb->len, - GFP_ATOMIC)) - goto handled; + if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, + rx->skb->data, rx->skb->len, + GFP_ATOMIC)) { + if (rx->sta) + rx->sta->rx_packets++; + dev_kfree_skb(rx->skb); + return RX_QUEUED; + } + + + return RX_CONTINUE; +} + +static ieee80211_rx_result debug_noinline +ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) +{ + struct ieee80211_local *local = rx->local; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; + struct sk_buff *nskb; + struct ieee80211_sub_if_data *sdata = rx->sdata; + + if (!ieee80211_is_action(mgmt->frame_control)) + return RX_CONTINUE; + + /* + * For AP mode, hostapd is responsible for handling any action + * frames that we didn't handle, including returning unknown + * ones. For all other modes we will return them to the sender, + * setting the 0x80 bit in the action category, as required by + * 802.11-2007 7.3.1.11. + * Newer versions of hostapd shall also use the management frame + * registration mechanisms, but older ones still use cooked + * monitor interfaces so push all frames there. + */ + if (!(rx->flags & IEEE80211_MALFORMED_ACTION_FRM) && + (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) + return RX_DROP_MONITOR; /* do not return rejected action frames */ if (mgmt->u.action.category & 0x80) @@ -2097,20 +2170,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) ieee80211_tx_skb(rx->sdata, nskb); } - - handled: - if (rx->sta) - rx->sta->rx_packets++; dev_kfree_skb(rx->skb); return RX_QUEUED; - - queue: - rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; - skb_queue_tail(&sdata->skb_queue, rx->skb); - ieee80211_queue_work(&local->hw, &sdata->work); - if (rx->sta) - rx->sta->rx_packets++; - return RX_QUEUED; } static ieee80211_rx_result debug_noinline @@ -2121,15 +2182,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; __le16 stype; - if (!(rx->flags & IEEE80211_RX_RA_MATCH)) - return RX_DROP_MONITOR; - - if (rx->skb->len < 24) - return RX_DROP_MONITOR; - - if (ieee80211_drop_unencrypted_mgmt(rx)) - return RX_DROP_UNUSABLE; - rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); if (rxs != RX_CONTINUE) return rxs; @@ -2374,7 +2426,10 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, if (res != RX_CONTINUE) goto rxh_next; + CALL_RXH(ieee80211_rx_h_mgmt_check) CALL_RXH(ieee80211_rx_h_action) + CALL_RXH(ieee80211_rx_h_userspace_mgmt) + CALL_RXH(ieee80211_rx_h_action_return) CALL_RXH(ieee80211_rx_h_mgmt) rxh_next: @@ -2527,7 +2582,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, break; case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_UNSPECIFIED: - case __NL80211_IFTYPE_AFTER_LAST: + case NUM_NL80211_IFTYPES: /* should never get here */ WARN_ON(1); break; diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 10caec5ea8fa..67a35841bef0 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -296,7 +296,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) } if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) - cfg80211_action_tx_status( + cfg80211_mgmt_tx_status( skb->dev, (unsigned long) skb, skb->data, skb->len, !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 748387d45bc0..cd2b485fed4f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -471,7 +471,7 @@ void ieee80211_iterate_active_interfaces( list_for_each_entry(sdata, &local->interfaces, list) { switch (sdata->vif.type) { - case __NL80211_IFTYPE_AFTER_LAST: + case NUM_NL80211_IFTYPES: case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_AP_VLAN: @@ -505,7 +505,7 @@ void ieee80211_iterate_active_interfaces_atomic( list_for_each_entry_rcu(sdata, &local->interfaces, list) { switch (sdata->vif.type) { - case __NL80211_IFTYPE_AFTER_LAST: + case NUM_NL80211_IFTYPES: case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_AP_VLAN: @@ -1189,7 +1189,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) /* ignore virtual */ break; case NL80211_IFTYPE_UNSPECIFIED: - case __NL80211_IFTYPE_AFTER_LAST: + case NUM_NL80211_IFTYPES: WARN_ON(1); break; } diff --git a/net/wireless/core.c b/net/wireless/core.c index c70909c3eae4..d52630bbab04 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -433,7 +433,7 @@ int wiphy_register(struct wiphy *wiphy) /* sanity check ifmodes */ WARN_ON(!ifmodes); - ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; + ifmodes &= ((1 << NUM_NL80211_IFTYPES) - 1) & ~1; if (WARN_ON(ifmodes != wiphy->interface_modes)) wiphy->interface_modes = ifmodes; @@ -685,8 +685,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); INIT_LIST_HEAD(&wdev->event_list); spin_lock_init(&wdev->event_lock); - INIT_LIST_HEAD(&wdev->action_registrations); - spin_lock_init(&wdev->action_registrations_lock); + INIT_LIST_HEAD(&wdev->mgmt_registrations); + spin_lock_init(&wdev->mgmt_registrations_lock); mutex_lock(&rdev->devlist_mtx); list_add_rcu(&wdev->list, &rdev->netdev_list); @@ -806,7 +806,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, sysfs_remove_link(&dev->dev.kobj, "phy80211"); list_del_rcu(&wdev->list); rdev->devlist_generation++; - cfg80211_mlme_purge_actions(wdev); + cfg80211_mlme_purge_registrations(wdev); #ifdef CONFIG_CFG80211_WEXT kfree(wdev->wext.keys); #endif diff --git a/net/wireless/core.h b/net/wireless/core.h index 63d57ae399c3..58ab2c791d28 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -331,16 +331,17 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, const u8 *resp_ie, size_t resp_ie_len, u16 status, bool wextev, struct cfg80211_bss *bss); -int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, - const u8 *match_data, int match_len); -void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid); -void cfg80211_mlme_purge_actions(struct wireless_dev *wdev); -int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type, - bool channel_type_valid, - const u8 *buf, size_t len, u64 *cookie); +int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, + u16 frame_type, const u8 *match_data, + int match_len); +void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid); +void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); +int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, + const u8 *buf, size_t len, u64 *cookie); /* SME */ int __cfg80211_connect(struct cfg80211_registered_device *rdev, diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index ee0af32ed59e..8515b1e5c578 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -748,31 +748,51 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, } EXPORT_SYMBOL(cfg80211_new_sta); -struct cfg80211_action_registration { +struct cfg80211_mgmt_registration { struct list_head list; u32 nlpid; int match_len; + __le16 frame_type; + u8 match[]; }; -int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, - const u8 *match_data, int match_len) +int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, + u16 frame_type, const u8 *match_data, + int match_len) { - struct cfg80211_action_registration *reg, *nreg; + struct cfg80211_mgmt_registration *reg, *nreg; int err = 0; + u16 mgmt_type; + + if (!wdev->wiphy->mgmt_stypes) + return -EOPNOTSUPP; + + if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) + return -EINVAL; + + if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) + return -EINVAL; + + mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4; + if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type))) + return -EINVAL; nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); if (!nreg) return -ENOMEM; - spin_lock_bh(&wdev->action_registrations_lock); + spin_lock_bh(&wdev->mgmt_registrations_lock); - list_for_each_entry(reg, &wdev->action_registrations, list) { + list_for_each_entry(reg, &wdev->mgmt_registrations, list) { int mlen = min(match_len, reg->match_len); + if (frame_type != le16_to_cpu(reg->frame_type)) + continue; + if (memcmp(reg->match, match_data, mlen) == 0) { err = -EALREADY; break; @@ -787,62 +807,75 @@ int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, memcpy(nreg->match, match_data, match_len); nreg->match_len = match_len; nreg->nlpid = snd_pid; - list_add(&nreg->list, &wdev->action_registrations); + nreg->frame_type = cpu_to_le16(frame_type); + list_add(&nreg->list, &wdev->mgmt_registrations); out: - spin_unlock_bh(&wdev->action_registrations_lock); + spin_unlock_bh(&wdev->mgmt_registrations_lock); return err; } -void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid) +void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid) { - struct cfg80211_action_registration *reg, *tmp; + struct cfg80211_mgmt_registration *reg, *tmp; - spin_lock_bh(&wdev->action_registrations_lock); + spin_lock_bh(&wdev->mgmt_registrations_lock); - list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { + list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { if (reg->nlpid == nlpid) { list_del(®->list); kfree(reg); } } - spin_unlock_bh(&wdev->action_registrations_lock); + spin_unlock_bh(&wdev->mgmt_registrations_lock); } -void cfg80211_mlme_purge_actions(struct wireless_dev *wdev) +void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev) { - struct cfg80211_action_registration *reg, *tmp; + struct cfg80211_mgmt_registration *reg, *tmp; - spin_lock_bh(&wdev->action_registrations_lock); + spin_lock_bh(&wdev->mgmt_registrations_lock); - list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { + list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { list_del(®->list); kfree(reg); } - spin_unlock_bh(&wdev->action_registrations_lock); + spin_unlock_bh(&wdev->mgmt_registrations_lock); } -int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type, - bool channel_type_valid, - const u8 *buf, size_t len, u64 *cookie) +int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, + const u8 *buf, size_t len, u64 *cookie) { struct wireless_dev *wdev = dev->ieee80211_ptr; const struct ieee80211_mgmt *mgmt; + u16 stype; + + if (!wdev->wiphy->mgmt_stypes) + return -EOPNOTSUPP; - if (rdev->ops->action == NULL) + if (!rdev->ops->mgmt_tx) return -EOPNOTSUPP; + if (len < 24 + 1) return -EINVAL; mgmt = (const struct ieee80211_mgmt *) buf; - if (!ieee80211_is_action(mgmt->frame_control)) + + if (!ieee80211_is_mgmt(mgmt->frame_control)) return -EINVAL; - if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { + + stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; + if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4))) + return -EINVAL; + + if (ieee80211_is_action(mgmt->frame_control) && + mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { /* Verify that we are associated with the destination AP */ wdev_lock(wdev); @@ -863,64 +896,75 @@ int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, return -EINVAL; /* Transmit the Action frame as requested by user space */ - return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type, - channel_type_valid, buf, len, cookie); + return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, channel_type, + channel_type_valid, buf, len, cookie); } -bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, - size_t len, gfp_t gfp) +bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, + size_t len, gfp_t gfp) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - struct cfg80211_action_registration *reg; - const u8 *action_data; - int action_data_len; + struct cfg80211_mgmt_registration *reg; + const struct ieee80211_txrx_stypes *stypes = + &wiphy->mgmt_stypes[wdev->iftype]; + struct ieee80211_mgmt *mgmt = (void *)buf; + const u8 *data; + int data_len; bool result = false; + __le16 ftype = mgmt->frame_control & + cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE); + u16 stype; - /* frame length - min size excluding category */ - action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1); + stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4; - /* action data starts with category */ - action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1; + if (!(stypes->rx & BIT(stype))) + return false; - spin_lock_bh(&wdev->action_registrations_lock); + data = buf + ieee80211_hdrlen(mgmt->frame_control); + data_len = len - ieee80211_hdrlen(mgmt->frame_control); + + spin_lock_bh(&wdev->mgmt_registrations_lock); + + list_for_each_entry(reg, &wdev->mgmt_registrations, list) { + if (reg->frame_type != ftype) + continue; - list_for_each_entry(reg, &wdev->action_registrations, list) { - if (reg->match_len > action_data_len) + if (reg->match_len > data_len) continue; - if (memcmp(reg->match, action_data, reg->match_len)) + if (memcmp(reg->match, data, reg->match_len)) continue; /* found match! */ /* Indicate the received Action frame to user space */ - if (nl80211_send_action(rdev, dev, reg->nlpid, freq, - buf, len, gfp)) + if (nl80211_send_mgmt(rdev, dev, reg->nlpid, freq, + buf, len, gfp)) continue; result = true; break; } - spin_unlock_bh(&wdev->action_registrations_lock); + spin_unlock_bh(&wdev->mgmt_registrations_lock); return result; } -EXPORT_SYMBOL(cfg80211_rx_action); +EXPORT_SYMBOL(cfg80211_rx_mgmt); -void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, - const u8 *buf, size_t len, bool ack, gfp_t gfp) +void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie, + const u8 *buf, size_t len, bool ack, gfp_t gfp) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); /* Indicate TX status of the Action frame to user space */ - nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); + nl80211_send_mgmt_tx_status(rdev, dev, cookie, buf, len, ack, gfp); } -EXPORT_SYMBOL(cfg80211_action_tx_status); +EXPORT_SYMBOL(cfg80211_mgmt_tx_status); void cfg80211_cqm_rssi_notify(struct net_device *dev, enum nl80211_cqm_rssi_threshold_event rssi_event, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index bb5b78eebeb2..927ffbd2aebc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -156,6 +156,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, + [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, }; /* policy for the attributes */ @@ -437,6 +438,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct ieee80211_rate *rate; int i; u16 ifmodes = dev->wiphy.interface_modes; + const struct ieee80211_txrx_stypes *mgmt_stypes = + dev->wiphy.mgmt_stypes; hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); if (!hdr) @@ -587,7 +590,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(flush_pmksa, FLUSH_PMKSA); CMD(remain_on_channel, REMAIN_ON_CHANNEL); CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); - CMD(action, ACTION); + CMD(mgmt_tx, FRAME); if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { i++; NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); @@ -608,6 +611,53 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, nla_nest_end(msg, nl_cmds); + if (mgmt_stypes) { + u16 stypes; + struct nlattr *nl_ftypes, *nl_ifs; + enum nl80211_iftype ift; + + nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); + if (!nl_ifs) + goto nla_put_failure; + + for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { + nl_ftypes = nla_nest_start(msg, ift); + if (!nl_ftypes) + goto nla_put_failure; + i = 0; + stypes = mgmt_stypes[ift].tx; + while (stypes) { + if (stypes & 1) + NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, + (i << 4) | IEEE80211_FTYPE_MGMT); + stypes >>= 1; + i++; + } + nla_nest_end(msg, nl_ftypes); + } + + nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); + if (!nl_ifs) + goto nla_put_failure; + + for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { + nl_ftypes = nla_nest_start(msg, ift); + if (!nl_ftypes) + goto nla_put_failure; + i = 0; + stypes = mgmt_stypes[ift].rx; + while (stypes) { + if (stypes & 1) + NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, + (i << 4) | IEEE80211_FTYPE_MGMT); + stypes >>= 1; + i++; + } + nla_nest_end(msg, nl_ftypes); + } + nla_nest_end(msg, nl_ifs); + } + return genlmsg_end(msg, hdr); nla_put_failure: @@ -4732,17 +4782,18 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, return err; } -static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) +static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev; struct net_device *dev; + u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION; int err; if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) return -EINVAL; - if (nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]) < 1) - return -EINVAL; + if (info->attrs[NL80211_ATTR_FRAME_TYPE]) + frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]); rtnl_lock(); @@ -4757,12 +4808,13 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) } /* not much point in registering if we can't reply */ - if (!rdev->ops->action) { + if (!rdev->ops->mgmt_tx) { err = -EOPNOTSUPP; goto out; } - err = cfg80211_mlme_register_action(dev->ieee80211_ptr, info->snd_pid, + err = cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid, + frame_type, nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); out: @@ -4773,7 +4825,7 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) return err; } -static int nl80211_action(struct sk_buff *skb, struct genl_info *info) +static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev; struct net_device *dev; @@ -4796,7 +4848,7 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info) if (err) goto unlock_rtnl; - if (!rdev->ops->action) { + if (!rdev->ops->mgmt_tx) { err = -EOPNOTSUPP; goto out; } @@ -4839,17 +4891,17 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info) } hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, - NL80211_CMD_ACTION); + NL80211_CMD_FRAME); if (IS_ERR(hdr)) { err = PTR_ERR(hdr); goto free_msg; } - err = cfg80211_mlme_action(rdev, dev, chan, channel_type, - channel_type_valid, - nla_data(info->attrs[NL80211_ATTR_FRAME]), - nla_len(info->attrs[NL80211_ATTR_FRAME]), - &cookie); + err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, channel_type, + channel_type_valid, + nla_data(info->attrs[NL80211_ATTR_FRAME]), + nla_len(info->attrs[NL80211_ATTR_FRAME]), + &cookie); if (err) goto free_msg; @@ -5348,14 +5400,14 @@ static struct genl_ops nl80211_ops[] = { .flags = GENL_ADMIN_PERM, }, { - .cmd = NL80211_CMD_REGISTER_ACTION, - .doit = nl80211_register_action, + .cmd = NL80211_CMD_REGISTER_FRAME, + .doit = nl80211_register_mgmt, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, { - .cmd = NL80211_CMD_ACTION, - .doit = nl80211_action, + .cmd = NL80211_CMD_FRAME, + .doit = nl80211_tx_mgmt, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, @@ -6055,9 +6107,9 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, nl80211_mlme_mcgrp.id, gfp); } -int nl80211_send_action(struct cfg80211_registered_device *rdev, - struct net_device *netdev, u32 nlpid, - int freq, const u8 *buf, size_t len, gfp_t gfp) +int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u32 nlpid, + int freq, const u8 *buf, size_t len, gfp_t gfp) { struct sk_buff *msg; void *hdr; @@ -6067,7 +6119,7 @@ int nl80211_send_action(struct cfg80211_registered_device *rdev, if (!msg) return -ENOMEM; - hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION); + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME); if (!hdr) { nlmsg_free(msg); return -ENOMEM; @@ -6095,10 +6147,10 @@ int nl80211_send_action(struct cfg80211_registered_device *rdev, return -ENOBUFS; } -void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, - struct net_device *netdev, u64 cookie, - const u8 *buf, size_t len, bool ack, - gfp_t gfp) +void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u64 cookie, + const u8 *buf, size_t len, bool ack, + gfp_t gfp) { struct sk_buff *msg; void *hdr; @@ -6107,7 +6159,7 @@ void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, if (!msg) return; - hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION_TX_STATUS); + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME_TX_STATUS); if (!hdr) { nlmsg_free(msg); return; @@ -6194,7 +6246,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb, list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) - cfg80211_mlme_unregister_actions(wdev, notify->pid); + cfg80211_mlme_unregister_socket(wdev, notify->pid); rcu_read_unlock(); diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 2ad7fbc7d9f1..30d2f939150d 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -74,13 +74,13 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *mac_addr, struct station_info *sinfo, gfp_t gfp); -int nl80211_send_action(struct cfg80211_registered_device *rdev, - struct net_device *netdev, u32 nlpid, int freq, - const u8 *buf, size_t len, gfp_t gfp); -void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, - struct net_device *netdev, u64 cookie, - const u8 *buf, size_t len, bool ack, - gfp_t gfp); +int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u32 nlpid, int freq, + const u8 *buf, size_t len, gfp_t gfp); +void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u64 cookie, + const u8 *buf, size_t len, bool ack, + gfp_t gfp); void nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, diff --git a/net/wireless/util.c b/net/wireless/util.c index 1eb24162be61..8d961cc4ae98 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -823,7 +823,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, /* monitor can't bridge anyway */ break; case NL80211_IFTYPE_UNSPECIFIED: - case __NL80211_IFTYPE_AFTER_LAST: + case NUM_NL80211_IFTYPES: /* not happening */ break; } -- cgit v1.2.3-59-g8ed1b From 418de6d955fa1da0cb4332661a31d21f57e954ab Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 15 Aug 2010 13:03:10 -0400 Subject: ath5k: rename ath5k_hw_set_associd to _set_bssid Although the named function also sets the aid, its main purpose is configuring the bssid and we use that everywhere else. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 2 +- drivers/net/wireless/ath/ath5k/attach.c | 2 +- drivers/net/wireless/ath/ath5k/base.c | 4 ++-- drivers/net/wireless/ath/ath5k/pcu.c | 13 ++++++------- drivers/net/wireless/ath/ath5k/reset.c | 2 +- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ea6362a8988d..9129e51b4f18 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1190,7 +1190,7 @@ extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); /* BSSID Functions */ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); -void ath5k_hw_set_associd(struct ath5k_hw *ah); +void ath5k_hw_set_bssid(struct ath5k_hw *ah); void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); /* Receive start/stop functions */ void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index b32e28caeee2..e72a1e5421d7 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -329,7 +329,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); - ath5k_hw_set_associd(ah); + ath5k_hw_set_bssid(ah); ath5k_hw_set_opmode(ah, sc->opmode); ath5k_hw_rfgain_opt_init(ah); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a729b8774670..0378bbcce494 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -3476,7 +3476,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, /* Cache for later use during resets */ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); common->curaid = 0; - ath5k_hw_set_associd(ah); + ath5k_hw_set_bssid(ah); mmiowb(); } @@ -3494,7 +3494,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, "Bss Info ASSOC %d, bssid: %pM\n", bss_conf->aid, common->curbssid); common->curaid = bss_conf->aid; - ath5k_hw_set_associd(ah); + ath5k_hw_set_bssid(ah); /* Once ANI is available you would start it here */ } } diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index af273358c7cb..3fef5931ec3a 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -308,27 +308,26 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) } /** - * ath5k_hw_set_associd - Set BSSID for association + * ath5k_hw_set_bssid - Set current BSSID on hw * * @ah: The &struct ath5k_hw - * @bssid: BSSID - * @assoc_id: Assoc id * - * Sets the BSSID which trigers the "SME Join" operation + * Sets the current BSSID and BSSID mask we have from the + * common struct into the hardware */ -void ath5k_hw_set_associd(struct ath5k_hw *ah) +void ath5k_hw_set_bssid(struct ath5k_hw *ah) { struct ath_common *common = ath5k_hw_common(ah); u16 tim_offset = 0; /* - * Set simple BSSID mask on 5212 + * Set BSSID mask on 5212 */ if (ah->ah_version == AR5K_AR5212) ath_hw_setbssidmask(common); /* - * Set BSSID which triggers the "SME Join" operation + * Set BSSID */ ath5k_hw_reg_write(ah, get_unaligned_le32(common->curbssid), diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 498aa28ea9e6..f5434eb7f980 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -1160,7 +1160,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, */ /* Restore bssid and bssid mask */ - ath5k_hw_set_associd(ah); + ath5k_hw_set_bssid(ah); /* Set PCU config */ ath5k_hw_set_opmode(ah, op_mode); -- cgit v1.2.3-59-g8ed1b From b61279809860690fe5c9fcb40441008d31fabab6 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 15 Aug 2010 13:03:11 -0400 Subject: ath5k: remove own (wrong) IEEE80211_MAX_LEN Use the version already supplied in include/linux/ieee80211.h. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 5 +---- drivers/net/wireless/ath/ath5k/base.c | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 9129e51b4f18..f399c4dd8e69 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -175,7 +175,7 @@ #define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 #define AR5K_TUNE_RADAR_ALERT false #define AR5K_TUNE_MIN_TX_FIFO_THRES 1 -#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1) +#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_FRAME_LEN / 64) + 1) #define AR5K_TUNE_REGISTER_TIMEOUT 20000 /* Register for RSSI threshold has a mask of 0xff, so 255 seems to * be the max value. */ @@ -343,9 +343,6 @@ struct ath5k_srev_name { #define AR5K_SREV_PHY_5413 0x61 #define AR5K_SREV_PHY_2425 0x70 -/* IEEE defs */ -#define IEEE80211_MAX_LEN 2500 - /* TODO add support to mac80211 for vendor-specific rates and modes */ /* diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 0378bbcce494..91241b4525ad 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1709,7 +1709,7 @@ ath5k_rx_start(struct ath5k_softc *sc) struct ath5k_buf *bf; int ret; - common->rx_bufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz); + common->rx_bufsize = roundup(IEEE80211_MAX_FRAME_LEN, common->cachelsz); ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n", common->cachelsz, common->rx_bufsize); -- cgit v1.2.3-59-g8ed1b From a180a13081708b78d42232c6d922ce3de63f12e0 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 15 Aug 2010 13:03:12 -0400 Subject: ath5k: clean up some comments This fixes a few misspellings, word repetitions, and some grammar nits in ath5k comments. No code changes. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ani.c | 6 ++-- drivers/net/wireless/ath/ath5k/attach.c | 6 ++-- drivers/net/wireless/ath/ath5k/base.c | 58 +++++++++++++++---------------- drivers/net/wireless/ath/ath5k/dma.c | 4 +-- drivers/net/wireless/ath/ath5k/eeprom.c | 4 +-- drivers/net/wireless/ath/ath5k/phy.c | 15 ++++---- drivers/net/wireless/ath/ath5k/reg.h | 2 +- drivers/net/wireless/ath/ath5k/reset.c | 22 ++++++------ drivers/net/wireless/ath/ath5k/rfbuffer.h | 4 +-- 9 files changed, 59 insertions(+), 62 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index 26dbe65fedb0..e4a5f046bba4 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c @@ -552,9 +552,9 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah) if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) return; - /* if one of the errors triggered, we can get a superfluous second - * interrupt, even though we have already reset the register. the - * function detects that so we can return early */ + /* If one of the errors triggered, we can get a superfluous second + * interrupt, even though we have already reset the register. The + * function detects that so we can return early. */ if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0) return; diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index e72a1e5421d7..aabad4f13e2a 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -139,12 +139,12 @@ int ath5k_hw_attach(struct ath5k_softc *sc) else ah->ah_version = AR5K_AR5212; - /*Fill the ath5k_hw struct with the needed functions*/ + /* Fill the ath5k_hw struct with the needed functions */ ret = ath5k_hw_init_desc_functions(ah); if (ret) goto err_free; - /* Bring device out of sleep and reset it's units */ + /* Bring device out of sleep and reset its units */ ret = ath5k_hw_nic_wakeup(ah, 0, true); if (ret) goto err_free; @@ -158,7 +158,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) CHANNEL_5GHZ); ah->ah_phy = AR5K_PHY(0); - /* Try to identify radio chip based on it's srev */ + /* Try to identify radio chip based on its srev */ switch (ah->ah_radio_5ghz_revision & 0xf0) { case AR5K_SREV_RAD_5111: ah->ah_radio = AR5K_RF5111; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 91241b4525ad..c3b614d2ef34 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -612,7 +612,7 @@ ath5k_pci_probe(struct pci_dev *pdev, goto err_free; } - /*If we passed the test malloc a ath5k_hw struct*/ + /* If we passed the test, malloc an ath5k_hw struct */ sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); if (!sc->ah) { ret = -ENOMEM; @@ -786,8 +786,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) /* * Check if the MAC has multi-rate retry support. * We do this by trying to setup a fake extended - * descriptor. MAC's that don't have support will - * return false w/o doing anything. MAC's that do + * descriptor. MACs that don't have support will + * return false w/o doing anything. MACs that do * support it will return true w/o doing anything. */ ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); @@ -827,7 +827,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) /* * Allocate hardware transmit queues: one queue for * beacon frames and one data queue for each QoS - * priority. Note that hw functions handle reseting + * priority. Note that hw functions handle resetting * these queues at the needed time. */ ret = ath5k_beaconq_setup(ah); @@ -909,7 +909,7 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) /* * NB: the order of these is important: * o call the 802.11 layer before detaching ath5k_hw to - * insure callbacks into the driver to delete global + * ensure callbacks into the driver to delete global * key cache entries can be handled * o reclaim the tx queue data structures after calling * the 802.11 layer as we'll get called back to reclaim @@ -1514,7 +1514,7 @@ ath5k_txq_setup(struct ath5k_softc *sc, /* * Enable interrupts only for EOL and DESC conditions. * We mark tx descriptors to receive a DESC interrupt - * when a tx queue gets deep; otherwise waiting for the + * when a tx queue gets deep; otherwise we wait for the * EOL to reap descriptors. Note that this is done to * reduce interrupt load and this only defers reaping * descriptors, never transmitting frames. Aside from @@ -1859,7 +1859,7 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) } /* - * Compute padding position. skb must contains an IEEE 802.11 frame + * Compute padding position. skb must contain an IEEE 802.11 frame */ static int ath5k_common_padpos(struct sk_buff *skb) { @@ -1878,10 +1878,9 @@ static int ath5k_common_padpos(struct sk_buff *skb) } /* - * This function expects a 802.11 frame and returns the number of - * bytes added, or -1 if we don't have enought header room. + * This function expects an 802.11 frame and returns the number of + * bytes added, or -1 if we don't have enough header room. */ - static int ath5k_add_padding(struct sk_buff *skb) { int padpos = ath5k_common_padpos(skb); @@ -1901,10 +1900,18 @@ static int ath5k_add_padding(struct sk_buff *skb) } /* - * This function expects a 802.11 frame and returns the number of - * bytes removed + * The MAC header is padded to have 32-bit boundary if the + * packet payload is non-zero. The general calculation for + * padsize would take into account odd header lengths: + * padsize = 4 - (hdrlen & 3); however, since only + * even-length headers are used, padding can only be 0 or 2 + * bytes and we can optimize this a bit. We must not try to + * remove padding from short control frames that do not have a + * payload. + * + * This function expects an 802.11 frame and returns the number of + * bytes removed. */ - static int ath5k_remove_padding(struct sk_buff *skb) { int padpos = ath5k_common_padpos(skb); @@ -1925,14 +1932,6 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, { struct ieee80211_rx_status *rxs; - /* The MAC header is padded to have 32-bit boundary if the - * packet payload is non-zero. The general calculation for - * padsize would take into account odd header lengths: - * padsize = (4 - hdrlen % 4) % 4; However, since only - * even-length headers are used, padding can only be 0 or 2 - * bytes and we can optimize this a bit. In addition, we must - * not try to remove padding from short control frames that do - * not have payload. */ ath5k_remove_padding(skb); rxs = IEEE80211_SKB_RXCB(skb); @@ -2281,10 +2280,11 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) * default antenna which is supposed to be an omni. * * Note2: On sectored scenarios it's possible to have - * multiple antennas (1omni -the default- and 14 sectors) - * so if we choose to actually support this mode we need - * to allow user to set how many antennas we have and tweak - * the code below to send beacons on all of them. + * multiple antennas (1 omni -- the default -- and 14 + * sectors), so if we choose to actually support this + * mode, we need to allow the user to set how many antennas + * we have and tweak the code below to send beacons + * on all of them. */ if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) antenna = sc->bsent & 4 ? 2 : 1; @@ -2333,7 +2333,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) } /* * Check if the previous beacon has gone out. If - * not don't don't try to post another, skip this + * not, don't don't try to post another: skip this * period and wait for the next. Missed beacons * indicate a problem and should not occur. If we * miss too many consecutive beacons reset the device. @@ -2905,8 +2905,8 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n"); /* - * the hardware expects the header padded to 4 byte boundaries - * if this is not the case we add the padding after the header + * The hardware expects the header padded to 4 byte boundaries. + * If this is not the case, we add the padding after the header. */ padsize = ath5k_add_padding(skb); if (padsize < 0) { @@ -3274,7 +3274,7 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, /* Set multicast bits */ ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); - /* Set the cached hw filter flags, this will alter actually + /* Set the cached hw filter flags, this will later actually * be set in HW */ sc->filter_flags = rfilt; diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 484f31870ba8..58bb6c5dda7b 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -377,11 +377,11 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) * * This function increases/decreases the tx trigger level for the tx fifo * buffer (aka FIFO threshold) that is used to indicate when PCU flushes - * the buffer and transmits it's data. Lowering this results sending small + * the buffer and transmits its data. Lowering this results sending small * frames more quickly but can lead to tx underruns, raising it a lot can * result other problems (i think bmiss is related). Right now we start with * the lowest possible (64Bytes) and if we get tx underrun we increase it using - * the increase flag. Returns -EIO if we have have reached maximum/minimum. + * the increase flag. Returns -EIO if we have reached maximum/minimum. * * XXX: Link this with tx DMA size ? * XXX: Use it to save interrupts ? diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index ae316fec4a6a..39722dd73e43 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -661,7 +661,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC * steps that match with the power values we read from eeprom. On * older eeprom versions (< 3.2) these steps are equaly spaced at - * 10% of the pcdac curve -until the curve reaches it's maximum- + * 10% of the pcdac curve -until the curve reaches its maximum- * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) * these 11 steps are spaced in a different way. This function returns * the pcdac steps based on eeprom version and curve min/max so that we @@ -1113,7 +1113,7 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) */ /* For RF2413 power calibration data doesn't start on a fixed location and - * if a mode is not supported, it's section is missing -not zeroed-. + * if a mode is not supported, its section is missing -not zeroed-. * So we need to calculate the starting offset for each section by using * these two functions */ diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 6284c389ba18..c7c446592374 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -115,7 +115,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, \**********************/ /* - * This code is used to optimize rf gain on different environments + * This code is used to optimize RF gain on different environments * (temperature mostly) based on feedback from a power detector. * * It's only used on RF5111 and RF5112, later RF chips seem to have @@ -302,7 +302,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) } /* Perform gain_F adjustment by choosing the right set - * of parameters from rf gain optimization ladder */ + * of parameters from RF gain optimization ladder */ static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) { const struct ath5k_gain_opt *go; @@ -367,7 +367,7 @@ done: return ret; } -/* Main callback for thermal rf gain calibration engine +/* Main callback for thermal RF gain calibration engine * Check for a new gain reading and schedule an adjustment * if needed. * @@ -433,7 +433,7 @@ done: return ah->ah_gain.g_state; } -/* Write initial rf gain table to set the RF sensitivity +/* Write initial RF gain table to set the RF sensitivity * this one works on all RF chips and has nothing to do * with gain_F calibration */ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) @@ -496,7 +496,7 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) /* - * Setup RF registers by writing rf buffer on hw + * Setup RF registers by writing RF buffer on hw */ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int mode) @@ -571,7 +571,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, return -EINVAL; } - /* If it's the first time we set rf buffer, allocate + /* If it's the first time we set RF buffer, allocate * ah->ah_rf_banks based on ah->ah_rf_banks_size * we set above */ if (ah->ah_rf_banks == NULL) { @@ -3035,9 +3035,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, /* Limit max power if we have a CTL available */ ath5k_get_max_ctl_power(ah, channel); - /* FIXME: Tx power limit for this regdomain - * XXX: Mac80211/CRDA will do that anyway ? */ - /* FIXME: Antenna reduction stuff */ /* FIXME: Limit power on turbo modes */ diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 55b4ac6d236f..05ef587ad2b4 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -1911,7 +1911,7 @@ #define AR5K_PHY_TURBO 0x9804 /* Register Address */ #define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ #define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */ -#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */ +#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo */ /* * PHY agility command register diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index f5434eb7f980..4154959125b6 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -959,7 +959,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, AR5K_QUEUE_DCU_SEQNUM(0)); } - /* TSF accelerates on AR5211 durring reset + /* TSF accelerates on AR5211 during reset * As a workaround save it here and restore * it later so that it's back in time after * reset. This way it'll get re-synced on the @@ -1080,7 +1080,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, return ret; /* Spur info is available only from EEPROM versions - * bigger than 5.3 but but the EEPOM routines will use + * greater than 5.3, but the EEPROM routines will use * static values for older versions */ if (ah->ah_mac_srev >= AR5K_SREV_AR5424) ath5k_hw_set_spur_mitigation_filter(ah, @@ -1173,11 +1173,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* Set RSSI/BRSSI thresholds * * Note: If we decide to set this value - * dynamicaly, have in mind that when AR5K_RSSI_THR - * register is read it might return 0x40 if we haven't - * wrote anything to it plus BMISS RSSI threshold is zeroed. + * dynamically, keep in mind that when AR5K_RSSI_THR + * register is read, it might return 0x40 if we haven't + * written anything to it. Also, BMISS RSSI threshold is zeroed. * So doing a save/restore procedure here isn't the right - * choice. Instead store it on ath5k_hw */ + * choice. Instead, store it in ath5k_hw */ ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S), @@ -1235,7 +1235,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* * Perform ADC test to see if baseband is ready - * Set tx hold and check adc test register + * Set TX hold and check ADC test register */ phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); @@ -1254,15 +1254,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, * * This method is used to calibrate some static offsets * used together with on-the fly I/Q calibration (the - * one performed via ath5k_hw_phy_calibrate), that doesn't + * one performed via ath5k_hw_phy_calibrate), which doesn't * interrupt rx path. * * While rx path is re-routed to the power detector we also - * start a noise floor calibration, to measure the + * start a noise floor calibration to measure the * card's noise floor (the noise we measure when we are not - * transmiting or receiving anything). + * transmitting or receiving anything). * - * If we are in a noisy environment AGC calibration may time + * If we are in a noisy environment, AGC calibration may time * out and/or noise floor calibration might timeout. */ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h index e50baff66175..3ac4cff4239d 100644 --- a/drivers/net/wireless/ath/ath5k/rfbuffer.h +++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h @@ -25,10 +25,10 @@ * * We don't write on those registers directly but * we send a data packet on the chip, using a special register, - * that holds all the settings we need. After we 've sent the + * that holds all the settings we need. After we've sent the * data packet, we write on another special register to notify hw * to apply the settings. This is done so that control registers - * can be dynamicaly programmed during operation and the settings + * can be dynamically programmed during operation and the settings * are applied faster on the hw. * * We call each data packet an "RF Bank" and all the data we write -- cgit v1.2.3-59-g8ed1b From 23538c268c834d73a2f3e65a06ea6bf218ba1a0e Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 15 Aug 2010 13:03:13 -0400 Subject: ath5k: remove monitor check in receive_frame_ok filter Monitor interfaces are never seen by the driver, so tests based on that opmode don't make sense. Also, we already pass all mic failure packets. Consequently this code is actually accepting any frames with just crypto errors and rejecting those with CRC, FIFO, and PHY errors for all interface types. Adjust the code and comment accordingly. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index c3b614d2ef34..166029913884 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2035,9 +2035,8 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) return true; } - /* let crypto-error packets fall through in MNTR */ - if ((rs->rs_status & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || - sc->opmode != NL80211_IFTYPE_MONITOR) + /* reject any frames with non-crypto errors */ + if (rs->rs_status & ~(AR5K_RXERR_DECRYPT)) return false; } -- cgit v1.2.3-59-g8ed1b From 4afd89d9cf17df46c3cfa1eb744232e345b3b0e6 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 15 Aug 2010 13:03:14 -0400 Subject: ath5k: remove all mention of monitor iftype Monitor interfaces are never seen by the driver so these cases are never reached. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 166029913884..99d56c6f06f1 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2325,8 +2325,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); - if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || - sc->opmode == NL80211_IFTYPE_MONITOR)) { + if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION)) { ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); return; } @@ -2900,9 +2899,6 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, ath5k_debug_dump_skb(sc, skb, "TX ", 1); - if (sc->opmode == NL80211_IFTYPE_MONITOR) - ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n"); - /* * The hardware expects the header padded to 4 byte boundaries. * If this is not the case, we add the padding after the header. @@ -3048,7 +3044,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_MONITOR: sc->opmode = vif->type; break; default: @@ -3250,7 +3245,6 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, switch (sc->opmode) { case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_MONITOR: rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ | -- cgit v1.2.3-59-g8ed1b From 30bf4169ad163047f87a2555cb33aa55f5d5e2bc Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 15 Aug 2010 13:03:15 -0400 Subject: ath5k: don't enable probe request rx for STAs AR5K_RX_FILTER_PROBEREQ enables reception of probe requests, but the filter flag FIF_BCN_PRBRESP_PROMISC is actually about receiving beacons and probe _responses_, so we shouldn't turn on the filter when scanning. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 99d56c6f06f1..f2fceb10c9fc 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -3227,9 +3227,9 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, rfilt |= AR5K_RX_FILTER_PHYERR; /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons - * and probes for any BSSID, this needs testing */ + * and probes for any BSSID */ if (*new_flags & FIF_BCN_PRBRESP_PROMISC) - rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ; + rfilt |= AR5K_RX_FILTER_BEACON; /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not * set we should only pass on control frames for this -- cgit v1.2.3-59-g8ed1b From 9f19fa62edd2c397ed41c2dba29fb9f7144cb918 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 16 Aug 2010 18:25:21 +0200 Subject: drivers/net/wireless/wl12xx: Use available error codes In each case, error codes are stored in ret, but the return value is always 0. Return ret instead. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r@ local idexpression x; constant C; @@ if (...) { ... x = -C ... when != x ( return <+...x...+>; | return NULL; | return; | * return ...; ) } // Signed-off-by: Julia Lawall Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_acx.c | 2 +- drivers/net/wireless/wl12xx/wl1251_cmd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c index 91891f928070..2f8a2ba744dc 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl12xx/wl1251_acx.c @@ -380,7 +380,7 @@ int wl1251_acx_pd_threshold(struct wl1251 *wl) out: kfree(pd); - return 0; + return ret; } int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time) diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c index ce3722f4c3e3..15fb68c6b542 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c @@ -200,7 +200,7 @@ int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity, out: kfree(vbm); - return 0; + return ret; } int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) -- cgit v1.2.3-59-g8ed1b From 36d344131c154c0fb7dd6a3703fc1b29c56a75a1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 16 Aug 2010 18:27:30 +0200 Subject: drivers/net/wireless/wl12xx: Use available error codes Error codes are stored in ret, but the return value is always 0. Return ret instead. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r@ local idexpression x; constant C; @@ if (...) { ... x = -C ... when != x ( return <+...x...+>; | return NULL; | return; | * return ...; ) } // Signed-off-by: Julia Lawall Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index bb245f05af49..f03ad088db8b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -269,7 +269,7 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl) out: kfree(pd); - return 0; + return ret; } int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) -- cgit v1.2.3-59-g8ed1b From 0975cc8fbf5b61b188734f2edd9e588c7edff2a1 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 31 Jul 2010 08:34:07 -0700 Subject: iwlwifi: separate thermal throttling function "Thermal Throttling" is an advance feature which only available for newer _agn devices. Move from iwl-core to iwl-agn for better code organization. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 1 + drivers/net/wireless/iwlwifi/iwl-1000.c | 5 + drivers/net/wireless/iwlwifi/iwl-5000.c | 10 + drivers/net/wireless/iwlwifi/iwl-6000.c | 5 + drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 696 ++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn-tt.h | 129 ++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 46 ++ drivers/net/wireless/iwlwifi/iwl-core.c | 48 --- drivers/net/wireless/iwlwifi/iwl-core.h | 10 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + drivers/net/wireless/iwlwifi/iwl-power.c | 640 +-------------------------- drivers/net/wireless/iwlwifi/iwl-power.h | 93 ---- drivers/net/wireless/iwlwifi/iwl-tx.c | 9 +- 13 files changed, 917 insertions(+), 776 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-tt.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-tt.h diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 728bb858ba97..493163925a45 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o +iwlagn-objs += iwl-agn-tt.o iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index fec026212326..f687a190f917 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -229,6 +229,11 @@ static struct iwl_lib_ops iwl1000_lib = { .check_ack_health = iwl_good_ack_health, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, + .tt_ops = { + .lower_power_detection = iwl_tt_is_low_power_state, + .tt_power_mode = iwl_tt_current_power_mode, + .ct_kill_check = iwl_check_for_ct_kill, + } }; static const struct iwl_ops iwl1000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index aacf3770f075..54083a39c724 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -405,6 +405,11 @@ static struct iwl_lib_ops iwl5000_lib = { .check_ack_health = iwl_good_ack_health, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, + .tt_ops = { + .lower_power_detection = iwl_tt_is_low_power_state, + .tt_power_mode = iwl_tt_current_power_mode, + .ct_kill_check = iwl_check_for_ct_kill, + } }; static struct iwl_lib_ops iwl5150_lib = { @@ -470,6 +475,11 @@ static struct iwl_lib_ops iwl5150_lib = { .check_ack_health = iwl_good_ack_health, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, + .tt_ops = { + .lower_power_detection = iwl_tt_is_low_power_state, + .tt_power_mode = iwl_tt_current_power_mode, + .ct_kill_check = iwl_check_for_ct_kill, + } }; static const struct iwl_ops iwl5000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index af4fd50f3405..7902de172a38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -330,6 +330,11 @@ static struct iwl_lib_ops iwl6000_lib = { .check_ack_health = iwl_good_ack_health, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, + .tt_ops = { + .lower_power_detection = iwl_tt_is_low_power_state, + .tt_power_mode = iwl_tt_current_power_mode, + .ct_kill_check = iwl_check_for_ct_kill, + } }; static const struct iwl_ops iwl6000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c new file mode 100644 index 000000000000..30298ea56a24 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -0,0 +1,696 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project, as well + * as portions of the ieee80211 subsystem header files. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + + +#include +#include +#include +#include + +#include + +#include "iwl-eeprom.h" +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-io.h" +#include "iwl-commands.h" +#include "iwl-debug.h" +#include "iwl-agn-tt.h" + +/* default Thermal Throttling transaction table + * Current state | Throttling Down | Throttling Up + *============================================================================= + * Condition Nxt State Condition Nxt State Condition Nxt State + *----------------------------------------------------------------------------- + * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A + * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 + * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 + * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 + *============================================================================= + */ +static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { + {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, + {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1}, + {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} +}; +static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { + {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, + {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1}, + {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} +}; +static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { + {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, + {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}, + {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} +}; +static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { + {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, + {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, + {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX} +}; + +/* Advance Thermal Throttling default restriction table */ +static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = { + {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true }, + {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true }, + {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false }, + {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } +}; + +bool iwl_tt_is_low_power_state(struct iwl_priv *priv) +{ + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + + if (tt->state >= IWL_TI_1) + return true; + return false; +} + +u8 iwl_tt_current_power_mode(struct iwl_priv *priv) +{ + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + + return tt->tt_power_mode; +} + +bool iwl_ht_enabled(struct iwl_priv *priv) +{ + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + struct iwl_tt_restriction *restriction; + + if (!priv->thermal_throttle.advanced_tt) + return true; + restriction = tt->restriction + tt->state; + return restriction->is_ht; +} + +static bool iwl_within_ct_kill_margin(struct iwl_priv *priv) +{ + s32 temp = priv->temperature; /* degrees CELSIUS except specified */ + bool within_margin = false; + + if (priv->cfg->temperature_kelvin) + temp = KELVIN_TO_CELSIUS(priv->temperature); + + if (!priv->thermal_throttle.advanced_tt) + within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= + CT_KILL_THRESHOLD_LEGACY) ? true : false; + else + within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= + CT_KILL_THRESHOLD) ? true : false; + return within_margin; +} + +bool iwl_check_for_ct_kill(struct iwl_priv *priv) +{ + bool is_ct_kill = false; + + if (iwl_within_ct_kill_margin(priv)) { + iwl_tt_enter_ct_kill(priv); + is_ct_kill = true; + } + return is_ct_kill; +} + +enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) +{ + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + struct iwl_tt_restriction *restriction; + + if (!priv->thermal_throttle.advanced_tt) + return IWL_ANT_OK_MULTI; + restriction = tt->restriction + tt->state; + return restriction->tx_stream; +} + +enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) +{ + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + struct iwl_tt_restriction *restriction; + + if (!priv->thermal_throttle.advanced_tt) + return IWL_ANT_OK_MULTI; + restriction = tt->restriction + tt->state; + return restriction->rx_stream; +} + +#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ +#define CT_KILL_WAITING_DURATION (300) /* 300ms duration */ + +/* + * toggle the bit to wake up uCode and check the temperature + * if the temperature is below CT, uCode will stay awake and send card + * state notification with CT_KILL bit clear to inform Thermal Throttling + * Management to change state. Otherwise, uCode will go back to sleep + * without doing anything, driver should continue the 5 seconds timer + * to wake up uCode for temperature check until temperature drop below CT + */ +static void iwl_tt_check_exit_ct_kill(unsigned long data) +{ + struct iwl_priv *priv = (struct iwl_priv *)data; + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + unsigned long flags; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + if (tt->state == IWL_TI_CT_KILL) { + if (priv->thermal_throttle.ct_kill_toggle) { + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); + priv->thermal_throttle.ct_kill_toggle = false; + } else { + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, + CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); + priv->thermal_throttle.ct_kill_toggle = true; + } + iwl_read32(priv, CSR_UCODE_DRV_GP1); + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); + + /* Reschedule the ct_kill timer to occur in + * CT_KILL_EXIT_DURATION seconds to ensure we get a + * thermal update */ + IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); + mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, + jiffies + CT_KILL_EXIT_DURATION * HZ); + } +} + +static void iwl_perform_ct_kill_task(struct iwl_priv *priv, + bool stop) +{ + if (stop) { + IWL_DEBUG_POWER(priv, "Stop all queues\n"); + if (priv->mac80211_registered) + ieee80211_stop_queues(priv->hw); + IWL_DEBUG_POWER(priv, + "Schedule 5 seconds CT_KILL Timer\n"); + mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, + jiffies + CT_KILL_EXIT_DURATION * HZ); + } else { + IWL_DEBUG_POWER(priv, "Wake all queues\n"); + if (priv->mac80211_registered) + ieee80211_wake_queues(priv->hw); + } +} + +static void iwl_tt_ready_for_ct_kill(unsigned long data) +{ + struct iwl_priv *priv = (struct iwl_priv *)data; + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + /* temperature timer expired, ready to go into CT_KILL state */ + if (tt->state != IWL_TI_CT_KILL) { + IWL_DEBUG_POWER(priv, "entering CT_KILL state when " + "temperature timer expired\n"); + tt->state = IWL_TI_CT_KILL; + set_bit(STATUS_CT_KILL, &priv->status); + iwl_perform_ct_kill_task(priv, true); + } +} + +static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) +{ + IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); + /* make request to retrieve statistics information */ + iwl_send_statistics_request(priv, CMD_SYNC, false); + /* Reschedule the ct_kill wait timer */ + mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, + jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); +} + +#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) +#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) +#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) + +/* + * Legacy thermal throttling + * 1) Avoid NIC destruction due to high temperatures + * Chip will identify dangerously high temperatures that can + * harm the device and will power down + * 2) Avoid the NIC power down due to high temperature + * Throttle early enough to lower the power consumption before + * drastic steps are needed + */ +static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) +{ + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + enum iwl_tt_state old_state; + +#ifdef CONFIG_IWLWIFI_DEBUG + if ((tt->tt_previous_temp) && + (temp > tt->tt_previous_temp) && + ((temp - tt->tt_previous_temp) > + IWL_TT_INCREASE_MARGIN)) { + IWL_DEBUG_POWER(priv, + "Temperature increase %d degree Celsius\n", + (temp - tt->tt_previous_temp)); + } +#endif + old_state = tt->state; + /* in Celsius */ + if (temp >= IWL_MINIMAL_POWER_THRESHOLD) + tt->state = IWL_TI_CT_KILL; + else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2) + tt->state = IWL_TI_2; + else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1) + tt->state = IWL_TI_1; + else + tt->state = IWL_TI_0; + +#ifdef CONFIG_IWLWIFI_DEBUG + tt->tt_previous_temp = temp; +#endif + /* stop ct_kill_waiting_tm timer */ + del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); + if (tt->state != old_state) { + switch (tt->state) { + case IWL_TI_0: + /* + * When the system is ready to go back to IWL_TI_0 + * we only have to call iwl_power_update_mode() to + * do so. + */ + break; + case IWL_TI_1: + tt->tt_power_mode = IWL_POWER_INDEX_3; + break; + case IWL_TI_2: + tt->tt_power_mode = IWL_POWER_INDEX_4; + break; + default: + tt->tt_power_mode = IWL_POWER_INDEX_5; + break; + } + mutex_lock(&priv->mutex); + if (old_state == IWL_TI_CT_KILL) + clear_bit(STATUS_CT_KILL, &priv->status); + if (tt->state != IWL_TI_CT_KILL && + iwl_power_update_mode(priv, true)) { + /* TT state not updated + * try again during next temperature read + */ + if (old_state == IWL_TI_CT_KILL) + set_bit(STATUS_CT_KILL, &priv->status); + tt->state = old_state; + IWL_ERR(priv, "Cannot update power mode, " + "TT state not updated\n"); + } else { + if (tt->state == IWL_TI_CT_KILL) { + if (force) { + set_bit(STATUS_CT_KILL, &priv->status); + iwl_perform_ct_kill_task(priv, true); + } else { + iwl_prepare_ct_kill_task(priv); + tt->state = old_state; + } + } else if (old_state == IWL_TI_CT_KILL && + tt->state != IWL_TI_CT_KILL) + iwl_perform_ct_kill_task(priv, false); + IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", + tt->state); + IWL_DEBUG_POWER(priv, "Power Index change to %u\n", + tt->tt_power_mode); + } + mutex_unlock(&priv->mutex); + } +} + +/* + * Advance thermal throttling + * 1) Avoid NIC destruction due to high temperatures + * Chip will identify dangerously high temperatures that can + * harm the device and will power down + * 2) Avoid the NIC power down due to high temperature + * Throttle early enough to lower the power consumption before + * drastic steps are needed + * Actions include relaxing the power down sleep thresholds and + * decreasing the number of TX streams + * 3) Avoid throughput performance impact as much as possible + * + *============================================================================= + * Condition Nxt State Condition Nxt State Condition Nxt State + *----------------------------------------------------------------------------- + * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A + * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 + * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 + * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 + *============================================================================= + */ +static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) +{ + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + int i; + bool changed = false; + enum iwl_tt_state old_state; + struct iwl_tt_trans *transaction; + + old_state = tt->state; + for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) { + /* based on the current TT state, + * find the curresponding transaction table + * each table has (IWL_TI_STATE_MAX - 1) entries + * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1)) + * will advance to the correct table. + * then based on the current temperature + * find the next state need to transaction to + * go through all the possible (IWL_TI_STATE_MAX - 1) entries + * in the current table to see if transaction is needed + */ + transaction = tt->transaction + + ((old_state * (IWL_TI_STATE_MAX - 1)) + i); + if (temp >= transaction->tt_low && + temp <= transaction->tt_high) { +#ifdef CONFIG_IWLWIFI_DEBUG + if ((tt->tt_previous_temp) && + (temp > tt->tt_previous_temp) && + ((temp - tt->tt_previous_temp) > + IWL_TT_INCREASE_MARGIN)) { + IWL_DEBUG_POWER(priv, + "Temperature increase %d " + "degree Celsius\n", + (temp - tt->tt_previous_temp)); + } + tt->tt_previous_temp = temp; +#endif + if (old_state != + transaction->next_state) { + changed = true; + tt->state = + transaction->next_state; + } + break; + } + } + /* stop ct_kill_waiting_tm timer */ + del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); + if (changed) { + struct iwl_rxon_cmd *rxon = &priv->staging_rxon; + + if (tt->state >= IWL_TI_1) { + /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ + tt->tt_power_mode = IWL_POWER_INDEX_5; + if (!iwl_ht_enabled(priv)) + /* disable HT */ + rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | + RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | + RXON_FLG_HT40_PROT_MSK | + RXON_FLG_HT_PROT_MSK); + else { + /* check HT capability and set + * according to the system HT capability + * in case get disabled before */ + iwl_set_rxon_ht(priv, &priv->current_ht_config); + } + + } else { + /* + * restore system power setting -- it will be + * recalculated automatically. + */ + + /* check HT capability and set + * according to the system HT capability + * in case get disabled before */ + iwl_set_rxon_ht(priv, &priv->current_ht_config); + } + mutex_lock(&priv->mutex); + if (old_state == IWL_TI_CT_KILL) + clear_bit(STATUS_CT_KILL, &priv->status); + if (tt->state != IWL_TI_CT_KILL && + iwl_power_update_mode(priv, true)) { + /* TT state not updated + * try again during next temperature read + */ + IWL_ERR(priv, "Cannot update power mode, " + "TT state not updated\n"); + if (old_state == IWL_TI_CT_KILL) + set_bit(STATUS_CT_KILL, &priv->status); + tt->state = old_state; + } else { + IWL_DEBUG_POWER(priv, + "Thermal Throttling to new state: %u\n", + tt->state); + if (old_state != IWL_TI_CT_KILL && + tt->state == IWL_TI_CT_KILL) { + if (force) { + IWL_DEBUG_POWER(priv, + "Enter IWL_TI_CT_KILL\n"); + set_bit(STATUS_CT_KILL, &priv->status); + iwl_perform_ct_kill_task(priv, true); + } else { + iwl_prepare_ct_kill_task(priv); + tt->state = old_state; + } + } else if (old_state == IWL_TI_CT_KILL && + tt->state != IWL_TI_CT_KILL) { + IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); + iwl_perform_ct_kill_task(priv, false); + } + } + mutex_unlock(&priv->mutex); + } +} + +/* Card State Notification indicated reach critical temperature + * if PSP not enable, no Thermal Throttling function will be performed + * just set the GP1 bit to acknowledge the event + * otherwise, go into IWL_TI_CT_KILL state + * since Card State Notification will not provide any temperature reading + * for Legacy mode + * so just pass the CT_KILL temperature to iwl_legacy_tt_handler() + * for advance mode + * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state + */ +static void iwl_bg_ct_enter(struct work_struct *work) +{ + struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + if (!iwl_is_ready(priv)) + return; + + if (tt->state != IWL_TI_CT_KILL) { + IWL_ERR(priv, "Device reached critical temperature " + "- ucode going to sleep!\n"); + if (!priv->thermal_throttle.advanced_tt) + iwl_legacy_tt_handler(priv, + IWL_MINIMAL_POWER_THRESHOLD, + true); + else + iwl_advance_tt_handler(priv, + CT_KILL_THRESHOLD + 1, true); + } +} + +/* Card State Notification indicated out of critical temperature + * since Card State Notification will not provide any temperature reading + * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature + * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state + */ +static void iwl_bg_ct_exit(struct work_struct *work) +{ + struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + if (!iwl_is_ready(priv)) + return; + + /* stop ct_kill_exit_tm timer */ + del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); + + if (tt->state == IWL_TI_CT_KILL) { + IWL_ERR(priv, + "Device temperature below critical" + "- ucode awake!\n"); + /* + * exit from CT_KILL state + * reset the current temperature reading + */ + priv->temperature = 0; + if (!priv->thermal_throttle.advanced_tt) + iwl_legacy_tt_handler(priv, + IWL_REDUCED_PERFORMANCE_THRESHOLD_2, + true); + else + iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD, + true); + } +} + +void iwl_tt_enter_ct_kill(struct iwl_priv *priv) +{ + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n"); + queue_work(priv->workqueue, &priv->ct_enter); +} +EXPORT_SYMBOL(iwl_tt_enter_ct_kill); + +void iwl_tt_exit_ct_kill(struct iwl_priv *priv) +{ + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); + queue_work(priv->workqueue, &priv->ct_exit); +} +EXPORT_SYMBOL(iwl_tt_exit_ct_kill); + +static void iwl_bg_tt_work(struct work_struct *work) +{ + struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); + s32 temp = priv->temperature; /* degrees CELSIUS except specified */ + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + if (priv->cfg->temperature_kelvin) + temp = KELVIN_TO_CELSIUS(priv->temperature); + + if (!priv->thermal_throttle.advanced_tt) + iwl_legacy_tt_handler(priv, temp, false); + else + iwl_advance_tt_handler(priv, temp, false); +} + +void iwl_tt_handler(struct iwl_priv *priv) +{ + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); + queue_work(priv->workqueue, &priv->tt_work); +} +EXPORT_SYMBOL(iwl_tt_handler); + +/* Thermal throttling initialization + * For advance thermal throttling: + * Initialize Thermal Index and temperature threshold table + * Initialize thermal throttling restriction table + */ +void iwl_tt_initialize(struct iwl_priv *priv) +{ + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); + struct iwl_tt_trans *transaction; + + IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); + + memset(tt, 0, sizeof(struct iwl_tt_mgmt)); + + tt->state = IWL_TI_0; + init_timer(&priv->thermal_throttle.ct_kill_exit_tm); + priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; + priv->thermal_throttle.ct_kill_exit_tm.function = + iwl_tt_check_exit_ct_kill; + init_timer(&priv->thermal_throttle.ct_kill_waiting_tm); + priv->thermal_throttle.ct_kill_waiting_tm.data = + (unsigned long)priv; + priv->thermal_throttle.ct_kill_waiting_tm.function = + iwl_tt_ready_for_ct_kill; + /* setup deferred ct kill work */ + INIT_WORK(&priv->tt_work, iwl_bg_tt_work); + INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); + INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); + + if (priv->cfg->adv_thermal_throttle) { + IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); + tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * + IWL_TI_STATE_MAX, GFP_KERNEL); + tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * + IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), + GFP_KERNEL); + if (!tt->restriction || !tt->transaction) { + IWL_ERR(priv, "Fallback to Legacy Throttling\n"); + priv->thermal_throttle.advanced_tt = false; + kfree(tt->restriction); + tt->restriction = NULL; + kfree(tt->transaction); + tt->transaction = NULL; + } else { + transaction = tt->transaction + + (IWL_TI_0 * (IWL_TI_STATE_MAX - 1)); + memcpy(transaction, &tt_range_0[0], size); + transaction = tt->transaction + + (IWL_TI_1 * (IWL_TI_STATE_MAX - 1)); + memcpy(transaction, &tt_range_1[0], size); + transaction = tt->transaction + + (IWL_TI_2 * (IWL_TI_STATE_MAX - 1)); + memcpy(transaction, &tt_range_2[0], size); + transaction = tt->transaction + + (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1)); + memcpy(transaction, &tt_range_3[0], size); + size = sizeof(struct iwl_tt_restriction) * + IWL_TI_STATE_MAX; + memcpy(tt->restriction, + &restriction_range[0], size); + priv->thermal_throttle.advanced_tt = true; + } + } else { + IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); + priv->thermal_throttle.advanced_tt = false; + } +} +EXPORT_SYMBOL(iwl_tt_initialize); + +/* cleanup thermal throttling management related memory and timer */ +void iwl_tt_exit(struct iwl_priv *priv) +{ + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; + + /* stop ct_kill_exit_tm timer if activated */ + del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); + /* stop ct_kill_waiting_tm timer if activated */ + del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); + cancel_work_sync(&priv->tt_work); + cancel_work_sync(&priv->ct_enter); + cancel_work_sync(&priv->ct_exit); + + if (priv->thermal_throttle.advanced_tt) { + /* free advance thermal throttling memory */ + kfree(tt->restriction); + tt->restriction = NULL; + kfree(tt->transaction); + tt->transaction = NULL; + } +} +EXPORT_SYMBOL(iwl_tt_exit); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h new file mode 100644 index 000000000000..d55060427cac --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project, as well + * as portions of the ieee80211 subsystem header files. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ +#ifndef __iwl_tt_setting_h__ +#define __iwl_tt_setting_h__ + +#include "iwl-commands.h" + +#define IWL_ABSOLUTE_ZERO 0 +#define IWL_ABSOLUTE_MAX 0xFFFFFFFF +#define IWL_TT_INCREASE_MARGIN 5 +#define IWL_TT_CT_KILL_MARGIN 3 + +enum iwl_antenna_ok { + IWL_ANT_OK_NONE, + IWL_ANT_OK_SINGLE, + IWL_ANT_OK_MULTI, +}; + +/* Thermal Throttling State Machine states */ +enum iwl_tt_state { + IWL_TI_0, /* normal temperature, system power state */ + IWL_TI_1, /* high temperature detect, low power state */ + IWL_TI_2, /* higher temperature detected, lower power state */ + IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */ + IWL_TI_STATE_MAX +}; + +/** + * struct iwl_tt_restriction - Thermal Throttling restriction table + * @tx_stream: number of tx stream allowed + * @is_ht: ht enable/disable + * @rx_stream: number of rx stream allowed + * + * This table is used by advance thermal throttling management + * based on the current thermal throttling state, and determines + * the number of tx/rx streams and the status of HT operation. + */ +struct iwl_tt_restriction { + enum iwl_antenna_ok tx_stream; + enum iwl_antenna_ok rx_stream; + bool is_ht; +}; + +/** + * struct iwl_tt_trans - Thermal Throttling transaction table + * @next_state: next thermal throttling mode + * @tt_low: low temperature threshold to change state + * @tt_high: high temperature threshold to change state + * + * This is used by the advanced thermal throttling algorithm + * to determine the next thermal state to go based on the + * current temperature. + */ +struct iwl_tt_trans { + enum iwl_tt_state next_state; + u32 tt_low; + u32 tt_high; +}; + +/** + * struct iwl_tt_mgnt - Thermal Throttling Management structure + * @advanced_tt: advanced thermal throttle required + * @state: current Thermal Throttling state + * @tt_power_mode: Thermal Throttling power mode index + * being used to set power level when + * when thermal throttling state != IWL_TI_0 + * the tt_power_mode should set to different + * power mode based on the current tt state + * @tt_previous_temperature: last measured temperature + * @iwl_tt_restriction: ptr to restriction tbl, used by advance + * thermal throttling to determine how many tx/rx streams + * should be used in tt state; and can HT be enabled or not + * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling + * state transaction + * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature + * @ct_kill_exit_tm: timer to exit thermal kill + */ +struct iwl_tt_mgmt { + enum iwl_tt_state state; + bool advanced_tt; + u8 tt_power_mode; + bool ct_kill_toggle; +#ifdef CONFIG_IWLWIFI_DEBUG + s32 tt_previous_temp; +#endif + struct iwl_tt_restriction *restriction; + struct iwl_tt_trans *transaction; + struct timer_list ct_kill_exit_tm; + struct timer_list ct_kill_waiting_tm; +}; + +u8 iwl_tt_current_power_mode(struct iwl_priv *priv); +bool iwl_tt_is_low_power_state(struct iwl_priv *priv); +bool iwl_ht_enabled(struct iwl_priv *priv); +bool iwl_check_for_ct_kill(struct iwl_priv *priv); +enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); +enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); +void iwl_tt_enter_ct_kill(struct iwl_priv *priv); +void iwl_tt_exit_ct_kill(struct iwl_priv *priv); +void iwl_tt_handler(struct iwl_priv *priv); +void iwl_tt_initialize(struct iwl_priv *priv); +void iwl_tt_exit(struct iwl_priv *priv); + +#endif /* __iwl_tt_setting_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 21a52ae05c0d..bce77eeb31c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2592,6 +2592,52 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, return pos; } +static void iwl_rf_kill_ct_config(struct iwl_priv *priv) +{ + struct iwl_ct_kill_config cmd; + struct iwl_ct_kill_throttling_config adv_cmd; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&priv->lock, flags); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); + spin_unlock_irqrestore(&priv->lock, flags); + priv->thermal_throttle.ct_kill_toggle = false; + + if (priv->cfg->support_ct_kill_exit) { + adv_cmd.critical_temperature_enter = + cpu_to_le32(priv->hw_params.ct_kill_threshold); + adv_cmd.critical_temperature_exit = + cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); + + ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, + sizeof(adv_cmd), &adv_cmd); + if (ret) + IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); + else + IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " + "succeeded, " + "critical temperature enter is %d," + "exit is %d\n", + priv->hw_params.ct_kill_threshold, + priv->hw_params.ct_kill_exit_threshold); + } else { + cmd.critical_temperature_R = + cpu_to_le32(priv->hw_params.ct_kill_threshold); + + ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, + sizeof(cmd), &cmd); + if (ret) + IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); + else + IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " + "succeeded, " + "critical temperature is %d\n", + priv->hw_params.ct_kill_threshold); + } +} + /** * iwl_alive_start - called after REPLY_ALIVE notification received * from protocol/runtime uCode (initialization uCode's diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index ccdf3c02bb3c..b5045c62de7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1514,54 +1514,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) } EXPORT_SYMBOL(iwl_send_statistics_request); -void iwl_rf_kill_ct_config(struct iwl_priv *priv) -{ - struct iwl_ct_kill_config cmd; - struct iwl_ct_kill_throttling_config adv_cmd; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&priv->lock, flags); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - spin_unlock_irqrestore(&priv->lock, flags); - priv->thermal_throttle.ct_kill_toggle = false; - - if (priv->cfg->support_ct_kill_exit) { - adv_cmd.critical_temperature_enter = - cpu_to_le32(priv->hw_params.ct_kill_threshold); - adv_cmd.critical_temperature_exit = - cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); - - ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, - sizeof(adv_cmd), &adv_cmd); - if (ret) - IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); - else - IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " - "succeeded, " - "critical temperature enter is %d," - "exit is %d\n", - priv->hw_params.ct_kill_threshold, - priv->hw_params.ct_kill_exit_threshold); - } else { - cmd.critical_temperature_R = - cpu_to_le32(priv->hw_params.ct_kill_threshold); - - ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, - sizeof(cmd), &cmd); - if (ret) - IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); - else - IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " - "succeeded, " - "critical temperature is %d\n", - priv->hw_params.ct_kill_threshold); - } -} -EXPORT_SYMBOL(iwl_rf_kill_ct_config); - - /* * CARD_STATE_CMD * diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7f1aaf206078..e6d127df01ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -136,6 +136,12 @@ struct iwl_temp_ops { void (*set_calib_version)(struct iwl_priv *priv); }; +struct iwl_tt_ops { + bool (*lower_power_detection)(struct iwl_priv *priv); + u8 (*tt_power_mode)(struct iwl_priv *priv); + bool (*ct_kill_check)(struct iwl_priv *priv); +}; + struct iwl_lib_ops { /* set hw dependent parameters */ int (*set_hw_params)(struct iwl_priv *priv); @@ -212,6 +218,9 @@ struct iwl_lib_ops { void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control); struct iwl_debugfs_ops debugfs_ops; + + /* thermal throttling */ + struct iwl_tt_ops tt_ops; }; struct iwl_led_ops { @@ -693,7 +702,6 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) return iwl_is_ready(priv); } -extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); extern void iwl_send_bt_config(struct iwl_priv *priv); extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 149619fb1c07..a2927b3a606e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -47,6 +47,7 @@ #include "iwl-led.h" #include "iwl-power.h" #include "iwl-agn-rs.h" +#include "iwl-agn-tt.h" struct iwl_tx_queue; diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index cda6a94d6cc9..da1f2ae24472 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -192,47 +192,6 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); } -/* default Thermal Throttling transaction table - * Current state | Throttling Down | Throttling Up - *============================================================================= - * Condition Nxt State Condition Nxt State Condition Nxt State - *----------------------------------------------------------------------------- - * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A - * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 - * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 - * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 - *============================================================================= - */ -static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { - {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, - {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1}, - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} -}; -static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { - {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, - {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1}, - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} -}; -static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { - {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}, - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} -}; -static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { - {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, - {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, - {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX} -}; - -/* Advance Thermal Throttling default restriction table */ -static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = { - {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true }, - {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true }, - {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false }, - {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } -}; - - static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) { @@ -308,7 +267,6 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) int iwl_power_update_mode(struct iwl_priv *priv, bool force) { int ret = 0; - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; bool update_chains; struct iwl_powertable_cmd cmd; @@ -325,9 +283,15 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) else if (priv->cfg->supports_idle && priv->hw->conf.flags & IEEE80211_CONF_IDLE) iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); - else if (tt->state >= IWL_TI_1) - iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); - else if (!enabled) + else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && + priv->cfg->ops->lib->tt_ops.tt_power_mode) { + if (priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) { + /* in thermal throttling low power state */ + iwl_static_sleep_cmd(priv, &cmd, + priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), + dtimper); + } + } else if (!enabled) iwl_power_sleep_cam_cmd(priv, &cmd); else if (priv->power_data.debug_sleep_level_override >= 0) iwl_static_sleep_cmd(priv, &cmd, @@ -367,592 +331,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) } EXPORT_SYMBOL(iwl_power_update_mode); -bool iwl_ht_enabled(struct iwl_priv *priv) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - struct iwl_tt_restriction *restriction; - - if (!priv->thermal_throttle.advanced_tt) - return true; - restriction = tt->restriction + tt->state; - return restriction->is_ht; -} -EXPORT_SYMBOL(iwl_ht_enabled); - -bool iwl_within_ct_kill_margin(struct iwl_priv *priv) -{ - s32 temp = priv->temperature; /* degrees CELSIUS except specified */ - bool within_margin = false; - - if (priv->cfg->temperature_kelvin) - temp = KELVIN_TO_CELSIUS(priv->temperature); - - if (!priv->thermal_throttle.advanced_tt) - within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= - CT_KILL_THRESHOLD_LEGACY) ? true : false; - else - within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= - CT_KILL_THRESHOLD) ? true : false; - return within_margin; -} - -enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - struct iwl_tt_restriction *restriction; - - if (!priv->thermal_throttle.advanced_tt) - return IWL_ANT_OK_MULTI; - restriction = tt->restriction + tt->state; - return restriction->tx_stream; -} -EXPORT_SYMBOL(iwl_tx_ant_restriction); - -enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - struct iwl_tt_restriction *restriction; - - if (!priv->thermal_throttle.advanced_tt) - return IWL_ANT_OK_MULTI; - restriction = tt->restriction + tt->state; - return restriction->rx_stream; -} - -#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ -#define CT_KILL_WAITING_DURATION (300) /* 300ms duration */ - -/* - * toggle the bit to wake up uCode and check the temperature - * if the temperature is below CT, uCode will stay awake and send card - * state notification with CT_KILL bit clear to inform Thermal Throttling - * Management to change state. Otherwise, uCode will go back to sleep - * without doing anything, driver should continue the 5 seconds timer - * to wake up uCode for temperature check until temperature drop below CT - */ -static void iwl_tt_check_exit_ct_kill(unsigned long data) -{ - struct iwl_priv *priv = (struct iwl_priv *)data; - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - unsigned long flags; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (tt->state == IWL_TI_CT_KILL) { - if (priv->thermal_throttle.ct_kill_toggle) { - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - priv->thermal_throttle.ct_kill_toggle = false; - } else { - iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - priv->thermal_throttle.ct_kill_toggle = true; - } - iwl_read32(priv, CSR_UCODE_DRV_GP1); - spin_lock_irqsave(&priv->reg_lock, flags); - if (!iwl_grab_nic_access(priv)) - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); - - /* Reschedule the ct_kill timer to occur in - * CT_KILL_EXIT_DURATION seconds to ensure we get a - * thermal update */ - IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); - mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + - CT_KILL_EXIT_DURATION * HZ); - } -} - -static void iwl_perform_ct_kill_task(struct iwl_priv *priv, - bool stop) -{ - if (stop) { - IWL_DEBUG_POWER(priv, "Stop all queues\n"); - if (priv->mac80211_registered) - ieee80211_stop_queues(priv->hw); - IWL_DEBUG_POWER(priv, - "Schedule 5 seconds CT_KILL Timer\n"); - mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + - CT_KILL_EXIT_DURATION * HZ); - } else { - IWL_DEBUG_POWER(priv, "Wake all queues\n"); - if (priv->mac80211_registered) - ieee80211_wake_queues(priv->hw); - } -} - -static void iwl_tt_ready_for_ct_kill(unsigned long data) -{ - struct iwl_priv *priv = (struct iwl_priv *)data; - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - /* temperature timer expired, ready to go into CT_KILL state */ - if (tt->state != IWL_TI_CT_KILL) { - IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n"); - tt->state = IWL_TI_CT_KILL; - set_bit(STATUS_CT_KILL, &priv->status); - iwl_perform_ct_kill_task(priv, true); - } -} - -static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) -{ - IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); - /* make request to retrieve statistics information */ - iwl_send_statistics_request(priv, CMD_SYNC, false); - /* Reschedule the ct_kill wait timer */ - mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, - jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); -} - -#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) -#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) -#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) - -/* - * Legacy thermal throttling - * 1) Avoid NIC destruction due to high temperatures - * Chip will identify dangerously high temperatures that can - * harm the device and will power down - * 2) Avoid the NIC power down due to high temperature - * Throttle early enough to lower the power consumption before - * drastic steps are needed - */ -static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - enum iwl_tt_state old_state; - -#ifdef CONFIG_IWLWIFI_DEBUG - if ((tt->tt_previous_temp) && - (temp > tt->tt_previous_temp) && - ((temp - tt->tt_previous_temp) > - IWL_TT_INCREASE_MARGIN)) { - IWL_DEBUG_POWER(priv, - "Temperature increase %d degree Celsius\n", - (temp - tt->tt_previous_temp)); - } -#endif - old_state = tt->state; - /* in Celsius */ - if (temp >= IWL_MINIMAL_POWER_THRESHOLD) - tt->state = IWL_TI_CT_KILL; - else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2) - tt->state = IWL_TI_2; - else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1) - tt->state = IWL_TI_1; - else - tt->state = IWL_TI_0; - -#ifdef CONFIG_IWLWIFI_DEBUG - tt->tt_previous_temp = temp; -#endif - /* stop ct_kill_waiting_tm timer */ - del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); - if (tt->state != old_state) { - switch (tt->state) { - case IWL_TI_0: - /* - * When the system is ready to go back to IWL_TI_0 - * we only have to call iwl_power_update_mode() to - * do so. - */ - break; - case IWL_TI_1: - tt->tt_power_mode = IWL_POWER_INDEX_3; - break; - case IWL_TI_2: - tt->tt_power_mode = IWL_POWER_INDEX_4; - break; - default: - tt->tt_power_mode = IWL_POWER_INDEX_5; - break; - } - mutex_lock(&priv->mutex); - if (old_state == IWL_TI_CT_KILL) - clear_bit(STATUS_CT_KILL, &priv->status); - if (tt->state != IWL_TI_CT_KILL && - iwl_power_update_mode(priv, true)) { - /* TT state not updated - * try again during next temperature read - */ - if (old_state == IWL_TI_CT_KILL) - set_bit(STATUS_CT_KILL, &priv->status); - tt->state = old_state; - IWL_ERR(priv, "Cannot update power mode, " - "TT state not updated\n"); - } else { - if (tt->state == IWL_TI_CT_KILL) { - if (force) { - set_bit(STATUS_CT_KILL, &priv->status); - iwl_perform_ct_kill_task(priv, true); - } else { - iwl_prepare_ct_kill_task(priv); - tt->state = old_state; - } - } else if (old_state == IWL_TI_CT_KILL && - tt->state != IWL_TI_CT_KILL) - iwl_perform_ct_kill_task(priv, false); - IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", - tt->state); - IWL_DEBUG_POWER(priv, "Power Index change to %u\n", - tt->tt_power_mode); - } - mutex_unlock(&priv->mutex); - } -} - -/* - * Advance thermal throttling - * 1) Avoid NIC destruction due to high temperatures - * Chip will identify dangerously high temperatures that can - * harm the device and will power down - * 2) Avoid the NIC power down due to high temperature - * Throttle early enough to lower the power consumption before - * drastic steps are needed - * Actions include relaxing the power down sleep thresholds and - * decreasing the number of TX streams - * 3) Avoid throughput performance impact as much as possible - * - *============================================================================= - * Condition Nxt State Condition Nxt State Condition Nxt State - *----------------------------------------------------------------------------- - * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A - * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 - * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 - * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 - *============================================================================= - */ -static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - int i; - bool changed = false; - enum iwl_tt_state old_state; - struct iwl_tt_trans *transaction; - - old_state = tt->state; - for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) { - /* based on the current TT state, - * find the curresponding transaction table - * each table has (IWL_TI_STATE_MAX - 1) entries - * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1)) - * will advance to the correct table. - * then based on the current temperature - * find the next state need to transaction to - * go through all the possible (IWL_TI_STATE_MAX - 1) entries - * in the current table to see if transaction is needed - */ - transaction = tt->transaction + - ((old_state * (IWL_TI_STATE_MAX - 1)) + i); - if (temp >= transaction->tt_low && - temp <= transaction->tt_high) { -#ifdef CONFIG_IWLWIFI_DEBUG - if ((tt->tt_previous_temp) && - (temp > tt->tt_previous_temp) && - ((temp - tt->tt_previous_temp) > - IWL_TT_INCREASE_MARGIN)) { - IWL_DEBUG_POWER(priv, - "Temperature increase %d " - "degree Celsius\n", - (temp - tt->tt_previous_temp)); - } - tt->tt_previous_temp = temp; -#endif - if (old_state != - transaction->next_state) { - changed = true; - tt->state = - transaction->next_state; - } - break; - } - } - /* stop ct_kill_waiting_tm timer */ - del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); - if (changed) { - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - - if (tt->state >= IWL_TI_1) { - /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ - tt->tt_power_mode = IWL_POWER_INDEX_5; - if (!iwl_ht_enabled(priv)) - /* disable HT */ - rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | - RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | - RXON_FLG_HT40_PROT_MSK | - RXON_FLG_HT_PROT_MSK); - else { - /* check HT capability and set - * according to the system HT capability - * in case get disabled before */ - iwl_set_rxon_ht(priv, &priv->current_ht_config); - } - - } else { - /* - * restore system power setting -- it will be - * recalculated automatically. - */ - - /* check HT capability and set - * according to the system HT capability - * in case get disabled before */ - iwl_set_rxon_ht(priv, &priv->current_ht_config); - } - mutex_lock(&priv->mutex); - if (old_state == IWL_TI_CT_KILL) - clear_bit(STATUS_CT_KILL, &priv->status); - if (tt->state != IWL_TI_CT_KILL && - iwl_power_update_mode(priv, true)) { - /* TT state not updated - * try again during next temperature read - */ - IWL_ERR(priv, "Cannot update power mode, " - "TT state not updated\n"); - if (old_state == IWL_TI_CT_KILL) - set_bit(STATUS_CT_KILL, &priv->status); - tt->state = old_state; - } else { - IWL_DEBUG_POWER(priv, - "Thermal Throttling to new state: %u\n", - tt->state); - if (old_state != IWL_TI_CT_KILL && - tt->state == IWL_TI_CT_KILL) { - if (force) { - IWL_DEBUG_POWER(priv, - "Enter IWL_TI_CT_KILL\n"); - set_bit(STATUS_CT_KILL, &priv->status); - iwl_perform_ct_kill_task(priv, true); - } else { - iwl_prepare_ct_kill_task(priv); - tt->state = old_state; - } - } else if (old_state == IWL_TI_CT_KILL && - tt->state != IWL_TI_CT_KILL) { - IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); - iwl_perform_ct_kill_task(priv, false); - } - } - mutex_unlock(&priv->mutex); - } -} - -/* Card State Notification indicated reach critical temperature - * if PSP not enable, no Thermal Throttling function will be performed - * just set the GP1 bit to acknowledge the event - * otherwise, go into IWL_TI_CT_KILL state - * since Card State Notification will not provide any temperature reading - * for Legacy mode - * so just pass the CT_KILL temperature to iwl_legacy_tt_handler() - * for advance mode - * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state - */ -static void iwl_bg_ct_enter(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (!iwl_is_ready(priv)) - return; - - if (tt->state != IWL_TI_CT_KILL) { - IWL_ERR(priv, "Device reached critical temperature " - "- ucode going to sleep!\n"); - if (!priv->thermal_throttle.advanced_tt) - iwl_legacy_tt_handler(priv, - IWL_MINIMAL_POWER_THRESHOLD, - true); - else - iwl_advance_tt_handler(priv, - CT_KILL_THRESHOLD + 1, true); - } -} - -/* Card State Notification indicated out of critical temperature - * since Card State Notification will not provide any temperature reading - * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature - * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state - */ -static void iwl_bg_ct_exit(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (!iwl_is_ready(priv)) - return; - - /* stop ct_kill_exit_tm timer */ - del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); - - if (tt->state == IWL_TI_CT_KILL) { - IWL_ERR(priv, - "Device temperature below critical" - "- ucode awake!\n"); - /* - * exit from CT_KILL state - * reset the current temperature reading - */ - priv->temperature = 0; - if (!priv->thermal_throttle.advanced_tt) - iwl_legacy_tt_handler(priv, - IWL_REDUCED_PERFORMANCE_THRESHOLD_2, - true); - else - iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD, - true); - } -} - -void iwl_tt_enter_ct_kill(struct iwl_priv *priv) -{ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n"); - queue_work(priv->workqueue, &priv->ct_enter); -} -EXPORT_SYMBOL(iwl_tt_enter_ct_kill); - -void iwl_tt_exit_ct_kill(struct iwl_priv *priv) -{ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); - queue_work(priv->workqueue, &priv->ct_exit); -} -EXPORT_SYMBOL(iwl_tt_exit_ct_kill); - -static void iwl_bg_tt_work(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); - s32 temp = priv->temperature; /* degrees CELSIUS except specified */ - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (priv->cfg->temperature_kelvin) - temp = KELVIN_TO_CELSIUS(priv->temperature); - - if (!priv->thermal_throttle.advanced_tt) - iwl_legacy_tt_handler(priv, temp, false); - else - iwl_advance_tt_handler(priv, temp, false); -} - -void iwl_tt_handler(struct iwl_priv *priv) -{ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); - queue_work(priv->workqueue, &priv->tt_work); -} -EXPORT_SYMBOL(iwl_tt_handler); - -/* Thermal throttling initialization - * For advance thermal throttling: - * Initialize Thermal Index and temperature threshold table - * Initialize thermal throttling restriction table - */ -void iwl_tt_initialize(struct iwl_priv *priv) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); - struct iwl_tt_trans *transaction; - - IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); - - memset(tt, 0, sizeof(struct iwl_tt_mgmt)); - - tt->state = IWL_TI_0; - init_timer(&priv->thermal_throttle.ct_kill_exit_tm); - priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; - priv->thermal_throttle.ct_kill_exit_tm.function = - iwl_tt_check_exit_ct_kill; - init_timer(&priv->thermal_throttle.ct_kill_waiting_tm); - priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv; - priv->thermal_throttle.ct_kill_waiting_tm.function = - iwl_tt_ready_for_ct_kill; - /* setup deferred ct kill work */ - INIT_WORK(&priv->tt_work, iwl_bg_tt_work); - INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); - INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); - - if (priv->cfg->adv_thermal_throttle) { - IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); - tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * - IWL_TI_STATE_MAX, GFP_KERNEL); - tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * - IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), - GFP_KERNEL); - if (!tt->restriction || !tt->transaction) { - IWL_ERR(priv, "Fallback to Legacy Throttling\n"); - priv->thermal_throttle.advanced_tt = false; - kfree(tt->restriction); - tt->restriction = NULL; - kfree(tt->transaction); - tt->transaction = NULL; - } else { - transaction = tt->transaction + - (IWL_TI_0 * (IWL_TI_STATE_MAX - 1)); - memcpy(transaction, &tt_range_0[0], size); - transaction = tt->transaction + - (IWL_TI_1 * (IWL_TI_STATE_MAX - 1)); - memcpy(transaction, &tt_range_1[0], size); - transaction = tt->transaction + - (IWL_TI_2 * (IWL_TI_STATE_MAX - 1)); - memcpy(transaction, &tt_range_2[0], size); - transaction = tt->transaction + - (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1)); - memcpy(transaction, &tt_range_3[0], size); - size = sizeof(struct iwl_tt_restriction) * - IWL_TI_STATE_MAX; - memcpy(tt->restriction, - &restriction_range[0], size); - priv->thermal_throttle.advanced_tt = true; - } - } else { - IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); - priv->thermal_throttle.advanced_tt = false; - } -} -EXPORT_SYMBOL(iwl_tt_initialize); - -/* cleanup thermal throttling management related memory and timer */ -void iwl_tt_exit(struct iwl_priv *priv) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - - /* stop ct_kill_exit_tm timer if activated */ - del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); - /* stop ct_kill_waiting_tm timer if activated */ - del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); - cancel_work_sync(&priv->tt_work); - cancel_work_sync(&priv->ct_enter); - cancel_work_sync(&priv->ct_exit); - - if (priv->thermal_throttle.advanced_tt) { - /* free advance thermal throttling memory */ - kfree(tt->restriction); - tt->restriction = NULL; - kfree(tt->transaction); - tt->transaction = NULL; - } -} -EXPORT_SYMBOL(iwl_tt_exit); - /* initialize to default */ void iwl_power_initialize(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 5db91c10dcc8..df81565a7cc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -30,90 +30,6 @@ #include "iwl-commands.h" -#define IWL_ABSOLUTE_ZERO 0 -#define IWL_ABSOLUTE_MAX 0xFFFFFFFF -#define IWL_TT_INCREASE_MARGIN 5 -#define IWL_TT_CT_KILL_MARGIN 3 - -enum iwl_antenna_ok { - IWL_ANT_OK_NONE, - IWL_ANT_OK_SINGLE, - IWL_ANT_OK_MULTI, -}; - -/* Thermal Throttling State Machine states */ -enum iwl_tt_state { - IWL_TI_0, /* normal temperature, system power state */ - IWL_TI_1, /* high temperature detect, low power state */ - IWL_TI_2, /* higher temperature detected, lower power state */ - IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */ - IWL_TI_STATE_MAX -}; - -/** - * struct iwl_tt_restriction - Thermal Throttling restriction table - * @tx_stream: number of tx stream allowed - * @is_ht: ht enable/disable - * @rx_stream: number of rx stream allowed - * - * This table is used by advance thermal throttling management - * based on the current thermal throttling state, and determines - * the number of tx/rx streams and the status of HT operation. - */ -struct iwl_tt_restriction { - enum iwl_antenna_ok tx_stream; - enum iwl_antenna_ok rx_stream; - bool is_ht; -}; - -/** - * struct iwl_tt_trans - Thermal Throttling transaction table - * @next_state: next thermal throttling mode - * @tt_low: low temperature threshold to change state - * @tt_high: high temperature threshold to change state - * - * This is used by the advanced thermal throttling algorithm - * to determine the next thermal state to go based on the - * current temperature. - */ -struct iwl_tt_trans { - enum iwl_tt_state next_state; - u32 tt_low; - u32 tt_high; -}; - -/** - * struct iwl_tt_mgnt - Thermal Throttling Management structure - * @advanced_tt: advanced thermal throttle required - * @state: current Thermal Throttling state - * @tt_power_mode: Thermal Throttling power mode index - * being used to set power level when - * when thermal throttling state != IWL_TI_0 - * the tt_power_mode should set to different - * power mode based on the current tt state - * @tt_previous_temperature: last measured temperature - * @iwl_tt_restriction: ptr to restriction tbl, used by advance - * thermal throttling to determine how many tx/rx streams - * should be used in tt state; and can HT be enabled or not - * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling - * state transaction - * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature - * @ct_kill_exit_tm: timer to exit thermal kill - */ -struct iwl_tt_mgmt { - enum iwl_tt_state state; - bool advanced_tt; - u8 tt_power_mode; - bool ct_kill_toggle; -#ifdef CONFIG_IWLWIFI_DEBUG - s32 tt_previous_temp; -#endif - struct iwl_tt_restriction *restriction; - struct iwl_tt_trans *transaction; - struct timer_list ct_kill_exit_tm; - struct timer_list ct_kill_waiting_tm; -}; - enum iwl_power_level { IWL_POWER_INDEX_1, IWL_POWER_INDEX_2, @@ -130,15 +46,6 @@ struct iwl_power_mgr { }; int iwl_power_update_mode(struct iwl_priv *priv, bool force); -bool iwl_ht_enabled(struct iwl_priv *priv); -bool iwl_within_ct_kill_margin(struct iwl_priv *priv); -enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); -enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); -void iwl_tt_enter_ct_kill(struct iwl_priv *priv); -void iwl_tt_exit_ct_kill(struct iwl_priv *priv); -void iwl_tt_handler(struct iwl_priv *priv); -void iwl_tt_initialize(struct iwl_priv *priv); -void iwl_tt_exit(struct iwl_priv *priv); void iwl_power_initialize(struct iwl_priv *priv); extern bool no_sleep_autoadjust; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index a81989c06983..c308dab14673 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -422,6 +422,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) int len; u32 idx; u16 fix_size; + bool is_ct_kill = false; cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); @@ -443,9 +444,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { IWL_ERR(priv, "No space in command queue\n"); - if (iwl_within_ct_kill_margin(priv)) - iwl_tt_enter_ct_kill(priv); - else { + if (priv->cfg->ops->lib->tt_ops.ct_kill_check) { + is_ct_kill = + priv->cfg->ops->lib->tt_ops.ct_kill_check(priv); + } + if (!is_ct_kill) { IWL_ERR(priv, "Restarting adapter due to queue full\n"); queue_work(priv->workqueue, &priv->restart); } -- cgit v1.2.3-59-g8ed1b From e7f45d3ff8de9e936d870aba947b2e4ce88a1d1e Mon Sep 17 00:00:00 2001 From: Gábor Stefanik Date: Mon, 16 Aug 2010 22:39:14 +0200 Subject: b43: N-PHY: Implement Host Flags write during device init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 5a725703770c..cb815ccedfb3 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1098,7 +1098,8 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) if (dev->phy.rev < 2) { if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) - ; /*TODO: b43_mhf(dev, 2, 0x0010, 0x0010, 3);*/ + b43_hf_write(dev, b43_hf_read(dev) | + B43_HF_MLADVW); } else if (dev->phy.rev == 2) { b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0); b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0); -- cgit v1.2.3-59-g8ed1b From e723ef305c36785c08af9463b3a3ec369dfcedcb Mon Sep 17 00:00:00 2001 From: Gábor Stefanik Date: Mon, 16 Aug 2010 22:39:15 +0200 Subject: b43: N-PHY: Fix typo in function name (gain_crtl -> gain_ctrl) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index cb815ccedfb3..f1b57070ada9 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -893,7 +893,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ -static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) +static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; u8 i, j; @@ -1094,7 +1094,7 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); - b43_nphy_gain_crtl_workarounds(dev); + b43_nphy_gain_ctrl_workarounds(dev); if (dev->phy.rev < 2) { if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) -- cgit v1.2.3-59-g8ed1b From d2730b2a6a019d14455556019d744ab051e6554b Mon Sep 17 00:00:00 2001 From: Gábor Stefanik Date: Mon, 16 Aug 2010 22:39:16 +0200 Subject: b43: N-PHY: Implement MAC PHY clock set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 13 ++++++++++++- include/linux/ssb/ssb_regs.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index f1b57070ada9..d212726d509b 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -3074,6 +3074,17 @@ static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */ +static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on) +{ + u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); + if (on) + tmslow |= SSB_TMSLOW_PHYCLK; + else + tmslow &= ~SSB_TMSLOW_PHYCLK; + ssb_write32(dev->dev, SSB_TMSLOW, tmslow); +} + /* * Init N-PHY * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N @@ -3174,7 +3185,7 @@ int b43_phy_initn(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); b43_nphy_bmac_clock_fgc(dev, 0); - /* TODO N PHY MAC PHY Clock Set with argument 1 */ + b43_nphy_mac_phy_clock_set(dev, true); b43_nphy_pa_override(dev, false); b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index a6d5225b9275..11daf9c140e7 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h @@ -97,6 +97,7 @@ #define SSB_TMSLOW_RESET 0x00000001 /* Reset */ #define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */ #define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */ +#define SSB_TMSLOW_PHYCLK 0x00000010 /* MAC PHY Clock Control Enable */ #define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */ #define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */ #define SSB_TMSLOW_PE 0x40000000 /* Power Management Enable */ -- cgit v1.2.3-59-g8ed1b From 4e687b2226f47c656302b9c313bfe2ece85fe2ef Mon Sep 17 00:00:00 2001 From: Gábor Stefanik Date: Mon, 16 Aug 2010 22:39:17 +0200 Subject: b43: N-PHY: Implement RX core state setting for rev.2 and earlier PHYs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rev.3+ support coming in a later patch. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index d212726d509b..a0a6554a76d1 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -3085,6 +3085,44 @@ static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on) ssb_write32(dev->dev, SSB_TMSLOW, tmslow); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */ +static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) +{ + struct b43_phy *phy = &dev->phy; + struct b43_phy_n *nphy = phy->n; + u16 buf[16]; + + if (0 /* FIXME clk */) + return; + + b43_mac_suspend(dev); + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, true); + + b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN, + (mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT); + + if (mask & 0x3 != 0x3) { + b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1); + if (dev->phy.rev >= 3) { + /* TODO */ + } + } else { + b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E); + if (dev->phy.rev >= 3) { + /* TODO */ + } + } + + b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, false); + + b43_mac_enable(dev); +} + /* * Init N-PHY * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N @@ -3211,7 +3249,7 @@ int b43_phy_initn(struct b43_wldev *dev) } if (nphy->phyrxchain != 3) - ;/* TODO N PHY RX Core Set State with phyrxchain as argument */ + b43_nphy_set_rx_core_state(dev, nphy->phyrxchain); if (nphy->mphase_cal_phase_id > 0) ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ -- cgit v1.2.3-59-g8ed1b From b9c066597fdf38b126d2e0434d0ce18d22bbf401 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 17 Aug 2010 01:16:05 +0200 Subject: p54spi: fix eeprom checksum This patch corrects the bogus descriptor checksum of our Nokia N8XX EEPROM blob. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi_eeprom.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54spi_eeprom.h b/drivers/net/wireless/p54/p54spi_eeprom.h index 1ea1050911d9..d592cbd34d78 100644 --- a/drivers/net/wireless/p54/p54spi_eeprom.h +++ b/drivers/net/wireless/p54/p54spi_eeprom.h @@ -671,7 +671,7 @@ static unsigned char p54spi_eeprom[] = { 0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, /* PDR_END */ - 0xa8, 0xf5 /* bogus data */ + 0x67, 0x99, }; #endif /* P54SPI_EEPROM_H */ -- cgit v1.2.3-59-g8ed1b From d7eb50c0f7cb5d3ebb7bea8c681a6dfda3819a3b Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 17 Aug 2010 01:16:58 +0200 Subject: p54: improve eeprom parser Like other vendors, p54* devices have a checksum for the EEPROM descriptor data. This patch enhances the parser code to generate and verify the data fields, before initializing the radio-chip on the card. Note: If you have to bootstrap an alternative EEPROM image for your device and you don't know how to generate a valid crc ccitt checksum, you should take a look at: http://git.kernel.org/?p=linux/kernel/git/chr/p54tools.git The "checksum" utility loads a binary p54 EEPROM blob (use the -f switch, to skip the check) and applies the correct crc automatically. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/Kconfig | 1 + drivers/net/wireless/p54/eeprom.c | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig index b0342a520bf1..60a930e45a8b 100644 --- a/drivers/net/wireless/p54/Kconfig +++ b/drivers/net/wireless/p54/Kconfig @@ -2,6 +2,7 @@ config P54_COMMON tristate "Softmac Prism54 support" depends on MAC80211 && EXPERIMENTAL select FW_LOADER + select CRC_CCITT ---help--- This is common code for isl38xx/stlc45xx based modules. This module does nothing by itself - the USB/PCI/SPI front-ends diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index d687cb7f2a59..32d3f99b0844 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -23,6 +23,7 @@ #include #include +#include #include "p54.h" #include "eeprom.h" @@ -540,6 +541,7 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) int err; u8 *end = (u8 *)eeprom + len; u16 synth = 0; + u16 crc16 = ~0; wrap = (struct eeprom_pda_wrap *) eeprom; entry = (void *)wrap->data + le16_to_cpu(wrap->len); @@ -655,16 +657,29 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) } break; case PDR_END: - /* make it overrun */ - entry_len = len; + crc16 = ~crc_ccitt(crc16, (u8 *) entry, sizeof(*entry)); + if (crc16 != le16_to_cpup((__le16 *)entry->data)) { + wiphy_err(dev->wiphy, "eeprom failed checksum " + "test!\n"); + err = -ENOMSG; + goto err; + } else { + goto good_eeprom; + } break; default: break; } - entry = (void *)entry + (entry_len + 1)*2; + crc16 = crc_ccitt(crc16, (u8 *)entry, (entry_len + 1) * 2); + entry = (void *)entry + (entry_len + 1) * 2; } + wiphy_err(dev->wiphy, "unexpected end of eeprom data.\n"); + err = -ENODATA; + goto err; + +good_eeprom: if (!synth || !priv->iq_autocal || !priv->output_limit || !priv->curve_data) { wiphy_err(dev->wiphy, -- cgit v1.2.3-59-g8ed1b From 352de5573f60af0ab054859931cfb68eecb1832b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 17 Aug 2010 12:04:34 +0200 Subject: wireless: move documentation books This moves mac80211 documentation into a new 802.11 bookset and also adds a cfg80211 book to the set. All of this is rather incomplete, but it's easier to work with big code moving as a separate patch. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/DocBook/80211.tmpl | 371 ++++++++++++++++++++++++++++++++++++ Documentation/DocBook/Makefile | 2 +- Documentation/DocBook/mac80211.tmpl | 337 -------------------------------- 3 files changed, 372 insertions(+), 338 deletions(-) create mode 100644 Documentation/DocBook/80211.tmpl delete mode 100644 Documentation/DocBook/mac80211.tmpl diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl new file mode 100644 index 000000000000..6f88e184d2e7 --- /dev/null +++ b/Documentation/DocBook/80211.tmpl @@ -0,0 +1,371 @@ + + + + + The 802.11 subsystems – for kernel developers + + Explaining wireless 802.11 networking in the Linux kernel + + + + 2007-2009 + Johannes Berg + + + + + Johannes + Berg + +
johannes@sipsolutions.net
+
+
+
+ + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + + + This documentation 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 documentation; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + For more details see the file COPYING in the source + distribution of Linux. + + + + + + These books attempt to give a description of the + various subsystems that play a role in 802.11 wireless + networking in Linux. Since these books are for kernel + developers they attempts to document the structures + and functions used in the kernel as well as giving a + higher-level overview. + + + The reader is expected to be familiar with the 802.11 + standard as published by the IEEE in 802.11-2007 (or + possibly later versions). References to this standard + will be given as "802.11-2007 8.1.5". + + +
+ + + The cfg80211 subsystem + + + +MISSING + + + + +!Finclude/net/cfg80211.h ieee80211_band + + + + + The mac80211 subsystem + +!Pinclude/net/mac80211.h Introduction +!Pinclude/net/mac80211.h Warning + + + + + + + + + The basic mac80211 driver interface + + + You should read and understand the information contained + within this part of the book while implementing a driver. + In some chapters, advanced usage is noted, that may be + skipped at first. + + + This part of the book only covers station and monitor mode + functionality, additional information required to implement + the other modes is covered in the second part of the book. + + + + + Basic hardware handling + TBD + + This chapter shall contain information on getting a hw + struct allocated and registered with mac80211. + + + Since it is required to allocate rates/modes before registering + a hw struct, this chapter shall also contain information on setting + up the rate/mode structs. + + + Additionally, some discussion about the callbacks and + the general programming model should be in here, including + the definition of ieee80211_ops which will be referred to + a lot. + + + Finally, a discussion of hardware capabilities should be done + with references to other parts of the book. + + +!Finclude/net/mac80211.h ieee80211_hw +!Finclude/net/mac80211.h ieee80211_hw_flags +!Finclude/net/mac80211.h SET_IEEE80211_DEV +!Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR +!Finclude/net/mac80211.h ieee80211_ops +!Finclude/net/mac80211.h ieee80211_alloc_hw +!Finclude/net/mac80211.h ieee80211_register_hw +!Finclude/net/mac80211.h ieee80211_get_tx_led_name +!Finclude/net/mac80211.h ieee80211_get_rx_led_name +!Finclude/net/mac80211.h ieee80211_get_assoc_led_name +!Finclude/net/mac80211.h ieee80211_get_radio_led_name +!Finclude/net/mac80211.h ieee80211_unregister_hw +!Finclude/net/mac80211.h ieee80211_free_hw + + + + PHY configuration + TBD + + This chapter should describe PHY handling including + start/stop callbacks and the various structures used. + +!Finclude/net/mac80211.h ieee80211_conf +!Finclude/net/mac80211.h ieee80211_conf_flags + + + + Virtual interfaces + TBD + + This chapter should describe virtual interface basics + that are relevant to the driver (VLANs, MGMT etc are not.) + It should explain the use of the add_iface/remove_iface + callbacks as well as the interface configuration callbacks. + + Things related to AP mode should be discussed there. + + Things related to supporting multiple interfaces should be + in the appropriate chapter, a BIG FAT note should be here about + this though and the recommendation to allow only a single + interface in STA mode at first! + +!Finclude/net/mac80211.h ieee80211_vif + + + + Receive and transmit processing + + what should be here + TBD + + This should describe the receive and transmit + paths in mac80211/the drivers as well as + transmit status handling. + + + + Frame format +!Pinclude/net/mac80211.h Frame format + + + Packet alignment +!Pnet/mac80211/rx.c Packet alignment + + + Calling into mac80211 from interrupts +!Pinclude/net/mac80211.h Calling mac80211 from interrupts + + + functions/definitions +!Finclude/net/mac80211.h ieee80211_rx_status +!Finclude/net/mac80211.h mac80211_rx_flags +!Finclude/net/mac80211.h ieee80211_tx_info +!Finclude/net/mac80211.h ieee80211_rx +!Finclude/net/mac80211.h ieee80211_rx_irqsafe +!Finclude/net/mac80211.h ieee80211_tx_status +!Finclude/net/mac80211.h ieee80211_tx_status_irqsafe +!Finclude/net/mac80211.h ieee80211_rts_get +!Finclude/net/mac80211.h ieee80211_rts_duration +!Finclude/net/mac80211.h ieee80211_ctstoself_get +!Finclude/net/mac80211.h ieee80211_ctstoself_duration +!Finclude/net/mac80211.h ieee80211_generic_frame_duration +!Finclude/net/mac80211.h ieee80211_wake_queue +!Finclude/net/mac80211.h ieee80211_stop_queue +!Finclude/net/mac80211.h ieee80211_wake_queues +!Finclude/net/mac80211.h ieee80211_stop_queues + + + + + Frame filtering +!Pinclude/net/mac80211.h Frame filtering +!Finclude/net/mac80211.h ieee80211_filter_flags + + + + + Advanced driver interface + + + Information contained within this part of the book is + of interest only for advanced interaction of mac80211 + with drivers to exploit more hardware capabilities and + improve performance. + + + + + Hardware crypto acceleration +!Pinclude/net/mac80211.h Hardware crypto acceleration + +!Finclude/net/mac80211.h set_key_cmd +!Finclude/net/mac80211.h ieee80211_key_conf +!Finclude/net/mac80211.h ieee80211_key_alg +!Finclude/net/mac80211.h ieee80211_key_flags + + + + Powersave support +!Pinclude/net/mac80211.h Powersave support + + + + Beacon filter support +!Pinclude/net/mac80211.h Beacon filter support +!Finclude/net/mac80211.h ieee80211_beacon_loss + + + + Multiple queues and QoS support + TBD +!Finclude/net/mac80211.h ieee80211_tx_queue_params + + + + Access point mode support + TBD + Some parts of the if_conf should be discussed here instead + + Insert notes about VLAN interfaces with hw crypto here or + in the hw crypto chapter. + +!Finclude/net/mac80211.h ieee80211_get_buffered_bc +!Finclude/net/mac80211.h ieee80211_beacon_get + + + + Supporting multiple virtual interfaces + TBD + + Note: WDS with identical MAC address should almost always be OK + + + Insert notes about having multiple virtual interfaces with + different MAC addresses here, note which configurations are + supported by mac80211, add notes about supporting hw crypto + with it. + + + + + Hardware scan offload + TBD +!Finclude/net/mac80211.h ieee80211_scan_completed + + + + + Rate control interface + + TBD + + This part of the book describes the rate control algorithm + interface and how it relates to mac80211 and drivers. + + + + dummy chapter + TBD + + + + + Internals + + TBD + + This part of the book describes mac80211 internals. + + + + + Key handling + + Key handling basics +!Pnet/mac80211/key.c Key handling basics + + + MORE TBD + TBD + + + + + Receive processing + TBD + + + + Transmit processing + TBD + + + + Station info handling + + Programming information +!Fnet/mac80211/sta_info.h sta_info +!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags + + + STA information lifetime rules +!Pnet/mac80211/sta_info.c STA information lifetime rules + + + + + Synchronisation + TBD + Locking, lots of RCU + + + +
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index c7e5dc7e8cb3..b6f2ba2f36b7 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -12,7 +12,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ - mac80211.xml debugobjects.xml sh.xml regulator.xml \ + 80211.xml debugobjects.xml sh.xml regulator.xml \ alsa-driver-api.xml writing-an-alsa-driver.xml \ tracepoint.xml media.xml drm.xml diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl deleted file mode 100644 index affb15a344a1..000000000000 --- a/Documentation/DocBook/mac80211.tmpl +++ /dev/null @@ -1,337 +0,0 @@ - - - - - - The mac80211 subsystem for kernel developers - - - - Johannes - Berg - -
johannes@sipsolutions.net
-
-
-
- - - 2007-2009 - Johannes Berg - - - - - This documentation is free software; you can redistribute - it and/or modify it under the terms of the GNU General Public - License version 2 as published by the Free Software Foundation. - - - - This documentation 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 documentation; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, - MA 02111-1307 USA - - - - For more details see the file COPYING in the source - distribution of Linux. - - - - -!Pinclude/net/mac80211.h Introduction -!Pinclude/net/mac80211.h Warning - -
- - - - - - - The basic mac80211 driver interface - - - You should read and understand the information contained - within this part of the book while implementing a driver. - In some chapters, advanced usage is noted, that may be - skipped at first. - - - This part of the book only covers station and monitor mode - functionality, additional information required to implement - the other modes is covered in the second part of the book. - - - - - Basic hardware handling - TBD - - This chapter shall contain information on getting a hw - struct allocated and registered with mac80211. - - - Since it is required to allocate rates/modes before registering - a hw struct, this chapter shall also contain information on setting - up the rate/mode structs. - - - Additionally, some discussion about the callbacks and - the general programming model should be in here, including - the definition of ieee80211_ops which will be referred to - a lot. - - - Finally, a discussion of hardware capabilities should be done - with references to other parts of the book. - - -!Finclude/net/mac80211.h ieee80211_hw -!Finclude/net/mac80211.h ieee80211_hw_flags -!Finclude/net/mac80211.h SET_IEEE80211_DEV -!Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR -!Finclude/net/mac80211.h ieee80211_ops -!Finclude/net/mac80211.h ieee80211_alloc_hw -!Finclude/net/mac80211.h ieee80211_register_hw -!Finclude/net/mac80211.h ieee80211_get_tx_led_name -!Finclude/net/mac80211.h ieee80211_get_rx_led_name -!Finclude/net/mac80211.h ieee80211_get_assoc_led_name -!Finclude/net/mac80211.h ieee80211_get_radio_led_name -!Finclude/net/mac80211.h ieee80211_unregister_hw -!Finclude/net/mac80211.h ieee80211_free_hw - - - - PHY configuration - TBD - - This chapter should describe PHY handling including - start/stop callbacks and the various structures used. - -!Finclude/net/mac80211.h ieee80211_conf -!Finclude/net/mac80211.h ieee80211_conf_flags - - - - Virtual interfaces - TBD - - This chapter should describe virtual interface basics - that are relevant to the driver (VLANs, MGMT etc are not.) - It should explain the use of the add_iface/remove_iface - callbacks as well as the interface configuration callbacks. - - Things related to AP mode should be discussed there. - - Things related to supporting multiple interfaces should be - in the appropriate chapter, a BIG FAT note should be here about - this though and the recommendation to allow only a single - interface in STA mode at first! - -!Finclude/net/mac80211.h ieee80211_vif - - - - Receive and transmit processing - - what should be here - TBD - - This should describe the receive and transmit - paths in mac80211/the drivers as well as - transmit status handling. - - - - Frame format -!Pinclude/net/mac80211.h Frame format - - - Packet alignment -!Pnet/mac80211/rx.c Packet alignment - - - Calling into mac80211 from interrupts -!Pinclude/net/mac80211.h Calling mac80211 from interrupts - - - functions/definitions -!Finclude/net/mac80211.h ieee80211_rx_status -!Finclude/net/mac80211.h mac80211_rx_flags -!Finclude/net/mac80211.h ieee80211_tx_info -!Finclude/net/mac80211.h ieee80211_rx -!Finclude/net/mac80211.h ieee80211_rx_irqsafe -!Finclude/net/mac80211.h ieee80211_tx_status -!Finclude/net/mac80211.h ieee80211_tx_status_irqsafe -!Finclude/net/mac80211.h ieee80211_rts_get -!Finclude/net/mac80211.h ieee80211_rts_duration -!Finclude/net/mac80211.h ieee80211_ctstoself_get -!Finclude/net/mac80211.h ieee80211_ctstoself_duration -!Finclude/net/mac80211.h ieee80211_generic_frame_duration -!Finclude/net/mac80211.h ieee80211_wake_queue -!Finclude/net/mac80211.h ieee80211_stop_queue -!Finclude/net/mac80211.h ieee80211_wake_queues -!Finclude/net/mac80211.h ieee80211_stop_queues - - - - - Frame filtering -!Pinclude/net/mac80211.h Frame filtering -!Finclude/net/mac80211.h ieee80211_filter_flags - - - - - Advanced driver interface - - - Information contained within this part of the book is - of interest only for advanced interaction of mac80211 - with drivers to exploit more hardware capabilities and - improve performance. - - - - - Hardware crypto acceleration -!Pinclude/net/mac80211.h Hardware crypto acceleration - -!Finclude/net/mac80211.h set_key_cmd -!Finclude/net/mac80211.h ieee80211_key_conf -!Finclude/net/mac80211.h ieee80211_key_alg -!Finclude/net/mac80211.h ieee80211_key_flags - - - - Powersave support -!Pinclude/net/mac80211.h Powersave support - - - - Beacon filter support -!Pinclude/net/mac80211.h Beacon filter support -!Finclude/net/mac80211.h ieee80211_beacon_loss - - - - Multiple queues and QoS support - TBD -!Finclude/net/mac80211.h ieee80211_tx_queue_params - - - - Access point mode support - TBD - Some parts of the if_conf should be discussed here instead - - Insert notes about VLAN interfaces with hw crypto here or - in the hw crypto chapter. - -!Finclude/net/mac80211.h ieee80211_get_buffered_bc -!Finclude/net/mac80211.h ieee80211_beacon_get - - - - Supporting multiple virtual interfaces - TBD - - Note: WDS with identical MAC address should almost always be OK - - - Insert notes about having multiple virtual interfaces with - different MAC addresses here, note which configurations are - supported by mac80211, add notes about supporting hw crypto - with it. - - - - - Hardware scan offload - TBD -!Finclude/net/mac80211.h ieee80211_scan_completed - - - - - Rate control interface - - TBD - - This part of the book describes the rate control algorithm - interface and how it relates to mac80211 and drivers. - - - - dummy chapter - TBD - - - - - Internals - - TBD - - This part of the book describes mac80211 internals. - - - - - Key handling - - Key handling basics -!Pnet/mac80211/key.c Key handling basics - - - MORE TBD - TBD - - - - - Receive processing - TBD - - - - Transmit processing - TBD - - - - Station info handling - - Programming information -!Fnet/mac80211/sta_info.h sta_info -!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags - - - STA information lifetime rules -!Pnet/mac80211/sta_info.c STA information lifetime rules - - - - - Synchronisation - TBD - Locking, lots of RCU - - -
-- cgit v1.2.3-59-g8ed1b From 2b2d7795371df85bb106513d1b5fec077a29176e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 17 Aug 2010 12:08:07 +0200 Subject: mac80211-hwsim: allow configuring IBSS It will not look standard-compliant in a sniffer because because it doesn't * sync TSF * adjust the TSF in beacons * send beacons at TBTT * cancel beacons when another phy sends However, it does allow testing the configuration and parts of the mac80211 code for IBSS and as such is still useful. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 01ad7f77383a..d9dd9f9d3040 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -9,7 +9,8 @@ /* * TODO: - * - IBSS mode simulation (Beacon transmission with competition for "air time") + * - Add TSF sync and fix IBSS beacon transmission by adding + * competition for "air time" at TBTT * - RX filtering based on filter configuration (data->rx_filter) */ @@ -620,7 +621,8 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, hwsim_check_magic(vif); if (vif->type != NL80211_IFTYPE_AP && - vif->type != NL80211_IFTYPE_MESH_POINT) + vif->type != NL80211_IFTYPE_MESH_POINT && + vif->type != NL80211_IFTYPE_ADHOC) return; skb = ieee80211_beacon_get(hw, vif); @@ -1295,6 +1297,7 @@ static int __init init_mac80211_hwsim(void) hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); hw->flags = IEEE80211_HW_MFP_CAPABLE | -- cgit v1.2.3-59-g8ed1b From 6ddbf8cd39dc1faee7ba60337b11eb02edfcbee6 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 6 Aug 2010 12:39:14 -0700 Subject: iwlwifi: fix thermal throttling related power management operation The current approach is very broken because it adds an often-used code path that will not initialise "cmd" at all. Signed-off-by: Johannes Berg Signed-off-by: Shanyu Zhao Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-power.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index da1f2ae24472..63c0ab46261f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -284,13 +284,11 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) priv->hw->conf.flags & IEEE80211_CONF_IDLE) iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && - priv->cfg->ops->lib->tt_ops.tt_power_mode) { - if (priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) { - /* in thermal throttling low power state */ - iwl_static_sleep_cmd(priv, &cmd, - priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), - dtimper); - } + priv->cfg->ops->lib->tt_ops.tt_power_mode && + priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) { + /* in thermal throttling low power state */ + iwl_static_sleep_cmd(priv, &cmd, + priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper); } else if (!enabled) iwl_power_sleep_cam_cmd(priv, &cmd); else if (priv->power_data.debug_sleep_level_override >= 0) -- cgit v1.2.3-59-g8ed1b From 24e0f9f84707560d029fe17395f71e99866b438b Mon Sep 17 00:00:00 2001 From: Julian Calaby Date: Tue, 17 Aug 2010 14:52:41 -0400 Subject: Hostap: Fix "'ret' set but not used" warning message from GCC in hostap CC [M] drivers/net/wireless/hostap/hostap_ioctl.o drivers/net/wireless/hostap/hostap_ioctl.c: In function 'prism2_request_scan': drivers/net/wireless/hostap/hostap_ioctl.c:1666:6: warning: variable 'ret' set but not used Signed-off-by: Julian Calaby Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index a85e43a8d758..6038633ef361 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c @@ -1696,7 +1696,7 @@ static int prism2_request_scan(struct net_device *dev) hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE, HFA384X_ROAMING_FIRMWARE); - return 0; + return ret; } #else /* !PRISM2_NO_STATION_MODES */ -- cgit v1.2.3-59-g8ed1b From 9c82d0a73f54adc2c8cc0ea10f91efc366b50992 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 23 Jul 2010 13:42:39 -0700 Subject: iwlwifi: remove unused define IWL_SIXTY_SECS is not been used, remove it Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index a2927b3a606e..91d9c8b3efeb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1052,7 +1052,6 @@ struct iwl_event_log { /* timer constants use to monitor and recover stuck tx queues in mSecs */ #define IWL_MONITORING_PERIOD (1000) #define IWL_ONE_HUNDRED_MSECS (100) -#define IWL_SIXTY_SECS (60000) enum iwl_reset { IWL_RF_RESET = 0, -- cgit v1.2.3-59-g8ed1b From 2cbc19f3d0cfe6cf7d9d2b3fac52976c3f2c6e89 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 23 Jul 2010 16:49:44 -0700 Subject: iwlwifi: additional comments in iwl_cfg No functional changes, just add additional comments to iwl_cfg structure Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e6d127df01ea..702d62bf4ee4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -278,6 +278,8 @@ struct iwl_mod_params { * @chain_noise_calib_by_driver: driver has the capability to perform * chain noise calibration operation * @scan_antennas: available antenna for scan operation + * @need_dc_calib: need to perform init dc calibration + * @bt_statistics: use BT version of statistics notification * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the -- cgit v1.2.3-59-g8ed1b From b15826a795969cbdd85a0b5100165e240e6508e4 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 28 Jul 2010 09:18:53 -0700 Subject: iwlwifi: max/min aggregation time limit Set the minimum and maximum for aggregation time limit in uSec. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 9435fd934d5e..c6a0470b2f50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2092,8 +2092,8 @@ struct iwl_link_qual_general_params { } __packed; #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ -#define LINK_QUAL_AGG_TIME_LIMIT_MAX (65535) -#define LINK_QUAL_AGG_TIME_LIMIT_MIN (0) +#define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) +#define LINK_QUAL_AGG_TIME_LIMIT_MIN (100) #define LINK_QUAL_AGG_DISABLE_START_DEF (3) #define LINK_QUAL_AGG_DISABLE_START_MAX (255) -- cgit v1.2.3-59-g8ed1b From 7469701e10adb6bcc3d66544bd9f6d553fc678c9 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 28 Jul 2010 09:18:54 -0700 Subject: iwlwifi: make aggregation time limit configurable By default, aggregation time limit is 4000 uSec, add the parameter to .cfg to allow this parameter can be configure per device base if needed. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 10 ++++++++++ drivers/net/wireless/iwlwifi/iwl-commands.h | 6 ++++-- drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 23e5c42e7d7e..7c4deee4c527 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2694,8 +2694,18 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; + lq_cmd->agg_params.agg_time_limit = cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); + /* + * overwrite if needed, pass aggregation time limit + * to uCode in uSec + */ + if (priv && priv->cfg->agg_time_limit && + priv->cfg->agg_time_limit >= LINK_QUAL_AGG_TIME_LIMIT_MIN && + priv->cfg->agg_time_limit <= LINK_QUAL_AGG_TIME_LIMIT_MAX) + lq_cmd->agg_params.agg_time_limit = + cpu_to_le16(priv->cfg->agg_time_limit); } static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index c6a0470b2f50..14a7a8c0711a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2110,8 +2110,10 @@ struct iwl_link_qual_general_params { */ struct iwl_link_qual_agg_params { - /* Maximum number of uSec in aggregation. - * Driver should set this to 4000 (4 milliseconds). */ + /* + *Maximum number of uSec in aggregation. + * default set to 4000 (4 milliseconds) if not configured in .cfg + */ __le16 agg_time_limit; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 702d62bf4ee4..f5586b5e0496 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -280,6 +280,7 @@ struct iwl_mod_params { * @scan_antennas: available antenna for scan operation * @need_dc_calib: need to perform init dc calibration * @bt_statistics: use BT version of statistics notification + * @agg_time_limit: maximum number of uSec in aggregation * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the @@ -350,6 +351,7 @@ struct iwl_cfg { u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; const bool need_dc_calib; const bool bt_statistics; + u16 agg_time_limit; }; /*************************** -- cgit v1.2.3-59-g8ed1b From 81e95430aaa898799421617c2db2882386bab69a Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Wed, 28 Jul 2010 13:40:27 -0700 Subject: iwlwifi: do not call ieee80211_frequency_to_channel A few cases in iwlwifi driver function ieee80211_frequency_to_channel() is called to get channel number from center frequency. This is not needed since the channel number is already saved in hw_value field of struct ieee80211_channel in function iwlcore_init_geos(). So replace those function calls with hw_value field of struct ieee80211_channel. Signed-off-by: Shanyu Zhao Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 6 ++---- 7 files changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d6da356608fa..9415b71fa12d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1470,7 +1470,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, cmd.band = band; cmd.expect_beacon = 0; - ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); + ch = ch_switch->channel->hw_value; cmd.channel = cpu_to_le16(ch); cmd.rxon_flags = priv->staging_rxon.flags; cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 54083a39c724..0c2ea136cfd5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -291,7 +291,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, }; cmd.band = priv->band == IEEE80211_BAND_2GHZ; - ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); + ch = ch_switch->channel->hw_value; IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", priv->active_rxon.channel, ch); cmd.channel = cpu_to_le16(ch); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 7902de172a38..e0c6c3afba27 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -214,7 +214,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, }; cmd.band = priv->band == IEEE80211_BAND_2GHZ; - ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); + ch = ch_switch->channel->hw_value; IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", priv->active_rxon.channel, ch); cmd.channel = cpu_to_le16(ch); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 9dd9e64c2b0b..eedd71f5506b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1098,7 +1098,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, if (chan->band != band) continue; - channel = ieee80211_frequency_to_channel(chan->center_freq); + channel = chan->hw_value; scan_ch->channel = cpu_to_le16(channel); ch_info = iwl_get_channel_info(priv, band, channel); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index bce77eeb31c0..eecfec7c4063 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3655,8 +3655,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); if (priv->cfg->ops->lib->set_channel_switch) { - ch = ieee80211_frequency_to_channel( - ch_switch->channel->center_freq); + ch = ch_switch->channel->hw_value; if (le16_to_cpu(priv->active_rxon.channel) != ch) { ch_info = iwl_get_channel_info(priv, conf->channel->band, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b5045c62de7e..dc29844cce1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -916,7 +916,7 @@ EXPORT_SYMBOL(iwl_get_single_channel_number); int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) { enum ieee80211_band band = ch->band; - u16 channel = ieee80211_frequency_to_channel(ch->center_freq); + u16 channel = ch->hw_value; if (!iwl_get_channel_info(priv, band, channel)) { IWL_DEBUG_INFO(priv, "Could not set channel to %d [%d]\n", @@ -2032,7 +2032,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) if (scan_active) goto set_ch_out; - ch = ieee80211_frequency_to_channel(conf->channel->center_freq); + ch = conf->channel->hw_value; ch_info = iwl_get_channel_info(priv, conf->channel->band, ch); if (!is_channel_valid(ch_info)) { IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index e96a1bb12783..d3acdae72381 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -467,8 +467,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, for (i = 0; i < supp_band->n_channels; i++) pos += scnprintf(buf + pos, bufsz - pos, "%d: %ddBm: BSS%s%s, %s.\n", - ieee80211_frequency_to_channel( - channels[i].center_freq), + channels[i].hw_value, channels[i].max_power, channels[i].flags & IEEE80211_CHAN_RADAR ? " (IEEE 802.11h required)" : "", @@ -491,8 +490,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, for (i = 0; i < supp_band->n_channels; i++) pos += scnprintf(buf + pos, bufsz - pos, "%d: %ddBm: BSS%s%s, %s.\n", - ieee80211_frequency_to_channel( - channels[i].center_freq), + channels[i].hw_value, channels[i].max_power, channels[i].flags & IEEE80211_CHAN_RADAR ? " (IEEE 802.11h required)" : "", -- cgit v1.2.3-59-g8ed1b From aa2dc6b529d781a375f7ad3185198f6315865b06 Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Wed, 28 Jul 2010 13:40:39 -0700 Subject: iwlwifi: avoid race condition in channel change When iwl_mac_config() is called by mac80211, the channel pointer hw->conf->channel can potentially change, resulting in mismatch band and channel number when configuring RXON command. To avoid this situation, save the channel pointer in local variables and validate the channel before using it. Note that priv->mutex is locked during the whole function so the local variables are safe. Same change is applied to iwl_mac_channel_switch() since basically it copies code from iwl_mac_config(). Also removed an outdated comment in the flow. Signed-off-by: Shanyu Zhao Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 14 ++++++-------- drivers/net/wireless/iwlwifi/iwl-core.c | 14 ++++++-------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index eecfec7c4063..61ecd180982e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3632,6 +3632,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, struct iwl_priv *priv = hw->priv; const struct iwl_channel_info *ch_info; struct ieee80211_conf *conf = &hw->conf; + struct ieee80211_channel *channel = ch_switch->channel; struct iwl_ht_config *ht_conf = &priv->current_ht_config; u16 ch; unsigned long flags = 0; @@ -3655,10 +3656,10 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); if (priv->cfg->ops->lib->set_channel_switch) { - ch = ch_switch->channel->hw_value; + ch = channel->hw_value; if (le16_to_cpu(priv->active_rxon.channel) != ch) { ch_info = iwl_get_channel_info(priv, - conf->channel->band, + channel->band, ch); if (!is_channel_valid(ch_info)) { IWL_DEBUG_MAC80211(priv, "invalid channel\n"); @@ -3687,15 +3688,12 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, } else ht_conf->is_40mhz = false; - /* if we are switching from ht to 2.4 clear flags - * from any ht related info since 2.4 does not - * support ht */ - if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) + if (le16_to_cpu(priv->staging_rxon.channel) != ch) priv->staging_rxon.flags = 0; - iwl_set_rxon_channel(priv, conf->channel); + iwl_set_rxon_channel(priv, channel); iwl_set_rxon_ht(priv, ht_conf); - iwl_set_flags_for_band(priv, conf->channel->band, + iwl_set_flags_for_band(priv, channel->band, priv->vif); spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index dc29844cce1f..39aea7545603 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1992,6 +1992,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) struct iwl_priv *priv = hw->priv; const struct iwl_channel_info *ch_info; struct ieee80211_conf *conf = &hw->conf; + struct ieee80211_channel *channel = conf->channel; struct iwl_ht_config *ht_conf = &priv->current_ht_config; unsigned long flags = 0; int ret = 0; @@ -2001,7 +2002,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", - conf->channel->hw_value, changed); + channel->hw_value, changed); if (unlikely(!priv->cfg->mod_params->disable_hw_scan && test_bit(STATUS_SCANNING, &priv->status))) { @@ -2032,8 +2033,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) if (scan_active) goto set_ch_out; - ch = conf->channel->hw_value; - ch_info = iwl_get_channel_info(priv, conf->channel->band, ch); + ch = channel->hw_value; + ch_info = iwl_get_channel_info(priv, channel->band, ch); if (!is_channel_valid(ch_info)) { IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); ret = -EINVAL; @@ -2064,16 +2065,13 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) * from BSS config in iwl_ht_conf */ ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; - /* if we are switching from ht to 2.4 clear flags - * from any ht related info since 2.4 does not - * support ht */ if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) priv->staging_rxon.flags = 0; - iwl_set_rxon_channel(priv, conf->channel); + iwl_set_rxon_channel(priv, channel); iwl_set_rxon_ht(priv, ht_conf); - iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); + iwl_set_flags_for_band(priv, channel->band, priv->vif); spin_unlock_irqrestore(&priv->lock, flags); if (priv->cfg->ops->lib->update_bcast_station) -- cgit v1.2.3-59-g8ed1b From 3edb5fd6ac898182a186d403695986f6ff51ac65 Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Tue, 27 Jul 2010 20:45:15 -0700 Subject: iwlwifi: cleanup iwl_set_rxon_channel() Update outdated comments of iwl_set_rxon_channel() to reflect the current signature. Also remove the unnecessary validation of the channel. Those channel info are constructed in iwlwifi driver and mac80211 will never modify the content of the struct. Also everytime before this function is called the channel info has been validated already (as a paranoid check). Signed-off-by: Shanyu Zhao Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 39aea7545603..602636c88fef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -904,26 +904,19 @@ u8 iwl_get_single_channel_number(struct iwl_priv *priv, EXPORT_SYMBOL(iwl_get_single_channel_number); /** - * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON - * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz - * @channel: Any channel valid for the requested phymode + * iwl_set_rxon_channel - Set the band and channel values in staging RXON + * @ch: requested channel as a pointer to struct ieee80211_channel - * In addition to setting the staging RXON, priv->phymode is also set. + * In addition to setting the staging RXON, priv->band is also set. * * NOTE: Does not commit to the hardware; it sets appropriate bit fields - * in the staging RXON flag structure based on the phymode + * in the staging RXON flag structure based on the ch->band */ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) { enum ieee80211_band band = ch->band; u16 channel = ch->hw_value; - if (!iwl_get_channel_info(priv, band, channel)) { - IWL_DEBUG_INFO(priv, "Could not set channel to %d [%d]\n", - channel, band); - return -EINVAL; - } - if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && (priv->band == band)) return 0; -- cgit v1.2.3-59-g8ed1b From 948f5a2f08cb782adf3c5bb92abc6dbec2b4275f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Jul 2010 07:07:51 -0700 Subject: iwlwifi: refactor iwl_setup_rxon_timing All callers of iwl_setup_rxon_timing() also send the command right away, so rename the function to iwl_send_rxon_timing() and move the sending into it. Also, some callers clear the data, this can be done always and thus moved in as well. Finally, there's no reason for the function to acquire the spinlock, but it should be called with the mutex held, so assert that. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 ++------ drivers/net/wireless/iwlwifi/iwl-core.c | 14 +++++++++----- drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 11 ++--------- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 61ecd180982e..f832535c3a47 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3109,9 +3109,7 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - iwl_setup_rxon_timing(priv, vif); - ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, - sizeof(priv->rxon_timing), &priv->rxon_timing); + ret = iwl_send_rxon_timing(priv, vif); if (ret) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); @@ -3347,9 +3345,7 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) iwlcore_commit_rxon(priv); /* RXON Timing */ - iwl_setup_rxon_timing(priv, vif); - ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, - sizeof(priv->rxon_timing), &priv->rxon_timing); + ret = iwl_send_rxon_timing(priv, vif); if (ret) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 602636c88fef..7754be4463d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -491,17 +491,19 @@ static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) return new_val; } -void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) +int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) { u64 tsf; s32 interval_tm, rem; - unsigned long flags; struct ieee80211_conf *conf = NULL; u16 beacon_int; conf = ieee80211_get_hw_conf(priv->hw); - spin_lock_irqsave(&priv->lock, flags); + lockdep_assert_held(&priv->mutex); + + memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); + priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); @@ -524,14 +526,16 @@ void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) rem = do_div(tsf, interval_tm); priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); - spin_unlock_irqrestore(&priv->lock, flags); IWL_DEBUG_ASSOC(priv, "beacon interval %d beacon timer %d beacon tim %d\n", le16_to_cpu(priv->rxon_timing.beacon_interval), le32_to_cpu(priv->rxon_timing.beacon_init_val), le16_to_cpu(priv->rxon_timing.atim_window)); + + return iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, + sizeof(priv->rxon_timing), &priv->rxon_timing); } -EXPORT_SYMBOL(iwl_setup_rxon_timing); +EXPORT_SYMBOL(iwl_send_rxon_timing); void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f5586b5e0496..edadca510099 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -714,7 +714,7 @@ extern int iwl_send_lq_cmd(struct iwl_priv *priv, void iwl_apm_stop(struct iwl_priv *priv); int iwl_apm_init(struct iwl_priv *priv); -void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif); +int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif); static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) { return priv->cfg->ops->hcmd->rxon_assoc(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index faa2e0037e10..84494b1f833e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3094,10 +3094,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); - iwl_setup_rxon_timing(priv, vif); - rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, - sizeof(priv->rxon_timing), &priv->rxon_timing); + rc = iwl_send_rxon_timing(priv, vif); if (rc) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); @@ -3271,11 +3268,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) iwlcore_commit_rxon(priv); /* RXON Timing */ - memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); - iwl_setup_rxon_timing(priv, vif); - rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, - sizeof(priv->rxon_timing), - &priv->rxon_timing); + rc = iwl_send_rxon_timing(priv, vif); if (rc) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); -- cgit v1.2.3-59-g8ed1b From b1a78858c4579d678444c007617292ccf6f7a315 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 31 Jul 2010 08:52:03 -0700 Subject: iwlagn: adjust starting action for rate scale During rate scale, reset starting action after making action adjustment to avoid the possibility of break out of loop too early. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 7c4deee4c527..4d5738dfc7eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1265,7 +1265,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, struct iwl_rate_scale_data *window = &(tbl->win[index]); u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); - u8 start_action = tbl->action; + u8 start_action; u8 valid_tx_ant = priv->hw_params.valid_tx_ant; u8 tx_chains_num = priv->hw_params.tx_chains_num; int ret = 0; @@ -1277,6 +1277,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && tbl->action > IWL_LEGACY_SWITCH_SISO) tbl->action = IWL_LEGACY_SWITCH_SISO; + start_action = tbl->action; for (; ;) { lq_sta->action_counter++; switch (tbl->action) { @@ -1403,7 +1404,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); - u8 start_action = tbl->action; + u8 start_action; u8 valid_tx_ant = priv->hw_params.valid_tx_ant; u8 tx_chains_num = priv->hw_params.tx_chains_num; u8 update_search_tbl_counter = 0; @@ -1414,6 +1415,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, /* stay in SISO */ tbl->action = IWL_SISO_SWITCH_ANTENNA1; } + start_action = tbl->action; for (;;) { lq_sta->action_counter++; switch (tbl->action) { @@ -1541,7 +1543,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); - u8 start_action = tbl->action; + u8 start_action; u8 valid_tx_ant = priv->hw_params.valid_tx_ant; u8 tx_chains_num = priv->hw_params.tx_chains_num; u8 update_search_tbl_counter = 0; @@ -1553,6 +1555,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, /* switch in SISO */ tbl->action = IWL_MIMO2_SWITCH_SISO_A; } + start_action = tbl->action; for (;;) { lq_sta->action_counter++; switch (tbl->action) { @@ -1682,7 +1685,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); - u8 start_action = tbl->action; + u8 start_action; u8 valid_tx_ant = priv->hw_params.valid_tx_ant; u8 tx_chains_num = priv->hw_params.tx_chains_num; int ret; @@ -1694,6 +1697,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, /* switch in SISO */ tbl->action = IWL_MIMO3_SWITCH_SISO_A; } + start_action = tbl->action; for (;;) { lq_sta->action_counter++; switch (tbl->action) { -- cgit v1.2.3-59-g8ed1b From 80e9158c3fc1b55301b71cbeea2b31aa1d3c9b76 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 3 Aug 2010 08:23:32 -0700 Subject: iwlagn: continue perform rate scale when error detected If for some reason, the actual link command not matching neither active nor search table; instead of return and not performing rate scale, by-pass the data collection and continue the rate scale process. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 4d5738dfc7eb..a4563389bad0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -82,6 +82,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta); static void rs_fill_link_cmd(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, u32 rate_n_flags); +static void rs_stay_in_table(struct iwl_lq_sta *lq_sta); #ifdef CONFIG_MAC80211_DEBUGFS @@ -502,6 +503,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); u8 mcs; + memset(tbl, 0, sizeof(struct iwl_scale_tbl_info)); *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); if (*rate_idx == IWL_RATE_INVALID) { @@ -848,7 +850,20 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); } else { IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); - return; + tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + IWL_DEBUG_RATE(priv, "active- lq:%x, ant:%x, SGI:%d\n", + tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI); + tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); + IWL_DEBUG_RATE(priv, "search- lq:%x, ant:%x, SGI:%d\n", + tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI); + IWL_DEBUG_RATE(priv, "actual- lq:%x, ant:%x, SGI:%d\n", + tbl_type.lq_type, tbl_type.ant_type, tbl_type.is_SGI); + /* + * no matching table found, let's by-pass the data collection + * and continue to perform rate scale to find the rate table + */ + rs_stay_in_table(lq_sta); + goto done; } /* @@ -909,7 +924,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, } /* The last TX rate is cached in lq_sta; it's set in if/else above */ lq_sta->last_rate_n_flags = tx_rate; - +done: /* See if there's a better rate or modulation mode to try. */ if (sta && sta->supp_rates[sband->band]) rs_rate_scale_perform(priv, skb, sta, lq_sta); @@ -2598,7 +2613,6 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, rs_dbgfs_set_mcs(lq_sta, &new_rate, index); /* Interpret new_rate (rate_n_flags) */ - memset(&tbl_type, 0, sizeof(tbl_type)); rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, &rate_idx); -- cgit v1.2.3-59-g8ed1b From 30c1b0f7e96144e42e2be0bdec18d2475f5af31b Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 4 Aug 2010 08:05:33 -0700 Subject: iwlwifi: additional parameter in REPLY_RX_PHY_CMD Adding additional parameter in REPLY_RX_PHY_CMD, frame_time indicate the frame's time on the air based on byte count and frame rate calculation Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 14a7a8c0711a..13893a0a6197 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -1401,7 +1401,7 @@ struct iwl_rx_phy_res { u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */ __le32 rate_n_flags; /* RATE_MCS_* */ __le16 byte_count; /* frame's byte-count */ - __le16 reserved3; + __le16 frame_time; /* frame's time on the air */ } __packed; struct iwl_rx_mpdu_res_start { -- cgit v1.2.3-59-g8ed1b From 7ccc896f4c9d5f11e449368cf520565bf2073a9b Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 4 Aug 2010 08:42:17 -0700 Subject: iwlwifi: more generic name for rssi calc in iwlagn Change the define to more generic naming to match _agn devices since the rssi calculation are common function for 5000 series and up Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 21 ++++++++++-------- drivers/net/wireless/iwlwifi/iwl-commands.h | 33 ++++++++++++++++------------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 75b901b3eb1e..84939763d178 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -235,13 +235,13 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, /* data from PHY/DSP regarding signal strength, etc., * contents are always there, not configurable by host */ - struct iwl5000_non_cfg_phy *ncphy = - (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; + struct iwlagn_non_cfg_phy *ncphy = + (struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf; u32 val, rssi_a, rssi_b, rssi_c, max_rssi; u8 agc; - val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); - agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; + val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]); + agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS; /* Find max rssi among 3 possible receivers. * These values are measured by the digital signal processor (DSP). @@ -249,11 +249,14 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, * if the radio's automatic gain control (AGC) is working right. * AGC value (see below) will provide the "interesting" info. */ - val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); - rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; - rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; - val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); - rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; + val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]); + rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >> + IWLAGN_OFDM_RSSI_A_BIT_POS; + rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >> + IWLAGN_OFDM_RSSI_B_BIT_POS; + val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]); + rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >> + IWLAGN_OFDM_RSSI_C_BIT_POS; max_rssi = max_t(u32, rssi_a, rssi_b); max_rssi = max_t(u32, max_rssi, rssi_c); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 13893a0a6197..4083e4430827 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -1367,21 +1367,24 @@ struct iwl4965_rx_non_cfg_phy { } __packed; -#define IWL50_RX_RES_PHY_CNT 8 -#define IWL50_RX_RES_AGC_IDX 1 -#define IWL50_RX_RES_RSSI_AB_IDX 2 -#define IWL50_RX_RES_RSSI_C_IDX 3 -#define IWL50_OFDM_AGC_MSK 0xfe00 -#define IWL50_OFDM_AGC_BIT_POS 9 -#define IWL50_OFDM_RSSI_A_MSK 0x00ff -#define IWL50_OFDM_RSSI_A_BIT_POS 0 -#define IWL50_OFDM_RSSI_B_MSK 0xff0000 -#define IWL50_OFDM_RSSI_B_BIT_POS 16 -#define IWL50_OFDM_RSSI_C_MSK 0x00ff -#define IWL50_OFDM_RSSI_C_BIT_POS 0 - -struct iwl5000_non_cfg_phy { - __le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT]; /* up to 8 phy entries */ +#define IWLAGN_RX_RES_PHY_CNT 8 +#define IWLAGN_RX_RES_AGC_IDX 1 +#define IWLAGN_RX_RES_RSSI_AB_IDX 2 +#define IWLAGN_RX_RES_RSSI_C_IDX 3 +#define IWLAGN_OFDM_AGC_MSK 0xfe00 +#define IWLAGN_OFDM_AGC_BIT_POS 9 +#define IWLAGN_OFDM_RSSI_INBAND_A_BITMSK 0x00ff +#define IWLAGN_OFDM_RSSI_ALLBAND_A_BITMSK 0xff00 +#define IWLAGN_OFDM_RSSI_A_BIT_POS 0 +#define IWLAGN_OFDM_RSSI_INBAND_B_BITMSK 0xff0000 +#define IWLAGN_OFDM_RSSI_ALLBAND_B_BITMSK 0xff000000 +#define IWLAGN_OFDM_RSSI_B_BIT_POS 16 +#define IWLAGN_OFDM_RSSI_INBAND_C_BITMSK 0x00ff +#define IWLAGN_OFDM_RSSI_ALLBAND_C_BITMSK 0xff00 +#define IWLAGN_OFDM_RSSI_C_BIT_POS 0 + +struct iwlagn_non_cfg_phy { + __le32 non_cfg_phy[IWLAGN_RX_RES_PHY_CNT]; /* up to 8 phy entries */ } __packed; -- cgit v1.2.3-59-g8ed1b From 172c1d112a38c8721fe1d7114e2ce1e8a91451c1 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 4 Aug 2010 12:02:43 -0700 Subject: iwlwifi: configurable ampdu factor and density Add ampdu factor and density to .cfg, this allow both parameters can be configure per device based. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl-core.h | 4 ++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 13 ++++++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 7754be4463d8..346e0ad7e351 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -239,7 +239,11 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; + if (priv->cfg->ampdu_factor) + ht_info->ampdu_factor = priv->cfg->ampdu_factor; ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; + if (priv->cfg->ampdu_density) + ht_info->ampdu_density = priv->cfg->ampdu_density; ht_info->mcs.rx_mask[0] = 0xFF; if (rx_chains_num >= 2) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index edadca510099..3efab0e29b06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -281,6 +281,8 @@ struct iwl_mod_params { * @need_dc_calib: need to perform init dc calibration * @bt_statistics: use BT version of statistics notification * @agg_time_limit: maximum number of uSec in aggregation + * @ampdu_factor: Maximum A-MPDU length factor + * @ampdu_density: Minimum A-MPDU spacing * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the @@ -352,6 +354,8 @@ struct iwl_cfg { const bool need_dc_calib; const bool bt_statistics; u16 agg_time_limit; + u8 ampdu_factor; + u8 ampdu_density; }; /*************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 91d9c8b3efeb..f72fbf4dc92b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -435,7 +435,13 @@ union iwl_ht_rate_supp { }; }; -#define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3) +#define CFG_HT_RX_AMPDU_FACTOR_8K (0x0) +#define CFG_HT_RX_AMPDU_FACTOR_16K (0x1) +#define CFG_HT_RX_AMPDU_FACTOR_32K (0x2) +#define CFG_HT_RX_AMPDU_FACTOR_64K (0x3) +#define CFG_HT_RX_AMPDU_FACTOR_DEF CFG_HT_RX_AMPDU_FACTOR_64K +#define CFG_HT_RX_AMPDU_FACTOR_MAX CFG_HT_RX_AMPDU_FACTOR_64K +#define CFG_HT_RX_AMPDU_FACTOR_MIN CFG_HT_RX_AMPDU_FACTOR_8K /* * Maximal MPDU density for TX aggregation @@ -444,8 +450,13 @@ union iwl_ht_rate_supp { * 6 - 8us density * 7 - 16us density */ +#define CFG_HT_MPDU_DENSITY_2USEC (0x4) #define CFG_HT_MPDU_DENSITY_4USEC (0x5) +#define CFG_HT_MPDU_DENSITY_8USEC (0x6) +#define CFG_HT_MPDU_DENSITY_16USEC (0x7) #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC +#define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC +#define CFG_HT_MPDU_DENSITY_MIN (0x1) struct iwl_ht_config { /* self configuration data */ -- cgit v1.2.3-59-g8ed1b From 79e88e79a29abede50bf82064ad9d9b1a625e42a Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 11 Aug 2010 07:30:20 -0700 Subject: iwlwifi: remove unused iwl_send_card_state function iwl_send_card_state() is not being call from anywhere, remove it. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 22 ---------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 2 -- 2 files changed, 24 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 346e0ad7e351..ef713003682e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1515,28 +1515,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) } EXPORT_SYMBOL(iwl_send_statistics_request); -/* - * CARD_STATE_CMD - * - * Use: Sets the device's internal card state to enable, disable, or halt - * - * When in the 'enable' state the card operates as normal. - * When in the 'disable' state, the card enters into a low power mode. - * When in the 'halt' state, the card is shut down and must be fully - * restarted to come back on. - */ -int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) -{ - struct iwl_host_cmd cmd = { - .id = REPLY_CARD_STATE_CMD, - .len = sizeof(u32), - .data = &flags, - .flags = meta_flag, - }; - - return iwl_send_cmd(priv, &cmd); -} - void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 3efab0e29b06..870c62d438a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -595,8 +595,6 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); -int iwl_send_card_state(struct iwl_priv *priv, u32 flags, - u8 meta_flag); /***************************************************** * PCI * -- cgit v1.2.3-59-g8ed1b From 3939608591d1d0cbb79d7afd08beabcfb5eb115f Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Thu, 12 Aug 2010 10:24:07 -0700 Subject: iwlwifi: enable experimental ucode support ucode firmware may need to be released as experimental for testing or debugging. released ucode filenames have the API version as the last component. experimental ucode files will have that component be "exp" and the fw_version string reported by ethtool will also contain the string EXP to clearly identify this ucode from released ucode. EXP is short for EXPERIMENTAL since fw_version has a max lenght on 32. this capability is controlled by Kconfig and defaulted to not be used. Signed-off-by: Jay Sternberg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/Kconfig | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 33 +++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index a51e4da1bdfc..7ab5b51951ff 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -36,6 +36,12 @@ config IWLWIFI_DEBUGFS is a low-impact option that allows getting insight into the driver's state at runtime. +config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE + bool "Experimental uCode support" + depends on IWLWIFI && IWLWIFI_DEBUG + ---help--- + Enable use of experimental ucode for testing and debugging. + config IWLWIFI_DEVICE_TRACING bool "iwlwifi device access tracing" depends on IWLWIFI diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f832535c3a47..40b82d9f309e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1659,24 +1659,37 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); static int iwl_mac_setup_register(struct iwl_priv *priv, struct iwlagn_ucode_capabilities *capa); +#define UCODE_EXPERIMENTAL_INDEX 100 +#define UCODE_EXPERIMENTAL_TAG "exp" + static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) { const char *name_pre = priv->cfg->fw_name_pre; + char tag[8]; - if (first) + if (first) { +#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE + priv->fw_index = UCODE_EXPERIMENTAL_INDEX; + strcpy(tag, UCODE_EXPERIMENTAL_TAG); + } else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) { +#endif priv->fw_index = priv->cfg->ucode_api_max; - else + sprintf(tag, "%d", priv->fw_index); + } else { priv->fw_index--; + sprintf(tag, "%d", priv->fw_index); + } if (priv->fw_index < priv->cfg->ucode_api_min) { IWL_ERR(priv, "no suitable firmware found!\n"); return -ENOENT; } - sprintf(priv->firmware_name, "%s%d%s", - name_pre, priv->fw_index, ".ucode"); + sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode"); - IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n", + IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n", + (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) + ? "EXPERIMENTAL " : "", priv->firmware_name); return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, @@ -1971,8 +1984,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) memset(&pieces, 0, sizeof(pieces)); if (!ucode_raw) { - IWL_ERR(priv, "request for firmware file '%s' failed.\n", - priv->firmware_name); + if (priv->fw_index <= priv->cfg->ucode_api_max) + IWL_ERR(priv, + "request for firmware file '%s' failed.\n", + priv->firmware_name); goto try_again; } @@ -2019,7 +2034,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) api_max, api_ver); if (build) - sprintf(buildstr, " build %u", build); + sprintf(buildstr, " build %u%s", build, + (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) + ? " (EXP)" : ""); else buildstr[0] = '\0'; -- cgit v1.2.3-59-g8ed1b From 110ff6db6f6fbb946c099f49f666b59258746048 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Thu, 12 Aug 2010 12:15:55 -0700 Subject: iwlwifi: move debug options into submenu more debug options being added so it is useful to move them into a submenu for ease of readability when using config commands like make menuconfig and make xconfig Signed-off-by: Jay Sternberg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 7ab5b51951ff..b82364258dc5 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -3,6 +3,9 @@ config IWLWIFI depends on PCI && MAC80211 select FW_LOADER +menu "Debugging Options" + depends on IWLWIFI + config IWLWIFI_DEBUG bool "Enable full debugging output in iwlagn and iwl3945 drivers" depends on IWLWIFI @@ -59,6 +62,7 @@ config IWLWIFI_DEVICE_TRACING If unsure, say Y so we can help you better when problems occur. +endmenu config IWLAGN tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)" -- cgit v1.2.3-59-g8ed1b From 8d5ad08525f1a8e0484d125ba155dbd3c3282ab8 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Tue, 17 Aug 2010 22:46:52 +0300 Subject: wl1251: add missing __packed modifier for some structs Several acx and cmd structures are missing __packed modifier, add it. This was noticed while comparing them with corresponding wl1271 code. Signed-off-by: Grazvydas Ignotas Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_acx.h | 6 +++--- drivers/net/wireless/wl12xx/wl1251_cmd.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index 842df310d92a..9864124d9e1b 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h @@ -37,7 +37,7 @@ struct acx_header { /* payload length (not including headers */ u16 len; -}; +} __packed; struct acx_error_counter { struct acx_header header; @@ -471,7 +471,7 @@ struct acx_conn_monit_params { u32 synch_fail_thold; /* number of beacons missed */ u32 bss_lose_timeout; /* number of TU's from synch fail */ -}; +} __packed; enum { SG_ENABLE = 0, @@ -1056,7 +1056,7 @@ struct acx_rate_class { u8 long_retry_limit; u8 aflags; u8 reserved; -}; +} __packed; struct acx_rate_policy { struct acx_header header; diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h index a9e4991369be..60d7e522486c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h @@ -111,7 +111,7 @@ struct wl1251_cmd_header { struct wl1251_command { struct wl1251_cmd_header header; u8 parameters[MAX_CMD_PARAMS]; -}; +} __packed; enum { CMD_MAILBOX_IDLE = 0, @@ -164,7 +164,7 @@ struct cmd_read_write_memory { of this field is the Host in WRITE command or the Wilink in READ command. */ u8 value[MAX_READ_SIZE]; -}; +} __packed; #define CMDMBOX_HEADER_LEN 4 #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 @@ -339,7 +339,7 @@ struct wl1251_cmd_trigger_scan_to { struct wl1251_cmd_header header; u32 timeout; -}; +} __packed; /* HW encryption keys */ #define NUM_ACCESS_CATEGORIES_COPY 4 -- cgit v1.2.3-59-g8ed1b From d41776fad4c6601c1711d4e454291efd6687addb Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Tue, 17 Aug 2010 22:46:53 +0300 Subject: wl1251: fix event handling mechanism In case both A and B events occured simultaneously, current code would only process A and clear both interrupts. Make it process both events instead. Based on wl1271 patches by Juuso Oikarinen: 1fd2794f36913992798184c464fe8f85753b13e0 13f2dc52c69bcca074cd12d4806953b2af45c386 Signed-off-by: Grazvydas Ignotas Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 6d31c855fcfe..51474b697c1a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -293,14 +293,14 @@ static void wl1251_irq_work(struct work_struct *work) wl1251_tx_complete(wl); } - if (intr & (WL1251_ACX_INTR_EVENT_A | - WL1251_ACX_INTR_EVENT_B)) { - wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", - intr); - if (intr & WL1251_ACX_INTR_EVENT_A) - wl1251_event_handle(wl, 0); - else - wl1251_event_handle(wl, 1); + if (intr & WL1251_ACX_INTR_EVENT_A) { + wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_A"); + wl1251_event_handle(wl, 0); + } + + if (intr & WL1251_ACX_INTR_EVENT_B) { + wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_B"); + wl1251_event_handle(wl, 1); } if (intr & WL1251_ACX_INTR_INIT_COMPLETE) -- cgit v1.2.3-59-g8ed1b From 5b44a1b5164c69cb274215fc79a9f4f5a1203c4d Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Tue, 17 Aug 2010 22:46:54 +0300 Subject: wl1251: fix beacon filter table structure The beacon filter table configuration ACX structure had certain elements reversed, fix it to match TI driver. Based on wl1271 patch 1937e742639c03a6fe77239c3003ce9602302117 by Juuso Oikarinen. Signed-off-by: Grazvydas Ignotas Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_acx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index 9864124d9e1b..a8845b8f2451 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h @@ -459,8 +459,8 @@ struct acx_beacon_filter_ie_table { struct acx_header header; u8 num_ie; - u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; u8 pad[3]; + u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; } __packed; #define SYNCH_FAIL_DEFAULT_THRESHOLD 10 /* number of beacons */ -- cgit v1.2.3-59-g8ed1b From 7273b9700b74e8c26b612207aea47effb0e530bf Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Tue, 17 Aug 2010 22:46:55 +0300 Subject: wl1251: wait for join command complete event Poll for join command completion instead of waiting blindly for 10 msecs. There is a timeout of 100 msecs, if the command doesn't complete by then, we return an error code. Based on wl1271 patch 99d84c1de8fdf5f9b09f07fdbc628857a040bf8b by Luciano Coelho. Signed-off-by: Grazvydas Ignotas Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_boot.c | 2 +- drivers/net/wireless/wl12xx/wl1251_event.c | 29 +++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1251_event.h | 1 + drivers/net/wireless/wl12xx/wl1251_main.c | 8 +++----- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 65e0416be5b6..5e65f47fda8a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c @@ -302,7 +302,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) ROAMING_TRIGGER_LOW_RSSI_EVENT_ID | ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID | REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID | - BT_PTA_PREDICTION_EVENT_ID; + BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID; ret = wl1251_event_unmask(wl); if (ret < 0) { diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c index 020d764f9c13..e093a1c5a205 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.c +++ b/drivers/net/wireless/wl12xx/wl1251_event.c @@ -97,6 +97,35 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) return 0; } +/* + * Poll the mailbox event field until any of the bits in the mask is set or a + * timeout occurs (WL1251_EVENT_TIMEOUT in msecs) + */ +int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms) +{ + u32 events_vector, event; + unsigned long timeout; + + timeout = jiffies + msecs_to_jiffies(timeout_ms); + + do { + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + + msleep(1); + + /* read from both event fields */ + wl1251_mem_read(wl, wl->mbox_ptr[0], &events_vector, + sizeof(events_vector)); + event = events_vector & mask; + wl1251_mem_read(wl, wl->mbox_ptr[1], &events_vector, + sizeof(events_vector)); + event |= events_vector & mask; + } while (!event); + + return 0; +} + int wl1251_event_unmask(struct wl1251 *wl) { int ret; diff --git a/drivers/net/wireless/wl12xx/wl1251_event.h b/drivers/net/wireless/wl12xx/wl1251_event.h index f48a2b66bc5a..ec456474a842 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.h +++ b/drivers/net/wireless/wl12xx/wl1251_event.h @@ -117,5 +117,6 @@ struct event_mailbox { int wl1251_event_unmask(struct wl1251 *wl); void wl1251_event_mbox_config(struct wl1251 *wl); int wl1251_event_handle(struct wl1251 *wl, u8 mbox); +int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms); #endif diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 51474b697c1a..c81e95b45c14 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -339,11 +339,9 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel, if (ret < 0) goto out; - /* - * FIXME: we should wait for JOIN_EVENT_COMPLETE_ID but to simplify - * locking we just sleep instead, for now - */ - msleep(10); + ret = wl1251_event_wait(wl, JOIN_EVENT_COMPLETE_ID, 100); + if (ret < 0) + wl1251_warning("join timeout"); out: return ret; -- cgit v1.2.3-59-g8ed1b From 633dd1ea683d907af944bcd9814092efe9869b05 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 18 Aug 2010 15:01:23 +0200 Subject: mac80211: fix docbook Fix a small problem in the documentation for ieee80211_request_smps, and a now erroneous inclusion of enum ieee80211_key_alg, which no longer exists after the change to ciphers. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/DocBook/80211.tmpl | 1 - include/net/mac80211.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 6f88e184d2e7..52310ac892ea 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -248,7 +248,6 @@ MISSING !Finclude/net/mac80211.h set_key_cmd !Finclude/net/mac80211.h ieee80211_key_conf -!Finclude/net/mac80211.h ieee80211_key_alg !Finclude/net/mac80211.h ieee80211_key_flags diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 914c747ac3a0..2a1811366076 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2537,7 +2537,7 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success); /** * ieee80211_request_smps - request SM PS transition * @vif: &struct ieee80211_vif pointer from the add_interface callback. - * @mode: new SM PS mode + * @smps_mode: new SM PS mode * * This allows the driver to request an SM PS transition in managed * mode. This is useful when the driver has more information than -- cgit v1.2.3-59-g8ed1b From 2a5fb7b088f8418958775774dda9427d6c73c522 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 18 Aug 2010 17:44:36 +0200 Subject: nl80211: some documentation fixes The nl80211 documentation is currently never generated, so problems have accumulated. Fix most of the trivial ones. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 57 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 8af1e66c3cf9..ec1690da7845 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -347,6 +347,8 @@ * four bytes for vendor frames including the OUI. The registration * cannot be dropped, but is removed automatically when the netlink * socket is closed. Multiple registrations can be made. + * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for + * backward compatibility * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This * command is used both as a request to transmit a management frame and * as an event indicating reception of a frame that was not processed in @@ -359,11 +361,14 @@ * operational channel). When called, this operation returns a cookie * (%NL80211_ATTR_COOKIE) that will be included with the TX status event * pertaining to the TX request. + * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility. * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies * the TX command and %NL80211_ATTR_FRAME includes the contents of the * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged * the frame. + * @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for + * backward compatibility. * @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command * is used to configure connection quality monitoring notification trigger * levels. @@ -1029,11 +1034,14 @@ enum nl80211_iftype { * Station flags. When a station is added to an AP interface, it is * assumed to be already associated (and hence authenticated.) * + * @__NL80211_STA_FLAG_INVALID: attribute number 0 is reserved * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames * with short barker preamble * @NL80211_STA_FLAG_WME: station is WME/QoS capable * @NL80211_STA_FLAG_MFP: station uses management frame protection + * @NL80211_STA_FLAG_MAX: highest station flag number currently defined + * @__NL80211_STA_FLAG_AFTER_LAST: internal use */ enum nl80211_sta_flags { __NL80211_STA_FLAG_INVALID, @@ -1146,14 +1154,17 @@ enum nl80211_mpath_flags { * information about a mesh path. * * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved - * @NL80211_ATTR_MPATH_FRAME_QLEN: number of queued frames for this destination - * @NL80211_ATTR_MPATH_SN: destination sequence number - * @NL80211_ATTR_MPATH_METRIC: metric (cost) of this mesh path - * @NL80211_ATTR_MPATH_EXPTIME: expiration time for the path, in msec from now - * @NL80211_ATTR_MPATH_FLAGS: mesh path flags, enumerated in + * @NL80211_MPATH_INFO_FRAME_QLEN: number of queued frames for this destination + * @NL80211_MPATH_INFO_SN: destination sequence number + * @NL80211_MPATH_INFO_METRIC: metric (cost) of this mesh path + * @NL80211_MPATH_INFO_EXPTIME: expiration time for the path, in msec from now + * @NL80211_MPATH_INFO_FLAGS: mesh path flags, enumerated in * &enum nl80211_mpath_flags; - * @NL80211_ATTR_MPATH_DISCOVERY_TIMEOUT: total path discovery timeout, in msec - * @NL80211_ATTR_MPATH_DISCOVERY_RETRIES: mesh path discovery retries + * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec + * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries + * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number + * currently defind + * @__NL80211_MPATH_INFO_AFTER_LAST: internal use */ enum nl80211_mpath_info { __NL80211_MPATH_INFO_INVALID, @@ -1182,6 +1193,8 @@ enum nl80211_mpath_info { * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n + * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined + * @__NL80211_BAND_ATTR_AFTER_LAST: internal use */ enum nl80211_band_attr { __NL80211_BAND_ATTR_INVALID, @@ -1202,6 +1215,7 @@ enum nl80211_band_attr { /** * enum nl80211_frequency_attr - frequency attributes + * @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current * regulatory domain. @@ -1213,6 +1227,9 @@ enum nl80211_band_attr { * on this channel in current regulatory domain. * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm * (100 * dBm). + * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number + * currently defined + * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use */ enum nl80211_frequency_attr { __NL80211_FREQUENCY_ATTR_INVALID, @@ -1232,9 +1249,13 @@ enum nl80211_frequency_attr { /** * enum nl80211_bitrate_attr - bitrate attributes + * @__NL80211_BITRATE_ATTR_INVALID: attribute number 0 is reserved * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported * in 2.4 GHz band. + * @NL80211_BITRATE_ATTR_MAX: highest bitrate attribute number + * currently defined + * @__NL80211_BITRATE_ATTR_AFTER_LAST: internal use */ enum nl80211_bitrate_attr { __NL80211_BITRATE_ATTR_INVALID, @@ -1290,6 +1311,7 @@ enum nl80211_reg_type { /** * enum nl80211_reg_rule_attr - regulatory rule attributes + * @__NL80211_REG_RULE_ATTR_INVALID: attribute number 0 is reserved * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional * considerations for a given frequency range. These are the * &enum nl80211_reg_rule_flags. @@ -1306,6 +1328,9 @@ enum nl80211_reg_type { * If you don't have one then don't send this. * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for * a given frequency range. The value is in mBm (100 * dBm). + * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number + * currently defined + * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use */ enum nl80211_reg_rule_attr { __NL80211_REG_RULE_ATTR_INVALID, @@ -1357,6 +1382,9 @@ enum nl80211_reg_rule_flags { * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) + * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number + * currently defined + * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use */ enum nl80211_survey_info { __NL80211_SURVEY_INFO_INVALID, @@ -1521,6 +1549,7 @@ enum nl80211_channel_type { * enum nl80211_bss - netlink attributes for a BSS * * @__NL80211_BSS_INVALID: invalid + * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets) * @NL80211_BSS_FREQUENCY: frequency in MHz (u32) * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64) * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) @@ -1564,6 +1593,12 @@ enum nl80211_bss { /** * enum nl80211_bss_status - BSS "status" + * @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS. + * @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS. + * @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS. + * + * The BSS status is a BSS attribute in scan dumps, which + * indicates the status the interface has wrt. this BSS. */ enum nl80211_bss_status { NL80211_BSS_STATUS_AUTHENTICATED, @@ -1674,8 +1709,8 @@ enum nl80211_tx_rate_attributes { /** * enum nl80211_band - Frequency band - * @NL80211_BAND_2GHZ - 2.4 GHz ISM band - * @NL80211_BAND_5GHZ - around 5 GHz band (4.9 - 5.7 GHz) + * @NL80211_BAND_2GHZ: 2.4 GHz ISM band + * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) */ enum nl80211_band { NL80211_BAND_2GHZ, @@ -1713,9 +1748,9 @@ enum nl80211_attr_cqm { /** * enum nl80211_cqm_rssi_threshold_event - RSSI threshold event - * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW - The RSSI level is lower than the + * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: The RSSI level is lower than the * configured threshold - * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH - The RSSI is higher than the + * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the * configured threshold */ enum nl80211_cqm_rssi_threshold_event { -- cgit v1.2.3-59-g8ed1b From d99eeb87420a6da1f87064c7fa70bdf299699d90 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Wed, 18 Aug 2010 19:57:48 +0530 Subject: ath9k_common: Move bt_stomp to common for sharing with ath9k_htc. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 8 ------- drivers/net/wireless/ath/ath9k/common.c | 31 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/common.h | 10 +++++++++ drivers/net/wireless/ath/ath9k/gpio.c | 40 +++++---------------------------- 4 files changed, 47 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index def0cd308fdd..f0197a6046ab 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -437,14 +437,6 @@ void ath_ani_calibrate(unsigned long data); /* BTCOEX */ /**********/ -/* Defines the BT AR_BT_COEX_WGHT used */ -enum ath_stomp_type { - ATH_BTCOEX_NO_STOMP, - ATH_BTCOEX_STOMP_ALL, - ATH_BTCOEX_STOMP_LOW, - ATH_BTCOEX_STOMP_NONE -}; - struct ath_btcoex { bool hw_timer_enabled; spinlock_t btcoex_lock; diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 3100c87a4fcd..31cfe468e3fc 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -420,6 +420,37 @@ int ath9k_cmn_count_streams(unsigned int chainmask, int max) } EXPORT_SYMBOL(ath9k_cmn_count_streams); +/* + * Configures appropriate weight based on stomp type. + */ +void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, + enum ath_stomp_type stomp_type) +{ + struct ath_hw *ah = common->ah; + + switch (stomp_type) { + case ATH_BTCOEX_STOMP_ALL: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_ALL_WLAN_WGHT); + break; + case ATH_BTCOEX_STOMP_LOW: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_LOW_WLAN_WGHT); + break; + case ATH_BTCOEX_STOMP_NONE: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_NONE_WLAN_WGHT); + break; + default: + ath_print(common, ATH_DBG_BTCOEX, + "Invalid Stomptype\n"); + break; + } + + ath9k_hw_btcoex_enable(ah); +} +EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp); + static int __init ath9k_cmn_init(void) { return 0; diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 97809d39c73f..4aa4e7dbe4d2 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -52,6 +52,14 @@ #define ATH_EP_RND(x, mul) \ ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) +/* Defines the BT AR_BT_COEX_WGHT used */ +enum ath_stomp_type { + ATH_BTCOEX_NO_STOMP, + ATH_BTCOEX_STOMP_ALL, + ATH_BTCOEX_STOMP_LOW, + ATH_BTCOEX_STOMP_NONE +}; + int ath9k_cmn_padpos(__le16 frame_control); int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, @@ -65,3 +73,5 @@ int ath9k_cmn_key_config(struct ath_common *common, void ath9k_cmn_key_delete(struct ath_common *common, struct ieee80211_key_conf *key); int ath9k_cmn_count_streams(unsigned int chainmask, int max); +void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, + enum ath_stomp_type stomp_type); diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 3a8ee999da5d..4a9a68bba324 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -251,36 +251,6 @@ static void ath_detect_bt_priority(struct ath_softc *sc) } } -/* - * Configures appropriate weight based on stomp type. - */ -static void ath9k_btcoex_bt_stomp(struct ath_softc *sc, - enum ath_stomp_type stomp_type) -{ - struct ath_hw *ah = sc->sc_ah; - - switch (stomp_type) { - case ATH_BTCOEX_STOMP_ALL: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_ALL_WLAN_WGHT); - break; - case ATH_BTCOEX_STOMP_LOW: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT); - break; - case ATH_BTCOEX_STOMP_NONE: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_NONE_WLAN_WGHT); - break; - default: - ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, - "Invalid Stomptype\n"); - break; - } - - ath9k_hw_btcoex_enable(ah); -} - static void ath9k_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer, u32 timer_next, @@ -319,6 +289,7 @@ static void ath_btcoex_period_timer(unsigned long data) struct ath_softc *sc = (struct ath_softc *) data; struct ath_hw *ah = sc->sc_ah; struct ath_btcoex *btcoex = &sc->btcoex; + struct ath_common *common = ath9k_hw_common(ah); u32 timer_period; bool is_btscan; @@ -328,7 +299,7 @@ static void ath_btcoex_period_timer(unsigned long data) spin_lock_bh(&btcoex->btcoex_lock); - ath9k_btcoex_bt_stomp(sc, is_btscan ? ATH_BTCOEX_STOMP_ALL : + ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : btcoex->bt_stomp_type); spin_unlock_bh(&btcoex->btcoex_lock); @@ -359,17 +330,18 @@ static void ath_btcoex_no_stomp_timer(void *arg) struct ath_softc *sc = (struct ath_softc *)arg; struct ath_hw *ah = sc->sc_ah; struct ath_btcoex *btcoex = &sc->btcoex; + struct ath_common *common = ath9k_hw_common(ah); bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; - ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + ath_print(common, ATH_DBG_BTCOEX, "no stomp timer running\n"); spin_lock_bh(&btcoex->btcoex_lock); if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) - ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); + ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) - ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); + ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); spin_unlock_bh(&btcoex->btcoex_lock); } -- cgit v1.2.3-59-g8ed1b From 21cb987914cb5334af78378141efed77505ea987 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Wed, 18 Aug 2010 19:57:49 +0530 Subject: ath9k_htc: Add support for bluetooth coexistence. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 3 +- drivers/net/wireless/ath/ath9k/btcoex.c | 7 ++ drivers/net/wireless/ath/ath9k/hif_usb.c | 3 +- drivers/net/wireless/ath/ath9k/htc.h | 42 +++++--- drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 134 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 42 +++++++- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 12 +++ drivers/net/wireless/ath/ath9k/htc_hst.c | 4 +- drivers/net/wireless/ath/ath9k/htc_hst.h | 2 +- drivers/net/wireless/ath/ath9k/wmi.c | 2 + drivers/net/wireless/ath/ath9k/wmi.h | 1 + 11 files changed, 230 insertions(+), 22 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/htc_drv_gpio.c diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 973ae4f49f35..4555e9983903 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -46,6 +46,7 @@ ath9k_htc-y += htc_hst.o \ htc_drv_txrx.o \ htc_drv_main.o \ htc_drv_beacon.o \ - htc_drv_init.o + htc_drv_init.o \ + htc_drv_gpio.o obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index fb4ac15f3b93..6a92e57fddf0 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -168,6 +168,7 @@ EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) { struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; + u32 val; /* * Program coex mode and weight registers to @@ -177,6 +178,12 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2); + if (AR_SREV_9271(ah)) { + val = REG_READ(ah, 0x50040); + val &= 0xFFFFFEFF; + REG_WRITE(ah, 0x50040, val); + } + REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 17e7a9a367e7..495f18950ac9 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -920,7 +920,8 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, } ret = ath9k_htc_hw_init(hif_dev->htc_handle, - &hif_dev->udev->dev, hif_dev->device_id); + &hif_dev->udev->dev, hif_dev->device_id, + hif_dev->udev->product); if (ret) { ret = -EINVAL; goto err_htc_hw_init; diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 43b9e21bc562..75ecf6a30d25 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -316,17 +316,32 @@ struct htc_beacon_config { u8 dtim_count; }; -#define OP_INVALID BIT(0) -#define OP_SCANNING BIT(1) -#define OP_FULL_RESET BIT(2) -#define OP_LED_ASSOCIATED BIT(3) -#define OP_LED_ON BIT(4) -#define OP_PREAMBLE_SHORT BIT(5) -#define OP_PROTECT_ENABLE BIT(6) -#define OP_ASSOCIATED BIT(7) -#define OP_ENABLE_BEACON BIT(8) -#define OP_LED_DEINIT BIT(9) -#define OP_UNPLUGGED BIT(10) +struct ath_btcoex { + u32 bt_priority_cnt; + unsigned long bt_priority_time; + int bt_stomp_type; /* Types of BT stomping */ + u32 btcoex_no_stomp; + u32 btcoex_period; + u32 btscan_no_stomp; +}; + +void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv); +void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv); +void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv); + +#define OP_INVALID BIT(0) +#define OP_SCANNING BIT(1) +#define OP_FULL_RESET BIT(2) +#define OP_LED_ASSOCIATED BIT(3) +#define OP_LED_ON BIT(4) +#define OP_PREAMBLE_SHORT BIT(5) +#define OP_PROTECT_ENABLE BIT(6) +#define OP_ASSOCIATED BIT(7) +#define OP_ENABLE_BEACON BIT(8) +#define OP_LED_DEINIT BIT(9) +#define OP_UNPLUGGED BIT(10) +#define OP_BT_PRIORITY_DETECTED BIT(11) +#define OP_BT_SCAN BIT(12) struct ath9k_htc_priv { struct device *dev; @@ -391,6 +406,9 @@ struct ath9k_htc_priv { int cabq; int hwq_map[WME_NUM_AC]; + struct ath_btcoex btcoex; + struct delayed_work coex_period_work; + struct delayed_work duty_cycle_work; #ifdef CONFIG_ATH9K_HTC_DEBUGFS struct ath9k_debug debug; #endif @@ -443,7 +461,7 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv); void ath9k_deinit_leds(struct ath9k_htc_priv *priv); int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, - u16 devid); + u16 devid, char *product); void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); #ifdef CONFIG_PM int ath9k_htc_resume(struct htc_target *htc_handle); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c new file mode 100644 index 000000000000..50eec9a3b88c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -0,0 +1,134 @@ +#include "htc.h" + +/******************/ +/* BTCOEX */ +/******************/ + +/* + * Detects if there is any priority bt traffic + */ +static void ath_detect_bt_priority(struct ath9k_htc_priv *priv) +{ + struct ath_btcoex *btcoex = &priv->btcoex; + struct ath_hw *ah = priv->ah; + + if (ath9k_hw_gpio_get(ah, ah->btcoex_hw.btpriority_gpio)) + btcoex->bt_priority_cnt++; + + if (time_after(jiffies, btcoex->bt_priority_time + + msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { + priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); + /* Detect if colocated bt started scanning */ + if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { + ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "BT scan detected"); + priv->op_flags |= (OP_BT_SCAN | + OP_BT_PRIORITY_DETECTED); + } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { + ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "BT priority traffic detected"); + priv->op_flags |= OP_BT_PRIORITY_DETECTED; + } + + btcoex->bt_priority_cnt = 0; + btcoex->bt_priority_time = jiffies; + } +} + +/* + * This is the master bt coex work which runs for every + * 45ms, bt traffic will be given priority during 55% of this + * period while wlan gets remaining 45% + */ +static void ath_btcoex_period_work(struct work_struct *work) +{ + struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, + coex_period_work.work); + struct ath_btcoex *btcoex = &priv->btcoex; + struct ath_common *common = ath9k_hw_common(priv->ah); + u32 timer_period; + bool is_btscan; + int ret; + u8 cmd_rsp, aggr; + + ath_detect_bt_priority(priv); + + is_btscan = !!(priv->op_flags & OP_BT_SCAN); + + aggr = priv->op_flags & OP_BT_PRIORITY_DETECTED; + + WMI_CMD_BUF(WMI_AGGR_LIMIT_CMD, &aggr); + + ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : + btcoex->bt_stomp_type); + + timer_period = is_btscan ? btcoex->btscan_no_stomp : + btcoex->btcoex_no_stomp; + ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work, + msecs_to_jiffies(timer_period)); + ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, + msecs_to_jiffies(btcoex->btcoex_period)); +} + +/* + * Work to time slice between wlan and bt traffic and + * configure weight registers + */ +static void ath_btcoex_duty_cycle_work(struct work_struct *work) +{ + struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, + duty_cycle_work.work); + struct ath_hw *ah = priv->ah; + struct ath_btcoex *btcoex = &priv->btcoex; + struct ath_common *common = ath9k_hw_common(ah); + bool is_btscan = priv->op_flags & OP_BT_SCAN; + + ath_print(common, ATH_DBG_BTCOEX, + "time slice work for bt and wlan\n"); + + if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) + ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); + else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) + ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); +} + +void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv) +{ + struct ath_btcoex *btcoex = &priv->btcoex; + + btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD; + btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * + btcoex->btcoex_period / 100; + btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * + btcoex->btcoex_period / 100; + INIT_DELAYED_WORK(&priv->coex_period_work, ath_btcoex_period_work); + INIT_DELAYED_WORK(&priv->duty_cycle_work, ath_btcoex_duty_cycle_work); +} + +/* + * (Re)start btcoex work + */ + +void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv) +{ + struct ath_btcoex *btcoex = &priv->btcoex; + struct ath_hw *ah = priv->ah; + + ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "Starting btcoex work"); + + btcoex->bt_priority_cnt = 0; + btcoex->bt_priority_time = jiffies; + priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); + ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0); +} + + +/* + * Cancel btcoex and bt duty cycle work. + */ +void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv) +{ + cancel_delayed_work_sync(&priv->coex_period_work); + cancel_delayed_work_sync(&priv->duty_cycle_work); +} diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 2d4279191d7a..695e2b088d10 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -41,6 +41,8 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); .max_power = 20, \ } +#define ATH_HTC_BTCOEX_PRODUCT_ID "wb193" + static struct ieee80211_channel ath9k_2ghz_channels[] = { CHAN2G(2412, 0), /* Channel 1 */ CHAN2G(2417, 1), /* Channel 2 */ @@ -605,7 +607,31 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) priv->ah->opmode = NL80211_IFTYPE_STATION; } -static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) +static void ath9k_init_btcoex(struct ath9k_htc_priv *priv) +{ + int qnum; + + switch (priv->ah->btcoex_hw.scheme) { + case ATH_BTCOEX_CFG_NONE: + break; + case ATH_BTCOEX_CFG_3WIRE: + priv->ah->btcoex_hw.btactive_gpio = 7; + priv->ah->btcoex_hw.btpriority_gpio = 6; + priv->ah->btcoex_hw.wlanactive_gpio = 8; + priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; + ath9k_hw_btcoex_init_3wire(priv->ah); + ath_htc_init_btcoex_work(priv); + qnum = priv->hwq_map[WME_AC_BE]; + ath9k_hw_init_btcoex_hw(priv->ah, qnum); + break; + default: + WARN_ON(1); + break; + } +} + +static int ath9k_init_priv(struct ath9k_htc_priv *priv, + u16 devid, char *product) { struct ath_hw *ah = NULL; struct ath_common *common; @@ -672,6 +698,11 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) ath9k_init_channels_rates(priv); ath9k_init_misc(priv); + if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) { + ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE; + ath9k_init_btcoex(priv); + } + return 0; err_queues: @@ -734,7 +765,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, SET_IEEE80211_PERM_ADDR(hw, common->macaddr); } -static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) +static int ath9k_init_device(struct ath9k_htc_priv *priv, + u16 devid, char *product) { struct ieee80211_hw *hw = priv->hw; struct ath_common *common; @@ -743,7 +775,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) struct ath_regulatory *reg; /* Bring up device */ - error = ath9k_init_priv(priv, devid); + error = ath9k_init_priv(priv, devid, product); if (error != 0) goto err_init; @@ -801,7 +833,7 @@ err_init: } int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, - u16 devid) + u16 devid, char *product) { struct ieee80211_hw *hw; struct ath9k_htc_priv *priv; @@ -835,7 +867,7 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, /* The device may have been unplugged earlier. */ priv->op_flags &= ~OP_UNPLUGGED; - ret = ath9k_init_device(priv, devid); + ret = ath9k_init_device(priv, devid, product); if (ret) goto err_init; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 4e345be62435..5e318cb662c6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1210,6 +1210,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) ieee80211_wake_queues(hw); + if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) { + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_LOW_WLAN_WGHT); + ath9k_hw_btcoex_enable(ah); + ath_htc_resume_btcoex_work(priv); + } mutex_unlock(&priv->mutex); return ret; @@ -1254,6 +1260,12 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) "Monitor interface removed\n"); } + if (ah->btcoex_hw.enabled) { + ath9k_hw_btcoex_disable(ah); + if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) + ath_htc_cancel_btcoex_work(priv); + } + ath9k_hw_phy_disable(ah); ath9k_hw_disable(ah); ath9k_hw_configpcipowersave(ah, 1, 1); diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 705c0f342e1c..861ec9269309 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -462,9 +462,9 @@ void ath9k_htc_hw_free(struct htc_target *htc) } int ath9k_htc_hw_init(struct htc_target *target, - struct device *dev, u16 devid) + struct device *dev, u16 devid, char *product) { - if (ath9k_htc_probe_device(target, dev, devid)) { + if (ath9k_htc_probe_device(target, dev, devid, product)) { printk(KERN_ERR "Failed to initialize the device\n"); return -ENODEV; } diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index faba6790328b..07b6509d5896 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -239,7 +239,7 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle, struct device *dev); void ath9k_htc_hw_free(struct htc_target *htc); int ath9k_htc_hw_init(struct htc_target *target, - struct device *dev, u16 devid); + struct device *dev, u16 devid, char *product); void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); #endif /* HTC_HST_H */ diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 6260faa658a2..45fe9cac7971 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -85,6 +85,8 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_TGT_DETACH_CMDID"; case WMI_TGT_TXQ_ENABLE_CMDID: return "WMI_TGT_TXQ_ENABLE_CMDID"; + case WMI_AGGR_LIMIT_CMD: + return "WMI_AGGR_LIMIT_CMD"; } return "Bogus"; diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 765db5faa2d3..a0bf857625df 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -71,6 +71,7 @@ enum wmi_cmd_id { WMI_TX_AGGR_ENABLE_CMDID, WMI_TGT_DETACH_CMDID, WMI_TGT_TXQ_ENABLE_CMDID, + WMI_AGGR_LIMIT_CMD = 0x0026, }; enum wmi_event_id { -- cgit v1.2.3-59-g8ed1b From 54c8067a4a0606f466faf0f30b16684b00060e70 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 18 Aug 2010 09:35:21 -0700 Subject: iwlagn: do not check for AP mode for WEP keys Even when we configure WEP keys in AP mode ones without a station pointer are default keys, so don't check for AP mode here. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 40b82d9f309e..5b967c014b41 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3450,7 +3450,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, */ if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) && - !sta && vif->type != NL80211_IFTYPE_AP) { + !sta) { if (cmd == SET_KEY) is_default_wep_key = !priv->key_mapping_key; else -- cgit v1.2.3-59-g8ed1b From 672ddeffeb2afad18fe1a2fc5aa14a07b4da1551 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 18 Aug 2010 09:35:22 -0700 Subject: iwlwifi: do not spuriously call ieee80211_scan_completed When a scan is aborted because the corresponding virtual interface is removed, we may still later attempt to tell mac80211 that the scan completed. This is obviously wrong, since we already told it that it was aborted, so don't do that. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-scan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index ac510840519c..8d7fa59364fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -508,6 +508,7 @@ static void iwl_bg_scan_completed(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, scan_completed); bool internal = false; + bool scan_completed = false; IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); @@ -518,7 +519,8 @@ static void iwl_bg_scan_completed(struct work_struct *work) priv->is_internal_short_scan = false; IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); internal = true; - } else { + } else if (priv->scan_request) { + scan_completed = true; priv->scan_request = NULL; priv->scan_vif = NULL; } @@ -549,7 +551,7 @@ static void iwl_bg_scan_completed(struct work_struct *work) * into driver again into functions that will attempt to take * mutex. */ - if (!internal) + if (scan_completed) ieee80211_scan_completed(priv->hw, false); } -- cgit v1.2.3-59-g8ed1b From d70e96932de55fb2c05b1c0af1dff178651a9b77 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 19 Aug 2010 16:11:27 +0200 Subject: cfg80211: add some documentation Add some documentation for cfg80211. I'm hoping some of the regulatory documentation will be filled by somebody more familiar with it, hint hint! :) Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/DocBook/80211.tmpl | 136 +++++++++++++++++++++++++++++++++++++-- include/net/cfg80211.h | 121 ++++++++++++++++++++++++++++++++-- 2 files changed, 246 insertions(+), 11 deletions(-) diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 52310ac892ea..b84c9282828f 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -65,18 +65,144 @@ +!Ainclude/net/cfg80211.h The cfg80211 subsystem - -MISSING - +!Pinclude/net/cfg80211.h Introduction - + + Device registration +!Pinclude/net/cfg80211.h Device registration !Finclude/net/cfg80211.h ieee80211_band - +!Finclude/net/cfg80211.h ieee80211_channel_flags +!Finclude/net/cfg80211.h ieee80211_channel +!Finclude/net/cfg80211.h ieee80211_rate_flags +!Finclude/net/cfg80211.h ieee80211_rate +!Finclude/net/cfg80211.h ieee80211_sta_ht_cap +!Finclude/net/cfg80211.h ieee80211_supported_band +!Finclude/net/cfg80211.h cfg80211_signal_type +!Finclude/net/cfg80211.h wiphy_params_flags +!Finclude/net/cfg80211.h wiphy_flags +!Finclude/net/cfg80211.h wiphy +!Finclude/net/cfg80211.h wireless_dev +!Finclude/net/cfg80211.h wiphy_new +!Finclude/net/cfg80211.h wiphy_register +!Finclude/net/cfg80211.h wiphy_unregister +!Finclude/net/cfg80211.h wiphy_free + +!Finclude/net/cfg80211.h wiphy_name +!Finclude/net/cfg80211.h wiphy_dev +!Finclude/net/cfg80211.h wiphy_priv +!Finclude/net/cfg80211.h priv_to_wiphy +!Finclude/net/cfg80211.h set_wiphy_dev +!Finclude/net/cfg80211.h wdev_priv + + + Actions and configuration +!Pinclude/net/cfg80211.h Actions and configuration +!Finclude/net/cfg80211.h cfg80211_ops +!Finclude/net/cfg80211.h vif_params +!Finclude/net/cfg80211.h key_params +!Finclude/net/cfg80211.h survey_info_flags +!Finclude/net/cfg80211.h survey_info +!Finclude/net/cfg80211.h beacon_parameters +!Finclude/net/cfg80211.h plink_actions +!Finclude/net/cfg80211.h station_parameters +!Finclude/net/cfg80211.h station_info_flags +!Finclude/net/cfg80211.h rate_info_flags +!Finclude/net/cfg80211.h rate_info +!Finclude/net/cfg80211.h station_info +!Finclude/net/cfg80211.h monitor_flags +!Finclude/net/cfg80211.h mpath_info_flags +!Finclude/net/cfg80211.h mpath_info +!Finclude/net/cfg80211.h bss_parameters +!Finclude/net/cfg80211.h ieee80211_txq_params +!Finclude/net/cfg80211.h cfg80211_crypto_settings +!Finclude/net/cfg80211.h cfg80211_auth_request +!Finclude/net/cfg80211.h cfg80211_assoc_request +!Finclude/net/cfg80211.h cfg80211_deauth_request +!Finclude/net/cfg80211.h cfg80211_disassoc_request +!Finclude/net/cfg80211.h cfg80211_ibss_params +!Finclude/net/cfg80211.h cfg80211_connect_params +!Finclude/net/cfg80211.h cfg80211_pmksa +!Finclude/net/cfg80211.h cfg80211_send_rx_auth +!Finclude/net/cfg80211.h cfg80211_send_auth_timeout +!Finclude/net/cfg80211.h __cfg80211_auth_canceled +!Finclude/net/cfg80211.h cfg80211_send_rx_assoc +!Finclude/net/cfg80211.h cfg80211_send_assoc_timeout +!Finclude/net/cfg80211.h cfg80211_send_deauth +!Finclude/net/cfg80211.h __cfg80211_send_deauth +!Finclude/net/cfg80211.h cfg80211_send_disassoc +!Finclude/net/cfg80211.h __cfg80211_send_disassoc +!Finclude/net/cfg80211.h cfg80211_ibss_joined +!Finclude/net/cfg80211.h cfg80211_connect_result +!Finclude/net/cfg80211.h cfg80211_roamed +!Finclude/net/cfg80211.h cfg80211_disconnected +!Finclude/net/cfg80211.h cfg80211_ready_on_channel +!Finclude/net/cfg80211.h cfg80211_remain_on_channel_expired +!Finclude/net/cfg80211.h cfg80211_new_sta +!Finclude/net/cfg80211.h cfg80211_rx_mgmt +!Finclude/net/cfg80211.h cfg80211_mgmt_tx_status +!Finclude/net/cfg80211.h cfg80211_cqm_rssi_notify +!Finclude/net/cfg80211.h cfg80211_michael_mic_failure + + + Scanning and BSS list handling +!Pinclude/net/cfg80211.h Scanning and BSS list handling +!Finclude/net/cfg80211.h cfg80211_ssid +!Finclude/net/cfg80211.h cfg80211_scan_request +!Finclude/net/cfg80211.h cfg80211_scan_done +!Finclude/net/cfg80211.h cfg80211_bss +!Finclude/net/cfg80211.h cfg80211_inform_bss_frame +!Finclude/net/cfg80211.h cfg80211_inform_bss +!Finclude/net/cfg80211.h cfg80211_unlink_bss +!Finclude/net/cfg80211.h cfg80211_find_ie +!Finclude/net/cfg80211.h ieee80211_bss_get_ie + + + Utility functions +!Pinclude/net/cfg80211.h Utility functions +!Finclude/net/cfg80211.h ieee80211_channel_to_frequency +!Finclude/net/cfg80211.h ieee80211_frequency_to_channel +!Finclude/net/cfg80211.h ieee80211_get_channel +!Finclude/net/cfg80211.h ieee80211_get_response_rate +!Finclude/net/cfg80211.h ieee80211_hdrlen +!Finclude/net/cfg80211.h ieee80211_get_hdrlen_from_skb +!Finclude/net/cfg80211.h ieee80211_radiotap_iterator + + + Data path helpers +!Pinclude/net/cfg80211.h Data path helpers +!Finclude/net/cfg80211.h ieee80211_data_to_8023 +!Finclude/net/cfg80211.h ieee80211_data_from_8023 +!Finclude/net/cfg80211.h ieee80211_amsdu_to_8023s +!Finclude/net/cfg80211.h cfg80211_classify8021d + + + Regulatory enforcement infrastructure +!Pinclude/net/cfg80211.h Regulatory enforcement infrastructure +!Finclude/net/cfg80211.h regulatory_hint +!Finclude/net/cfg80211.h wiphy_apply_custom_regulatory +!Finclude/net/cfg80211.h freq_reg_info + + + RFkill integration +!Pinclude/net/cfg80211.h RFkill integration +!Finclude/net/cfg80211.h wiphy_rfkill_set_hw_state +!Finclude/net/cfg80211.h wiphy_rfkill_start_polling +!Finclude/net/cfg80211.h wiphy_rfkill_stop_polling + + + Test mode +!Pinclude/net/cfg80211.h Test mode +!Finclude/net/cfg80211.h cfg80211_testmode_alloc_reply_skb +!Finclude/net/cfg80211.h cfg80211_testmode_reply +!Finclude/net/cfg80211.h cfg80211_testmode_alloc_event_skb +!Finclude/net/cfg80211.h cfg80211_testmode_event + diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6a98b1b3bfde..f2740537b5d6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -25,6 +25,43 @@ #include +/** + * DOC: Introduction + * + * cfg80211 is the configuration API for 802.11 devices in Linux. It bridges + * userspace and drivers, and offers some utility functionality associated + * with 802.11. cfg80211 must, directly or indirectly via mac80211, be used + * by all modern wireless drivers in Linux, so that they offer a consistent + * API through nl80211. For backward compatibility, cfg80211 also offers + * wireless extensions to userspace, but hides them from drivers completely. + * + * Additionally, cfg80211 contains code to help enforce regulatory spectrum + * use restrictions. + */ + + +/** + * DOC: Device registration + * + * In order for a driver to use cfg80211, it must register the hardware device + * with cfg80211. This happens through a number of hardware capability structs + * described below. + * + * The fundamental structure for each device is the 'wiphy', of which each + * instance describes a physical wireless device connected to the system. Each + * such wiphy can have zero, one, or many virtual interfaces associated with + * it, which need to be identified as such by pointing the network interface's + * @ieee80211_ptr pointer to a &struct wireless_dev which further describes + * the wireless part of the interface, normally this struct is embedded in the + * network interface's private data area. Drivers can optionally allow creating + * or destroying virtual interfaces on the fly, but without at least one or the + * ability to create some the wireless device isn't useful. + * + * Each wiphy structure contains device capability information, and also has + * a pointer to the various operations the driver offers. The definitions and + * structures here describe these capabilities in detail. + */ + /* * wireless hardware capability structures */ @@ -204,6 +241,21 @@ struct ieee80211_supported_band { * Wireless hardware/device configuration structures and methods */ +/** + * DOC: Actions and configuration + * + * Each wireless device and each virtual interface offer a set of configuration + * operations and other actions that are invoked by userspace. Each of these + * actions is described in the operations structure, and the parameters these + * operations use are described separately. + * + * Additionally, some operations are asynchronous and expect to get status + * information via some functions that drivers need to call. + * + * Scanning and BSS list handling with its associated functionality is described + * in a separate chapter. + */ + /** * struct vif_params - describes virtual interface parameters * @mesh_id: mesh ID to use @@ -570,8 +622,28 @@ struct ieee80211_txq_params { /* from net/wireless.h */ struct wiphy; -/* from net/ieee80211.h */ -struct ieee80211_channel; +/** + * DOC: Scanning and BSS list handling + * + * The scanning process itself is fairly simple, but cfg80211 offers quite + * a bit of helper functionality. To start a scan, the scan operation will + * be invoked with a scan definition. This scan definition contains the + * channels to scan, and the SSIDs to send probe requests for (including the + * wildcard, if desired). A passive scan is indicated by having no SSIDs to + * probe. Additionally, a scan request may contain extra information elements + * that should be added to the probe request. The IEs are guaranteed to be + * well-formed, and will not exceed the maximum length the driver advertised + * in the wiphy structure. + * + * When scanning finds a BSS, cfg80211 needs to be notified of that, because + * it is responsible for maintaining the BSS list; the driver should not + * maintain a list itself. For this notification, various functions exist. + * + * Since drivers do not maintain a BSS list, there are also a number of + * functions to search for a BSS and obtain information about it from the + * BSS structure cfg80211 maintains. The BSS list is also made available + * to userspace. + */ /** * struct cfg80211_ssid - SSID description @@ -1574,8 +1646,10 @@ static inline void *wdev_priv(struct wireless_dev *wdev) return wiphy_priv(wdev->wiphy); } -/* - * Utility functions +/** + * DOC: Utility functions + * + * cfg80211 offers a number of utility functions that can be useful. */ /** @@ -1728,6 +1802,14 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); */ unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); +/** + * DOC: Data path helpers + * + * In addition to generic utilities, cfg80211 also offers + * functions that help implement the data path for devices + * that do not do the 802.11/802.3 conversion on the device. + */ + /** * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3 * @skb: the 802.11 data frame @@ -1788,8 +1870,10 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb); */ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len); -/* - * Regulatory helper functions for wiphys +/** + * DOC: Regulatory enforcement infrastructure + * + * TODO */ /** @@ -2191,6 +2275,20 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, */ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp); +/** + * DOC: RFkill integration + * + * RFkill integration in cfg80211 is almost invisible to drivers, + * as cfg80211 automatically registers an rfkill instance for each + * wireless device it knows about. Soft kill is also translated + * into disconnecting and turning all interfaces off, drivers are + * expected to turn off the device when all interfaces are down. + * + * However, devices may have a hard RFkill line, in which case they + * also need to interact with the rfkill subsystem, via cfg80211. + * They can do this with a few helper functions documented here. + */ + /** * wiphy_rfkill_set_hw_state - notify cfg80211 about hw block state * @wiphy: the wiphy @@ -2211,6 +2309,17 @@ void wiphy_rfkill_start_polling(struct wiphy *wiphy); void wiphy_rfkill_stop_polling(struct wiphy *wiphy); #ifdef CONFIG_NL80211_TESTMODE +/** + * DOC: Test mode + * + * Test mode is a set of utility functions to allow drivers to + * interact with driver-specific tools to aid, for instance, + * factory programming. + * + * This chapter describes how drivers interact with it, for more + * information see the nl80211 book's chapter on it. + */ + /** * cfg80211_testmode_alloc_reply_skb - allocate testmode reply * @wiphy: the wiphy -- cgit v1.2.3-59-g8ed1b From ec550d246e38e1b4ea8604b5c71ccb72e38f3290 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 24 Aug 2010 14:45:09 -0700 Subject: net: ip_append_data() optim Compiler is not smart enough to avoid a conditional branch. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 6d2753c7ffdd..e42762023c27 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -837,10 +837,9 @@ int ip_append_data(struct sock *sk, inet->cork.length = 0; sk->sk_sndmsg_page = NULL; sk->sk_sndmsg_off = 0; - if ((exthdrlen = rt->dst.header_len) != 0) { - length += exthdrlen; - transhdrlen += exthdrlen; - } + exthdrlen = rt->dst.header_len; + length += exthdrlen; + transhdrlen += exthdrlen; } else { rt = (struct rtable *)inet->cork.dst; if (inet->cork.flags & IPCORK_OPT) -- cgit v1.2.3-59-g8ed1b From 5a46790ca4c40fdb6ed5336d7d6b593c96326b31 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 24 Aug 2010 14:46:53 -0700 Subject: include/linux/if_ether.h: Remove unused #define MAC_FMT Last use was removed, so remove the #define. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/linux/if_ether.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index bed7a4682b90..f9c3df03db0f 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -137,8 +137,6 @@ extern struct ctl_table ether_table[]; extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); -#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" - #endif #endif /* _LINUX_IF_ETHER_H */ -- cgit v1.2.3-59-g8ed1b From c2e3143e3c46ede22336316b3ff4746727c0d93a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 24 Aug 2010 14:48:10 -0700 Subject: tc: add meta match on receive hash Trivial extension to existing meta data match rules to allow matching on skb receive hash value. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/tc_ematch/tc_em_meta.h | 1 + net/sched/em_meta.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h index 0864206ec1a3..7138962664f8 100644 --- a/include/linux/tc_ematch/tc_em_meta.h +++ b/include/linux/tc_ematch/tc_em_meta.h @@ -79,6 +79,7 @@ enum { TCF_META_ID_SK_SENDMSG_OFF, TCF_META_ID_SK_WRITE_PENDING, TCF_META_ID_VLAN_TAG, + TCF_META_ID_RXHASH, __TCF_META_ID_MAX }; #define TCF_META_ID_MAX (__TCF_META_ID_MAX - 1) diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 3bcac8aa333c..34da5e29ea1a 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -223,6 +223,11 @@ META_COLLECTOR(int_maclen) dst->value = skb->mac_len; } +META_COLLECTOR(int_rxhash) +{ + dst->value = skb_get_rxhash(skb); +} + /************************************************************************** * Netfilter **************************************************************************/ @@ -541,6 +546,7 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = { [META_ID(SK_SENDMSG_OFF)] = META_FUNC(int_sk_sendmsg_off), [META_ID(SK_WRITE_PENDING)] = META_FUNC(int_sk_write_pend), [META_ID(VLAN_TAG)] = META_FUNC(int_vlan_tag), + [META_ID(RXHASH)] = META_FUNC(int_rxhash), } }; -- cgit v1.2.3-59-g8ed1b From 69351a2933428515b31fe54100f90a669cbbd384 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:45:05 +0000 Subject: mlx4_en: Fixed incorrect unmapping on RX flow. When allocating new fragments to replace the ones that would be passed to the stack, The fragments that should be replaced, are the ones that were already used. Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 2add04025fd0..4335c58160d7 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -459,7 +459,7 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv, goto fail; /* Unmap buffer */ - pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size, + pci_unmap_single(mdev->pdev, dma, skb_frags_rx[nr].size, PCI_DMA_FROMDEVICE); } /* Adjust size of last fragment to match actual length */ -- cgit v1.2.3-59-g8ed1b From 00d7d7bc6e886ef48af6ed766eb12b8cec241d35 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:45:20 +0000 Subject: mlx4_en: Setting actual RX ring size When configuring HW resources, the RX ring size that is passed should be the actual size that depends on number of buffers that we succeeded to allocate. The mask for ring size should also be configured accordingly Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_rx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 4335c58160d7..7a5123c4a366 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -251,7 +251,6 @@ reduce_rings: ring->prod--; mlx4_en_free_rx_desc(priv, ring, ring->actual_size); } - ring->size_mask = ring->actual_size - 1; } return 0; @@ -389,6 +388,7 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv) for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) { ring = &priv->rx_ring[ring_ind]; + ring->size_mask = ring->actual_size - 1; mlx4_en_update_rx_prod_db(ring); } @@ -816,7 +816,7 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn, qp->event = mlx4_en_sqp_event; memset(context, 0, sizeof *context); - mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 0, 0, + mlx4_en_fill_qp_context(priv, ring->actual_size, ring->stride, 0, 0, qpn, ring->cqn, context); context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma); -- cgit v1.2.3-59-g8ed1b From 8bf2e58f8b7a14244bf182ad0a3ba0457ad70c62 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:45:30 +0000 Subject: mlx4_en: Setting dev->perm_addr field Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_netdev.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index d00bfe250b05..4d6dac7617f7 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -1023,9 +1023,10 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, /* Set defualt MAC */ dev->addr_len = ETH_ALEN; - for (i = 0; i < ETH_ALEN; i++) - dev->dev_addr[ETH_ALEN - 1 - i] = - (u8) (priv->mac >> (8 * i)); + for (i = 0; i < ETH_ALEN; i++) { + dev->dev_addr[ETH_ALEN - 1 - i] = (u8) (priv->mac >> (8 * i)); + dev->perm_addr[ETH_ALEN - 1 - i] = (u8) (priv->mac >> (8 * i)); + } /* * Set driver features -- cgit v1.2.3-59-g8ed1b From 7c2873809dd1a2d5e46be3f0ff2071fcdc3cf0fd Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:45:45 +0000 Subject: mlx4_en: performing CLOSE_PORT at the end of tear-down process All port's resources should be closed before we give the CLOSE_PORT command to the firmware. Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_netdev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 4d6dac7617f7..985e6f83b31a 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -704,9 +704,8 @@ void mlx4_en_stop_port(struct net_device *dev) netif_tx_stop_all_queues(dev); netif_tx_unlock_bh(dev); - /* close port*/ + /* Set port as not active */ priv->port_up = false; - mlx4_CLOSE_PORT(mdev->dev, priv->port); /* Unregister Mac address for the port */ mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index); @@ -731,6 +730,9 @@ void mlx4_en_stop_port(struct net_device *dev) msleep(1); mlx4_en_deactivate_cq(priv, &priv->rx_cq[i]); } + + /* close port*/ + mlx4_CLOSE_PORT(mdev->dev, priv->port); } static void mlx4_en_restart(struct work_struct *work) -- cgit v1.2.3-59-g8ed1b From a0b4e6e09c79df9efdb9872f30eb4cdb291c6c78 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:45:54 +0000 Subject: mlx4_en: Fixed MAX_TX_RINGS definition Defined as sum of default number of TX rings and number of rings used for priority flow control mode. Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/mlx4_en.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 9d0932348b96..554014bd8af5 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -61,7 +61,6 @@ #define MLX4_EN_PAGE_SHIFT 12 #define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT) -#define MAX_TX_RINGS 16 #define MAX_RX_RINGS 16 #define TXBB_SIZE 64 #define HEADROOM (2048 / TXBB_SIZE + 1) @@ -107,6 +106,7 @@ enum { #define MLX4_EN_SMALL_PKT_SIZE 64 #define MLX4_EN_NUM_TX_RINGS 8 #define MLX4_EN_NUM_PPP_RINGS 8 +#define MAX_TX_RINGS (MLX4_EN_NUM_TX_RINGS + MLX4_EN_NUM_PPP_RINGS) #define MLX4_EN_DEF_TX_RING_SIZE 512 #define MLX4_EN_DEF_RX_RING_SIZE 1024 -- cgit v1.2.3-59-g8ed1b From e5cc44b2eb2b8192c9623eb877936063ba8556f3 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:46:01 +0000 Subject: mlx4_en: Reporting link state with KERN_INFO Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_netdev.c | 4 ++-- drivers/net/mlx4/mlx4_en.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 985e6f83b31a..34cfa3cfbdae 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -528,10 +528,10 @@ static void mlx4_en_linkstate(struct work_struct *work) * report to system log */ if (priv->last_link_state != linkstate) { if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) { - en_dbg(LINK, priv, "Link Down\n"); + en_info(priv, "Link Down\n"); netif_carrier_off(priv->dev); } else { - en_dbg(LINK, priv, "Link Up\n"); + en_info(priv, "Link Up\n"); netif_carrier_on(priv->dev); } } diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 554014bd8af5..edf6523702c0 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -554,6 +554,8 @@ do { \ en_print(KERN_WARNING, priv, format, ##arg) #define en_err(priv, format, arg...) \ en_print(KERN_ERR, priv, format, ##arg) +#define en_info(priv, format, arg...) \ + en_print(KERN_INFO, priv, format, ## arg) #define mlx4_err(mdev, format, arg...) \ pr_err("%s %s: " format, DRV_NAME, \ -- cgit v1.2.3-59-g8ed1b From 3005ad40b95168aad530f1179cff47411b3ea8da Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:46:07 +0000 Subject: mlx4_en: Validate port up prior to transmitting We might try to use resources which were not activated. Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_tx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c index 580968f304eb..3deabd1d0357 100644 --- a/drivers/net/mlx4/en_tx.c +++ b/drivers/net/mlx4/en_tx.c @@ -612,6 +612,9 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) int lso_header_size; void *fragptr; + if (!priv->port_up) + goto tx_drop; + real_size = get_real_size(skb, dev, &lso_header_size); if (unlikely(!real_size)) goto tx_drop; -- cgit v1.2.3-59-g8ed1b From e7c1c2c46201e46f8ce817196507d2ffd3dafd8e Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:46:18 +0000 Subject: mlx4_en: Added self diagnostics test implementation The selftest includes 5 features: 1. Interrupt test: Executing commands and receiving command completion on all our interrupt vectors. 2. Link test: Verifying we are connected to valid link partner. 3. Speed test: Check that we negotiated link speed correctly. 4. Registers test: Activate HW health check command. 5. Loopback test: Send a packet on loopback interface and catch it on RX side. Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/Makefile | 2 +- drivers/net/mlx4/en_ethtool.c | 79 ++++++++++++------ drivers/net/mlx4/en_netdev.c | 2 +- drivers/net/mlx4/en_port.c | 32 ++++++++ drivers/net/mlx4/en_port.h | 14 ++++ drivers/net/mlx4/en_rx.c | 20 +++++ drivers/net/mlx4/en_selftest.c | 179 +++++++++++++++++++++++++++++++++++++++++ drivers/net/mlx4/en_tx.c | 16 ++++ drivers/net/mlx4/eq.c | 44 ++++++++++ drivers/net/mlx4/fw.c | 3 + drivers/net/mlx4/fw.h | 1 + drivers/net/mlx4/main.c | 1 + drivers/net/mlx4/mlx4_en.h | 19 +++++ include/linux/mlx4/cmd.h | 1 + include/linux/mlx4/device.h | 2 + 15 files changed, 388 insertions(+), 27 deletions(-) create mode 100644 drivers/net/mlx4/en_selftest.c diff --git a/drivers/net/mlx4/Makefile b/drivers/net/mlx4/Makefile index 1fd068e1d930..d1aa45a15854 100644 --- a/drivers/net/mlx4/Makefile +++ b/drivers/net/mlx4/Makefile @@ -6,4 +6,4 @@ mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \ obj-$(CONFIG_MLX4_EN) += mlx4_en.o mlx4_en-y := en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \ - en_resources.o en_netdev.o + en_resources.o en_netdev.o en_selftest.o diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c index 398d54136967..f7d72d7a8704 100644 --- a/drivers/net/mlx4/en_ethtool.c +++ b/drivers/net/mlx4/en_ethtool.c @@ -125,6 +125,14 @@ static const char main_strings[][ETH_GSTRING_LEN] = { #define NUM_MAIN_STATS 21 #define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS) +static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= { + "Interupt Test", + "Link Test", + "Speed Test", + "Register Test", + "Loopback Test", +}; + static u32 mlx4_en_get_msglevel(struct net_device *dev) { return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable; @@ -146,10 +154,15 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset) { struct mlx4_en_priv *priv = netdev_priv(dev); - if (sset != ETH_SS_STATS) + switch (sset) { + case ETH_SS_STATS: + return NUM_ALL_STATS + + (priv->tx_ring_num + priv->rx_ring_num) * 2; + case ETH_SS_TEST: + return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.loopback_support) * 2; + default: return -EOPNOTSUPP; - - return NUM_ALL_STATS + (priv->tx_ring_num + priv->rx_ring_num) * 2; + } } static void mlx4_en_get_ethtool_stats(struct net_device *dev, @@ -181,6 +194,12 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev, } +static void mlx4_en_self_test(struct net_device *dev, + struct ethtool_test *etest, u64 *buf) +{ + mlx4_en_ex_selftest(dev, &etest->flags, buf); +} + static void mlx4_en_get_strings(struct net_device *dev, uint32_t stringset, uint8_t *data) { @@ -188,30 +207,39 @@ static void mlx4_en_get_strings(struct net_device *dev, int index = 0; int i; - if (stringset != ETH_SS_STATS) - return; - - /* Add main counters */ - for (i = 0; i < NUM_MAIN_STATS; i++) - strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]); - for (i = 0; i < NUM_PORT_STATS; i++) - strcpy(data + (index++) * ETH_GSTRING_LEN, + switch (stringset) { + case ETH_SS_TEST: + for (i = 0; i < MLX4_EN_NUM_SELF_TEST - 2; i++) + strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]); + if (priv->mdev->dev->caps.loopback_support) + for (; i < MLX4_EN_NUM_SELF_TEST; i++) + strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]); + break; + + case ETH_SS_STATS: + /* Add main counters */ + for (i = 0; i < NUM_MAIN_STATS; i++) + strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]); + for (i = 0; i< NUM_PORT_STATS; i++) + strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i + NUM_MAIN_STATS]); - for (i = 0; i < priv->tx_ring_num; i++) { - sprintf(data + (index++) * ETH_GSTRING_LEN, - "tx%d_packets", i); - sprintf(data + (index++) * ETH_GSTRING_LEN, - "tx%d_bytes", i); - } - for (i = 0; i < priv->rx_ring_num; i++) { - sprintf(data + (index++) * ETH_GSTRING_LEN, - "rx%d_packets", i); - sprintf(data + (index++) * ETH_GSTRING_LEN, - "rx%d_bytes", i); - } - for (i = 0; i < NUM_PKT_STATS; i++) - strcpy(data + (index++) * ETH_GSTRING_LEN, + for (i = 0; i < priv->tx_ring_num; i++) { + sprintf(data + (index++) * ETH_GSTRING_LEN, + "tx%d_packets", i); + sprintf(data + (index++) * ETH_GSTRING_LEN, + "tx%d_bytes", i); + } + for (i = 0; i < priv->rx_ring_num; i++) { + sprintf(data + (index++) * ETH_GSTRING_LEN, + "rx%d_packets", i); + sprintf(data + (index++) * ETH_GSTRING_LEN, + "rx%d_bytes", i); + } + for (i = 0; i< NUM_PKT_STATS; i++) + strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]); + break; + } } static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) @@ -439,6 +467,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { .get_strings = mlx4_en_get_strings, .get_sset_count = mlx4_en_get_sset_count, .get_ethtool_stats = mlx4_en_get_ethtool_stats, + .self_test = mlx4_en_self_test, .get_wol = mlx4_en_get_wol, .get_msglevel = mlx4_en_get_msglevel, .set_msglevel = mlx4_en_set_msglevel, diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 34cfa3cfbdae..968e75b7acf4 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -109,7 +109,7 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) mutex_unlock(&mdev->state_lock); } -static u64 mlx4_en_mac_to_u64(u8 *addr) +u64 mlx4_en_mac_to_u64(u8 *addr) { u64 mac = 0; int i; diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c index a29abe845d2e..aa3ef2aee5bf 100644 --- a/drivers/net/mlx4/en_port.c +++ b/drivers/net/mlx4/en_port.c @@ -142,6 +142,38 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, return err; } +int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port) +{ + struct mlx4_en_query_port_context *qport_context; + struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]); + struct mlx4_en_port_state *state = &priv->port_state; + struct mlx4_cmd_mailbox *mailbox; + int err; + + mailbox = mlx4_alloc_cmd_mailbox(mdev->dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + memset(mailbox->buf, 0, sizeof(*qport_context)); + err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0, + MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B); + if (err) + goto out; + qport_context = mailbox->buf; + + /* This command is always accessed from Ethtool context + * already synchronized, no need in locking */ + state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK); + if ((qport_context->link_speed & MLX4_EN_SPEED_MASK) == + MLX4_EN_1G_SPEED) + state->link_speed = 1000; + else + state->link_speed = 10000; + state->transciver = qport_context->transceiver; + +out: + mlx4_free_cmd_mailbox(mdev->dev, mailbox); + return err; +} int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) { diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h index e6477f12beb5..f6511aa2b7df 100644 --- a/drivers/net/mlx4/en_port.h +++ b/drivers/net/mlx4/en_port.h @@ -84,6 +84,20 @@ enum { MLX4_MCAST_ENABLE = 2, }; +struct mlx4_en_query_port_context { + u8 link_up; +#define MLX4_EN_LINK_UP_MASK 0x80 + u8 reserved; + __be16 mtu; + u8 reserved2; + u8 link_speed; +#define MLX4_EN_SPEED_MASK 0x3 +#define MLX4_EN_1G_SPEED 0x2 + u16 reserved3[5]; + __be64 mac; + u8 transceiver; +}; + struct mlx4_en_stat_out_mbox { /* Received frames with a length of 64 octets */ diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 7a5123c4a366..f421a3d42723 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -541,6 +541,21 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, return skb; } +static void validate_loopback(struct mlx4_en_priv *priv, struct sk_buff *skb) +{ + int i; + int offset = ETH_HLEN; + + for (i = 0; i < MLX4_LOOPBACK_TEST_PAYLOAD; i++, offset++) { + if (*(skb->data + offset) != (unsigned char) (i & 0xff)) + goto out_loopback; + } + /* Loopback found */ + priv->loopback_ok = 1; + +out_loopback: + dev_kfree_skb_any(skb); +} int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget) { @@ -655,6 +670,11 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud goto next; } + if (unlikely(priv->validate_loopback)) { + validate_loopback(priv, skb); + goto next; + } + skb->ip_summed = ip_summed; skb->protocol = eth_type_trans(skb, dev); skb_record_rx_queue(skb, cq->ring); diff --git a/drivers/net/mlx4/en_selftest.c b/drivers/net/mlx4/en_selftest.c new file mode 100644 index 000000000000..43357d35616a --- /dev/null +++ b/drivers/net/mlx4/en_selftest.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2007 Mellanox Technologies. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include +#include +#include +#include +#include + +#include "mlx4_en.h" + + +static int mlx4_en_test_registers(struct mlx4_en_priv *priv) +{ + return mlx4_cmd(priv->mdev->dev, 0, 0, 0, MLX4_CMD_HW_HEALTH_CHECK, + MLX4_CMD_TIME_CLASS_A); +} + +static int mlx4_en_test_loopback_xmit(struct mlx4_en_priv *priv) +{ + struct sk_buff *skb; + struct ethhdr *ethh; + unsigned char *packet; + unsigned int packet_size = MLX4_LOOPBACK_TEST_PAYLOAD; + unsigned int i; + int err; + + + /* build the pkt before xmit */ + skb = netdev_alloc_skb(priv->dev, MLX4_LOOPBACK_TEST_PAYLOAD + ETH_HLEN + NET_IP_ALIGN); + if (!skb) { + en_err(priv, "-LOOPBACK_TEST_XMIT- failed to create skb for xmit\n"); + return -ENOMEM; + } + skb_reserve(skb, NET_IP_ALIGN); + + ethh = (struct ethhdr *)skb_put(skb, sizeof(struct ethhdr)); + packet = (unsigned char *)skb_put(skb, packet_size); + memcpy(ethh->h_dest, priv->dev->dev_addr, ETH_ALEN); + memset(ethh->h_source, 0, ETH_ALEN); + ethh->h_proto = htons(ETH_P_ARP); + skb_set_mac_header(skb, 0); + for (i = 0; i < packet_size; ++i) /* fill our packet */ + packet[i] = (unsigned char)(i & 0xff); + + /* xmit the pkt */ + err = mlx4_en_xmit(skb, priv->dev); + return err; +} + +static int mlx4_en_test_loopback(struct mlx4_en_priv *priv) +{ + u32 loopback_ok = 0; + int i; + + + priv->loopback_ok = 0; + priv->validate_loopback = 1; + + /* xmit */ + if (mlx4_en_test_loopback_xmit(priv)) { + en_err(priv, "Transmitting loopback packet failed\n"); + goto mlx4_en_test_loopback_exit; + } + + /* polling for result */ + for (i = 0; i < MLX4_EN_LOOPBACK_RETRIES; ++i) { + msleep(MLX4_EN_LOOPBACK_TIMEOUT); + if (priv->loopback_ok) { + loopback_ok = 1; + break; + } + } + if (!loopback_ok) + en_err(priv, "Loopback packet didn't arrive\n"); + +mlx4_en_test_loopback_exit: + + priv->validate_loopback = 0; + return (!loopback_ok); +} + + +static int mlx4_en_test_link(struct mlx4_en_priv *priv) +{ + if (mlx4_en_QUERY_PORT(priv->mdev, priv->port)) + return -ENOMEM; + if (priv->port_state.link_state == 1) + return 0; + else + return 1; +} + +static int mlx4_en_test_speed(struct mlx4_en_priv *priv) +{ + + if (mlx4_en_QUERY_PORT(priv->mdev, priv->port)) + return -ENOMEM; + + /* The device currently only supports 10G speed */ + if (priv->port_state.link_speed != SPEED_10000) + return priv->port_state.link_speed; + return 0; +} + + +void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + struct mlx4_en_tx_ring *tx_ring; + int i, carrier_ok; + + memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST); + + if (*flags & ETH_TEST_FL_OFFLINE) { + /* disable the interface */ + carrier_ok = netif_carrier_ok(dev); + + netif_carrier_off(dev); +retry_tx: + /* Wait untill all tx queues are empty. + * there should not be any additional incoming traffic + * since we turned the carrier off */ + msleep(200); + for (i = 0; i < priv->tx_ring_num && carrier_ok; i++) { + tx_ring = &priv->tx_ring[i]; + if (tx_ring->prod != (tx_ring->cons + tx_ring->last_nr_txbb)) + goto retry_tx; + } + + if (priv->mdev->dev->caps.loopback_support){ + buf[3] = mlx4_en_test_registers(priv); + buf[4] = mlx4_en_test_loopback(priv); + } + + if (carrier_ok) + netif_carrier_on(dev); + + } + buf[0] = mlx4_test_interrupts(mdev->dev); + buf[1] = mlx4_en_test_link(priv); + buf[2] = mlx4_en_test_speed(priv); + + for (i = 0; i < MLX4_EN_NUM_SELF_TEST; i++) { + if (buf[i]) + *flags |= ETH_TEST_FL_FAILED; + } +} diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c index 3deabd1d0357..b875f9c38848 100644 --- a/drivers/net/mlx4/en_tx.c +++ b/drivers/net/mlx4/en_tx.c @@ -600,6 +600,9 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) struct mlx4_wqe_data_seg *data; struct skb_frag_struct *frag; struct mlx4_en_tx_info *tx_info; + struct ethhdr *ethh; + u64 mac; + u32 mac_l, mac_h; int tx_ind = 0; int nr_txbb; int desc_size; @@ -679,6 +682,19 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) priv->port_stats.tx_chksum_offload++; } + if (unlikely(priv->validate_loopback)) { + /* Copy dst mac address to wqe */ + skb_reset_mac_header(skb); + ethh = eth_hdr(skb); + if (ethh && ethh->h_dest) { + mac = mlx4_en_mac_to_u64(ethh->h_dest); + mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16); + mac_l = (u32) (mac & 0xffffffff); + tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h); + tx_desc->ctrl.imm = cpu_to_be32(mac_l); + } + } + /* Handle LSO (TSO) packets */ if (lso_header_size) { /* Mark opcode as LSO */ diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c index 6d7b2bf210ce..552d0fce6f67 100644 --- a/drivers/net/mlx4/eq.c +++ b/drivers/net/mlx4/eq.c @@ -699,3 +699,47 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev) kfree(priv->eq_table.uar_map); } + +/* A test that verifies that we can accept interrupts on all + * the irq vectors of the device. + * Interrupts are checked using the NOP command. + */ +int mlx4_test_interrupts(struct mlx4_dev *dev) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + int i; + int err; + + err = mlx4_NOP(dev); + /* When not in MSI_X, there is only one irq to check */ + if (!(dev->flags & MLX4_FLAG_MSI_X)) + return err; + + /* A loop over all completion vectors, for each vector we will check + * whether it works by mapping command completions to that vector + * and performing a NOP command + */ + for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) { + /* Temporary use polling for command completions */ + mlx4_cmd_use_polling(dev); + + /* Map the new eq to handle all asyncronous events */ + err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0, + priv->eq_table.eq[i].eqn); + if (err) { + mlx4_warn(dev, "Failed mapping eq for interrupt test\n"); + mlx4_cmd_use_events(dev); + break; + } + + /* Go back to using events */ + mlx4_cmd_use_events(dev); + err = mlx4_NOP(dev); + } + + /* Return to default */ + mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0, + priv->eq_table.eq[dev->caps.num_comp_vectors].eqn); + return err; +} +EXPORT_SYMBOL(mlx4_test_interrupts); diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index 04f42ae1eda0..a87bf3c97055 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c @@ -178,6 +178,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c #define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f +#define QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET 0x43 #define QUERY_DEV_CAP_FLAGS_OFFSET 0x44 #define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48 #define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49 @@ -268,6 +269,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->max_msg_sz = 1 << (field & 0x1f); MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); dev_cap->stat_rate_support = stat_rate; + MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET); + dev_cap->loopback_support = field & 0x1; MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET); dev_cap->reserved_uars = field >> 4; diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h index 526d7f30c041..2cc1ba5452e3 100644 --- a/drivers/net/mlx4/fw.h +++ b/drivers/net/mlx4/fw.h @@ -74,6 +74,7 @@ struct mlx4_dev_cap { u64 def_mac[MLX4_MAX_PORTS + 1]; u16 eth_mtu[MLX4_MAX_PORTS + 1]; u16 stat_rate_support; + int loopback_support; u32 flags; int reserved_uars; int uar_size; diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 5102ab1ac561..7390cdb19414 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -221,6 +221,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.bmme_flags = dev_cap->bmme_flags; dev->caps.reserved_lkey = dev_cap->reserved_lkey; dev->caps.stat_rate_support = dev_cap->stat_rate_support; + dev->caps.loopback_support = dev_cap->loopback_support; dev->caps.max_gso_sz = dev_cap->max_gso_sz; dev->caps.log_num_macs = log_num_mac; diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index edf6523702c0..a09598b2b12e 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -45,6 +45,7 @@ #include #include #include +#include #include "en_port.h" @@ -139,10 +140,14 @@ enum { #define SMALL_PACKET_SIZE (256 - NET_IP_ALIGN) #define HEADER_COPY_SIZE (128 - NET_IP_ALIGN) +#define MLX4_LOOPBACK_TEST_PAYLOAD (HEADER_COPY_SIZE - ETH_HLEN) #define MLX4_EN_MIN_MTU 46 #define ETH_BCAST 0xffffffffffffULL +#define MLX4_EN_LOOPBACK_RETRIES 5 +#define MLX4_EN_LOOPBACK_TIMEOUT 100 + #ifdef MLX4_EN_PERF_STAT /* Number of samples to 'average' */ #define AVG_SIZE 128 @@ -356,6 +361,12 @@ struct mlx4_en_rss_context { __be32 rss_key[10]; }; +struct mlx4_en_port_state { + int link_state; + int link_speed; + int transciver; +}; + struct mlx4_en_pkt_stats { unsigned long broadcast; unsigned long rx_prio[8]; @@ -404,6 +415,7 @@ struct mlx4_en_priv { struct vlan_group *vlgrp; struct net_device_stats stats; struct net_device_stats ret_stats; + struct mlx4_en_port_state port_state; spinlock_t stats_lock; unsigned long last_moder_packets; @@ -422,6 +434,8 @@ struct mlx4_en_priv { u16 sample_interval; u16 adaptive_rx_coal; u32 msg_enable; + u32 loopback_ok; + u32 validate_loopback; struct mlx4_hwq_resources res; int link_state; @@ -530,6 +544,11 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, u8 promisc); int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset); +int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port); + +#define MLX4_EN_NUM_SELF_TEST 5 +void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf); +u64 mlx4_en_mac_to_u64(u8 *addr); /* * Globals diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h index 0f82293a82ed..78a1b9671752 100644 --- a/include/linux/mlx4/cmd.h +++ b/include/linux/mlx4/cmd.h @@ -56,6 +56,7 @@ enum { MLX4_CMD_QUERY_HCA = 0xb, MLX4_CMD_QUERY_PORT = 0x43, MLX4_CMD_SENSE_PORT = 0x4d, + MLX4_CMD_HW_HEALTH_CHECK = 0x50, MLX4_CMD_SET_PORT = 0xc, MLX4_CMD_ACCESS_DDR = 0x2e, MLX4_CMD_MAP_ICM = 0xffa, diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 7a7f9c1e679a..2cec58722738 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -229,6 +229,7 @@ struct mlx4_caps { u32 bmme_flags; u32 reserved_lkey; u16 stat_rate_support; + int loopback_support; u8 port_width_cap[MLX4_MAX_PORTS + 1]; int max_gso_sz; int reserved_qps_cnt[MLX4_NUM_QP_REGION]; @@ -480,5 +481,6 @@ void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u32 *lkey, u32 *rkey); int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr); int mlx4_SYNC_TPT(struct mlx4_dev *dev); +int mlx4_test_interrupts(struct mlx4_dev *dev); #endif /* MLX4_DEVICE_H */ -- cgit v1.2.3-59-g8ed1b From 7699517db435fd24143bd32dd644275e3eeb4c86 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:46:23 +0000 Subject: mlx4_en: Fixing report in Ethtool get_settings The report now based on query from FW, giving the correct tranciever type and link speed. Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_ethtool.c | 27 +++++++++++++++++++++++++-- drivers/net/mlx4/fw.c | 9 +++++++++ drivers/net/mlx4/fw.h | 4 ++++ drivers/net/mlx4/main.c | 4 ++++ include/linux/mlx4/device.h | 4 ++++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c index f7d72d7a8704..fa2f2f43ab48 100644 --- a/drivers/net/mlx4/en_ethtool.c +++ b/drivers/net/mlx4/en_ethtool.c @@ -244,16 +244,39 @@ static void mlx4_en_get_strings(struct net_device *dev, static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { + struct mlx4_en_priv *priv = netdev_priv(dev); + int trans_type; + cmd->autoneg = AUTONEG_DISABLE; cmd->supported = SUPPORTED_10000baseT_Full; - cmd->advertising = ADVERTISED_1000baseT_Full; + cmd->advertising = ADVERTISED_10000baseT_Full; + + if (mlx4_en_QUERY_PORT(priv->mdev, priv->port)) + return -ENOMEM; + + trans_type = priv->port_state.transciver; if (netif_carrier_ok(dev)) { - cmd->speed = SPEED_10000; + cmd->speed = priv->port_state.link_speed; cmd->duplex = DUPLEX_FULL; } else { cmd->speed = -1; cmd->duplex = -1; } + + if (trans_type > 0 && trans_type <= 0xC) { + cmd->port = PORT_FIBRE; + cmd->transceiver = XCVR_EXTERNAL; + cmd->supported |= SUPPORTED_FIBRE; + cmd->advertising |= ADVERTISED_FIBRE; + } else if (trans_type == 0x80 || trans_type == 0) { + cmd->port = PORT_TP; + cmd->transceiver = XCVR_INTERNAL; + cmd->supported |= SUPPORTED_TP; + cmd->advertising |= ADVERTISED_TP; + } else { + cmd->port = -1; + cmd->transceiver = -1; + } return 0; } diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index a87bf3c97055..515c6348f32b 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c @@ -141,6 +141,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) struct mlx4_cmd_mailbox *mailbox; u32 *outbox; u8 field; + u32 field32; u16 size; u16 stat_rate; int err; @@ -368,6 +369,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_PORT_MAX_MACVLAN_OFFSET 0x0a #define QUERY_PORT_MAX_VL_OFFSET 0x0b #define QUERY_PORT_MAC_OFFSET 0x10 +#define QUERY_PORT_TRANS_VENDOR_OFFSET 0x18 +#define QUERY_PORT_WAVELENGTH_OFFSET 0x1c +#define QUERY_PORT_TRANS_CODE_OFFSET 0x20 for (i = 1; i <= dev_cap->num_ports; ++i) { err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT, @@ -391,6 +395,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->log_max_vlans[i] = field >> 4; MLX4_GET(dev_cap->eth_mtu[i], outbox, QUERY_PORT_ETH_MTU_OFFSET); MLX4_GET(dev_cap->def_mac[i], outbox, QUERY_PORT_MAC_OFFSET); + MLX4_GET(field32, outbox, QUERY_PORT_TRANS_VENDOR_OFFSET); + dev_cap->trans_type[i] = field32 >> 24; + dev_cap->vendor_oui[i] = field32 & 0xffffff; + MLX4_GET(dev_cap->wavelength[i], outbox, QUERY_PORT_WAVELENGTH_OFFSET); + MLX4_GET(dev_cap->trans_code[i], outbox, QUERY_PORT_TRANS_CODE_OFFSET); } } diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h index 2cc1ba5452e3..443e456c9dab 100644 --- a/drivers/net/mlx4/fw.h +++ b/drivers/net/mlx4/fw.h @@ -73,6 +73,10 @@ struct mlx4_dev_cap { int max_pkeys[MLX4_MAX_PORTS + 1]; u64 def_mac[MLX4_MAX_PORTS + 1]; u16 eth_mtu[MLX4_MAX_PORTS + 1]; + int trans_type[MLX4_MAX_PORTS + 1]; + int vendor_oui[MLX4_MAX_PORTS + 1]; + u16 wavelength[MLX4_MAX_PORTS + 1]; + u64 trans_code[MLX4_MAX_PORTS + 1]; u16 stat_rate_support; int loopback_support; u32 flags; diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 7390cdb19414..f4791fa2472f 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -184,6 +184,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.eth_mtu_cap[i] = dev_cap->eth_mtu[i]; dev->caps.def_mac[i] = dev_cap->def_mac[i]; dev->caps.supported_type[i] = dev_cap->supported_port_types[i]; + dev->caps.trans_type[i] = dev_cap->trans_type[i]; + dev->caps.vendor_oui[i] = dev_cap->vendor_oui[i]; + dev->caps.wavelength[i] = dev_cap->wavelength[i]; + dev->caps.trans_code[i] = dev_cap->trans_code[i]; } dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE; diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 2cec58722738..2a36a344fb3d 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -186,6 +186,10 @@ struct mlx4_caps { int eth_mtu_cap[MLX4_MAX_PORTS + 1]; int gid_table_len[MLX4_MAX_PORTS + 1]; int pkey_table_len[MLX4_MAX_PORTS + 1]; + int trans_type[MLX4_MAX_PORTS + 1]; + int vendor_oui[MLX4_MAX_PORTS + 1]; + int wavelength[MLX4_MAX_PORTS + 1]; + u64 trans_code[MLX4_MAX_PORTS + 1]; int local_ca_ack_delay; int num_uars; int bf_reg_size; -- cgit v1.2.3-59-g8ed1b From bc081cecf3cb3da236061cf353d74c42ba7e37fb Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:46:34 +0000 Subject: mlx4_en: get/set ringsize uses actual ring size In case that the rings were not fully filled, the report in Ethtool should be according to the actual size that was filled. Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_ethtool.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c index fa2f2f43ab48..c5551f2cf260 100644 --- a/drivers/net/mlx4/en_ethtool.c +++ b/drivers/net/mlx4/en_ethtool.c @@ -394,8 +394,9 @@ static int mlx4_en_set_ringparam(struct net_device *dev, tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE); tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE); - if (rx_size == priv->prof->rx_ring_size && - tx_size == priv->prof->tx_ring_size) + if (rx_size == (priv->port_up ? priv->rx_ring[0].actual_size : + priv->rx_ring[0].size) && + tx_size == priv->tx_ring[0].size) return 0; mutex_lock(&mdev->state_lock); @@ -429,13 +430,13 @@ static void mlx4_en_get_ringparam(struct net_device *dev, struct ethtool_ringparam *param) { struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; memset(param, 0, sizeof(*param)); param->rx_max_pending = MLX4_EN_MAX_RX_SIZE; param->tx_max_pending = MLX4_EN_MAX_TX_SIZE; - param->rx_pending = mdev->profile.prof[priv->port].rx_ring_size; - param->tx_pending = mdev->profile.prof[priv->port].tx_ring_size; + param->rx_pending = priv->port_up ? + priv->rx_ring[0].actual_size : priv->rx_ring[0].size; + param->tx_pending = priv->tx_ring[0].size; } static int mlx4_ethtool_op_set_flags(struct net_device *dev, u32 data) -- cgit v1.2.3-59-g8ed1b From d7e1a487d31933deba742c1bd3ffe0f73220b729 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:46:38 +0000 Subject: mlx4_en: reconfiguring mac address. When Mac address is removed from one port of the CX2 device, the other device should reconfigure its Mac. This fixes an issue with failover, when both ports have the same Mac address, and one of the ports, is closed, the second one stops receiving traffic. (bugzilla #1965 at bugs.openfabrics.org) Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_netdev.c | 6 ++++++ drivers/net/mlx4/mlx4_en.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 968e75b7acf4..242366ca0793 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -513,6 +513,10 @@ static void mlx4_en_do_get_stats(struct work_struct *work) queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); } + if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) { + queue_work(mdev->workqueue, &priv->mac_task); + mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0; + } mutex_unlock(&mdev->state_lock); } @@ -653,6 +657,7 @@ int mlx4_en_start_port(struct net_device *dev) en_err(priv, "Failed setting port mac\n"); goto tx_err; } + mdev->mac_removed[priv->port] = 0; /* Init port */ en_dbg(HW, priv, "Initializing port\n"); @@ -709,6 +714,7 @@ void mlx4_en_stop_port(struct net_device *dev) /* Unregister Mac address for the port */ mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index); + mdev->mac_removed[priv->port] = 1; /* Free TX Rings */ for (i = 0; i < priv->tx_ring_num; i++) { diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index a09598b2b12e..5d8f097d7e06 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -341,6 +341,7 @@ struct mlx4_en_dev { struct mlx4_mr mr; u32 priv_pdn; spinlock_t uar_lock; + u8 mac_removed[MLX4_MAX_PORTS + 1]; }; -- cgit v1.2.3-59-g8ed1b From 0533943c5c45cce2e26432bf0a6b8e114757c897 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:46:42 +0000 Subject: mlx4_en: UDP RSS support Adding capability for RSS for UDP traffic, hashing is done based on IP addresses and UDP port number. The support depends on HW/FW capabilities. Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_main.c | 19 ++++++++++++------- drivers/net/mlx4/en_rx.c | 8 ++++---- drivers/net/mlx4/fw.c | 3 +++ drivers/net/mlx4/fw.h | 1 + drivers/net/mlx4/main.c | 1 + drivers/net/mlx4/mlx4_en.h | 3 +++ include/linux/mlx4/device.h | 1 + 7 files changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c index cacac4e966ee..143906417048 100644 --- a/drivers/net/mlx4/en_main.c +++ b/drivers/net/mlx4/en_main.c @@ -63,11 +63,12 @@ static const char mlx4_en_version[] = */ -/* Use a XOR rathern than Toeplitz hash function for RSS */ -MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS"); - -/* RSS hash type mask - default to */ -MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask"); +/* Enable RSS TCP traffic */ +MLX4_EN_PARM_INT(tcp_rss, 1, + "Enable RSS for incomming TCP traffic or disabled (0)"); +/* Enable RSS UDP traffic */ +MLX4_EN_PARM_INT(udp_rss, 1, + "Enable RSS for incomming UDP traffic or disabled (0)"); /* Priority pausing */ MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]." @@ -103,8 +104,12 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev) struct mlx4_en_profile *params = &mdev->profile; int i; - params->rss_xor = (rss_xor != 0); - params->rss_mask = rss_mask & 0x1f; + params->tcp_rss = tcp_rss; + params->udp_rss = udp_rss; + if (params->udp_rss && !mdev->dev->caps.udp_rss) { + mlx4_warn(mdev, "UDP RSS is not supported on this device.\n"); + params->udp_rss = 0; + } for (i = 1; i <= MLX4_MAX_PORTS; i++) { params->prof[i].rx_pause = 1; params->prof[i].rx_ppp = pfcrx; diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index f421a3d42723..e2126c76d1dc 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -859,8 +859,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) struct mlx4_qp_context context; struct mlx4_en_rss_context *rss_context; void *ptr; - int rss_xor = mdev->profile.rss_xor; - u8 rss_mask = mdev->profile.rss_mask; + u8 rss_mask = 0x3f; int i, qpn; int err = 0; int good_qps = 0; @@ -906,9 +905,10 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 | (rss_map->base_qpn)); rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn); - rss_context->hash_fn = rss_xor & 0x3; - rss_context->flags = rss_mask << 2; + rss_context->flags = rss_mask; + if (priv->mdev->profile.udp_rss) + rss_context->base_qpn_udp = rss_context->default_qpn; err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context, &rss_map->indir_qp, &rss_map->indir_state); if (err) diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index 515c6348f32b..b716e1a1b298 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c @@ -179,6 +179,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c #define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f +#define QUERY_DEV_CAP_UDP_RSS_OFFSET 0x42 #define QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET 0x43 #define QUERY_DEV_CAP_FLAGS_OFFSET 0x44 #define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48 @@ -270,6 +271,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->max_msg_sz = 1 << (field & 0x1f); MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); dev_cap->stat_rate_support = stat_rate; + MLX4_GET(field, outbox, QUERY_DEV_CAP_UDP_RSS_OFFSET); + dev_cap->udp_rss = field & 0x1; MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET); dev_cap->loopback_support = field & 0x1; MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h index 443e456c9dab..65cc72eb899d 100644 --- a/drivers/net/mlx4/fw.h +++ b/drivers/net/mlx4/fw.h @@ -78,6 +78,7 @@ struct mlx4_dev_cap { u16 wavelength[MLX4_MAX_PORTS + 1]; u64 trans_code[MLX4_MAX_PORTS + 1]; u16 stat_rate_support; + int udp_rss; int loopback_support; u32 flags; int reserved_uars; diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index f4791fa2472f..569fa3df381f 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -225,6 +225,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.bmme_flags = dev_cap->bmme_flags; dev->caps.reserved_lkey = dev_cap->reserved_lkey; dev->caps.stat_rate_support = dev_cap->stat_rate_support; + dev->caps.udp_rss = dev_cap->udp_rss; dev->caps.loopback_support = dev_cap->loopback_support; dev->caps.max_gso_sz = dev_cap->max_gso_sz; diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 5d8f097d7e06..4036a053ee32 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -318,6 +318,8 @@ struct mlx4_en_port_profile { struct mlx4_en_profile { int rss_xor; + int tcp_rss; + int udp_rss; u8 rss_mask; u32 active_ports; u32 small_pkt_int; @@ -360,6 +362,7 @@ struct mlx4_en_rss_context { u8 hash_fn; u8 flags; __be32 rss_key[10]; + __be32 base_qpn_udp; }; struct mlx4_en_port_state { diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 2a36a344fb3d..7338654c02b4 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -233,6 +233,7 @@ struct mlx4_caps { u32 bmme_flags; u32 reserved_lkey; u16 stat_rate_support; + int udp_rss; int loopback_support; u8 port_width_cap[MLX4_MAX_PORTS + 1]; int max_gso_sz; -- cgit v1.2.3-59-g8ed1b From fa37a9586f92051de03a13e55e5ec3880bb6783e Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:46:46 +0000 Subject: mlx4_en: Moving to work with GRO Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_ethtool.c | 56 ++---------------------------------- drivers/net/mlx4/en_netdev.c | 2 +- drivers/net/mlx4/en_rx.c | 66 +++++++++---------------------------------- drivers/net/mlx4/en_tx.c | 1 + drivers/net/mlx4/mlx4_en.h | 5 ---- 5 files changed, 17 insertions(+), 113 deletions(-) diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c index c5551f2cf260..01634a3efe85 100644 --- a/drivers/net/mlx4/en_ethtool.c +++ b/drivers/net/mlx4/en_ethtool.c @@ -39,21 +39,6 @@ #include "en_port.h" -static void mlx4_en_update_lro_stats(struct mlx4_en_priv *priv) -{ - int i; - - priv->port_stats.lro_aggregated = 0; - priv->port_stats.lro_flushed = 0; - priv->port_stats.lro_no_desc = 0; - - for (i = 0; i < priv->rx_ring_num; i++) { - priv->port_stats.lro_aggregated += priv->rx_ring[i].lro.stats.aggregated; - priv->port_stats.lro_flushed += priv->rx_ring[i].lro.stats.flushed; - priv->port_stats.lro_no_desc += priv->rx_ring[i].lro.stats.no_desc; - } -} - static void mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) { @@ -112,7 +97,7 @@ static const char main_strings[][ETH_GSTRING_LEN] = { "tx_heartbeat_errors", "tx_window_errors", /* port statistics */ - "lro_aggregated", "lro_flushed", "lro_no_desc", "tso_packets", + "tso_packets", "queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed", "rx_csum_good", "rx_csum_none", "tx_chksum_offload", @@ -122,7 +107,7 @@ static const char main_strings[][ETH_GSTRING_LEN] = { "tx_prio_1", "tx_prio_2", "tx_prio_3", "tx_prio_4", "tx_prio_5", "tx_prio_6", "tx_prio_7", }; -#define NUM_MAIN_STATS 21 +#define NUM_MAIN_STATS 18 #define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS) static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= { @@ -174,8 +159,6 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev, spin_lock_bh(&priv->stats_lock); - mlx4_en_update_lro_stats(priv); - for (i = 0; i < NUM_MAIN_STATS; i++) data[index++] = ((unsigned long *) &priv->stats)[i]; for (i = 0; i < NUM_PORT_STATS; i++) @@ -439,40 +422,6 @@ static void mlx4_en_get_ringparam(struct net_device *dev, param->tx_pending = priv->tx_ring[0].size; } -static int mlx4_ethtool_op_set_flags(struct net_device *dev, u32 data) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - int rc = 0; - int changed = 0; - - if (data & ~ETH_FLAG_LRO) - return -EOPNOTSUPP; - - if (data & ETH_FLAG_LRO) { - if (!(dev->features & NETIF_F_LRO)) - changed = 1; - } else if (dev->features & NETIF_F_LRO) { - changed = 1; - } - - if (changed) { - if (netif_running(dev)) { - mutex_lock(&mdev->state_lock); - mlx4_en_stop_port(dev); - } - dev->features ^= NETIF_F_LRO; - if (netif_running(dev)) { - rc = mlx4_en_start_port(dev); - if (rc) - en_err(priv, "Failed to restart port\n"); - mutex_unlock(&mdev->state_lock); - } - } - - return rc; -} - const struct ethtool_ops mlx4_en_ethtool_ops = { .get_drvinfo = mlx4_en_get_drvinfo, .get_settings = mlx4_en_get_settings, @@ -502,7 +451,6 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { .get_ringparam = mlx4_en_get_ringparam, .set_ringparam = mlx4_en_set_ringparam, .get_flags = ethtool_op_get_flags, - .set_flags = mlx4_ethtool_op_set_flags, }; diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 242366ca0793..411bda581c04 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -1047,7 +1047,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; - dev->features |= NETIF_F_LRO; + dev->features |= NETIF_F_GRO; if (mdev->LSO_support) { dev->features |= NETIF_F_TSO; dev->features |= NETIF_F_TSO6; diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index e2126c76d1dc..cb7ff00ce6de 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -42,18 +42,6 @@ #include "mlx4_en.h" -static int mlx4_en_get_frag_header(struct skb_frag_struct *frags, void **mac_hdr, - void **ip_hdr, void **tcpudp_hdr, - u64 *hdr_flags, void *priv) -{ - *mac_hdr = page_address(frags->page) + frags->page_offset; - *ip_hdr = *mac_hdr + ETH_HLEN; - *tcpudp_hdr = (struct tcphdr *)(*ip_hdr + sizeof(struct iphdr)); - *hdr_flags = LRO_IPV4 | LRO_TCP; - - return 0; -} - static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv, struct mlx4_en_rx_desc *rx_desc, struct skb_frag_struct *skb_frags, @@ -312,24 +300,6 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, } ring->buf = ring->wqres.buf.direct.buf; - /* Configure lro mngr */ - memset(&ring->lro, 0, sizeof(struct net_lro_mgr)); - ring->lro.dev = priv->dev; - ring->lro.features = LRO_F_NAPI; - ring->lro.frag_align_pad = NET_IP_ALIGN; - ring->lro.ip_summed = CHECKSUM_UNNECESSARY; - ring->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY; - ring->lro.max_desc = MLX4_EN_MAX_LRO_DESCRIPTORS; - ring->lro.max_aggr = MAX_SKB_FRAGS; - ring->lro.lro_arr = kcalloc(MLX4_EN_MAX_LRO_DESCRIPTORS, - sizeof(struct net_lro_desc), - GFP_KERNEL); - if (!ring->lro.lro_arr) { - en_err(priv, "Failed to allocate lro array\n"); - goto err_map; - } - ring->lro.get_frag_header = mlx4_en_get_frag_header; - return 0; err_map: @@ -412,7 +382,6 @@ void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv, { struct mlx4_en_dev *mdev = priv->mdev; - kfree(ring->lro.lro_arr); mlx4_en_unmap_buffer(&ring->wqres.buf); mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE); vfree(ring->rx_info); @@ -563,7 +532,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud struct mlx4_cqe *cqe; struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring]; struct skb_frag_struct *skb_frags; - struct skb_frag_struct lro_frags[MLX4_EN_MAX_RX_FRAGS]; struct mlx4_en_rx_desc *rx_desc; struct sk_buff *skb; int index; @@ -623,37 +591,33 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud * - TCP/IP (v4) * - without IP options * - not an IP fragment */ - if (mlx4_en_can_lro(cqe->status) && - dev->features & NETIF_F_LRO) { + if (dev->features & NETIF_F_GRO) { + struct sk_buff *gro_skb = napi_get_frags(&cq->napi); nr = mlx4_en_complete_rx_desc( priv, rx_desc, - skb_frags, lro_frags, + skb_frags, skb_shinfo(gro_skb)->frags, ring->page_alloc, length); if (!nr) goto next; + skb_shinfo(gro_skb)->nr_frags = nr; + gro_skb->len = length; + gro_skb->data_len = length; + gro_skb->truesize += length; + gro_skb->ip_summed = CHECKSUM_UNNECESSARY; + if (priv->vlgrp && (cqe->vlan_my_qpn & - cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK))) { - lro_vlan_hwaccel_receive_frags( - &ring->lro, lro_frags, - length, length, - priv->vlgrp, - be16_to_cpu(cqe->sl_vid), - NULL, 0); - } else - lro_receive_frags(&ring->lro, - lro_frags, - length, - length, - NULL, 0); + cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK))) + vlan_gro_frags(&cq->napi, priv->vlgrp, be16_to_cpu(cqe->sl_vid)); + else + napi_gro_frags(&cq->napi); goto next; } /* LRO not possible, complete processing here */ ip_summed = CHECKSUM_UNNECESSARY; - INC_PERF_COUNTER(priv->pstats.lro_misses); } else { ip_summed = CHECKSUM_NONE; priv->port_stats.rx_chksum_none++; @@ -694,14 +658,10 @@ next: if (++polled == budget) { /* We are here because we reached the NAPI budget - * flush only pending LRO sessions */ - lro_flush_all(&ring->lro); goto out; } } - /* If CQ is empty flush all LRO sessions unconditionally */ - lro_flush_all(&ring->lro); - out: AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled); mlx4_cq_set_ci(&cq->mcq); diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c index b875f9c38848..98dd620042a8 100644 --- a/drivers/net/mlx4/en_tx.c +++ b/drivers/net/mlx4/en_tx.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "mlx4_en.h" diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 4036a053ee32..7d4ddb9a2bec 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -254,7 +253,6 @@ struct mlx4_en_rx_desc { struct mlx4_en_rx_ring { struct mlx4_hwq_resources wqres; struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS]; - struct net_lro_mgr lro; u32 size ; /* number of Rx descs*/ u32 actual_size; u32 size_mask; @@ -379,9 +377,6 @@ struct mlx4_en_pkt_stats { }; struct mlx4_en_port_stats { - unsigned long lro_aggregated; - unsigned long lro_flushed; - unsigned long lro_no_desc; unsigned long tso_packets; unsigned long queue_stopped; unsigned long wake_queue; -- cgit v1.2.3-59-g8ed1b From 04714a16db6fd8d175050a01459fd16660fba18c Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 24 Aug 2010 03:46:49 +0000 Subject: mlx4_en: updated driver version Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/mlx4_en.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 7d4ddb9a2bec..ce8e2338ee31 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -49,8 +49,8 @@ #include "en_port.h" #define DRV_NAME "mlx4_en" -#define DRV_VERSION "1.4.1.1" -#define DRV_RELDATE "June 2009" +#define DRV_VERSION "1.5.1.6" +#define DRV_RELDATE "August 2010" #define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN) -- cgit v1.2.3-59-g8ed1b From 4562487a00445eab96311365ba15c41dc4d043cd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 24 Aug 2010 15:06:27 -0700 Subject: mlx4_en: Fix build warning in mlx4_en_create_rx_ring. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/net/mlx4/en_rx.c: In function ‘mlx4_en_create_rx_ring’: drivers/net/mlx4/en_rx.c:305: warning: label ‘err_map’ defined but not used Signed-off-by: David S. Miller --- drivers/net/mlx4/en_rx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index cb7ff00ce6de..c4aad7f2beb9 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -302,8 +302,6 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, return 0; -err_map: - mlx4_en_unmap_buffer(&ring->wqres.buf); err_hwq: mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size); err_ring: -- cgit v1.2.3-59-g8ed1b From a10430443120205853e5f13a938e6560d027b42f Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 16 Aug 2010 16:26:08 +0200 Subject: HID: Kconfig: Complete Kconfig prompt names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make special HID devices' Kconfig names unambiguous, obviating the need to enter the help menu of each driver in order to know what hardware device it actually supports. Cc: Jiri Kosina Cc: "Bruno Prémont" Cc: Stephane Chatty Cc: Don Prince Cc: linux-input@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Borislav Petkov Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 60 ++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 6369ba7f96f8..2072e0138e9f 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -56,20 +56,20 @@ menu "Special HID drivers" depends on HID config HID_3M_PCT - tristate "3M PCT" + tristate "3M PCT touchscreen" depends on USB_HID ---help--- Support for 3M PCT touch screens. config HID_A4TECH - tristate "A4 tech" if EMBEDDED + tristate "A4 tech mice" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- Support for A4 tech X5 and WOP-35 / Trust 450L mice. config HID_ACRUX_FF - tristate "ACRUX force feedback support" + tristate "ACRUX force feedback" depends on USB_HID select INPUT_FF_MEMLESS ---help--- @@ -77,7 +77,7 @@ config HID_ACRUX_FF game controllers. config HID_APPLE - tristate "Apple" if EMBEDDED + tristate "Apple {i,Power,Mac}Books" if EMBEDDED depends on (USB_HID || BT_HIDP) default !EMBEDDED ---help--- @@ -88,7 +88,7 @@ config HID_APPLE MacBooks, MacBook Pros and Apple Aluminum. config HID_BELKIN - tristate "Belkin" if EMBEDDED + tristate "Belkin Flip KVM and Wireless keyboard" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- @@ -101,14 +101,14 @@ config HID_CANDO Support for Cando dual touch panel. config HID_CHERRY - tristate "Cherry" if EMBEDDED + tristate "Cherry Cymotion keyboard" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- Support for Cherry Cymotion keyboard. config HID_CHICONY - tristate "Chicony" if EMBEDDED + tristate "Chicony Tactical pad" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- @@ -130,20 +130,20 @@ config HID_PRODIKEYS and some additional multimedia keys. config HID_CYPRESS - tristate "Cypress" if EMBEDDED + tristate "Cypress mouse and barcode readers" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- Support for cypress mouse and barcode readers. config HID_DRAGONRISE - tristate "DragonRise Inc. support" + tristate "DragonRise Inc. game controller" depends on USB_HID ---help--- Say Y here if you have DragonRise Inc.game controllers. config DRAGONRISE_FF - bool "DragonRise Inc. force feedback support" + bool "DragonRise Inc. force feedback" depends on HID_DRAGONRISE select INPUT_FF_MEMLESS ---help--- @@ -157,46 +157,46 @@ config HID_EGALAX Support for the eGalax dual-touch panel. config HID_ELECOM - tristate "ELECOM" + tristate "ELECOM BM084 bluetooth mouse" depends on BT_HIDP ---help--- Support for the ELECOM BM084 (bluetooth mouse). config HID_EZKEY - tristate "Ezkey" if EMBEDDED + tristate "Ezkey BTC 8193 keyboard" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- Support for Ezkey BTC 8193 keyboard. config HID_KYE - tristate "Kye" if EMBEDDED + tristate "Kye/Genius Ergo Mouse" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- Support for Kye/Genius Ergo Mouse. config HID_GYRATION - tristate "Gyration" + tristate "Gyration remote control" depends on USB_HID ---help--- Support for Gyration remote control. config HID_TWINHAN - tristate "Twinhan" + tristate "Twinhan IR remote control" depends on USB_HID ---help--- Support for Twinhan IR remote control. config HID_KENSINGTON - tristate "Kensington" if EMBEDDED + tristate "Kensington Slimblade Trackball" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- Support for Kensington Slimblade Trackball. config HID_LOGITECH - tristate "Logitech" if EMBEDDED + tristate "Logitech devices" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- @@ -245,39 +245,39 @@ config HID_MAGICMOUSE Apple Wireless "Magic" Mouse. config HID_MICROSOFT - tristate "Microsoft" if EMBEDDED + tristate "Microsoft non-fully HID-compliant devices" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- Support for Microsoft devices that are not fully compliant with HID standard. config HID_MOSART - tristate "MosArt" + tristate "MosArt dual-touch panels" depends on USB_HID ---help--- Support for MosArt dual-touch panels. config HID_MONTEREY - tristate "Monterey" if EMBEDDED + tristate "Monterey Genius KB29E keyboard" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- Support for Monterey Genius KB29E. config HID_NTRIG - tristate "NTrig" + tristate "N-Trig touch screen" depends on USB_HID ---help--- Support for N-Trig touch screen. config HID_ORTEK - tristate "Ortek" + tristate "Ortek WKB-2000 wireless keyboard and mouse trackpad" depends on USB_HID ---help--- Support for Ortek WKB-2000 wireless keyboard + mouse trackpad. config HID_PANTHERLORD - tristate "Pantherlord support" + tristate "Pantherlord/GreenAsia game controller" depends on USB_HID ---help--- Say Y here if you have a PantherLord/GreenAsia based game controller @@ -292,7 +292,7 @@ config PANTHERLORD_FF or adapter and want to enable force feedback support for it. config HID_PETALYNX - tristate "Petalynx" + tristate "Petalynx Maxter remote control" depends on USB_HID ---help--- Support for Petalynx Maxter remote control. @@ -356,7 +356,7 @@ config HID_PICOLCD_LEDS Provide access to PicoLCD's GPO pins via leds class. config HID_QUANTA - tristate "Quanta Optical Touch" + tristate "Quanta Optical Touch panels" depends on USB_HID ---help--- Support for Quanta Optical Touch dual-touch panels. @@ -377,31 +377,31 @@ config HID_ROCCAT_KONE Support for Roccat Kone mouse. config HID_SAMSUNG - tristate "Samsung" + tristate "Samsung InfraRed remote control or keyboards" depends on USB_HID ---help--- Support for Samsung InfraRed remote control or keyboards. config HID_SONY - tristate "Sony" + tristate "Sony PS3 controller" depends on USB_HID ---help--- Support for Sony PS3 controller. config HID_STANTUM - tristate "Stantum" + tristate "Stantum multitouch panel" depends on USB_HID ---help--- Support for Stantum multitouch panel. config HID_SUNPLUS - tristate "Sunplus" + tristate "Sunplus wireless desktop" depends on USB_HID ---help--- Support for Sunplus wireless desktop. config HID_GREENASIA - tristate "GreenAsia (Product ID 0x12) support" + tristate "GreenAsia (Product ID 0x12) game controller support" depends on USB_HID ---help--- Say Y here if you have a GreenAsia (Product ID 0x12) based game -- cgit v1.2.3-59-g8ed1b From 014a27553a804c24a213d11aee30470b0a83f341 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 25 Aug 2010 16:59:11 +0800 Subject: ASoC: pxa-ssp: fix a memory leak in pxa_ssp_remove() The "priv" allocated in pxa_ssp_probe() should be kfreed in pxa_ssp_remove(). Signed-off-by: Axel Lin Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 8dfbcda956ff..b439eee462cb 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -758,6 +758,7 @@ static int pxa_ssp_remove(struct snd_soc_dai *dai) struct ssp_priv *priv = snd_soc_dai_get_drvdata(dai); pxa_ssp_free(priv->ssp); + kfree(priv); return 0; } -- cgit v1.2.3-59-g8ed1b From b62177a0aa0521fd07cd7501534c0c3b256ebce6 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 20 Aug 2010 15:23:47 +0200 Subject: iwlwifi: fix canceling monitor_recover timer To make del_timer_sync() works we have to assure that timer function does not rearm the timer. To achieve that we cancel timer with STATUS_EXIT_PENDING bit set in __iwl{3945,}_down function. Patch also fix priv->txq memory usage after free for iwl3945, because it move timer cancellation before iwl3945_hw_txq_ctx_free(priv) is called. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 7 +++++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3ced9ea9c5fe..26bc0482dd9e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2764,6 +2764,11 @@ static void __iwl_down(struct iwl_priv *priv) if (!exit_pending) set_bit(STATUS_EXIT_PENDING, &priv->status); + /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set + * to prevent rearm timer */ + if (priv->cfg->ops->lib->recover_from_tx_stall) + del_timer_sync(&priv->monitor_recover); + iwl_clear_ucode_stations(priv); iwl_dealloc_bcast_station(priv); iwl_clear_driver_stations(priv); @@ -3870,8 +3875,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->beacon_update); del_timer_sync(&priv->statistics_periodic); del_timer_sync(&priv->ucode_trace); - if (priv->cfg->ops->lib->recover_from_tx_stall) - del_timer_sync(&priv->monitor_recover); } static void iwl_init_hw_rates(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 94d7e6e1323d..53e6cbb3aaaa 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2571,6 +2571,11 @@ static void __iwl3945_down(struct iwl_priv *priv) if (!exit_pending) set_bit(STATUS_EXIT_PENDING, &priv->status); + /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set + * to prevent rearm timer */ + if (priv->cfg->ops->lib->recover_from_tx_stall) + del_timer_sync(&priv->monitor_recover); + /* Station information will now be cleared in device */ iwl_clear_ucode_stations(priv); iwl_dealloc_bcast_station(priv); @@ -3811,8 +3816,6 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work(&priv->alive_start); cancel_work_sync(&priv->start_internal_scan); cancel_work_sync(&priv->beacon_update); - if (priv->cfg->ops->lib->recover_from_tx_stall) - del_timer_sync(&priv->monitor_recover); } static struct attribute *iwl3945_sysfs_entries[] = { -- cgit v1.2.3-59-g8ed1b From 0fb9a9ec27718fbf7fa3153bc94becefb716ceeb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Aug 2010 16:25:38 -0700 Subject: net/mac80211: Use wiphy_ Standardize logging messages from printk(KERN_ "%s: " fmt , wiphy_name(foo), args); to wiphy_(foo, fmt, args); Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 6 +++--- net/mac80211/debugfs.c | 6 ++++-- net/mac80211/ibss.c | 4 ++-- net/mac80211/iface.c | 6 ++---- net/mac80211/key.c | 14 ++++++-------- net/mac80211/main.c | 15 +++++++-------- net/mac80211/mlme.c | 17 +++++++++-------- net/mac80211/rate.c | 9 ++++----- net/mac80211/rx.c | 13 +++++-------- net/mac80211/sta_info.c | 21 +++++++++------------ net/mac80211/status.c | 9 ++++----- net/mac80211/tx.c | 8 ++++---- 12 files changed, 59 insertions(+), 69 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 94787d21282c..7693ebc77596 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1123,9 +1123,9 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, p.uapsd = false; if (drv_conf_tx(local, params->queue, &p)) { - printk(KERN_DEBUG "%s: failed to set TX queue " - "parameters for queue %d\n", - wiphy_name(local->hw.wiphy), params->queue); + wiphy_debug(local->hw.wiphy, + "failed to set TX queue parameters for queue %d\n", + params->queue); return -EINVAL; } diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index a694c593ff6a..e81ef4e8cb32 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -85,13 +85,15 @@ static ssize_t tsf_write(struct file *file, if (strncmp(buf, "reset", 5) == 0) { if (local->ops->reset_tsf) { drv_reset_tsf(local); - printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy)); + wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); } } else { tsf = simple_strtoul(buf, NULL, 0); if (local->ops->set_tsf) { drv_set_tsf(local, tsf); - printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf); + wiphy_info(local->hw.wiphy, + "debugfs set TSF to %#018llx\n", tsf); + } } diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 32af97108425..1a3aae54f0cf 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -427,8 +427,8 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, return NULL; #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n", - wiphy_name(local->hw.wiphy), addr, sdata->name); + wiphy_debug(local->hw.wiphy, "Adding new IBSS station %pM (dev=%s)\n", + addr, sdata->name); #endif sta = sta_info_alloc(sdata, addr, gfp); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 86f434f234ae..9369710cc65b 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1175,8 +1175,7 @@ static u32 ieee80211_idle_off(struct ieee80211_local *local, return 0; #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: device no longer idle - %s\n", - wiphy_name(local->hw.wiphy), reason); + wiphy_debug(local->hw.wiphy, "device no longer idle - %s\n", reason); #endif local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; @@ -1189,8 +1188,7 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) return 0; #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: device now idle\n", - wiphy_name(local->hw.wiphy)); + wiphy_debug(local->hw.wiphy, "device now idle\n"); #endif drv_flush(local, false); diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 9c27c53cfae5..2ce2dbbf6309 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -87,10 +87,9 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) - printk(KERN_ERR "mac80211-%s: failed to set key " - "(%d, %pM) to hardware (%d)\n", - wiphy_name(key->local->hw.wiphy), - key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); + wiphy_err(key->local->hw.wiphy, + "failed to set key (%d, %pM) to hardware (%d)\n", + key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); } static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) @@ -121,10 +120,9 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) sta, &key->conf); if (ret) - printk(KERN_ERR "mac80211-%s: failed to remove key " - "(%d, %pM) from hardware (%d)\n", - wiphy_name(key->local->hw.wiphy), - key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); + wiphy_err(key->local->hw.wiphy, + "failed to remove key (%d, %pM) from hardware (%d)\n", + key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index a53feac4618c..5756fba63d48 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -713,16 +713,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) result = ieee80211_wep_init(local); if (result < 0) - printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", - wiphy_name(local->hw.wiphy), result); + wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", + result); rtnl_lock(); result = ieee80211_init_rate_ctrl_alg(local, hw->rate_control_algorithm); if (result < 0) { - printk(KERN_DEBUG "%s: Failed to initialize rate control " - "algorithm\n", wiphy_name(local->hw.wiphy)); + wiphy_debug(local->hw.wiphy, + "Failed to initialize rate control algorithm\n"); goto fail_rate; } @@ -731,8 +731,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) result = ieee80211_if_add(local, "wlan%d", NULL, NL80211_IFTYPE_STATION, NULL); if (result) - printk(KERN_WARNING "%s: Failed to add default virtual iface\n", - wiphy_name(local->hw.wiphy)); + wiphy_warn(local->hw.wiphy, + "Failed to add default virtual iface\n"); } rtnl_unlock(); @@ -815,8 +815,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) if (skb_queue_len(&local->skb_queue) || skb_queue_len(&local->skb_queue_unreliable)) - printk(KERN_WARNING "%s: skb_queue not empty\n", - wiphy_name(local->hw.wiphy)); + wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); skb_queue_purge(&local->skb_queue); skb_queue_purge(&local->skb_queue_unreliable); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 38996a44aa8e..5282ac18d2cf 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -778,16 +778,17 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, params.uapsd = uapsd; #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " - "cWmin=%d cWmax=%d txop=%d uapsd=%d\n", - wiphy_name(local->hw.wiphy), queue, aci, acm, - params.aifs, params.cw_min, params.cw_max, params.txop, - params.uapsd); + wiphy_debug(local->hw.wiphy, + "WMM queue=%d aci=%d acm=%d aifs=%d " + "cWmin=%d cWmax=%d txop=%d uapsd=%d\n", + queue, aci, acm, + params.aifs, params.cw_min, params.cw_max, + params.txop, params.uapsd); #endif if (drv_conf_tx(local, queue, ¶ms)) - printk(KERN_DEBUG "%s: failed to set TX queue " - "parameters for queue %d\n", - wiphy_name(local->hw.wiphy), queue); + wiphy_debug(local->hw.wiphy, + "failed to set TX queue parameters for queue %d\n", + queue); } /* enable WMM or activate new settings */ diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 6d0bd198af19..f77a45625c0b 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -366,8 +366,8 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, ref = rate_control_alloc(name, local); if (!ref) { - printk(KERN_WARNING "%s: Failed to select rate control " - "algorithm\n", wiphy_name(local->hw.wiphy)); + wiphy_warn(local->hw.wiphy, + "Failed to select rate control algorithm\n"); return -ENOENT; } @@ -378,9 +378,8 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, sta_info_flush(local, NULL); } - printk(KERN_DEBUG "%s: Selected rate control " - "algorithm '%s'\n", wiphy_name(local->hw.wiphy), - ref->ops->name); + wiphy_debug(local->hw.wiphy, "Selected rate control algorithm '%s'\n", + ref->ops->name); return 0; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index aa41e382bbb3..e1844f7085de 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -605,10 +605,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, #ifdef CONFIG_MAC80211_HT_DEBUG if (net_ratelimit()) - printk(KERN_DEBUG "%s: release an RX reorder " - "frame due to timeout on earlier " - "frames\n", - wiphy_name(hw->wiphy)); + wiphy_debug(hw->wiphy, + "release an RX reorder frame due to timeout on earlier frames\n"); #endif ieee80211_release_reorder_frame(hw, tid_agg_rx, j, frames); @@ -2698,10 +2696,9 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, skb_new = skb_copy(skb, GFP_ATOMIC); if (!skb_new) { if (net_ratelimit()) - printk(KERN_DEBUG "%s: failed to copy " - "multicast frame for %s\n", - wiphy_name(local->hw.wiphy), - prev->name); + wiphy_debug(local->hw.wiphy, + "failed to copy multicast frame for %s\n", + prev->name); goto next; } ieee80211_invoke_rx_handlers(prev, &rx, skb_new); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 6d86f0c1ad04..687077e49dc6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -174,8 +174,7 @@ static void __sta_info_free(struct ieee80211_local *local, } #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Destroyed STA %pM\n", - wiphy_name(local->hw.wiphy), sta->sta.addr); + wiphy_debug(local->hw.wiphy, "Destroyed STA %pM\n", sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ kfree(sta); @@ -262,8 +261,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Allocated STA %pM\n", - wiphy_name(local->hw.wiphy), sta->sta.addr); + wiphy_debug(local->hw.wiphy, "Allocated STA %pM\n", sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ #ifdef CONFIG_MAC80211_MESH @@ -300,8 +298,9 @@ static int sta_info_finish_insert(struct sta_info *sta, bool async) sta->uploaded = true; #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (async) - printk(KERN_DEBUG "%s: Finished adding IBSS STA %pM\n", - wiphy_name(local->hw.wiphy), sta->sta.addr); + wiphy_debug(local->hw.wiphy, + "Finished adding IBSS STA %pM\n", + sta->sta.addr); #endif } @@ -411,8 +410,8 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) spin_unlock_irqrestore(&local->sta_lock, flags); #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Added IBSS STA %pM\n", - wiphy_name(local->hw.wiphy), sta->sta.addr); + wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", + sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ ieee80211_queue_work(&local->hw, &local->sta_finish_work); @@ -459,8 +458,7 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) } #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Inserted STA %pM\n", - wiphy_name(local->hw.wiphy), sta->sta.addr); + wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ /* move reference to rcu-protected */ @@ -690,8 +688,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) #endif #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Removed STA %pM\n", - wiphy_name(local->hw.wiphy), sta->sta.addr); + wiphy_debug(local->hw.wiphy, "Removed STA %pM\n", sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ cancel_work_sync(&sta->drv_unblock_wk); diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 67a35841bef0..571b32bfc54c 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -114,11 +114,10 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (net_ratelimit()) - printk(KERN_DEBUG "%s: dropped TX filtered frame, " - "queue_len=%d PS=%d @%lu\n", - wiphy_name(local->hw.wiphy), - skb_queue_len(&sta->tx_filtered), - !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); + wiphy_debug(local->hw.wiphy, + "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n", + skb_queue_len(&sta->tx_filtered), + !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); #endif dev_kfree_skb(skb); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index bc4fefc91663..d51ec74cfb62 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -351,8 +351,8 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) local->total_ps_buffered = total; #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n", - wiphy_name(local->hw.wiphy), purged); + wiphy_debug(local->hw.wiphy, "PS buffers full - purged %d frames\n", + purged); #endif } @@ -1513,8 +1513,8 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, I802_DEBUG_INC(local->tx_expand_skb_head); if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { - printk(KERN_DEBUG "%s: failed to reallocate TX buffer\n", - wiphy_name(local->hw.wiphy)); + wiphy_debug(local->hw.wiphy, + "failed to reallocate TX buffer\n"); return -ENOMEM; } -- cgit v1.2.3-59-g8ed1b From 9736ebfe39687f2edde9e97fc188f013a31048f6 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 21 Aug 2010 12:08:15 +0100 Subject: orinoco: Fix walking past the end of the buffer Fix walking past the end of the bitrate_table array in the case when the loop counter == BITRATE_TABLE_SIZE. Reported by: Denis Kirjanov Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/hw.c | 9 ++++++--- drivers/net/wireless/orinoco/wext.c | 11 +++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 077baa86756b..b4772c1c6135 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -762,14 +762,17 @@ int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate) case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */ case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */ for (i = 0; i < BITRATE_TABLE_SIZE; i++) - if (bitrate_table[i].intersil_txratectrl == val) + if (bitrate_table[i].intersil_txratectrl == val) { + *bitrate = bitrate_table[i].bitrate * 100000; break; + } - if (i >= BITRATE_TABLE_SIZE) + if (i >= BITRATE_TABLE_SIZE) { printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n", priv->ndev->name, val); + err = -EIO; + } - *bitrate = bitrate_table[i].bitrate * 100000; break; default: BUG(); diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index cf7be1eb6124..93505f93bf97 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -589,8 +589,15 @@ static int orinoco_ioctl_getrate(struct net_device *dev, /* If the interface is running we try to find more about the current mode */ - if (netif_running(dev)) - err = orinoco_hw_get_act_bitrate(priv, &bitrate); + if (netif_running(dev)) { + int act_bitrate; + int lerr; + + /* Ignore errors if we can't get the actual bitrate */ + lerr = orinoco_hw_get_act_bitrate(priv, &act_bitrate); + if (!lerr) + bitrate = act_bitrate; + } orinoco_unlock(priv, &flags); -- cgit v1.2.3-59-g8ed1b From 3a59babbee409fa5f1b2dd8a14c40803b5eb288b Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 21 Aug 2010 12:13:45 +0100 Subject: orinoco: update status in MAINTAINERS Signed-off-by: David Kilroy Cc: Pavel Roskin Cc: David Gibson Signed-off-by: John W. Linville --- MAINTAINERS | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 44620aebb369..a41e3a7b18f3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4265,13 +4265,12 @@ F: Documentation/filesystems/dlmfs.txt F: fs/ocfs2/ ORINOCO DRIVER -M: Pavel Roskin -M: David Gibson L: linux-wireless@vger.kernel.org L: orinoco-users@lists.sourceforge.net L: orinoco-devel@lists.sourceforge.net +W: http://linuxwireless.org/en/users/Drivers/orinoco W: http://www.nongnu.org/orinoco/ -S: Maintained +S: Orphan F: drivers/net/wireless/orinoco/ OSD LIBRARY and FILESYSTEM -- cgit v1.2.3-59-g8ed1b From ff67bb86d448c26cb9110e9681669dc4a8aa5e0a Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 21 Aug 2010 07:23:29 -0700 Subject: mac80211: fix warning for un-used parameter mesh_hdr only used when CONFIG_MAC80211_MESH is defined Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- net/mac80211/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d51ec74cfb62..a6ac9fd248f2 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1701,7 +1701,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, u16 ethertype, hdrlen, meshhdrlen = 0; __le16 fc; struct ieee80211_hdr hdr; - struct ieee80211s_hdr mesh_hdr; + struct ieee80211s_hdr mesh_hdr __maybe_unused; const u8 *encaps_data; int encaps_len, skip_header_bytes; int nh_pos, h_pos; -- cgit v1.2.3-59-g8ed1b From 2738bd682df546f34654ed3d59dfc9ebe8d04979 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 21 Aug 2010 16:39:01 -0400 Subject: mac80211: trivial spelling fixes Fix spelling and readability of a few lines of kernel doc: s/issueing/issuing/g s/approriate/appropriate/g s/supported by simply/supported simply by/ s/IEEE80211_HW_BEACON_FILTERING/IEEE80211_HW_BEACON_FILTER/g Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- include/net/mac80211.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 2a1811366076..dcc8c2bf986e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1242,8 +1242,8 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * %IEEE80211_CONF_PS flag enabled means that the powersave mode defined in * IEEE 802.11-2007 section 11.2 is enabled. This is not to be confused * with hardware wakeup and sleep states. Driver is responsible for waking - * up the hardware before issueing commands to the hardware and putting it - * back to sleep at approriate times. + * up the hardware before issuing commands to the hardware and putting it + * back to sleep at appropriate times. * * When PS is enabled, hardware needs to wakeup for beacons and receive the * buffered multicast/broadcast frames after the beacon. Also it must be @@ -1264,7 +1264,7 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * there's data traffic and still saving significantly power in idle * periods. * - * Dynamic powersave is supported by simply mac80211 enabling and disabling + * Dynamic powersave is simply supported by mac80211 enabling and disabling * PS based on traffic. Driver needs to only set %IEEE80211_HW_SUPPORTS_PS * flag and mac80211 will handle everything automatically. Additionally, * hardware having support for the dynamic PS feature may set the @@ -2458,7 +2458,7 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, * * @vif: &struct ieee80211_vif pointer from the add_interface callback. * - * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTERING and + * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTER and * %IEEE80211_CONF_PS is set, the driver needs to inform whenever the * hardware is not receiving beacons with this function. */ @@ -2469,7 +2469,7 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif); * * @vif: &struct ieee80211_vif pointer from the add_interface callback. * - * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTERING, and + * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTER, and * %IEEE80211_CONF_PS and %IEEE80211_HW_CONNECTION_MONITOR are set, the driver * needs to inform if the connection to the AP has been lost. * -- cgit v1.2.3-59-g8ed1b From 8801df86d79b1ffda94e3b937bc19bbe9a66557d Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 21 Aug 2010 16:39:02 -0400 Subject: ath5k: trivial spelling fixes Fix some comments: s/transmition/transmission/ s/puting/putting/ Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/pcu.c | 4 ++-- drivers/net/wireless/ath/ath5k/phy.c | 2 +- drivers/net/wireless/ath/ath5k/reset.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 3fef5931ec3a..bb2e21553d1b 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -137,11 +137,11 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) * ath5k_hw_set_ack_bitrate - set bitrate for ACKs * * @ah: The &struct ath5k_hw - * @high: Flag to determine if we want to use high transmition rate + * @high: Flag to determine if we want to use high transmission rate * for ACKs or not * * If high flag is set, we tell hw to use a set of control rates based on - * the current transmition rate (check out control_rates array inside reset.c). + * the current transmission rate (check out control_rates array inside reset.c). * If not hw just uses the lowest rate available for the current modulation * scheme being used (1Mbit for CCK and 6Mbits for OFDM). */ diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index c7c446592374..8c27a3644d2f 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -2987,7 +2987,7 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, /* - * Set transmition power + * Set transmission power */ int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 4154959125b6..58912cd762d9 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -326,7 +326,7 @@ commit: * register). After this MAC and Baseband are * disabled and a full reset is needed to come * back. This way we save as much power as possible - * without puting the card on full sleep. + * without putting the card on full sleep. */ int ath5k_hw_on_hold(struct ath5k_hw *ah) { @@ -344,7 +344,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) /* * Put chipset on warm reset... * - * Note: puting PCI core on warm reset on PCI-E cards + * Note: putting PCI core on warm reset on PCI-E cards * results card to hang and always return 0xffff... so * we ingore that flag for PCI-E cards. On PCI cards * this flag gets cleared after 64 PCI clocks. @@ -400,7 +400,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) /* * Put chipset on warm reset... * - * Note: puting PCI core on warm reset on PCI-E cards + * Note: putting PCI core on warm reset on PCI-E cards * results card to hang and always return 0xffff... so * we ingore that flag for PCI-E cards. On PCI cards * this flag gets cleared after 64 PCI clocks. -- cgit v1.2.3-59-g8ed1b From b4c52612069c2756ad7506754765bfee57315efe Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 21 Aug 2010 16:39:03 -0400 Subject: ath5k: log descriptor chains at a new debug level Descriptors are currently logged with ATH5K_DEBUG_RESET, which isn't really apt, and also means we can't see just the descriptor setup or just the resets. Add a new debug level just for that. Acked-by: Bruno Randolf Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/debug.c | 5 +++-- drivers/net/wireless/ath/ath5k/debug.h | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 4cccc29964f6..1b7c6d7fde93 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -312,6 +312,7 @@ static const struct { { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, + { ATH5K_DEBUG_DESC, "desc", "descriptor chains" }, { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, }; @@ -955,7 +956,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) struct ath5k_rx_status rs = {}; int status; - if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) + if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC))) return; printk(KERN_DEBUG "rxdp %x, rxlink %p\n", @@ -997,7 +998,7 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) struct ath5k_tx_status ts = {}; int done; - if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) + if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC))) return; done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts); diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 606ae94a9157..9b22722a95f0 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -95,6 +95,7 @@ struct ath5k_dbg_info { * @ATH5K_DEBUG_DUMP_TX: print transmit skb content * @ATH5K_DEBUG_DUMPBANDS: dump bands * @ATH5K_DEBUG_TRACE: trace function calls + * @ATH5K_DEBUG_DESC: descriptor setup * @ATH5K_DEBUG_ANY: show at any debug level * * The debug level is used to control the amount and type of debugging output @@ -117,6 +118,7 @@ enum ath5k_debug_level { ATH5K_DEBUG_DUMP_TX = 0x00000200, ATH5K_DEBUG_DUMPBANDS = 0x00000400, ATH5K_DEBUG_ANI = 0x00002000, + ATH5K_DEBUG_DESC = 0x00004000, ATH5K_DEBUG_ANY = 0xffffffff }; -- cgit v1.2.3-59-g8ed1b From d7065c305544d575c3697b46ddbc8601de03e46f Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 22 Aug 2010 00:00:14 +0200 Subject: p54spi: Kconfig option for config blob This patch adds an Kconfig option, which allows the user to select, whenever he/she wants to include a 4k blob for generic calibration and interface values into the driver, or cut the module size by about 15 to 20%. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/Kconfig | 17 +++++++++++++++++ drivers/net/wireless/p54/p54spi.c | 7 ++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig index 60a930e45a8b..e5f45cb2a7a2 100644 --- a/drivers/net/wireless/p54/Kconfig +++ b/drivers/net/wireless/p54/Kconfig @@ -49,6 +49,23 @@ config P54_SPI If you choose to build a module, it'll be called p54spi. +config P54_SPI_DEFAULT_EEPROM + bool "Include fallback EEPROM blob" + depends on P54_SPI + default n + ---help--- + Unlike the PCI or USB devices, the SPI variants don't have + a dedicated EEPROM chip to store all device specific values + for calibration, country and interface settings. + + The driver will try to load the image "3826.eeprom", if the + file is put at the right place. (usually /lib/firmware.) + + Only if this request fails, this option will provide a + backup set of generic values to get the device working. + + Enabling this option adds about 4k to p54spi. + config P54_LEDS bool depends on P54_COMMON && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = P54_COMMON) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 087bf0698a5a..156e57dbd2cf 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -32,11 +32,14 @@ #include #include "p54spi.h" -#include "p54spi_eeprom.h" #include "p54.h" #include "lmac.h" +#ifdef CONFIG_P54_SPI_DEFAULT_EEPROM +#include "p54spi_eeprom.h" +#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */ + MODULE_FIRMWARE("3826.arm"); MODULE_ALIAS("stlc45xx"); @@ -195,9 +198,11 @@ static int p54spi_request_eeprom(struct ieee80211_hw *dev) ret = request_firmware(&eeprom, "3826.eeprom", &priv->spi->dev); if (ret < 0) { +#ifdef CONFIG_P54_SPI_DEFAULT_EEPROM dev_info(&priv->spi->dev, "loading default eeprom...\n"); ret = p54_parse_eeprom(dev, (void *) p54spi_eeprom, sizeof(p54spi_eeprom)); +#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */ } else { dev_info(&priv->spi->dev, "loading user eeprom...\n"); ret = p54_parse_eeprom(dev, (void *) eeprom->data, -- cgit v1.2.3-59-g8ed1b From 31c726f0963cd022680dacd0c9f0036d7e12a8b2 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 22 Aug 2010 22:46:15 +0300 Subject: wl1251: update my email address I use now my adurom.com address. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- MAINTAINERS | 2 +- drivers/net/wireless/wl12xx/wl1251_main.c | 2 +- drivers/net/wireless/wl12xx/wl1251_sdio.c | 2 +- drivers/net/wireless/wl12xx/wl1251_spi.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a41e3a7b18f3..2fde65d66f51 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6302,7 +6302,7 @@ S: Maintained F: drivers/input/misc/wistron_btns.c WL1251 WIRELESS DRIVER -M: Kalle Valo +M: Kalle Valo L: linux-wireless@vger.kernel.org W: http://wireless.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index c81e95b45c14..c7cffbafdf66 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1437,5 +1437,5 @@ EXPORT_SYMBOL_GPL(wl1251_free_hw); MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core"); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kalle Valo "); +MODULE_AUTHOR("Kalle Valo "); MODULE_FIRMWARE(WL1251_FW_NAME); diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index b901b6135654..c0b68b0a9aa8 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c @@ -339,4 +339,4 @@ module_init(wl1251_sdio_init); module_exit(wl1251_sdio_exit); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kalle Valo "); +MODULE_AUTHOR("Kalle Valo "); diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c index 27fdfaaeb074..a6435fb66339 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl12xx/wl1251_spi.c @@ -344,5 +344,5 @@ module_init(wl1251_spi_init); module_exit(wl1251_spi_exit); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kalle Valo "); +MODULE_AUTHOR("Kalle Valo "); MODULE_ALIAS("spi:wl1251"); -- cgit v1.2.3-59-g8ed1b From 4c5f7d7a1e6cf20ad515dad8a63c0813fac5bcea Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 22 Aug 2010 22:46:28 +0300 Subject: wl12xx: change contact person for the include file Luciano should be the contact person for the include/linux/spi/wl12xx.h file. Signed-off-by: Kalle Valo Acked-by: Luciano Coelho Signed-off-by: John W. Linville --- include/linux/spi/wl12xx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/spi/wl12xx.h b/include/linux/spi/wl12xx.h index a223ecbc71ef..a20bccf0b5c2 100644 --- a/include/linux/spi/wl12xx.h +++ b/include/linux/spi/wl12xx.h @@ -3,7 +3,7 @@ * * Copyright (C) 2009 Nokia Corporation * - * Contact: Kalle Valo + * Contact: Luciano Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License -- cgit v1.2.3-59-g8ed1b From fe71559239b2227649198f032daa5a877204771b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Aug 2010 13:02:03 -0700 Subject: MAINTAINERS: add info for include/linux/spi/wl12xx.h Signed-off-by: Joe Perches Acked-by: Luciano Coelho Signed-off-by: John W. Linville --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2fde65d66f51..4a6d93648b9c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6317,6 +6317,7 @@ W: http://wireless.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git S: Maintained F: drivers/net/wireless/wl12xx/wl1271* +F: include/linux/spi/wl12xx.h WL3501 WIRELESS PCMCIA CARD DRIVER M: Arnaldo Carvalho de Melo -- cgit v1.2.3-59-g8ed1b From ba0492cf904629f7900fc213ee729f23a0084ad6 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 22 Aug 2010 22:46:43 +0300 Subject: wl1251: remove copyright contact person As my nokia address doesn't work anymore, it's better just to remove the copyright contact altogether. We have MODULE_AUTHOR() scripts for these anyway. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251.h | 2 -- drivers/net/wireless/wl12xx/wl1251_acx.h | 2 -- drivers/net/wireless/wl12xx/wl1251_boot.c | 2 -- drivers/net/wireless/wl12xx/wl1251_boot.h | 2 -- drivers/net/wireless/wl12xx/wl1251_cmd.h | 2 -- drivers/net/wireless/wl12xx/wl1251_debugfs.c | 2 -- drivers/net/wireless/wl12xx/wl1251_debugfs.h | 2 -- drivers/net/wireless/wl12xx/wl1251_event.c | 2 -- drivers/net/wireless/wl12xx/wl1251_event.h | 2 -- drivers/net/wireless/wl12xx/wl1251_init.c | 2 -- drivers/net/wireless/wl12xx/wl1251_init.h | 2 -- drivers/net/wireless/wl12xx/wl1251_io.c | 2 -- drivers/net/wireless/wl12xx/wl1251_main.c | 2 -- drivers/net/wireless/wl12xx/wl1251_ps.c | 2 -- drivers/net/wireless/wl12xx/wl1251_ps.h | 2 -- drivers/net/wireless/wl12xx/wl1251_reg.h | 2 -- drivers/net/wireless/wl12xx/wl1251_rx.c | 2 -- drivers/net/wireless/wl12xx/wl1251_rx.h | 2 -- drivers/net/wireless/wl12xx/wl1251_spi.c | 2 -- drivers/net/wireless/wl12xx/wl1251_spi.h | 2 -- drivers/net/wireless/wl12xx/wl1251_tx.c | 2 -- drivers/net/wireless/wl12xx/wl1251_tx.h | 2 -- 22 files changed, 44 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 6b942a28e6a5..9bc4fea3315a 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h @@ -4,8 +4,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008-2009 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index a8845b8f2451..c7cc5c1e8a75 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h @@ -4,8 +4,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 5e65f47fda8a..468b47b0328a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c @@ -3,8 +3,6 @@ * * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.h b/drivers/net/wireless/wl12xx/wl1251_boot.h index 90063697e8f2..7661bc5e4662 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.h +++ b/drivers/net/wireless/wl12xx/wl1251_boot.h @@ -3,8 +3,6 @@ * * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h index 60d7e522486c..e5c74c631374 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h @@ -4,8 +4,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/drivers/net/wireless/wl12xx/wl1251_debugfs.c index 5e4465ac08fa..6ffe4cd58561 100644 --- a/drivers/net/wireless/wl12xx/wl1251_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1251_debugfs.c @@ -3,8 +3,6 @@ * * Copyright (C) 2009 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.h b/drivers/net/wireless/wl12xx/wl1251_debugfs.h index 6dc3d080853c..b3417c02a218 100644 --- a/drivers/net/wireless/wl12xx/wl1251_debugfs.h +++ b/drivers/net/wireless/wl12xx/wl1251_debugfs.h @@ -3,8 +3,6 @@ * * Copyright (C) 2009 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c index e093a1c5a205..00c3e648d93f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.c +++ b/drivers/net/wireless/wl12xx/wl1251_event.c @@ -4,8 +4,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_event.h b/drivers/net/wireless/wl12xx/wl1251_event.h index ec456474a842..30eb5d150bf7 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.h +++ b/drivers/net/wireless/wl12xx/wl1251_event.h @@ -4,8 +4,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c index b538bdd7b320..c5daec05d9ee 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.c +++ b/drivers/net/wireless/wl12xx/wl1251_init.c @@ -3,8 +3,6 @@ * * Copyright (C) 2009 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl12xx/wl1251_init.h index 269cefb3e7d4..543f17582ead 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.h +++ b/drivers/net/wireless/wl12xx/wl1251_init.h @@ -3,8 +3,6 @@ * * Copyright (C) 2009 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_io.c b/drivers/net/wireless/wl12xx/wl1251_io.c index f1c232e0887f..ad6ca68b303f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_io.c +++ b/drivers/net/wireless/wl12xx/wl1251_io.c @@ -3,8 +3,6 @@ * * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index c7cffbafdf66..edd4845c3707 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -3,8 +3,6 @@ * * Copyright (C) 2008-2009 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c index b55cb2bd459a..0b997bdfec09 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c @@ -3,8 +3,6 @@ * * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.h b/drivers/net/wireless/wl12xx/wl1251_ps.h index c688ac57aee4..98ed6c237561 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.h +++ b/drivers/net/wireless/wl12xx/wl1251_ps.h @@ -7,8 +7,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h index d16edd9bf06c..a5809019c5c1 100644 --- a/drivers/net/wireless/wl12xx/wl1251_reg.h +++ b/drivers/net/wireless/wl12xx/wl1251_reg.h @@ -4,8 +4,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index 1b6294b3b996..25764592a596 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c @@ -4,8 +4,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.h b/drivers/net/wireless/wl12xx/wl1251_rx.h index da4e53406a0e..4448f635a4d8 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.h +++ b/drivers/net/wireless/wl12xx/wl1251_rx.h @@ -4,8 +4,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c index a6435fb66339..334ded9881c0 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl12xx/wl1251_spi.c @@ -3,8 +3,6 @@ * * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl12xx/wl1251_spi.h index 2e273a97e7f3..7dcf3cf7ae40 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.h +++ b/drivers/net/wireless/wl12xx/wl1251_spi.h @@ -4,8 +4,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index 6634b3e27cfc..6d618fb1fd95 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c @@ -4,8 +4,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h index f40eeb37f5aa..96011e78cd5a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.h +++ b/drivers/net/wireless/wl12xx/wl1251_tx.h @@ -4,8 +4,6 @@ * Copyright (c) 1998-2007 Texas Instruments Incorporated * Copyright (C) 2008 Nokia Corporation * - * Contact: Kalle Valo - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. -- cgit v1.2.3-59-g8ed1b From 5effdf18aa10c3683094140cf893c399d581d39f Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 22 Aug 2010 22:47:02 +0300 Subject: wl1251: move include guard after the license Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_ps.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.h b/drivers/net/wireless/wl12xx/wl1251_ps.h index 98ed6c237561..e5db81fc1dfc 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.h +++ b/drivers/net/wireless/wl12xx/wl1251_ps.h @@ -1,6 +1,3 @@ -#ifndef __WL1251_PS_H__ -#define __WL1251_PS_H__ - /* * This file is part of wl1251 * @@ -23,6 +20,9 @@ * */ +#ifndef __WL1251_PS_H__ +#define __WL1251_PS_H__ + #include "wl1251.h" #include "wl1251_acx.h" -- cgit v1.2.3-59-g8ed1b From 049fbfeeb5c7edb260848a89af4895e3dabfa77e Mon Sep 17 00:00:00 2001 From: RafaÅ‚ MiÅ‚ecki Date: Sun, 22 Aug 2010 21:47:32 +0200 Subject: b43: N-PHY: add missing phyrxchain setting and fix warning in RX core function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index a0a6554a76d1..5f0ce35bbe27 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -3092,6 +3092,8 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) struct b43_phy_n *nphy = phy->n; u16 buf[16]; + nphy->phyrxchain = mask; + if (0 /* FIXME clk */) return; @@ -3103,7 +3105,7 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN, (mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT); - if (mask & 0x3 != 0x3) { + if ((mask & 0x3) != 0x3) { b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1); if (dev->phy.rev >= 3) { /* TODO */ -- cgit v1.2.3-59-g8ed1b From 11791a6f7534906b4a01ffb54ba0b02ca39398ef Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 22 Aug 2010 22:41:33 +0200 Subject: p54usb: fix off-by-one on !CONFIG_PM The ISL3887 chip needs a USB reset, whenever the usb-frontend module "p54usb" is reloaded. This patch fixes an off-by-one bug, if the user is running a kernel without the CONFIG_PM option set and for some reason (e.g.: compat-wireless) wants to switch between different p54usb modules. Cc: Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index ad595958b7df..063248b35069 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -930,8 +930,8 @@ static int __devinit p54u_probe(struct usb_interface *intf, #ifdef CONFIG_PM /* ISL3887 needs a full reset on resume */ udev->reset_resume = 1; +#endif /* CONFIG_PM */ err = p54u_device_reset(dev); -#endif priv->hw_type = P54U_3887; dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); -- cgit v1.2.3-59-g8ed1b From 258086a48b766d12a500f98834654ffa927ca475 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 22 Aug 2010 23:48:25 +0200 Subject: mac80211: cancel restart_work in ieee80211_unregister_hw Unlike most other workqueue-tasks, the restart_work is not scheduled onto mac80211's private per-interface workqueue, but onto one of the system-wide workqueues. Therefore the mac80211-stack has to cancel any pending restarts, before destroying the shared device context and handing back the memory. Otherwise - under very unlucky circumstances - there could be a stale work- item left, because some other kernel component might have delayed the execution of ieee80211_restart_work for too long. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5756fba63d48..28415de5f476 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -807,6 +807,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) rtnl_unlock(); + cancel_work_sync(&local->restart_work); cancel_work_sync(&local->reconfig_filter); ieee80211_clear_tx_pending(local); -- cgit v1.2.3-59-g8ed1b From 5c673fbf193e272c8c786931b31f23090ab3cb9d Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:56:52 -0700 Subject: iwlwifi: update out-of-date comments No functional changes, update comments to match current file structure Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 2 +- drivers/net/wireless/iwlwifi/iwl-5000-hw.h | 2 +- drivers/net/wireless/iwlwifi/iwl-6000-hw.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 7c731a793632..a4a3194779d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -62,7 +62,7 @@ *****************************************************************************/ /* * Please use this file (iwl-3945-hw.h) only for hardware-related definitions. - * Please use iwl-3945-commands.h for uCode API definitions. + * Please use iwl-commands.h for uCode API definitions. * Please use iwl-3945.h for driver implementation definitions. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 146e6431ae95..3975e45e7500 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -62,7 +62,7 @@ *****************************************************************************/ /* * Please use this file (iwl-5000-hw.h) only for hardware-related definitions. - * Use iwl-5000-commands.h for uCode API definitions. + * Use iwl-commands.h for uCode API definitions. */ #ifndef __iwl_5000_hw_h__ diff --git a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h index ddba39999997..47891e16a758 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h @@ -62,7 +62,7 @@ *****************************************************************************/ /* * Please use this file (iwl-6000-hw.h) only for hardware-related definitions. - * Use iwl-5000-commands.h for uCode API definitions. + * Use iwl-commands.h for uCode API definitions. */ #ifndef __iwl_6000_hw_h__ -- cgit v1.2.3-59-g8ed1b From 767d055d6a85435bf1d5e63a5097402a5399cfdc Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:56:53 -0700 Subject: iwlwifi: comments cleanup No code or function changes, just some cleanup work for out-of-date comments Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 62 +++++++++++++++-------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 4083e4430827..e2f3616f5b8f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -62,7 +62,7 @@ *****************************************************************************/ /* * Please use this file (iwl-commands.h) only for uCode API definitions. - * Please use iwl-4965-hw.h for hardware-related definitions. + * Please use iwl-xxxx-hw.h for hardware-related definitions. * Please use iwl-dev.h for driver implementation definitions. */ @@ -1056,7 +1056,8 @@ struct sta_id_modify { * * The device contains an internal table of per-station information, * with info on security keys, aggregation parameters, and Tx rates for - * initial Tx attempt and any retries (4965 uses REPLY_TX_LINK_QUALITY_CMD, + * initial Tx attempt and any retries (agn devices uses + * REPLY_TX_LINK_QUALITY_CMD, * 3945 uses REPLY_RATE_SCALE to set up rate tables). * * REPLY_ADD_STA sets up the table entry for one station, either creating @@ -1427,12 +1428,12 @@ struct iwl_rx_mpdu_res_start { * uCode handles all timing and protocol related to control frames * (RTS/CTS/ACK), based on flags in the Tx command. uCode and Tx scheduler * handle reception of block-acks; uCode updates the host driver via - * REPLY_COMPRESSED_BA (4965). + * REPLY_COMPRESSED_BA. * * uCode handles retrying Tx when an ACK is expected but not received. * This includes trying lower data rates than the one requested in the Tx * command, as set up by the REPLY_RATE_SCALE (for 3945) or - * REPLY_TX_LINK_QUALITY_CMD (4965). + * REPLY_TX_LINK_QUALITY_CMD (agn). * * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD. * This command must be executed after every RXON command, before Tx can occur. @@ -1468,7 +1469,7 @@ struct iwl_rx_mpdu_res_start { * Set this for unicast frames, but not broadcast/multicast. */ #define TX_CMD_FLG_ACK_MSK cpu_to_le32(1 << 3) -/* For 4965: +/* For agn devices: * 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD). * Tx command's initial_rate_index indicates first rate to try; * uCode walks through table for additional Tx attempts. @@ -1487,7 +1488,7 @@ struct iwl_rx_mpdu_res_start { */ #define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7) -/* Tx antenna selection field; used only for 3945, reserved (0) for 4965. +/* Tx antenna selection field; used only for 3945, reserved (0) for agn devices. * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */ #define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00) #define TX_CMD_FLG_ANT_A_MSK cpu_to_le32(1 << 8) @@ -1870,9 +1871,10 @@ enum { * frame in this new agg block failed in previous agg block(s). * * Note that, for aggregation, ACK (block-ack) status is not delivered here; - * block-ack has not been received by the time the 4965 records this status. + * block-ack has not been received by the time the agn device records + * this status. * This status relates to reasons the tx might have been blocked or aborted - * within the sending station (this 4965), rather than whether it was + * within the sending station (this agn device), rather than whether it was * received successfully by the destination station. */ struct agg_tx_status { @@ -2140,14 +2142,16 @@ struct iwl_link_qual_agg_params { /* * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response) * - * For 4965 only; 3945 uses REPLY_RATE_SCALE. + * For agn devices only; 3945 uses REPLY_RATE_SCALE. * - * Each station in the 4965's internal station table has its own table of 16 + * Each station in the agn device's internal station table has its own table + * of 16 * Tx rates and modulation modes (e.g. legacy/SISO/MIMO) for retrying Tx when * an ACK is not received. This command replaces the entire table for * one station. * - * NOTE: Station must already be in 4965's station table. Use REPLY_ADD_STA. + * NOTE: Station must already be in agn device's station table. + * Use REPLY_ADD_STA. * * The rate scaling procedures described below work well. Of course, other * procedures are possible, and may work better for particular environments. @@ -2184,12 +2188,12 @@ struct iwl_link_qual_agg_params { * * ACCUMULATING HISTORY * - * The rate scaling algorithm for 4965, as implemented in Linux driver, uses - * two sets of frame Tx success history: One for the current/active modulation - * mode, and one for a speculative/search mode that is being attempted. If the - * speculative mode turns out to be more effective (i.e. actual transfer - * rate is better), then the driver continues to use the speculative mode - * as the new current active mode. + * The rate scaling algorithm for agn devices, as implemented in Linux driver, + * uses two sets of frame Tx success history: One for the current/active + * modulation mode, and one for a speculative/search mode that is being + * attempted. If the speculative mode turns out to be more effective (i.e. + * actual transfer rate is better), then the driver continues to use the + * speculative mode as the new current active mode. * * Each history set contains, separately for each possible rate, data for a * sliding window of the 62 most recent tx attempts at that rate. The data @@ -2200,12 +2204,12 @@ struct iwl_link_qual_agg_params { * The driver uses the bit map to remove successes from the success sum, as * the oldest tx attempts fall out of the window. * - * When the 4965 makes multiple tx attempts for a given frame, each attempt - * might be at a different rate, and have different modulation characteristics - * (e.g. antenna, fat channel, short guard interval), as set up in the rate - * scaling table in the Link Quality command. The driver must determine - * which rate table entry was used for each tx attempt, to determine which - * rate-specific history to update, and record only those attempts that + * When the agn device makes multiple tx attempts for a given frame, each + * attempt might be at a different rate, and have different modulation + * characteristics (e.g. antenna, fat channel, short guard interval), as set + * up in the rate scaling table in the Link Quality command. The driver must + * determine which rate table entry was used for each tx attempt, to determine + * which rate-specific history to update, and record only those attempts that * match the modulation characteristics of the history set. * * When using block-ack (aggregation), all frames are transmitted at the same @@ -2335,7 +2339,7 @@ struct iwl_link_quality_cmd { /* * Rate info; when using rate-scaling, Tx command's initial_rate_index * specifies 1st Tx rate attempted, via index into this table. - * 4965 works its way through table when retrying Tx. + * agn devices works its way through table when retrying Tx. */ struct { __le32 rate_n_flags; /* RATE_MCS_*, IWL_RATE_* */ @@ -2371,7 +2375,7 @@ struct iwl_link_quality_cmd { /* * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) * - * 3945 and 4965 support hardware handshake with Bluetooth device on + * 3945 and agn devices support hardware handshake with Bluetooth device on * same platform. Bluetooth device alerts wireless device when it will Tx; * wireless device can delay or kill its own Tx to accommodate. */ @@ -2572,7 +2576,7 @@ struct iwl_powertable_cmd { /* * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command) - * 3945 and 4965 identical. + * all devices identical. */ struct iwl_sleep_notification { u8 pm_sleep_mode; @@ -2583,7 +2587,7 @@ struct iwl_sleep_notification { __le32 bcon_timer; } __packed; -/* Sleep states. 3945 and 4965 identical. */ +/* Sleep states. all devices identical. */ enum { IWL_PM_NO_SLEEP = 0, IWL_PM_SLP_MAC = 1, @@ -3270,7 +3274,7 @@ struct statistics_general_bt { /* * REPLY_STATISTICS_CMD = 0x9c, - * 3945 and 4965 identical. + * all devices identical. * * This command triggers an immediate response containing uCode statistics. * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below. @@ -3608,7 +3612,7 @@ struct iwl_enhance_sensitivity_cmd { /** * REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response) * - * This command sets the relative gains of 4965's 3 radio receiver chains. + * This command sets the relative gains of agn device's 3 radio receiver chains. * * After the first association, driver should accumulate signal and noise * statistics from the STATISTICS_NOTIFICATIONs that follow the first 20 -- cgit v1.2.3-59-g8ed1b From 0288d237fff4cbe54879e3c3433ae5782874f98c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 07:56:54 -0700 Subject: iwlwifi: add 6000g2b BT coexist API The new 6000g2b hardware requires a different bluetooth coexist implementation on the host, this adds the command/notification definitions for it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 76 ++++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 3 ++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e2f3616f5b8f..78086ad6b72e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -173,6 +173,12 @@ enum { REPLY_RX_MPDU_CMD = 0xc1, REPLY_RX = 0xc3, REPLY_COMPRESSED_BA = 0xc5, + + /* BT Coex */ + REPLY_BT_COEX_PRIO_TABLE = 0xcc, + REPLY_BT_COEX_PROT_ENV = 0xcd, + REPLY_BT_COEX_PROFILE_NOTIF = 0xce, + REPLY_MAX = 0xff }; @@ -2896,6 +2902,12 @@ struct iwl_scanstart_notification { #define SCAN_OWNER_STATUS 0x1; #define MEASURE_OWNER_STATUS 0x2; +#define IWL_PROBE_STATUS_OK 0 +#define IWL_PROBE_STATUS_TX_FAILED BIT(0) +/* error statuses combined with TX_FAILED */ +#define IWL_PROBE_STATUS_FAIL_TTL BIT(1) +#define IWL_PROBE_STATUS_FAIL_BT BIT(2) + #define NUMBER_OF_STATISTICS 1 /* first __le32 is good CRC */ /* * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command) @@ -2903,7 +2915,8 @@ struct iwl_scanstart_notification { struct iwl_scanresults_notification { u8 channel; u8 band; - u8 reserved[2]; + u8 probe_status; + u8 num_probe_not_sent; /* not enough time to send */ __le32 tsf_low; __le32 tsf_high; __le32 statistics[NUMBER_OF_STATISTICS]; @@ -3968,6 +3981,66 @@ struct iwl_coex_event_resp { } __packed; +/****************************************************************************** + * Bluetooth Coexistence commands + * + *****************************************************************************/ + +/* + * BT Status notification + * REPLY_BT_COEX_PROFILE_NOTIF = 0xcb + */ +enum iwl_bt_coex_profile_traffic_load { + IWL_BT_COEX_TRAFFIC_LOAD_NONE = 0, + IWL_BT_COEX_TRAFFIC_LOAD_LOW = 1, + IWL_BT_COEX_TRAFFIC_LOAD_HIGH = 2, + IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS = 3, +/* + * There are no more even though below is a u8, the + * indication from the BT device only has two bits. + */ +}; + +struct iwl_bt_coex_profile_notif { + u8 uart_msg[8]; + u8 bt_status; /* 0 - off, 1 - on */ + u8 bt_traffic_load; /* 0 .. 3? */ + u8 bt_ci_compliance; /* 0 - not complied, 1 - complied */ + u8 reserved; +} __attribute__((packed)); + +#define IWL_BT_COEX_PRIO_SHARED_ANTENNA 0x1 +#define IWL_BT_COEX_PRIO_PRIO_MASK 0xe +#define IWL_BT_COEX_PRIO_PRIO_SHIFT 1 + +/* + * BT Coexistence Priority table + * REPLY_BT_COEX_PRIO_TABLE = 0xcc + */ +struct iwl_bt_coex_prio_table_cmd { + u8 init_calib_protection_cfg1, + init_calib_protection_cfg2, + init_calib_protection_lowprio_cfg1, + init_calib_protection_lowprio_cfg2, + init_calib_protection_highprio_cfg1, + init_calib_protection_highprio_cfg2, + dtim_protection_prio_cfg, + scan_52_protection_cfg, + scan_24_protection_cfg, + bc_mc_protection_cfg; + u8 reserved[6]; +} __attribute__((packed)); + +/* + * BT Protection Envelope + * REPLY_BT_COEX_PROT_ENV = 0xcd + */ +struct iwl_bt_coex_prot_env_cmd { + u8 open; /* 0 = closed, 1 = open */ + u8 type; /* 0 .. 15 */ + u8 reserved[2]; +} __attribute__((packed)); + /****************************************************************************** * (13) * Union of all expected notifications/responses: @@ -4007,6 +4080,7 @@ struct iwl_rx_packet { struct iwl_missed_beacon_notif missed_beacon; struct iwl_coex_medium_notification coex_medium_notif; struct iwl_coex_event_resp coex_event; + struct iwl_bt_coex_profile_notif bt_coex_profile_notif; __le32 status; u8 raw[0]; } u; diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 258d059ef41f..1f15b3aa8478 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -97,6 +97,9 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(REPLY_TX_POWER_DBM_CMD); IWL_CMD(TEMPERATURE_NOTIFICATION); IWL_CMD(TX_ANT_CONFIGURATION_CMD); + IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF); + IWL_CMD(REPLY_BT_COEX_PRIO_TABLE); + IWL_CMD(REPLY_BT_COEX_PROT_ENV); default: return "UNKNOWN"; -- cgit v1.2.3-59-g8ed1b From 670245ed4515cbc5e39e39d44965cb7add2c8aa9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 07:56:55 -0700 Subject: iwlagn: implement advance BT config command 6000g2b hardware implements advance bluetooth coexist command, implement base on the new API command strucutre. Also increment the API 5 to support the advance BT/WIfi coex. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 140 ++++++++++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-commands.h | 62 ++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 3 +- drivers/net/wireless/iwlwifi/iwl-core.h | 5 + 4 files changed, 203 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 9e390f698641..fc2eeb00c78c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -52,7 +52,7 @@ /* Highest firmware API version supported */ #define IWL6000_UCODE_API_MAX 4 #define IWL6050_UCODE_API_MAX 4 -#define IWL6000G2_UCODE_API_MAX 4 +#define IWL6000G2_UCODE_API_MAX 5 /* Lowest firmware API version supported */ #define IWL6000_UCODE_API_MIN 4 @@ -122,6 +122,120 @@ static void iwl6000_nic_config(struct iwl_priv *priv) priv->cfg->ops->lib->temp_ops.set_calib_version(priv); } +/* + * Macros to access the lookup table. + * + * The lookup table has 7 inputs: bt3_prio, bt3_txrx, bt_rf_act, wifi_req, + * wifi_prio, wifi_txrx and wifi_sh_ant_req. + * + * It has three outputs: WLAN_ACTIVE, WLAN_KILL and ANT_SWITCH + * + * The format is that "registers" 8 through 11 contain the WLAN_ACTIVE bits + * one after another in 32-bit registers, and "registers" 0 through 7 contain + * the WLAN_KILL and ANT_SWITCH bits interleaved (in that order). + * + * These macros encode that format. + */ +#define LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, wifi_req, wifi_prio, \ + wifi_txrx, wifi_sh_ant_req) \ + (bt3_prio | (bt3_txrx << 1) | (bt_rf_act << 2) | (wifi_req << 3) | \ + (wifi_prio << 4) | (wifi_txrx << 5) | (wifi_sh_ant_req << 6)) + +#define LUT_PTA_WLAN_ACTIVE_OP(lut, op, val) \ + lut[8 + ((val) >> 5)] op (cpu_to_le32(BIT((val) & 0x1f))) +#define LUT_TEST_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + (!!(LUT_PTA_WLAN_ACTIVE_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx,\ + bt_rf_act, wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)))) +#define LUT_SET_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + LUT_PTA_WLAN_ACTIVE_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, \ + bt_rf_act, wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) +#define LUT_CLEAR_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + LUT_PTA_WLAN_ACTIVE_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, \ + bt_rf_act, wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) + +#define LUT_WLAN_KILL_OP(lut, op, val) \ + lut[(val) >> 4] op (cpu_to_le32(BIT(((val) << 1) & 0x1e))) +#define LUT_TEST_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + (!!(LUT_WLAN_KILL_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)))) +#define LUT_SET_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + LUT_WLAN_KILL_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) +#define LUT_CLEAR_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + LUT_WLAN_KILL_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) + +#define LUT_ANT_SWITCH_OP(lut, op, val) \ + lut[(val) >> 4] op (cpu_to_le32(BIT((((val) << 1) & 0x1e) + 1))) +#define LUT_TEST_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + (!!(LUT_ANT_SWITCH_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)))) +#define LUT_SET_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + LUT_ANT_SWITCH_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) +#define LUT_CLEAR_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + LUT_ANT_SWITCH_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) + +static const __le32 iwl6000g2b_def_3w_lookup[12] = { + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaeaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xcc00ff28), + cpu_to_le32(0x0000aaaa), + cpu_to_le32(0xcc00aaaa), + cpu_to_le32(0x0000aaaa), + cpu_to_le32(0xc0004000), + cpu_to_le32(0x00004000), + cpu_to_le32(0xf0005000), + cpu_to_le32(0xf0004000), +}; + +static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) +{ + struct iwl6000g2b_bt_cmd bt_cmd = { + .prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, + .max_kill = IWL6000G2B_BT_MAX_KILL_DEFAULT, + .bt3_timer_t7_value = IWL6000G2B_BT3_T7_DEFAULT, + .kill_ack_mask = IWL6000G2B_BT_KILL_ACK_MASK_DEFAULT, + .kill_cts_mask = IWL6000G2B_BT_KILL_CTS_MASK_DEFAULT, + .bt3_prio_sample_time = IWL6000G2B_BT3_PRIO_SAMPLE_DEFAULT, + .bt3_timer_t2_value = IWL6000G2B_BT3_T2_DEFAULT, + .valid = IWL6000G2B_BT_VALID_ENABLE_FLAGS, + }; + + BUILD_BUG_ON(sizeof(iwl6000g2b_def_3w_lookup) != + sizeof(bt_cmd.bt3_lookup_table)); + + if (!bt_coex_active) { + bt_cmd.flags = 0; + } else { + bt_cmd.flags = IWL6000G2B_BT_FLAG_CHANNEL_INHIBITION | + IWL6000G2B_BT_FLAG_COEX_MODE_3W << + IWL6000G2B_BT_FLAG_COEX_MODE_SHIFT; + bt_cmd.valid |= IWL6000G2B_BT_ALL_VALID_MSK; + } + + memcpy(bt_cmd.bt3_lookup_table, iwl6000g2b_def_3w_lookup, + sizeof(iwl6000g2b_def_3w_lookup)); + + IWL_DEBUG_INFO(priv, "BT coex %s\n", + bt_cmd.flags ? "active" : "disabled"); + + if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd)) + IWL_ERR(priv, "failed to send BT Coex Config\n"); +} + static struct iwl_sensitivity_ranges iwl6000_sensitivity = { .min_nrg_cck = 97, .max_nrg_cck = 0, /* not used, set to 0 */ @@ -344,16 +458,12 @@ static const struct iwl_ops iwl6000_ops = { .led = &iwlagn_led_ops, }; -static void do_not_send_bt_config(struct iwl_priv *priv) -{ -} - static struct iwl_hcmd_ops iwl6000g2b_hcmd = { .rxon_assoc = iwlagn_send_rxon_assoc, .commit_rxon = iwl_commit_rxon, .set_rxon_chain = iwl_set_rxon_chain, .set_tx_ant = iwlagn_send_tx_ant_config, - .send_bt_config = do_not_send_bt_config, + .send_bt_config = iwl6000g2b_send_bt_config, }; static const struct iwl_ops iwl6000g2b_ops = { @@ -507,6 +617,9 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .chain_noise_calib_by_driver = true, .need_dc_calib = true, .bt_statistics = true, + /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ + .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, + .advanced_bt_coexist = true, }; struct iwl_cfg iwl6000g2b_2abg_cfg = { @@ -543,6 +656,9 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .chain_noise_calib_by_driver = true, .need_dc_calib = true, .bt_statistics = true, + /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ + .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, + .advanced_bt_coexist = true, }; struct iwl_cfg iwl6000g2b_2bgn_cfg = { @@ -581,6 +697,9 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .chain_noise_calib_by_driver = true, .need_dc_calib = true, .bt_statistics = true, + /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ + .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, + .advanced_bt_coexist = true, }; struct iwl_cfg iwl6000g2b_2bg_cfg = { @@ -617,6 +736,9 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .chain_noise_calib_by_driver = true, .need_dc_calib = true, .bt_statistics = true, + /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ + .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, + .advanced_bt_coexist = true, }; struct iwl_cfg iwl6000g2b_bgn_cfg = { @@ -655,6 +777,9 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .chain_noise_calib_by_driver = true, .need_dc_calib = true, .bt_statistics = true, + /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ + .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, + .advanced_bt_coexist = true, }; struct iwl_cfg iwl6000g2b_bg_cfg = { @@ -691,6 +816,9 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .chain_noise_calib_by_driver = true, .need_dc_calib = true, .bt_statistics = true, + /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ + .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, + .advanced_bt_coexist = true, }; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 78086ad6b72e..69fc7745edaa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2394,6 +2394,68 @@ struct iwl_bt_cmd { __le32 kill_cts_mask; } __packed; +#define IWL6000G2B_BT_FLAG_CHANNEL_INHIBITION BIT(0) + +#define IWL6000G2B_BT_FLAG_COEX_MODE_MASK (BIT(3)|BIT(4)|BIT(5)) +#define IWL6000G2B_BT_FLAG_COEX_MODE_SHIFT 3 +#define IWL6000G2B_BT_FLAG_COEX_MODE_DISABLED 0 +#define IWL6000G2B_BT_FLAG_COEX_MODE_LEGACY_2W 1 +#define IWL6000G2B_BT_FLAG_COEX_MODE_3W 2 +#define IWL6000G2B_BT_FLAG_COEX_MODE_4W 3 + +#define IWL6000G2B_BT_FLAG_UCODE_DEFAULT BIT(6) +#define IWL6000G2B_BT_FLAG_NOCOEX_NOTIF BIT(7) + +#define IWL6000G2B_BT_PRIO_BOOST_MAX 0xFF +#define IWL6000G2B_BT_PRIO_BOOST_MIN 0x00 +#define IWL6000G2B_BT_PRIO_BOOST_DEFAULT 0x00 + +#define IWL6000G2B_BT_MAX_KILL_DEFAULT 5 + +#define IWL6000G2B_BT3_T7_DEFAULT 1 + +#define IWL6000G2B_BT_KILL_ACK_MASK_DEFAULT cpu_to_le32(0xffffffff) +#define IWL6000G2B_BT_KILL_CTS_MASK_DEFAULT cpu_to_le32(0xffffffff) + +#define IWL6000G2B_BT3_PRIO_SAMPLE_DEFAULT 2 + +#define IWL6000G2B_BT3_T2_DEFAULT 0xc + +#define IWL6000G2B_BT_VALID_ENABLE_FLAGS cpu_to_le16(BIT(0)) +#define IWL6000G2B_BT_VALID_BOOST cpu_to_le16(BIT(1)) +#define IWL6000G2B_BT_VALID_MAX_KILL cpu_to_le16(BIT(2)) +#define IWL6000G2B_BT_VALID_3W_TIMERS cpu_to_le16(BIT(3)) +#define IWL6000G2B_BT_VALID_KILL_ACK_MASK cpu_to_le16(BIT(4)) +#define IWL6000G2B_BT_VALID_KILL_CTS_MASK cpu_to_le16(BIT(5)) +#define IWL6000G2B_BT_VALID_BT4_TIMES cpu_to_le16(BIT(6)) +#define IWL6000G2B_BT_VALID_3W_LUT cpu_to_le16(BIT(7)) + +#define IWL6000G2B_BT_ALL_VALID_MSK (IWL6000G2B_BT_VALID_ENABLE_FLAGS | \ + IWL6000G2B_BT_VALID_BOOST | \ + IWL6000G2B_BT_VALID_MAX_KILL | \ + IWL6000G2B_BT_VALID_3W_TIMERS | \ + IWL6000G2B_BT_VALID_KILL_ACK_MASK | \ + IWL6000G2B_BT_VALID_KILL_CTS_MASK | \ + IWL6000G2B_BT_VALID_BT4_TIMES | \ + IWL6000G2B_BT_VALID_3W_LUT) + +struct iwl6000g2b_bt_cmd { + u8 flags; + u8 ledtime; /* unused */ + u8 max_kill; + u8 bt3_timer_t7_value; + __le32 kill_ack_mask; + __le32 kill_cts_mask; + u8 bt3_prio_sample_time; + u8 bt3_timer_t2_value; + __le16 bt4_reaction_time; /* unused */ + __le32 bt3_lookup_table[12]; + __le16 bt4_decision_time; /* unused */ + __le16 valid; + u8 prio_boost; + u8 reserved[3]; +}; + /****************************************************************************** * (6) * Spectrum Management (802.11h) Commands, Responses, Notifications: diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 3d9443b9bec1..4beddade7423 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -64,7 +64,8 @@ MODULE_LICENSE("GPL"); * * default: bt_coex_active = true (BT_COEX_ENABLE) */ -static bool bt_coex_active = true; +bool bt_coex_active = true; +EXPORT_SYMBOL_GPL(bt_coex_active); module_param(bt_coex_active, bool, S_IRUGO); MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7b1e832bae56..d77337987156 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -278,6 +278,7 @@ struct iwl_mod_params { * @chain_noise_calib_by_driver: driver has the capability to perform * chain noise calibration operation * @scan_antennas: available antenna for scan operation + * @advanced_bt_coexist: support advanced bt coexist * @need_dc_calib: need to perform init dc calibration * @bt_statistics: use BT version of statistics notification * @agg_time_limit: maximum number of uSec in aggregation @@ -351,6 +352,7 @@ struct iwl_cfg { const bool chain_noise_calib_by_driver; u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; + bool advanced_bt_coexist; const bool need_dc_calib; const bool bt_statistics; u16 agg_time_limit; @@ -732,4 +734,7 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode( { return priv->hw->wiphy->bands[band]; } + +extern bool bt_coex_active; + #endif /* __iwl_core_h__ */ -- cgit v1.2.3-59-g8ed1b From d44ae69e80358ff88d39a14d92c27dba4e90c0c5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 07:56:56 -0700 Subject: iwlagn: set BT IGNORE for some frames The BT ignore bit should be set when transmitting auth, assoc response and eap frames. Also, scanning should set the BT ignore bit for the probe request transmission; Note that we only use the non-shared antenna. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 17 ++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index eedd71f5506b..e1b5250ea637 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1290,6 +1290,12 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) rate = IWL_RATE_1M_PLCP; rate_flags = RATE_MCS_CCK_MSK; } + /* + * Internal scans are passive, so we can indiscriminately set + * the BT ignore flag on 2.4 GHz since it applies to TX only. + */ + if (priv->cfg->advanced_bt_coexist) + scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; break; case IEEE80211_BAND_5GHZ: diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 3fc982e87921..8d2ffffe01b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -342,10 +342,11 @@ static inline int get_queue_from_ac(u16 ac) * handle build REPLY_TX command notification. */ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, - struct iwl_tx_cmd *tx_cmd, - struct ieee80211_tx_info *info, - struct ieee80211_hdr *hdr, - u8 std_id) + struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, + struct ieee80211_tx_info *info, + struct ieee80211_hdr *hdr, + u8 std_id) { __le16 fc = hdr->frame_control; __le32 tx_flags = tx_cmd->tx_flags; @@ -365,6 +366,12 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, if (ieee80211_is_back_req(fc)) tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; + else if (info->band == IEEE80211_BAND_2GHZ && + priv->cfg->advanced_bt_coexist && + (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) || + ieee80211_is_reassoc_req(fc) || + skb->protocol == cpu_to_be16(ETH_P_PAE))) + tx_flags |= TX_CMD_FLG_IGNORE_BT; tx_cmd->sta_id = std_id; @@ -655,7 +662,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); /* TODO need this for burst mode later on */ - iwlagn_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); + iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id); iwl_dbg_log_tx_data_frame(priv, len, hdr); iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc); -- cgit v1.2.3-59-g8ed1b From 9e4afc21895476114f131b70d1e8fdc3a9c75bb3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 07:56:57 -0700 Subject: iwlwifi: add BT notification support for bt coex When advanced bt coex enabled, uCode will send bt status notification to driver, here add support for it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 161 +++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-commands.h | 7 ++ drivers/net/wireless/iwlwifi/iwl-dev.h | 4 + 3 files changed, 171 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index fc2eeb00c78c..f049ebc4a6aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -377,6 +377,90 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, return iwl_send_cmd_sync(priv, &hcmd); } +static void iwl6000g2b_bt_traffic_change_work(struct work_struct *work) +{ + struct iwl_priv *priv = + container_of(work, struct iwl_priv, bt_traffic_change_work); + int smps_request = -1; + + switch (priv->bt_traffic_load) { + case IWL_BT_COEX_TRAFFIC_LOAD_NONE: + smps_request = IEEE80211_SMPS_AUTOMATIC; + break; + case IWL_BT_COEX_TRAFFIC_LOAD_LOW: + smps_request = IEEE80211_SMPS_DYNAMIC; + break; + case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: + case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: + smps_request = IEEE80211_SMPS_STATIC; + break; + default: + IWL_ERR(priv, "Invalid BT traffic load: %d\n", + priv->bt_traffic_load); + break; + } + + mutex_lock(&priv->mutex); + + if (smps_request != -1 && + priv->vif && priv->vif->type == NL80211_IFTYPE_STATION) + ieee80211_request_smps(priv->vif, smps_request); + + mutex_unlock(&priv->mutex); +} + +static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; + struct iwl6000g2b_bt_sco_cmd sco_cmd = { .flags = 0 }; + + IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n"); + IWL_DEBUG_NOTIF(priv, " status: %d\n", coex->bt_status); + IWL_DEBUG_NOTIF(priv, " traffic load: %d\n", coex->bt_traffic_load); + IWL_DEBUG_NOTIF(priv, " CI compliance: %d\n", coex->bt_ci_compliance); + IWL_DEBUG_NOTIF(priv, " UART msg: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x:" + "%.2x:%.2x\n", + coex->uart_msg[0], coex->uart_msg[1], coex->uart_msg[2], + coex->uart_msg[3], coex->uart_msg[4], coex->uart_msg[5], + coex->uart_msg[6], coex->uart_msg[7]); + + if (coex->bt_traffic_load != priv->bt_traffic_load) { + priv->bt_traffic_load = coex->bt_traffic_load; + + queue_work(priv->workqueue, &priv->bt_traffic_change_work); + } + + /* FIXME: add defines for this check */ + priv->bt_sco_active = coex->uart_msg[3] & 1; + if (priv->bt_sco_active) + sco_cmd.flags |= IWL6000G2B_BT_SCO_ACTIVE; + iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO, + sizeof(sco_cmd), &sco_cmd, NULL); +} + +void iwl6000g2b_rx_handler_setup(struct iwl_priv *priv) +{ + iwlagn_rx_handler_setup(priv); + priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] = + iwl6000g2b_bt_coex_profile_notif; +} + +static void iwl6000g2b_bt_setup_deferred_work(struct iwl_priv *priv) +{ + iwlagn_setup_deferred_work(priv); + + INIT_WORK(&priv->bt_traffic_change_work, + iwl6000g2b_bt_traffic_change_work); + +} + +static void iwl6000g2b_bt_cancel_deferred_work(struct iwl_priv *priv) +{ + cancel_work_sync(&priv->bt_traffic_change_work); +} + static struct iwl_lib_ops iwl6000_lib = { .set_hw_params = iwl6000_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, @@ -451,6 +535,81 @@ static struct iwl_lib_ops iwl6000_lib = { } }; +static struct iwl_lib_ops iwl6000g2b_lib = { + .set_hw_params = iwl6000_hw_set_hw_params, + .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, + .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, + .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, + .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, + .txq_free_tfd = iwl_hw_txq_free_tfd, + .txq_init = iwl_hw_tx_queue_init, + .rx_handler_setup = iwl6000g2b_rx_handler_setup, + .setup_deferred_work = iwl6000g2b_bt_setup_deferred_work, + .cancel_deferred_work = iwl6000g2b_bt_cancel_deferred_work, + .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, + .load_ucode = iwlagn_load_ucode, + .dump_nic_event_log = iwl_dump_nic_event_log, + .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, + .dump_fh = iwl_dump_fh, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, + .send_tx_power = iwlagn_send_tx_power, + .update_chain_flags = iwl_update_chain_flags, + .set_channel_switch = iwl6000_hw_channel_switch, + .apm_ops = { + .init = iwl_apm_init, + .stop = iwl_apm_stop, + .config = iwl6000_nic_config, + .set_pwr_src = iwl_set_pwr_src, + }, + .eeprom_ops = { + .regulatory_bands = { + EEPROM_REG_BAND_1_CHANNELS, + EEPROM_REG_BAND_2_CHANNELS, + EEPROM_REG_BAND_3_CHANNELS, + EEPROM_REG_BAND_4_CHANNELS, + EEPROM_REG_BAND_5_CHANNELS, + EEPROM_6000_REG_BAND_24_HT40_CHANNELS, + EEPROM_REG_BAND_52_HT40_CHANNELS + }, + .verify_signature = iwlcore_eeprom_verify_signature, + .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, + .release_semaphore = iwlcore_eeprom_release_semaphore, + .calib_version = iwlagn_eeprom_calib_version, + .query_addr = iwlagn_eeprom_query_addr, + .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, + }, + .post_associate = iwl_post_associate, + .isr = iwl_isr_ict, + .config_ap = iwl_config_ap, + .temp_ops = { + .temperature = iwlagn_temperature, + .set_ct_kill = iwl6000_set_ct_threshold, + .set_calib_version = iwl6000_set_calib_version, + }, + .manage_ibss_station = iwlagn_manage_ibss_station, + .update_bcast_station = iwl_update_bcast_station, + .debugfs_ops = { + .rx_stats_read = iwl_ucode_rx_stats_read, + .tx_stats_read = iwl_ucode_tx_stats_read, + .general_stats_read = iwl_ucode_general_stats_read, + .bt_stats_read = iwl_ucode_bt_stats_read, + }, + .recover_from_tx_stall = iwl_bg_monitor_recover, + .check_plcp_health = iwl_good_plcp_health, + .check_ack_health = iwl_good_ack_health, + .txfifo_flush = iwlagn_txfifo_flush, + .dev_txfifo_flush = iwlagn_dev_txfifo_flush, + .tt_ops = { + .lower_power_detection = iwl_tt_is_low_power_state, + .tt_power_mode = iwl_tt_current_power_mode, + .ct_kill_check = iwl_check_for_ct_kill, + } +}; + static const struct iwl_ops iwl6000_ops = { .lib = &iwl6000_lib, .hcmd = &iwlagn_hcmd, @@ -467,7 +626,7 @@ static struct iwl_hcmd_ops iwl6000g2b_hcmd = { }; static const struct iwl_ops iwl6000g2b_ops = { - .lib = &iwl6000_lib, + .lib = &iwl6000g2b_lib, .hcmd = &iwl6000g2b_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 69fc7745edaa..67eaeb6822cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -178,6 +178,7 @@ enum { REPLY_BT_COEX_PRIO_TABLE = 0xcc, REPLY_BT_COEX_PROT_ENV = 0xcd, REPLY_BT_COEX_PROFILE_NOTIF = 0xce, + REPLY_BT_COEX_SCO = 0xcf, REPLY_MAX = 0xff }; @@ -2456,6 +2457,12 @@ struct iwl6000g2b_bt_cmd { u8 reserved[3]; }; +#define IWL6000G2B_BT_SCO_ACTIVE cpu_to_le32(BIT(0)) + +struct iwl6000g2b_bt_sco_cmd { + __le32 flags; +}; + /****************************************************************************** * (6) * Spectrum Management (802.11h) Commands, Responses, Notifications: diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 1ad330342ffc..5d327b44533b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1362,6 +1362,10 @@ struct iwl_priv { #endif }; + u8 bt_traffic_load; + bool bt_sco_active; + struct work_struct bt_traffic_change_work; + struct iwl_hw_params hw_params; u32 inta_mask; -- cgit v1.2.3-59-g8ed1b From 290f599cc6ee8c769355486b7d98fd1dc5115d76 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 07:56:58 -0700 Subject: iwlagn: let bluetooth traffic load impact rate scale Depending on the amount of bluetooth traffic, using the shared antenna (antenna B) will have adverse impact on both bluetooth and wireless traffic. Add controls to improve the situation by making rate scaling depend on the BT load. When there's high bluetooth traffic load, there's little point in trying to aggregate as BT traffic would disrupt the aggregated frames all the time, so simply don't start sessions then. When BT traffic returns to lower levels, the rate scaling will come here again automatically when wifi traffic is high enough, and then it will be able to successfully enable aggregation. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 113 +++++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 2 + 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index a4563389bad0..f8eed92c1add 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -301,7 +301,19 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, struct ieee80211_sta *sta) { int ret = -EAGAIN; - u32 load = rs_tl_get_load(lq_data, tid); + u32 load; + + /* + * Don't create TX aggregation sessions when in high + * BT traffic, as they would just be disrupted by BT. + */ + if (priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) { + IWL_ERR(priv, "BT traffic (%d), no aggregation allowed\n", + priv->bt_traffic_load); + return ret; + } + + load = rs_tl_get_load(lq_data, tid); if (load > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", @@ -1286,6 +1298,27 @@ static int rs_move_legacy_other(struct iwl_priv *priv, int ret = 0; u8 update_search_tbl_counter = 0; + switch (priv->bt_traffic_load) { + case IWL_BT_COEX_TRAFFIC_LOAD_NONE: + /* nothing */ + break; + case IWL_BT_COEX_TRAFFIC_LOAD_LOW: + /* avoid antenna B unless MIMO */ + if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2) + tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; + break; + case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: + case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: + /* avoid antenna B and MIMO */ + if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && + tbl->action != IWL_LEGACY_SWITCH_SISO) + tbl->action = IWL_SISO_SWITCH_ANTENNA1; + break; + default: + IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); + break; + } + if (!iwl_ht_enabled(priv)) /* stay in Legacy */ tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; @@ -1425,6 +1458,27 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, u8 update_search_tbl_counter = 0; int ret; + switch (priv->bt_traffic_load) { + case IWL_BT_COEX_TRAFFIC_LOAD_NONE: + /* nothing */ + break; + case IWL_BT_COEX_TRAFFIC_LOAD_LOW: + /* avoid antenna B unless MIMO */ + if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) + tbl->action = IWL_SISO_SWITCH_ANTENNA1; + break; + case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: + case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: + /* avoid antenna B and MIMO */ + if (tbl->action >= IWL_SISO_SWITCH_ANTENNA2 && + tbl->action != IWL_SISO_SWITCH_GI) + tbl->action = IWL_SISO_SWITCH_ANTENNA1; + break; + default: + IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); + break; + } + if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && tbl->action > IWL_SISO_SWITCH_ANTENNA2) { /* stay in SISO */ @@ -1564,6 +1618,27 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, u8 update_search_tbl_counter = 0; int ret; + switch (priv->bt_traffic_load) { + case IWL_BT_COEX_TRAFFIC_LOAD_NONE: + /* nothing */ + break; + case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: + case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: + /* avoid antenna B and MIMO */ + if (tbl->action == IWL_MIMO2_SWITCH_MIMO3_ABC) + tbl->action = IWL_SISO_SWITCH_ANTENNA1; + case IWL_BT_COEX_TRAFFIC_LOAD_LOW: + /* avoid antenna B unless MIMO */ + if (tbl->action == IWL_MIMO2_SWITCH_ANTENNA2) + tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; + else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B) + tbl->action = IWL_MIMO2_SWITCH_SISO_A; + break; + default: + IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); + break; + } + if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) && (tbl->action < IWL_MIMO2_SWITCH_SISO_A || tbl->action > IWL_MIMO2_SWITCH_SISO_C)) { @@ -1706,6 +1781,29 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, int ret; u8 update_search_tbl_counter = 0; + switch (priv->bt_traffic_load) { + case IWL_BT_COEX_TRAFFIC_LOAD_NONE: + /* nothing */ + break; + case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: + case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: + /* avoid antenna B and MIMO */ + if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AB || + tbl->action == IWL_MIMO3_SWITCH_MIMO2_AC || + tbl->action == IWL_MIMO3_SWITCH_MIMO2_BC) + tbl->action = IWL_MIMO3_SWITCH_SISO_A; + case IWL_BT_COEX_TRAFFIC_LOAD_LOW: + /* avoid antenna B unless MIMO */ + if (tbl->action == IWL_MIMO3_SWITCH_SISO_B) + tbl->action = IWL_MIMO3_SWITCH_SISO_A; + else if (tbl->action == IWL_MIMO3_SWITCH_ANTENNA2) + tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; + break; + default: + IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); + break; + } + if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) && (tbl->action < IWL_MIMO3_SWITCH_SISO_A || tbl->action > IWL_MIMO3_SWITCH_SISO_C)) { @@ -2234,6 +2332,19 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, if (iwl_tx_ant_restriction(priv) != IWL_ANT_OK_MULTI && (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) scale_action = -1; + + if (lq_sta->last_bt_traffic > priv->bt_traffic_load) { + lq_sta->last_bt_traffic = priv->bt_traffic_load; + /* + * don't set scale_action, don't want to scale up if + * the rate scale doesn't otherwise think that is a + * good idea. + */ + } else if (lq_sta->last_bt_traffic < priv->bt_traffic_load) { + lq_sta->last_bt_traffic = priv->bt_traffic_load; + scale_action = -1; + } + switch (scale_action) { case -1: /* Decrease starting rate, update uCode's rate table */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 8292f6d48ec6..3970ab1deaf9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -432,6 +432,8 @@ struct iwl_lq_sta { u32 last_rate_n_flags; /* packets destined for this STA are aggregated */ u8 is_agg; + /* BT traffic this sta was last updated in */ + u8 last_bt_traffic; }; static inline u8 num_of_ant(u8 mask) -- cgit v1.2.3-59-g8ed1b From a11741383ba6eef707b8330f0d3c1da6a7478ee3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 07:56:59 -0700 Subject: iwlwifi: reset BT when going down When we turn off the device, reset BT data so that we don't have outdated information when we come up again. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 26bc0482dd9e..a8a5a5b79f39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2773,6 +2773,10 @@ static void __iwl_down(struct iwl_priv *priv) iwl_dealloc_bcast_station(priv); iwl_clear_driver_stations(priv); + /* reset BT coex data */ + priv->bt_traffic_load = 0; + priv->bt_sco_active = false; + /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); @@ -3078,8 +3082,9 @@ static void iwl_bg_restart(struct work_struct *data) mutex_lock(&priv->mutex); priv->vif = NULL; priv->is_open = 0; + __iwl_down(priv); mutex_unlock(&priv->mutex); - iwl_down(priv); + iwl_cancel_deferred_work(priv); ieee80211_restart_hw(priv->hw); } else { iwl_down(priv); -- cgit v1.2.3-59-g8ed1b From 59079949faed96cc2756d5a59c185b304f1bc840 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 07:57:00 -0700 Subject: iwlagn: disable gen2b BT coexistence in IBSS IBSS doesn't allow for coexistence, so it should be disabled. Additionally, disable reacting to the BT profile notification when in IBSS mode, it likely won't be sent by the device to start with though. Also, in IBSS mode, BT coexistence isn't as fully-featured and we must use a single antenna only. So instead of peppering the code with new checks, simply pretend we are in high BT traffic load, which has the needed effect of disabling antenna B use. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 34 ++++++++++++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-core.c | 21 ++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index f049ebc4a6aa..51419444834f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -217,7 +217,14 @@ static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) BUILD_BUG_ON(sizeof(iwl6000g2b_def_3w_lookup) != sizeof(bt_cmd.bt3_lookup_table)); - if (!bt_coex_active) { + /* + * Configure BT coex mode to "no coexistence" when the + * user disabled BT coexistence, we have no interface + * (might be in monitor mode), or the interface is in + * IBSS mode (no proper uCode support for coex then). + */ + if (!bt_coex_active || !priv->vif || + priv->iw_mode == NL80211_IFTYPE_ADHOC) { bt_cmd.flags = 0; } else { bt_cmd.flags = IWL6000G2B_BT_FLAG_CHANNEL_INHIBITION | @@ -426,18 +433,23 @@ static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv, coex->uart_msg[3], coex->uart_msg[4], coex->uart_msg[5], coex->uart_msg[6], coex->uart_msg[7]); - if (coex->bt_traffic_load != priv->bt_traffic_load) { - priv->bt_traffic_load = coex->bt_traffic_load; + priv->notif_bt_traffic_load = coex->bt_traffic_load; - queue_work(priv->workqueue, &priv->bt_traffic_change_work); - } + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { + if (coex->bt_traffic_load != priv->bt_traffic_load) { + priv->bt_traffic_load = coex->bt_traffic_load; - /* FIXME: add defines for this check */ - priv->bt_sco_active = coex->uart_msg[3] & 1; - if (priv->bt_sco_active) - sco_cmd.flags |= IWL6000G2B_BT_SCO_ACTIVE; - iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO, - sizeof(sco_cmd), &sco_cmd, NULL); + queue_work(priv->workqueue, + &priv->bt_traffic_change_work); + } + + /* FIXME: add defines for this check */ + priv->bt_sco_active = coex->uart_msg[3] & 1; + if (priv->bt_sco_active) + sco_cmd.flags |= IWL6000G2B_BT_SCO_ACTIVE; + iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO, + sizeof(sco_cmd), &sco_cmd, NULL); + } } void iwl6000g2b_rx_handler_setup(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4beddade7423..1921307a23b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1872,6 +1872,16 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) if (err) goto out_err; + if (priv->cfg->advanced_bt_coexist && + vif->type == NL80211_IFTYPE_ADHOC) { + /* + * pretend to have high BT traffic as long as we + * are operating in IBSS mode, as this will cause + * the rate scaling etc. to behave as intended. + */ + priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH; + } + goto out; out_err: @@ -1909,6 +1919,17 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, } memset(priv->bssid, 0, ETH_ALEN); } + + /* + * When removing the IBSS interface, overwrite the + * BT traffic load with the stored one from the last + * notification, if any. If this is a device that + * doesn't implement this, this has no effect since + * both values are the same and zero. + */ + if (vif->type == NL80211_IFTYPE_ADHOC) + priv->bt_traffic_load = priv->notif_bt_traffic_load; + mutex_unlock(&priv->mutex); if (scan_completed) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 5d327b44533b..815ba0af94ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1362,7 +1362,7 @@ struct iwl_priv { #endif }; - u8 bt_traffic_load; + u8 bt_traffic_load, notif_bt_traffic_load; bool bt_sco_active; struct work_struct bt_traffic_change_work; -- cgit v1.2.3-59-g8ed1b From 511b082d29bc68c722abd34c1f0219b5754c1163 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 07:57:01 -0700 Subject: iwlagn: keep BT settings across restart The BT SCO needs to be re-applied to the device, while the traffic load just needs to be correct in software. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 16 ++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 51419444834f..22676d960d6e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -241,6 +241,22 @@ static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd)) IWL_ERR(priv, "failed to send BT Coex Config\n"); + + /* + * When we are doing a restart, need to also reconfigure BT + * SCO to the device. If not doing a restart, bt_sco_active + * will always be false, so there's no need to have an extra + * variable to check for it. + */ + if (priv->bt_sco_active) { + struct iwl6000g2b_bt_sco_cmd sco_cmd = { .flags = 0 }; + + if (priv->bt_sco_active) + sco_cmd.flags |= IWL6000G2B_BT_SCO_ACTIVE; + if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_SCO, + sizeof(sco_cmd), &sco_cmd)) + IWL_ERR(priv, "failed to send BT SCO command\n"); + } } static struct iwl_sensitivity_ranges iwl6000_sensitivity = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a8a5a5b79f39..ecf7cf012679 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3079,10 +3079,30 @@ static void iwl_bg_restart(struct work_struct *data) return; if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { + bool bt_sco; + u8 bt_load; + mutex_lock(&priv->mutex); priv->vif = NULL; priv->is_open = 0; + + /* + * __iwl_down() will clear the BT status variables, + * which is correct, but when we restart we really + * want to keep them so restore them afterwards. + * + * The restart process will later pick them up and + * re-configure the hw when we reconfigure the BT + * command. + */ + bt_sco = priv->bt_sco_active; + bt_load = priv->bt_traffic_load; + __iwl_down(priv); + + priv->bt_sco_active = bt_sco; + priv->bt_traffic_load = bt_load; + mutex_unlock(&priv->mutex); iwl_cancel_deferred_work(priv); ieee80211_restart_hw(priv->hw); -- cgit v1.2.3-59-g8ed1b From 74e5c41bafb07f73d8445dcf5a6a968a717d3daa Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:02 -0700 Subject: iwlwifi: Relax uCode timeout/error checking for 6000g2b Disable plcp error checking for 6000g2b devices, with wifi/bt coex; this got trigger too often, disable for now until finding better trigger point. Also extend the firmware reload timer much longer for BT coex to make sure there are will be no mistake to reload firmware too fast and too often. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 12 ++++++------ drivers/net/wireless/iwlwifi/iwl-core.c | 10 +++++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 22676d960d6e..9d430987cc62 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -796,7 +796,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, .chain_noise_scale = 1000, .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, @@ -835,7 +835,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, .chain_noise_scale = 1000, .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, @@ -876,7 +876,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, .chain_noise_scale = 1000, .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, @@ -915,7 +915,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, .chain_noise_scale = 1000, .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, @@ -956,7 +956,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, .chain_noise_scale = 1000, .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, @@ -995,7 +995,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, .chain_noise_scale = 1000, .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 1921307a23b8..72eda7e8a00d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2646,10 +2646,14 @@ static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) "queue %d, not read %d time\n", q->id, q->repeat_same_read_ptr); - mod_timer(&priv->monitor_recover, jiffies + - msecs_to_jiffies(IWL_ONE_HUNDRED_MSECS)); + if (!priv->cfg->advanced_bt_coexist) { + mod_timer(&priv->monitor_recover, + jiffies + msecs_to_jiffies( + IWL_ONE_HUNDRED_MSECS)); + return 1; + } } - return 1; + return 0; } else { q->last_read_ptr = q->read_ptr; q->repeat_same_read_ptr = 0; -- cgit v1.2.3-59-g8ed1b From bd6e2d579949aede258c673caf4b1eb39b95e172 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 07:57:03 -0700 Subject: iwlwifi: use antenna A only under high BT load When bluetooth indicated high load, we should use only antenna A in 2.4 GHz for management frames. Add this condition to iwl_toggle_tx_ant() to make sure it'll always be met. Note that scanning has a separate way of forcing the antenna, because we should scan on antenna A only regardless of BT traffic load. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 72eda7e8a00d..5e8fc720c570 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -147,6 +147,10 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) int i; u8 ind = ant; + if (priv->band == IEEE80211_BAND_2GHZ && + priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) + return 0; + for (i = 0; i < RATE_ANT_NUM - 1; i++) { ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0; if (valid & BIT(ind)) -- cgit v1.2.3-59-g8ed1b From bee008b78307ccc2e17c7ec152dd2098d5f2e1fa Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:04 -0700 Subject: iwlwifi: add bt full concurrency support Adding the bluetooth full concurrency support for WiFi/BT combo devices. Driver should configure uCode to operate in "full concurrency" mode (via LUT) if both conditions are met: - Antenna Coupling is more than 35dB - WiFi Channel Inhibition Request is hornored by BT Core Currently, there is no antenna coupling information provided by uCode; use module parameter to specified the antenna coupling in dB. When in "full concurrency" mode, driver need to download different LUT to uCode while sending bt configuration command; also, driver need to configure the device operate in 1x1 while in full concurrency mode. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 34 ++++++++++++-- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 6 ++- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 11 +++++ drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 70 ++++++++++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 7 ++- drivers/net/wireless/iwlwifi/iwl-agn.c | 49 ++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-core.c | 11 ++++- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 7 +++ 9 files changed, 185 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 9d430987cc62..a4601b58a5db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -201,6 +201,21 @@ static const __le32 iwl6000g2b_def_3w_lookup[12] = { cpu_to_le32(0xf0004000), }; +static const __le32 iwl6000g2b_concurrent_lookup[12] = { + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0x00000000), + cpu_to_le32(0x00000000), + cpu_to_le32(0x00000000), + cpu_to_le32(0x00000000), +}; + static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) { struct iwl6000g2b_bt_cmd bt_cmd = { @@ -233,11 +248,17 @@ static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) bt_cmd.valid |= IWL6000G2B_BT_ALL_VALID_MSK; } - memcpy(bt_cmd.bt3_lookup_table, iwl6000g2b_def_3w_lookup, - sizeof(iwl6000g2b_def_3w_lookup)); + if (priv->bt_full_concurrent) + memcpy(bt_cmd.bt3_lookup_table, iwl6000g2b_concurrent_lookup, + sizeof(iwl6000g2b_concurrent_lookup)); + else + memcpy(bt_cmd.bt3_lookup_table, iwl6000g2b_def_3w_lookup, + sizeof(iwl6000g2b_def_3w_lookup)); - IWL_DEBUG_INFO(priv, "BT coex %s\n", - bt_cmd.flags ? "active" : "disabled"); + IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n", + bt_cmd.flags ? "active" : "disabled", + priv->bt_full_concurrent ? + "full concurrency" : "3-wire"); if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd)) IWL_ERR(priv, "failed to send BT Coex Config\n"); @@ -435,6 +456,7 @@ static void iwl6000g2b_bt_traffic_change_work(struct work_struct *work) static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { + unsigned long flags; struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; struct iwl6000g2b_bt_sco_cmd sco_cmd = { .flags = 0 }; @@ -466,6 +488,10 @@ static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv, iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO, sizeof(sco_cmd), &sco_cmd, NULL); } + + spin_lock_irqsave(&priv->lock, flags); + priv->bt_ci_compliance = coex->bt_ci_compliance; + spin_unlock_irqrestore(&priv->lock, flags); } void iwl6000g2b_rx_handler_setup(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index c4c5691032a6..156b125dba71 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -914,7 +914,11 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) * To be safe, simply mask out any chains that we know * are not on the device. */ - active_chains &= priv->hw_params.valid_rx_ant; + if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { + /* operated as 1x1 in full concurrency mode */ + active_chains &= first_antenna(priv->hw_params.valid_rx_ant); + } else + active_chains &= priv->hw_params.valid_rx_ant; num_tx_chains = 0; for (i = 0; i < NUM_RX_CHAINS; i++) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index e1b5250ea637..e0ec6c08b222 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1333,6 +1333,12 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) if (priv->cfg->scan_tx_antennas[band]) scan_tx_antennas = priv->cfg->scan_tx_antennas[band]; + if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { + /* operated as 1x1 in full concurrency mode */ + scan_tx_antennas = + first_antenna(priv->cfg->scan_tx_antennas[band]); + } + priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band], scan_tx_antennas); rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); @@ -1351,6 +1357,11 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) rx_ant = first_antenna(active_chains); } + if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { + /* operated as 1x1 in full concurrency mode */ + rx_ant = first_antenna(rx_ant); + } + /* MIMO is not used here, but value is required */ rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index f8eed92c1add..687b534d83d0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -758,6 +758,32 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a, (a->is_SGI == b->is_SGI); } +static void rs_bt_update_lq(struct iwl_priv *priv, + struct iwl_lq_sta *lq_sta) +{ + struct iwl_scale_tbl_info *tbl; + bool full_concurrent; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) + full_concurrent = true; + else + full_concurrent = false; + spin_unlock_irqrestore(&priv->lock, flags); + + if (priv->bt_full_concurrent != full_concurrent) { + priv->bt_full_concurrent = full_concurrent; + + /* Update uCode's rate table. */ + tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); + + queue_work(priv->workqueue, &priv->bt_full_concurrency); + } +} + /* * mac80211 sends us Tx status */ @@ -940,6 +966,10 @@ done: /* See if there's a better rate or modulation mode to try. */ if (sta && sta->supp_rates[sband->band]) rs_rate_scale_perform(priv, skb, sta, lq_sta); + + /* Is there a need to switch between full concurrency and 3-wire? */ + if (priv->bt_ant_couple_ok) + rs_bt_update_lq(priv, lq_sta); } /* @@ -1325,6 +1355,15 @@ static int rs_move_legacy_other(struct iwl_priv *priv, else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && tbl->action > IWL_LEGACY_SWITCH_SISO) tbl->action = IWL_LEGACY_SWITCH_SISO; + + /* configure as 1x1 if bt full concurrency */ + if (priv->bt_full_concurrent) { + if (!iwl_ht_enabled(priv)) + tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; + else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) + tbl->action = IWL_LEGACY_SWITCH_SISO; + } + start_action = tbl->action; for (; ;) { lq_sta->action_counter++; @@ -1484,6 +1523,12 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, /* stay in SISO */ tbl->action = IWL_SISO_SWITCH_ANTENNA1; } + + /* configure as 1x1 if bt full concurrency */ + if (priv->bt_full_concurrent && + tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) + tbl->action = IWL_SISO_SWITCH_ANTENNA1; + start_action = tbl->action; for (;;) { lq_sta->action_counter++; @@ -1645,6 +1690,13 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, /* switch in SISO */ tbl->action = IWL_MIMO2_SWITCH_SISO_A; } + + /* configure as 1x1 if bt full concurrency */ + if (priv->bt_full_concurrent && + (tbl->action < IWL_MIMO2_SWITCH_SISO_A || + tbl->action > IWL_MIMO2_SWITCH_SISO_C)) + tbl->action = IWL_MIMO2_SWITCH_SISO_A; + start_action = tbl->action; for (;;) { lq_sta->action_counter++; @@ -1810,6 +1862,13 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, /* switch in SISO */ tbl->action = IWL_MIMO3_SWITCH_SISO_A; } + + /* configure as 1x1 if bt full concurrency */ + if (priv->bt_full_concurrent && + (tbl->action < IWL_MIMO3_SWITCH_SISO_A || + tbl->action > IWL_MIMO3_SWITCH_SISO_C)) + tbl->action = IWL_MIMO3_SWITCH_SISO_A; + start_action = tbl->action; for (;;) { lq_sta->action_counter++; @@ -2741,7 +2800,8 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, /* Fill 1st table entry (index 0) */ lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate); - if (num_of_ant(tbl_type.ant_type) == 1) { + if (num_of_ant(tbl_type.ant_type) == 1 || + (priv && priv->bt_full_concurrent)) { lq_cmd->general_params.single_stream_ant_msk = tbl_type.ant_type; } else if (num_of_ant(tbl_type.ant_type) == 2) { @@ -2752,8 +2812,12 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, index++; repeat_rate--; - if (priv) - valid_tx_ant = priv->hw_params.valid_tx_ant; + if (priv) { + if (priv->bt_full_concurrent) + valid_tx_ant = ANT_A; + else + valid_tx_ant = priv->hw_params.valid_tx_ant; + } /* Fill rest of rate table */ while (index < LINK_QUAL_MAX_RETRY_NUM) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 8d2ffffe01b2..e2497e7ba926 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -461,7 +461,12 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, rate_flags |= RATE_MCS_CCK_MSK; /* Set up antennas */ - priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, + if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { + /* operated as 1x1 in full concurrency mode */ + priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, + first_antenna(priv->hw_params.valid_tx_ant)); + } else + priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, priv->hw_params.valid_tx_ant); rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ecf7cf012679..807d697f6239 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -87,6 +87,8 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); MODULE_ALIAS("iwl4965"); +static int iwlagn_ant_coupling; + /** * iwl_commit_rxon - commit staging_rxon to hardware * @@ -612,6 +614,33 @@ static void iwl_bg_beacon_update(struct work_struct *work) iwl_send_beacon_cmd(priv); } +static void iwl_bg_bt_full_concurrency(struct work_struct *work) +{ + struct iwl_priv *priv = + container_of(work, struct iwl_priv, bt_full_concurrency); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + /* dont send host command if rf-kill is on */ + if (!iwl_is_ready_rf(priv)) + return; + + IWL_DEBUG_INFO(priv, "BT coex in %s mode\n", + priv->bt_full_concurrent ? + "full concurrency" : "3-wire"); + + /* + * LQ & RXON updated cmds must be sent before BT Config cmd + * to avoid 3-wire collisions + */ + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + iwlcore_commit_rxon(priv); + + priv->cfg->ops->hcmd->send_bt_config(priv); +} + /** * iwl_bg_statistics_periodic - Timer callback to queue statistics * @@ -2776,6 +2805,8 @@ static void __iwl_down(struct iwl_priv *priv) /* reset BT coex data */ priv->bt_traffic_load = 0; priv->bt_sco_active = false; + priv->bt_full_concurrent = false; + priv->bt_ci_compliance = 0; /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); @@ -3079,7 +3110,8 @@ static void iwl_bg_restart(struct work_struct *data) return; if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { - bool bt_sco; + bool bt_sco, bt_full_concurrent; + u8 bt_ci_compliance; u8 bt_load; mutex_lock(&priv->mutex); @@ -3096,11 +3128,15 @@ static void iwl_bg_restart(struct work_struct *data) * command. */ bt_sco = priv->bt_sco_active; + bt_full_concurrent = priv->bt_full_concurrent; + bt_ci_compliance = priv->bt_ci_compliance; bt_load = priv->bt_traffic_load; __iwl_down(priv); priv->bt_sco_active = bt_sco; + priv->bt_full_concurrent = bt_full_concurrent; + priv->bt_ci_compliance = bt_ci_compliance; priv->bt_traffic_load = bt_load; mutex_unlock(&priv->mutex); @@ -3856,6 +3892,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); + INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); @@ -3898,6 +3935,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work(&priv->alive_start); cancel_work_sync(&priv->run_time_calib_work); cancel_work_sync(&priv->beacon_update); + cancel_work_sync(&priv->bt_full_concurrency); del_timer_sync(&priv->statistics_periodic); del_timer_sync(&priv->ucode_trace); } @@ -4078,6 +4116,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->pci_dev = pdev; priv->inta_mask = CSR_INI_SET_MASK; + /* is antenna coupling more than 35dB ? */ + priv->bt_ant_couple_ok = + (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? + true : false; + if (iwl_alloc_traffic_mem(priv)) IWL_ERR(priv, "Not enough memory to generate traffic log\n"); @@ -4611,3 +4654,7 @@ module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, S_IRUGO); MODULE_PARM_DESC(ucode_alternative, "specify ucode alternative to use from ucode file"); + +module_param_named(antenna_coupling, iwlagn_ant_coupling, int, S_IRUGO); +MODULE_PARM_DESC(antenna_coupling, + "specify antenna coupling in dB (defualt: 0 dB)"); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5e8fc720c570..13d2dcea85d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -780,6 +780,10 @@ EXPORT_SYMBOL(iwl_set_rxon_ht); */ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) { + if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { + /* operated as 1x1 in full concurrency mode */ + return IWL_NUM_RX_CHAINS_SINGLE; + } /* # of Rx chains to use when expecting MIMO. */ if (is_single_rx_stream(priv)) return IWL_NUM_RX_CHAINS_SINGLE; @@ -836,11 +840,16 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) * Before first association, we assume all antennas are connected. * Just after first association, iwl_chain_noise_calibration() * checks which antennas actually *are* connected. */ - if (priv->chain_noise_data.active_chains) + if (priv->chain_noise_data.active_chains) active_chains = priv->chain_noise_data.active_chains; else active_chains = priv->hw_params.valid_rx_ant; + if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { + /* operated as 1x1 in full concurrency mode */ + active_chains = first_antenna(active_chains); + } + rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS; /* How many receivers should we use? */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index d77337987156..146d0d5ec6b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -736,5 +736,6 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode( } extern bool bt_coex_active; +extern bool bt_siso_mode; #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 815ba0af94ce..7a96d9dd1732 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1065,6 +1065,9 @@ struct iwl_event_log { #define IWL_LONG_MONITORING_PERIOD (5000) #define IWL_ONE_HUNDRED_MSECS (100) +/* BT Antenna Coupling Threshold (dB) */ +#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) + enum iwl_reset { IWL_RF_RESET = 0, IWL_FW_RESET, @@ -1364,6 +1367,9 @@ struct iwl_priv { u8 bt_traffic_load, notif_bt_traffic_load; bool bt_sco_active; + bool bt_full_concurrent; + bool bt_ant_couple_ok; + u8 bt_ci_compliance; struct work_struct bt_traffic_change_work; struct iwl_hw_params hw_params; @@ -1384,6 +1390,7 @@ struct iwl_priv { struct work_struct ct_exit; struct work_struct start_internal_scan; struct work_struct tx_flush; + struct work_struct bt_full_concurrency; struct tasklet_struct irq_tasklet; -- cgit v1.2.3-59-g8ed1b From aeb4a2eec2b1d2ac6507e9cec2aecc46fdba8741 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:05 -0700 Subject: iwlagn: wifi/bt coex configuration sequence bt config command need to send before the init calibration command, driver need to let uCode know that calibrations are being performed now in order to assure antenna is not being taken to BT use during radio/dsp reads/writes Also, bt_coex_priorty_table command need to be send right after the bt_config_command during init sequence. Followed by bt coex envelope command to initialize and prepare uCode bt state machine Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 5 +-- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 59 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++- drivers/net/wireless/iwlwifi/iwl-commands.h | 59 +++++++++++++++++++++------- 4 files changed, 109 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index a4601b58a5db..101630b80c40 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -235,11 +235,10 @@ static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) /* * Configure BT coex mode to "no coexistence" when the * user disabled BT coexistence, we have no interface - * (might be in monitor mode), or the interface is in + * user disabled BT coexistence, or the interface is in * IBSS mode (no proper uCode support for coex then). */ - if (!bt_coex_active || !priv->vif || - priv->iw_mode == NL80211_IFTYPE_ADHOC) { + if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) { bt_cmd.flags = 0; } else { bt_cmd.flags = IWL6000G2B_BT_FLAG_CHANNEL_INHIBITION | diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 6f77441cb65a..2dc569bc7e8f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -329,6 +329,51 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv) sizeof(coex_cmd), &coex_cmd); } +static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { + ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_COEX_OFF << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_COEX_ON << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + 0, 0, 0, 0, 0, 0, 0 +}; + +static void iwlagn_send_prio_tbl(struct iwl_priv *priv) +{ + struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd; + + memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, + sizeof(iwlagn_bt_prio_tbl)); + if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PRIO_TABLE, + sizeof(prio_tbl_cmd), &prio_tbl_cmd)) + IWL_ERR(priv, "failed to send BT prio tbl command\n"); +} + +static void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) +{ + struct iwl_bt_coex_prot_env_cmd env_cmd; + + env_cmd.action = action; + env_cmd.type = type; + if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, + sizeof(env_cmd), &env_cmd)) + IWL_ERR(priv, "failed to send BT env command\n"); +} + + int iwlagn_alive_notify(struct iwl_priv *priv) { u32 a; @@ -416,6 +461,20 @@ int iwlagn_alive_notify(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); + if (priv->cfg->advanced_bt_coexist) { + /* Configure Bluetooth device coexistence support */ + /* need to perform this before any calibration */ + priv->cfg->ops->hcmd->send_bt_config(priv); + if (bt_coex_active && priv->iw_mode != NL80211_IFTYPE_ADHOC) { + iwlagn_send_prio_tbl(priv); + iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, + BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); + iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, + BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); + } + + } + iwlagn_send_wimax_coex(priv); iwlagn_set_Xtal_calib(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 807d697f6239..c17ce823f84d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2754,8 +2754,10 @@ static void iwl_alive_start(struct iwl_priv *priv) priv->cfg->ops->hcmd->set_rxon_chain(priv); } - /* Configure Bluetooth device coexistence support */ - priv->cfg->ops->hcmd->send_bt_config(priv); + if (!priv->cfg->advanced_bt_coexist) { + /* Configure Bluetooth device coexistence support */ + priv->cfg->ops->hcmd->send_bt_config(priv); + } iwl_reset_run_time_calib(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 67eaeb6822cb..b45882aa68fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -4078,34 +4078,63 @@ struct iwl_bt_coex_profile_notif { u8 reserved; } __attribute__((packed)); -#define IWL_BT_COEX_PRIO_SHARED_ANTENNA 0x1 -#define IWL_BT_COEX_PRIO_PRIO_MASK 0xe -#define IWL_BT_COEX_PRIO_PRIO_SHIFT 1 +#define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS 0 +#define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_MSK 0x1 +#define IWL_BT_COEX_PRIO_TBL_PRIO_POS 1 +#define IWL_BT_COEX_PRIO_TBL_PRIO_MASK 0x0e +#define IWL_BT_COEX_PRIO_TBL_RESERVED_POS 4 +#define IWL_BT_COEX_PRIO_TBL_RESERVED_MASK 0xf0 +#define IWL_BT_COEX_PRIO_TBL_PRIO_SHIFT 1 /* * BT Coexistence Priority table * REPLY_BT_COEX_PRIO_TABLE = 0xcc */ +enum bt_coex_prio_table_events { + BT_COEX_PRIO_TBL_EVT_INIT_CALIB1 = 0, + BT_COEX_PRIO_TBL_EVT_INIT_CALIB2 = 1, + BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1 = 2, + BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2 = 3, /* DC calib */ + BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1 = 4, + BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2 = 5, + BT_COEX_PRIO_TBL_EVT_DTIM = 6, + BT_COEX_PRIO_TBL_EVT_SCAN52 = 7, + BT_COEX_PRIO_TBL_EVT_SCAN24 = 8, + BT_COEX_PRIO_TBL_EVT_RESERVED0 = 9, + BT_COEX_PRIO_TBL_EVT_RESERVED1 = 10, + BT_COEX_PRIO_TBL_EVT_RESERVED2 = 11, + BT_COEX_PRIO_TBL_EVT_RESERVED3 = 12, + BT_COEX_PRIO_TBL_EVT_RESERVED4 = 13, + BT_COEX_PRIO_TBL_EVT_RESERVED5 = 14, + BT_COEX_PRIO_TBL_EVT_RESERVED6 = 15, + /* BT_COEX_PRIO_TBL_EVT_MAX should always be last */ + BT_COEX_PRIO_TBL_EVT_MAX, +}; + +enum bt_coex_prio_table_priorities { + BT_COEX_PRIO_TBL_DISABLED = 0, + BT_COEX_PRIO_TBL_PRIO_LOW = 1, + BT_COEX_PRIO_TBL_PRIO_HIGH = 2, + BT_COEX_PRIO_TBL_PRIO_BYPASS = 3, + BT_COEX_PRIO_TBL_PRIO_COEX_OFF = 4, + BT_COEX_PRIO_TBL_PRIO_COEX_ON = 5, + BT_COEX_PRIO_TBL_PRIO_RSRVD1 = 6, + BT_COEX_PRIO_TBL_PRIO_RSRVD2 = 7, + BT_COEX_PRIO_TBL_MAX, +}; + struct iwl_bt_coex_prio_table_cmd { - u8 init_calib_protection_cfg1, - init_calib_protection_cfg2, - init_calib_protection_lowprio_cfg1, - init_calib_protection_lowprio_cfg2, - init_calib_protection_highprio_cfg1, - init_calib_protection_highprio_cfg2, - dtim_protection_prio_cfg, - scan_52_protection_cfg, - scan_24_protection_cfg, - bc_mc_protection_cfg; - u8 reserved[6]; + u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX]; } __attribute__((packed)); +#define IWL_BT_COEX_ENV_CLOSE 0 +#define IWL_BT_COEX_ENV_OPEN 1 /* * BT Protection Envelope * REPLY_BT_COEX_PROT_ENV = 0xcd */ struct iwl_bt_coex_prot_env_cmd { - u8 open; /* 0 = closed, 1 = open */ + u8 action; /* 0 = closed, 1 = open */ u8 type; /* 0 .. 15 */ u8 reserved[2]; } __attribute__((packed)); -- cgit v1.2.3-59-g8ed1b From c6c996b5de82b5de4b4b5a31941aab725961a6dd Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:06 -0700 Subject: iwlwifi: indicate bt_kill condition when receive tx reply Generate log when receive tx reply with bt_kill count > 0 and in advance bt coex mode Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index e0ec6c08b222..ea242401b5a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -247,7 +247,14 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_ht_agg *agg; agg = &priv->stations[sta_id].tid[tid].agg; - + /* + * If the BT kill count is non-zero, we'll get this + * notification again. + */ + if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && + priv->cfg->advanced_bt_coexist) { + IWL_WARN(priv, "receive reply tx with bt_kill\n"); + } iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); /* check if BAR is needed */ -- cgit v1.2.3-59-g8ed1b From 7bdc473c7a52497af9fe8c73e4745615a2825aaa Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:07 -0700 Subject: iwlwifi: add debugfs to control stuck queue timer In current implementation, stuck queue timer is fixed to 1 second. Add debugfs file to modify the timer to enhance the flexibility: Set the monitor_period as following: 0: disable stuck queue force reset function 1 - 60000: monitor period (1 - 60 second) Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 14 ++++++++------ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 30 ++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 13d2dcea85d1..34cba38f1d0c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2697,12 +2697,14 @@ void iwl_bg_monitor_recover(unsigned long data) return; } } - /* - * Reschedule the timer to occur in - * priv->cfg->monitor_recover_period - */ - mod_timer(&priv->monitor_recover, - jiffies + msecs_to_jiffies(priv->cfg->monitor_recover_period)); + if (priv->cfg->monitor_recover_period) { + /* + * Reschedule the timer to occur in + * priv->cfg->monitor_recover_period + */ + mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies( + priv->cfg->monitor_recover_period)); + } } EXPORT_SYMBOL(iwl_bg_monitor_recover); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d3acdae72381..aae9eb552350 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1527,6 +1527,34 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, user_buf, count, ppos); } +static ssize_t iwl_dbgfs_monitor_period_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + int period; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &period) != 1) + return -EINVAL; + if (period < 0 || period > IWL_MAX_MONITORING_PERIOD) + priv->cfg->monitor_recover_period = IWL_DEF_MONITORING_PERIOD; + else + priv->cfg->monitor_recover_period = period; + + if (priv->cfg->monitor_recover_period) + mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies( + priv->cfg->monitor_recover_period)); + else + del_timer_sync(&priv->monitor_recover); + return count; +} + DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); @@ -1550,6 +1578,7 @@ DEBUGFS_READ_FILE_OPS(rxon_flags); DEBUGFS_READ_FILE_OPS(rxon_filter_flags); DEBUGFS_WRITE_FILE_OPS(txfifo_flush); DEBUGFS_READ_FILE_OPS(ucode_bt_stats); +DEBUGFS_WRITE_FILE_OPS(monitor_period); /* * Create the debugfs files and directories @@ -1621,6 +1650,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR); if (priv->cfg->sensitivity_calib_by_driver) DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 7a96d9dd1732..bb92a7f01988 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1064,6 +1064,7 @@ struct iwl_event_log { #define IWL_DEF_MONITORING_PERIOD (1000) #define IWL_LONG_MONITORING_PERIOD (5000) #define IWL_ONE_HUNDRED_MSECS (100) +#define IWL_MAX_MONITORING_PERIOD (60000) /* BT Antenna Coupling Threshold (dB) */ #define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) -- cgit v1.2.3-59-g8ed1b From a4b96cc4e3fa99d5d6d8ad38c5b0aa4c3aa8a828 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:08 -0700 Subject: iwlwifi: add bt_init_traffic_load as configurable parameter Adding configurable parameter in .cfg for the initial Bluetooth traffic load; set it to IWL_BT_COEX_TRAFFIC_LOAD_NONE for now, but can be change for debugging or other reason. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 101630b80c40..396d80c0ef38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -832,6 +832,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, + .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, }; struct iwl_cfg iwl6000g2b_2abg_cfg = { @@ -871,6 +872,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, + .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, }; struct iwl_cfg iwl6000g2b_2bgn_cfg = { @@ -912,6 +914,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, + .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, }; struct iwl_cfg iwl6000g2b_2bg_cfg = { @@ -951,6 +954,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, + .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, }; struct iwl_cfg iwl6000g2b_bgn_cfg = { @@ -992,6 +996,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, + .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, }; struct iwl_cfg iwl6000g2b_bg_cfg = { @@ -1031,6 +1036,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, + .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, }; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c17ce823f84d..06e89d474d04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2805,7 +2805,7 @@ static void __iwl_down(struct iwl_priv *priv) iwl_clear_driver_stations(priv); /* reset BT coex data */ - priv->bt_traffic_load = 0; + priv->bt_traffic_load = priv->cfg->bt_init_traffic_load; priv->bt_sco_active = false; priv->bt_full_concurrent = false; priv->bt_ci_compliance = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 146d0d5ec6b9..d5dacaf0d09f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -279,6 +279,7 @@ struct iwl_mod_params { * chain noise calibration operation * @scan_antennas: available antenna for scan operation * @advanced_bt_coexist: support advanced bt coexist + * @bt_init_traffic_load: specify initial bt traffic load * @need_dc_calib: need to perform init dc calibration * @bt_statistics: use BT version of statistics notification * @agg_time_limit: maximum number of uSec in aggregation @@ -353,6 +354,7 @@ struct iwl_cfg { u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; bool advanced_bt_coexist; + u8 bt_init_traffic_load; const bool need_dc_calib; const bool bt_statistics; u16 agg_time_limit; -- cgit v1.2.3-59-g8ed1b From 5d297d50653ba0c498e0b1e7b72b6611651357aa Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:09 -0700 Subject: iwlagn: add bt prio_boost to .cfg Use .cfg to configure the default bt priority boost value; the default bt priority boost is 0xf0 Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 11 ++++++++++- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 396d80c0ef38..54b59dadf2a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -219,7 +219,6 @@ static const __le32 iwl6000g2b_concurrent_lookup[12] = { static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) { struct iwl6000g2b_bt_cmd bt_cmd = { - .prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, .max_kill = IWL6000G2B_BT_MAX_KILL_DEFAULT, .bt3_timer_t7_value = IWL6000G2B_BT3_T7_DEFAULT, .kill_ack_mask = IWL6000G2B_BT_KILL_ACK_MASK_DEFAULT, @@ -232,6 +231,8 @@ static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) BUILD_BUG_ON(sizeof(iwl6000g2b_def_3w_lookup) != sizeof(bt_cmd.bt3_lookup_table)); + bt_cmd.prio_boost = priv->cfg->bt_prio_boost; + /* * Configure BT coex mode to "no coexistence" when the * user disabled BT coexistence, we have no interface @@ -488,6 +489,8 @@ static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv, sizeof(sco_cmd), &sco_cmd, NULL); } + /* FIXME: based on notification, adjust the prio_boost */ + spin_lock_irqsave(&priv->lock, flags); priv->bt_ci_compliance = coex->bt_ci_compliance; spin_unlock_irqrestore(&priv->lock, flags); @@ -833,6 +836,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, + .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, }; struct iwl_cfg iwl6000g2b_2abg_cfg = { @@ -873,6 +877,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, + .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, }; struct iwl_cfg iwl6000g2b_2bgn_cfg = { @@ -915,6 +920,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, + .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, }; struct iwl_cfg iwl6000g2b_2bg_cfg = { @@ -955,6 +961,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, + .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, }; struct iwl_cfg iwl6000g2b_bgn_cfg = { @@ -997,6 +1004,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, + .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, }; struct iwl_cfg iwl6000g2b_bg_cfg = { @@ -1037,6 +1045,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, + .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, }; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index b45882aa68fe..e742f994ff82 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2409,7 +2409,7 @@ struct iwl_bt_cmd { #define IWL6000G2B_BT_PRIO_BOOST_MAX 0xFF #define IWL6000G2B_BT_PRIO_BOOST_MIN 0x00 -#define IWL6000G2B_BT_PRIO_BOOST_DEFAULT 0x00 +#define IWL6000G2B_BT_PRIO_BOOST_DEFAULT 0xF0 #define IWL6000G2B_BT_MAX_KILL_DEFAULT 5 diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index d5dacaf0d09f..de2e39f36c25 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -280,6 +280,7 @@ struct iwl_mod_params { * @scan_antennas: available antenna for scan operation * @advanced_bt_coexist: support advanced bt coexist * @bt_init_traffic_load: specify initial bt traffic load + * @bt_prio_boost: default bt priority boost value * @need_dc_calib: need to perform init dc calibration * @bt_statistics: use BT version of statistics notification * @agg_time_limit: maximum number of uSec in aggregation @@ -355,6 +356,7 @@ struct iwl_cfg { u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; bool advanced_bt_coexist; u8 bt_init_traffic_load; + u8 bt_prio_boost; const bool need_dc_calib; const bool bt_statistics; u16 agg_time_limit; -- cgit v1.2.3-59-g8ed1b From fbba94104fb44d2f984e767cd8ac1edd80cb03d5 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:10 -0700 Subject: iwlagn: parsing uart message and take actions 1. Based on uart message from uCode, re-configure BT kill ack mask messages from uCode 2. send REPLY_BT_COEX_SCO command to uCode based on the uart frame received from uCode Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 116 +++++++++++++++++++++++---- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 5 ++ drivers/net/wireless/iwlwifi/iwl-agn.c | 16 ++++ drivers/net/wireless/iwlwifi/iwl-commands.h | 110 ++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 + 5 files changed, 235 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 54b59dadf2a8..e4873cc2a57a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -221,17 +221,17 @@ static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) struct iwl6000g2b_bt_cmd bt_cmd = { .max_kill = IWL6000G2B_BT_MAX_KILL_DEFAULT, .bt3_timer_t7_value = IWL6000G2B_BT3_T7_DEFAULT, - .kill_ack_mask = IWL6000G2B_BT_KILL_ACK_MASK_DEFAULT, - .kill_cts_mask = IWL6000G2B_BT_KILL_CTS_MASK_DEFAULT, .bt3_prio_sample_time = IWL6000G2B_BT3_PRIO_SAMPLE_DEFAULT, .bt3_timer_t2_value = IWL6000G2B_BT3_T2_DEFAULT, - .valid = IWL6000G2B_BT_VALID_ENABLE_FLAGS, }; BUILD_BUG_ON(sizeof(iwl6000g2b_def_3w_lookup) != sizeof(bt_cmd.bt3_lookup_table)); bt_cmd.prio_boost = priv->cfg->bt_prio_boost; + bt_cmd.kill_ack_mask = priv->kill_ack_mask; + bt_cmd.kill_cts_mask = priv->kill_cts_mask; + bt_cmd.valid = priv->bt_valid; /* * Configure BT coex mode to "no coexistence" when the @@ -245,7 +245,6 @@ static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) bt_cmd.flags = IWL6000G2B_BT_FLAG_CHANNEL_INHIBITION | IWL6000G2B_BT_FLAG_COEX_MODE_3W << IWL6000G2B_BT_FLAG_COEX_MODE_SHIFT; - bt_cmd.valid |= IWL6000G2B_BT_ALL_VALID_MSK; } if (priv->bt_full_concurrent) @@ -453,6 +452,93 @@ static void iwl6000g2b_bt_traffic_change_work(struct work_struct *work) mutex_unlock(&priv->mutex); } +static void iwlagn_print_uartmsg(struct iwl_priv *priv, + struct iwl_bt_uart_msg *uart_msg) +{ + IWL_DEBUG_NOTIF(priv, "Message Type = 0x%X, SSN = 0x%X, " + "Update Req = 0x%X", + (BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >> + BT_UART_MSG_FRAME1MSGTYPE_POS, + (BT_UART_MSG_FRAME1SSN_MSK & uart_msg->frame1) >> + BT_UART_MSG_FRAME1SSN_POS, + (BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >> + BT_UART_MSG_FRAME1UPDATEREQ_POS); + + IWL_DEBUG_NOTIF(priv, "Open connections = 0x%X, Traffic load = 0x%X, " + "Chl_SeqN = 0x%X, In band = 0x%X", + (BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >> + BT_UART_MSG_FRAME2OPENCONNECTIONS_POS, + (BT_UART_MSG_FRAME2TRAFFICLOAD_MSK & uart_msg->frame2) >> + BT_UART_MSG_FRAME2TRAFFICLOAD_POS, + (BT_UART_MSG_FRAME2CHLSEQN_MSK & uart_msg->frame2) >> + BT_UART_MSG_FRAME2CHLSEQN_POS, + (BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >> + BT_UART_MSG_FRAME2INBAND_POS); + + IWL_DEBUG_NOTIF(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, " + "ACL = 0x%X, Master = 0x%X, OBEX = 0x%X", + (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3SCOESCO_POS, + (BT_UART_MSG_FRAME3SNIFF_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3SNIFF_POS, + (BT_UART_MSG_FRAME3A2DP_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3A2DP_POS, + (BT_UART_MSG_FRAME3ACL_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3ACL_POS, + (BT_UART_MSG_FRAME3MASTER_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3MASTER_POS, + (BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3OBEX_POS); + + IWL_DEBUG_NOTIF(priv, "Idle duration = 0x%X", + (BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >> + BT_UART_MSG_FRAME4IDLEDURATION_POS); + + IWL_DEBUG_NOTIF(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, " + "eSCO Retransmissions = 0x%X", + (BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >> + BT_UART_MSG_FRAME5TXACTIVITY_POS, + (BT_UART_MSG_FRAME5RXACTIVITY_MSK & uart_msg->frame5) >> + BT_UART_MSG_FRAME5RXACTIVITY_POS, + (BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >> + BT_UART_MSG_FRAME5ESCORETRANSMIT_POS); + + IWL_DEBUG_NOTIF(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X", + (BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >> + BT_UART_MSG_FRAME6SNIFFINTERVAL_POS, + (BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >> + BT_UART_MSG_FRAME6DISCOVERABLE_POS); + + IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Inquiry/Page SR Mode = " + "0x%X, Connectable = 0x%X", + (BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >> + BT_UART_MSG_FRAME7SNIFFACTIVITY_POS, + (BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_MSK & uart_msg->frame7) >> + BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS, + (BT_UART_MSG_FRAME7CONNECTABLE_MSK & uart_msg->frame7) >> + BT_UART_MSG_FRAME7CONNECTABLE_POS); +} + +static void iwl6000g2b_set_kill_ack_msk(struct iwl_priv *priv, + struct iwl_bt_uart_msg *uart_msg) +{ + u8 kill_ack_msk; + __le32 bt_kill_ack_msg[2] = { + cpu_to_le32(0xFFFFFFF), cpu_to_le32(0xFFFFFC00) }; + + kill_ack_msk = (((BT_UART_MSG_FRAME3A2DP_MSK | + BT_UART_MSG_FRAME3SNIFF_MSK | + BT_UART_MSG_FRAME3SCOESCO_MSK) & + uart_msg->frame3) == 0) ? 1 : 0; + if (priv->kill_ack_mask != bt_kill_ack_msg[kill_ack_msk]) { + priv->bt_valid |= IWL6000G2B_BT_VALID_KILL_ACK_MASK; + priv->kill_ack_mask = bt_kill_ack_msg[kill_ack_msk]; + /* schedule to send runtime bt_config */ + queue_work(priv->workqueue, &priv->bt_runtime_config); + } + +} + static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -460,16 +546,13 @@ static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv, struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; struct iwl6000g2b_bt_sco_cmd sco_cmd = { .flags = 0 }; + struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg; IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n"); IWL_DEBUG_NOTIF(priv, " status: %d\n", coex->bt_status); IWL_DEBUG_NOTIF(priv, " traffic load: %d\n", coex->bt_traffic_load); IWL_DEBUG_NOTIF(priv, " CI compliance: %d\n", coex->bt_ci_compliance); - IWL_DEBUG_NOTIF(priv, " UART msg: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x:" - "%.2x:%.2x\n", - coex->uart_msg[0], coex->uart_msg[1], coex->uart_msg[2], - coex->uart_msg[3], coex->uart_msg[4], coex->uart_msg[5], - coex->uart_msg[6], coex->uart_msg[7]); + iwlagn_print_uartmsg(priv, uart_msg); priv->notif_bt_traffic_load = coex->bt_traffic_load; @@ -481,14 +564,19 @@ static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv, &priv->bt_traffic_change_work); } - /* FIXME: add defines for this check */ - priv->bt_sco_active = coex->uart_msg[3] & 1; - if (priv->bt_sco_active) - sco_cmd.flags |= IWL6000G2B_BT_SCO_ACTIVE; - iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO, + if (priv->bt_sco_active != + (uart_msg->frame3 & BT_UART_MSG_FRAME3SCOESCO_MSK)) { + priv->bt_sco_active = uart_msg->frame3 & + BT_UART_MSG_FRAME3SCOESCO_MSK; + if (priv->bt_sco_active) + sco_cmd.flags |= IWL6000G2B_BT_SCO_ACTIVE; + iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO, sizeof(sco_cmd), &sco_cmd, NULL); + } } + iwl6000g2b_set_kill_ack_msk(priv, uart_msg); + /* FIXME: based on notification, adjust the prio_boost */ spin_lock_irqsave(&priv->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 2dc569bc7e8f..771ceffb8f8b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -464,7 +464,12 @@ int iwlagn_alive_notify(struct iwl_priv *priv) if (priv->cfg->advanced_bt_coexist) { /* Configure Bluetooth device coexistence support */ /* need to perform this before any calibration */ + priv->bt_valid = IWL6000G2B_BT_ALL_VALID_MSK; + priv->kill_ack_mask = IWL6000G2B_BT_KILL_ACK_MASK_DEFAULT; + priv->kill_cts_mask = IWL6000G2B_BT_KILL_CTS_MASK_DEFAULT; priv->cfg->ops->hcmd->send_bt_config(priv); + priv->bt_valid = IWL6000G2B_BT_VALID_ENABLE_FLAGS; + if (bt_coex_active && priv->iw_mode != NL80211_IFTYPE_ADHOC) { iwlagn_send_prio_tbl(priv); iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 06e89d474d04..0c457be7bc01 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -614,6 +614,20 @@ static void iwl_bg_beacon_update(struct work_struct *work) iwl_send_beacon_cmd(priv); } +static void iwl_bg_bt_runtime_config(struct work_struct *work) +{ + struct iwl_priv *priv = + container_of(work, struct iwl_priv, bt_runtime_config); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + /* dont send host command if rf-kill is on */ + if (!iwl_is_ready_rf(priv)) + return; + priv->cfg->ops->hcmd->send_bt_config(priv); +} + static void iwl_bg_bt_full_concurrency(struct work_struct *work) { struct iwl_priv *priv = @@ -3895,6 +3909,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); + INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); @@ -3938,6 +3953,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->run_time_calib_work); cancel_work_sync(&priv->beacon_update); cancel_work_sync(&priv->bt_full_concurrency); + cancel_work_sync(&priv->bt_runtime_config); del_timer_sync(&priv->statistics_periodic); del_timer_sync(&priv->ucode_trace); } diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e742f994ff82..7369c52d42dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -4057,7 +4057,7 @@ struct iwl_coex_event_resp { /* * BT Status notification - * REPLY_BT_COEX_PROFILE_NOTIF = 0xcb + * REPLY_BT_COEX_PROFILE_NOTIF = 0xce */ enum iwl_bt_coex_profile_traffic_load { IWL_BT_COEX_TRAFFIC_LOAD_NONE = 0, @@ -4070,8 +4070,114 @@ enum iwl_bt_coex_profile_traffic_load { */ }; +#define BT_UART_MSG_FRAME1MSGTYPE_POS (0) +#define BT_UART_MSG_FRAME1MSGTYPE_MSK \ + (0x7 << BT_UART_MSG_FRAME1MSGTYPE_POS) +#define BT_UART_MSG_FRAME1SSN_POS (3) +#define BT_UART_MSG_FRAME1SSN_MSK \ + (0x3 << BT_UART_MSG_FRAME1SSN_POS) +#define BT_UART_MSG_FRAME1UPDATEREQ_POS (5) +#define BT_UART_MSG_FRAME1UPDATEREQ_MSK \ + (0x1 << BT_UART_MSG_FRAME1UPDATEREQ_POS) +#define BT_UART_MSG_FRAME1RESERVED_POS (6) +#define BT_UART_MSG_FRAME1RESERVED_MSK \ + (0x3 << BT_UART_MSG_FRAME1RESERVED_POS) + +#define BT_UART_MSG_FRAME2OPENCONNECTIONS_POS (0) +#define BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK \ + (0x3 << BT_UART_MSG_FRAME2OPENCONNECTIONS_POS) +#define BT_UART_MSG_FRAME2TRAFFICLOAD_POS (2) +#define BT_UART_MSG_FRAME2TRAFFICLOAD_MSK \ + (0x3 << BT_UART_MSG_FRAME2TRAFFICLOAD_POS) +#define BT_UART_MSG_FRAME2CHLSEQN_POS (4) +#define BT_UART_MSG_FRAME2CHLSEQN_MSK \ + (0x1 << BT_UART_MSG_FRAME2CHLSEQN_POS) +#define BT_UART_MSG_FRAME2INBAND_POS (5) +#define BT_UART_MSG_FRAME2INBAND_MSK \ + (0x1 << BT_UART_MSG_FRAME2INBAND_POS) +#define BT_UART_MSG_FRAME2RESERVED_POS (6) +#define BT_UART_MSG_FRAME2RESERVED_MSK \ + (0x3 << BT_UART_MSG_FRAME2RESERVED_POS) + +#define BT_UART_MSG_FRAME3SCOESCO_POS (0) +#define BT_UART_MSG_FRAME3SCOESCO_MSK \ + (0x1 << BT_UART_MSG_FRAME3SCOESCO_POS) +#define BT_UART_MSG_FRAME3SNIFF_POS (1) +#define BT_UART_MSG_FRAME3SNIFF_MSK \ + (0x1 << BT_UART_MSG_FRAME3SNIFF_POS) +#define BT_UART_MSG_FRAME3A2DP_POS (2) +#define BT_UART_MSG_FRAME3A2DP_MSK \ + (0x1 << BT_UART_MSG_FRAME3A2DP_POS) +#define BT_UART_MSG_FRAME3ACL_POS (3) +#define BT_UART_MSG_FRAME3ACL_MSK \ + (0x1 << BT_UART_MSG_FRAME3ACL_POS) +#define BT_UART_MSG_FRAME3MASTER_POS (4) +#define BT_UART_MSG_FRAME3MASTER_MSK \ + (0x1 << BT_UART_MSG_FRAME3MASTER_POS) +#define BT_UART_MSG_FRAME3OBEX_POS (5) +#define BT_UART_MSG_FRAME3OBEX_MSK \ + (0x1 << BT_UART_MSG_FRAME3OBEX_POS) +#define BT_UART_MSG_FRAME3RESERVED_POS (6) +#define BT_UART_MSG_FRAME3RESERVED_MSK \ + (0x3 << BT_UART_MSG_FRAME3RESERVED_POS) + +#define BT_UART_MSG_FRAME4IDLEDURATION_POS (0) +#define BT_UART_MSG_FRAME4IDLEDURATION_MSK \ + (0x3F << BT_UART_MSG_FRAME4IDLEDURATION_POS) +#define BT_UART_MSG_FRAME4RESERVED_POS (6) +#define BT_UART_MSG_FRAME4RESERVED_MSK \ + (0x3 << BT_UART_MSG_FRAME4RESERVED_POS) + +#define BT_UART_MSG_FRAME5TXACTIVITY_POS (0) +#define BT_UART_MSG_FRAME5TXACTIVITY_MSK \ + (0x3 << BT_UART_MSG_FRAME5TXACTIVITY_POS) +#define BT_UART_MSG_FRAME5RXACTIVITY_POS (2) +#define BT_UART_MSG_FRAME5RXACTIVITY_MSK \ + (0x3 << BT_UART_MSG_FRAME5RXACTIVITY_POS) +#define BT_UART_MSG_FRAME5ESCORETRANSMIT_POS (4) +#define BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK \ + (0x3 << BT_UART_MSG_FRAME5ESCORETRANSMIT_POS) +#define BT_UART_MSG_FRAME5RESERVED_POS (6) +#define BT_UART_MSG_FRAME5RESERVED_MSK \ + (0x3 << BT_UART_MSG_FRAME5RESERVED_POS) + +#define BT_UART_MSG_FRAME6SNIFFINTERVAL_POS (0) +#define BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK \ + (0x1F << BT_UART_MSG_FRAME6SNIFFINTERVAL_POS) +#define BT_UART_MSG_FRAME6DISCOVERABLE_POS (5) +#define BT_UART_MSG_FRAME6DISCOVERABLE_MSK \ + (0x1 << BT_UART_MSG_FRAME6DISCOVERABLE_POS) +#define BT_UART_MSG_FRAME6RESERVED_POS (6) +#define BT_UART_MSG_FRAME6RESERVED_MSK \ + (0x3 << BT_UART_MSG_FRAME6RESERVED_POS) + +#define BT_UART_MSG_FRAME7SNIFFACTIVITY_POS (0) +#define BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK \ + (0x7 << BT_UART_MSG_FRAME7SNIFFACTIVITY_POS) +#define BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS (3) +#define BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_MSK \ + (0x3 << BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS) +#define BT_UART_MSG_FRAME7CONNECTABLE_POS (5) +#define BT_UART_MSG_FRAME7CONNECTABLE_MSK \ + (0x1 << BT_UART_MSG_FRAME7CONNECTABLE_POS) +#define BT_UART_MSG_FRAME7RESERVED_POS (6) +#define BT_UART_MSG_FRAME7RESERVED_MSK \ + (0x3 << BT_UART_MSG_FRAME7RESERVED_POS) + + +struct iwl_bt_uart_msg { + u8 header; + u8 frame1; + u8 frame2; + u8 frame3; + u8 frame4; + u8 frame5; + u8 frame6; + u8 frame7; +} __attribute__((packed)); + struct iwl_bt_coex_profile_notif { - u8 uart_msg[8]; + struct iwl_bt_uart_msg last_bt_uart_msg; u8 bt_status; /* 0 - off, 1 - on */ u8 bt_traffic_load; /* 0 .. 3? */ u8 bt_ci_compliance; /* 0 - not complied, 1 - complied */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index bb92a7f01988..e0d524d633bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1370,6 +1370,9 @@ struct iwl_priv { bool bt_sco_active; bool bt_full_concurrent; bool bt_ant_couple_ok; + __le32 kill_ack_mask; + __le32 kill_cts_mask; + __le16 bt_valid; u8 bt_ci_compliance; struct work_struct bt_traffic_change_work; @@ -1392,6 +1395,7 @@ struct iwl_priv { struct work_struct start_internal_scan; struct work_struct tx_flush; struct work_struct bt_full_concurrency; + struct work_struct bt_runtime_config; struct tasklet_struct irq_tasklet; -- cgit v1.2.3-59-g8ed1b From 22bf59a03aacc221483e5aad1af903fc191ae958 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:11 -0700 Subject: iwlagn: add additional bt related parameters Add additional bt coex related parameters and initialize at init time. Thoese parameters will be used in later implementations. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 +++++++++++ drivers/net/wireless/iwlwifi/iwl-commands.h | 16 ++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 5 +++++ 3 files changed, 32 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0c457be7bc01..e8098a798240 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -4014,6 +4014,17 @@ static int iwl_init_drv(struct iwl_priv *priv) iwl_init_scan_params(priv); + /* init bt coex */ + if (priv->cfg->advanced_bt_coexist) { + priv->kill_ack_mask = IWL6000G2B_BT_KILL_ACK_MASK_DEFAULT; + priv->kill_cts_mask = IWL6000G2B_BT_KILL_CTS_MASK_DEFAULT; + priv->bt_valid = IWL6000G2B_BT_ALL_VALID_MSK; + priv->bt_on_thresh = BT_ON_THRESHOLD_DEF; + priv->bt_duration = BT_DURATION_LIMIT_DEF; + priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; + priv->dynamic_agg_thresh = BT_AGG_THRESHOLD_DEF; + } + /* Set the tx_power_user_lmt to the lowest power level * this value will get overwritten by channel max power avg * from eeprom */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 7369c52d42dd..5df22f1d57a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2379,6 +2379,22 @@ struct iwl_link_quality_cmd { #define BT_MAX_KILL_DEF (0x5) #define BT_MAX_KILL_MAX (0xFF) +#define BT_DURATION_LIMIT_DEF 625 +#define BT_DURATION_LIMIT_MAX 1250 +#define BT_DURATION_LIMIT_MIN 625 + +#define BT_ON_THRESHOLD_DEF 4 +#define BT_ON_THRESHOLD_MAX 1000 +#define BT_ON_THRESHOLD_MIN 1 + +#define BT_FRAG_THRESHOLD_DEF 0 +#define BT_FRAG_THRESHOLD_MAX 0 +#define BT_FRAG_THRESHOLD_MIN 0 + +#define BT_AGG_THRESHOLD_DEF 0 +#define BT_AGG_THRESHOLD_MAX 0 +#define BT_AGG_THRESHOLD_MIN 0 + /* * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) * diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index e0d524d633bb..836fe2762464 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1366,6 +1366,7 @@ struct iwl_priv { #endif }; + /* bt coex */ u8 bt_traffic_load, notif_bt_traffic_load; bool bt_sco_active; bool bt_full_concurrent; @@ -1373,6 +1374,10 @@ struct iwl_priv { __le32 kill_ack_mask; __le32 kill_cts_mask; __le16 bt_valid; + u16 bt_on_thresh; + u16 bt_duration; + u16 dynamic_frag_thresh; + u16 dynamic_agg_thresh; u8 bt_ci_compliance; struct work_struct bt_traffic_change_work; -- cgit v1.2.3-59-g8ed1b From f37837c962c309f1d90636626c779497b614be42 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:12 -0700 Subject: iwlagn: add bt_ch_announce module parameter Add bt_ch_announce module parameter to enable/disable BT channel announcement mode; default is "enable" Based on the bt channel announcement module parameter to configure the bt_config host command. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 6 ++++-- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 +++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index e4873cc2a57a..ebf0c7ecef4e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -242,9 +242,11 @@ static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) { bt_cmd.flags = 0; } else { - bt_cmd.flags = IWL6000G2B_BT_FLAG_CHANNEL_INHIBITION | - IWL6000G2B_BT_FLAG_COEX_MODE_3W << + bt_cmd.flags = IWL6000G2B_BT_FLAG_COEX_MODE_3W << IWL6000G2B_BT_FLAG_COEX_MODE_SHIFT; + if (priv->bt_ch_announce) + bt_cmd.flags |= IWL6000G2B_BT_FLAG_CHANNEL_INHIBITION; + IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", bt_cmd.flags); } if (priv->bt_full_concurrent) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e8098a798240..989e4a702602 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -88,6 +88,7 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("iwl4965"); static int iwlagn_ant_coupling; +static bool iwlagn_bt_ch_announce = 1; /** * iwl_commit_rxon - commit staging_rxon to hardware @@ -2606,6 +2607,9 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, return pos; } + /* enable/disable bt channel announcement */ + priv->bt_ch_announce = iwlagn_bt_ch_announce; + #ifdef CONFIG_IWLWIFI_DEBUG if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) @@ -4150,6 +4154,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? true : false; + /* enable/disable bt channel announcement */ + priv->bt_ch_announce = iwlagn_bt_ch_announce; + if (iwl_alloc_traffic_mem(priv)) IWL_ERR(priv, "Not enough memory to generate traffic log\n"); @@ -4687,3 +4694,7 @@ MODULE_PARM_DESC(ucode_alternative, module_param_named(antenna_coupling, iwlagn_ant_coupling, int, S_IRUGO); MODULE_PARM_DESC(antenna_coupling, "specify antenna coupling in dB (defualt: 0 dB)"); + +module_param_named(bt_ch_announce, iwlagn_bt_ch_announce, bool, S_IRUGO); +MODULE_PARM_DESC(bt_ch_announce, + "Enable BT channel announcement mode (default: enable)"); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 836fe2762464..1adb68e92e8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1368,6 +1368,7 @@ struct iwl_priv { /* bt coex */ u8 bt_traffic_load, notif_bt_traffic_load; + bool bt_ch_announce; bool bt_sco_active; bool bt_full_concurrent; bool bt_ant_couple_ok; -- cgit v1.2.3-59-g8ed1b From da5dbb971573efda54c7c39e7e4ccd3fc7c86e49 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:13 -0700 Subject: iwlagn: set traffic load based on multiple factors Current BT traffic load should based on the following conditions: 1. BT On/Off status 2. Channel announcement enable/disable 3. Curren traffic load report from uCode Need to modify rate scale to down-grade from MIMO to SISO if detected high BT traffic load. Also need to make sure not using chain "B" with high BT traffic or if it is in "full concurrency" mode. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 29 ++++++-- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 113 +++++++++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++ drivers/net/wireless/iwlwifi/iwl-core.c | 16 +++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 5 files changed, 112 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index ebf0c7ecef4e..30dc1f334202 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -428,6 +428,9 @@ static void iwl6000g2b_bt_traffic_change_work(struct work_struct *work) container_of(work, struct iwl_priv, bt_traffic_change_work); int smps_request = -1; + IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n", + priv->bt_traffic_load); + switch (priv->bt_traffic_load) { case IWL_BT_COEX_TRAFFIC_LOAD_NONE: smps_request = IEEE80211_SMPS_AUTOMATIC; @@ -447,6 +450,9 @@ static void iwl6000g2b_bt_traffic_change_work(struct work_struct *work) mutex_lock(&priv->mutex); + if (priv->cfg->ops->lib->update_chain_flags) + priv->cfg->ops->lib->update_chain_flags(priv); + if (smps_request != -1 && priv->vif && priv->vif->type == NL80211_IFTYPE_STATION) ieee80211_request_smps(priv->vif, smps_request); @@ -549,6 +555,7 @@ static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv, struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; struct iwl6000g2b_bt_sco_cmd sco_cmd = { .flags = 0 }; struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg; + u8 last_traffic_load; IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n"); IWL_DEBUG_NOTIF(priv, " status: %d\n", coex->bt_status); @@ -556,16 +563,28 @@ static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv, IWL_DEBUG_NOTIF(priv, " CI compliance: %d\n", coex->bt_ci_compliance); iwlagn_print_uartmsg(priv, uart_msg); + last_traffic_load = priv->notif_bt_traffic_load; priv->notif_bt_traffic_load = coex->bt_traffic_load; - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - if (coex->bt_traffic_load != priv->bt_traffic_load) { - priv->bt_traffic_load = coex->bt_traffic_load; - + if (priv->bt_status != coex->bt_status || + last_traffic_load != coex->bt_traffic_load) { + if (coex->bt_status) { + /* BT on */ + if (!priv->bt_ch_announce) + priv->bt_traffic_load = + IWL_BT_COEX_TRAFFIC_LOAD_HIGH; + else + priv->bt_traffic_load = + coex->bt_traffic_load; + } else { + /* BT off */ + priv->bt_traffic_load = + IWL_BT_COEX_TRAFFIC_LOAD_NONE; + } + priv->bt_status = coex->bt_status; queue_work(priv->workqueue, &priv->bt_traffic_change_work); } - if (priv->bt_sco_active != (uart_msg->frame3 & BT_UART_MSG_FRAME3SCOESCO_MSK)) { priv->bt_sco_active = uart_msg->frame3 & diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 687b534d83d0..e78f3f0592d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -82,7 +82,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta); static void rs_fill_link_cmd(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, u32 rate_n_flags); -static void rs_stay_in_table(struct iwl_lq_sta *lq_sta); +static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); #ifdef CONFIG_MAC80211_DEBUGFS @@ -900,7 +900,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, * no matching table found, let's by-pass the data collection * and continue to perform rate scale to find the rate table */ - rs_stay_in_table(lq_sta); + rs_stay_in_table(lq_sta, true); goto done; } @@ -1334,15 +1334,17 @@ static int rs_move_legacy_other(struct iwl_priv *priv, break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: /* avoid antenna B unless MIMO */ + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2) tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; break; case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: /* avoid antenna B and MIMO */ + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && tbl->action != IWL_LEGACY_SWITCH_SISO) - tbl->action = IWL_SISO_SWITCH_ANTENNA1; + tbl->action = IWL_LEGACY_SWITCH_SISO; break; default: IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); @@ -1362,6 +1364,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) tbl->action = IWL_LEGACY_SWITCH_SISO; + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); } start_action = tbl->action; @@ -1379,7 +1382,10 @@ static int rs_move_legacy_other(struct iwl_priv *priv, break; /* Don't change antenna if success has been great */ - if (window->success_ratio >= IWL_RS_GOOD_RATIO) + if (window->success_ratio >= IWL_RS_GOOD_RATIO && + !priv->bt_full_concurrent && + priv->bt_traffic_load == + IWL_BT_COEX_TRAFFIC_LOAD_NONE) break; /* Set up search table to try other antenna */ @@ -1503,14 +1509,15 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: /* avoid antenna B unless MIMO */ + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) tbl->action = IWL_SISO_SWITCH_ANTENNA1; break; case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: /* avoid antenna B and MIMO */ - if (tbl->action >= IWL_SISO_SWITCH_ANTENNA2 && - tbl->action != IWL_SISO_SWITCH_GI) + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); + if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) tbl->action = IWL_SISO_SWITCH_ANTENNA1; break; default: @@ -1525,9 +1532,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, } /* configure as 1x1 if bt full concurrency */ - if (priv->bt_full_concurrent && - tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) - tbl->action = IWL_SISO_SWITCH_ANTENNA1; + if (priv->bt_full_concurrent) { + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); + if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) + tbl->action = IWL_SISO_SWITCH_ANTENNA1; + } start_action = tbl->action; for (;;) { @@ -1536,14 +1545,16 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, case IWL_SISO_SWITCH_ANTENNA1: case IWL_SISO_SWITCH_ANTENNA2: IWL_DEBUG_RATE(priv, "LQ: SISO toggle Antenna\n"); - if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 && - tx_chains_num <= 1) || + tx_chains_num <= 1) || (tbl->action == IWL_SISO_SWITCH_ANTENNA2 && - tx_chains_num <= 2)) + tx_chains_num <= 2)) break; - if (window->success_ratio >= IWL_RS_GOOD_RATIO) + if (window->success_ratio >= IWL_RS_GOOD_RATIO && + !priv->bt_full_concurrent && + priv->bt_traffic_load == + IWL_BT_COEX_TRAFFIC_LOAD_NONE) break; memcpy(search_tbl, tbl, sz); @@ -1670,13 +1681,13 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: /* avoid antenna B and MIMO */ - if (tbl->action == IWL_MIMO2_SWITCH_MIMO3_ABC) - tbl->action = IWL_SISO_SWITCH_ANTENNA1; + if (tbl->action != IWL_MIMO2_SWITCH_SISO_A) + tbl->action = IWL_MIMO2_SWITCH_SISO_A; + break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: /* avoid antenna B unless MIMO */ - if (tbl->action == IWL_MIMO2_SWITCH_ANTENNA2) - tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; - else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B) + if (tbl->action == IWL_MIMO2_SWITCH_SISO_B || + tbl->action == IWL_MIMO2_SWITCH_SISO_C) tbl->action = IWL_MIMO2_SWITCH_SISO_A; break; default: @@ -1840,16 +1851,14 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: /* avoid antenna B and MIMO */ - if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AB || - tbl->action == IWL_MIMO3_SWITCH_MIMO2_AC || - tbl->action == IWL_MIMO3_SWITCH_MIMO2_BC) + if (tbl->action != IWL_MIMO3_SWITCH_SISO_A) tbl->action = IWL_MIMO3_SWITCH_SISO_A; + break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: /* avoid antenna B unless MIMO */ - if (tbl->action == IWL_MIMO3_SWITCH_SISO_B) + if (tbl->action == IWL_MIMO3_SWITCH_SISO_B || + tbl->action == IWL_MIMO3_SWITCH_SISO_C) tbl->action = IWL_MIMO3_SWITCH_SISO_A; - else if (tbl->action == IWL_MIMO3_SWITCH_ANTENNA2) - tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; break; default: IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); @@ -1996,7 +2005,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, * 2) # times calling this function * 3) elapsed time in this mode (not used, for now) */ -static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) +static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) { struct iwl_scale_tbl_info *tbl; int i; @@ -2027,7 +2036,8 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) * allow a new search. Also (below) reset all bitmaps and * stats in active history. */ - if ((lq_sta->total_failed > lq_sta->max_failure_limit) || + if (force_search || + (lq_sta->total_failed > lq_sta->max_failure_limit) || (lq_sta->total_success > lq_sta->max_success_limit) || ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer) && (flush_interval_passed))) { @@ -2243,7 +2253,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, /* Should we stay with this modulation mode, * or search for a new one? */ - rs_stay_in_table(lq_sta); + rs_stay_in_table(lq_sta, false); goto out; } @@ -2392,16 +2402,25 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) scale_action = -1; - if (lq_sta->last_bt_traffic > priv->bt_traffic_load) { - lq_sta->last_bt_traffic = priv->bt_traffic_load; - /* - * don't set scale_action, don't want to scale up if - * the rate scale doesn't otherwise think that is a - * good idea. - */ - } else if (lq_sta->last_bt_traffic < priv->bt_traffic_load) { - lq_sta->last_bt_traffic = priv->bt_traffic_load; - scale_action = -1; + if ((priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && + (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) { + if (lq_sta->last_bt_traffic > priv->bt_traffic_load) { + /* + * don't set scale_action, don't want to scale up if + * the rate scale doesn't otherwise think that is a + * good idea. + */ + } else if (lq_sta->last_bt_traffic <= priv->bt_traffic_load) { + scale_action = -1; + } + } + lq_sta->last_bt_traffic = priv->bt_traffic_load; + + if ((priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && + (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) { + /* search for a new modulation */ + rs_stay_in_table(lq_sta, true); + goto lq_update; } switch (scale_action) { @@ -2440,7 +2459,7 @@ lq_update: if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) { /* Should we stay with this modulation mode, * or search for a new one? */ - rs_stay_in_table(lq_sta); + rs_stay_in_table(lq_sta, false); } /* * Search for new modulation mode if we're: @@ -2786,6 +2805,12 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, &rate_idx); + if (priv && priv->bt_full_concurrent) { + /* 1x1 only */ + tbl_type.ant_type = + first_antenna(priv->hw_params.valid_tx_ant); + } + /* How many times should we repeat the initial rate? */ if (is_legacy(tbl_type.lq_type)) { ant_toggle_cnt = 1; @@ -2800,8 +2825,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, /* Fill 1st table entry (index 0) */ lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate); - if (num_of_ant(tbl_type.ant_type) == 1 || - (priv && priv->bt_full_concurrent)) { + if (num_of_ant(tbl_type.ant_type) == 1) { lq_cmd->general_params.single_stream_ant_msk = tbl_type.ant_type; } else if (num_of_ant(tbl_type.ant_type) == 2) { @@ -2811,7 +2835,6 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, index++; repeat_rate--; - if (priv) { if (priv->bt_full_concurrent) valid_tx_ant = ANT_A; @@ -2832,7 +2855,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, rs_toggle_antenna(valid_tx_ant, &new_rate, &tbl_type)) ant_toggle_cnt = 1; -} + } /* Override next rate if needed for debug purposes */ rs_dbgfs_set_mcs(lq_sta, &new_rate, index); @@ -2847,6 +2870,12 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, &rate_idx); + if (priv && priv->bt_full_concurrent) { + /* 1x1 only */ + tbl_type.ant_type = + first_antenna(priv->hw_params.valid_tx_ant); + } + /* Indicate to uCode which entries might be MIMO. * If initial rate was MIMO, this will finally end up * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 989e4a702602..4410f820c2f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2823,6 +2823,7 @@ static void __iwl_down(struct iwl_priv *priv) iwl_clear_driver_stations(priv); /* reset BT coex data */ + priv->bt_status = 0; priv->bt_traffic_load = priv->cfg->bt_init_traffic_load; priv->bt_sco_active = false; priv->bt_full_concurrent = false; @@ -3133,6 +3134,7 @@ static void iwl_bg_restart(struct work_struct *data) bool bt_sco, bt_full_concurrent; u8 bt_ci_compliance; u8 bt_load; + u8 bt_status; mutex_lock(&priv->mutex); priv->vif = NULL; @@ -3151,6 +3153,7 @@ static void iwl_bg_restart(struct work_struct *data) bt_full_concurrent = priv->bt_full_concurrent; bt_ci_compliance = priv->bt_ci_compliance; bt_load = priv->bt_traffic_load; + bt_status = priv->bt_status; __iwl_down(priv); @@ -3158,6 +3161,7 @@ static void iwl_bg_restart(struct work_struct *data) priv->bt_full_concurrent = bt_full_concurrent; priv->bt_ci_compliance = bt_ci_compliance; priv->bt_traffic_load = bt_load; + priv->bt_status = bt_status; mutex_unlock(&priv->mutex); iwl_cancel_deferred_work(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 34cba38f1d0c..c43124c997cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -780,8 +780,12 @@ EXPORT_SYMBOL(iwl_set_rxon_ht); */ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) { - if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { - /* operated as 1x1 in full concurrency mode */ + if (priv->cfg->advanced_bt_coexist && (priv->bt_full_concurrent || + priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { + /* + * only use chain 'A' in bt high traffic load or + * full concurrency mode + */ return IWL_NUM_RX_CHAINS_SINGLE; } /* # of Rx chains to use when expecting MIMO. */ @@ -845,8 +849,12 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) else active_chains = priv->hw_params.valid_rx_ant; - if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { - /* operated as 1x1 in full concurrency mode */ + if (priv->cfg->advanced_bt_coexist && (priv->bt_full_concurrent || + priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { + /* + * only use chain 'A' in bt high traffic load or + * full concurrency mode + */ active_chains = first_antenna(active_chains); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 1adb68e92e8d..8d5201ac80f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1367,6 +1367,7 @@ struct iwl_priv { }; /* bt coex */ + u8 bt_status; u8 bt_traffic_load, notif_bt_traffic_load; bool bt_ch_announce; bool bt_sco_active; -- cgit v1.2.3-59-g8ed1b From b6e116e8bf7d749b0743c167bd47930c22c77a82 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:14 -0700 Subject: iwlagn: generic bt coex functions Move bt coex functions to iwl-agn-lib.c, so those functions can be shared by multiple wifi/bt combo devices Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 391 +-------------------------- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 8 + drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 370 +++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 8 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 9 + drivers/net/wireless/iwlwifi/iwl-commands.h | 74 ++--- 7 files changed, 441 insertions(+), 425 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 30dc1f334202..fc9344b873ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -122,165 +122,6 @@ static void iwl6000_nic_config(struct iwl_priv *priv) priv->cfg->ops->lib->temp_ops.set_calib_version(priv); } -/* - * Macros to access the lookup table. - * - * The lookup table has 7 inputs: bt3_prio, bt3_txrx, bt_rf_act, wifi_req, - * wifi_prio, wifi_txrx and wifi_sh_ant_req. - * - * It has three outputs: WLAN_ACTIVE, WLAN_KILL and ANT_SWITCH - * - * The format is that "registers" 8 through 11 contain the WLAN_ACTIVE bits - * one after another in 32-bit registers, and "registers" 0 through 7 contain - * the WLAN_KILL and ANT_SWITCH bits interleaved (in that order). - * - * These macros encode that format. - */ -#define LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, wifi_req, wifi_prio, \ - wifi_txrx, wifi_sh_ant_req) \ - (bt3_prio | (bt3_txrx << 1) | (bt_rf_act << 2) | (wifi_req << 3) | \ - (wifi_prio << 4) | (wifi_txrx << 5) | (wifi_sh_ant_req << 6)) - -#define LUT_PTA_WLAN_ACTIVE_OP(lut, op, val) \ - lut[8 + ((val) >> 5)] op (cpu_to_le32(BIT((val) & 0x1f))) -#define LUT_TEST_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \ - wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req) \ - (!!(LUT_PTA_WLAN_ACTIVE_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx,\ - bt_rf_act, wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)))) -#define LUT_SET_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \ - wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req) \ - LUT_PTA_WLAN_ACTIVE_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, \ - bt_rf_act, wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) -#define LUT_CLEAR_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \ - wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req) \ - LUT_PTA_WLAN_ACTIVE_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, \ - bt_rf_act, wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) - -#define LUT_WLAN_KILL_OP(lut, op, val) \ - lut[(val) >> 4] op (cpu_to_le32(BIT(((val) << 1) & 0x1e))) -#define LUT_TEST_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ - wifi_prio, wifi_txrx, wifi_sh_ant_req) \ - (!!(LUT_WLAN_KILL_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ - wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)))) -#define LUT_SET_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ - wifi_prio, wifi_txrx, wifi_sh_ant_req) \ - LUT_WLAN_KILL_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ - wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) -#define LUT_CLEAR_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ - wifi_prio, wifi_txrx, wifi_sh_ant_req) \ - LUT_WLAN_KILL_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ - wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) - -#define LUT_ANT_SWITCH_OP(lut, op, val) \ - lut[(val) >> 4] op (cpu_to_le32(BIT((((val) << 1) & 0x1e) + 1))) -#define LUT_TEST_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ - wifi_prio, wifi_txrx, wifi_sh_ant_req) \ - (!!(LUT_ANT_SWITCH_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ - wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)))) -#define LUT_SET_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ - wifi_prio, wifi_txrx, wifi_sh_ant_req) \ - LUT_ANT_SWITCH_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ - wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) -#define LUT_CLEAR_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ - wifi_prio, wifi_txrx, wifi_sh_ant_req) \ - LUT_ANT_SWITCH_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ - wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) - -static const __le32 iwl6000g2b_def_3w_lookup[12] = { - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaeaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xcc00ff28), - cpu_to_le32(0x0000aaaa), - cpu_to_le32(0xcc00aaaa), - cpu_to_le32(0x0000aaaa), - cpu_to_le32(0xc0004000), - cpu_to_le32(0x00004000), - cpu_to_le32(0xf0005000), - cpu_to_le32(0xf0004000), -}; - -static const __le32 iwl6000g2b_concurrent_lookup[12] = { - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), -}; - -static void iwl6000g2b_send_bt_config(struct iwl_priv *priv) -{ - struct iwl6000g2b_bt_cmd bt_cmd = { - .max_kill = IWL6000G2B_BT_MAX_KILL_DEFAULT, - .bt3_timer_t7_value = IWL6000G2B_BT3_T7_DEFAULT, - .bt3_prio_sample_time = IWL6000G2B_BT3_PRIO_SAMPLE_DEFAULT, - .bt3_timer_t2_value = IWL6000G2B_BT3_T2_DEFAULT, - }; - - BUILD_BUG_ON(sizeof(iwl6000g2b_def_3w_lookup) != - sizeof(bt_cmd.bt3_lookup_table)); - - bt_cmd.prio_boost = priv->cfg->bt_prio_boost; - bt_cmd.kill_ack_mask = priv->kill_ack_mask; - bt_cmd.kill_cts_mask = priv->kill_cts_mask; - bt_cmd.valid = priv->bt_valid; - - /* - * Configure BT coex mode to "no coexistence" when the - * user disabled BT coexistence, we have no interface - * user disabled BT coexistence, or the interface is in - * IBSS mode (no proper uCode support for coex then). - */ - if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) { - bt_cmd.flags = 0; - } else { - bt_cmd.flags = IWL6000G2B_BT_FLAG_COEX_MODE_3W << - IWL6000G2B_BT_FLAG_COEX_MODE_SHIFT; - if (priv->bt_ch_announce) - bt_cmd.flags |= IWL6000G2B_BT_FLAG_CHANNEL_INHIBITION; - IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", bt_cmd.flags); - } - - if (priv->bt_full_concurrent) - memcpy(bt_cmd.bt3_lookup_table, iwl6000g2b_concurrent_lookup, - sizeof(iwl6000g2b_concurrent_lookup)); - else - memcpy(bt_cmd.bt3_lookup_table, iwl6000g2b_def_3w_lookup, - sizeof(iwl6000g2b_def_3w_lookup)); - - IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n", - bt_cmd.flags ? "active" : "disabled", - priv->bt_full_concurrent ? - "full concurrency" : "3-wire"); - - if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd)) - IWL_ERR(priv, "failed to send BT Coex Config\n"); - - /* - * When we are doing a restart, need to also reconfigure BT - * SCO to the device. If not doing a restart, bt_sco_active - * will always be false, so there's no need to have an extra - * variable to check for it. - */ - if (priv->bt_sco_active) { - struct iwl6000g2b_bt_sco_cmd sco_cmd = { .flags = 0 }; - - if (priv->bt_sco_active) - sco_cmd.flags |= IWL6000G2B_BT_SCO_ACTIVE; - if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_SCO, - sizeof(sco_cmd), &sco_cmd)) - IWL_ERR(priv, "failed to send BT SCO command\n"); - } -} - static struct iwl_sensitivity_ranges iwl6000_sensitivity = { .min_nrg_cck = 97, .max_nrg_cck = 0, /* not used, set to 0 */ @@ -422,210 +263,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, return iwl_send_cmd_sync(priv, &hcmd); } -static void iwl6000g2b_bt_traffic_change_work(struct work_struct *work) -{ - struct iwl_priv *priv = - container_of(work, struct iwl_priv, bt_traffic_change_work); - int smps_request = -1; - - IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n", - priv->bt_traffic_load); - - switch (priv->bt_traffic_load) { - case IWL_BT_COEX_TRAFFIC_LOAD_NONE: - smps_request = IEEE80211_SMPS_AUTOMATIC; - break; - case IWL_BT_COEX_TRAFFIC_LOAD_LOW: - smps_request = IEEE80211_SMPS_DYNAMIC; - break; - case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: - case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: - smps_request = IEEE80211_SMPS_STATIC; - break; - default: - IWL_ERR(priv, "Invalid BT traffic load: %d\n", - priv->bt_traffic_load); - break; - } - - mutex_lock(&priv->mutex); - - if (priv->cfg->ops->lib->update_chain_flags) - priv->cfg->ops->lib->update_chain_flags(priv); - - if (smps_request != -1 && - priv->vif && priv->vif->type == NL80211_IFTYPE_STATION) - ieee80211_request_smps(priv->vif, smps_request); - - mutex_unlock(&priv->mutex); -} - -static void iwlagn_print_uartmsg(struct iwl_priv *priv, - struct iwl_bt_uart_msg *uart_msg) -{ - IWL_DEBUG_NOTIF(priv, "Message Type = 0x%X, SSN = 0x%X, " - "Update Req = 0x%X", - (BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >> - BT_UART_MSG_FRAME1MSGTYPE_POS, - (BT_UART_MSG_FRAME1SSN_MSK & uart_msg->frame1) >> - BT_UART_MSG_FRAME1SSN_POS, - (BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >> - BT_UART_MSG_FRAME1UPDATEREQ_POS); - - IWL_DEBUG_NOTIF(priv, "Open connections = 0x%X, Traffic load = 0x%X, " - "Chl_SeqN = 0x%X, In band = 0x%X", - (BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >> - BT_UART_MSG_FRAME2OPENCONNECTIONS_POS, - (BT_UART_MSG_FRAME2TRAFFICLOAD_MSK & uart_msg->frame2) >> - BT_UART_MSG_FRAME2TRAFFICLOAD_POS, - (BT_UART_MSG_FRAME2CHLSEQN_MSK & uart_msg->frame2) >> - BT_UART_MSG_FRAME2CHLSEQN_POS, - (BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >> - BT_UART_MSG_FRAME2INBAND_POS); - - IWL_DEBUG_NOTIF(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, " - "ACL = 0x%X, Master = 0x%X, OBEX = 0x%X", - (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >> - BT_UART_MSG_FRAME3SCOESCO_POS, - (BT_UART_MSG_FRAME3SNIFF_MSK & uart_msg->frame3) >> - BT_UART_MSG_FRAME3SNIFF_POS, - (BT_UART_MSG_FRAME3A2DP_MSK & uart_msg->frame3) >> - BT_UART_MSG_FRAME3A2DP_POS, - (BT_UART_MSG_FRAME3ACL_MSK & uart_msg->frame3) >> - BT_UART_MSG_FRAME3ACL_POS, - (BT_UART_MSG_FRAME3MASTER_MSK & uart_msg->frame3) >> - BT_UART_MSG_FRAME3MASTER_POS, - (BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >> - BT_UART_MSG_FRAME3OBEX_POS); - - IWL_DEBUG_NOTIF(priv, "Idle duration = 0x%X", - (BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >> - BT_UART_MSG_FRAME4IDLEDURATION_POS); - - IWL_DEBUG_NOTIF(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, " - "eSCO Retransmissions = 0x%X", - (BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >> - BT_UART_MSG_FRAME5TXACTIVITY_POS, - (BT_UART_MSG_FRAME5RXACTIVITY_MSK & uart_msg->frame5) >> - BT_UART_MSG_FRAME5RXACTIVITY_POS, - (BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >> - BT_UART_MSG_FRAME5ESCORETRANSMIT_POS); - - IWL_DEBUG_NOTIF(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X", - (BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >> - BT_UART_MSG_FRAME6SNIFFINTERVAL_POS, - (BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >> - BT_UART_MSG_FRAME6DISCOVERABLE_POS); - - IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Inquiry/Page SR Mode = " - "0x%X, Connectable = 0x%X", - (BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >> - BT_UART_MSG_FRAME7SNIFFACTIVITY_POS, - (BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_MSK & uart_msg->frame7) >> - BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS, - (BT_UART_MSG_FRAME7CONNECTABLE_MSK & uart_msg->frame7) >> - BT_UART_MSG_FRAME7CONNECTABLE_POS); -} - -static void iwl6000g2b_set_kill_ack_msk(struct iwl_priv *priv, - struct iwl_bt_uart_msg *uart_msg) -{ - u8 kill_ack_msk; - __le32 bt_kill_ack_msg[2] = { - cpu_to_le32(0xFFFFFFF), cpu_to_le32(0xFFFFFC00) }; - - kill_ack_msk = (((BT_UART_MSG_FRAME3A2DP_MSK | - BT_UART_MSG_FRAME3SNIFF_MSK | - BT_UART_MSG_FRAME3SCOESCO_MSK) & - uart_msg->frame3) == 0) ? 1 : 0; - if (priv->kill_ack_mask != bt_kill_ack_msg[kill_ack_msk]) { - priv->bt_valid |= IWL6000G2B_BT_VALID_KILL_ACK_MASK; - priv->kill_ack_mask = bt_kill_ack_msg[kill_ack_msk]; - /* schedule to send runtime bt_config */ - queue_work(priv->workqueue, &priv->bt_runtime_config); - } - -} - -static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - unsigned long flags; - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; - struct iwl6000g2b_bt_sco_cmd sco_cmd = { .flags = 0 }; - struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg; - u8 last_traffic_load; - - IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n"); - IWL_DEBUG_NOTIF(priv, " status: %d\n", coex->bt_status); - IWL_DEBUG_NOTIF(priv, " traffic load: %d\n", coex->bt_traffic_load); - IWL_DEBUG_NOTIF(priv, " CI compliance: %d\n", coex->bt_ci_compliance); - iwlagn_print_uartmsg(priv, uart_msg); - - last_traffic_load = priv->notif_bt_traffic_load; - priv->notif_bt_traffic_load = coex->bt_traffic_load; - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - if (priv->bt_status != coex->bt_status || - last_traffic_load != coex->bt_traffic_load) { - if (coex->bt_status) { - /* BT on */ - if (!priv->bt_ch_announce) - priv->bt_traffic_load = - IWL_BT_COEX_TRAFFIC_LOAD_HIGH; - else - priv->bt_traffic_load = - coex->bt_traffic_load; - } else { - /* BT off */ - priv->bt_traffic_load = - IWL_BT_COEX_TRAFFIC_LOAD_NONE; - } - priv->bt_status = coex->bt_status; - queue_work(priv->workqueue, - &priv->bt_traffic_change_work); - } - if (priv->bt_sco_active != - (uart_msg->frame3 & BT_UART_MSG_FRAME3SCOESCO_MSK)) { - priv->bt_sco_active = uart_msg->frame3 & - BT_UART_MSG_FRAME3SCOESCO_MSK; - if (priv->bt_sco_active) - sco_cmd.flags |= IWL6000G2B_BT_SCO_ACTIVE; - iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO, - sizeof(sco_cmd), &sco_cmd, NULL); - } - } - - iwl6000g2b_set_kill_ack_msk(priv, uart_msg); - - /* FIXME: based on notification, adjust the prio_boost */ - - spin_lock_irqsave(&priv->lock, flags); - priv->bt_ci_compliance = coex->bt_ci_compliance; - spin_unlock_irqrestore(&priv->lock, flags); -} - -void iwl6000g2b_rx_handler_setup(struct iwl_priv *priv) -{ - iwlagn_rx_handler_setup(priv); - priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] = - iwl6000g2b_bt_coex_profile_notif; -} - -static void iwl6000g2b_bt_setup_deferred_work(struct iwl_priv *priv) -{ - iwlagn_setup_deferred_work(priv); - - INIT_WORK(&priv->bt_traffic_change_work, - iwl6000g2b_bt_traffic_change_work); - -} - -static void iwl6000g2b_bt_cancel_deferred_work(struct iwl_priv *priv) -{ - cancel_work_sync(&priv->bt_traffic_change_work); -} - static struct iwl_lib_ops iwl6000_lib = { .set_hw_params = iwl6000_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, @@ -710,9 +347,9 @@ static struct iwl_lib_ops iwl6000g2b_lib = { .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, - .rx_handler_setup = iwl6000g2b_rx_handler_setup, - .setup_deferred_work = iwl6000g2b_bt_setup_deferred_work, - .cancel_deferred_work = iwl6000g2b_bt_cancel_deferred_work, + .rx_handler_setup = iwlagn_bt_rx_handler_setup, + .setup_deferred_work = iwlagn_bt_setup_deferred_work, + .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .load_ucode = iwlagn_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, @@ -782,17 +419,9 @@ static const struct iwl_ops iwl6000_ops = { .led = &iwlagn_led_ops, }; -static struct iwl_hcmd_ops iwl6000g2b_hcmd = { - .rxon_assoc = iwlagn_send_rxon_assoc, - .commit_rxon = iwl_commit_rxon, - .set_rxon_chain = iwl_set_rxon_chain, - .set_tx_ant = iwlagn_send_tx_ant_config, - .send_bt_config = iwl6000g2b_send_bt_config, -}; - static const struct iwl_ops iwl6000g2b_ops = { .lib = &iwl6000g2b_lib, - .hcmd = &iwl6000g2b_hcmd, + .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, }; @@ -945,7 +574,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, - .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, + .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, }; struct iwl_cfg iwl6000g2b_2abg_cfg = { @@ -986,7 +615,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, - .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, + .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, }; struct iwl_cfg iwl6000g2b_2bgn_cfg = { @@ -1029,7 +658,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, - .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, + .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, }; struct iwl_cfg iwl6000g2b_2bg_cfg = { @@ -1070,7 +699,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, - .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, + .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, }; struct iwl_cfg iwl6000g2b_bgn_cfg = { @@ -1113,7 +742,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, - .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, + .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, }; struct iwl_cfg iwl6000g2b_bg_cfg = { @@ -1154,7 +783,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, .advanced_bt_coexist = true, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, - .bt_prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT, + .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, }; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 84939763d178..84fe06adcef4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -277,6 +277,14 @@ struct iwl_hcmd_ops iwlagn_hcmd = { .send_bt_config = iwl_send_bt_config, }; +struct iwl_hcmd_ops iwlagn_bt_hcmd = { + .rxon_assoc = iwlagn_send_rxon_assoc, + .commit_rxon = iwl_commit_rxon, + .set_rxon_chain = iwl_set_rxon_chain, + .set_tx_ant = iwlagn_send_tx_ant_config, + .send_bt_config = iwlagn_send_advance_bt_config, +}; + struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { .get_hcmd_size = iwlagn_get_hcmd_size, .build_addsta_hcmd = iwlagn_build_addsta_hcmd, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index ea242401b5a3..a9e69a6213f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1542,3 +1542,373 @@ done: ieee80211_wake_queues(priv->hw); mutex_unlock(&priv->mutex); } + +/* + * BT coex + */ +/* + * Macros to access the lookup table. + * + * The lookup table has 7 inputs: bt3_prio, bt3_txrx, bt_rf_act, wifi_req, +* wifi_prio, wifi_txrx and wifi_sh_ant_req. + * + * It has three outputs: WLAN_ACTIVE, WLAN_KILL and ANT_SWITCH + * + * The format is that "registers" 8 through 11 contain the WLAN_ACTIVE bits + * one after another in 32-bit registers, and "registers" 0 through 7 contain + * the WLAN_KILL and ANT_SWITCH bits interleaved (in that order). + * + * These macros encode that format. + */ +#define LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, wifi_req, wifi_prio, \ + wifi_txrx, wifi_sh_ant_req) \ + (bt3_prio | (bt3_txrx << 1) | (bt_rf_act << 2) | (wifi_req << 3) | \ + (wifi_prio << 4) | (wifi_txrx << 5) | (wifi_sh_ant_req << 6)) + +#define LUT_PTA_WLAN_ACTIVE_OP(lut, op, val) \ + lut[8 + ((val) >> 5)] op (cpu_to_le32(BIT((val) & 0x1f))) +#define LUT_TEST_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + (!!(LUT_PTA_WLAN_ACTIVE_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, \ + bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \ + wifi_sh_ant_req)))) +#define LUT_SET_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + LUT_PTA_WLAN_ACTIVE_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, \ + bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \ + wifi_sh_ant_req)) +#define LUT_CLEAR_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, \ + wifi_sh_ant_req) \ + LUT_PTA_WLAN_ACTIVE_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, \ + bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \ + wifi_sh_ant_req)) + +#define LUT_WLAN_KILL_OP(lut, op, val) \ + lut[(val) >> 4] op (cpu_to_le32(BIT(((val) << 1) & 0x1e))) +#define LUT_TEST_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + (!!(LUT_WLAN_KILL_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)))) +#define LUT_SET_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + LUT_WLAN_KILL_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) +#define LUT_CLEAR_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + LUT_WLAN_KILL_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) + +#define LUT_ANT_SWITCH_OP(lut, op, val) \ + lut[(val) >> 4] op (cpu_to_le32(BIT((((val) << 1) & 0x1e) + 1))) +#define LUT_TEST_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + (!!(LUT_ANT_SWITCH_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, \ + wifi_sh_ant_req)))) +#define LUT_SET_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + LUT_ANT_SWITCH_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) +#define LUT_CLEAR_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \ + wifi_prio, wifi_txrx, wifi_sh_ant_req) \ + LUT_ANT_SWITCH_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \ + wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req)) + +static const __le32 iwlagn_def_3w_lookup[12] = { + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaeaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xcc00ff28), + cpu_to_le32(0x0000aaaa), + cpu_to_le32(0xcc00aaaa), + cpu_to_le32(0x0000aaaa), + cpu_to_le32(0xc0004000), + cpu_to_le32(0x00004000), + cpu_to_le32(0xf0005000), + cpu_to_le32(0xf0004000), +}; + +static const __le32 iwlagn_concurrent_lookup[12] = { + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0x00000000), + cpu_to_le32(0x00000000), + cpu_to_le32(0x00000000), + cpu_to_le32(0x00000000), +}; + +void iwlagn_send_advance_bt_config(struct iwl_priv *priv) +{ + struct iwlagn_bt_cmd bt_cmd = { + .max_kill = IWLAGN_BT_MAX_KILL_DEFAULT, + .bt3_timer_t7_value = IWLAGN_BT3_T7_DEFAULT, + .bt3_prio_sample_time = IWLAGN_BT3_PRIO_SAMPLE_DEFAULT, + .bt3_timer_t2_value = IWLAGN_BT3_T2_DEFAULT, + }; + + BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) != + sizeof(bt_cmd.bt3_lookup_table)); + + bt_cmd.prio_boost = priv->cfg->bt_prio_boost; + bt_cmd.kill_ack_mask = priv->kill_ack_mask; + bt_cmd.kill_cts_mask = priv->kill_cts_mask; + bt_cmd.valid = priv->bt_valid; + + /* + * Configure BT coex mode to "no coexistence" when the + * user disabled BT coexistence, we have no interface + * (might be in monitor mode), or the interface is in + * IBSS mode (no proper uCode support for coex then). + */ + if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) { + bt_cmd.flags = 0; + } else { + bt_cmd.flags = IWLAGN_BT_FLAG_COEX_MODE_3W << + IWLAGN_BT_FLAG_COEX_MODE_SHIFT; + if (priv->bt_ch_announce) + bt_cmd.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION; + IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", bt_cmd.flags); + } + if (priv->bt_full_concurrent) + memcpy(bt_cmd.bt3_lookup_table, iwlagn_concurrent_lookup, + sizeof(iwlagn_concurrent_lookup)); + else + memcpy(bt_cmd.bt3_lookup_table, iwlagn_def_3w_lookup, + sizeof(iwlagn_def_3w_lookup)); + + IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n", + bt_cmd.flags ? "active" : "disabled", + priv->bt_full_concurrent ? + "full concurrency" : "3-wire"); + + if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd)) + IWL_ERR(priv, "failed to send BT Coex Config\n"); + + /* + * When we are doing a restart, need to also reconfigure BT + * SCO to the device. If not doing a restart, bt_sco_active + * will always be false, so there's no need to have an extra + * variable to check for it. + */ + if (priv->bt_sco_active) { + struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 }; + + if (priv->bt_sco_active) + sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE; + if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_SCO, + sizeof(sco_cmd), &sco_cmd)) + IWL_ERR(priv, "failed to send BT SCO command\n"); + } +} + +static void iwlagn_bt_traffic_change_work(struct work_struct *work) +{ + struct iwl_priv *priv = + container_of(work, struct iwl_priv, bt_traffic_change_work); + int smps_request = -1; + + IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n", + priv->bt_traffic_load); + + switch (priv->bt_traffic_load) { + case IWL_BT_COEX_TRAFFIC_LOAD_NONE: + smps_request = IEEE80211_SMPS_AUTOMATIC; + break; + case IWL_BT_COEX_TRAFFIC_LOAD_LOW: + smps_request = IEEE80211_SMPS_DYNAMIC; + break; + case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: + case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: + smps_request = IEEE80211_SMPS_STATIC; + break; + default: + IWL_ERR(priv, "Invalid BT traffic load: %d\n", + priv->bt_traffic_load); + break; + } + + mutex_lock(&priv->mutex); + + if (priv->cfg->ops->lib->update_chain_flags) + priv->cfg->ops->lib->update_chain_flags(priv); + + if (smps_request != -1 && + priv->vif && priv->vif->type == NL80211_IFTYPE_STATION) + ieee80211_request_smps(priv->vif, smps_request); + + mutex_unlock(&priv->mutex); +} + +static void iwlagn_print_uartmsg(struct iwl_priv *priv, + struct iwl_bt_uart_msg *uart_msg) +{ + IWL_DEBUG_NOTIF(priv, "Message Type = 0x%X, SSN = 0x%X, " + "Update Req = 0x%X", + (BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >> + BT_UART_MSG_FRAME1MSGTYPE_POS, + (BT_UART_MSG_FRAME1SSN_MSK & uart_msg->frame1) >> + BT_UART_MSG_FRAME1SSN_POS, + (BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >> + BT_UART_MSG_FRAME1UPDATEREQ_POS); + + IWL_DEBUG_NOTIF(priv, "Open connections = 0x%X, Traffic load = 0x%X, " + "Chl_SeqN = 0x%X, In band = 0x%X", + (BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >> + BT_UART_MSG_FRAME2OPENCONNECTIONS_POS, + (BT_UART_MSG_FRAME2TRAFFICLOAD_MSK & uart_msg->frame2) >> + BT_UART_MSG_FRAME2TRAFFICLOAD_POS, + (BT_UART_MSG_FRAME2CHLSEQN_MSK & uart_msg->frame2) >> + BT_UART_MSG_FRAME2CHLSEQN_POS, + (BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >> + BT_UART_MSG_FRAME2INBAND_POS); + + IWL_DEBUG_NOTIF(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, " + "ACL = 0x%X, Master = 0x%X, OBEX = 0x%X", + (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3SCOESCO_POS, + (BT_UART_MSG_FRAME3SNIFF_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3SNIFF_POS, + (BT_UART_MSG_FRAME3A2DP_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3A2DP_POS, + (BT_UART_MSG_FRAME3ACL_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3ACL_POS, + (BT_UART_MSG_FRAME3MASTER_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3MASTER_POS, + (BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3OBEX_POS); + + IWL_DEBUG_NOTIF(priv, "Idle duration = 0x%X", + (BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >> + BT_UART_MSG_FRAME4IDLEDURATION_POS); + + IWL_DEBUG_NOTIF(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, " + "eSCO Retransmissions = 0x%X", + (BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >> + BT_UART_MSG_FRAME5TXACTIVITY_POS, + (BT_UART_MSG_FRAME5RXACTIVITY_MSK & uart_msg->frame5) >> + BT_UART_MSG_FRAME5RXACTIVITY_POS, + (BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >> + BT_UART_MSG_FRAME5ESCORETRANSMIT_POS); + + IWL_DEBUG_NOTIF(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X", + (BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >> + BT_UART_MSG_FRAME6SNIFFINTERVAL_POS, + (BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >> + BT_UART_MSG_FRAME6DISCOVERABLE_POS); + + IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Inquiry/Page SR Mode = " + "0x%X, Connectable = 0x%X", + (BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >> + BT_UART_MSG_FRAME7SNIFFACTIVITY_POS, + (BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_MSK & uart_msg->frame7) >> + BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS, + (BT_UART_MSG_FRAME7CONNECTABLE_MSK & uart_msg->frame7) >> + BT_UART_MSG_FRAME7CONNECTABLE_POS); +} + +static void iwlagn_set_kill_ack_msk(struct iwl_priv *priv, + struct iwl_bt_uart_msg *uart_msg) +{ + u8 kill_ack_msk; + __le32 bt_kill_ack_msg[2] = { + cpu_to_le32(0xFFFFFFF), cpu_to_le32(0xFFFFFC00) }; + + kill_ack_msk = (((BT_UART_MSG_FRAME3A2DP_MSK | + BT_UART_MSG_FRAME3SNIFF_MSK | + BT_UART_MSG_FRAME3SCOESCO_MSK) & + uart_msg->frame3) == 0) ? 1 : 0; + if (priv->kill_ack_mask != bt_kill_ack_msg[kill_ack_msk]) { + priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK; + priv->kill_ack_mask = bt_kill_ack_msg[kill_ack_msk]; + /* schedule to send runtime bt_config */ + queue_work(priv->workqueue, &priv->bt_runtime_config); + } + +} + +void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + unsigned long flags; + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; + struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 }; + struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg; + u8 last_traffic_load; + + IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n"); + IWL_DEBUG_NOTIF(priv, " status: %d\n", coex->bt_status); + IWL_DEBUG_NOTIF(priv, " traffic load: %d\n", coex->bt_traffic_load); + IWL_DEBUG_NOTIF(priv, " CI compliance: %d\n", + coex->bt_ci_compliance); + iwlagn_print_uartmsg(priv, uart_msg); + + last_traffic_load = priv->notif_bt_traffic_load; + priv->notif_bt_traffic_load = coex->bt_traffic_load; + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { + if (priv->bt_status != coex->bt_status || + last_traffic_load != coex->bt_traffic_load) { + if (coex->bt_status) { + /* BT on */ + if (!priv->bt_ch_announce) + priv->bt_traffic_load = + IWL_BT_COEX_TRAFFIC_LOAD_HIGH; + else + priv->bt_traffic_load = + coex->bt_traffic_load; + } else { + /* BT off */ + priv->bt_traffic_load = + IWL_BT_COEX_TRAFFIC_LOAD_NONE; + } + priv->bt_status = coex->bt_status; + queue_work(priv->workqueue, + &priv->bt_traffic_change_work); + } + if (priv->bt_sco_active != + (uart_msg->frame3 & BT_UART_MSG_FRAME3SCOESCO_MSK)) { + priv->bt_sco_active = uart_msg->frame3 & + BT_UART_MSG_FRAME3SCOESCO_MSK; + if (priv->bt_sco_active) + sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE; + iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO, + sizeof(sco_cmd), &sco_cmd, NULL); + } + } + + iwlagn_set_kill_ack_msk(priv, uart_msg); + + /* FIXME: based on notification, adjust the prio_boost */ + + spin_lock_irqsave(&priv->lock, flags); + priv->bt_ci_compliance = coex->bt_ci_compliance; + spin_unlock_irqrestore(&priv->lock, flags); +} + +void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv) +{ + iwlagn_rx_handler_setup(priv); + priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] = + iwlagn_bt_coex_profile_notif; +} + +void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv) +{ + iwlagn_setup_deferred_work(priv); + + INIT_WORK(&priv->bt_traffic_change_work, + iwlagn_bt_traffic_change_work); +} + +void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv) +{ + cancel_work_sync(&priv->bt_traffic_change_work); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 771ceffb8f8b..f2499e1f2047 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -464,11 +464,11 @@ int iwlagn_alive_notify(struct iwl_priv *priv) if (priv->cfg->advanced_bt_coexist) { /* Configure Bluetooth device coexistence support */ /* need to perform this before any calibration */ - priv->bt_valid = IWL6000G2B_BT_ALL_VALID_MSK; - priv->kill_ack_mask = IWL6000G2B_BT_KILL_ACK_MASK_DEFAULT; - priv->kill_cts_mask = IWL6000G2B_BT_KILL_CTS_MASK_DEFAULT; + priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; + priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; + priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; priv->cfg->ops->hcmd->send_bt_config(priv); - priv->bt_valid = IWL6000G2B_BT_VALID_ENABLE_FLAGS; + priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; if (bt_coex_active && priv->iw_mode != NL80211_IFTYPE_ADHOC) { iwlagn_send_prio_tbl(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4410f820c2f3..5e0d0d527bf0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -4024,9 +4024,9 @@ static int iwl_init_drv(struct iwl_priv *priv) /* init bt coex */ if (priv->cfg->advanced_bt_coexist) { - priv->kill_ack_mask = IWL6000G2B_BT_KILL_ACK_MASK_DEFAULT; - priv->kill_cts_mask = IWL6000G2B_BT_KILL_CTS_MASK_DEFAULT; - priv->bt_valid = IWL6000G2B_BT_ALL_VALID_MSK; + priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; + priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; + priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; priv->bt_on_thresh = BT_ON_THRESHOLD_DEF; priv->bt_duration = BT_DURATION_LIMIT_DEF; priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index cc6464dc72e5..1a7f70f293a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -95,6 +95,7 @@ extern struct iwl_cfg iwl1000_bg_cfg; extern struct iwl_mod_params iwlagn_mod_params; extern struct iwl_hcmd_ops iwlagn_hcmd; +extern struct iwl_hcmd_ops iwlagn_bt_hcmd; extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; int iwl_reset_ict(struct iwl_priv *priv); @@ -226,4 +227,12 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, int iwlagn_send_rxon_assoc(struct iwl_priv *priv); int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); +/* bt coex */ +void iwlagn_send_advance_bt_config(struct iwl_priv *priv); +void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); +void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv); +void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv); +void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv); + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 5df22f1d57a5..8ed2412862d7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2411,52 +2411,52 @@ struct iwl_bt_cmd { __le32 kill_cts_mask; } __packed; -#define IWL6000G2B_BT_FLAG_CHANNEL_INHIBITION BIT(0) +#define IWLAGN_BT_FLAG_CHANNEL_INHIBITION BIT(0) -#define IWL6000G2B_BT_FLAG_COEX_MODE_MASK (BIT(3)|BIT(4)|BIT(5)) -#define IWL6000G2B_BT_FLAG_COEX_MODE_SHIFT 3 -#define IWL6000G2B_BT_FLAG_COEX_MODE_DISABLED 0 -#define IWL6000G2B_BT_FLAG_COEX_MODE_LEGACY_2W 1 -#define IWL6000G2B_BT_FLAG_COEX_MODE_3W 2 -#define IWL6000G2B_BT_FLAG_COEX_MODE_4W 3 +#define IWLAGN_BT_FLAG_COEX_MODE_MASK (BIT(3)|BIT(4)|BIT(5)) +#define IWLAGN_BT_FLAG_COEX_MODE_SHIFT 3 +#define IWLAGN_BT_FLAG_COEX_MODE_DISABLED 0 +#define IWLAGN_BT_FLAG_COEX_MODE_LEGACY_2W 1 +#define IWLAGN_BT_FLAG_COEX_MODE_3W 2 +#define IWLAGN_BT_FLAG_COEX_MODE_4W 3 -#define IWL6000G2B_BT_FLAG_UCODE_DEFAULT BIT(6) -#define IWL6000G2B_BT_FLAG_NOCOEX_NOTIF BIT(7) +#define IWLAGN_BT_FLAG_UCODE_DEFAULT BIT(6) +#define IWLAGN_BT_FLAG_NOCOEX_NOTIF BIT(7) -#define IWL6000G2B_BT_PRIO_BOOST_MAX 0xFF -#define IWL6000G2B_BT_PRIO_BOOST_MIN 0x00 -#define IWL6000G2B_BT_PRIO_BOOST_DEFAULT 0xF0 +#define IWLAGN_BT_PRIO_BOOST_MAX 0xFF +#define IWLAGN_BT_PRIO_BOOST_MIN 0x00 +#define IWLAGN_BT_PRIO_BOOST_DEFAULT 0xF0 -#define IWL6000G2B_BT_MAX_KILL_DEFAULT 5 +#define IWLAGN_BT_MAX_KILL_DEFAULT 5 -#define IWL6000G2B_BT3_T7_DEFAULT 1 +#define IWLAGN_BT3_T7_DEFAULT 1 -#define IWL6000G2B_BT_KILL_ACK_MASK_DEFAULT cpu_to_le32(0xffffffff) -#define IWL6000G2B_BT_KILL_CTS_MASK_DEFAULT cpu_to_le32(0xffffffff) +#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT cpu_to_le32(0xffffffff) +#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT cpu_to_le32(0xffffffff) -#define IWL6000G2B_BT3_PRIO_SAMPLE_DEFAULT 2 +#define IWLAGN_BT3_PRIO_SAMPLE_DEFAULT 2 -#define IWL6000G2B_BT3_T2_DEFAULT 0xc +#define IWLAGN_BT3_T2_DEFAULT 0xc -#define IWL6000G2B_BT_VALID_ENABLE_FLAGS cpu_to_le16(BIT(0)) -#define IWL6000G2B_BT_VALID_BOOST cpu_to_le16(BIT(1)) -#define IWL6000G2B_BT_VALID_MAX_KILL cpu_to_le16(BIT(2)) -#define IWL6000G2B_BT_VALID_3W_TIMERS cpu_to_le16(BIT(3)) -#define IWL6000G2B_BT_VALID_KILL_ACK_MASK cpu_to_le16(BIT(4)) -#define IWL6000G2B_BT_VALID_KILL_CTS_MASK cpu_to_le16(BIT(5)) -#define IWL6000G2B_BT_VALID_BT4_TIMES cpu_to_le16(BIT(6)) -#define IWL6000G2B_BT_VALID_3W_LUT cpu_to_le16(BIT(7)) +#define IWLAGN_BT_VALID_ENABLE_FLAGS cpu_to_le16(BIT(0)) +#define IWLAGN_BT_VALID_BOOST cpu_to_le16(BIT(1)) +#define IWLAGN_BT_VALID_MAX_KILL cpu_to_le16(BIT(2)) +#define IWLAGN_BT_VALID_3W_TIMERS cpu_to_le16(BIT(3)) +#define IWLAGN_BT_VALID_KILL_ACK_MASK cpu_to_le16(BIT(4)) +#define IWLAGN_BT_VALID_KILL_CTS_MASK cpu_to_le16(BIT(5)) +#define IWLAGN_BT_VALID_BT4_TIMES cpu_to_le16(BIT(6)) +#define IWLAGN_BT_VALID_3W_LUT cpu_to_le16(BIT(7)) -#define IWL6000G2B_BT_ALL_VALID_MSK (IWL6000G2B_BT_VALID_ENABLE_FLAGS | \ - IWL6000G2B_BT_VALID_BOOST | \ - IWL6000G2B_BT_VALID_MAX_KILL | \ - IWL6000G2B_BT_VALID_3W_TIMERS | \ - IWL6000G2B_BT_VALID_KILL_ACK_MASK | \ - IWL6000G2B_BT_VALID_KILL_CTS_MASK | \ - IWL6000G2B_BT_VALID_BT4_TIMES | \ - IWL6000G2B_BT_VALID_3W_LUT) +#define IWLAGN_BT_ALL_VALID_MSK (IWLAGN_BT_VALID_ENABLE_FLAGS | \ + IWLAGN_BT_VALID_BOOST | \ + IWLAGN_BT_VALID_MAX_KILL | \ + IWLAGN_BT_VALID_3W_TIMERS | \ + IWLAGN_BT_VALID_KILL_ACK_MASK | \ + IWLAGN_BT_VALID_KILL_CTS_MASK | \ + IWLAGN_BT_VALID_BT4_TIMES | \ + IWLAGN_BT_VALID_3W_LUT) -struct iwl6000g2b_bt_cmd { +struct iwlagn_bt_cmd { u8 flags; u8 ledtime; /* unused */ u8 max_kill; @@ -2473,9 +2473,9 @@ struct iwl6000g2b_bt_cmd { u8 reserved[3]; }; -#define IWL6000G2B_BT_SCO_ACTIVE cpu_to_le32(BIT(0)) +#define IWLAGN_BT_SCO_ACTIVE cpu_to_le32(BIT(0)) -struct iwl6000g2b_bt_sco_cmd { +struct iwlagn_bt_sco_cmd { __le32 flags; }; -- cgit v1.2.3-59-g8ed1b From f78e545449bb07a28b419d888c4c558b13d9e5e1 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:15 -0700 Subject: iwlagn: update bt status upon scan complete Update bt status upon receive scan complete notification Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 8ed2412862d7..9b535832f117 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -3013,7 +3013,7 @@ struct iwl_scanresults_notification { struct iwl_scancomplete_notification { u8 scanned_channels; u8 status; - u8 reserved; + u8 bt_status; /* BT On/Off status */ u8 last_channel; __le32 tsf_low; __le32 tsf_high; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 8d7fa59364fe..33aa7a5eea8a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -236,6 +236,26 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, clear_bit(STATUS_SCANNING, &priv->status); + if (priv->iw_mode != NL80211_IFTYPE_ADHOC && + priv->cfg->advanced_bt_coexist && priv->bt_status != + scan_notif->bt_status) { + if (scan_notif->bt_status) { + /* BT on */ + if (!priv->bt_ch_announce) + priv->bt_traffic_load = + IWL_BT_COEX_TRAFFIC_LOAD_HIGH; + /* + * otherwise, no traffic load information provided + * no changes made + */ + } else { + /* BT off */ + priv->bt_traffic_load = + IWL_BT_COEX_TRAFFIC_LOAD_NONE; + } + priv->bt_status = scan_notif->bt_status; + queue_work(priv->workqueue, &priv->bt_traffic_change_work); + } queue_work(priv->workqueue, &priv->scan_completed); } -- cgit v1.2.3-59-g8ed1b From befe8c469baebe8a0fb5bd9b7cd4afd8c54ebbd5 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 23 Aug 2010 07:57:16 -0700 Subject: iwlwifi: add bt traffic load debugfs file Add the debugfs file to show current bluetooth traffic load Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 45 ++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index aae9eb552350..ef787905f51c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1555,6 +1555,48 @@ static ssize_t iwl_dbgfs_monitor_period_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int pos = 0; + char buf[200]; + const size_t bufsz = sizeof(buf); + ssize_t ret; + + pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n", + priv->bt_full_concurrent ? "full concurrency" : "3-wire"); + pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, " + "last traffic notif: %d\n", + priv->bt_status ? "On" : "Off", priv->notif_bt_traffic_load); + pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, " + "sco_active: %d, kill_ack_mask: %x, " + "kill_cts_mask: %x\n", + priv->bt_ch_announce, priv->bt_sco_active, + priv->kill_ack_mask, priv->kill_cts_mask); + + pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: "); + switch (priv->bt_traffic_load) { + case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: + pos += scnprintf(buf + pos, bufsz - pos, "Continuous\n"); + break; + case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: + pos += scnprintf(buf + pos, bufsz - pos, "High\n"); + break; + case IWL_BT_COEX_TRAFFIC_LOAD_LOW: + pos += scnprintf(buf + pos, bufsz - pos, "Low\n"); + break; + case IWL_BT_COEX_TRAFFIC_LOAD_NONE: + default: + pos += scnprintf(buf + pos, bufsz - pos, "None\n"); + break; + } + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + return ret; +} + DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); @@ -1579,6 +1621,7 @@ DEBUGFS_READ_FILE_OPS(rxon_filter_flags); DEBUGFS_WRITE_FILE_OPS(txfifo_flush); DEBUGFS_READ_FILE_OPS(ucode_bt_stats); DEBUGFS_WRITE_FILE_OPS(monitor_period); +DEBUGFS_READ_FILE_OPS(bt_traffic); /* * Create the debugfs files and directories @@ -1651,6 +1694,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR); + if (priv->cfg->advanced_bt_coexist) + DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); if (priv->cfg->sensitivity_calib_by_driver) DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); -- cgit v1.2.3-59-g8ed1b From 18c121d7558a550e8e48956fbd389759a850ab53 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 07:57:17 -0700 Subject: iwlwifi: disable aggregation queue if stopped early When aggregation is stopped again for some reason before the queue we selected has drained, we will currently leak the TX queue and keep it enabled for aggregation. Normally this doesn't happen, so the problem is rarely seen. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 32 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index e2497e7ba926..a51a7cfa5a14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1036,7 +1036,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid) { - int tx_fifo_id, txq_id, sta_id, ssn = -1; + int tx_fifo_id, txq_id, sta_id, ssn; struct iwl_tid_data *tid_data; int write_ptr, read_ptr; unsigned long flags; @@ -1054,21 +1054,26 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, spin_lock_irqsave(&priv->sta_lock, flags); - if (priv->stations[sta_id].tid[tid].agg.state == - IWL_EMPTYING_HW_QUEUE_ADDBA) { - IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); - ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); - priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; - } - - if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) - IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); - tid_data = &priv->stations[sta_id].tid[tid]; ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; txq_id = tid_data->agg.txq_id; + + switch (priv->stations[sta_id].tid[tid].agg.state) { + case IWL_EMPTYING_HW_QUEUE_ADDBA: + /* + * This can happen if the peer stops aggregation + * again before we've had a chance to drain the + * queue we selected previously, i.e. before the + * session was really started completely. + */ + IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); + goto turn_off; + case IWL_AGG_ON: + break; + default: + IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); + } + write_ptr = priv->txq[txq_id].q.write_ptr; read_ptr = priv->txq[txq_id].q.read_ptr; @@ -1082,6 +1087,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, } IWL_DEBUG_HT(priv, "HW queue is empty\n"); + turn_off: priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; /* do not restore/save irqs */ -- cgit v1.2.3-59-g8ed1b From 933314582ee5db00123683cf4c4d713ec9add306 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 23 Aug 2010 19:53:39 +0200 Subject: rt2x00: Simplify arguments to rt2x00 driver callback functions write_tx_desc shouldn't pass a rt2x00dev and skb pointer, instead it should use the same format as other TX frame callback functions, which is passing the data_entry pointer which contains all the information which is needed to work on a TX frame. Most callers of the kick_tx_queue and kill_tx_queue already have the data_queue pointer, so rather then sending the QID with the given function, when the driver requests a new pointer to the data_queue, it is more efficient to just send the data_queue pointer directly. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 25 +++++++++---------- drivers/net/wireless/rt2x00/rt2500pci.c | 25 +++++++++---------- drivers/net/wireless/rt2x00/rt2500usb.c | 9 +++---- drivers/net/wireless/rt2x00/rt2800pci.c | 41 +++++++++++++------------------ drivers/net/wireless/rt2x00/rt2800usb.c | 9 +++---- drivers/net/wireless/rt2x00/rt2x00.h | 9 +++---- drivers/net/wireless/rt2x00/rt2x00queue.c | 11 ++++----- drivers/net/wireless/rt2x00/rt2x00usb.c | 14 ++++------- drivers/net/wireless/rt2x00/rt2x00usb.h | 12 +++------ drivers/net/wireless/rt2x00/rt61pci.c | 39 ++++++++++++++--------------- drivers/net/wireless/rt2x00/rt73usb.c | 11 ++++----- 11 files changed, 90 insertions(+), 115 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 5063e01410e5..b86b6132a69c 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1007,12 +1007,11 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, /* * TX descriptor initialization */ -static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, +static void rt2400pci_write_tx_desc(struct queue_entry *entry, struct txentry_desc *txdesc) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + struct queue_entry_priv_pci *entry_priv = entry->priv_data; __le32 *txd = entry_priv->desc; u32 word; @@ -1096,7 +1095,7 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, /* * Write the TX descriptor for the beacon. */ - rt2400pci_write_tx_desc(rt2x00dev, entry->skb, txdesc); + rt2400pci_write_tx_desc(entry, txdesc); /* * Dump beacon to userspace through debugfs. @@ -1112,24 +1111,24 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, rt2x00pci_register_write(rt2x00dev, CSR14, reg); } -static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) +static void rt2400pci_kick_tx_queue(struct data_queue *queue) { + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; u32 reg; rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue == QID_AC_BE)); - rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue == QID_AC_BK)); - rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue == QID_ATIM)); + rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE)); + rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK)); + rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM)); rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); } -static void rt2400pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid) +static void rt2400pci_kill_tx_queue(struct data_queue *queue) { + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; u32 reg; - if (qid == QID_BEACON) { + if (queue->qid == QID_BEACON) { rt2x00pci_register_write(rt2x00dev, CSR14, 0); } else { rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index c2a555d5376b..21f45810fd1e 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1161,12 +1161,11 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, /* * TX descriptor initialization */ -static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, +static void rt2500pci_write_tx_desc(struct queue_entry *entry, struct txentry_desc *txdesc) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + struct queue_entry_priv_pci *entry_priv = entry->priv_data; __le32 *txd = entry_priv->desc; u32 word; @@ -1249,7 +1248,7 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, /* * Write the TX descriptor for the beacon. */ - rt2500pci_write_tx_desc(rt2x00dev, entry->skb, txdesc); + rt2500pci_write_tx_desc(entry, txdesc); /* * Dump beacon to userspace through debugfs. @@ -1265,24 +1264,24 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, rt2x00pci_register_write(rt2x00dev, CSR14, reg); } -static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) +static void rt2500pci_kick_tx_queue(struct data_queue *queue) { + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; u32 reg; rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue == QID_AC_BE)); - rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue == QID_AC_BK)); - rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue == QID_ATIM)); + rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE)); + rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK)); + rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM)); rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); } -static void rt2500pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid) +static void rt2500pci_kill_tx_queue(struct data_queue *queue) { + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; u32 reg; - if (qid == QID_BEACON) { + if (queue->qid == QID_BEACON) { rt2x00pci_register_write(rt2x00dev, CSR14, 0); } else { rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 97cf72f8bc12..8722464944f5 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1041,12 +1041,11 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, /* * TX descriptor initialization */ -static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, +static void rt2500usb_write_tx_desc(struct queue_entry *entry, struct txentry_desc *txdesc) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = (__le32 *) skb->data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + __le32 *txd = (__le32 *) entry->skb->data; u32 word; /* @@ -1129,7 +1128,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry, /* * Write the TX descriptor for the beacon. */ - rt2500usb_write_tx_desc(rt2x00dev, entry->skb, txdesc); + rt2500usb_write_tx_desc(entry, txdesc); /* * Dump beacon to userspace through debugfs. diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 4390f2b74b2e..af1c6914d7b4 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -571,12 +571,11 @@ static __le32 *rt2800pci_get_txwi(struct queue_entry *entry) return (__le32 *) entry->skb->data; } -static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, +static void rt2800pci_write_tx_desc(struct queue_entry *entry, struct txentry_desc *txdesc) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + struct queue_entry_priv_pci *entry_priv = entry->priv_data; __le32 *txd = entry_priv->desc; u32 word; @@ -596,7 +595,7 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 0, word); rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_SD_LEN1, skb->len); + rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len); rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W1_BURST, @@ -627,41 +626,35 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ -static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue_idx) +static void rt2800pci_kick_tx_queue(struct data_queue *queue) { - struct data_queue *queue; - unsigned int idx, qidx = 0; - - if (queue_idx > QID_HCCA && queue_idx != QID_MGMT) - return; - - queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); - idx = queue->index[Q_INDEX]; + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + unsigned int idx = queue->index[Q_INDEX]; + unsigned int qidx = 0; - if (queue_idx == QID_MGMT) + if (queue->qid == QID_MGMT) qidx = 5; else - qidx = queue_idx; + qidx = queue->qid; rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx); } -static void rt2800pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid) +static void rt2800pci_kill_tx_queue(struct data_queue *queue) { + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; u32 reg; - if (qid == QID_BEACON) { + if (queue->qid == QID_BEACON) { rt2800_register_write(rt2x00dev, BCN_TIME_CFG, 0); return; } rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, (qid == QID_AC_BE)); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, (qid == QID_AC_BK)); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, (qid == QID_AC_VI)); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, (qid == QID_AC_VO)); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, (queue->qid == QID_AC_BE)); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, (queue->qid == QID_AC_BK)); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, (queue->qid == QID_AC_VI)); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, (queue->qid == QID_AC_VO)); rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); } diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 9ad28be294eb..02f95892aa07 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -329,12 +329,11 @@ static __le32 *rt2800usb_get_txwi(struct queue_entry *entry) return (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE); } -static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, +static void rt2800usb_write_tx_desc(struct queue_entry *entry, struct txentry_desc *txdesc) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txi = (__le32 *) skb->data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + __le32 *txi = (__le32 *) entry->skb->data; u32 word; /* @@ -342,7 +341,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ rt2x00_desc_read(txi, 0, &word); rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, - skb->len - TXINFO_DESC_SIZE); + entry->skb->len - TXINFO_DESC_SIZE); rt2x00_set_field32(&word, TXINFO_W0_WIV, !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 8c65244a847a..69308a0df74f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -559,18 +559,15 @@ struct rt2x00lib_ops { /* * TX control handlers */ - void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, + void (*write_tx_desc) (struct queue_entry *entry, struct txentry_desc *txdesc); void (*write_tx_data) (struct queue_entry *entry, struct txentry_desc *txdesc); void (*write_beacon) (struct queue_entry *entry, struct txentry_desc *txdesc); int (*get_tx_data_len) (struct queue_entry *entry); - void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue); - void (*kill_tx_queue) (struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue); + void (*kick_tx_queue) (struct data_queue *queue); + void (*kill_tx_queue) (struct data_queue *queue); /* * RX control handlers diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 18220953851e..189eaf72967e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -449,15 +449,14 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc) { struct data_queue *queue = entry->queue; - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc); + queue->rt2x00dev->ops->lib->write_tx_desc(entry, txdesc); /* * All processing on the frame has been completed, this means * it is now ready to be dumped to userspace through debugfs. */ - rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb); + rt2x00debug_dump_frame(queue->rt2x00dev, DUMP_FRAME_TX, entry->skb); } static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, @@ -477,7 +476,7 @@ static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, */ if (rt2x00queue_threshold(queue) || !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) - rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); + rt2x00dev->ops->lib->kick_tx_queue(queue); } int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, @@ -591,7 +590,7 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, intf->beacon->skb = NULL; if (!enable_beacon) { - rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_BEACON); + rt2x00dev->ops->lib->kill_tx_queue(intf->beacon->queue); mutex_unlock(&intf->beacon_skb_mutex); return 0; } @@ -719,7 +718,7 @@ void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev) struct data_queue *queue; txall_queue_for_each(rt2x00dev, queue) - rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, queue->qid); + rt2x00dev->ops->lib->kill_tx_queue(queue); } void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index f76014f732ce..52ed3f44c843 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -249,10 +249,8 @@ static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) } } -void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid) +void rt2x00usb_kick_tx_queue(struct data_queue *queue) { - struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid); unsigned long irqflags; unsigned int index; unsigned int index_done; @@ -286,10 +284,8 @@ void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue); -void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid) +void rt2x00usb_kill_tx_queue(struct data_queue *queue) { - struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid); struct queue_entry_priv_usb *entry_priv; struct queue_entry_priv_usb_bcn *bcn_priv; unsigned int i; @@ -300,8 +296,8 @@ void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, * the beacon guard byte. */ kill_guard = - (qid == QID_BEACON) && - (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)); + (queue->qid == QID_BEACON) && + (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &queue->rt2x00dev->flags)); /* * Cancel all entries. @@ -447,7 +443,7 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) * The USB version of kill_tx_queue also works * on the RX queue. */ - rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_RX); + rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev->rx); } EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index d3d3ddc40875..c2d997f67b3e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -379,25 +379,21 @@ struct queue_entry_priv_usb_bcn { /** * rt2x00usb_kick_tx_queue - Kick data queue - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @qid: Data queue to kick + * @queue: Data queue to kick * * This will walk through all entries of the queue and push all pending * frames to the hardware as a single burst. */ -void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid); +void rt2x00usb_kick_tx_queue(struct data_queue *queue); /** * rt2x00usb_kill_tx_queue - Kill data queue - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @qid: Data queue to kill + * @queue: Data queue to kill * * This will walk through all entries of the queue and kill all * previously kicked frames before they can be send. */ -void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid); +void rt2x00usb_kill_tx_queue(struct data_queue *queue); /** * rt2x00usb_watchdog - Watchdog for USB communication diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index cff503faac65..ae4698e18729 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1766,12 +1766,11 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, /* * TX descriptor initialization */ -static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, +static void rt61pci_write_tx_desc(struct queue_entry *entry, struct txentry_desc *txdesc) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + struct queue_entry_priv_pci *entry_priv = entry->priv_data; __le32 *txd = entry_priv->desc; u32 word; @@ -1802,11 +1801,11 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, } rt2x00_desc_read(txd, 5, &word); - rt2x00_set_field32(&word, TXD_W5_PID_TYPE, skbdesc->entry->queue->qid); + rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid); rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, skbdesc->entry->entry_idx); rt2x00_set_field32(&word, TXD_W5_TX_POWER, - TXPOWER_TO_DEV(rt2x00dev->tx_power)); + TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power)); rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); @@ -1882,7 +1881,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry, /* * Write the TX descriptor for the beacon. */ - rt61pci_write_tx_desc(rt2x00dev, entry->skb, txdesc); + rt61pci_write_tx_desc(entry, txdesc); /* * Dump beacon to userspace through debugfs. @@ -1918,34 +1917,34 @@ static void rt61pci_write_beacon(struct queue_entry *entry, entry->skb = NULL; } -static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) +static void rt61pci_kick_tx_queue(struct data_queue *queue) { + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; u32 reg; rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, (queue == QID_AC_BE)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, (queue == QID_AC_BK)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, (queue == QID_AC_VI)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, (queue == QID_AC_VO)); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, (queue->qid == QID_AC_BE)); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, (queue->qid == QID_AC_BK)); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, (queue->qid == QID_AC_VI)); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, (queue->qid == QID_AC_VO)); rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); } -static void rt61pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid) +static void rt61pci_kill_tx_queue(struct data_queue *queue) { + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; u32 reg; - if (qid == QID_BEACON) { + if (queue->qid == QID_BEACON) { rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); return; } rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, (qid == QID_AC_BE)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, (qid == QID_AC_BK)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, (qid == QID_AC_VI)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, (qid == QID_AC_VO)); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, (queue->qid == QID_AC_BE)); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, (queue->qid == QID_AC_BK)); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, (queue->qid == QID_AC_VI)); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, (queue->qid == QID_AC_VO)); rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index c65529678fbd..ab9389439d75 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1426,12 +1426,11 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, /* * TX descriptor initialization */ -static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, +static void rt73usb_write_tx_desc(struct queue_entry *entry, struct txentry_desc *txdesc) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = (__le32 *) skb->data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + __le32 *txd = (__le32 *) entry->skb->data; u32 word; /* @@ -1487,7 +1486,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_read(txd, 5, &word); rt2x00_set_field32(&word, TXD_W5_TX_POWER, - TXPOWER_TO_DEV(rt2x00dev->tx_power)); + TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power)); rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); @@ -1526,7 +1525,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry, /* * Write the TX descriptor for the beacon. */ - rt73usb_write_tx_desc(rt2x00dev, entry->skb, txdesc); + rt73usb_write_tx_desc(entry, txdesc); /* * Dump beacon to userspace through debugfs. -- cgit v1.2.3-59-g8ed1b From ee1e755f84dfd5d482076c642fac830aafdc482b Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 23 Aug 2010 19:54:02 +0200 Subject: rt2x00: Reduce indenting Cosmetic change, reduce indenting. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 52ed3f44c843..1d2eb461329f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -232,21 +232,22 @@ static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) struct queue_entry_priv_usb *entry_priv = entry->priv_data; u32 length; - if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) { - /* - * USB devices cannot blindly pass the skb->len as the - * length of the data to usb_fill_bulk_urb. Pass the skb - * to the driver to determine what the length should be. - */ - length = rt2x00dev->ops->lib->get_tx_data_len(entry); + if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) + return; + + /* + * USB devices cannot blindly pass the skb->len as the + * length of the data to usb_fill_bulk_urb. Pass the skb + * to the driver to determine what the length should be. + */ + length = rt2x00dev->ops->lib->get_tx_data_len(entry); - usb_fill_bulk_urb(entry_priv->urb, usb_dev, - usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint), - entry->skb->data, length, - rt2x00usb_interrupt_txdone, entry); + usb_fill_bulk_urb(entry_priv->urb, usb_dev, + usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint), + entry->skb->data, length, + rt2x00usb_interrupt_txdone, entry); - usb_submit_urb(entry_priv->urb, GFP_ATOMIC); - } + usb_submit_urb(entry_priv->urb, GFP_ATOMIC); } void rt2x00usb_kick_tx_queue(struct data_queue *queue) -- cgit v1.2.3-59-g8ed1b From 5eb7efe8a4807d98a277280e1317e5094eedfb6b Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 23 Aug 2010 19:54:21 +0200 Subject: rt2x00: Move direct access to queue->entries to rt2x00queue.c All access to queue->entries through the Q_INDEX/Q_INDEX_DONE variables must be done using spinlock protection. It is best to manage this completely from rt2x00queue.c. For safely looping through all entries in the queue, the function rt2x00queue_for_each_entry is added which will walk from from a index range in a safe manner. This also fixes rt2x00usb which walked the entries list from 0 to length to kill each entry (killing entries must be done from Q_INDEX_DONE to Q_INDEX to enforce TX status reporting to occur in the correct order. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 4 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 45 +++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00queue.h | 16 +++++++ drivers/net/wireless/rt2x00/rt2x00usb.c | 75 +++++++++---------------------- 4 files changed, 83 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index af1c6914d7b4..a5e58705b49b 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -629,7 +629,7 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry, static void rt2800pci_kick_tx_queue(struct data_queue *queue) { struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - unsigned int idx = queue->index[Q_INDEX]; + struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); unsigned int qidx = 0; if (queue->qid == QID_MGMT) @@ -637,7 +637,7 @@ static void rt2800pci_kick_tx_queue(struct data_queue *queue) else qidx = queue->qid; - rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx); + rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), entry->entry_idx); } static void rt2800pci_kill_tx_queue(struct data_queue *queue) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 189eaf72967e..7fb9b6179af1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -625,6 +625,51 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, return 0; } +void rt2x00queue_for_each_entry(struct data_queue *queue, + enum queue_index start, + enum queue_index end, + void (*fn)(struct queue_entry *entry)) +{ + unsigned long irqflags; + unsigned int index_start; + unsigned int index_end; + unsigned int i; + + if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) { + ERROR(queue->rt2x00dev, + "Entry requested from invalid index range (%d - %d)\n", + start, end); + return; + } + + /* + * Only protect the range we are going to loop over, + * if during our loop a extra entry is set to pending + * it should not be kicked during this run, since it + * is part of another TX operation. + */ + spin_lock_irqsave(&queue->lock, irqflags); + index_start = queue->index[start]; + index_end = queue->index[end]; + spin_unlock_irqrestore(&queue->lock, irqflags); + + /* + * Start from the TX done pointer, this guarentees that we will + * send out all frames in the correct order. + */ + if (index_start < index_end) { + for (i = index_start; i < index_end; i++) + fn(&queue->entries[i]); + } else { + for (i = index_start; i < queue->limit; i++) + fn(&queue->entries[i]); + + for (i = 0; i < index_end; i++) + fn(&queue->entries[i]); + } +} +EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry); + struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 2d3bf843735f..46a3be1d82b9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -570,6 +570,22 @@ struct data_queue_desc { #define txall_queue_for_each(__dev, __entry) \ queue_loop(__entry, (__dev)->tx, queue_end(__dev)) +/** + * rt2x00queue_for_each_entry - Loop through all entries in the queue + * @queue: Pointer to @data_queue + * @start: &enum queue_index Pointer to start index + * @end: &enum queue_index Pointer to end index + * @fn: The function to call for each &struct queue_entry + * + * This will walk through all entries in the queue, in chronological + * order. This means it will start at the current @start pointer + * and will walk through the queue until it reaches the @end pointer. + */ +void rt2x00queue_for_each_entry(struct data_queue *queue, + enum queue_index start, + enum queue_index end, + void (*fn)(struct queue_entry *entry)); + /** * rt2x00queue_empty - Check if the queue is empty. * @queue: Queue to check if empty. diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 1d2eb461329f..6cc7aa418d87 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -225,7 +225,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); } -static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) +static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); @@ -252,69 +252,34 @@ static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) void rt2x00usb_kick_tx_queue(struct data_queue *queue) { - unsigned long irqflags; - unsigned int index; - unsigned int index_done; - unsigned int i; - - /* - * Only protect the range we are going to loop over, - * if during our loop a extra entry is set to pending - * it should not be kicked during this run, since it - * is part of another TX operation. - */ - spin_lock_irqsave(&queue->lock, irqflags); - index = queue->index[Q_INDEX]; - index_done = queue->index[Q_INDEX_DONE]; - spin_unlock_irqrestore(&queue->lock, irqflags); - - /* - * Start from the TX done pointer, this guarentees that we will - * send out all frames in the correct order. - */ - if (index_done < index) { - for (i = index_done; i < index; i++) - rt2x00usb_kick_tx_entry(&queue->entries[i]); - } else { - for (i = index_done; i < queue->limit; i++) - rt2x00usb_kick_tx_entry(&queue->entries[i]); - - for (i = 0; i < index; i++) - rt2x00usb_kick_tx_entry(&queue->entries[i]); - } + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00usb_kick_tx_entry); } EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue); -void rt2x00usb_kill_tx_queue(struct data_queue *queue) +static void rt2x00usb_kill_tx_entry(struct queue_entry *entry) { - struct queue_entry_priv_usb *entry_priv; - struct queue_entry_priv_usb_bcn *bcn_priv; - unsigned int i; - bool kill_guard; + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct queue_entry_priv_usb *entry_priv = entry->priv_data; + struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; - /* - * When killing the beacon queue, we must also kill - * the beacon guard byte. - */ - kill_guard = - (queue->qid == QID_BEACON) && - (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &queue->rt2x00dev->flags)); + if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + return; + + usb_kill_urb(entry_priv->urb); /* - * Cancel all entries. + * Kill guardian urb (if required by driver). */ - for (i = 0; i < queue->limit; i++) { - entry_priv = queue->entries[i].priv_data; - usb_kill_urb(entry_priv->urb); + if ((entry->queue->qid == QID_BEACON) && + (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) + usb_kill_urb(bcn_priv->guardian_urb); +} - /* - * Kill guardian urb (if required by driver). - */ - if (kill_guard) { - bcn_priv = queue->entries[i].priv_data; - usb_kill_urb(bcn_priv->guardian_urb); - } - } +void rt2x00usb_kill_tx_queue(struct data_queue *queue) +{ + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00usb_kill_tx_entry); } EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); -- cgit v1.2.3-59-g8ed1b From 54e34fbb6fae67b3dba4c2600d3c65aca81635ae Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 23 Aug 2010 19:54:41 +0200 Subject: rt2x00: Remove Q_INDEX_CRYPTO and ENTRY_OWNER_DEVICE_CRYPTO Q_INDEX_CRYPTO and ENTRY_OWNER_DEVICE_CRYPTO where initially added with the plan to implement hardware encryption for rt2500pci. However there are no plans to do so anymore as the crypto mechanism in rt2500pci is very different then any other Ralink device. So we can now safely remove the definitions, and don't think about this feature anymore. :) Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00debug.c | 7 +++---- drivers/net/wireless/rt2x00/rt2x00queue.h | 7 ------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index b0498e7e7aae..74f0d679883e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -338,16 +338,15 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file, return -ENOMEM; temp = data + - sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n"); + sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\n"); queue_for_each(intf->rt2x00dev, queue) { spin_lock_irqsave(&queue->lock, irqflags); - temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, + temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, queue->count, queue->limit, queue->length, queue->index[Q_INDEX], - queue->index[Q_INDEX_DONE], - queue->index[Q_INDEX_CRYPTO]); + queue->index[Q_INDEX_DONE]); spin_unlock_irqrestore(&queue->lock, irqflags); } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 46a3be1d82b9..c451a50f7a01 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -360,9 +360,6 @@ struct txentry_desc { * @ENTRY_OWNER_DEVICE_DATA: This entry is owned by the device for data * transfer (either TX or RX depending on the queue). The entry should * only be touched after the device has signaled it is done with it. - * @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data - * encryption or decryption. The entry should only be touched after - * the device has signaled it is done with it. * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting * for the signal to start sending. * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured @@ -372,7 +369,6 @@ struct txentry_desc { enum queue_entry_flags { ENTRY_BCN_ASSIGNED, ENTRY_OWNER_DEVICE_DATA, - ENTRY_OWNER_DEVICE_CRYPTO, ENTRY_DATA_PENDING, ENTRY_DATA_IO_FAILED }; @@ -408,15 +404,12 @@ struct queue_entry { * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by * the hardware and for which we need to run the txdone handler. If this * entry is not owned by the hardware the queue is considered to be empty. - * @Q_INDEX_CRYPTO: Index pointer to the next entry which encryption/decription - * will be completed by the hardware next. * @Q_INDEX_MAX: Keep last, used in &struct data_queue to determine the size * of the index array. */ enum queue_index { Q_INDEX, Q_INDEX_DONE, - Q_INDEX_CRYPTO, Q_INDEX_MAX, }; -- cgit v1.2.3-59-g8ed1b From 21595bd50dd1ef16cf0dce33835caaf5ab458d4c Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 23 Aug 2010 19:55:01 +0200 Subject: rt2x00: Fix rt2800 retry calculation The retry count for a frame is calculated by the realized MCS rate subtracting of the requested MCS rate. However during TX done reporting we accidently override the requested MCS rate with the realized MCS rate. This causes the retry count to be reset to 0 always, and feeding invalid rate information into minstrel_ht. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 3a150d3a9d9f..8706702b69a2 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -650,7 +650,6 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) txdesc.flags = 0; rt2x00_desc_read(txwi, 0, &word); mcs = rt2x00_get_field32(word, TXWI_W0_MCS); - mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); /* -- cgit v1.2.3-59-g8ed1b From b9a07ae9d9e09662013992088fd58ffbcb2f9a30 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 23 Aug 2010 19:55:22 +0200 Subject: rt2x00: Merge rt2800{pci/usb} radio enabling/disabling code to rt2800lib The functions rt2800pci_enable_radio and rt2800usb_disable_radio are almost equal and can be merged into rt2800lib. This reduces the number of functions which must be exported from rt2800lib to the drivers at the same time. Also rt2800pci_disable_radio and rt2800usb_disable_radio are almost equal and can be merged into rt2800lib in a similar fashion. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 103 ++++++++++++++++++++++++++++++-- drivers/net/wireless/rt2x00/rt2800lib.h | 8 +-- drivers/net/wireless/rt2x00/rt2800pci.c | 69 +-------------------- drivers/net/wireless/rt2x00/rt2800usb.c | 72 +--------------------- 4 files changed, 107 insertions(+), 145 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 8706702b69a2..b2f9b04134eb 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1655,7 +1655,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner); /* * Initialization functions. */ -int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) +static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; u16 eeprom; @@ -2025,7 +2025,6 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) return 0; } -EXPORT_SYMBOL_GPL(rt2800_init_registers); static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev) { @@ -2068,7 +2067,7 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) return -EACCES; } -int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) +static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) { unsigned int i; u16 eeprom; @@ -2163,7 +2162,6 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return 0; } -EXPORT_SYMBOL_GPL(rt2800_init_bbp); static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40, u8 rfcsr24, u8 filter_target) @@ -2225,7 +2223,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, return rfcsr24; } -int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) +static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) { u8 rfcsr; u8 bbp; @@ -2479,7 +2477,100 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) return 0; } -EXPORT_SYMBOL_GPL(rt2800_init_rfcsr); + +int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + u16 word; + + /* + * Initialize all registers. + */ + if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || + rt2800_init_registers(rt2x00dev) || + rt2800_init_bbp(rt2x00dev) || + rt2800_init_rfcsr(rt2x00dev))) + return -EIO; + + /* + * Send signal to firmware during boot time. + */ + rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); + + if (rt2x00_is_usb(rt2x00dev) && + (rt2x00_rt(rt2x00dev, RT3070) || + rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3572))) { + udelay(200); + rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); + udelay(10); + } + + /* + * Enable RX. + */ + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + udelay(50); + + rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); + rt2x00_set_field32(®, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2); + rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); + rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + /* + * Initialize LED control + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff, + word & 0xff, (word >> 8) & 0xff); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff, + word & 0xff, (word >> 8) & 0xff); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff, + word & 0xff, (word >> 8) & 0xff); + + return 0; +} +EXPORT_SYMBOL_GPL(rt2800_enable_radio); + +void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); + rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + + /* Wait for DMA, ignore error */ + rt2800_wait_wpdma_ready(rt2x00dev); + + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 0); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); + rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); +} +EXPORT_SYMBOL_GPL(rt2800_disable_radio); int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev) { diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 3b572c63382d..deb10b14157b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -140,6 +140,8 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 command, const u8 token, const u8 arg0, const u8 arg1); +int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev); + int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len); int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, @@ -176,10 +178,8 @@ void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, const u32 count); -int rt2800_init_registers(struct rt2x00_dev *rt2x00dev); -int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev); -int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev); -int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev); +int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev); +void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev); void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index a5e58705b49b..4d93204b221f 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -399,78 +399,18 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) { - u32 reg; - u16 word; - - /* - * Initialize all registers. - */ if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || - rt2800pci_init_queues(rt2x00dev) || - rt2800_init_registers(rt2x00dev) || - rt2800_wait_wpdma_ready(rt2x00dev) || - rt2800_init_bbp(rt2x00dev) || - rt2800_init_rfcsr(rt2x00dev))) + rt2800pci_init_queues(rt2x00dev))) return -EIO; - /* - * Send signal to firmware during boot time. - */ - rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); - - /* - * Enable RX. - */ - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); - rt2x00_set_field32(®, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2); - rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - - /* - * Initialize LED control - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff, - word & 0xff, (word >> 8) & 0xff); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff, - word & 0xff, (word >> 8) & 0xff); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff, - word & 0xff, (word >> 8) & 0xff); - - return 0; + return rt2800_enable_radio(rt2x00dev); } static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0); - rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); - rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); + rt2800_disable_radio(rt2x00dev); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280); @@ -486,9 +426,6 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); - - /* Wait for DMA, ignore error */ - rt2800_wait_wpdma_ready(rt2x00dev); } static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 02f95892aa07..82ae58e0c5d7 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -101,19 +101,6 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, msleep(10); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); - /* - * Send signal to firmware during boot time. - */ - rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); - - if (rt2x00_rt(rt2x00dev, RT3070) || - rt2x00_rt(rt2x00dev, RT3071) || - rt2x00_rt(rt2x00dev, RT3572)) { - udelay(200); - rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); - udelay(10); - } - return 0; } @@ -173,30 +160,10 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; - u16 word; - /* - * Initialize all registers. - */ - if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || - rt2800_init_registers(rt2x00dev) || - rt2800_init_bbp(rt2x00dev) || - rt2800_init_rfcsr(rt2x00dev))) + if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev))) return -EIO; - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - - udelay(50); - - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - - rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0); @@ -211,45 +178,12 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg); - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - - /* - * Initialize LED control - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff, - word & 0xff, (word >> 8) & 0xff); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff, - word & 0xff, (word >> 8) & 0xff); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff, - word & 0xff, (word >> 8) & 0xff); - - return 0; + return rt2800_enable_radio(rt2x00dev); } static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev) { - u32 reg; - - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0); - rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); - rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); - - /* Wait for DMA, ignore error */ - rt2800_wait_wpdma_ready(rt2x00dev); - + rt2800_disable_radio(rt2x00dev); rt2x00usb_disable_radio(rt2x00dev); } -- cgit v1.2.3-59-g8ed1b From 46323e112ce2a0fdaf2dd5389f95b248576b8fda Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 23 Aug 2010 19:55:43 +0200 Subject: rt2x00: Fix channel configuration for RF3052 We missed a check for RF3052 in the config_channel configuration function. As a result the channel is not properly configured for RF3052 devices. This also requires rt2800_config_channel_rf3xxx to support 5GHz channels, so we must apply the TXPOWER_A_TO_DEV and TXPOWER_G_TO_DEV conversions during rt2800_config_channel() Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b2f9b04134eb..cbab2e126167 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1244,8 +1244,7 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev, if (info->tx_power1 < 0) info->tx_power1 += 7; - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, - TXPOWER_A_TO_DEV(info->tx_power1)); + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->tx_power1); rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, (info->tx_power2 >= 0)); @@ -1253,13 +1252,10 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev, if (info->tx_power2 < 0) info->tx_power2 += 7; - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, - TXPOWER_A_TO_DEV(info->tx_power2)); + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->tx_power2); } else { - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, - TXPOWER_G_TO_DEV(info->tx_power1)); - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, - TXPOWER_G_TO_DEV(info->tx_power2)); + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->tx_power1); + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->tx_power2); } rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); @@ -1299,13 +1295,11 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, - TXPOWER_G_TO_DEV(info->tx_power1)); + rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->tx_power1); rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, - TXPOWER_G_TO_DEV(info->tx_power2)); + rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->tx_power2); rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); @@ -1329,10 +1323,19 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, unsigned int tx_pin; u8 bbp; + if (rf->channel <= 14) { + info->tx_power1 = TXPOWER_G_TO_DEV(info->tx_power1); + info->tx_power2 = TXPOWER_G_TO_DEV(info->tx_power2); + } else { + info->tx_power1 = TXPOWER_A_TO_DEV(info->tx_power1); + info->tx_power2 = TXPOWER_A_TO_DEV(info->tx_power2); + } + if (rt2x00_rf(rt2x00dev, RF2020) || rt2x00_rf(rt2x00dev, RF3020) || rt2x00_rf(rt2x00dev, RF3021) || - rt2x00_rf(rt2x00dev, RF3022)) + rt2x00_rf(rt2x00dev, RF3022) || + rt2x00_rf(rt2x00dev, RF3052)) rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); else rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); -- cgit v1.2.3-59-g8ed1b From 8d1331b37d5b656a7a8e561f8e9d7661dd00c910 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 23 Aug 2010 19:56:07 +0200 Subject: rt2x00: Fix max TX power settings During initialization each driver reads the default TX power for each individual channel. However mac80211 only accepts the maximum value (which is also handled as default value). As a result, the TX power of the device was being limited to the default value, which is often quite low compared to the real maximum acceptable value. This patch allows each driver to set the maximum value on a per-channel basis which is forwarded to mac80211. The default value will be preserved for now, in case we want to update mac80211 to differentiate between the maximum and default txpower. This fixes bug complaining about limited TX power values like: https://bugzilla.kernel.org/show_bug.cgi?id=16358 Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 6 ++- drivers/net/wireless/rt2x00/rt2500pci.c | 12 ++++-- drivers/net/wireless/rt2x00/rt2500usb.c | 12 ++++-- drivers/net/wireless/rt2x00/rt2800.h | 7 ++++ drivers/net/wireless/rt2x00/rt2800lib.c | 65 ++++++++++++++++++++------------- drivers/net/wireless/rt2x00/rt2x00.h | 5 ++- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- drivers/net/wireless/rt2x00/rt61pci.c | 12 ++++-- drivers/net/wireless/rt2x00/rt73usb.c | 12 ++++-- 9 files changed, 86 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index b86b6132a69c..e3005ff5ae98 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1487,8 +1487,10 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 0; i < 14; i++) { + info[i].max_power = TXPOWER_FROM_DEV(MAX_TXPOWER); + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } return 0; } diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 21f45810fd1e..1e6a91b8d3df 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1801,12 +1801,16 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 0; i < 14; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } if (spec->num_channels > 14) { - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = DEFAULT_TXPOWER; + for (i = 14; i < spec->num_channels; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = DEFAULT_TXPOWER; + } } return 0; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 8722464944f5..71d8d821c4e1 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1706,12 +1706,16 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 0; i < 14; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } if (spec->num_channels > 14) { - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = DEFAULT_TXPOWER; + for (i = 14; i < spec->num_channels; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = DEFAULT_TXPOWER; + } } return 0; diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index cf1f16bfcd5e..5c006a795346 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1858,6 +1858,13 @@ struct mac_iveiv_entry { #define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff) #define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) +/* + * EEPROM Maximum TX power values + */ +#define EEPROM_MAX_TX_POWER 0x0027 +#define EEPROM_MAX_TX_POWER_24GHZ FIELD16(0x00ff) +#define EEPROM_MAX_TX_POWER_5GHZ FIELD16(0xff00) + /* * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. * This is delta in 40MHZ. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index cbab2e126167..ecbd07a78edb 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1239,23 +1239,23 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev, * double meaning, and we should set a 7DBm boost flag. */ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, - (info->tx_power1 >= 0)); + (info->default_power1 >= 0)); - if (info->tx_power1 < 0) - info->tx_power1 += 7; + if (info->default_power1 < 0) + info->default_power1 += 7; - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->tx_power1); + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->default_power1); rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, - (info->tx_power2 >= 0)); + (info->default_power2 >= 0)); - if (info->tx_power2 < 0) - info->tx_power2 += 7; + if (info->default_power2 < 0) + info->default_power2 += 7; - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->tx_power2); + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->default_power2); } else { - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->tx_power1); - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->tx_power2); + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->default_power1); + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->default_power2); } rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); @@ -1295,11 +1295,11 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->tx_power1); + rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->default_power1); rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->tx_power2); + rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2); rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); @@ -1324,11 +1324,11 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, u8 bbp; if (rf->channel <= 14) { - info->tx_power1 = TXPOWER_G_TO_DEV(info->tx_power1); - info->tx_power2 = TXPOWER_G_TO_DEV(info->tx_power2); + info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1); + info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2); } else { - info->tx_power1 = TXPOWER_A_TO_DEV(info->tx_power1); - info->tx_power2 = TXPOWER_A_TO_DEV(info->tx_power2); + info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1); + info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2); } if (rt2x00_rf(rt2x00dev, RF2020) || @@ -2729,6 +2729,13 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) default_lna_gain); rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); + rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &word); + if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_24GHZ) == 0xff) + rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_24GHZ, MAX_G_TXPOWER); + if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_5GHZ) == 0xff) + rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_5GHZ, MAX_A_TXPOWER); + rt2x00_eeprom_write(rt2x00dev, EEPROM_MAX_TX_POWER, word); + return 0; } EXPORT_SYMBOL_GPL(rt2800_validate_eeprom); @@ -2968,9 +2975,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; struct channel_info *info; - char *tx_power1; - char *tx_power2; + char *default_power1; + char *default_power2; unsigned int i; + unsigned short max_power; u16 eeprom; /* @@ -3084,21 +3092,26 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; - tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); - tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); + rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &eeprom); + max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_24GHZ); + default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); + default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); for (i = 0; i < 14; i++) { - info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]); - info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]); + info[i].max_power = max_power; + info[i].default_power1 = TXPOWER_G_FROM_DEV(default_power1[i]); + info[i].default_power2 = TXPOWER_G_FROM_DEV(default_power2[i]); } if (spec->num_channels > 14) { - tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); - tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); + max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_5GHZ); + default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); + default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); for (i = 14; i < spec->num_channels; i++) { - info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]); - info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]); + info[i].max_power = max_power; + info[i].default_power1 = TXPOWER_A_FROM_DEV(default_power1[i]); + info[i].default_power2 = TXPOWER_A_FROM_DEV(default_power2[i]); } } diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 69308a0df74f..762f6b4e7afc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -213,8 +213,9 @@ struct channel_info { unsigned int flags; #define GEOGRAPHY_ALLOWED 0x00000001 - short tx_power1; - short tx_power2; + short max_power; + short default_power1; + short default_power2; }; /* diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index e692608bee8b..580595ba5683 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -711,7 +711,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, for (i = 0; i < spec->num_channels; i++) { rt2x00lib_channel(&channels[i], spec->channels[i].channel, - spec->channels_info[i].tx_power1, i); + spec->channels_info[i].max_power, i); } /* diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index ae4698e18729..8f017ad8c3db 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2656,13 +2656,17 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 0; i < 14; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } if (spec->num_channels > 14) { tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 14; i < spec->num_channels; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } } return 0; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ab9389439d75..ee2c52fd0d73 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2090,13 +2090,17 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 0; i < 14; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } if (spec->num_channels > 14) { tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 14; i < spec->num_channels; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } } return 0; -- cgit v1.2.3-59-g8ed1b From f8d8b7a13d3d61f99bf3dc5c9650f87f9818d7a7 Mon Sep 17 00:00:00 2001 From: "Arnaud Patard (Rtp)" Date: Mon, 23 Aug 2010 23:02:22 +0200 Subject: rt2x00: fix "buffer size not provably correct" build warning rt2x00 debugfs interface doesn't check the size of the data coming from userspace, leading to a build warning. Fix That. v2: return EINVAL if input is too long Signed-off-by: Arnaud Patard Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00debug.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 74f0d679883e..daf7f950a28f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -480,6 +480,9 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \ if (index >= debug->__name.word_count) \ return -EINVAL; \ \ + if (length > sizeof(line)) \ + return -EINVAL; \ + \ if (copy_from_user(line, buf, length)) \ return -EFAULT; \ \ -- cgit v1.2.3-59-g8ed1b From 74b70a4e38d542843fccfb367dce1ac861cc3890 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 24 Aug 2010 12:15:53 +0200 Subject: nl80211: fix missing nesting commit 95a6ccbb46c70cff376684c752831c014c87029d Author: Johannes Berg Date: Thu Aug 12 15:38:38 2010 +0200 cfg80211/mac80211: extensible frame processing introduced a netlink bug that caused parsing errors in userspace because it forgot to close a nesting, which would advertise a nesting length of zero to userspace, which then completely threw off parsing and led to Illegal nla->nla_type == 0 being printed by libnl. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 927ffbd2aebc..49f5ca35e787 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -636,6 +636,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, nla_nest_end(msg, nl_ftypes); } + nla_nest_end(msg, nl_ifs); + nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); if (!nl_ifs) goto nla_put_failure; -- cgit v1.2.3-59-g8ed1b From 2c15a0cf27a74213a714cc7be31685b841f7c1ac Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 24 Aug 2010 19:22:42 +0200 Subject: mac80211: fix rcu-unsafe pointer dereference This patch fixes a potential crash (null-pointer de- reference) which was introduced in my previous patch: "mac80211: AMPDU rx reorder timeout timer" During a BA teardown, the pointer to the soon-to-be-gone tid_ampdu_rx element will be nullified. Therefore the release timer mechanism has to be careful not to accidentally access the item without any RCU protection. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/rx.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index e1844f7085de..e67deb48af5c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2479,6 +2479,11 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) { struct sk_buff_head frames; struct ieee80211_rx_data rx = { }; + struct tid_ampdu_rx *tid_agg_rx; + + tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); + if (!tid_agg_rx) + return; __skb_queue_head_init(&frames); @@ -2493,10 +2498,9 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) test_bit(SCAN_OFF_CHANNEL, &sta->local->scanning))) rx.flags |= IEEE80211_RX_IN_SCAN; - spin_lock(&sta->ampdu_mlme.tid_rx[tid]->reorder_lock); - ieee80211_sta_reorder_release(&sta->local->hw, - sta->ampdu_mlme.tid_rx[tid], &frames); - spin_unlock(&sta->ampdu_mlme.tid_rx[tid]->reorder_lock); + spin_lock(&tid_agg_rx->reorder_lock); + ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx, &frames); + spin_unlock(&tid_agg_rx->reorder_lock); ieee80211_rx_handlers(&rx, &frames); } -- cgit v1.2.3-59-g8ed1b From 45f7e3116fad77e6dd15cb0e2eaccb7de7b806c9 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 24 Aug 2010 23:29:05 +0200 Subject: p54: better rssi->dbm conversion for longbow phys This patch should fix the dodgy signal and noise value reports for most longbow (p54spi) users: e.g.: (an older tcpdump extract) > 2.0 Mb/s 2437 MHz (0x00a0) -49dB signal -41dB noise > 1.0 Mb/s 2437 MHz (0x00a0) 4dB signal -41dB noise The formula is taken from stlc45xx: http://gitorious.org/stlc45xx/mainline/blobs/master/stlc45xx.c#line1199 Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/txrx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 34447d1ad80d..8f67db487f57 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -275,15 +275,15 @@ static int p54_rssi_to_dbm(struct p54_common *priv, int rssi) { int band = priv->hw->conf.channel->band; - if (priv->rxhw != 5) + if (priv->rxhw != 5) { return ((rssi * priv->rssical_db[band].mul) / 64 + priv->rssical_db[band].add) / 4; - else + } else { /* * TODO: find the correct formula */ - return ((rssi * priv->rssical_db[band].mul) / 64 + - priv->rssical_db[band].add) / 4; + return rssi / 2 - 110; + } } /* -- cgit v1.2.3-59-g8ed1b From 5eb5a52da6ef04604cf8faca43ec670f69f417d3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 25 Aug 2010 14:34:01 +0200 Subject: mac80211: fix mesh advertisement When a mac80211-based driver advertises mesh mode support, this will be advertised to userspace. However, if mac80211 was compiled without mesh support, then that won't actually be true. Fix this by removing the bit for mesh if mesh isn't compiled in. Since this synchronizes what we advertise to cfg80211 and actually support, it means we can now rely on cfg80211's interface type checks and need not check again in mac80211. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 33 --------------------------------- net/mac80211/main.c | 5 +++++ 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 7693ebc77596..581438255d7e 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -19,33 +19,6 @@ #include "rate.h" #include "mesh.h" -static bool nl80211_type_check(enum nl80211_iftype type) -{ - switch (type) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_MONITOR: -#ifdef CONFIG_MAC80211_MESH - case NL80211_IFTYPE_MESH_POINT: -#endif - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_WDS: - return true; - default: - return false; - } -} - -static bool nl80211_params_check(enum nl80211_iftype type, - struct vif_params *params) -{ - if (!nl80211_type_check(type)) - return false; - - return true; -} - static int ieee80211_add_iface(struct wiphy *wiphy, char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params) @@ -55,9 +28,6 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, struct ieee80211_sub_if_data *sdata; int err; - if (!nl80211_params_check(type, params)) - return -EINVAL; - err = ieee80211_if_add(local, name, &dev, type, params); if (err || type != NL80211_IFTYPE_MONITOR || !flags) return err; @@ -85,9 +55,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, if (ieee80211_sdata_running(sdata)) return -EBUSY; - if (!nl80211_params_check(type, params)) - return -EINVAL; - ret = ieee80211_if_change_type(sdata, type); if (ret) return ret; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 28415de5f476..80db5ea02052 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -622,6 +622,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) /* mac80211 always supports monitor */ local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); +#ifndef CONFIG_MAC80211_MESH + /* mesh depends on Kconfig, but drivers should set it if they want */ + local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT); +#endif + if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) -- cgit v1.2.3-59-g8ed1b From 903786a5626e7214d97b232bece88ee75e37d021 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 24 Aug 2010 07:27:56 -0700 Subject: iwlwifi: fix compile error without debugging support Encounter compiler error when iwlwifi debugging support is disabled, fix it. This compiler error was introduced by the previous WiFi/BT coexist patchset. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 33aa7a5eea8a..2939699a1200 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -206,7 +206,6 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; @@ -214,7 +213,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, scan_notif->scanned_channels, scan_notif->tsf_low, scan_notif->tsf_high, scan_notif->status); -#endif /* The HW is no longer scanning */ clear_bit(STATUS_SCAN_HW, &priv->status); -- cgit v1.2.3-59-g8ed1b From e9a47700cb35bc84d4954f762a193b150722612e Mon Sep 17 00:00:00 2001 From: Rajesh Borundia Date: Wed, 25 Aug 2010 04:03:02 +0000 Subject: qlcnic: eswitch config fixes o remove validation before deleting vlan id o Add missing 'break' while deleting vlan id. Signed-off-by: Rajesh Borundia Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_ctx.c | 1 + drivers/net/qlcnic/qlcnic_main.c | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index 315705b22be2..bd4b06b2d86d 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c @@ -1160,6 +1160,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, case QLCNIC_DEL_VLAN: arg1 |= (BIT_3 | BIT_5); arg1 &= ~(0x0ffff << 16); + break; default: return err; } diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 46b9137ca893..5d93b464681a 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -3301,8 +3301,6 @@ validate_esw_config(struct qlcnic_adapter *adapter, return QL_STATUS_INVALID_PARAM; break; case QLCNIC_DEL_VLAN: - if (!IS_VALID_VLAN(esw_cfg[i].vlan_id)) - return QL_STATUS_INVALID_PARAM; if (!esw_cfg[i].op_type) return QL_STATUS_INVALID_PARAM; break; @@ -3338,21 +3336,25 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, if (adapter->op_mode == QLCNIC_MGMT_FUNC) if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) return QL_STATUS_INVALID_PARAM; - if (adapter->ahw.pci_func == esw_cfg[i].pci_func) - op_mode = esw_cfg[i].op_mode; - qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]); - esw_cfg[i].op_mode = op_mode; - esw_cfg[i].pci_func = adapter->ahw.pci_func; - switch (esw_cfg[i].op_mode) { - case QLCNIC_PORT_DEFAULTS: - qlcnic_set_eswitch_port_features(adapter, - &esw_cfg[i]); - break; + + if (adapter->ahw.pci_func != esw_cfg[i].pci_func) + continue; + + op_mode = esw_cfg[i].op_mode; + qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]); + esw_cfg[i].op_mode = op_mode; + esw_cfg[i].pci_func = adapter->ahw.pci_func; + + switch (esw_cfg[i].op_mode) { + case QLCNIC_PORT_DEFAULTS: + qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]); + break; } } if (adapter->op_mode != QLCNIC_MGMT_FUNC) goto out; + for (i = 0; i < count; i++) { pci_func = esw_cfg[i].pci_func; npar = &adapter->npars[pci_func]; -- cgit v1.2.3-59-g8ed1b From 8cf61f890ac4c2a15acb24658feba13c9c838b52 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Wed, 25 Aug 2010 04:03:03 +0000 Subject: qlcnic: support port vlan id On NIC Partition capable adapter, Administrator can configure to tag packet with particular vlan id. Packet will be tagged and strip with that vlan id. Also if 'Tagging' flag is disable, other packet will be drop. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 4 +- drivers/net/qlcnic/qlcnic_init.c | 39 ++++++++++++++++++ drivers/net/qlcnic/qlcnic_main.c | 89 +++++++++++++++++++++++++++++++--------- 3 files changed, 111 insertions(+), 21 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 508d531a55e5..d15de63ed0bb 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -175,7 +175,7 @@ ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)) #define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \ - ((_desc)->flags_opcode = \ + ((_desc)->flags_opcode |= \ cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))) #define qlcnic_set_tx_frags_len(_desc, _frags, _len) \ @@ -902,6 +902,7 @@ struct qlcnic_mac_req { #define QLCNIC_BRIDGE_ENABLED 0X10 #define QLCNIC_DIAG_ENABLED 0x20 #define QLCNIC_ESWITCH_ENABLED 0x40 +#define QLCNIC_TAGGING_ENABLED 0x100 #define QLCNIC_MACSPOOF 0x200 #define QLCNIC_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) @@ -967,6 +968,7 @@ struct qlcnic_adapter { u16 max_tx_ques; u16 max_rx_ques; u16 max_mtu; + u16 pvid; u32 fw_hal_version; u32 capabilities; diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index a174521daa63..df91b754bb70 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "qlcnic.h" struct crb_addr_pair { @@ -1302,6 +1303,27 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, return skb; } +static int +qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb) +{ + u16 vlan_tag; + struct ethhdr *eth_hdr; + + if (!__vlan_get_tag(skb, &vlan_tag)) { + if (vlan_tag == adapter->pvid) { + /* strip the tag from the packet and send it up */ + eth_hdr = (struct ethhdr *) skb->data; + memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2); + skb_pull(skb, VLAN_HLEN); + return 0; + } + } + if (adapter->flags & QLCNIC_TAGGING_ENABLED) + return 0; + + return -EIO; +} + static struct qlcnic_rx_buffer * qlcnic_process_rcv(struct qlcnic_adapter *adapter, struct qlcnic_host_sds_ring *sds_ring, @@ -1342,6 +1364,15 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, skb_pull(skb, pkt_offset); skb->truesize = skb->len + sizeof(struct sk_buff); + + if (unlikely(adapter->pvid)) { + if (qlcnic_check_rx_tagging(adapter, skb)) { + adapter->stats.rxdropped++; + dev_kfree_skb_any(skb); + return buffer; + } + } + skb->protocol = eth_type_trans(skb, netdev); napi_gro_receive(&sds_ring->napi, skb); @@ -1406,6 +1437,14 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); skb_pull(skb, l2_hdr_offset); + + if (unlikely(adapter->pvid)) { + if (qlcnic_check_rx_tagging(adapter, skb)) { + adapter->stats.rxdropped++; + dev_kfree_skb_any(skb); + return buffer; + } + } skb->protocol = eth_type_trans(skb, netdev); iph = (struct iphdr *)skb->data; diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 5d93b464681a..089212214ad4 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -758,6 +758,21 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) adapter->max_rds_rings = MAX_RDS_RINGS; } +static void +qlcnic_set_vlan_config(struct qlcnic_adapter *adapter, + struct qlcnic_esw_func_cfg *esw_cfg) +{ + if (esw_cfg->discard_tagged) + adapter->flags &= ~QLCNIC_TAGGING_ENABLED; + else + adapter->flags |= QLCNIC_TAGGING_ENABLED; + + if (esw_cfg->vlan_id) + adapter->pvid = esw_cfg->vlan_id; + else + adapter->pvid = 0; +} + static void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, struct qlcnic_esw_func_cfg *esw_cfg) @@ -781,6 +796,7 @@ qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) esw_cfg.pci_func = adapter->ahw.pci_func; if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg)) return -EIO; + qlcnic_set_vlan_config(adapter, &esw_cfg); qlcnic_set_eswitch_port_features(adapter, &esw_cfg); return 0; @@ -1728,26 +1744,13 @@ qlcnic_tso_check(struct net_device *netdev, { u8 opcode = TX_ETHER_PKT; __be16 protocol = skb->protocol; - u16 flags = 0, vid = 0; - int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0; + u16 flags = 0; + int copied, offset, copy_len, hdr_len = 0, tso = 0; struct cmd_desc_type0 *hwdesc; struct vlan_ethhdr *vh; struct qlcnic_adapter *adapter = netdev_priv(netdev); u32 producer = tx_ring->producer; - - if (protocol == cpu_to_be16(ETH_P_8021Q)) { - - vh = (struct vlan_ethhdr *)skb->data; - protocol = vh->h_vlan_encapsulated_proto; - flags = FLAGS_VLAN_TAGGED; - - } else if (vlan_tx_tag_present(skb)) { - - flags = FLAGS_VLAN_OOB; - vid = vlan_tx_tag_get(skb); - qlcnic_set_tx_vlan_tci(first_desc, vid); - vlan_oob = 1; - } + int vlan_oob = first_desc->flags_opcode & cpu_to_le16(FLAGS_VLAN_OOB); if (*(skb->data) & BIT_0) { flags |= BIT_0; @@ -1818,7 +1821,7 @@ qlcnic_tso_check(struct net_device *netdev, vh = (struct vlan_ethhdr *)((char *)hwdesc + 2); skb_copy_from_linear_data(skb, vh, 12); vh->h_vlan_proto = htons(ETH_P_8021Q); - vh->h_vlan_TCI = htons(vid); + vh->h_vlan_TCI = htons(first_desc->vlan_TCI); skb_copy_from_linear_data_offset(skb, 12, (char *)vh + 16, copy_len - 16); @@ -1898,11 +1901,47 @@ out_err: return -ENOMEM; } +static int +qlcnic_check_tx_tagging(struct qlcnic_adapter *adapter, + struct sk_buff *skb, + struct cmd_desc_type0 *first_desc) +{ + u8 opcode = 0; + u16 flags = 0; + __be16 protocol = skb->protocol; + struct vlan_ethhdr *vh; + + if (protocol == cpu_to_be16(ETH_P_8021Q)) { + vh = (struct vlan_ethhdr *)skb->data; + protocol = vh->h_vlan_encapsulated_proto; + flags = FLAGS_VLAN_TAGGED; + qlcnic_set_tx_vlan_tci(first_desc, ntohs(vh->h_vlan_TCI)); + } else if (vlan_tx_tag_present(skb)) { + flags = FLAGS_VLAN_OOB; + qlcnic_set_tx_vlan_tci(first_desc, vlan_tx_tag_get(skb)); + } + if (unlikely(adapter->pvid)) { + if (first_desc->vlan_TCI && + !(adapter->flags & QLCNIC_TAGGING_ENABLED)) + return -EIO; + if (first_desc->vlan_TCI && + (adapter->flags & QLCNIC_TAGGING_ENABLED)) + goto set_flags; + + flags = FLAGS_VLAN_OOB; + qlcnic_set_tx_vlan_tci(first_desc, adapter->pvid); + } +set_flags: + qlcnic_set_tx_flags_opcode(first_desc, flags, opcode); + return 0; +} + static inline void qlcnic_clear_cmddesc(u64 *desc) { desc[0] = 0ULL; desc[2] = 0ULL; + desc[7] = 0ULL; } netdev_tx_t @@ -1952,6 +1991,12 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) pdev = adapter->pdev; + first_desc = hwdesc = &tx_ring->desc_head[producer]; + qlcnic_clear_cmddesc((u64 *)hwdesc); + + if (qlcnic_check_tx_tagging(adapter, skb, first_desc)) + goto drop_packet; + if (qlcnic_map_tx_skb(pdev, skb, pbuf)) { adapter->stats.tx_dma_map_error++; goto drop_packet; @@ -1960,9 +2005,6 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) pbuf->skb = skb; pbuf->frag_count = frag_count; - first_desc = hwdesc = &tx_ring->desc_head[producer]; - qlcnic_clear_cmddesc((u64 *)hwdesc); - qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len); qlcnic_set_tx_port(first_desc, adapter->portnum); @@ -3349,6 +3391,13 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, case QLCNIC_PORT_DEFAULTS: qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]); break; + case QLCNIC_ADD_VLAN: + qlcnic_set_vlan_config(adapter, &esw_cfg[i]); + break; + case QLCNIC_DEL_VLAN: + esw_cfg[i].vlan_id = 0; + qlcnic_set_vlan_config(adapter, &esw_cfg[i]); + break; } } -- cgit v1.2.3-59-g8ed1b From b18971d199cf35f68ffa22e4be1c477493fdb7e1 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Wed, 25 Aug 2010 04:03:04 +0000 Subject: qlcnic: fix fw recovery for PF Privilege function should wait for npar state to be operational before creating context. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 089212214ad4..26d9e10a36d5 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -997,11 +997,7 @@ check_fw_status: set_dev_ready: QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); qlcnic_idc_debug_info(adapter, 1); - err = qlcnic_check_npar_opertional(adapter); - if (err) { - qlcnic_release_firmware(adapter); - return err; - } + if (qlcnic_set_default_offload_settings(adapter)) goto err_out; if (qlcnic_reset_npar_config(adapter)) @@ -2602,6 +2598,7 @@ skip_ack_check: if (!adapter->nic_ops->start_firmware(adapter)) { qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); + adapter->fw_wait_cnt = 0; return; } goto err_ret; @@ -2617,6 +2614,7 @@ wait_npar: case QLCNIC_DEV_READY: if (!adapter->nic_ops->start_firmware(adapter)) { qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); + adapter->fw_wait_cnt = 0; return; } case QLCNIC_DEV_FAILED: @@ -2750,7 +2748,21 @@ qlcnic_attach_work(struct work_struct *work) struct qlcnic_adapter *adapter = container_of(work, struct qlcnic_adapter, fw_work.work); struct net_device *netdev = adapter->netdev; + u32 npar_state; + if (adapter->op_mode != QLCNIC_MGMT_FUNC) { + npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); + if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO) + qlcnic_clr_all_drv_state(adapter, 0); + else if (npar_state != QLCNIC_DEV_NPAR_OPER) + qlcnic_schedule_work(adapter, qlcnic_attach_work, + FW_POLL_DELAY); + else + goto attach; + QLCDB(adapter, DRV, "Waiting for NPAR state to operational\n"); + return; + } +attach: if (netif_running(netdev)) { if (qlcnic_up(adapter, netdev)) goto done; -- cgit v1.2.3-59-g8ed1b From 31018e068edb9eed740bec5cf14802c3c676c9ee Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Wed, 25 Aug 2010 04:03:05 +0000 Subject: qlcnic: change reg name Change QLCNIC_CRB_DEV_REF_COUNT to QLCNIC_CRB_DRV_ACTIVE to match document. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_ethtool.c | 2 +- drivers/net/qlcnic/qlcnic_hdr.h | 2 +- drivers/net/qlcnic/qlcnic_main.c | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 2805f88aaf7c..e294b825bac5 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -99,7 +99,7 @@ static const u32 diag_registers[] = { CRB_XG_STATE_P3, CRB_FW_CAPABILITIES_1, ISR_INT_STATE_REG, - QLCNIC_CRB_DEV_REF_COUNT, + QLCNIC_CRB_DRV_ACTIVE, QLCNIC_CRB_DEV_STATE, QLCNIC_CRB_DRV_STATE, QLCNIC_CRB_DRV_SCRATCH, diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h index 794f6572e8fd..219de9f4496f 100644 --- a/drivers/net/qlcnic/qlcnic_hdr.h +++ b/drivers/net/qlcnic/qlcnic_hdr.h @@ -698,7 +698,7 @@ enum { #define QLCNIC_PEG_ALIVE_COUNTER (QLCNIC_CAM_RAM(0xb0)) #define QLCNIC_PEG_HALT_STATUS1 (QLCNIC_CAM_RAM(0xa8)) #define QLCNIC_PEG_HALT_STATUS2 (QLCNIC_CAM_RAM(0xac)) -#define QLCNIC_CRB_DEV_REF_COUNT (QLCNIC_CAM_RAM(0x138)) +#define QLCNIC_CRB_DRV_ACTIVE (QLCNIC_CAM_RAM(0x138)) #define QLCNIC_CRB_DEV_STATE (QLCNIC_CAM_RAM(0x140)) #define QLCNIC_CRB_DRV_STATE (QLCNIC_CAM_RAM(0x144)) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 26d9e10a36d5..630a077e4547 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -540,7 +540,7 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter) void __iomem *priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE; /* If other drivers are not in use set their privilege level */ - ref_count = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); + ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); ret = qlcnic_api_lock(adapter); if (ret) goto err_lock; @@ -2404,9 +2404,9 @@ qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed) if (qlcnic_api_lock(adapter)) goto err; - val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); + val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); QLC_DEV_CLR_REF_CNT(val, adapter->portnum); - QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val); + QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val); if (failed) { QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED); @@ -2433,7 +2433,7 @@ qlcnic_check_drv_state(struct qlcnic_adapter *adapter) int act, state; state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); - act = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); + act = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); if (((state & 0x11111111) == (act & 0x11111111)) || ((act & 0x11111111) == ((state >> 1) & 0x11111111))) @@ -2468,10 +2468,10 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter) if (qlcnic_api_lock(adapter)) return -1; - val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); + val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); if (!(val & (1 << (portnum * 4)))) { QLC_DEV_SET_REF_CNT(val, portnum); - QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val); + QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val); } prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); -- cgit v1.2.3-59-g8ed1b From c061b18df0f1fe3f50fe451dbbdc9ede3c19701a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Aug 2010 18:20:03 +0000 Subject: drivers/net: Remove address use from assignments of function pointers "foo = &function" is more commonly written "foo = function" Done with coccinelle script: // @r@ identifier f; @@ f(...) { ... } @@ identifier r.f; @@ - &f + f // drivers/net/tehuti.c used a function and struct with the same name, the function was renamed. Compile tested x86 only. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/3c503.c | 8 +++---- drivers/net/3c515.c | 2 +- drivers/net/3c59x.c | 2 +- drivers/net/atl1e/atl1e_main.c | 2 +- drivers/net/atlx/atl1.c | 2 +- drivers/net/atlx/atl2.c | 4 ++-- drivers/net/atp.c | 2 +- drivers/net/bcm63xx_enet.c | 2 +- drivers/net/cpmac.c | 2 +- drivers/net/declance.c | 2 +- drivers/net/dl2k.c | 2 +- drivers/net/e1000/e1000_main.c | 6 ++--- drivers/net/e1000e/netdev.c | 4 ++-- drivers/net/ehea/ehea_main.c | 6 ++--- drivers/net/epic100.c | 2 +- drivers/net/fealnx.c | 4 ++-- drivers/net/forcedeth.c | 6 ++--- drivers/net/hamachi.c | 2 +- drivers/net/hp.c | 8 +++---- drivers/net/hydra.c | 8 +++---- drivers/net/igb/igb_main.c | 4 ++-- drivers/net/ioc3-eth.c | 2 +- drivers/net/ixgb/ixgb_main.c | 2 +- drivers/net/ixgbe/ixgbe_main.c | 4 ++-- drivers/net/ixgbevf/ixgbevf_main.c | 2 +- drivers/net/mac8390.c | 48 +++++++++++++++++++------------------- drivers/net/natsemi.c | 2 +- drivers/net/pci-skeleton.c | 2 +- drivers/net/pcmcia/3c574_cs.c | 2 +- drivers/net/pcmcia/3c589_cs.c | 2 +- drivers/net/pcmcia/axnet_cs.c | 10 ++++---- drivers/net/pcmcia/pcnet_cs.c | 16 ++++++------- drivers/net/pcmcia/smc91c92_cs.c | 4 ++-- drivers/net/rrunner.c | 2 +- drivers/net/sh_eth.c | 2 +- drivers/net/sis900.c | 2 +- drivers/net/sunbmac.c | 2 +- drivers/net/sundance.c | 2 +- drivers/net/sunhme.c | 2 +- drivers/net/sunlance.c | 2 +- drivers/net/tehuti.c | 8 +++---- drivers/net/tlan.c | 8 +++---- drivers/net/tulip/dmfe.c | 2 +- drivers/net/tulip/uli526x.c | 2 +- drivers/net/tulip/winbond-840.c | 2 +- drivers/net/wan/lmc/lmc_main.c | 2 +- drivers/net/wd.c | 8 +++---- drivers/net/wireless/ray_cs.c | 12 +++++----- drivers/net/yellowfin.c | 2 +- 49 files changed, 118 insertions(+), 118 deletions(-) diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index baac246561b9..4777a1cbcd8d 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -337,10 +337,10 @@ el2_probe1(struct net_device *dev, int ioaddr) /* Finish setting the board's parameters. */ ei_status.stop_page = EL2_MB1_STOP_PG; ei_status.word16 = wordlength; - ei_status.reset_8390 = &el2_reset_8390; - ei_status.get_8390_hdr = &el2_get_8390_hdr; - ei_status.block_input = &el2_block_input; - ei_status.block_output = &el2_block_output; + ei_status.reset_8390 = el2_reset_8390; + ei_status.get_8390_hdr = el2_get_8390_hdr; + ei_status.block_input = el2_block_input; + ei_status.block_output = el2_block_output; if (dev->irq == 2) dev->irq = 9; diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index 3bba835f1a21..8a6eb0c44486 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -734,7 +734,7 @@ static int corkscrew_open(struct net_device *dev) init_timer(&vp->timer); vp->timer.expires = jiffies + media_tbl[dev->if_port].wait; vp->timer.data = (unsigned long) dev; - vp->timer.function = &corkscrew_timer; /* timer handler */ + vp->timer.function = corkscrew_timer; /* timer handler */ add_timer(&vp->timer); } else dev->if_port = vp->default_media; diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index c754d88e5ec9..7a01588fb6fb 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1738,7 +1738,7 @@ vortex_open(struct net_device *dev) /* Use the now-standard shared IRQ implementation. */ if ((retval = request_irq(dev->irq, vp->full_bus_master_rx ? - &boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev))) { + boomerang_interrupt : vortex_interrupt, IRQF_SHARED, dev->name, dev))) { pr_err("%s: Could not reserve IRQ %d\n", dev->name, dev->irq); goto err; } diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 1acea5774e89..1ae44bb26317 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -2316,7 +2316,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev, netif_napi_add(netdev, &adapter->napi, atl1e_clean, 64); init_timer(&adapter->phy_config_timer); - adapter->phy_config_timer.function = &atl1e_phy_config; + adapter->phy_config_timer.function = atl1e_phy_config; adapter->phy_config_timer.data = (unsigned long) adapter; /* get user settings */ diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 63b9ba0cc67e..5837b0184d4b 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -3036,7 +3036,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev, netif_carrier_off(netdev); netif_stop_queue(netdev); - setup_timer(&adapter->phy_config_timer, &atl1_phy_config, + setup_timer(&adapter->phy_config_timer, atl1_phy_config, (unsigned long)adapter); adapter->phy_timer_pending = false; diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index 8da87383fb39..07adc8446901 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -1444,11 +1444,11 @@ static int __devinit atl2_probe(struct pci_dev *pdev, atl2_check_options(adapter); init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = &atl2_watchdog; + adapter->watchdog_timer.function = atl2_watchdog; adapter->watchdog_timer.data = (unsigned long) adapter; init_timer(&adapter->phy_config_timer); - adapter->phy_config_timer.function = &atl2_phy_config; + adapter->phy_config_timer.function = atl2_phy_config; adapter->phy_config_timer.data = (unsigned long) adapter; INIT_WORK(&adapter->reset_task, atl2_reset_task); diff --git a/drivers/net/atp.c b/drivers/net/atp.c index bd2f9d331dac..dfd96b20547f 100644 --- a/drivers/net/atp.c +++ b/drivers/net/atp.c @@ -445,7 +445,7 @@ static int net_open(struct net_device *dev) init_timer(&lp->timer); lp->timer.expires = jiffies + TIMED_CHECKER; lp->timer.data = (unsigned long)dev; - lp->timer.function = &atp_timed_checker; /* timer handler */ + lp->timer.function = atp_timed_checker; /* timer handler */ add_timer(&lp->timer); netif_start_queue(dev); diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index e2f70c3d7be4..ecfef240a303 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -798,7 +798,7 @@ static int bcm_enet_open(struct net_device *dev) snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, priv->mac_id ? "1" : "0", priv->phy_id); - phydev = phy_connect(dev, phy_id, &bcm_enet_adjust_phy_link, 0, + phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(phydev)) { diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 8e142aaa05d4..5a5af1ca7541 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -1175,7 +1175,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev) snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); - priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, + priv->phy = phy_connect(dev, priv->phy_name, cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(priv->phy)) { diff --git a/drivers/net/declance.c b/drivers/net/declance.c index d7de376d7178..219eb5ad5c12 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -1255,7 +1255,7 @@ static int __devinit dec_lance_probe(struct device *bdev, const int type) */ init_timer(&lp->multicast_timer); lp->multicast_timer.data = (unsigned long) dev; - lp->multicast_timer.function = &lance_set_multicast_retry; + lp->multicast_timer.function = lance_set_multicast_retry; ret = register_netdev(dev); if (ret) { diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index a2f238d20caa..e1a8216ff692 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -465,7 +465,7 @@ rio_open (struct net_device *dev) init_timer (&np->timer); np->timer.expires = jiffies + 1*HZ; np->timer.data = (unsigned long) dev; - np->timer.function = &rio_timer; + np->timer.function = rio_timer; add_timer (&np->timer); /* Start Tx/Rx */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5cc39ed289c6..3e8ac4baae1b 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -962,15 +962,15 @@ static int __devinit e1000_probe(struct pci_dev *pdev, e1000_get_bus_info(hw); init_timer(&adapter->tx_fifo_stall_timer); - adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall; + adapter->tx_fifo_stall_timer.function = e1000_82547_tx_fifo_stall; adapter->tx_fifo_stall_timer.data = (unsigned long)adapter; init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = &e1000_watchdog; + adapter->watchdog_timer.function = e1000_watchdog; adapter->watchdog_timer.data = (unsigned long) adapter; init_timer(&adapter->phy_info_timer); - adapter->phy_info_timer.function = &e1000_update_phy_info; + adapter->phy_info_timer.function = e1000_update_phy_info; adapter->phy_info_timer.data = (unsigned long)adapter; INIT_WORK(&adapter->reset_task, e1000_reset_task); diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 2b8ef44bd2b1..5f3eac6432cb 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -5745,11 +5745,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev, } init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = &e1000_watchdog; + adapter->watchdog_timer.function = e1000_watchdog; adapter->watchdog_timer.data = (unsigned long) adapter; init_timer(&adapter->phy_info_timer); - adapter->phy_info_timer.function = &e1000_update_phy_info; + adapter->phy_info_timer.function = e1000_update_phy_info; adapter->phy_info_timer.data = (unsigned long) adapter; INIT_WORK(&adapter->reset_task, e1000_reset_task); diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 2b98ee80fa33..043d99013056 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -3721,7 +3721,7 @@ int __init ehea_module_init(void) if (ret) ehea_info("failed registering memory remove notifier"); - ret = crash_shutdown_register(&ehea_crash_handler); + ret = crash_shutdown_register(ehea_crash_handler); if (ret) ehea_info("failed registering crash handler"); @@ -3746,7 +3746,7 @@ out3: out2: unregister_memory_notifier(&ehea_mem_nb); unregister_reboot_notifier(&ehea_reboot_nb); - crash_shutdown_unregister(&ehea_crash_handler); + crash_shutdown_unregister(ehea_crash_handler); out: return ret; } @@ -3759,7 +3759,7 @@ static void __exit ehea_module_exit(void) driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities); ibmebus_unregister_driver(&ehea_driver); unregister_reboot_notifier(&ehea_reboot_nb); - ret = crash_shutdown_unregister(&ehea_crash_handler); + ret = crash_shutdown_unregister(ehea_crash_handler); if (ret) ehea_info("failed unregistering crash handler"); unregister_memory_notifier(&ehea_mem_nb); diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 57c8ac0ef3f1..32543a300b81 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -758,7 +758,7 @@ static int epic_open(struct net_device *dev) init_timer(&ep->timer); ep->timer.expires = jiffies + 3*HZ; ep->timer.data = (unsigned long)dev; - ep->timer.function = &epic_timer; /* timer handler */ + ep->timer.function = epic_timer; /* timer handler */ add_timer(&ep->timer); return 0; diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index d7e8f6b8f4cf..dd54abe2f710 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -915,14 +915,14 @@ static int netdev_open(struct net_device *dev) init_timer(&np->timer); np->timer.expires = RUN_AT(3 * HZ); np->timer.data = (unsigned long) dev; - np->timer.function = &netdev_timer; + np->timer.function = netdev_timer; /* timer handler */ add_timer(&np->timer); init_timer(&np->reset_timer); np->reset_timer.data = (unsigned long) dev; - np->reset_timer.function = &reset_timer; + np->reset_timer.function = reset_timer; np->reset_timer_armed = 0; return 0; diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 4da05b1b445c..6a44fe411589 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5440,13 +5440,13 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i init_timer(&np->oom_kick); np->oom_kick.data = (unsigned long) dev; - np->oom_kick.function = &nv_do_rx_refill; /* timer handler */ + np->oom_kick.function = nv_do_rx_refill; /* timer handler */ init_timer(&np->nic_poll); np->nic_poll.data = (unsigned long) dev; - np->nic_poll.function = &nv_do_nic_poll; /* timer handler */ + np->nic_poll.function = nv_do_nic_poll; /* timer handler */ init_timer(&np->stats_poll); np->stats_poll.data = (unsigned long) dev; - np->stats_poll.function = &nv_do_stats_poll; /* timer handler */ + np->stats_poll.function = nv_do_stats_poll; /* timer handler */ err = pci_enable_device(pci_dev); if (err) diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 49aac7027fbb..9a6485892b3d 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1004,7 +1004,7 @@ static int hamachi_open(struct net_device *dev) init_timer(&hmp->timer); hmp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */ hmp->timer.data = (unsigned long)dev; - hmp->timer.function = &hamachi_timer; /* timer handler */ + hmp->timer.function = hamachi_timer; /* timer handler */ add_timer(&hmp->timer); return 0; diff --git a/drivers/net/hp.c b/drivers/net/hp.c index 86ececd3c658..d15d2f2ba78e 100644 --- a/drivers/net/hp.c +++ b/drivers/net/hp.c @@ -204,10 +204,10 @@ static int __init hp_probe1(struct net_device *dev, int ioaddr) ei_status.rx_start_page = HP_START_PG + TX_PAGES; ei_status.stop_page = wordmode ? HP_16BSTOP_PG : HP_8BSTOP_PG; - ei_status.reset_8390 = &hp_reset_8390; - ei_status.get_8390_hdr = &hp_get_8390_hdr; - ei_status.block_input = &hp_block_input; - ei_status.block_output = &hp_block_output; + ei_status.reset_8390 = hp_reset_8390; + ei_status.get_8390_hdr = hp_get_8390_hdr; + ei_status.block_input = hp_block_input; + ei_status.block_output = hp_block_output; hp_init_card(dev); retval = register_netdev(dev); diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 07d8e5b634f3..376e953c6ce6 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -155,10 +155,10 @@ static int __devinit hydra_init(struct zorro_dev *z) ei_status.rx_start_page = start_page + TX_PAGES; - ei_status.reset_8390 = &hydra_reset_8390; - ei_status.block_input = &hydra_block_input; - ei_status.block_output = &hydra_block_output; - ei_status.get_8390_hdr = &hydra_get_8390_hdr; + ei_status.reset_8390 = hydra_reset_8390; + ei_status.block_input = hydra_block_input; + ei_status.block_output = hydra_block_output; + ei_status.get_8390_hdr = hydra_get_8390_hdr; ei_status.reg_offset = hydra_offsets; dev->netdev_ops = &hydra_netdev_ops; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 985e37cf17b6..d35cc38bf8b2 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1888,9 +1888,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, goto err_eeprom; } - setup_timer(&adapter->watchdog_timer, &igb_watchdog, + setup_timer(&adapter->watchdog_timer, igb_watchdog, (unsigned long) adapter); - setup_timer(&adapter->phy_info_timer, &igb_update_phy_info, + setup_timer(&adapter->phy_info_timer, igb_update_phy_info, (unsigned long) adapter); INIT_WORK(&adapter->reset_task, igb_reset_task); diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 0b3f6df5cff7..c8ee8d28767b 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -827,7 +827,7 @@ static void ioc3_mii_start(struct ioc3_private *ip) { ip->ioc3_timer.expires = jiffies + (12 * HZ)/10; /* 1.2 sec. */ ip->ioc3_timer.data = (unsigned long) ip; - ip->ioc3_timer.function = &ioc3_timer; + ip->ioc3_timer.function = ioc3_timer; add_timer(&ip->ioc3_timer); } diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 45fc89b9ba64..33c4ffe6e103 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -470,7 +470,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->part_num = ixgb_get_ee_pba_number(&adapter->hw); init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = &ixgb_watchdog; + adapter->watchdog_timer.function = ixgb_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; INIT_WORK(&adapter->tx_timeout_task, ixgb_tx_timeout_task); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 18163e312a39..5e4dc1b0a1bd 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -6730,7 +6730,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, * which might start the timer */ init_timer(&adapter->sfp_timer); - adapter->sfp_timer.function = &ixgbe_sfp_timer; + adapter->sfp_timer.function = ixgbe_sfp_timer; adapter->sfp_timer.data = (unsigned long) adapter; INIT_WORK(&adapter->sfp_task, ixgbe_sfp_task); @@ -6862,7 +6862,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, hw->mac.ops.disable_tx_laser(hw); init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = &ixgbe_watchdog; + adapter->watchdog_timer.function = ixgbe_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; INIT_WORK(&adapter->reset_task, ixgbe_reset_task); diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 918c00359b0a..5d3c869283a5 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -3426,7 +3426,7 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev, } init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = &ixgbevf_watchdog; + adapter->watchdog_timer.function = ixgbevf_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; INIT_WORK(&adapter->reset_task, ixgbevf_reset_task); diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index 3832fa4961dd..f84f5e6ededb 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -562,19 +562,19 @@ static int __init mac8390_initdev(struct net_device *dev, case ACCESS_16: /* 16 bit card, register map is reversed */ - ei_status.reset_8390 = &mac8390_no_reset; - ei_status.block_input = &slow_sane_block_input; - ei_status.block_output = &slow_sane_block_output; - ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; + ei_status.reset_8390 = mac8390_no_reset; + ei_status.block_input = slow_sane_block_input; + ei_status.block_output = slow_sane_block_output; + ei_status.get_8390_hdr = slow_sane_get_8390_hdr; ei_status.reg_offset = back4_offsets; break; case ACCESS_32: /* 32 bit card, register map is reversed */ - ei_status.reset_8390 = &mac8390_no_reset; - ei_status.block_input = &sane_block_input; - ei_status.block_output = &sane_block_output; - ei_status.get_8390_hdr = &sane_get_8390_hdr; + ei_status.reset_8390 = mac8390_no_reset; + ei_status.block_input = sane_block_input; + ei_status.block_output = sane_block_output; + ei_status.get_8390_hdr = sane_get_8390_hdr; ei_status.reg_offset = back4_offsets; access_bitmode = 1; break; @@ -586,19 +586,19 @@ static int __init mac8390_initdev(struct net_device *dev, * but overwrite system memory when run at 32 bit. * so we run them all at 16 bit. */ - ei_status.reset_8390 = &mac8390_no_reset; - ei_status.block_input = &slow_sane_block_input; - ei_status.block_output = &slow_sane_block_output; - ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; + ei_status.reset_8390 = mac8390_no_reset; + ei_status.block_input = slow_sane_block_input; + ei_status.block_output = slow_sane_block_output; + ei_status.get_8390_hdr = slow_sane_get_8390_hdr; ei_status.reg_offset = back4_offsets; break; case MAC8390_CABLETRON: /* 16 bit card, register map is short forward */ - ei_status.reset_8390 = &mac8390_no_reset; - ei_status.block_input = &slow_sane_block_input; - ei_status.block_output = &slow_sane_block_output; - ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; + ei_status.reset_8390 = mac8390_no_reset; + ei_status.block_input = slow_sane_block_input; + ei_status.block_output = slow_sane_block_output; + ei_status.get_8390_hdr = slow_sane_get_8390_hdr; ei_status.reg_offset = fwrd2_offsets; break; @@ -606,19 +606,19 @@ static int __init mac8390_initdev(struct net_device *dev, case MAC8390_KINETICS: /* 16 bit memory, register map is forward */ /* dayna and similar */ - ei_status.reset_8390 = &mac8390_no_reset; - ei_status.block_input = &dayna_block_input; - ei_status.block_output = &dayna_block_output; - ei_status.get_8390_hdr = &dayna_get_8390_hdr; + ei_status.reset_8390 = mac8390_no_reset; + ei_status.block_input = dayna_block_input; + ei_status.block_output = dayna_block_output; + ei_status.get_8390_hdr = dayna_get_8390_hdr; ei_status.reg_offset = fwrd4_offsets; break; case MAC8390_INTERLAN: /* 16 bit memory, register map is forward */ - ei_status.reset_8390 = &interlan_reset; - ei_status.block_input = &slow_sane_block_input; - ei_status.block_output = &slow_sane_block_output; - ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; + ei_status.reset_8390 = interlan_reset; + ei_status.block_input = slow_sane_block_input; + ei_status.block_output = slow_sane_block_output; + ei_status.get_8390_hdr = slow_sane_get_8390_hdr; ei_status.reg_offset = fwrd4_offsets; break; diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index a6033d48b5cc..2fd39630b1e5 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -1570,7 +1570,7 @@ static int netdev_open(struct net_device *dev) init_timer(&np->timer); np->timer.expires = round_jiffies(jiffies + NATSEMI_TIMER_FREQ); np->timer.data = (unsigned long)dev; - np->timer.function = &netdev_timer; /* timer handler */ + np->timer.function = netdev_timer; /* timer handler */ add_timer(&np->timer); return 0; diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 56f3fc45dbaa..8dd03439d994 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -1125,7 +1125,7 @@ static int netdrv_open(struct net_device *dev) init_timer(&tp->timer); tp->timer.expires = jiffies + 3 * HZ; tp->timer.data = (unsigned long) dev; - tp->timer.function = &netdrv_timer; + tp->timer.function = netdrv_timer; add_timer(&tp->timer); DPRINTK("EXIT, returning 0\n"); diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 9b319be7f1d2..042f6777e6b9 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -707,7 +707,7 @@ static int el3_open(struct net_device *dev) netif_start_queue(dev); tc574_reset(dev); - lp->media.function = &media_check; + lp->media.function = media_check; lp->media.data = (unsigned long) dev; lp->media.expires = jiffies + HZ; add_timer(&lp->media); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 1c534f392474..7f2baf5eae26 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -538,7 +538,7 @@ static int el3_open(struct net_device *dev) tc589_reset(dev); init_timer(&lp->media); - lp->media.function = &media_check; + lp->media.function = media_check; lp->media.data = (unsigned long) dev; lp->media.expires = jiffies + HZ; add_timer(&lp->media); diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index e97f1519a15f..3f61fde70d73 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -356,10 +356,10 @@ static int axnet_config(struct pcmcia_device *link) ei_status.tx_start_page = AXNET_START_PG; ei_status.rx_start_page = AXNET_START_PG + TX_PAGES; ei_status.stop_page = AXNET_STOP_PG; - ei_status.reset_8390 = &axnet_reset_8390; - ei_status.get_8390_hdr = &get_8390_hdr; - ei_status.block_input = &block_input; - ei_status.block_output = &block_output; + ei_status.reset_8390 = axnet_reset_8390; + ei_status.get_8390_hdr = get_8390_hdr; + ei_status.block_input = block_input; + ei_status.block_output = block_output; if (inb(dev->base_addr + AXNET_TEST) != 0) info->flags |= IS_AX88790; @@ -530,7 +530,7 @@ static int axnet_open(struct net_device *dev) info->link_status = 0x00; init_timer(&info->watchdog); - info->watchdog.function = &ei_watchdog; + info->watchdog.function = ei_watchdog; info->watchdog.data = (u_long)dev; info->watchdog.expires = jiffies + HZ; add_timer(&info->watchdog); diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 1815b2644b96..5ad42e0aee25 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -624,7 +624,7 @@ static int pcnet_config(struct pcmcia_device *link) ei_status.name = "NE2000"; ei_status.word16 = 1; - ei_status.reset_8390 = &pcnet_reset_8390; + ei_status.reset_8390 = pcnet_reset_8390; if (info->flags & (IS_DL10019|IS_DL10022)) mii_phy_probe(dev); @@ -957,7 +957,7 @@ static int pcnet_open(struct net_device *dev) info->phy_id = info->eth_phy; info->link_status = 0x00; init_timer(&info->watchdog); - info->watchdog.function = &ei_watchdog; + info->watchdog.function = ei_watchdog; info->watchdog.data = (u_long)dev; info->watchdog.expires = jiffies + HZ; add_timer(&info->watchdog); @@ -1341,9 +1341,9 @@ static int setup_dma_config(struct pcmcia_device *link, int start_pg, ei_status.stop_page = stop_pg; /* set up block i/o functions */ - ei_status.get_8390_hdr = &dma_get_8390_hdr; - ei_status.block_input = &dma_block_input; - ei_status.block_output = &dma_block_output; + ei_status.get_8390_hdr = dma_get_8390_hdr; + ei_status.block_input = dma_block_input; + ei_status.block_output = dma_block_output; return 0; } @@ -1489,9 +1489,9 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg, ei_status.stop_page = start_pg + ((req.Size - offset) >> 8); /* set up block i/o functions */ - ei_status.get_8390_hdr = &shmem_get_8390_hdr; - ei_status.block_input = &shmem_block_input; - ei_status.block_output = &shmem_block_output; + ei_status.get_8390_hdr = shmem_get_8390_hdr; + ei_status.block_input = shmem_block_input; + ei_status.block_output = shmem_block_output; info->flags |= USE_SHMEM; return 0; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index cc7a357feac9..3d1c549b7038 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -296,7 +296,7 @@ static const struct net_device_ops smc_netdev_ops = { .ndo_tx_timeout = smc_tx_timeout, .ndo_set_config = s9k_config, .ndo_set_multicast_list = set_rx_mode, - .ndo_do_ioctl = &smc_ioctl, + .ndo_do_ioctl = smc_ioctl, .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -1117,7 +1117,7 @@ static int smc_open(struct net_device *dev) smc_reset(dev); init_timer(&smc->media); - smc->media.function = &media_check; + smc->media.function = media_check; smc->media.data = (u_long) dev; smc->media.expires = jiffies + HZ; add_timer(&smc->media); diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index e26e107f93e0..e68c941926f1 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -1245,7 +1245,7 @@ static int rr_open(struct net_device *dev) init_timer(&rrpriv->timer); rrpriv->timer.expires = RUN_AT(5*HZ); /* 5 sec. watchdog */ rrpriv->timer.data = (unsigned long)dev; - rrpriv->timer.function = &rr_timer; /* timer handler */ + rrpriv->timer.function = rr_timer; /* timer handler */ add_timer(&rrpriv->timer); netif_start_queue(dev); diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 79fd02bc69fd..a812efc3632e 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -1031,7 +1031,7 @@ static int sh_eth_phy_init(struct net_device *ndev) mdp->duplex = -1; /* Try connect to PHY */ - phydev = phy_connect(ndev, phy_id, &sh_eth_adjust_link, + phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(phydev)) { dev_err(&ndev->dev, "phy_connect failed\n"); diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index bbbded76ff14..ffdd8591d4bc 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -1042,7 +1042,7 @@ sis900_open(struct net_device *net_dev) init_timer(&sis_priv->timer); sis_priv->timer.expires = jiffies + HZ; sis_priv->timer.data = (unsigned long)net_dev; - sis_priv->timer.function = &sis900_timer; + sis_priv->timer.function = sis900_timer; add_timer(&sis_priv->timer); return 0; diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 618643e3ca3e..0a6a5ced3c1c 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -617,7 +617,7 @@ static void bigmac_begin_auto_negotiation(struct bigmac *bp) bp->timer_ticks = 0; bp->bigmac_timer.expires = jiffies + (12 * HZ) / 10; bp->bigmac_timer.data = (unsigned long) bp; - bp->bigmac_timer.function = &bigmac_timer; + bp->bigmac_timer.function = bigmac_timer; add_timer(&bp->bigmac_timer); } diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 2678588ea4b2..3fa949789b42 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -874,7 +874,7 @@ static int netdev_open(struct net_device *dev) init_timer(&np->timer); np->timer.expires = jiffies + 3*HZ; np->timer.data = (unsigned long)dev; - np->timer.function = &netdev_timer; /* timer handler */ + np->timer.function = netdev_timer; /* timer handler */ add_timer(&np->timer); /* Enable interrupts by setting the interrupt mask. */ diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index d96431eb698b..45f315ed1868 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1409,7 +1409,7 @@ force_link: hp->timer_ticks = 0; hp->happy_timer.expires = jiffies + (12 * HZ)/10; /* 1.2 sec. */ hp->happy_timer.data = (unsigned long) hp; - hp->happy_timer.function = &happy_meal_timer; + hp->happy_timer.function = happy_meal_timer; add_timer(&hp->happy_timer); } diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 8dcb858f2168..2cf84e5968b2 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1483,7 +1483,7 @@ no_link_test: */ init_timer(&lp->multicast_timer); lp->multicast_timer.data = (unsigned long) dev; - lp->multicast_timer.function = &lance_set_multicast_retry; + lp->multicast_timer.function = lance_set_multicast_retry; if (register_netdev(dev)) { printk(KERN_ERR "SunLance: Cannot register device.\n"); diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index d808f95a87ca..3128d6a8e9ce 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -92,7 +92,7 @@ static void bdx_rx_free(struct bdx_priv *priv); static void bdx_tx_free(struct bdx_priv *priv); /* Definitions needed by bdx_probe */ -static void bdx_ethtool_ops(struct net_device *netdev); +static void bdx_set_ethtool_ops(struct net_device *netdev); /************************************************************************* * Print Info * @@ -2005,7 +2005,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ndev->netdev_ops = &bdx_netdev_ops; ndev->tx_queue_len = BDX_NDEV_TXQ_LEN; - bdx_ethtool_ops(ndev); /* ethtool interface */ + bdx_set_ethtool_ops(ndev); /* ethtool interface */ /* these fields are used for info purposes only * so we can have them same for all ports of the board */ @@ -2410,10 +2410,10 @@ static void bdx_get_ethtool_stats(struct net_device *netdev, } /* - * bdx_ethtool_ops - ethtool interface implementation + * bdx_set_ethtool_ops - ethtool interface implementation * @netdev */ -static void bdx_ethtool_ops(struct net_device *netdev) +static void bdx_set_ethtool_ops(struct net_device *netdev) { static const struct ethtool_ops bdx_ethtool_ops = { .get_settings = bdx_get_settings, diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index ccee3eddc5f4..0564ca05963d 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -393,7 +393,7 @@ TLan_SetTimer( struct net_device *dev, u32 ticks, u32 type ) spin_unlock_irqrestore(&priv->lock, flags); return; } - priv->timer.function = &TLan_Timer; + priv->timer.function = TLan_Timer; if (!in_irq()) spin_unlock_irqrestore(&priv->lock, flags); @@ -1453,7 +1453,7 @@ static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int ) TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT ); if ( priv->timer.function == NULL ) { - priv->timer.function = &TLan_Timer; + priv->timer.function = TLan_Timer; priv->timer.data = (unsigned long) dev; priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY; priv->timerSetAt = jiffies; @@ -1601,7 +1601,7 @@ drop_and_reuse: TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT ); if ( priv->timer.function == NULL ) { - priv->timer.function = &TLan_Timer; + priv->timer.function = TLan_Timer; priv->timer.data = (unsigned long) dev; priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY; priv->timerSetAt = jiffies; @@ -1897,7 +1897,7 @@ static void TLan_Timer( unsigned long data ) TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK ); } else { - priv->timer.function = &TLan_Timer; + priv->timer.function = TLan_Timer; priv->timer.expires = priv->timerSetAt + TLAN_TIMER_ACT_DELAY; spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 0bc4f3030a80..a9f7d5d1a269 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -599,7 +599,7 @@ static int dmfe_open(struct DEVICE *dev) init_timer(&db->timer); db->timer.expires = DMFE_TIMER_WUT + HZ * 2; db->timer.data = (unsigned long)dev; - db->timer.function = &dmfe_timer; + db->timer.function = dmfe_timer; add_timer(&db->timer); return 0; diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 96de5829b940..1dc27a557275 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -480,7 +480,7 @@ static int uli526x_open(struct net_device *dev) init_timer(&db->timer); db->timer.expires = ULI526X_TIMER_WUT + HZ * 2; db->timer.data = (unsigned long)dev; - db->timer.function = &uli526x_timer; + db->timer.function = uli526x_timer; add_timer(&db->timer); return 0; diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 66d41cf8da29..f0b231035dee 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -662,7 +662,7 @@ static int netdev_open(struct net_device *dev) init_timer(&np->timer); np->timer.expires = jiffies + 1*HZ; np->timer.data = (unsigned long)dev; - np->timer.function = &netdev_timer; /* timer handler */ + np->timer.function = netdev_timer; /* timer handler */ add_timer(&np->timer); return 0; out_err: diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index e2c6f7f4f51c..43af85b8e45e 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -1105,7 +1105,7 @@ static int lmc_open(struct net_device *dev) init_timer (&sc->timer); sc->timer.expires = jiffies + HZ; sc->timer.data = (unsigned long) dev; - sc->timer.function = &lmc_watchdog; + sc->timer.function = lmc_watchdog; add_timer (&sc->timer); lmc_trace(dev, "lmc_open out"); diff --git a/drivers/net/wd.c b/drivers/net/wd.c index eb72c67699ab..f1549fff0edc 100644 --- a/drivers/net/wd.c +++ b/drivers/net/wd.c @@ -342,10 +342,10 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n", model_name, dev->irq, dev->mem_start, dev->mem_end-1); - ei_status.reset_8390 = &wd_reset_8390; - ei_status.block_input = &wd_block_input; - ei_status.block_output = &wd_block_output; - ei_status.get_8390_hdr = &wd_get_8390_hdr; + ei_status.reset_8390 = wd_reset_8390; + ei_status.block_input = wd_block_input; + ei_status.block_output = wd_block_output; + ei_status.get_8390_hdr = wd_get_8390_hdr; dev->netdev_ops = &wd_netdev_ops; NS8390_init(dev, 0); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 3bd9cf76517d..d91a831a7700 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -604,7 +604,7 @@ static int dl_startup_params(struct net_device *dev) /* Start kernel timer to wait for dl startup to complete. */ local->timer.expires = jiffies + HZ / 2; local->timer.data = (long)local; - local->timer.function = &verify_dl_startup; + local->timer.function = verify_dl_startup; add_timer(&local->timer); dev_dbg(&link->dev, "ray_cs dl_startup_params started timer for verify_dl_startup\n"); @@ -1981,12 +1981,12 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id) dev_dbg(&link->dev, "ray_cs interrupt network \"%s\" start failed\n", local->sparm.b4.a_current_ess_id); - local->timer.function = &start_net; + local->timer.function = start_net; } else { dev_dbg(&link->dev, "ray_cs interrupt network \"%s\" join failed\n", local->sparm.b4.a_current_ess_id); - local->timer.function = &join_net; + local->timer.function = join_net; } add_timer(&local->timer); } @@ -2454,9 +2454,9 @@ static void authenticate(ray_dev_t *local) del_timer(&local->timer); if (build_auth_frame(local, local->bss_id, OPEN_AUTH_REQUEST)) { - local->timer.function = &join_net; + local->timer.function = join_net; } else { - local->timer.function = &authenticate_timeout; + local->timer.function = authenticate_timeout; } local->timer.expires = jiffies + HZ * 2; local->timer.data = (long)local; @@ -2541,7 +2541,7 @@ static void associate(ray_dev_t *local) del_timer(&local->timer); local->timer.expires = jiffies + HZ * 2; local->timer.data = (long)local; - local->timer.function = &join_net; + local->timer.function = join_net; add_timer(&local->timer); local->card_status = CARD_ASSOC_FAILED; return; diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 4eb67aed68dd..cd1b3dcd61db 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -646,7 +646,7 @@ static int yellowfin_open(struct net_device *dev) init_timer(&yp->timer); yp->timer.expires = jiffies + 3*HZ; yp->timer.data = (unsigned long)dev; - yp->timer.function = &yellowfin_timer; /* timer handler */ + yp->timer.function = yellowfin_timer; /* timer handler */ add_timer(&yp->timer); return 0; -- cgit v1.2.3-59-g8ed1b From c6a056a349d10a6e879ca1be6067873b6feed259 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 23 Aug 2010 19:44:08 +0000 Subject: bnx2x: small fix in stats handling Use a private variable to fold rx_dropped value, instead of shared destination buffer, as it might break SNMP applications. Signed-off-by: Eric Dumazet CC: Eilon Greenstein CC: Dmitry Kravkov Acked-By: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_stats.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c index c74724461020..efa1403ebf82 100644 --- a/drivers/net/bnx2x/bnx2x_stats.c +++ b/drivers/net/bnx2x/bnx2x_stats.c @@ -969,6 +969,7 @@ static void bnx2x_net_stats_update(struct bnx2x *bp) { struct bnx2x_eth_stats *estats = &bp->eth_stats; struct net_device_stats *nstats = &bp->dev->stats; + unsigned long tmp; int i; nstats->rx_packets = @@ -985,10 +986,10 @@ static void bnx2x_net_stats_update(struct bnx2x *bp) nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi); - nstats->rx_dropped = estats->mac_discard; + tmp = estats->mac_discard; for_each_queue(bp, i) - nstats->rx_dropped += - le32_to_cpu(bp->fp[i].old_tclient.checksum_discard); + tmp += le32_to_cpu(bp->fp[i].old_tclient.checksum_discard); + nstats->rx_dropped = tmp; nstats->tx_dropped = 0; -- cgit v1.2.3-59-g8ed1b From 219dd1132a71875ef7097ac47f634d402478385c Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Mon, 23 Aug 2010 20:40:40 +0000 Subject: stmmac: fix_mac_speed is called during 10/100<->1000 speed changes This patch modifies the stmmac_adjust_link() function so the fix_mac_speed() is called not only when link speed is changing between 10 and 100 Mbps (as required in RMII mode) but also for 1000 Mbps. Signed-off-by: Pawel Moll Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index bbb7951b9c4c..86b6c69c068c 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -238,6 +238,9 @@ static void stmmac_adjust_link(struct net_device *dev) case 1000: if (likely(priv->is_gmac)) ctrl &= ~priv->hw->link.port; + if (likely(priv->fix_mac_speed)) + priv->fix_mac_speed(priv->bsp_priv, + phydev->speed); break; case 100: case 10: -- cgit v1.2.3-59-g8ed1b From ac75791aa943c7953521cb4fa7728bf51f9abd2d Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Mon, 23 Aug 2010 20:40:41 +0000 Subject: stmmac: remove dead option in the driver's Kconfig This patch removes the CPU_SUBTYPE_ST40 dependency in the driver's Kconfig. In fact, this option has been removed in the commit: f96691872439ab2071171d4531c4a95b5d493ae5 as reported by Christian Dietrich. Note that the driver remains tested on STM platforms, only. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/stmmac/Kconfig b/drivers/net/stmmac/Kconfig index eb63d44748a7..643968098afd 100644 --- a/drivers/net/stmmac/Kconfig +++ b/drivers/net/stmmac/Kconfig @@ -3,10 +3,10 @@ config STMMAC_ETH select MII select PHYLIB select CRC32 - depends on NETDEVICES && CPU_SUBTYPE_ST40 + depends on NETDEVICES help This is the driver for the Ethernet IPs are built around a - Synopsys IP Core and fully tested on the STMicroelectronics + Synopsys IP Core and only tested on the STMicroelectronics platforms. if STMMAC_ETH -- cgit v1.2.3-59-g8ed1b From ad01b7d480a4a135f974afd5c617c417e0b0542f Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Mon, 23 Aug 2010 20:40:42 +0000 Subject: stmmac: make ioaddr 'void __iomem *' rather than unsigned long This avoids unnecessary casting and adds the ioaddr in the private structure. This patch also removes many warning when compile the driver. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/common.h | 50 +++++++-------- drivers/net/stmmac/dwmac1000_core.c | 18 +++--- drivers/net/stmmac/dwmac1000_dma.c | 8 +-- drivers/net/stmmac/dwmac100_core.c | 20 +++--- drivers/net/stmmac/dwmac100_dma.c | 8 +-- drivers/net/stmmac/dwmac_dma.h | 16 ++--- drivers/net/stmmac/dwmac_lib.c | 22 +++---- drivers/net/stmmac/enh_desc.c | 2 +- drivers/net/stmmac/norm_desc.c | 2 +- drivers/net/stmmac/stmmac.h | 3 +- drivers/net/stmmac/stmmac_ethtool.c | 21 +++--- drivers/net/stmmac/stmmac_main.c | 124 +++++++++++++++++------------------- drivers/net/stmmac/stmmac_mdio.c | 21 +++--- include/linux/stmmac.h | 2 +- 14 files changed, 153 insertions(+), 164 deletions(-) diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h index 66b9da0260fe..e8cbcb5c206e 100644 --- a/drivers/net/stmmac/common.h +++ b/drivers/net/stmmac/common.h @@ -167,7 +167,7 @@ struct stmmac_desc_ops { int (*get_tx_ls) (struct dma_desc *p); /* Return the transmit status looking at the TDES1 */ int (*tx_status) (void *data, struct stmmac_extra_stats *x, - struct dma_desc *p, unsigned long ioaddr); + struct dma_desc *p, void __iomem *ioaddr); /* Get the buffer size from the descriptor */ int (*get_tx_len) (struct dma_desc *p); /* Handle extra events on specific interrupts hw dependent */ @@ -182,44 +182,44 @@ struct stmmac_desc_ops { struct stmmac_dma_ops { /* DMA core initialization */ - int (*init) (unsigned long ioaddr, int pbl, u32 dma_tx, u32 dma_rx); + int (*init) (void __iomem *ioaddr, int pbl, u32 dma_tx, u32 dma_rx); /* Dump DMA registers */ - void (*dump_regs) (unsigned long ioaddr); + void (*dump_regs) (void __iomem *ioaddr); /* Set tx/rx threshold in the csr6 register * An invalid value enables the store-and-forward mode */ - void (*dma_mode) (unsigned long ioaddr, int txmode, int rxmode); + void (*dma_mode) (void __iomem *ioaddr, int txmode, int rxmode); /* To track extra statistic (if supported) */ void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x, - unsigned long ioaddr); - void (*enable_dma_transmission) (unsigned long ioaddr); - void (*enable_dma_irq) (unsigned long ioaddr); - void (*disable_dma_irq) (unsigned long ioaddr); - void (*start_tx) (unsigned long ioaddr); - void (*stop_tx) (unsigned long ioaddr); - void (*start_rx) (unsigned long ioaddr); - void (*stop_rx) (unsigned long ioaddr); - int (*dma_interrupt) (unsigned long ioaddr, + void __iomem *ioaddr); + void (*enable_dma_transmission) (void __iomem *ioaddr); + void (*enable_dma_irq) (void __iomem *ioaddr); + void (*disable_dma_irq) (void __iomem *ioaddr); + void (*start_tx) (void __iomem *ioaddr); + void (*stop_tx) (void __iomem *ioaddr); + void (*start_rx) (void __iomem *ioaddr); + void (*stop_rx) (void __iomem *ioaddr); + int (*dma_interrupt) (void __iomem *ioaddr, struct stmmac_extra_stats *x); }; struct stmmac_ops { /* MAC core initialization */ - void (*core_init) (unsigned long ioaddr) ____cacheline_aligned; + void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned; /* Dump MAC registers */ - void (*dump_regs) (unsigned long ioaddr); + void (*dump_regs) (void __iomem *ioaddr); /* Handle extra events on specific interrupts hw dependent */ - void (*host_irq_status) (unsigned long ioaddr); + void (*host_irq_status) (void __iomem *ioaddr); /* Multicast filter setting */ void (*set_filter) (struct net_device *dev); /* Flow control setting */ - void (*flow_ctrl) (unsigned long ioaddr, unsigned int duplex, + void (*flow_ctrl) (void __iomem *ioaddr, unsigned int duplex, unsigned int fc, unsigned int pause_time); /* Set power management mode (e.g. magic frame) */ - void (*pmt) (unsigned long ioaddr, unsigned long mode); + void (*pmt) (void __iomem *ioaddr, unsigned long mode); /* Set/Get Unicast MAC addresses */ - void (*set_umac_addr) (unsigned long ioaddr, unsigned char *addr, + void (*set_umac_addr) (void __iomem *ioaddr, unsigned char *addr, unsigned int reg_n); - void (*get_umac_addr) (unsigned long ioaddr, unsigned char *addr, + void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr, unsigned int reg_n); }; @@ -243,11 +243,11 @@ struct mac_device_info { struct mac_link link; }; -struct mac_device_info *dwmac1000_setup(unsigned long addr); -struct mac_device_info *dwmac100_setup(unsigned long addr); +struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr); +struct mac_device_info *dwmac100_setup(void __iomem *ioaddr); -extern void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6], +extern void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6], unsigned int high, unsigned int low); -extern void stmmac_get_mac_addr(unsigned long ioaddr, unsigned char *addr, +extern void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr, unsigned int high, unsigned int low); -extern void dwmac_dma_flush_tx_fifo(unsigned long ioaddr); +extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr); diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c index 2b2f5c8caf1c..8bbfc0f48dea 100644 --- a/drivers/net/stmmac/dwmac1000_core.c +++ b/drivers/net/stmmac/dwmac1000_core.c @@ -30,7 +30,7 @@ #include #include "dwmac1000.h" -static void dwmac1000_core_init(unsigned long ioaddr) +static void dwmac1000_core_init(void __iomem *ioaddr) { u32 value = readl(ioaddr + GMAC_CONTROL); value |= GMAC_CORE_INIT; @@ -50,7 +50,7 @@ static void dwmac1000_core_init(unsigned long ioaddr) #endif } -static void dwmac1000_dump_regs(unsigned long ioaddr) +static void dwmac1000_dump_regs(void __iomem *ioaddr) { int i; pr_info("\tDWMAC1000 regs (base addr = 0x%8x)\n", (unsigned int)ioaddr); @@ -62,14 +62,14 @@ static void dwmac1000_dump_regs(unsigned long ioaddr) } } -static void dwmac1000_set_umac_addr(unsigned long ioaddr, unsigned char *addr, +static void dwmac1000_set_umac_addr(void __iomem *ioaddr, unsigned char *addr, unsigned int reg_n) { stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), GMAC_ADDR_LOW(reg_n)); } -static void dwmac1000_get_umac_addr(unsigned long ioaddr, unsigned char *addr, +static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr, unsigned int reg_n) { stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), @@ -78,7 +78,7 @@ static void dwmac1000_get_umac_addr(unsigned long ioaddr, unsigned char *addr, static void dwmac1000_set_filter(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; + void __iomem *ioaddr = (void __iomem *) dev->base_addr; unsigned int value = 0; CHIP_DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n", @@ -139,7 +139,7 @@ static void dwmac1000_set_filter(struct net_device *dev) readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW)); } -static void dwmac1000_flow_ctrl(unsigned long ioaddr, unsigned int duplex, +static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex, unsigned int fc, unsigned int pause_time) { unsigned int flow = 0; @@ -162,7 +162,7 @@ static void dwmac1000_flow_ctrl(unsigned long ioaddr, unsigned int duplex, writel(flow, ioaddr + GMAC_FLOW_CTRL); } -static void dwmac1000_pmt(unsigned long ioaddr, unsigned long mode) +static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode) { unsigned int pmt = 0; @@ -178,7 +178,7 @@ static void dwmac1000_pmt(unsigned long ioaddr, unsigned long mode) } -static void dwmac1000_irq_status(unsigned long ioaddr) +static void dwmac1000_irq_status(void __iomem *ioaddr) { u32 intr_status = readl(ioaddr + GMAC_INT_STATUS); @@ -211,7 +211,7 @@ struct stmmac_ops dwmac1000_ops = { .get_umac_addr = dwmac1000_get_umac_addr, }; -struct mac_device_info *dwmac1000_setup(unsigned long ioaddr) +struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr) { struct mac_device_info *mac; u32 uid = readl(ioaddr + GMAC_VERSION); diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/stmmac/dwmac1000_dma.c index 415805057cb0..2ef5a56370e9 100644 --- a/drivers/net/stmmac/dwmac1000_dma.c +++ b/drivers/net/stmmac/dwmac1000_dma.c @@ -29,7 +29,7 @@ #include "dwmac1000.h" #include "dwmac_dma.h" -static int dwmac1000_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx, +static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx, u32 dma_rx) { u32 value = readl(ioaddr + DMA_BUS_MODE); @@ -58,7 +58,7 @@ static int dwmac1000_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx, return 0; } -static void dwmac1000_dma_operation_mode(unsigned long ioaddr, int txmode, +static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode, int rxmode) { u32 csr6 = readl(ioaddr + DMA_CONTROL); @@ -111,12 +111,12 @@ static void dwmac1000_dma_operation_mode(unsigned long ioaddr, int txmode, /* Not yet implemented --- no RMON module */ static void dwmac1000_dma_diagnostic_fr(void *data, - struct stmmac_extra_stats *x, unsigned long ioaddr) + struct stmmac_extra_stats *x, void __iomem *ioaddr) { return; } -static void dwmac1000_dump_dma_regs(unsigned long ioaddr) +static void dwmac1000_dump_dma_regs(void __iomem *ioaddr) { int i; pr_info(" DMA registers\n"); diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c index 2fb165fa2ba0..135a8082816e 100644 --- a/drivers/net/stmmac/dwmac100_core.c +++ b/drivers/net/stmmac/dwmac100_core.c @@ -31,7 +31,7 @@ #include #include "dwmac100.h" -static void dwmac100_core_init(unsigned long ioaddr) +static void dwmac100_core_init(void __iomem *ioaddr) { u32 value = readl(ioaddr + MAC_CONTROL); @@ -42,12 +42,12 @@ static void dwmac100_core_init(unsigned long ioaddr) #endif } -static void dwmac100_dump_mac_regs(unsigned long ioaddr) +static void dwmac100_dump_mac_regs(void __iomem *ioaddr) { pr_info("\t----------------------------------------------\n" "\t DWMAC 100 CSR (base addr = 0x%8x)\n" "\t----------------------------------------------\n", - (unsigned int)ioaddr); + (unsigned int) ioaddr); pr_info("\tcontrol reg (offset 0x%x): 0x%08x\n", MAC_CONTROL, readl(ioaddr + MAC_CONTROL)); pr_info("\taddr HI (offset 0x%x): 0x%08x\n ", MAC_ADDR_HIGH, @@ -77,18 +77,18 @@ static void dwmac100_dump_mac_regs(unsigned long ioaddr) MMC_LOW_INTR_MASK, readl(ioaddr + MMC_LOW_INTR_MASK)); } -static void dwmac100_irq_status(unsigned long ioaddr) +static void dwmac100_irq_status(void __iomem *ioaddr) { return; } -static void dwmac100_set_umac_addr(unsigned long ioaddr, unsigned char *addr, +static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr, unsigned int reg_n) { stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW); } -static void dwmac100_get_umac_addr(unsigned long ioaddr, unsigned char *addr, +static void dwmac100_get_umac_addr(void __iomem *ioaddr, unsigned char *addr, unsigned int reg_n) { stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW); @@ -96,7 +96,7 @@ static void dwmac100_get_umac_addr(unsigned long ioaddr, unsigned char *addr, static void dwmac100_set_filter(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; + void __iomem *ioaddr = (void __iomem *) dev->base_addr; u32 value = readl(ioaddr + MAC_CONTROL); if (dev->flags & IFF_PROMISC) { @@ -145,7 +145,7 @@ static void dwmac100_set_filter(struct net_device *dev) readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW)); } -static void dwmac100_flow_ctrl(unsigned long ioaddr, unsigned int duplex, +static void dwmac100_flow_ctrl(void __iomem *ioaddr, unsigned int duplex, unsigned int fc, unsigned int pause_time) { unsigned int flow = MAC_FLOW_CTRL_ENABLE; @@ -158,7 +158,7 @@ static void dwmac100_flow_ctrl(unsigned long ioaddr, unsigned int duplex, /* No PMT module supported for this Ethernet Controller. * Tested on ST platforms only. */ -static void dwmac100_pmt(unsigned long ioaddr, unsigned long mode) +static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode) { return; } @@ -174,7 +174,7 @@ struct stmmac_ops dwmac100_ops = { .get_umac_addr = dwmac100_get_umac_addr, }; -struct mac_device_info *dwmac100_setup(unsigned long ioaddr) +struct mac_device_info *dwmac100_setup(void __iomem *ioaddr) { struct mac_device_info *mac; diff --git a/drivers/net/stmmac/dwmac100_dma.c b/drivers/net/stmmac/dwmac100_dma.c index 2fece7b72727..c7279d2b946b 100644 --- a/drivers/net/stmmac/dwmac100_dma.c +++ b/drivers/net/stmmac/dwmac100_dma.c @@ -31,7 +31,7 @@ #include "dwmac100.h" #include "dwmac_dma.h" -static int dwmac100_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx, +static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx, u32 dma_rx) { u32 value = readl(ioaddr + DMA_BUS_MODE); @@ -58,7 +58,7 @@ static int dwmac100_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx, /* Store and Forward capability is not used at all.. * The transmit threshold can be programmed by * setting the TTC bits in the DMA control register.*/ -static void dwmac100_dma_operation_mode(unsigned long ioaddr, int txmode, +static void dwmac100_dma_operation_mode(void __iomem *ioaddr, int txmode, int rxmode) { u32 csr6 = readl(ioaddr + DMA_CONTROL); @@ -73,7 +73,7 @@ static void dwmac100_dma_operation_mode(unsigned long ioaddr, int txmode, writel(csr6, ioaddr + DMA_CONTROL); } -static void dwmac100_dump_dma_regs(unsigned long ioaddr) +static void dwmac100_dump_dma_regs(void __iomem *ioaddr) { int i; @@ -91,7 +91,7 @@ static void dwmac100_dump_dma_regs(unsigned long ioaddr) /* DMA controller has two counters to track the number of * the receive missed frames. */ static void dwmac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x, - unsigned long ioaddr) + void __iomem *ioaddr) { struct net_device_stats *stats = (struct net_device_stats *)data; u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR); diff --git a/drivers/net/stmmac/dwmac_dma.h b/drivers/net/stmmac/dwmac_dma.h index 7b815a1b7b8c..da3f5ccf83d3 100644 --- a/drivers/net/stmmac/dwmac_dma.h +++ b/drivers/net/stmmac/dwmac_dma.h @@ -97,12 +97,12 @@ #define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */ #define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */ -extern void dwmac_enable_dma_transmission(unsigned long ioaddr); -extern void dwmac_enable_dma_irq(unsigned long ioaddr); -extern void dwmac_disable_dma_irq(unsigned long ioaddr); -extern void dwmac_dma_start_tx(unsigned long ioaddr); -extern void dwmac_dma_stop_tx(unsigned long ioaddr); -extern void dwmac_dma_start_rx(unsigned long ioaddr); -extern void dwmac_dma_stop_rx(unsigned long ioaddr); -extern int dwmac_dma_interrupt(unsigned long ioaddr, +extern void dwmac_enable_dma_transmission(void __iomem *ioaddr); +extern void dwmac_enable_dma_irq(void __iomem *ioaddr); +extern void dwmac_disable_dma_irq(void __iomem *ioaddr); +extern void dwmac_dma_start_tx(void __iomem *ioaddr); +extern void dwmac_dma_stop_tx(void __iomem *ioaddr); +extern void dwmac_dma_start_rx(void __iomem *ioaddr); +extern void dwmac_dma_stop_rx(void __iomem *ioaddr); +extern int dwmac_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x); diff --git a/drivers/net/stmmac/dwmac_lib.c b/drivers/net/stmmac/dwmac_lib.c index a85415216ef4..d65fab1ba790 100644 --- a/drivers/net/stmmac/dwmac_lib.c +++ b/drivers/net/stmmac/dwmac_lib.c @@ -32,43 +32,43 @@ #endif /* CSR1 enables the transmit DMA to check for new descriptor */ -void dwmac_enable_dma_transmission(unsigned long ioaddr) +void dwmac_enable_dma_transmission(void __iomem *ioaddr) { writel(1, ioaddr + DMA_XMT_POLL_DEMAND); } -void dwmac_enable_dma_irq(unsigned long ioaddr) +void dwmac_enable_dma_irq(void __iomem *ioaddr) { writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); } -void dwmac_disable_dma_irq(unsigned long ioaddr) +void dwmac_disable_dma_irq(void __iomem *ioaddr) { writel(0, ioaddr + DMA_INTR_ENA); } -void dwmac_dma_start_tx(unsigned long ioaddr) +void dwmac_dma_start_tx(void __iomem *ioaddr) { u32 value = readl(ioaddr + DMA_CONTROL); value |= DMA_CONTROL_ST; writel(value, ioaddr + DMA_CONTROL); } -void dwmac_dma_stop_tx(unsigned long ioaddr) +void dwmac_dma_stop_tx(void __iomem *ioaddr) { u32 value = readl(ioaddr + DMA_CONTROL); value &= ~DMA_CONTROL_ST; writel(value, ioaddr + DMA_CONTROL); } -void dwmac_dma_start_rx(unsigned long ioaddr) +void dwmac_dma_start_rx(void __iomem *ioaddr) { u32 value = readl(ioaddr + DMA_CONTROL); value |= DMA_CONTROL_SR; writel(value, ioaddr + DMA_CONTROL); } -void dwmac_dma_stop_rx(unsigned long ioaddr) +void dwmac_dma_stop_rx(void __iomem *ioaddr) { u32 value = readl(ioaddr + DMA_CONTROL); value &= ~DMA_CONTROL_SR; @@ -145,7 +145,7 @@ static void show_rx_process_state(unsigned int status) } #endif -int dwmac_dma_interrupt(unsigned long ioaddr, +int dwmac_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x) { int ret = 0; @@ -219,7 +219,7 @@ int dwmac_dma_interrupt(unsigned long ioaddr, return ret; } -void dwmac_dma_flush_tx_fifo(unsigned long ioaddr) +void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr) { u32 csr6 = readl(ioaddr + DMA_CONTROL); writel((csr6 | DMA_CONTROL_FTF), ioaddr + DMA_CONTROL); @@ -227,7 +227,7 @@ void dwmac_dma_flush_tx_fifo(unsigned long ioaddr) do {} while ((readl(ioaddr + DMA_CONTROL) & DMA_CONTROL_FTF)); } -void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6], +void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6], unsigned int high, unsigned int low) { unsigned long data; @@ -238,7 +238,7 @@ void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6], writel(data, ioaddr + low); } -void stmmac_get_mac_addr(unsigned long ioaddr, unsigned char *addr, +void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr, unsigned int high, unsigned int low) { unsigned int hi_addr, lo_addr; diff --git a/drivers/net/stmmac/enh_desc.c b/drivers/net/stmmac/enh_desc.c index f612f986a7e1..77ff88c3958b 100644 --- a/drivers/net/stmmac/enh_desc.c +++ b/drivers/net/stmmac/enh_desc.c @@ -25,7 +25,7 @@ #include "common.h" static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x, - struct dma_desc *p, unsigned long ioaddr) + struct dma_desc *p, void __iomem *ioaddr) { int ret = 0; struct net_device_stats *stats = (struct net_device_stats *)data; diff --git a/drivers/net/stmmac/norm_desc.c b/drivers/net/stmmac/norm_desc.c index 31ad53643792..51f4440ab98b 100644 --- a/drivers/net/stmmac/norm_desc.c +++ b/drivers/net/stmmac/norm_desc.c @@ -25,7 +25,7 @@ #include "common.h" static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x, - struct dma_desc *p, unsigned long ioaddr) + struct dma_desc *p, void __iomem *ioaddr) { int ret = 0; struct net_device_stats *stats = (struct net_device_stats *)data; diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h index ebebc644b1b8..cca53dbac361 100644 --- a/drivers/net/stmmac/stmmac.h +++ b/drivers/net/stmmac/stmmac.h @@ -54,6 +54,7 @@ struct stmmac_priv { unsigned int dma_buf_sz; struct device *device; struct mac_device_info *hw; + void __iomem *ioaddr; struct stmmac_extra_stats xstats; struct napi_struct napi; @@ -65,7 +66,7 @@ struct stmmac_priv { int phy_mask; int (*phy_reset) (void *priv); void (*fix_mac_speed) (void *priv, unsigned int speed); - void (*bus_setup)(unsigned long ioaddr); + void (*bus_setup)(void __iomem *ioaddr); void *bsp_priv; int phy_irq; diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index f080509923f0..63b68e61afce 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -177,21 +177,21 @@ void stmmac_ethtool_gregs(struct net_device *dev, if (!priv->is_gmac) { /* MAC registers */ for (i = 0; i < 12; i++) - reg_space[i] = readl(dev->base_addr + (i * 4)); + reg_space[i] = readl(priv->ioaddr + (i * 4)); /* DMA registers */ for (i = 0; i < 9; i++) reg_space[i + 12] = - readl(dev->base_addr + (DMA_BUS_MODE + (i * 4))); - reg_space[22] = readl(dev->base_addr + DMA_CUR_TX_BUF_ADDR); - reg_space[23] = readl(dev->base_addr + DMA_CUR_RX_BUF_ADDR); + readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4))); + reg_space[22] = readl(priv->ioaddr + DMA_CUR_TX_BUF_ADDR); + reg_space[23] = readl(priv->ioaddr + DMA_CUR_RX_BUF_ADDR); } else { /* MAC registers */ for (i = 0; i < 55; i++) - reg_space[i] = readl(dev->base_addr + (i * 4)); + reg_space[i] = readl(priv->ioaddr + (i * 4)); /* DMA registers */ for (i = 0; i < 22; i++) reg_space[i + 55] = - readl(dev->base_addr + (DMA_BUS_MODE + (i * 4))); + readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4))); } } @@ -263,11 +263,9 @@ stmmac_set_pauseparam(struct net_device *netdev, cmd.phy_address = phy->addr; ret = phy_ethtool_sset(phy, &cmd); } - } else { - unsigned long ioaddr = netdev->base_addr; - priv->hw->mac->flow_ctrl(ioaddr, phy->duplex, + } else + priv->hw->mac->flow_ctrl(priv->ioaddr, phy->duplex, priv->flow_ctrl, priv->pause); - } spin_unlock(&priv->lock); return ret; } @@ -276,12 +274,11 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 *data) { struct stmmac_priv *priv = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int i; /* Update HW stats if supported */ priv->hw->dma->dma_diagnostic_fr(&dev->stats, (void *) &priv->xstats, - ioaddr); + priv->ioaddr); for (i = 0; i < STMMAC_STATS_LEN; i++) { char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset; diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 86b6c69c068c..c59c1061252a 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -202,7 +202,6 @@ static void stmmac_adjust_link(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); struct phy_device *phydev = priv->phydev; - unsigned long ioaddr = dev->base_addr; unsigned long flags; int new_state = 0; unsigned int fc = priv->flow_ctrl, pause_time = priv->pause; @@ -215,7 +214,7 @@ static void stmmac_adjust_link(struct net_device *dev) spin_lock_irqsave(&priv->lock, flags); if (phydev->link) { - u32 ctrl = readl(ioaddr + MAC_CTRL_REG); + u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG); /* Now we make sure that we can be in full duplex mode. * If not, we operate in half-duplex mode. */ @@ -229,7 +228,7 @@ static void stmmac_adjust_link(struct net_device *dev) } /* Flow Control operation */ if (phydev->pause) - priv->hw->mac->flow_ctrl(ioaddr, phydev->duplex, + priv->hw->mac->flow_ctrl(priv->ioaddr, phydev->duplex, fc, pause_time); if (phydev->speed != priv->speed) { @@ -268,7 +267,7 @@ static void stmmac_adjust_link(struct net_device *dev) priv->speed = phydev->speed; } - writel(ctrl, ioaddr + MAC_CTRL_REG); + writel(ctrl, priv->ioaddr + MAC_CTRL_REG); if (!priv->oldlink) { new_state = 1; @@ -345,7 +344,7 @@ static int stmmac_init_phy(struct net_device *dev) return 0; } -static inline void stmmac_mac_enable_rx(unsigned long ioaddr) +static inline void stmmac_mac_enable_rx(void __iomem *ioaddr) { u32 value = readl(ioaddr + MAC_CTRL_REG); value |= MAC_RNABLE_RX; @@ -353,7 +352,7 @@ static inline void stmmac_mac_enable_rx(unsigned long ioaddr) writel(value, ioaddr + MAC_CTRL_REG); } -static inline void stmmac_mac_enable_tx(unsigned long ioaddr) +static inline void stmmac_mac_enable_tx(void __iomem *ioaddr) { u32 value = readl(ioaddr + MAC_CTRL_REG); value |= MAC_ENABLE_TX; @@ -361,14 +360,14 @@ static inline void stmmac_mac_enable_tx(unsigned long ioaddr) writel(value, ioaddr + MAC_CTRL_REG); } -static inline void stmmac_mac_disable_rx(unsigned long ioaddr) +static inline void stmmac_mac_disable_rx(void __iomem *ioaddr) { u32 value = readl(ioaddr + MAC_CTRL_REG); value &= ~MAC_RNABLE_RX; writel(value, ioaddr + MAC_CTRL_REG); } -static inline void stmmac_mac_disable_tx(unsigned long ioaddr) +static inline void stmmac_mac_disable_tx(void __iomem *ioaddr) { u32 value = readl(ioaddr + MAC_CTRL_REG); value &= ~MAC_ENABLE_TX; @@ -577,17 +576,17 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) { if (!priv->is_gmac) { /* MAC 10/100 */ - priv->hw->dma->dma_mode(priv->dev->base_addr, tc, 0); + priv->hw->dma->dma_mode(priv->ioaddr, tc, 0); priv->tx_coe = NO_HW_CSUM; } else { if ((priv->dev->mtu <= ETH_DATA_LEN) && (tx_coe)) { - priv->hw->dma->dma_mode(priv->dev->base_addr, + priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE); tc = SF_DMA_MODE; priv->tx_coe = HW_CSUM; } else { /* Checksum computation is performed in software. */ - priv->hw->dma->dma_mode(priv->dev->base_addr, tc, + priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE); priv->tx_coe = NO_HW_CSUM; } @@ -603,7 +602,6 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) static void stmmac_tx(struct stmmac_priv *priv) { unsigned int txsize = priv->dma_tx_size; - unsigned long ioaddr = priv->dev->base_addr; while (priv->dirty_tx != priv->cur_tx) { int last; @@ -621,7 +619,7 @@ static void stmmac_tx(struct stmmac_priv *priv) int tx_error = priv->hw->desc->tx_status(&priv->dev->stats, &priv->xstats, p, - ioaddr); + priv->ioaddr); if (likely(tx_error == 0)) { priv->dev->stats.tx_packets++; priv->xstats.tx_pkt_n++; @@ -677,7 +675,7 @@ static inline void stmmac_enable_irq(struct stmmac_priv *priv) priv->tm->timer_start(tmrate); else #endif - priv->hw->dma->enable_dma_irq(priv->dev->base_addr); + priv->hw->dma->enable_dma_irq(priv->ioaddr); } static inline void stmmac_disable_irq(struct stmmac_priv *priv) @@ -687,7 +685,7 @@ static inline void stmmac_disable_irq(struct stmmac_priv *priv) priv->tm->timer_stop(); else #endif - priv->hw->dma->disable_dma_irq(priv->dev->base_addr); + priv->hw->dma->disable_dma_irq(priv->ioaddr); } static int stmmac_has_work(struct stmmac_priv *priv) @@ -742,14 +740,15 @@ static void stmmac_no_timer_stopped(void) */ static void stmmac_tx_err(struct stmmac_priv *priv) { + netif_stop_queue(priv->dev); - priv->hw->dma->stop_tx(priv->dev->base_addr); + priv->hw->dma->stop_tx(priv->ioaddr); dma_free_tx_skbufs(priv); priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size); priv->dirty_tx = 0; priv->cur_tx = 0; - priv->hw->dma->start_tx(priv->dev->base_addr); + priv->hw->dma->start_tx(priv->ioaddr); priv->dev->stats.tx_errors++; netif_wake_queue(priv->dev); @@ -758,11 +757,9 @@ static void stmmac_tx_err(struct stmmac_priv *priv) static void stmmac_dma_interrupt(struct stmmac_priv *priv) { - unsigned long ioaddr = priv->dev->base_addr; int status; - status = priv->hw->dma->dma_interrupt(priv->dev->base_addr, - &priv->xstats); + status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); if (likely(status == handle_tx_rx)) _stmmac_schedule(priv); @@ -770,7 +767,7 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv) /* Try to bump up the dma threshold on this failure */ if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) { tc += 64; - priv->hw->dma->dma_mode(ioaddr, tc, SF_DMA_MODE); + priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE); priv->xstats.threshold = tc; } stmmac_tx_err(priv); @@ -790,7 +787,6 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv) static int stmmac_open(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int ret; /* Check that the MAC address is valid. If its not, refuse @@ -846,7 +842,8 @@ static int stmmac_open(struct net_device *dev) init_dma_desc_rings(dev); /* DMA initialization and SW reset */ - if (unlikely(priv->hw->dma->init(ioaddr, priv->pbl, priv->dma_tx_phy, + if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->pbl, + priv->dma_tx_phy, priv->dma_rx_phy) < 0)) { pr_err("%s: DMA initialization failed\n", __func__); @@ -854,22 +851,22 @@ static int stmmac_open(struct net_device *dev) } /* Copy the MAC addr into the HW */ - priv->hw->mac->set_umac_addr(ioaddr, dev->dev_addr, 0); + priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0); /* If required, perform hw setup of the bus. */ if (priv->bus_setup) - priv->bus_setup(ioaddr); + priv->bus_setup(priv->ioaddr); /* Initialize the MAC Core */ - priv->hw->mac->core_init(ioaddr); + priv->hw->mac->core_init(priv->ioaddr); priv->shutdown = 0; /* Initialise the MMC (if present) to disable all interrupts. */ - writel(0xffffffff, ioaddr + MMC_HIGH_INTR_MASK); - writel(0xffffffff, ioaddr + MMC_LOW_INTR_MASK); + writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK); + writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK); /* Enable the MAC Rx/Tx */ - stmmac_mac_enable_rx(ioaddr); - stmmac_mac_enable_tx(ioaddr); + stmmac_mac_enable_rx(priv->ioaddr); + stmmac_mac_enable_tx(priv->ioaddr); /* Set the HW DMA mode and the COE */ stmmac_dma_operation_mode(priv); @@ -880,16 +877,16 @@ static int stmmac_open(struct net_device *dev) /* Start the ball rolling... */ DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name); - priv->hw->dma->start_tx(ioaddr); - priv->hw->dma->start_rx(ioaddr); + priv->hw->dma->start_tx(priv->ioaddr); + priv->hw->dma->start_rx(priv->ioaddr); #ifdef CONFIG_STMMAC_TIMER priv->tm->timer_start(tmrate); #endif /* Dump DMA/MAC registers */ if (netif_msg_hw(priv)) { - priv->hw->mac->dump_regs(ioaddr); - priv->hw->dma->dump_regs(ioaddr); + priv->hw->mac->dump_regs(priv->ioaddr); + priv->hw->dma->dump_regs(priv->ioaddr); } if (priv->phydev) @@ -933,15 +930,15 @@ static int stmmac_release(struct net_device *dev) free_irq(dev->irq, dev); /* Stop TX/RX DMA and clear the descriptors */ - priv->hw->dma->stop_tx(dev->base_addr); - priv->hw->dma->stop_rx(dev->base_addr); + priv->hw->dma->stop_tx(priv->ioaddr); + priv->hw->dma->stop_rx(priv->ioaddr); /* Release and free the Rx/Tx resources */ free_dma_desc_resources(priv); /* Disable the MAC core */ - stmmac_mac_disable_tx(dev->base_addr); - stmmac_mac_disable_rx(dev->base_addr); + stmmac_mac_disable_tx(priv->ioaddr); + stmmac_mac_disable_rx(priv->ioaddr); netif_carrier_off(dev); @@ -1143,7 +1140,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_bytes += skb->len; - priv->hw->dma->enable_dma_transmission(dev->base_addr); + priv->hw->dma->enable_dma_transmission(priv->ioaddr); return NETDEV_TX_OK; } @@ -1408,11 +1405,9 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) return IRQ_NONE; } - if (priv->is_gmac) { - unsigned long ioaddr = dev->base_addr; + if (priv->is_gmac) /* To handle GMAC own interrupts */ - priv->hw->mac->host_irq_status(ioaddr); - } + priv->hw->mac->host_irq_status((void __iomem *) dev->base_addr); stmmac_dma_interrupt(priv); @@ -1525,7 +1520,8 @@ static int stmmac_probe(struct net_device *dev) netif_napi_add(dev, &priv->napi, stmmac_poll, 64); /* Get the MAC address */ - priv->hw->mac->get_umac_addr(dev->base_addr, dev->dev_addr, 0); + priv->hw->mac->get_umac_addr((void __iomem *) dev->base_addr, + dev->dev_addr, 0); if (!is_valid_ether_addr(dev->dev_addr)) pr_warning("\tno valid MAC address;" @@ -1555,14 +1551,13 @@ static int stmmac_probe(struct net_device *dev) static int stmmac_mac_device_setup(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; struct mac_device_info *device; if (priv->is_gmac) - device = dwmac1000_setup(ioaddr); + device = dwmac1000_setup(priv->ioaddr); else - device = dwmac100_setup(ioaddr); + device = dwmac100_setup(priv->ioaddr); if (!device) return -ENOMEM; @@ -1656,7 +1651,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; - unsigned int *addr = NULL; + void __iomem *addr = NULL; struct net_device *ndev = NULL; struct stmmac_priv *priv; struct plat_stmmacenet_data *plat_dat; @@ -1711,6 +1706,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) priv->pbl = plat_dat->pbl; /* TLI */ priv->is_gmac = plat_dat->has_gmac; /* GMAC is on board */ priv->enh_desc = plat_dat->enh_desc; + priv->ioaddr = addr; platform_set_drvdata(pdev, ndev); @@ -1782,11 +1778,11 @@ static int stmmac_dvr_remove(struct platform_device *pdev) pr_info("%s:\n\tremoving driver", __func__); - priv->hw->dma->stop_rx(ndev->base_addr); - priv->hw->dma->stop_tx(ndev->base_addr); + priv->hw->dma->stop_rx(priv->ioaddr); + priv->hw->dma->stop_tx(priv->ioaddr); - stmmac_mac_disable_rx(ndev->base_addr); - stmmac_mac_disable_tx(ndev->base_addr); + stmmac_mac_disable_rx(priv->ioaddr); + stmmac_mac_disable_tx(priv->ioaddr); netif_carrier_off(ndev); @@ -1795,7 +1791,7 @@ static int stmmac_dvr_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); unregister_netdev(ndev); - iounmap((void *)ndev->base_addr); + iounmap((void *)priv->ioaddr); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, resource_size(res)); @@ -1830,22 +1826,21 @@ static int stmmac_suspend(struct platform_device *pdev, pm_message_t state) napi_disable(&priv->napi); /* Stop TX/RX DMA */ - priv->hw->dma->stop_tx(dev->base_addr); - priv->hw->dma->stop_rx(dev->base_addr); + priv->hw->dma->stop_tx(priv->ioaddr); + priv->hw->dma->stop_rx(priv->ioaddr); /* Clear the Rx/Tx descriptors */ priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size, dis_ic); priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size); - stmmac_mac_disable_tx(dev->base_addr); + stmmac_mac_disable_tx(priv->ioaddr); if (device_may_wakeup(&(pdev->dev))) { /* Enable Power down mode by programming the PMT regs */ if (priv->wolenabled == PMT_SUPPORTED) - priv->hw->mac->pmt(dev->base_addr, - priv->wolopts); + priv->hw->mac->pmt(priv->ioaddr, priv->wolopts); } else { - stmmac_mac_disable_rx(dev->base_addr); + stmmac_mac_disable_rx(priv->ioaddr); } } else { priv->shutdown = 1; @@ -1863,7 +1858,6 @@ static int stmmac_resume(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; if (!netif_running(dev)) return 0; @@ -1884,15 +1878,15 @@ static int stmmac_resume(struct platform_device *pdev) * from another devices (e.g. serial console). */ if (device_may_wakeup(&(pdev->dev))) if (priv->wolenabled == PMT_SUPPORTED) - priv->hw->mac->pmt(dev->base_addr, 0); + priv->hw->mac->pmt(priv->ioaddr, 0); netif_device_attach(dev); /* Enable the MAC and DMA */ - stmmac_mac_enable_rx(ioaddr); - stmmac_mac_enable_tx(ioaddr); - priv->hw->dma->start_tx(ioaddr); - priv->hw->dma->start_rx(ioaddr); + stmmac_mac_enable_rx(priv->ioaddr); + stmmac_mac_enable_tx(priv->ioaddr); + priv->hw->dma->start_tx(priv->ioaddr); + priv->hw->dma->start_rx(priv->ioaddr); #ifdef CONFIG_STMMAC_TIMER priv->tm->timer_start(tmrate); diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/stmmac/stmmac_mdio.c index 40b2c7929719..03dea1401571 100644 --- a/drivers/net/stmmac/stmmac_mdio.c +++ b/drivers/net/stmmac/stmmac_mdio.c @@ -47,7 +47,6 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) { struct net_device *ndev = bus->priv; struct stmmac_priv *priv = netdev_priv(ndev); - unsigned long ioaddr = ndev->base_addr; unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_data = priv->hw->mii.data; @@ -56,12 +55,12 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) ((phyreg << 6) & (0x000007C0))); regValue |= MII_BUSY; /* in case of GMAC */ - do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1); - writel(regValue, ioaddr + mii_address); - do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1); + do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); + writel(regValue, priv->ioaddr + mii_address); + do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); /* Read the data from the MII data register */ - data = (int)readl(ioaddr + mii_data); + data = (int)readl(priv->ioaddr + mii_data); return data; } @@ -79,7 +78,6 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, { struct net_device *ndev = bus->priv; struct stmmac_priv *priv = netdev_priv(ndev); - unsigned long ioaddr = ndev->base_addr; unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_data = priv->hw->mii.data; @@ -90,14 +88,14 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, value |= MII_BUSY; /* Wait until any existing MII operation is complete */ - do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1); + do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); /* Set the MII address register to write */ - writel(phydata, ioaddr + mii_data); - writel(value, ioaddr + mii_address); + writel(phydata, priv->ioaddr + mii_data); + writel(value, priv->ioaddr + mii_address); /* Wait until any existing MII operation is complete */ - do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1); + do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); return 0; } @@ -111,7 +109,6 @@ static int stmmac_mdio_reset(struct mii_bus *bus) { struct net_device *ndev = bus->priv; struct stmmac_priv *priv = netdev_priv(ndev); - unsigned long ioaddr = ndev->base_addr; unsigned int mii_address = priv->hw->mii.addr; if (priv->phy_reset) { @@ -123,7 +120,7 @@ static int stmmac_mdio_reset(struct mii_bus *bus) * It doesn't complete its reset until at least one clock cycle * on MDC, so perform a dummy mdio read. */ - writel(0, ioaddr + mii_address); + writel(0, priv->ioaddr + mii_address); return 0; } diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 632ff7c03280..a4adf0de6ed6 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -35,7 +35,7 @@ struct plat_stmmacenet_data { int has_gmac; int enh_desc; void (*fix_mac_speed)(void *priv, unsigned int speed); - void (*bus_setup)(unsigned long ioaddr); + void (*bus_setup)(void __iomem *ioaddr); #ifdef CONFIG_STM_DRIVERS struct stm_pad_config *pad_config; #endif -- cgit v1.2.3-59-g8ed1b From 884c06f4777c598ea7bf4fbc7557ff2fca066f63 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 24 Aug 2010 02:01:05 +0000 Subject: plip: remove superflous return This return isn't reachable and it obscures the goto on the line before. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/plip.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/plip.c b/drivers/net/plip.c index ec0349e84a8a..7e82a82422cf 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -1279,7 +1279,6 @@ static void plip_attach (struct parport *port) if (!nl->pardev) { printk(KERN_ERR "%s: parport_register failed\n", name); goto err_free_dev; - return; } plip_init_netdev(dev); -- cgit v1.2.3-59-g8ed1b From 21ff2929edc89397cc4c621d3c3f842994640acd Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 24 Aug 2010 04:18:13 +0000 Subject: typhoon: fix a race in typhoon_do_get_stats Its important to store 'final' values in counters, not using them as temporary variables, or this might break some SNMP applications. Signed-off-by: Eric Dumazet Acked-by: David Dillow Signed-off-by: David S. Miller --- drivers/net/typhoon.c | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 2e50077ff450..3f4681f78262 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -962,36 +962,34 @@ typhoon_do_get_stats(struct typhoon *tp) * The extra status reported would be a good candidate for * ethtool_ops->get_{strings,stats}() */ - stats->tx_packets = le32_to_cpu(s->txPackets); - stats->tx_bytes = le64_to_cpu(s->txBytes); - stats->tx_errors = le32_to_cpu(s->txCarrierLost); - stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost); - stats->collisions = le32_to_cpu(s->txMultipleCollisions); - stats->rx_packets = le32_to_cpu(s->rxPacketsGood); - stats->rx_bytes = le64_to_cpu(s->rxBytesGood); - stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns); + stats->tx_packets = le32_to_cpu(s->txPackets) + + saved->tx_packets; + stats->tx_bytes = le64_to_cpu(s->txBytes) + + saved->tx_bytes; + stats->tx_errors = le32_to_cpu(s->txCarrierLost) + + saved->tx_errors; + stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost) + + saved->tx_carrier_errors; + stats->collisions = le32_to_cpu(s->txMultipleCollisions) + + saved->collisions; + stats->rx_packets = le32_to_cpu(s->rxPacketsGood) + + saved->rx_packets; + stats->rx_bytes = le64_to_cpu(s->rxBytesGood) + + saved->rx_bytes; + stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns) + + saved->rx_fifo_errors; stats->rx_errors = le32_to_cpu(s->rxFifoOverruns) + - le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors); - stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors); - stats->rx_length_errors = le32_to_cpu(s->rxOversized); + le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors) + + saved->rx_errors; + stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors) + + saved->rx_crc_errors; + stats->rx_length_errors = le32_to_cpu(s->rxOversized) + + saved->rx_length_errors; tp->speed = (s->linkStatus & TYPHOON_LINK_100MBPS) ? SPEED_100 : SPEED_10; tp->duplex = (s->linkStatus & TYPHOON_LINK_FULL_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF; - /* add in the saved statistics - */ - stats->tx_packets += saved->tx_packets; - stats->tx_bytes += saved->tx_bytes; - stats->tx_errors += saved->tx_errors; - stats->collisions += saved->collisions; - stats->rx_packets += saved->rx_packets; - stats->rx_bytes += saved->rx_bytes; - stats->rx_fifo_errors += saved->rx_fifo_errors; - stats->rx_errors += saved->rx_errors; - stats->rx_crc_errors += saved->rx_crc_errors; - stats->rx_length_errors += saved->rx_length_errors; - return 0; } -- cgit v1.2.3-59-g8ed1b From 8d34e7d6f38fce1c7e595404295494cd1eaba3eb Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 24 Aug 2010 04:38:33 +0000 Subject: drivers/net/irda: Eliminate memory leak dev_alloc_skb allocates some memory, so that memory should be freed before leaving the function in an error case. Corrected some typos in a nearby comment as well. A simplified version of the semantic match that finds this problem is: (http://coccinelle.lip6.fr/) // @r exists@ local idexpression x; expression E; identifier f1; iterator I; @@ x = dev_alloc_skb(...); <... when != x when != true (x == NULL || ...) when != if (...) { <+...x...+> } when != I (...) { <+...x...+> } ( x == NULL | x == E | x->f1 ) ...> * return ...; // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/irda/via-ircc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c index b0a6cd815be1..67c0ad42d818 100644 --- a/drivers/net/irda/via-ircc.c +++ b/drivers/net/irda/via-ircc.c @@ -1182,12 +1182,13 @@ F01_E */ skb = dev_alloc_skb(len + 1 - 4); /* - * if frame size,data ptr,or skb ptr are wrong ,the get next + * if frame size, data ptr, or skb ptr are wrong, then get next * entry. */ if ((skb == NULL) || (skb->data == NULL) || (self->rx_buff.data == NULL) || (len < 6)) { self->netdev->stats.rx_dropped++; + kfree_skb(skb); return TRUE; } skb_reserve(skb, 1); -- cgit v1.2.3-59-g8ed1b From b2aff96327545aa5ceb25e3116be69c8b06de703 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 24 Aug 2010 04:39:49 +0000 Subject: net/netfilter/ipvs: Eliminate memory leak __ip_vs_service_get and __ip_vs_svc_fwm_get increment a reference count, so that reference count should be decremented before leaving the function in an error case. A simplified version of the semantic match that finds this problem is: (http://coccinelle.lip6.fr/) // @r exists@ local idexpression x; expression E; identifier f1; iterator I; @@ x = __ip_vs_service_get(...); <... when != x when != true (x == NULL || ...) when != if (...) { <+...x...+> } when != I (...) { <+...x...+> } ( x == NULL | x == E | x->f1 ) ...> * return ...; // Signed-off-by: Julia Lawall Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/netfilter/ipvs/ip_vs_ctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 0f0c079c422a..53a88af22503 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2155,7 +2155,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) if (cmd != IP_VS_SO_SET_ADD && (svc == NULL || svc->protocol != usvc.protocol)) { ret = -ESRCH; - goto out_unlock; + goto out_drop_service; } switch (cmd) { @@ -2189,6 +2189,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) ret = -EINVAL; } +out_drop_service: if (svc) ip_vs_service_put(svc); -- cgit v1.2.3-59-g8ed1b From 944c794d6437e5301c8769cb242c2b919a5acf59 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 24 Aug 2010 13:08:10 +0000 Subject: bridge: fix locking comment The carrier check is not called from work queue in current code. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_if.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index c03d2c3ff03e..170794546522 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -61,11 +61,7 @@ static int port_cost(struct net_device *dev) } -/* - * Check for port carrier transistions. - * Called from work queue to allow for calling functions that - * might sleep (such as speed check), and to debounce. - */ +/* Check for port carrier transistions. */ void br_port_carrier_check(struct net_bridge_port *p) { struct net_device *dev = p->dev; -- cgit v1.2.3-59-g8ed1b From c5dadddb8c9d310bc263f671f19fe3ba90b329fe Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Tue, 24 Aug 2010 12:50:40 +0000 Subject: qlge: Fix a deadlock when the interface is going down Currently qlge can deadlock when the interface is going down, and the mpi_port_cfg_work() is executing on another processor. It happens because unregister_netdev() holds the rtnl lock, and the mpi_port_cfg_work() also request this lock. Since unregiter_netdev() may wait mpi_port_cfg_work(), who also request the holding lock, it can cause an deadlock, displaying the following error: "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. rmmod D 00000080c6c1d190 0 3993 2081 0x00008080 Call Trace: [c000000975f56ee0] [c0000000000152a0] .__switch_to+0x100/0x1d0 [c000000975f56f70] [c0000000005781b4] .schedule+0x3a4/0x8c0 [c000000975f570c0] [c000000000578e8c] .schedule_timeout+0x24c/0x350 [c000000975f571e0] [c000000000578a88] .wait_for_common+0x198/0x210 [c000000975f572c0] [c0000000000abbb4] .__cancel_work_timer+0x2c4/0x2e0 [c000000975f57400] [d0000000078e7a20] .ql_adapter_down+0x80/0x260 [qlge] [c000000975f574b0] [d0000000078e7d80] .qlge_close+0x70/0x130 [qlge] [c000000975f57540] [c000000000497ef8] .__dev_close+0x98/0xf0 [c000000975f575d0] [c000000000497f74] .dev_close+0x24/0x60 [c000000975f57650] [c000000000498080] .rollback_registered_many+0xd0/0x2b0 [c000000975f576f0] [c000000000498338] .rollback_registered+0x38/0x50 [c000000975f57780] [c0000000004983d8] .unregister_netdevice_queue+0x88/0xe0 [c000000975f57810] [c000000000498574] .unregister_netdev+0x24/0x40 [c000000975f57890] [d0000000078f6f38] .qlge_remove+0x3c/0x78 [qlge] [c000000975f57920] [c0000000002d9298] .pci_device_remove+0x48/0x90 [c000000975f579a0] [c000000000372850] .__device_release_driver+0xa0/0x130 [c000000975f57a30] [c000000000372a08] .driver_detach+0x128/0x150 [c000000975f57ad0] [c000000000371134] .bus_remove_driver+0xc4/0x1a0 [c000000975f57b70] [c00000000037357c] .driver_unregister+0x8c/0xd0 [c000000975f57c00] [c0000000002d968c] .pci_unregister_driver+0x5c/0x110 [c000000975f57ca0] [d0000000078f6ee4] .qlge_exit+0x1c/0x34 [qlge] Signed-off-by: Breno Leitao Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index c9f9754f0784..5a245211fc53 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3889,11 +3889,8 @@ int ql_wol(struct ql_adapter *qdev) return status; } -static int ql_adapter_down(struct ql_adapter *qdev) +static void ql_cancel_all_work_sync(struct ql_adapter *qdev) { - int i, status = 0; - - ql_link_off(qdev); /* Don't kill the reset worker thread if we * are in the process of recovery. @@ -3905,6 +3902,15 @@ static int ql_adapter_down(struct ql_adapter *qdev) cancel_delayed_work_sync(&qdev->mpi_idc_work); cancel_delayed_work_sync(&qdev->mpi_core_to_log); cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); +} + +static int ql_adapter_down(struct ql_adapter *qdev) +{ + int i, status = 0; + + ql_link_off(qdev); + + ql_cancel_all_work_sync(qdev); for (i = 0; i < qdev->rss_ring_count; i++) napi_disable(&qdev->rx_ring[i].napi); @@ -4727,6 +4733,7 @@ static void __devexit qlge_remove(struct pci_dev *pdev) struct net_device *ndev = pci_get_drvdata(pdev); struct ql_adapter *qdev = netdev_priv(ndev); del_timer_sync(&qdev->timer); + ql_cancel_all_work_sync(qdev); unregister_netdev(ndev); ql_release_all(pdev); pci_disable_device(pdev); @@ -4746,13 +4753,7 @@ static void ql_eeh_close(struct net_device *ndev) /* Disabling the timer */ del_timer_sync(&qdev->timer); - if (test_bit(QL_ADAPTER_UP, &qdev->flags)) - cancel_delayed_work_sync(&qdev->asic_reset_work); - cancel_delayed_work_sync(&qdev->mpi_reset_work); - cancel_delayed_work_sync(&qdev->mpi_work); - cancel_delayed_work_sync(&qdev->mpi_idc_work); - cancel_delayed_work_sync(&qdev->mpi_core_to_log); - cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); + ql_cancel_all_work_sync(qdev); for (i = 0; i < qdev->rss_ring_count; i++) netif_napi_del(&qdev->rx_ring[i].napi); -- cgit v1.2.3-59-g8ed1b From aa7c6e5fa08bb5014b6432a690d28748f11e93fc Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Tue, 24 Aug 2010 13:12:56 +0000 Subject: bridge: avoid ethtool on non running interface If bridge port is offline, don't call ethtool to query speed. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_if.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 170794546522..89ad25a76202 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -67,20 +67,21 @@ void br_port_carrier_check(struct net_bridge_port *p) struct net_device *dev = p->dev; struct net_bridge *br = p->br; - if (netif_carrier_ok(dev)) + if (netif_running(dev) && netif_carrier_ok(dev)) p->path_cost = port_cost(dev); - if (netif_running(br->dev)) { - spin_lock_bh(&br->lock); - if (netif_carrier_ok(dev)) { - if (p->state == BR_STATE_DISABLED) - br_stp_enable_port(p); - } else { - if (p->state != BR_STATE_DISABLED) - br_stp_disable_port(p); - } - spin_unlock_bh(&br->lock); + if (!netif_running(br->dev)) + return; + + spin_lock_bh(&br->lock); + if (netif_running(dev) && netif_carrier_ok(dev)) { + if (p->state == BR_STATE_DISABLED) + br_stp_enable_port(p); + } else { + if (p->state != BR_STATE_DISABLED) + br_stp_disable_port(p); } + spin_unlock_bh(&br->lock); } static void release_nbp(struct kobject *kobj) -- cgit v1.2.3-59-g8ed1b From 6d87f5c3ac5856bf1309700e2f15e2e7fcd3c578 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 25 Aug 2010 00:32:33 +0000 Subject: be2net: fix to dynamically generate MAC Address for VFs The BE ASIC/firmware doesnot reserve and assign MAC address for VFs. This results in the VF interfaces being created with MAC Address 0. The code change proposed takes the MAC address of PF to generate a seed. MAC Address for VFs are assigned incrementally starting from the seed. These addresses are programmed in the ASIC by the PF and the VF driver queries for the MAC address during its probe. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 14 ++++++++++++ drivers/net/benet/be_main.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 99197bd54da5..d1fb7928ffc5 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -413,6 +413,20 @@ static inline void be_check_sriov_fn_type(struct be_adapter *adapter) adapter->is_virtfn = (data != 0xAA); } +static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac) +{ + u32 addr; + + addr = jhash(adapter->netdev->dev_addr, ETH_ALEN, 0); + + mac[5] = (u8)(addr & 0xFF); + mac[4] = (u8)((addr >> 8) & 0xFF); + mac[3] = (u8)((addr >> 16) & 0xFF); + mac[2] = 0xC9; + mac[1] = 0x00; + mac[0] = 0x00; +} + extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped); extern void be_link_status_update(struct be_adapter *adapter, bool link_up); diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index b89bae029620..9db10fec8235 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2088,6 +2088,47 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable) return status; } +/* + * Generate a seed MAC address from the PF MAC Address using jhash. + * MAC Address for VFs are assigned incrementally starting from the seed. + * These addresses are programmed in the ASIC by the PF and the VF driver + * queries for the MAC address during its probe. + */ +static inline int be_vf_eth_addr_config(struct be_adapter *adapter) +{ + u32 vf = 0; + int status; + u8 mac[ETH_ALEN]; + + be_vf_eth_addr_generate(adapter, mac); + + for (vf = 0; vf < num_vfs; vf++) { + status = be_cmd_pmac_add(adapter, mac, + adapter->vf_cfg[vf].vf_if_handle, + &adapter->vf_cfg[vf].vf_pmac_id); + if (status) + dev_err(&adapter->pdev->dev, + "Mac address add failed for VF %d\n", vf); + else + memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN); + + mac[5] += 1; + } + return status; +} + +static inline void be_vf_eth_addr_rem(struct be_adapter *adapter) +{ + u32 vf; + + for (vf = 0; vf < num_vfs; vf++) { + if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID) + be_cmd_pmac_del(adapter, + adapter->vf_cfg[vf].vf_if_handle, + adapter->vf_cfg[vf].vf_pmac_id); + } +} + static int be_setup(struct be_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -2147,10 +2188,20 @@ static int be_setup(struct be_adapter *adapter) if (status != 0) goto rx_qs_destroy; + if (be_physfn(adapter)) { + status = be_vf_eth_addr_config(adapter); + if (status) + goto mcc_q_destroy; + } + adapter->link_speed = -1; return 0; +mcc_q_destroy: + if (be_physfn(adapter)) + be_vf_eth_addr_rem(adapter); + be_mcc_queues_destroy(adapter); rx_qs_destroy: be_rx_queues_destroy(adapter); tx_qs_destroy: @@ -2167,6 +2218,9 @@ do_none: static int be_clear(struct be_adapter *adapter) { + if (be_physfn(adapter)) + be_vf_eth_addr_rem(adapter); + be_mcc_queues_destroy(adapter); be_rx_queues_destroy(adapter); be_tx_queues_destroy(adapter); -- cgit v1.2.3-59-g8ed1b From def824c0d4902d27c52f17d267af8bc648d29e16 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 25 Aug 2010 00:32:56 +0000 Subject: be2net: stats for packets received due to internal switching in ASIC. Counters for packets received due to internal switching are already available. This change will start displaying them in ethtool -S Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_ethtool.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index cd16243c7c36..9bedb9ff6e12 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -90,6 +90,9 @@ static const struct be_ethtool_stat et_stats[] = { {PORTSTAT_INFO(rx_non_rss_packets)}, {PORTSTAT_INFO(rx_ipv4_packets)}, {PORTSTAT_INFO(rx_ipv6_packets)}, + {PORTSTAT_INFO(rx_switched_unicast_packets)}, + {PORTSTAT_INFO(rx_switched_multicast_packets)}, + {PORTSTAT_INFO(rx_switched_broadcast_packets)}, {PORTSTAT_INFO(tx_unicastframes)}, {PORTSTAT_INFO(tx_multicastframes)}, {PORTSTAT_INFO(tx_broadcastframes)}, -- cgit v1.2.3-59-g8ed1b From f0c54ace9b74ec52e57d3ea2ef99fb277667abf8 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Wed, 25 Aug 2010 00:23:39 +0000 Subject: s2io: remove lro parameter Remove "lro" parameter of s2io driver. Signed-off-by: WANG Cong Cc: jon.mason@exar.com Acked-by: Jon Mason Signed-off-by: David S. Miller --- drivers/net/s2io.c | 29 +++++++++-------------------- drivers/net/s2io.h | 1 - 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 5f062ddfd5c5..7061fc8e99c7 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -38,8 +38,6 @@ * Tx descriptors that can be associated with each corresponding FIFO. * intr_type: This defines the type of interrupt. The values can be 0(INTA), * 2(MSI_X). Default value is '2(MSI_X)' - * lro: Specifies whether to enable Large Receive Offload (LRO) or not. - * Possible values '1' for enable '0' for disable. Default is '0' * lro_max_pkts: This parameter defines maximum number of packets can be * aggregated as a single large packet * napi: This parameter used to enable/disable NAPI (polling Rx) @@ -496,8 +494,6 @@ S2IO_PARM_INT(rxsync_frequency, 3); /* Interrupt type. Values can be 0(INTA), 2(MSI_X) */ S2IO_PARM_INT(intr_type, 2); /* Large receive offload feature */ -static unsigned int lro_enable = 1; -module_param_named(lro, lro_enable, uint, 0); /* Max pkts to be aggregated by LRO at one time. If not specified, * aggregation happens until we hit max IP pkt size(64K) @@ -6733,13 +6729,10 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data) return -EINVAL; if (data & ETH_FLAG_LRO) { - if (lro_enable) { - if (!(dev->features & NETIF_F_LRO)) { - dev->features |= NETIF_F_LRO; - changed = 1; - } - } else - rc = -EINVAL; + if (!(dev->features & NETIF_F_LRO)) { + dev->features |= NETIF_F_LRO; + changed = 1; + } } else if (dev->features & NETIF_F_LRO) { dev->features &= ~NETIF_F_LRO; changed = 1; @@ -6748,7 +6741,6 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data) if (changed && netif_running(dev)) { s2io_stop_all_tx_queue(sp); s2io_card_down(sp); - sp->lro = !!(dev->features & NETIF_F_LRO); rc = s2io_card_up(sp); if (rc) s2io_reset(sp); @@ -7305,7 +7297,7 @@ static int s2io_card_up(struct s2io_nic *sp) struct ring_info *ring = &mac_control->rings[i]; ring->mtu = dev->mtu; - ring->lro = sp->lro; + ring->lro = !!(dev->features & NETIF_F_LRO); ret = fill_rx_buffers(sp, ring, 1); if (ret) { DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n", @@ -7339,7 +7331,7 @@ static int s2io_card_up(struct s2io_nic *sp) /* Setting its receive mode */ s2io_set_multicast(dev); - if (sp->lro) { + if (dev->features & NETIF_F_LRO) { /* Initialize max aggregatable pkts per session based on MTU */ sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu; /* Check if we can use (if specified) user provided value */ @@ -7909,7 +7901,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) else sp->device_type = XFRAME_I_DEVICE; - sp->lro = lro_enable; /* Initialize some PCI/PCI-X fields of the NIC. */ s2io_init_pci(sp); @@ -8045,8 +8036,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->netdev_ops = &s2io_netdev_ops; SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - if (lro_enable) - dev->features |= NETIF_F_LRO; + dev->features |= NETIF_F_LRO; dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; if (sp->high_dma_flag == true) dev->features |= NETIF_F_HIGHDMA; @@ -8281,9 +8271,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->name); } - if (sp->lro) - DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n", - dev->name); + DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n", + dev->name); if (ufo) DBG_PRINT(ERR_DBG, "%s: UDP Fragmentation Offload(UFO) enabled\n", diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 924f618f2397..00b8614efe48 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -963,7 +963,6 @@ struct s2io_nic { unsigned long clubbed_frms_cnt; unsigned long sending_both; - u8 lro; u16 lro_max_aggr_per_sess; volatile unsigned long state; u64 general_int_mask; -- cgit v1.2.3-59-g8ed1b From ced1de4c9eeded664e5f1b21cfcb0fb70cc0cde3 Mon Sep 17 00:00:00 2001 From: Denis Kirjanov Date: Tue, 24 Aug 2010 23:57:55 +0000 Subject: r6040: Free irq line on error path Free irq line on error path. Signed-off-by: Denis Kirjanov Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/r6040.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 0a00850da79d..63db065508f4 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -756,7 +756,7 @@ static int r6040_open(struct net_device *dev) ret = request_irq(dev->irq, r6040_interrupt, IRQF_SHARED, dev->name, dev); if (ret) - return ret; + goto out; /* Set MAC address */ r6040_mac_address(dev); @@ -764,30 +764,37 @@ static int r6040_open(struct net_device *dev) /* Allocate Descriptor memory */ lp->rx_ring = pci_alloc_consistent(lp->pdev, RX_DESC_SIZE, &lp->rx_ring_dma); - if (!lp->rx_ring) - return -ENOMEM; + if (!lp->rx_ring) { + ret = -ENOMEM; + goto err_free_irq; + } lp->tx_ring = pci_alloc_consistent(lp->pdev, TX_DESC_SIZE, &lp->tx_ring_dma); if (!lp->tx_ring) { - pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring, - lp->rx_ring_dma); - return -ENOMEM; + ret = -ENOMEM; + goto err_free_rx_ring; } ret = r6040_up(dev); - if (ret) { - pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring, - lp->tx_ring_dma); - pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring, - lp->rx_ring_dma); - return ret; - } + if (ret) + goto err_free_tx_ring; napi_enable(&lp->napi); netif_start_queue(dev); return 0; + +err_free_tx_ring: + pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring, + lp->tx_ring_dma); +err_free_rx_ring: + pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring, + lp->rx_ring_dma); +err_free_irq: + free_irq(dev->irq, dev); +out: + return ret; } static netdev_tx_t r6040_start_xmit(struct sk_buff *skb, -- cgit v1.2.3-59-g8ed1b From 8a891429d1879ae4f37f547ef5c2d68e19277e4a Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Wed, 25 Aug 2010 23:00:27 -0700 Subject: bna: Fixed build break for allyesconfig This is the patch to fix the build break caused by multiple definitions of symbols between Brocade's FC/FCOE driver(BFA) and 10G Networking Driver(BNA). Changes are: 1. locally used functions are made static 2. unused functions are removed 3. using unique namespaces for the function names that must be globally visible Signed-off-by: Debashis Dutt Signed-off-by: Rasesh Mody Signed-off-by: David S. Miller --- drivers/net/bna/bfa_cee.c | 136 ++-------------------- drivers/net/bna/bfa_cee.h | 14 +-- drivers/net/bna/bfa_ioc.c | 249 ++++++++++++----------------------------- drivers/net/bna/bfa_ioc.h | 96 +++++----------- drivers/net/bna/bfa_ioc_ct.c | 49 ++++---- drivers/net/bna/bna_ctrl.c | 38 +++---- drivers/net/bna/bnad.c | 9 +- drivers/net/bna/bnad_ethtool.c | 2 +- 8 files changed, 162 insertions(+), 431 deletions(-) diff --git a/drivers/net/bna/bfa_cee.c b/drivers/net/bna/bfa_cee.c index 1545fc9720f8..f7b789a3b217 100644 --- a/drivers/net/bna/bfa_cee.c +++ b/drivers/net/bna/bfa_cee.c @@ -152,7 +152,7 @@ bfa_cee_reset_stats_isr(struct bfa_cee *cee, enum bfa_status status) cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status); } /** - * bfa_cee_meminfo() + * bfa_nw_cee_meminfo() * * @brief Returns the size of the DMA memory needed by CEE module * @@ -161,13 +161,13 @@ bfa_cee_reset_stats_isr(struct bfa_cee *cee, enum bfa_status status) * @return Size of DMA region */ u32 -bfa_cee_meminfo(void) +bfa_nw_cee_meminfo(void) { return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo(); } /** - * bfa_cee_mem_claim() + * bfa_nw_cee_mem_claim() * * @brief Initialized CEE DMA Memory * @@ -178,7 +178,7 @@ bfa_cee_meminfo(void) * @return void */ void -bfa_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa) +bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa) { cee->attr_dma.kva = dma_kva; cee->attr_dma.pa = dma_pa; @@ -189,108 +189,6 @@ bfa_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa) (dma_kva + bfa_cee_attr_meminfo()); } -/** - * bfa_cee_get_attr() - * - * @brief - * Send the request to the f/w to fetch CEE attributes. - * - * @param[in] Pointer to the CEE module data structure. - * - * @return Status - */ - -enum bfa_status -bfa_cee_get_attr(struct bfa_cee *cee, struct bfa_cee_attr *attr, - bfa_cee_get_attr_cbfn_t cbfn, void *cbarg) -{ - struct bfi_cee_get_req *cmd; - - BUG_ON(!((cee != NULL) && (cee->ioc != NULL))); - if (!bfa_ioc_is_operational(cee->ioc)) - return BFA_STATUS_IOC_FAILURE; - if (cee->get_attr_pending == true) - return BFA_STATUS_DEVBUSY; - cee->get_attr_pending = true; - cmd = (struct bfi_cee_get_req *) cee->get_cfg_mb.msg; - cee->attr = attr; - cee->cbfn.get_attr_cbfn = cbfn; - cee->cbfn.get_attr_cbarg = cbarg; - bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ, - bfa_ioc_portid(cee->ioc)); - bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa); - bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb); - - return BFA_STATUS_OK; -} - -/** - * bfa_cee_get_stats() - * - * @brief - * Send the request to the f/w to fetch CEE statistics. - * - * @param[in] Pointer to the CEE module data structure. - * - * @return Status - */ - -enum bfa_status -bfa_cee_get_stats(struct bfa_cee *cee, struct bfa_cee_stats *stats, - bfa_cee_get_stats_cbfn_t cbfn, void *cbarg) -{ - struct bfi_cee_get_req *cmd; - - BUG_ON(!((cee != NULL) && (cee->ioc != NULL))); - - if (!bfa_ioc_is_operational(cee->ioc)) - return BFA_STATUS_IOC_FAILURE; - if (cee->get_stats_pending == true) - return BFA_STATUS_DEVBUSY; - cee->get_stats_pending = true; - cmd = (struct bfi_cee_get_req *) cee->get_stats_mb.msg; - cee->stats = stats; - cee->cbfn.get_stats_cbfn = cbfn; - cee->cbfn.get_stats_cbarg = cbarg; - bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ, - bfa_ioc_portid(cee->ioc)); - bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa); - bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb); - - return BFA_STATUS_OK; -} - -/** - * bfa_cee_reset_stats() - * - * @brief Clears CEE Stats in the f/w. - * - * @param[in] Pointer to the CEE module data structure. - * - * @return Status - */ - -enum bfa_status -bfa_cee_reset_stats(struct bfa_cee *cee, bfa_cee_reset_stats_cbfn_t cbfn, - void *cbarg) -{ - struct bfi_cee_reset_stats *cmd; - - BUG_ON(!((cee != NULL) && (cee->ioc != NULL))); - if (!bfa_ioc_is_operational(cee->ioc)) - return BFA_STATUS_IOC_FAILURE; - if (cee->reset_stats_pending == true) - return BFA_STATUS_DEVBUSY; - cee->reset_stats_pending = true; - cmd = (struct bfi_cee_reset_stats *) cee->reset_stats_mb.msg; - cee->cbfn.reset_stats_cbfn = cbfn; - cee->cbfn.reset_stats_cbarg = cbarg; - bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS, - bfa_ioc_portid(cee->ioc)); - bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb); - return BFA_STATUS_OK; -} - /** * bfa_cee_isrs() * @@ -301,7 +199,7 @@ bfa_cee_reset_stats(struct bfa_cee *cee, bfa_cee_reset_stats_cbfn_t cbfn, * @return void */ -void +static void bfa_cee_isr(void *cbarg, struct bfi_mbmsg *m) { union bfi_cee_i2h_msg_u *msg; @@ -334,7 +232,7 @@ bfa_cee_isr(void *cbarg, struct bfi_mbmsg *m) * @return void */ -void +static void bfa_cee_hbfail(void *arg) { struct bfa_cee *cee; @@ -367,7 +265,7 @@ bfa_cee_hbfail(void *arg) } /** - * bfa_cee_attach() + * bfa_nw_cee_attach() * * @brief CEE module-attach API * @@ -380,28 +278,14 @@ bfa_cee_hbfail(void *arg) * @return void */ void -bfa_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, +bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, void *dev) { BUG_ON(!(cee != NULL)); cee->dev = dev; cee->ioc = ioc; - bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee); + bfa_nw_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee); bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee); - bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail); -} - -/** - * bfa_cee_detach() - * - * @brief CEE module-detach API - * - * @param[in] cee - Pointer to the CEE module data structure - * - * @return void - */ -void -bfa_cee_detach(struct bfa_cee *cee) -{ + bfa_nw_ioc_hbfail_register(cee->ioc, &cee->hbfail); } diff --git a/drivers/net/bna/bfa_cee.h b/drivers/net/bna/bfa_cee.h index 1208cadeceed..20543d15b64f 100644 --- a/drivers/net/bna/bfa_cee.h +++ b/drivers/net/bna/bfa_cee.h @@ -56,17 +56,9 @@ struct bfa_cee { struct bfa_mbox_cmd reset_stats_mb; }; -u32 bfa_cee_meminfo(void); -void bfa_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, +u32 bfa_nw_cee_meminfo(void); +void bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa); -void bfa_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, void *dev); -void bfa_cee_detach(struct bfa_cee *cee); -enum bfa_status bfa_cee_get_attr(struct bfa_cee *cee, - struct bfa_cee_attr *attr, bfa_cee_get_attr_cbfn_t cbfn, void *cbarg); -enum bfa_status bfa_cee_get_stats(struct bfa_cee *cee, - struct bfa_cee_stats *stats, bfa_cee_get_stats_cbfn_t cbfn, - void *cbarg); -enum bfa_status bfa_cee_reset_stats(struct bfa_cee *cee, - bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg); +void bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, void *dev); #endif /* __BFA_CEE_H__ */ diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c index cdc2cb1597ec..caa45c2185e9 100644 --- a/drivers/net/bna/bfa_ioc.c +++ b/drivers/net/bna/bfa_ioc.c @@ -65,7 +65,7 @@ (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \ readl((__ioc)->ioc_regs.hfn_mbox_cmd)) -bool bfa_auto_recover = true; +bool bfa_nw_auto_recover = true; /* * forward declarations @@ -85,6 +85,23 @@ static void bfa_ioc_recover(struct bfa_ioc *ioc); static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc); static void bfa_ioc_disable_comp(struct bfa_ioc *ioc); static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc); +static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, + u32 boot_param); +static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr); +static u32 bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr); +static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, + char *serial_num); +static void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, + char *fw_ver); +static void bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, + char *chip_rev); +static void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, + char *optrom_ver); +static void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, + char *manufacturer); +static void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model); +static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc); +static mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc); /** * IOC state machine events @@ -138,7 +155,7 @@ static void bfa_ioc_sm_reset_entry(struct bfa_ioc *ioc) { ioc->retry_count = 0; - ioc->auto_recover = bfa_auto_recover; + ioc->auto_recover = bfa_nw_auto_recover; } /** @@ -185,7 +202,7 @@ bfa_ioc_sm_fwcheck(struct bfa_ioc *ioc, enum ioc_event event) ioc->retry_count = 0; bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit); } else { - bfa_ioc_hw_sem_release(ioc); + bfa_nw_ioc_hw_sem_release(ioc); bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch); } break; @@ -314,12 +331,12 @@ bfa_ioc_sm_hwinit(struct bfa_ioc *ioc, enum ioc_event event) break; } - bfa_ioc_hw_sem_release(ioc); + bfa_nw_ioc_hw_sem_release(ioc); bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); break; case IOC_E_DISABLE: - bfa_ioc_hw_sem_release(ioc); + bfa_nw_ioc_hw_sem_release(ioc); bfa_ioc_timer_stop(ioc); bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); break; @@ -346,7 +363,7 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event) switch (event) { case IOC_E_FWRSP_ENABLE: bfa_ioc_timer_stop(ioc); - bfa_ioc_hw_sem_release(ioc); + bfa_nw_ioc_hw_sem_release(ioc); bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); break; @@ -363,13 +380,13 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event) break; } - bfa_ioc_hw_sem_release(ioc); + bfa_nw_ioc_hw_sem_release(ioc); bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); break; case IOC_E_DISABLE: bfa_ioc_timer_stop(ioc); - bfa_ioc_hw_sem_release(ioc); + bfa_nw_ioc_hw_sem_release(ioc); bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); break; @@ -662,7 +679,7 @@ bfa_ioc_disable_comp(struct bfa_ioc *ioc) } void -bfa_ioc_sem_timeout(void *ioc_arg) +bfa_nw_ioc_sem_timeout(void *ioc_arg) { struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg; @@ -670,7 +687,7 @@ bfa_ioc_sem_timeout(void *ioc_arg) } bool -bfa_ioc_sem_get(void __iomem *sem_reg) +bfa_nw_ioc_sem_get(void __iomem *sem_reg) { u32 r32; int cnt = 0; @@ -692,7 +709,7 @@ bfa_ioc_sem_get(void __iomem *sem_reg) } void -bfa_ioc_sem_release(void __iomem *sem_reg) +bfa_nw_ioc_sem_release(void __iomem *sem_reg) { writel(1, sem_reg); } @@ -717,7 +734,7 @@ bfa_ioc_hw_sem_get(struct bfa_ioc *ioc) } void -bfa_ioc_hw_sem_release(struct bfa_ioc *ioc) +bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc) { writel(1, ioc->ioc_regs.ioc_sem_reg); } @@ -800,7 +817,7 @@ bfa_ioc_lpu_stop(struct bfa_ioc *ioc) * Get driver and firmware versions. */ void -bfa_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) +bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) { u32 pgnum, pgoff; u32 loff = 0; @@ -823,7 +840,7 @@ bfa_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) * Returns TRUE if same. */ bool -bfa_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) +bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) { struct bfi_ioc_image_hdr *drv_fwhdr; int i; @@ -854,7 +871,7 @@ bfa_ioc_fwver_valid(struct bfa_ioc *ioc) if (bfa_ioc_is_optrom(ioc)) return true; - bfa_ioc_fwver_get(ioc, &fwhdr); + bfa_nw_ioc_fwver_get(ioc, &fwhdr); drv_fwhdr = (struct bfi_ioc_image_hdr *) bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0); @@ -864,7 +881,7 @@ bfa_ioc_fwver_valid(struct bfa_ioc *ioc) if (fwhdr.exec != drv_fwhdr->exec) return false; - return bfa_ioc_fwver_cmp(ioc, &fwhdr); + return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr); } /** @@ -941,14 +958,14 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force) } void -bfa_ioc_timeout(void *ioc_arg) +bfa_nw_ioc_timeout(void *ioc_arg) { struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg; bfa_fsm_send_event(ioc, IOC_E_TIMEOUT); } -void +static void bfa_ioc_mbox_send(struct bfa_ioc *ioc, void *ioc_msg, int len) { u32 *msgp = (u32 *) ioc_msg; @@ -1009,7 +1026,7 @@ bfa_ioc_send_getattr(struct bfa_ioc *ioc) } void -bfa_ioc_hb_check(void *cbarg) +bfa_nw_ioc_hb_check(void *cbarg) { struct bfa_ioc *ioc = cbarg; u32 hb_count; @@ -1195,13 +1212,13 @@ bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc) /** * IOC public */ -enum bfa_status +static enum bfa_status bfa_ioc_pll_init(struct bfa_ioc *ioc) { /* * Hold semaphore so that nobody can access the chip during init. */ - bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg); + bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg); bfa_ioc_pll_init_asic(ioc); @@ -1209,7 +1226,7 @@ bfa_ioc_pll_init(struct bfa_ioc *ioc) /* * release semaphore. */ - bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); + bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); return BFA_STATUS_OK; } @@ -1218,7 +1235,7 @@ bfa_ioc_pll_init(struct bfa_ioc *ioc) * Interface used by diag module to do firmware boot with memory test * as the entry vector. */ -void +static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param) { void __iomem *rb; @@ -1254,28 +1271,18 @@ bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param) * Enable/disable IOC failure auto recovery. */ void -bfa_ioc_auto_recover(bool auto_recover) +bfa_nw_ioc_auto_recover(bool auto_recover) { - bfa_auto_recover = auto_recover; + bfa_nw_auto_recover = auto_recover; } bool -bfa_ioc_is_operational(struct bfa_ioc *ioc) +bfa_nw_ioc_is_operational(struct bfa_ioc *ioc) { return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op); } -bool -bfa_ioc_is_initialized(struct bfa_ioc *ioc) -{ - u32 r32 = readl(ioc->ioc_regs.ioc_fwstate); - - return ((r32 != BFI_IOC_UNINIT) && - (r32 != BFI_IOC_INITING) && - (r32 != BFI_IOC_MEMTEST)); -} - -void +static void bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg) { u32 *msgp = mbmsg; @@ -1299,7 +1306,7 @@ bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg) readl(ioc->ioc_regs.lpu_mbox_cmd); } -void +static void bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m) { union bfi_ioc_i2h_msg_u *msg; @@ -1340,7 +1347,7 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m) * @param[in] bfa driver instance structure */ void -bfa_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn) +bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn) { ioc->bfa = bfa; ioc->cbfn = cbfn; @@ -1358,7 +1365,7 @@ bfa_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn) * Driver detach time IOC cleanup. */ void -bfa_ioc_detach(struct bfa_ioc *ioc) +bfa_nw_ioc_detach(struct bfa_ioc *ioc) { bfa_fsm_send_event(ioc, IOC_E_DETACH); } @@ -1369,7 +1376,7 @@ bfa_ioc_detach(struct bfa_ioc *ioc) * @param[in] pcidev PCI device information for this IOC */ void -bfa_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, +bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, enum bfi_mclass mc) { ioc->ioc_mc = mc; @@ -1377,7 +1384,7 @@ bfa_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id); ioc->cna = ioc->ctdev && !ioc->fcmode; - bfa_ioc_set_ct_hwif(ioc); + bfa_nw_ioc_set_ct_hwif(ioc); bfa_ioc_map_port(ioc); bfa_ioc_reg_init(ioc); @@ -1390,7 +1397,7 @@ bfa_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, * @param[in] dm_pa physical address of IOC dma memory */ void -bfa_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa) +bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa) { /** * dma memory for firmware attribute @@ -1404,13 +1411,13 @@ bfa_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa) * Return size of dma memory required. */ u32 -bfa_ioc_meminfo(void) +bfa_nw_ioc_meminfo(void) { return roundup(sizeof(struct bfi_ioc_attr), BFA_DMA_ALIGN_SZ); } void -bfa_ioc_enable(struct bfa_ioc *ioc) +bfa_nw_ioc_enable(struct bfa_ioc *ioc) { bfa_ioc_stats(ioc, ioc_enables); ioc->dbg_fwsave_once = true; @@ -1419,45 +1426,29 @@ bfa_ioc_enable(struct bfa_ioc *ioc) } void -bfa_ioc_disable(struct bfa_ioc *ioc) +bfa_nw_ioc_disable(struct bfa_ioc *ioc) { bfa_ioc_stats(ioc, ioc_disables); bfa_fsm_send_event(ioc, IOC_E_DISABLE); } -u32 +static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr) { return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr); } -u32 +static u32 bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr) { return PSS_SMEM_PGOFF(fmaddr); } -/** - * Register mailbox message handler functions - * - * @param[in] ioc IOC instance - * @param[in] mcfuncs message class handler functions - */ -void -bfa_ioc_mbox_register(struct bfa_ioc *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs) -{ - struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; - int mc; - - for (mc = 0; mc < BFI_MC_MAX; mc++) - mod->mbhdlr[mc].cbfn = mcfuncs[mc]; -} - /** * Register mailbox message handler function, to be called by common modules */ void -bfa_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, +bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg) { struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; @@ -1474,7 +1465,7 @@ bfa_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, * @param[i] cmd Mailbox command */ void -bfa_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd) +bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd) { struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; u32 stat; @@ -1506,7 +1497,7 @@ bfa_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd) * Handle mailbox interrupts */ void -bfa_ioc_mbox_isr(struct bfa_ioc *ioc) +bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc) { struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; struct bfi_mbmsg m; @@ -1530,86 +1521,24 @@ bfa_ioc_mbox_isr(struct bfa_ioc *ioc) } void -bfa_ioc_error_isr(struct bfa_ioc *ioc) +bfa_nw_ioc_error_isr(struct bfa_ioc *ioc) { bfa_fsm_send_event(ioc, IOC_E_HWERROR); } -void -bfa_ioc_set_fcmode(struct bfa_ioc *ioc) -{ - ioc->fcmode = true; - ioc->port_id = bfa_ioc_pcifn(ioc); -} - -/** - * return true if IOC is disabled - */ -bool -bfa_ioc_is_disabled(struct bfa_ioc *ioc) -{ - return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) || - bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled); -} - -/** - * return true if IOC firmware is different. - */ -bool -bfa_ioc_fw_mismatch(struct bfa_ioc *ioc) -{ - return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) || - bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck) || - bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch); -} - -#define bfa_ioc_state_disabled(__sm) \ - (((__sm) == BFI_IOC_UNINIT) || \ - ((__sm) == BFI_IOC_INITING) || \ - ((__sm) == BFI_IOC_HWINIT) || \ - ((__sm) == BFI_IOC_DISABLED) || \ - ((__sm) == BFI_IOC_FAIL) || \ - ((__sm) == BFI_IOC_CFG_DISABLED)) - -/** - * Check if adapter is disabled -- both IOCs should be in a disabled - * state. - */ -bool -bfa_ioc_adapter_is_disabled(struct bfa_ioc *ioc) -{ - u32 ioc_state; - void __iomem *rb = ioc->pcidev.pci_bar_kva; - - if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled)) - return false; - - ioc_state = readl(rb + BFA_IOC0_STATE_REG); - if (!bfa_ioc_state_disabled(ioc_state)) - return false; - - if (ioc->pcidev.device_id != PCI_DEVICE_ID_BROCADE_FC_8G1P) { - ioc_state = readl(rb + BFA_IOC1_STATE_REG); - if (!bfa_ioc_state_disabled(ioc_state)) - return false; - } - - return true; -} - /** * Add to IOC heartbeat failure notification queue. To be used by common * modules such as cee, port, diag. */ void -bfa_ioc_hbfail_register(struct bfa_ioc *ioc, +bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc, struct bfa_ioc_hbfail_notify *notify) { list_add_tail(¬ify->qe, &ioc->hb_notify_q); } #define BFA_MFG_NAME "Brocade" -void +static void bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc, struct bfa_adapter_attr *ad_attr) { @@ -1640,7 +1569,7 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc, ad_attr->prototype = 0; ad_attr->pwwn = bfa_ioc_get_pwwn(ioc); - ad_attr->mac = bfa_ioc_get_mac(ioc); + ad_attr->mac = bfa_nw_ioc_get_mac(ioc); ad_attr->pcie_gen = ioc_attr->pcie_gen; ad_attr->pcie_lanes = ioc_attr->pcie_lanes; @@ -1653,7 +1582,7 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc, ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna; } -enum bfa_ioc_type +static enum bfa_ioc_type bfa_ioc_get_type(struct bfa_ioc *ioc) { if (!ioc->ctdev || ioc->fcmode) @@ -1668,7 +1597,7 @@ bfa_ioc_get_type(struct bfa_ioc *ioc) } } -void +static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num) { memset(serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN); @@ -1677,14 +1606,14 @@ bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num) BFA_ADAPTER_SERIAL_NUM_LEN); } -void +static void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver) { memset(fw_ver, 0, BFA_VERSION_LEN); memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN); } -void +static void bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev) { BUG_ON(!(chip_rev)); @@ -1699,7 +1628,7 @@ bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev) chip_rev[5] = '\0'; } -void +static void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver) { memset(optrom_ver, 0, BFA_VERSION_LEN); @@ -1707,14 +1636,14 @@ bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver) BFA_VERSION_LEN); } -void +static void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer) { memset(manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN); memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); } -void +static void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model) { struct bfi_ioc_attr *ioc_attr; @@ -1731,14 +1660,14 @@ bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model) BFA_MFG_NAME, ioc_attr->card_type); } -enum bfa_ioc_state +static enum bfa_ioc_state bfa_ioc_get_state(struct bfa_ioc *ioc) { return bfa_sm_to_state(ioc_sm_table, ioc->fsm); } void -bfa_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr) +bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr) { memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr)); @@ -1757,26 +1686,14 @@ bfa_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr) /** * WWN public */ -u64 +static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc) { return ioc->attr->pwwn; } -u64 -bfa_ioc_get_nwwn(struct bfa_ioc *ioc) -{ - return ioc->attr->nwwn; -} - -u64 -bfa_ioc_get_adid(struct bfa_ioc *ioc) -{ - return ioc->attr->mfg_pwwn; -} - mac_t -bfa_ioc_get_mac(struct bfa_ioc *ioc) +bfa_nw_ioc_get_mac(struct bfa_ioc *ioc) { /* * Currently mfg mac is used as FCoE enode mac (not configured by PBC) @@ -1787,19 +1704,7 @@ bfa_ioc_get_mac(struct bfa_ioc *ioc) return ioc->attr->mac; } -u64 -bfa_ioc_get_mfg_pwwn(struct bfa_ioc *ioc) -{ - return ioc->attr->mfg_pwwn; -} - -u64 -bfa_ioc_get_mfg_nwwn(struct bfa_ioc *ioc) -{ - return ioc->attr->mfg_nwwn; -} - -mac_t +static mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc) { mac_t m; @@ -1814,12 +1719,6 @@ bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc) return m; } -bool -bfa_ioc_get_fcmode(struct bfa_ioc *ioc) -{ - return ioc->fcmode || !bfa_asic_id_ct(ioc->pcidev.device_id); -} - /** * Firmware failure detected. Start recovery actions. */ diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h index 2e5c0adef899..7f0719e17efc 100644 --- a/drivers/net/bna/bfa_ioc.h +++ b/drivers/net/bna/bfa_ioc.h @@ -239,13 +239,9 @@ struct bfa_ioc_hwif { /** * IOC mailbox interface */ -void bfa_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd); -void bfa_ioc_mbox_register(struct bfa_ioc *ioc, - bfa_ioc_mbox_mcfunc_t *mcfuncs); -void bfa_ioc_mbox_isr(struct bfa_ioc *ioc); -void bfa_ioc_mbox_send(struct bfa_ioc *ioc, void *ioc_msg, int len); -void bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg); -void bfa_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, +void bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd); +void bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc); +void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg); /** @@ -256,83 +252,45 @@ void bfa_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, ((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \ (__ioc)->fcmode)) -enum bfa_status bfa_ioc_pll_init(struct bfa_ioc *ioc); -enum bfa_status bfa_ioc_cb_pll_init(void __iomem *rb, bool fcmode); -enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode); - #define bfa_ioc_isr_mode_set(__ioc, __msix) \ ((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix)) #define bfa_ioc_ownership_reset(__ioc) \ ((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc)) -void bfa_ioc_set_ct_hwif(struct bfa_ioc *ioc); +void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc); -void bfa_ioc_attach(struct bfa_ioc *ioc, void *bfa, +void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn); -void bfa_ioc_auto_recover(bool auto_recover); -void bfa_ioc_detach(struct bfa_ioc *ioc); -void bfa_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, +void bfa_nw_ioc_auto_recover(bool auto_recover); +void bfa_nw_ioc_detach(struct bfa_ioc *ioc); +void bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, enum bfi_mclass mc); -u32 bfa_ioc_meminfo(void); -void bfa_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa); -void bfa_ioc_enable(struct bfa_ioc *ioc); -void bfa_ioc_disable(struct bfa_ioc *ioc); -bool bfa_ioc_intx_claim(struct bfa_ioc *ioc); - -void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, - u32 boot_param); -void bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *msg); -void bfa_ioc_error_isr(struct bfa_ioc *ioc); -bool bfa_ioc_is_operational(struct bfa_ioc *ioc); -bool bfa_ioc_is_initialized(struct bfa_ioc *ioc); -bool bfa_ioc_is_disabled(struct bfa_ioc *ioc); -bool bfa_ioc_fw_mismatch(struct bfa_ioc *ioc); -bool bfa_ioc_adapter_is_disabled(struct bfa_ioc *ioc); -void bfa_ioc_cfg_complete(struct bfa_ioc *ioc); -enum bfa_ioc_type bfa_ioc_get_type(struct bfa_ioc *ioc); -void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num); -void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver); -void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver); -void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model); -void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, - char *manufacturer); -void bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev); -enum bfa_ioc_state bfa_ioc_get_state(struct bfa_ioc *ioc); - -void bfa_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr); -void bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc, - struct bfa_adapter_attr *ad_attr); -u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr); -u32 bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr); -void bfa_ioc_set_fcmode(struct bfa_ioc *ioc); -bool bfa_ioc_get_fcmode(struct bfa_ioc *ioc); -void bfa_ioc_hbfail_register(struct bfa_ioc *ioc, +u32 bfa_nw_ioc_meminfo(void); +void bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa); +void bfa_nw_ioc_enable(struct bfa_ioc *ioc); +void bfa_nw_ioc_disable(struct bfa_ioc *ioc); + +void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc); +bool bfa_nw_ioc_is_operational(struct bfa_ioc *ioc); + +void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr); +void bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc, struct bfa_ioc_hbfail_notify *notify); -bool bfa_ioc_sem_get(void __iomem *sem_reg); -void bfa_ioc_sem_release(void __iomem *sem_reg); -void bfa_ioc_hw_sem_release(struct bfa_ioc *ioc); -void bfa_ioc_fwver_get(struct bfa_ioc *ioc, +bool bfa_nw_ioc_sem_get(void __iomem *sem_reg); +void bfa_nw_ioc_sem_release(void __iomem *sem_reg); +void bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc); +void bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr); -bool bfa_ioc_fwver_cmp(struct bfa_ioc *ioc, +bool bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr); +mac_t bfa_nw_ioc_get_mac(struct bfa_ioc *ioc); /* * Timeout APIs */ -void bfa_ioc_timeout(void *ioc); -void bfa_ioc_hb_check(void *ioc); -void bfa_ioc_sem_timeout(void *ioc); - -/* - * bfa mfg wwn API functions - */ -u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc); -u64 bfa_ioc_get_nwwn(struct bfa_ioc *ioc); -mac_t bfa_ioc_get_mac(struct bfa_ioc *ioc); -u64 bfa_ioc_get_mfg_pwwn(struct bfa_ioc *ioc); -u64 bfa_ioc_get_mfg_nwwn(struct bfa_ioc *ioc); -mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc); -u64 bfa_ioc_get_adid(struct bfa_ioc *ioc); +void bfa_nw_ioc_timeout(void *ioc); +void bfa_nw_ioc_hb_check(void *ioc); +void bfa_nw_ioc_sem_timeout(void *ioc); /* * F/W Image Size & Chunk diff --git a/drivers/net/bna/bfa_ioc_ct.c b/drivers/net/bna/bfa_ioc_ct.c index 870046e32c8d..462857cbab9b 100644 --- a/drivers/net/bna/bfa_ioc_ct.c +++ b/drivers/net/bna/bfa_ioc_ct.c @@ -32,25 +32,26 @@ static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc); static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix); static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc); static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc); +static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode); -struct bfa_ioc_hwif hwif_ct; +struct bfa_ioc_hwif nw_hwif_ct; /** * Called from bfa_ioc_attach() to map asic specific calls. */ void -bfa_ioc_set_ct_hwif(struct bfa_ioc *ioc) +bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc) { - hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init; - hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock; - hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock; - hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init; - hwif_ct.ioc_map_port = bfa_ioc_ct_map_port; - hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; - hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail; - hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; - - ioc->ioc_hwif = &hwif_ct; + nw_hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init; + nw_hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock; + nw_hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock; + nw_hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init; + nw_hwif_ct.ioc_map_port = bfa_ioc_ct_map_port; + nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; + nw_hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail; + nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; + + ioc->ioc_hwif = &nw_hwif_ct; } /** @@ -76,7 +77,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc) BFA_IOC_FWIMG_MINSZ) return true; - bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); + bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); usecnt = readl(ioc->ioc_regs.ioc_usage_reg); /** @@ -84,7 +85,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc) */ if (usecnt == 0) { writel(1, ioc->ioc_regs.ioc_usage_reg); - bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); return true; } @@ -98,9 +99,9 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc) /** * Check if another driver with a different firmware is active */ - bfa_ioc_fwver_get(ioc, &fwhdr); - if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) { - bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + bfa_nw_ioc_fwver_get(ioc, &fwhdr); + if (!bfa_nw_ioc_fwver_cmp(ioc, &fwhdr)) { + bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); return false; } @@ -109,7 +110,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc) */ usecnt++; writel(usecnt, ioc->ioc_regs.ioc_usage_reg); - bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); return true; } @@ -134,14 +135,14 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc) /** * decrement usage count */ - bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); + bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); usecnt = readl(ioc->ioc_regs.ioc_usage_reg); BUG_ON(!(usecnt > 0)); usecnt--; writel(usecnt, ioc->ioc_regs.ioc_usage_reg); - bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); } /** @@ -302,9 +303,9 @@ static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc) { if (ioc->cna) { - bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); + bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); writel(0, ioc->ioc_regs.ioc_usage_reg); - bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); } /* @@ -313,10 +314,10 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc) * will lock it instead of clearing it. */ readl(ioc->ioc_regs.ioc_sem_reg); - bfa_ioc_hw_sem_release(ioc); + bfa_nw_ioc_hw_sem_release(ioc); } -enum bfa_status +static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode) { u32 pll_sclk, pll_fclk, r32; diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c index 9d41ebf41cf4..f3034d6bda58 100644 --- a/drivers/net/bna/bna_ctrl.c +++ b/drivers/net/bna/bna_ctrl.c @@ -81,7 +81,7 @@ bna_ll_isr(void *llarg, struct bfi_mbmsg *msg) /* Post the next entry, if needed */ if (to_post) { mb_qe = bfa_q_first(&bna->mbox_mod.posted_q); - bfa_ioc_mbox_queue(&bna->device.ioc, + bfa_nw_ioc_mbox_queue(&bna->device.ioc, &mb_qe->cmd); } } else { @@ -107,7 +107,7 @@ bna_err_handler(struct bna *bna, u32 intr_status) writel(init_halt, bna->device.ioc.ioc_regs.ll_halt); } - bfa_ioc_error_isr(&bna->device.ioc); + bfa_nw_ioc_error_isr(&bna->device.ioc); } void @@ -118,7 +118,7 @@ bna_mbox_handler(struct bna *bna, u32 intr_status) return; } if (BNA_IS_MBOX_INTR(intr_status)) - bfa_ioc_mbox_isr(&bna->device.ioc); + bfa_nw_ioc_mbox_isr(&bna->device.ioc); } void @@ -133,7 +133,7 @@ bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe) bna->mbox_mod.msg_pending++; if (bna->mbox_mod.state == BNA_MBOX_FREE) { list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q); - bfa_ioc_mbox_queue(&bna->device.ioc, &mbox_qe->cmd); + bfa_nw_ioc_mbox_queue(&bna->device.ioc, &mbox_qe->cmd); bna->mbox_mod.state = BNA_MBOX_POSTED; } else { list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q); @@ -180,7 +180,7 @@ bna_mbox_mod_stop(struct bna_mbox_mod *mbox_mod) void bna_mbox_mod_init(struct bna_mbox_mod *mbox_mod, struct bna *bna) { - bfa_ioc_mbox_regisr(&bna->device.ioc, BFI_MC_LL, bna_ll_isr, bna); + bfa_nw_ioc_mbox_regisr(&bna->device.ioc, BFI_MC_LL, bna_ll_isr, bna); mbox_mod->state = BNA_MBOX_FREE; mbox_mod->msg_ctr = mbox_mod->msg_pending = 0; INIT_LIST_HEAD(&mbox_mod->posted_q); @@ -1289,7 +1289,7 @@ bna_port_mtu_set(struct bna_port *port, int mtu, void bna_port_mac_get(struct bna_port *port, mac_t *mac) { - *mac = bfa_ioc_get_mac(&port->bna->device.ioc); + *mac = bfa_nw_ioc_get_mac(&port->bna->device.ioc); } /** @@ -1427,7 +1427,7 @@ bna_device_sm_stopped(struct bna_device *device, case DEVICE_E_ENABLE: if (device->intr_type == BNA_INTR_T_MSIX) bna_mbox_msix_idx_set(device); - bfa_ioc_enable(&device->ioc); + bfa_nw_ioc_enable(&device->ioc); bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait); break; @@ -1547,7 +1547,7 @@ bna_device_sm_port_stop_wait(struct bna_device *device, static void bna_device_sm_ioc_disable_wait_entry(struct bna_device *device) { - bfa_ioc_disable(&device->ioc); + bfa_nw_ioc_disable(&device->ioc); } static void @@ -1655,12 +1655,12 @@ bna_device_init(struct bna_device *device, struct bna *bna, * 1. DMA memory for IOC attributes * 2. Kernel memory for FW trace */ - bfa_ioc_attach(&device->ioc, device, &bfa_iocll_cbfn); - bfa_ioc_pci_init(&device->ioc, &bna->pcidev, BFI_MC_LL); + bfa_nw_ioc_attach(&device->ioc, device, &bfa_iocll_cbfn); + bfa_nw_ioc_pci_init(&device->ioc, &bna->pcidev, BFI_MC_LL); BNA_GET_DMA_ADDR( &res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].dma, dma); - bfa_ioc_mem_claim(&device->ioc, + bfa_nw_ioc_mem_claim(&device->ioc, res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].kva, dma); @@ -1686,9 +1686,7 @@ bna_device_uninit(struct bna_device *device) { bna_mbox_mod_uninit(&device->bna->mbox_mod); - bfa_cee_detach(&device->bna->cee); - - bfa_ioc_detach(&device->ioc); + bfa_nw_ioc_detach(&device->ioc); device->bna = NULL; } @@ -1783,10 +1781,10 @@ bna_adv_device_init(struct bna_device *device, struct bna *bna, &res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].dma, dma); kva = res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].kva; - bfa_cee_attach(&bna->cee, &device->ioc, bna); - bfa_cee_mem_claim(&bna->cee, kva, dma); - kva += bfa_cee_meminfo(); - dma += bfa_cee_meminfo(); + bfa_nw_cee_attach(&bna->cee, &device->ioc, bna); + bfa_nw_cee_mem_claim(&bna->cee, kva, dma); + kva += bfa_nw_cee_meminfo(); + dma += bfa_nw_cee_meminfo(); } @@ -1800,7 +1798,7 @@ bna_adv_res_req(struct bna_res_info *res_info) res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mem_type = BNA_MEM_T_DMA; res_info[BNA_RES_MEM_T_COM].res_u.mem_info.num = 1; res_info[BNA_RES_MEM_T_COM].res_u.mem_info.len = ALIGN( - bfa_cee_meminfo(), PAGE_SIZE); + bfa_nw_cee_meminfo(), PAGE_SIZE); /* Virtual memory for retreiving fw_trc */ res_info[BNA_RES_MEM_T_FWTRC].res_type = BNA_RES_T_MEM; @@ -3333,7 +3331,7 @@ bna_res_req(struct bna_res_info *res_info) res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mem_type = BNA_MEM_T_DMA; res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.num = 1; res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.len = - ALIGN(bfa_ioc_meminfo(), PAGE_SIZE); + ALIGN(bfa_nw_ioc_meminfo(), PAGE_SIZE); /* DMA memory for index segment of an IB */ res_info[BNA_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM; diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c index 491d148f88ae..cbc1d563a0c2 100644 --- a/drivers/net/bna/bnad.c +++ b/drivers/net/bna/bnad.c @@ -1365,7 +1365,7 @@ bnad_ioc_timeout(unsigned long data) unsigned long flags; spin_lock_irqsave(&bnad->bna_lock, flags); - bfa_ioc_timeout((void *) &bnad->bna.device.ioc); + bfa_nw_ioc_timeout((void *) &bnad->bna.device.ioc); spin_unlock_irqrestore(&bnad->bna_lock, flags); } @@ -1376,7 +1376,7 @@ bnad_ioc_hb_check(unsigned long data) unsigned long flags; spin_lock_irqsave(&bnad->bna_lock, flags); - bfa_ioc_hb_check((void *) &bnad->bna.device.ioc); + bfa_nw_ioc_hb_check((void *) &bnad->bna.device.ioc); spin_unlock_irqrestore(&bnad->bna_lock, flags); } @@ -1387,7 +1387,7 @@ bnad_ioc_sem_timeout(unsigned long data) unsigned long flags; spin_lock_irqsave(&bnad->bna_lock, flags); - bfa_ioc_sem_timeout((void *) &bnad->bna.device.ioc); + bfa_nw_ioc_sem_timeout((void *) &bnad->bna.device.ioc); spin_unlock_irqrestore(&bnad->bna_lock, flags); } @@ -3067,7 +3067,6 @@ bnad_pci_probe(struct pci_dev *pdev, } bnad = netdev_priv(netdev); - /* * PCI initialization * Output : using_dac = 1 for 64 bit DMA @@ -3239,7 +3238,7 @@ bnad_module_init(void) pr_info("Brocade 10G Ethernet driver\n"); - bfa_ioc_auto_recover(bnad_ioc_auto_recover); + bfa_nw_ioc_auto_recover(bnad_ioc_auto_recover); err = pci_register_driver(&bnad_pci_driver); if (err < 0) { diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c index 7e630f5e8e03..b337bd9bed29 100644 --- a/drivers/net/bna/bnad_ethtool.c +++ b/drivers/net/bna/bnad_ethtool.c @@ -276,7 +276,7 @@ bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) if (ioc_attr) { memset(ioc_attr, 0, sizeof(*ioc_attr)); spin_lock_irqsave(&bnad->bna_lock, flags); - bfa_ioc_get_attr(&bnad->bna.device.ioc, ioc_attr); + bfa_nw_ioc_get_attr(&bnad->bna.device.ioc, ioc_attr); spin_unlock_irqrestore(&bnad->bna_lock, flags); strncpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver, -- cgit v1.2.3-59-g8ed1b From 8870f8427b8fe30b2684b9e569e5ce038faf41ac Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 26 Aug 2010 13:21:26 -0700 Subject: IPVS: ICMPv6 checksum calculation Cc: Xiaoyu Du Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/netfilter/ipvs/ip_vs_core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 4f8ddba48011..69661db420d7 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -637,10 +637,12 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp, } /* And finally the ICMP checksum */ - icmph->icmp6_cksum = 0; - /* TODO IPv6: is this correct for ICMPv6? */ - ip_vs_checksum_complete(skb, icmp_offset); - skb->ip_summed = CHECKSUM_UNNECESSARY; + icmph->icmp6_cksum = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, + skb->len - icmp_offset, + IPPROTO_ICMPV6, 0); + skb->csum_start = skb_network_header(skb) - skb->head + icmp_offset; + skb->csum_offset = offsetof(struct icmp6hdr, icmp6_cksum); + skb->ip_summed = CHECKSUM_PARTIAL; if (inout) IP_VS_DBG_PKT(11, pp, skb, (void *)ciph - (void *)iph, -- cgit v1.2.3-59-g8ed1b From bd144550489270a32a531e84a2b4bb6882096236 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 26 Aug 2010 02:54:29 +0000 Subject: IPVS: convert __ip_vs_sched_lock to a spinlock Also rename __ip_vs_sched_lock to ip_vs_sched_lock. Acked-by: Eric Dumazet Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/netfilter/ipvs/ip_vs_sched.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c index bbc1ac795952..727e45b66953 100644 --- a/net/netfilter/ipvs/ip_vs_sched.c +++ b/net/netfilter/ipvs/ip_vs_sched.c @@ -35,7 +35,7 @@ static LIST_HEAD(ip_vs_schedulers); /* lock for service table */ -static DEFINE_RWLOCK(__ip_vs_sched_lock); +static DEFINE_SPINLOCK(ip_vs_sched_lock); /* @@ -108,7 +108,7 @@ static struct ip_vs_scheduler *ip_vs_sched_getbyname(const char *sched_name) IP_VS_DBG(2, "%s(): sched_name \"%s\"\n", __func__, sched_name); - read_lock_bh(&__ip_vs_sched_lock); + spin_lock_bh(&ip_vs_sched_lock); list_for_each_entry(sched, &ip_vs_schedulers, n_list) { /* @@ -122,14 +122,14 @@ static struct ip_vs_scheduler *ip_vs_sched_getbyname(const char *sched_name) } if (strcmp(sched_name, sched->name)==0) { /* HIT */ - read_unlock_bh(&__ip_vs_sched_lock); + spin_unlock_bh(&ip_vs_sched_lock); return sched; } if (sched->module) module_put(sched->module); } - read_unlock_bh(&__ip_vs_sched_lock); + spin_unlock_bh(&ip_vs_sched_lock); return NULL; } @@ -184,10 +184,10 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler) /* increase the module use count */ ip_vs_use_count_inc(); - write_lock_bh(&__ip_vs_sched_lock); + spin_lock_bh(&ip_vs_sched_lock); if (!list_empty(&scheduler->n_list)) { - write_unlock_bh(&__ip_vs_sched_lock); + spin_unlock_bh(&ip_vs_sched_lock); ip_vs_use_count_dec(); pr_err("%s(): [%s] scheduler already linked\n", __func__, scheduler->name); @@ -200,7 +200,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler) */ list_for_each_entry(sched, &ip_vs_schedulers, n_list) { if (strcmp(scheduler->name, sched->name) == 0) { - write_unlock_bh(&__ip_vs_sched_lock); + spin_unlock_bh(&ip_vs_sched_lock); ip_vs_use_count_dec(); pr_err("%s(): [%s] scheduler already existed " "in the system\n", __func__, scheduler->name); @@ -211,7 +211,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler) * Add it into the d-linked scheduler list */ list_add(&scheduler->n_list, &ip_vs_schedulers); - write_unlock_bh(&__ip_vs_sched_lock); + spin_unlock_bh(&ip_vs_sched_lock); pr_info("[%s] scheduler registered.\n", scheduler->name); @@ -229,9 +229,9 @@ int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler) return -EINVAL; } - write_lock_bh(&__ip_vs_sched_lock); + spin_lock_bh(&ip_vs_sched_lock); if (list_empty(&scheduler->n_list)) { - write_unlock_bh(&__ip_vs_sched_lock); + spin_unlock_bh(&ip_vs_sched_lock); pr_err("%s(): [%s] scheduler is not in the list. failed\n", __func__, scheduler->name); return -EINVAL; @@ -241,7 +241,7 @@ int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler) * Remove it from the d-linked scheduler list */ list_del(&scheduler->n_list); - write_unlock_bh(&__ip_vs_sched_lock); + spin_unlock_bh(&ip_vs_sched_lock); /* decrease the module use count */ ip_vs_use_count_dec(); -- cgit v1.2.3-59-g8ed1b From 4f72816ef07fdf49338ee0e6764a3961d552994a Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 26 Aug 2010 02:54:30 +0000 Subject: IPVS: convert __ip_vs_securetcp_lock to a spinlock Also rename __ip_vs_securetcp_lock to ip_vs_securetcp_lock. Spinlock conversion was suggested by Eric Dumazet. Acked-by: Eric Dumazet Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/netfilter/ipvs/ip_vs_ctl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 53a88af22503..8ca1a474eed6 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -61,7 +61,7 @@ static DEFINE_RWLOCK(__ip_vs_svc_lock); static DEFINE_RWLOCK(__ip_vs_rs_lock); /* lock for state and timeout tables */ -static DEFINE_RWLOCK(__ip_vs_securetcp_lock); +static DEFINE_SPINLOCK(ip_vs_securetcp_lock); /* lock for drop entry handling */ static DEFINE_SPINLOCK(__ip_vs_dropentry_lock); @@ -204,7 +204,7 @@ static void update_defense_level(void) spin_unlock(&__ip_vs_droppacket_lock); /* secure_tcp */ - write_lock(&__ip_vs_securetcp_lock); + spin_lock(&ip_vs_securetcp_lock); switch (sysctl_ip_vs_secure_tcp) { case 0: if (old_secure_tcp >= 2) @@ -238,7 +238,7 @@ static void update_defense_level(void) old_secure_tcp = sysctl_ip_vs_secure_tcp; if (to_change >= 0) ip_vs_protocol_timeout_change(sysctl_ip_vs_secure_tcp>1); - write_unlock(&__ip_vs_securetcp_lock); + spin_unlock(&ip_vs_securetcp_lock); local_bh_enable(); } -- cgit v1.2.3-59-g8ed1b From dee06e4702b5a64b9ca81e650d66223c5b3e7f14 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 26 Aug 2010 02:54:31 +0000 Subject: ipvs: switch to GFP_KERNEL allocations Switch from GFP_ATOMIC allocations to GFP_KERNEL ones in ip_vs_add_service() and ip_vs_new_dest(), as we hold a mutex and are allowed to sleep in this context. Signed-off-by: Eric Dumazet Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/netfilter/ipvs/ip_vs_ctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 8ca1a474eed6..ca8ec8c4f311 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -843,7 +843,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest, return -EINVAL; } - dest = kzalloc(sizeof(struct ip_vs_dest), GFP_ATOMIC); + dest = kzalloc(sizeof(struct ip_vs_dest), GFP_KERNEL); if (dest == NULL) { pr_err("%s(): no memory.\n", __func__); return -ENOMEM; @@ -1177,7 +1177,7 @@ ip_vs_add_service(struct ip_vs_service_user_kern *u, } #endif - svc = kzalloc(sizeof(struct ip_vs_service), GFP_ATOMIC); + svc = kzalloc(sizeof(struct ip_vs_service), GFP_KERNEL); if (svc == NULL) { IP_VS_DBG(1, "%s(): no memory\n", __func__); ret = -ENOMEM; -- cgit v1.2.3-59-g8ed1b From 145ce502e44b57c074c72cfdc855557e19026999 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 24 Aug 2010 13:21:08 +0000 Subject: net/sctp: Use pr_fmt and pr_ Change SCTP_DEBUG_PRINTK and SCTP_DEBUG_PRINTK_IPADDR to use do { print } while (0) guards. Add SCTP_DEBUG_PRINTK_CONT to fix errors in log when lines were continued. Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Add a missing newline in "Failed bind hash alloc" Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 48 ++++++++++++++++++++++++++++++------------------ net/sctp/associola.c | 2 ++ net/sctp/chunk.c | 2 ++ net/sctp/inqueue.c | 2 ++ net/sctp/ipv6.c | 4 +++- net/sctp/objcnt.c | 5 +++-- net/sctp/output.c | 2 ++ net/sctp/outqueue.c | 34 ++++++++++++++++++---------------- net/sctp/probe.c | 4 +++- net/sctp/protocol.c | 17 ++++++++--------- net/sctp/sm_make_chunk.c | 2 ++ net/sctp/sm_sideeffect.c | 21 ++++++++++----------- net/sctp/sm_statefuns.c | 20 ++++++++++---------- net/sctp/sm_statetable.c | 42 +++++++++++++++++++++--------------------- net/sctp/socket.c | 39 +++++++++++++++------------------------ net/sctp/transport.c | 9 +++++---- 16 files changed, 136 insertions(+), 117 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 65946bc43d00..2cb3980b1616 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -275,24 +275,35 @@ struct sctp_mib { /* Print debugging messages. */ #if SCTP_DEBUG extern int sctp_debug_flag; -#define SCTP_DEBUG_PRINTK(whatever...) \ - ((void) (sctp_debug_flag && printk(KERN_DEBUG whatever))) -#define SCTP_DEBUG_PRINTK_IPADDR(lead, trail, leadparm, saddr, otherparms...) \ - if (sctp_debug_flag) { \ - if (saddr->sa.sa_family == AF_INET6) { \ - printk(KERN_DEBUG \ - lead "%pI6" trail, \ - leadparm, \ - &saddr->v6.sin6_addr, \ - otherparms); \ - } else { \ - printk(KERN_DEBUG \ - lead "%pI4" trail, \ - leadparm, \ - &saddr->v4.sin_addr.s_addr, \ - otherparms); \ - } \ - } +#define SCTP_DEBUG_PRINTK(fmt, args...) \ +do { \ + if (sctp_debug_flag) \ + printk(KERN_DEBUG pr_fmt(fmt), ##args); \ +} while (0) +#define SCTP_DEBUG_PRINTK_CONT(fmt, args...) \ +do { \ + if (sctp_debug_flag) \ + pr_cont(fmt, ##args); \ +} while (0) +#define SCTP_DEBUG_PRINTK_IPADDR(fmt_lead, fmt_trail, \ + args_lead, saddr, args_trail...) \ +do { \ + if (sctp_debug_flag) { \ + if (saddr->sa.sa_family == AF_INET6) { \ + printk(KERN_DEBUG \ + pr_fmt(fmt_lead "%pI6" fmt_trail), \ + args_lead, \ + &saddr->v6.sin6_addr, \ + args_trail); \ + } else { \ + printk(KERN_DEBUG \ + pr_fmt(fmt_lead "%pI4" fmt_trail), \ + args_lead, \ + &saddr->v4.sin_addr.s_addr, \ + args_trail); \ + } \ + } \ +} while (0) #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; } #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; } @@ -306,6 +317,7 @@ extern int sctp_debug_flag; #else /* SCTP_DEBUG */ #define SCTP_DEBUG_PRINTK(whatever...) +#define SCTP_DEBUG_PRINTK_CONT(fmt, args...) #define SCTP_DEBUG_PRINTK_IPADDR(whatever...) #define SCTP_ENABLE_DEBUG #define SCTP_DISABLE_DEBUG diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 0b85e5256434..5f1fb8bd862d 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -48,6 +48,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 476caaf100ed..6c8556459a75 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -37,6 +37,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index ccb6dc48d15b..397296fb156f 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -43,6 +43,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 732689140fb8..95e0c8eda1a0 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -47,6 +47,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -336,7 +338,7 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, memcpy(saddr, baddr, sizeof(union sctp_addr)); SCTP_DEBUG_PRINTK("saddr: %pI6\n", &saddr->v6.sin6_addr); } else { - printk(KERN_ERR "%s: asoc:%p Could not find a valid source " + pr_err("%s: asoc:%p Could not find a valid source " "address for the dest:%pI6\n", __func__, asoc, &daddr->v6.sin6_addr); } diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c index f73ec0ea93ba..8ef8e7d9eb61 100644 --- a/net/sctp/objcnt.c +++ b/net/sctp/objcnt.c @@ -38,6 +38,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include @@ -134,8 +136,7 @@ void sctp_dbg_objcnt_init(void) ent = proc_create("sctp_dbg_objcnt", 0, proc_net_sctp, &sctp_objcnt_ops); if (!ent) - printk(KERN_WARNING - "sctp_dbg_objcnt: Unable to create /proc entry.\n"); + pr_warn("sctp_dbg_objcnt: Unable to create /proc entry.\n"); } /* Cleanup the objcount entry in the proc filesystem. */ diff --git a/net/sctp/output.c b/net/sctp/output.c index a646681f5acd..901764b17aee 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -41,6 +41,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index c04b2eb59186..8c6d379b4bb6 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -46,6 +46,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include /* For struct list_head */ #include @@ -1463,23 +1465,23 @@ static void sctp_check_transmitted(struct sctp_outq *q, /* Display the end of the * current range. */ - SCTP_DEBUG_PRINTK("-%08x", - dbg_last_ack_tsn); + SCTP_DEBUG_PRINTK_CONT("-%08x", + dbg_last_ack_tsn); } /* Start a new range. */ - SCTP_DEBUG_PRINTK(",%08x", tsn); + SCTP_DEBUG_PRINTK_CONT(",%08x", tsn); dbg_ack_tsn = tsn; break; case 1: /* The last TSN was NOT ACKed. */ if (dbg_last_kept_tsn != dbg_kept_tsn) { /* Display the end of current range. */ - SCTP_DEBUG_PRINTK("-%08x", - dbg_last_kept_tsn); + SCTP_DEBUG_PRINTK_CONT("-%08x", + dbg_last_kept_tsn); } - SCTP_DEBUG_PRINTK("\n"); + SCTP_DEBUG_PRINTK_CONT("\n"); /* FALL THROUGH... */ default: @@ -1526,18 +1528,18 @@ static void sctp_check_transmitted(struct sctp_outq *q, break; if (dbg_last_kept_tsn != dbg_kept_tsn) - SCTP_DEBUG_PRINTK("-%08x", - dbg_last_kept_tsn); + SCTP_DEBUG_PRINTK_CONT("-%08x", + dbg_last_kept_tsn); - SCTP_DEBUG_PRINTK(",%08x", tsn); + SCTP_DEBUG_PRINTK_CONT(",%08x", tsn); dbg_kept_tsn = tsn; break; case 0: if (dbg_last_ack_tsn != dbg_ack_tsn) - SCTP_DEBUG_PRINTK("-%08x", - dbg_last_ack_tsn); - SCTP_DEBUG_PRINTK("\n"); + SCTP_DEBUG_PRINTK_CONT("-%08x", + dbg_last_ack_tsn); + SCTP_DEBUG_PRINTK_CONT("\n"); /* FALL THROUGH... */ default: @@ -1556,17 +1558,17 @@ static void sctp_check_transmitted(struct sctp_outq *q, switch (dbg_prt_state) { case 0: if (dbg_last_ack_tsn != dbg_ack_tsn) { - SCTP_DEBUG_PRINTK("-%08x\n", dbg_last_ack_tsn); + SCTP_DEBUG_PRINTK_CONT("-%08x\n", dbg_last_ack_tsn); } else { - SCTP_DEBUG_PRINTK("\n"); + SCTP_DEBUG_PRINTK_CONT("\n"); } break; case 1: if (dbg_last_kept_tsn != dbg_kept_tsn) { - SCTP_DEBUG_PRINTK("-%08x\n", dbg_last_kept_tsn); + SCTP_DEBUG_PRINTK_CONT("-%08x\n", dbg_last_kept_tsn); } else { - SCTP_DEBUG_PRINTK("\n"); + SCTP_DEBUG_PRINTK_CONT("\n"); } } #endif /* SCTP_DEBUG */ diff --git a/net/sctp/probe.c b/net/sctp/probe.c index db3a42b8b349..2e63e9dc010e 100644 --- a/net/sctp/probe.c +++ b/net/sctp/probe.c @@ -22,6 +22,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -192,7 +194,7 @@ static __init int sctpprobe_init(void) if (ret) goto remove_proc; - pr_info("SCTP probe registered (port=%d)\n", port); + pr_info("probe registered (port=%d)\n", port); return 0; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 5027b83f1cc0..f774e657641a 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -46,6 +46,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -707,8 +709,7 @@ static int sctp_ctl_sock_init(void) &init_net); if (err < 0) { - printk(KERN_ERR - "SCTP: Failed to create the SCTP control socket.\n"); + pr_err("Failed to create the SCTP control socket\n"); return err; } return 0; @@ -1206,7 +1207,7 @@ SCTP_STATIC __init int sctp_init(void) __get_free_pages(GFP_ATOMIC, order); } while (!sctp_assoc_hashtable && --order > 0); if (!sctp_assoc_hashtable) { - printk(KERN_ERR "SCTP: Failed association hash alloc.\n"); + pr_err("Failed association hash alloc\n"); status = -ENOMEM; goto err_ahash_alloc; } @@ -1220,7 +1221,7 @@ SCTP_STATIC __init int sctp_init(void) sctp_ep_hashtable = (struct sctp_hashbucket *) kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL); if (!sctp_ep_hashtable) { - printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n"); + pr_err("Failed endpoint_hash alloc\n"); status = -ENOMEM; goto err_ehash_alloc; } @@ -1239,7 +1240,7 @@ SCTP_STATIC __init int sctp_init(void) __get_free_pages(GFP_ATOMIC, order); } while (!sctp_port_hashtable && --order > 0); if (!sctp_port_hashtable) { - printk(KERN_ERR "SCTP: Failed bind hash alloc."); + pr_err("Failed bind hash alloc\n"); status = -ENOMEM; goto err_bhash_alloc; } @@ -1248,8 +1249,7 @@ SCTP_STATIC __init int sctp_init(void) INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain); } - printk(KERN_INFO "SCTP: Hash tables configured " - "(established %d bind %d)\n", + pr_info("Hash tables configured (established %d bind %d)\n", sctp_assoc_hashsize, sctp_port_hashsize); /* Disable ADDIP by default. */ @@ -1290,8 +1290,7 @@ SCTP_STATIC __init int sctp_init(void) /* Initialize the control inode/socket for handling OOTB packets. */ if ((status = sctp_ctl_sock_init())) { - printk (KERN_ERR - "SCTP: Failed to initialize the SCTP control sock.\n"); + pr_err("Failed to initialize the SCTP control sock\n"); goto err_ctl_sock_init; } diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 246f92924658..2cc46f0962ca 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -50,6 +50,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index f5e5e27cac5e..b21b218d564f 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -47,6 +47,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -1146,26 +1148,23 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, case SCTP_DISPOSITION_VIOLATION: if (net_ratelimit()) - printk(KERN_ERR "sctp protocol violation state %d " - "chunkid %d\n", state, subtype.chunk); + pr_err("protocol violation state %d chunkid %d\n", + state, subtype.chunk); break; case SCTP_DISPOSITION_NOT_IMPL: - printk(KERN_WARNING "sctp unimplemented feature in state %d, " - "event_type %d, event_id %d\n", - state, event_type, subtype.chunk); + pr_warn("unimplemented feature in state %d, event_type %d, event_id %d\n", + state, event_type, subtype.chunk); break; case SCTP_DISPOSITION_BUG: - printk(KERN_ERR "sctp bug in state %d, " - "event_type %d, event_id %d\n", + pr_err("bug in state %d, event_type %d, event_id %d\n", state, event_type, subtype.chunk); BUG(); break; default: - printk(KERN_ERR "sctp impossible disposition %d " - "in state %d, event_type %d, event_id %d\n", + pr_err("impossible disposition %d in state %d, event_type %d, event_id %d\n", status, state, event_type, subtype.chunk); BUG(); break; @@ -1679,8 +1678,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, sctp_cmd_send_asconf(asoc); break; default: - printk(KERN_WARNING "Impossible command: %u, %p\n", - cmd->verb, cmd->obj.ptr); + pr_warn("Impossible command: %u, %p\n", + cmd->verb, cmd->obj.ptr); break; } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 24b2cd555637..8b284436be65 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -50,6 +50,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -1138,18 +1140,16 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, if (unlikely(!link)) { if (from_addr.sa.sa_family == AF_INET6) { if (net_ratelimit()) - printk(KERN_WARNING - "%s association %p could not find address %pI6\n", - __func__, - asoc, - &from_addr.v6.sin6_addr); + pr_warn("%s association %p could not find address %pI6\n", + __func__, + asoc, + &from_addr.v6.sin6_addr); } else { if (net_ratelimit()) - printk(KERN_WARNING - "%s association %p could not find address %pI4\n", - __func__, - asoc, - &from_addr.v4.sin_addr.s_addr); + pr_warn("%s association %p could not find address %pI4\n", + __func__, + asoc, + &from_addr.v4.sin_addr.s_addr); } return SCTP_DISPOSITION_DISCARD; } diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 6d9b3aafcc5d..546d4387fb3c 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -46,6 +46,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -66,15 +68,19 @@ static const sctp_sm_table_entry_t bug = { .name = "sctp_sf_bug" }; -#define DO_LOOKUP(_max, _type, _table) \ - if ((event_subtype._type > (_max))) { \ - printk(KERN_WARNING \ - "sctp table %p possible attack:" \ - " event %d exceeds max %d\n", \ - _table, event_subtype._type, _max); \ - return &bug; \ - } \ - return &_table[event_subtype._type][(int)state]; +#define DO_LOOKUP(_max, _type, _table) \ +({ \ + const sctp_sm_table_entry_t *rtn; \ + \ + if ((event_subtype._type > (_max))) { \ + pr_warn("table %p possible attack: event %d exceeds max %d\n", \ + _table, event_subtype._type, _max); \ + rtn = &bug; \ + } else \ + rtn = &_table[event_subtype._type][(int)state]; \ + \ + rtn; \ +}) const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, sctp_state_t state, @@ -83,21 +89,15 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, switch (event_type) { case SCTP_EVENT_T_CHUNK: return sctp_chunk_event_lookup(event_subtype.chunk, state); - break; case SCTP_EVENT_T_TIMEOUT: - DO_LOOKUP(SCTP_EVENT_TIMEOUT_MAX, timeout, - timeout_event_table); - break; - + return DO_LOOKUP(SCTP_EVENT_TIMEOUT_MAX, timeout, + timeout_event_table); case SCTP_EVENT_T_OTHER: - DO_LOOKUP(SCTP_EVENT_OTHER_MAX, other, other_event_table); - break; - + return DO_LOOKUP(SCTP_EVENT_OTHER_MAX, other, + other_event_table); case SCTP_EVENT_T_PRIMITIVE: - DO_LOOKUP(SCTP_EVENT_PRIMITIVE_MAX, primitive, - primitive_event_table); - break; - + return DO_LOOKUP(SCTP_EVENT_PRIMITIVE_MAX, primitive, + primitive_event_table); default: /* Yikes! We got an illegal event type. */ return &bug; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ca44917872d2..f4bec2772351 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -57,6 +57,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -2458,9 +2460,8 @@ static int sctp_setsockopt_delayed_ack(struct sock *sk, if (params.sack_delay == 0 && params.sack_freq == 0) return 0; } else if (optlen == sizeof(struct sctp_assoc_value)) { - printk(KERN_WARNING "SCTP: Use of struct sctp_assoc_value " - "in delayed_ack socket option deprecated\n"); - printk(KERN_WARNING "SCTP: Use struct sctp_sack_info instead\n"); + pr_warn("Use of struct sctp_assoc_value in delayed_ack socket option deprecated\n"); + pr_warn("Use struct sctp_sack_info instead\n"); if (copy_from_user(¶ms, optval, optlen)) return -EFAULT; @@ -2868,10 +2869,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int val; if (optlen == sizeof(int)) { - printk(KERN_WARNING - "SCTP: Use of int in maxseg socket option deprecated\n"); - printk(KERN_WARNING - "SCTP: Use struct sctp_assoc_value instead\n"); + pr_warn("Use of int in maxseg socket option deprecated\n"); + pr_warn("Use struct sctp_assoc_value instead\n"); if (copy_from_user(&val, optval, optlen)) return -EFAULT; params.assoc_id = 0; @@ -3121,10 +3120,8 @@ static int sctp_setsockopt_maxburst(struct sock *sk, int assoc_id = 0; if (optlen == sizeof(int)) { - printk(KERN_WARNING - "SCTP: Use of int in max_burst socket option deprecated\n"); - printk(KERN_WARNING - "SCTP: Use struct sctp_assoc_value instead\n"); + pr_warn("Use of int in max_burst socket option deprecated\n"); + pr_warn("Use struct sctp_assoc_value instead\n"); if (copy_from_user(&val, optval, optlen)) return -EFAULT; } else if (optlen == sizeof(struct sctp_assoc_value)) { @@ -4281,9 +4278,8 @@ static int sctp_getsockopt_delayed_ack(struct sock *sk, int len, if (copy_from_user(¶ms, optval, len)) return -EFAULT; } else if (len == sizeof(struct sctp_assoc_value)) { - printk(KERN_WARNING "SCTP: Use of struct sctp_assoc_value " - "in delayed_ack socket option deprecated\n"); - printk(KERN_WARNING "SCTP: Use struct sctp_sack_info instead\n"); + pr_warn("Use of struct sctp_assoc_value in delayed_ack socket option deprecated\n"); + pr_warn("Use struct sctp_sack_info instead\n"); if (copy_from_user(¶ms, optval, len)) return -EFAULT; } else @@ -4929,10 +4925,8 @@ static int sctp_getsockopt_maxseg(struct sock *sk, int len, struct sctp_association *asoc; if (len == sizeof(int)) { - printk(KERN_WARNING - "SCTP: Use of int in maxseg socket option deprecated\n"); - printk(KERN_WARNING - "SCTP: Use struct sctp_assoc_value instead\n"); + pr_warn("Use of int in maxseg socket option deprecated\n"); + pr_warn("Use struct sctp_assoc_value instead\n"); params.assoc_id = 0; } else if (len >= sizeof(struct sctp_assoc_value)) { len = sizeof(struct sctp_assoc_value); @@ -5023,10 +5017,8 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len, struct sctp_association *asoc; if (len == sizeof(int)) { - printk(KERN_WARNING - "SCTP: Use of int in max_burst socket option deprecated\n"); - printk(KERN_WARNING - "SCTP: Use struct sctp_assoc_value instead\n"); + pr_warn("Use of int in max_burst socket option deprecated\n"); + pr_warn("Use struct sctp_assoc_value instead\n"); params.assoc_id = 0; } else if (len >= sizeof(struct sctp_assoc_value)) { len = sizeof(struct sctp_assoc_value); @@ -5586,8 +5578,7 @@ SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog) tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { if (net_ratelimit()) { - printk(KERN_INFO - "SCTP: failed to load transform for %s: %ld\n", + pr_info("failed to load transform for %s: %ld\n", sctp_hmac_alg, PTR_ERR(tfm)); } return -ENOSYS; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 132046cb82fc..d3ae493d234a 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -48,6 +48,8 @@ * be incorporated into the next SCTP release. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -244,10 +246,9 @@ void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) struct dst_entry *dst; if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) { - printk(KERN_WARNING "%s: Reported pmtu %d too low, " - "using default minimum of %d\n", - __func__, pmtu, - SCTP_DEFAULT_MINSEGMENT); + pr_warn("%s: Reported pmtu %d too low, using default minimum of %d\n", + __func__, pmtu, + SCTP_DEFAULT_MINSEGMENT); /* Use default minimum segment size and disable * pmtu discovery on this transport. */ -- cgit v1.2.3-59-g8ed1b From 53f91dc1f76922375ad7957ef29f48986722532d Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 24 Aug 2010 13:32:58 +0000 Subject: net: use scnprintf() to avoid potential buffer overflow strlcpy() returns the total length of the string they tried to create, so we should not use its return value without any check. scnprintf() returns the number of characters written into @buf not including the trailing '\0', so use it instead here. Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- net/ethernet/eth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 215c83986a9d..85e7b4551326 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -367,7 +367,7 @@ struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count) EXPORT_SYMBOL(alloc_etherdev_mq); static size_t _format_mac_addr(char *buf, int buflen, - const unsigned char *addr, int len) + const unsigned char *addr, int len) { int i; char *cp = buf; @@ -376,7 +376,7 @@ static size_t _format_mac_addr(char *buf, int buflen, cp += scnprintf(cp, buflen - (cp - buf), "%02x", addr[i]); if (i == len - 1) break; - cp += strlcpy(cp, ":", buflen - (cp - buf)); + cp += scnprintf(cp, buflen - (cp - buf), ":"); } return cp - buf; } @@ -386,7 +386,7 @@ ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len) size_t l; l = _format_mac_addr(buf, PAGE_SIZE, addr, len); - l += strlcpy(buf + l, "\n", PAGE_SIZE - l); + l += scnprintf(buf + l, PAGE_SIZE - l, "\n"); return ((ssize_t) l); } EXPORT_SYMBOL(sysfs_format_mac); -- cgit v1.2.3-59-g8ed1b From 8cfdce080722101a7fd2a1eff9763ca4008ec626 Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Thu, 26 Aug 2010 14:02:41 +0000 Subject: qlcnic: Fix missing error codes In the original code, the error codes returned from some of the functions are not caught and sent up the caller chain. Fixed it here. Signed-off-by: Sony Chacko Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 630a077e4547..1b8f67dab9b8 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -967,7 +967,8 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter) if (load_fw_file) qlcnic_request_firmware(adapter); else { - if (qlcnic_check_flash_fw_ver(adapter)) + err = qlcnic_check_flash_fw_ver(adapter); + if (err) goto err_out; adapter->fw_type = QLCNIC_FLASH_ROMIMAGE; @@ -998,9 +999,11 @@ set_dev_ready: QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); qlcnic_idc_debug_info(adapter, 1); - if (qlcnic_set_default_offload_settings(adapter)) + err = qlcnic_set_default_offload_settings(adapter); + if (err) goto err_out; - if (qlcnic_reset_npar_config(adapter)) + err = qlcnic_reset_npar_config(adapter); + if (err) goto err_out; qlcnic_dev_set_npar_ready(adapter); qlcnic_check_options(adapter); @@ -1515,7 +1518,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (qlcnic_read_mac_addr(adapter)) dev_warn(&pdev->dev, "failed to read mac addr\n"); - if (qlcnic_setup_idc_param(adapter)) + err = qlcnic_setup_idc_param(adapter); + if (err) goto err_out_iounmap; err = adapter->nic_ops->start_firmware(adapter); -- cgit v1.2.3-59-g8ed1b From 0866d96da02cccc3ca837d0d71687aba962b3f2f Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Thu, 26 Aug 2010 14:02:52 +0000 Subject: qlcnic: Fix driver load issue in FW hang If there is a FW hang when the driver loads, it can not determine the FW operational mode. Fix it by checking the FW state first before issuing any FW commands to determine its capabilities and thereby detecting driver operational mode. Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 1 + drivers/net/qlcnic/qlcnic_hdr.h | 2 +- drivers/net/qlcnic/qlcnic_init.c | 16 ++++-- drivers/net/qlcnic/qlcnic_main.c | 116 +++++++++++++++++++++------------------ 4 files changed, 75 insertions(+), 60 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index d15de63ed0bb..0a537044d7da 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -902,6 +902,7 @@ struct qlcnic_mac_req { #define QLCNIC_BRIDGE_ENABLED 0X10 #define QLCNIC_DIAG_ENABLED 0x20 #define QLCNIC_ESWITCH_ENABLED 0x40 +#define QLCNIC_ADAPTER_INITIALIZED 0x80 #define QLCNIC_TAGGING_ENABLED 0x100 #define QLCNIC_MACSPOOF 0x200 #define QLCNIC_IS_MSI_FAMILY(adapter) \ diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h index 219de9f4496f..bce1b1d541b7 100644 --- a/drivers/net/qlcnic/qlcnic_hdr.h +++ b/drivers/net/qlcnic/qlcnic_hdr.h @@ -748,7 +748,7 @@ enum { #define QLCNIC_RESET_TIMEOUT_SECS 10 #define QLCNIC_INIT_TIMEOUT_SECS 30 #define QLCNIC_HEARTBEAT_PERIOD_MSECS 200 -#define QLCNIC_HEARTBEAT_RETRY_COUNT 30 +#define QLCNIC_HEARTBEAT_RETRY_COUNT 45 #define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC))) #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index df91b754bb70..eb8256bec516 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -547,7 +547,7 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter) int qlcnic_check_fw_status(struct qlcnic_adapter *adapter) { - u32 heartbit, ret = -EIO; + u32 heartbit, cmdpeg_state, ret = -EIO; int retries = QLCNIC_HEARTBEAT_RETRY_COUNT; adapter->heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); @@ -555,10 +555,16 @@ qlcnic_check_fw_status(struct qlcnic_adapter *adapter) msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS); heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); if (heartbit != adapter->heartbit) { - /* Complete firmware handshake */ - QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); - ret = QLCNIC_RCODE_SUCCESS; - break; + cmdpeg_state = QLCRD32(adapter, CRB_CMDPEG_STATE); + /* Ensure peg states are initialized */ + if (cmdpeg_state == PHAN_INITIALIZE_COMPLETE || + cmdpeg_state == PHAN_INITIALIZE_ACK) { + /* Complete firmware handshake */ + QLCWR32(adapter, CRB_CMDPEG_STATE, + PHAN_INITIALIZE_ACK); + ret = QLCNIC_RCODE_SUCCESS; + break; + } } } while (--retries); diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 1b8f67dab9b8..6999d5aaa157 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -566,12 +566,11 @@ err_lock: return ret; } -static u32 -qlcnic_get_driver_mode(struct qlcnic_adapter *adapter) +static void +qlcnic_check_vf(struct qlcnic_adapter *adapter) { void __iomem *msix_base_addr; void __iomem *priv_op; - struct qlcnic_info nic_info; u32 func; u32 msix_base; u32 op_mode, priv_level; @@ -586,20 +585,6 @@ qlcnic_get_driver_mode(struct qlcnic_adapter *adapter) func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE; adapter->ahw.pci_func = func; - if (!qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func)) { - adapter->capabilities = nic_info.capabilities; - - if (adapter->capabilities & BIT_6) - adapter->flags |= QLCNIC_ESWITCH_ENABLED; - else - adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; - } - - if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) { - adapter->nic_ops = &qlcnic_ops; - return adapter->fw_hal_version; - } - /* Determine function privilege level */ priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE; op_mode = readl(priv_op); @@ -608,37 +593,14 @@ qlcnic_get_driver_mode(struct qlcnic_adapter *adapter) else priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func); - switch (priv_level) { - case QLCNIC_MGMT_FUNC: - adapter->op_mode = QLCNIC_MGMT_FUNC; - adapter->nic_ops = &qlcnic_ops; - qlcnic_init_pci_info(adapter); - /* Set privilege level for other functions */ - qlcnic_set_function_modes(adapter); - dev_info(&adapter->pdev->dev, - "HAL Version: %d, Management function\n", - adapter->fw_hal_version); - break; - case QLCNIC_PRIV_FUNC: - adapter->op_mode = QLCNIC_PRIV_FUNC; - dev_info(&adapter->pdev->dev, - "HAL Version: %d, Privileged function\n", - adapter->fw_hal_version); - adapter->nic_ops = &qlcnic_ops; - break; - case QLCNIC_NON_PRIV_FUNC: + if (priv_level == QLCNIC_NON_PRIV_FUNC) { adapter->op_mode = QLCNIC_NON_PRIV_FUNC; dev_info(&adapter->pdev->dev, "HAL Version: %d Non Privileged function\n", adapter->fw_hal_version); adapter->nic_ops = &qlcnic_vf_ops; - break; - default: - dev_info(&adapter->pdev->dev, "Unknown function mode: %d\n", - priv_level); - return 0; - } - return adapter->fw_hal_version; + } else + adapter->nic_ops = &qlcnic_ops; } static int @@ -671,10 +633,7 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter) adapter->ahw.pci_base0 = mem_ptr0; adapter->ahw.pci_len0 = pci_len0; - if (!qlcnic_get_driver_mode(adapter)) { - iounmap(adapter->ahw.pci_base0); - return -EIO; - } + qlcnic_check_vf(adapter); adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter, QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(adapter->ahw.pci_func))); @@ -719,6 +678,9 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build); + if (!(adapter->flags & QLCNIC_ADAPTER_INITIALIZED)) + if (qlcnic_read_mac_addr(adapter)) + dev_warn(&pdev->dev, "failed to read mac addr\n"); if (adapter->portnum == 0) { get_brd_name(adapter, brd_name); @@ -836,6 +798,51 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, netdev->vlan_features = (features & vlan_features); } +static int +qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter) +{ + void __iomem *priv_op; + u32 op_mode, priv_level; + int err = 0; + + if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED) + return 0; + + priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE; + op_mode = readl(priv_op); + priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func); + + if (op_mode == QLC_DEV_DRV_DEFAULT) + priv_level = QLCNIC_MGMT_FUNC; + else + priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func); + + if (adapter->capabilities & BIT_6) { + adapter->flags |= QLCNIC_ESWITCH_ENABLED; + if (priv_level == QLCNIC_MGMT_FUNC) { + adapter->op_mode = QLCNIC_MGMT_FUNC; + err = qlcnic_init_pci_info(adapter); + if (err) + return err; + /* Set privilege level for other functions */ + qlcnic_set_function_modes(adapter); + dev_info(&adapter->pdev->dev, + "HAL Version: %d, Management function\n", + adapter->fw_hal_version); + } else if (priv_level == QLCNIC_PRIV_FUNC) { + adapter->op_mode = QLCNIC_PRIV_FUNC; + dev_info(&adapter->pdev->dev, + "HAL Version: %d, Privileged function\n", + adapter->fw_hal_version); + } + } else + adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; + + adapter->flags |= QLCNIC_ADAPTER_INITIALIZED; + + return err; +} + static int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) { @@ -1005,8 +1012,14 @@ set_dev_ready: err = qlcnic_reset_npar_config(adapter); if (err) goto err_out; - qlcnic_dev_set_npar_ready(adapter); qlcnic_check_options(adapter); + err = qlcnic_check_eswitch_mode(adapter); + if (err) { + dev_err(&adapter->pdev->dev, + "Memory allocation failed for eswitch\n"); + goto err_out; + } + qlcnic_dev_set_npar_ready(adapter); adapter->need_fw_reset = 0; qlcnic_release_firmware(adapter); @@ -1015,6 +1028,7 @@ set_dev_ready: err_out: QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED); dev_err(&adapter->pdev->dev, "Device state set to failed\n"); + qlcnic_release_firmware(adapter); return err; } @@ -1419,9 +1433,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, netdev->features |= NETIF_F_LRO; netdev->irq = adapter->msix_entries[0].vector; - if (qlcnic_read_mac_addr(adapter)) - dev_warn(&pdev->dev, "failed to read mac addr\n"); - netif_carrier_off(netdev); netif_stop_queue(netdev); @@ -1515,9 +1526,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_iounmap; } - if (qlcnic_read_mac_addr(adapter)) - dev_warn(&pdev->dev, "failed to read mac addr\n"); - err = qlcnic_setup_idc_param(adapter); if (err) goto err_out_iounmap; -- cgit v1.2.3-59-g8ed1b From e132d8d3d2b4df0895fe73c9cfad53b3a5329edf Mon Sep 17 00:00:00 2001 From: Sritej Velaga Date: Thu, 26 Aug 2010 14:03:05 +0000 Subject: qlcnic: PCI ID addition Added PCI ID to board info. Signed-off-by: Sritej Velaga Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 0a537044d7da..1f5c10bc9376 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -1326,6 +1326,8 @@ static const struct qlcnic_brdinfo qlcnic_boards[] = { "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"}, {0x1077, 0x8020, 0x1077, 0x20f, "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"}, + {0x1077, 0x8020, 0x103c, 0x3733, + "NC523SFP 10Gb 2-port Flex-10 Server Adapter"}, {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"}, }; -- cgit v1.2.3-59-g8ed1b From 250ad8f55c06eb866cfb57f8d3ea6ff961a7d1d7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 26 Aug 2010 20:32:02 -0700 Subject: stmmac: Make time functionality depend upon RTC_HCTOSYS_DEVICE Based upon a report by Stephen Rothwell. Signed-off-by: David S. Miller --- drivers/net/stmmac/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/stmmac/Kconfig b/drivers/net/stmmac/Kconfig index 643968098afd..3c2af7c6a39b 100644 --- a/drivers/net/stmmac/Kconfig +++ b/drivers/net/stmmac/Kconfig @@ -32,6 +32,7 @@ config STMMAC_DUAL_MAC config STMMAC_TIMER bool "STMMAC Timer optimisation" default n + depends on RTC_HCTOSYS_DEVICE help Use an external timer for mitigating the number of network interrupts. Currently, for SH architectures, it is possible -- cgit v1.2.3-59-g8ed1b From 40d0802b3eb47d57e2d57a5244a18cbbe9632e13 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 26 Aug 2010 22:03:08 -0700 Subject: gro: __napi_gro_receive() optimizations compare_ether_header() can have a special implementation on 64 bit arches if CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is defined. __napi_gro_receive() and vlan_gro_common() can avoid a conditional branch to perform device match. On x86_64, __napi_gro_receive() has now 38 instructions instead of 53 As gcc-4.4.3 still choose to not inline it, add inline keyword to this performance critical function. Signed-off-by: Eric Dumazet CC: Herbert Xu Signed-off-by: David S. Miller --- include/linux/etherdevice.h | 18 +++++++++++++++++- net/8021q/vlan_core.c | 9 ++++++--- net/core/dev.c | 10 ++++++---- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index 2308fbb4523a..fb6aa6070921 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -237,13 +237,29 @@ static inline bool is_etherdev_addr(const struct net_device *dev, * entry points. */ -static inline int compare_ether_header(const void *a, const void *b) +static inline unsigned long compare_ether_header(const void *a, const void *b) { +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 + unsigned long fold; + + /* + * We want to compare 14 bytes: + * [a0 ... a13] ^ [b0 ... b13] + * Use two long XOR, ORed together, with an overlap of two bytes. + * [a0 a1 a2 a3 a4 a5 a6 a7 ] ^ [b0 b1 b2 b3 b4 b5 b6 b7 ] | + * [a6 a7 a8 a9 a10 a11 a12 a13] ^ [b6 b7 b8 b9 b10 b11 b12 b13] + * This means the [a6 a7] ^ [b6 b7] part is done two times. + */ + fold = *(unsigned long *)a ^ *(unsigned long *)b; + fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6); + return fold; +#else u32 *a32 = (u32 *)((u8 *)a + 2); u32 *b32 = (u32 *)((u8 *)b + 2); return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); +#endif } #endif /* _LINUX_ETHERDEVICE_H */ diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 07eeb5b99dce..3438c01bbacf 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -105,9 +105,12 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, goto drop; for (p = napi->gro_list; p; p = p->next) { - NAPI_GRO_CB(p)->same_flow = - p->dev == skb->dev && !compare_ether_header( - skb_mac_header(p), skb_gro_mac_header(skb)); + unsigned long diffs; + + diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev; + diffs |= compare_ether_header(skb_mac_header(p), + skb_gro_mac_header(skb)); + NAPI_GRO_CB(p)->same_flow = !diffs; NAPI_GRO_CB(p)->flush = 0; } diff --git a/net/core/dev.c b/net/core/dev.c index 859e30ff044a..63bd20a75929 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3169,16 +3169,18 @@ normal: } EXPORT_SYMBOL(dev_gro_receive); -static gro_result_t +static inline gro_result_t __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { struct sk_buff *p; for (p = napi->gro_list; p; p = p->next) { - NAPI_GRO_CB(p)->same_flow = - (p->dev == skb->dev) && - !compare_ether_header(skb_mac_header(p), + unsigned long diffs; + + diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev; + diffs |= compare_ether_header(skb_mac_header(p), skb_gro_mac_header(skb)); + NAPI_GRO_CB(p)->same_flow = !diffs; NAPI_GRO_CB(p)->flush = 0; } -- cgit v1.2.3-59-g8ed1b From 0fdf4d096102464e290d5ccaee8ad0cee7bd9e8a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 26 Aug 2010 22:03:53 -0700 Subject: bnx2x: fix wrong return from bnx2x_trylock_hw_lock bnx2x_trylock_hw_lock() returns a bool : true if succeeded to acquire the lock. false in case of error. -EINVAL is not an acceptable value, since its promoted to true. Signed-off-by: Eric Dumazet Acked-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 05a08d1a09f3..7fb9a61a73c7 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -781,7 +781,7 @@ static bool bnx2x_trylock_hw_lock(struct bnx2x *bp, u32 resource) DP(NETIF_MSG_HW, "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n", resource, HW_LOCK_MAX_RESOURCE_VALUE); - return -EINVAL; + return false; } if (func <= 5) -- cgit v1.2.3-59-g8ed1b From e4b6b74ffd32d114227a5dcfe814e2cecd80554b Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Thu, 26 Aug 2010 16:07:23 +0100 Subject: ARM: S3C64XX: Fix fallthrough bug in i2sv3 gpio configuration, improve logging If the platform device id is 1, the code will fallthrough the case and incorrectly return -EINVAL. Add a break to avoid fallthrough. Make logging slightly more verbose by including the device id. This fixes an issue only present in multi-component. Signed-off-by: Dimitris Papastamos Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- arch/arm/mach-s3c64xx/dev-audio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c index f0942585b9c1..3838335f125b 100644 --- a/arch/arm/mach-s3c64xx/dev-audio.c +++ b/arch/arm/mach-s3c64xx/dev-audio.c @@ -43,8 +43,10 @@ static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev) s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK); s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI); s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0); + break; default: - printk(KERN_DEBUG "Invalid I2S Controller number!"); + printk(KERN_DEBUG "Invalid I2S Controller number: %d\n", + pdev->id); return -EINVAL; } @@ -184,7 +186,8 @@ static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev) s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_PCM1_SOUT); break; default: - printk(KERN_DEBUG "Invalid PCM Controller number!"); + printk(KERN_DEBUG "Invalid PCM Controller number: %d\n", + pdev->id); return -EINVAL; } -- cgit v1.2.3-59-g8ed1b From 246ed355221076884d225f9d8a4c30a048be8162 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:32 +0200 Subject: iwlwifi: initial contextification In order to support multiple interfaces, we must move a lot of data into per-context structures so we can use the contexts the device offers. To start with, this makes a lot of code context-aware, more changes will move more things into the context structure. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 3 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 53 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 46 ++-- drivers/net/wireless/iwlwifi/iwl-5000.c | 15 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 15 +- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 12 +- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 27 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 26 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 172 +++++++----- drivers/net/wireless/iwlwifi/iwl-agn.h | 3 +- drivers/net/wireless/iwlwifi/iwl-core.c | 391 ++++++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-core.h | 38 ++- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 7 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 62 ++++- drivers/net/wireless/iwlwifi/iwl-rx.c | 9 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 9 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 6 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 111 ++++---- 19 files changed, 611 insertions(+), 400 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 8e84a08ff951..08f53f869c18 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -949,7 +949,8 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) switch (priv->band) { case IEEE80211_BAND_2GHZ: /* TODO: this always does G, not a regression */ - if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) { + if (priv->contexts[IWL_RXON_CTX_BSS].active.flags & + RXON_FLG_TGG_PROTECT_MSK) { rs_sta->tgg = 1; rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot; } else diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8ccfcd08218d..f4aa229986ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -245,7 +245,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate) break; case IEEE80211_BAND_2GHZ: if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && - iwl_is_associated(priv)) { + iwl_is_associated(priv, IWL_RXON_CTX_BSS)) { if (rate == IWL_RATE_11M_INDEX) next_rate = IWL_RATE_5M_INDEX; } @@ -1439,17 +1439,18 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv) int rate_idx, i; const struct iwl_channel_info *ch_info = NULL; struct iwl3945_txpowertable_cmd txpower = { - .channel = priv->active_rxon.channel, + .channel = priv->contexts[IWL_RXON_CTX_BSS].active.channel, }; + u16 chan; + + chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel); txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1; - ch_info = iwl_get_channel_info(priv, - priv->band, - le16_to_cpu(priv->active_rxon.channel)); + ch_info = iwl_get_channel_info(priv, priv->band, chan); if (!ch_info) { IWL_ERR(priv, "Failed to get channel info for channel %d [%d]\n", - le16_to_cpu(priv->active_rxon.channel), priv->band); + chan, priv->band); return -EINVAL; } @@ -1710,7 +1711,8 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) return 0; } -static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) +static int iwl3945_send_rxon_assoc(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { int rc = 0; struct iwl_rx_packet *pkt; @@ -1721,8 +1723,8 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) .flags = CMD_WANT_SKB, .data = &rxon_assoc, }; - const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; + const struct iwl_rxon_cmd *rxon1 = &ctx->staging; + const struct iwl_rxon_cmd *rxon2 = &ctx->active; if ((rxon1->flags == rxon2->flags) && (rxon1->filter_flags == rxon2->filter_flags) && @@ -1732,10 +1734,10 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) return 0; } - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; + rxon_assoc.flags = ctx->staging.flags; + rxon_assoc.filter_flags = ctx->staging.filter_flags; + rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; rxon_assoc.reserved = 0; rc = iwl_send_cmd_sync(priv, &cmd); @@ -1761,14 +1763,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) * function correctly transitions out of the RXON_ASSOC_MSK state if * a HW tune is required based on the RXON structure changes. */ -static int iwl3945_commit_rxon(struct iwl_priv *priv) +static int iwl3945_commit_rxon(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { /* cast away the const for active_rxon in this function */ - struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; - struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; + struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active; + struct iwl3945_rxon_cmd *staging_rxon = (void *)&ctx->staging; int rc = 0; - bool new_assoc = - !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); + bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK); if (!iwl_is_alive(priv)) return -1; @@ -1781,7 +1783,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); staging_rxon->flags |= iwl3945_get_antenna_flags(priv); - rc = iwl_check_rxon_cmd(priv); + rc = iwl_check_rxon_cmd(priv, ctx); if (rc) { IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); return -EINVAL; @@ -1790,8 +1792,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) /* If we don't need to send a full RXON, we can use * iwl3945_rxon_assoc_cmd which is used to reconfigure filter * and other flags for the current radio configuration. */ - if (!iwl_full_rxon_required(priv)) { - rc = iwl_send_rxon_assoc(priv); + if (!iwl_full_rxon_required(priv, &priv->contexts[IWL_RXON_CTX_BSS])) { + rc = iwl_send_rxon_assoc(priv, + &priv->contexts[IWL_RXON_CTX_BSS]); if (rc) { IWL_ERR(priv, "Error setting RXON_ASSOC " "configuration (%d).\n", rc); @@ -1807,7 +1810,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) * an RXON_ASSOC and the new config wants the associated mask enabled, * we must clear the associated from the active configuration * before we apply the new config */ - if (iwl_is_associated(priv) && new_assoc) { + if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && new_assoc) { IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -1819,7 +1822,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) active_rxon->reserved5 = 0; rc = iwl_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl3945_rxon_cmd), - &priv->active_rxon); + &priv->contexts[IWL_RXON_CTX_BSS].active); /* If the mask clearing failed then we set * active_rxon back to what it was previously */ @@ -1848,7 +1851,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) staging_rxon->reserved4 = 0; staging_rxon->reserved5 = 0; - iwl_set_rxon_hwcrypto(priv, !iwl3945_mod_params.sw_crypto); + iwl_set_rxon_hwcrypto(priv, ctx, !iwl3945_mod_params.sw_crypto); /* Apply the new configuration */ rc = iwl_send_cmd_pdu(priv, REPLY_RXON, @@ -2366,7 +2369,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) * 1M CCK rates */ if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && - iwl_is_associated(priv)) { + iwl_is_associated(priv, IWL_RXON_CTX_BSS)) { index = IWL_FIRST_CCK_RATE; for (i = IWL_RATE_6M_INDEX_TABLE; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index f0a47f42d4b8..82f32305f50e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -347,7 +347,7 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv) struct iwl_chain_noise_data *data = &(priv->chain_noise_data); if ((data->state == IWL_CHAIN_NOISE_ALIVE) && - iwl_is_associated(priv)) { + iwl_is_any_associated(priv)) { struct iwl_calib_diff_gain_cmd cmd; /* clear data for chain noise calibration algorithm */ @@ -1374,6 +1374,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv) u8 band = 0; bool is_ht40 = false; u8 ctrl_chan_high = 0; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; if (test_bit(STATUS_SCANNING, &priv->status)) { /* If this gets hit a lot, switch it to a BUG() and catch @@ -1385,17 +1386,16 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv) band = priv->band == IEEE80211_BAND_2GHZ; - is_ht40 = is_ht40_channel(priv->active_rxon.flags); + is_ht40 = is_ht40_channel(ctx->active.flags); - if (is_ht40 && - (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) + if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) ctrl_chan_high = 1; cmd.band = band; - cmd.channel = priv->active_rxon.channel; + cmd.channel = ctx->active.channel; ret = iwl4965_fill_txpower_tbl(priv, band, - le16_to_cpu(priv->active_rxon.channel), + le16_to_cpu(ctx->active.channel), is_ht40, ctrl_chan_high, &cmd.tx_power); if (ret) goto out; @@ -1406,12 +1406,13 @@ out: return ret; } -static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) +static int iwl4965_send_rxon_assoc(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { int ret = 0; struct iwl4965_rxon_assoc_cmd rxon_assoc; - const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; + const struct iwl_rxon_cmd *rxon1 = &ctx->staging; + const struct iwl_rxon_cmd *rxon2 = &ctx->active; if ((rxon1->flags == rxon2->flags) && (rxon1->filter_flags == rxon2->filter_flags) && @@ -1426,16 +1427,16 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) return 0; } - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; + rxon_assoc.flags = ctx->staging.flags; + rxon_assoc.filter_flags = ctx->staging.filter_flags; + rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; rxon_assoc.reserved = 0; rxon_assoc.ofdm_ht_single_stream_basic_rates = - priv->staging_rxon.ofdm_ht_single_stream_basic_rates; + ctx->staging.ofdm_ht_single_stream_basic_rates; rxon_assoc.ofdm_ht_dual_stream_basic_rates = - priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; - rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; + ctx->staging.ofdm_ht_dual_stream_basic_rates; + rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain; ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, sizeof(rxon_assoc), &rxon_assoc, NULL); @@ -1448,6 +1449,7 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) static int iwl4965_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_channel_switch *ch_switch) { + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; int rc; u8 band = 0; bool is_ht40 = false; @@ -1458,22 +1460,22 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 ch; u32 tsf_low; u8 switch_count; - u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); + u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); struct ieee80211_vif *vif = priv->vif; band = priv->band == IEEE80211_BAND_2GHZ; - is_ht40 = is_ht40_channel(priv->staging_rxon.flags); + is_ht40 = is_ht40_channel(ctx->staging.flags); if (is_ht40 && - (priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) + (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) ctrl_chan_high = 1; cmd.band = band; cmd.expect_beacon = 0; ch = ch_switch->channel->hw_value; cmd.channel = cpu_to_le16(ch); - cmd.rxon_flags = priv->staging_rxon.flags; - cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; + cmd.rxon_flags = ctx->staging.flags; + cmd.rxon_filter_flags = ctx->staging.filter_flags; switch_count = ch_switch->count; tsf_low = ch_switch->timestamp & 0x0ffffffff; /* @@ -1508,7 +1510,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, cmd.expect_beacon = is_channel_radar(ch_info); else { IWL_ERR(priv, "invalid channel switch from %u to %u\n", - priv->active_rxon.channel, ch); + ctx->active.channel, ch); return -EFAULT; } diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 013f3dae69f1..8536f19d7dcc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -275,13 +275,18 @@ static void iwl5150_temperature(struct iwl_priv *priv) static int iwl5000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_channel_switch *ch_switch) { + /* + * MULTI-FIXME + * See iwl_mac_channel_switch. + */ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl5000_channel_switch_cmd cmd; const struct iwl_channel_info *ch_info; u32 switch_time_in_usec, ucode_switch_time; u16 ch; u32 tsf_low; u8 switch_count; - u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); + u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); struct ieee80211_vif *vif = priv->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, @@ -293,10 +298,10 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, cmd.band = priv->band == IEEE80211_BAND_2GHZ; ch = ch_switch->channel->hw_value; IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", - priv->active_rxon.channel, ch); + ctx->active.channel, ch); cmd.channel = cpu_to_le16(ch); - cmd.rxon_flags = priv->staging_rxon.flags; - cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; + cmd.rxon_flags = ctx->staging.flags; + cmd.rxon_filter_flags = ctx->staging.filter_flags; switch_count = ch_switch->count; tsf_low = ch_switch->timestamp & 0x0ffffffff; /* @@ -331,7 +336,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, cmd.expect_beacon = is_channel_radar(ch_info); else { IWL_ERR(priv, "invalid channel switch from %u to %u\n", - priv->active_rxon.channel, ch); + ctx->active.channel, ch); return -EFAULT; } priv->switch_rxon.channel = cmd.channel; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index fc9344b873ba..bf1fe25fae73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -198,13 +198,18 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) static int iwl6000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_channel_switch *ch_switch) { + /* + * MULTI-FIXME + * See iwl_mac_channel_switch. + */ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl6000_channel_switch_cmd cmd; const struct iwl_channel_info *ch_info; u32 switch_time_in_usec, ucode_switch_time; u16 ch; u32 tsf_low; u8 switch_count; - u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); + u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); struct ieee80211_vif *vif = priv->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, @@ -216,10 +221,10 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, cmd.band = priv->band == IEEE80211_BAND_2GHZ; ch = ch_switch->channel->hw_value; IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", - priv->active_rxon.channel, ch); + ctx->active.channel, ch); cmd.channel = cpu_to_le16(ch); - cmd.rxon_flags = priv->staging_rxon.flags; - cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; + cmd.rxon_flags = ctx->staging.flags; + cmd.rxon_filter_flags = ctx->staging.filter_flags; switch_count = ch_switch->count; tsf_low = ch_switch->timestamp & 0x0ffffffff; /* @@ -254,7 +259,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, cmd.expect_beacon = is_channel_radar(ch_info); else { IWL_ERR(priv, "invalid channel switch from %u to %u\n", - priv->active_rxon.channel, ch); + ctx->active.channel, ch); return -EFAULT; } priv->switch_rxon.channel = cmd.channel; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 156b125dba71..84ad62958535 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -625,7 +625,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp) data = &(priv->sensitivity_data); - if (!iwl_is_associated(priv)) { + if (!iwl_is_any_associated(priv)) { IWL_DEBUG_CALIB(priv, "<< - not associated\n"); return; } @@ -763,6 +763,12 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) unsigned long flags; struct statistics_rx_non_phy *rx_info; u8 first_chain; + /* + * MULTI-FIXME: + * When we support multiple interfaces on different channels, + * this must be modified/fixed. + */ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; if (priv->disable_chain_noise_cal) return; @@ -793,8 +799,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) return; } - rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK); - rxon_chnum = le16_to_cpu(priv->staging_rxon.channel); + rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK); + rxon_chnum = le16_to_cpu(ctx->staging.channel); if (priv->cfg->bt_statistics) { stat_band24 = !!(((struct iwl_bt_notif_statistics *) stat_resp)->flag & diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 84fe06adcef4..3e5069943dde 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -37,12 +37,13 @@ #include "iwl-io.h" #include "iwl-agn.h" -int iwlagn_send_rxon_assoc(struct iwl_priv *priv) +int iwlagn_send_rxon_assoc(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { int ret = 0; struct iwl5000_rxon_assoc_cmd rxon_assoc; - const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; + const struct iwl_rxon_cmd *rxon1 = &ctx->staging; + const struct iwl_rxon_cmd *rxon2 = &ctx->active; if ((rxon1->flags == rxon2->flags) && (rxon1->filter_flags == rxon2->filter_flags) && @@ -60,21 +61,21 @@ int iwlagn_send_rxon_assoc(struct iwl_priv *priv) return 0; } - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; + rxon_assoc.flags = ctx->staging.flags; + rxon_assoc.filter_flags = ctx->staging.filter_flags; + rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; rxon_assoc.reserved1 = 0; rxon_assoc.reserved2 = 0; rxon_assoc.reserved3 = 0; rxon_assoc.ofdm_ht_single_stream_basic_rates = - priv->staging_rxon.ofdm_ht_single_stream_basic_rates; + ctx->staging.ofdm_ht_single_stream_basic_rates; rxon_assoc.ofdm_ht_dual_stream_basic_rates = - priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; - rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; + ctx->staging.ofdm_ht_dual_stream_basic_rates; + rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain; rxon_assoc.ofdm_ht_triple_stream_basic_rates = - priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; - rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; + ctx->staging.ofdm_ht_triple_stream_basic_rates; + rxon_assoc.acquisition_data = ctx->staging.acquisition_data; ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, sizeof(rxon_assoc), &rxon_assoc, NULL); @@ -184,7 +185,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) int ret; if ((data->state == IWL_CHAIN_NOISE_ALIVE) && - iwl_is_associated(priv)) { + iwl_is_any_associated(priv)) { struct iwl_calib_chain_noise_reset_cmd cmd; /* clear data for chain noise calibration algorithm */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index a9e69a6213f4..531a7dc3dc72 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1232,7 +1232,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; scan->quiet_time = IWL_ACTIVE_QUIET_TIME; - if (iwl_is_associated(priv)) { + if (iwl_is_any_associated(priv)) { u16 interval = 0; u32 extra; u32 suspend_time = 100; @@ -1289,7 +1289,9 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) switch (priv->scan_band) { case IEEE80211_BAND_2GHZ: scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; - chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK) + chan_mod = le32_to_cpu( + priv->contexts[IWL_RXON_CTX_BSS].active.flags & + RXON_FLG_CHANNEL_MODE_MSK) >> RXON_FLG_CHANNEL_MODE_POS; if (chan_mod == CHANNEL_MODE_PURE_40) { rate = IWL_RATE_6M_PLCP; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 30298ea56a24..07b2c6cadf51 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -416,18 +416,26 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) /* stop ct_kill_waiting_tm timer */ del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); if (changed) { - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - if (tt->state >= IWL_TI_1) { /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ tt->tt_power_mode = IWL_POWER_INDEX_5; - if (!iwl_ht_enabled(priv)) - /* disable HT */ - rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | - RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | - RXON_FLG_HT40_PROT_MSK | - RXON_FLG_HT_PROT_MSK); - else { + + if (!iwl_ht_enabled(priv)) { + struct iwl_rxon_context *ctx; + + for_each_context(priv, ctx) { + struct iwl_rxon_cmd *rxon; + + rxon = &ctx->staging; + + /* disable HT */ + rxon->flags &= ~( + RXON_FLG_CHANNEL_MODE_MSK | + RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | + RXON_FLG_HT40_PROT_MSK | + RXON_FLG_HT_PROT_MSK); + } + } else { /* check HT capability and set * according to the system HT capability * in case get disabled before */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5e0d0d527bf0..e073069a44c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -98,21 +98,21 @@ static bool iwlagn_bt_ch_announce = 1; * function correctly transitions out of the RXON_ASSOC_MSK state if * a HW tune is required based on the RXON structure changes. */ -int iwl_commit_rxon(struct iwl_priv *priv) +int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { /* cast away the const for active_rxon in this function */ - struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon; + struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active; int ret; bool new_assoc = - !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); + !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); if (!iwl_is_alive(priv)) return -EBUSY; /* always get timestamp with Rx frame */ - priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; + ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; - ret = iwl_check_rxon_cmd(priv); + ret = iwl_check_rxon_cmd(priv, ctx); if (ret) { IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); return -EINVAL; @@ -123,7 +123,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) * abort any previous channel switch if still in process */ if (priv->switch_rxon.switch_in_progress && - (priv->switch_rxon.channel != priv->staging_rxon.channel)) { + (priv->switch_rxon.channel != ctx->staging.channel)) { IWL_DEBUG_11H(priv, "abort channel switch on %d\n", le16_to_cpu(priv->switch_rxon.channel)); iwl_chswitch_done(priv, false); @@ -132,15 +132,15 @@ int iwl_commit_rxon(struct iwl_priv *priv) /* If we don't need to send a full RXON, we can use * iwl_rxon_assoc_cmd which is used to reconfigure filter * and other flags for the current radio configuration. */ - if (!iwl_full_rxon_required(priv)) { - ret = iwl_send_rxon_assoc(priv); + if (!iwl_full_rxon_required(priv, ctx)) { + ret = iwl_send_rxon_assoc(priv, ctx); if (ret) { IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); return ret; } - memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); - iwl_print_rx_config_cmd(priv); + memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); + iwl_print_rx_config_cmd(priv, ctx); return 0; } @@ -148,13 +148,13 @@ int iwl_commit_rxon(struct iwl_priv *priv) * an RXON_ASSOC and the new config wants the associated mask enabled, * we must clear the associated from the active configuration * before we apply the new config */ - if (iwl_is_associated(priv) && new_assoc) { + if (iwl_is_associated_ctx(ctx) && new_assoc) { IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; ret = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl_rxon_cmd), - &priv->active_rxon); + sizeof(struct iwl_rxon_cmd), + active_rxon); /* If the mask clearing failed then we set * active_rxon back to what it was previously */ @@ -177,10 +177,10 @@ int iwl_commit_rxon(struct iwl_priv *priv) "* channel = %d\n" "* bssid = %pM\n", (new_assoc ? "" : "out"), - le16_to_cpu(priv->staging_rxon.channel), - priv->staging_rxon.bssid_addr); + le16_to_cpu(ctx->staging.channel), + ctx->staging.bssid_addr); - iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto); + iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); /* Apply the new configuration * RXON unassoc clears the station table in uCode so restoration of @@ -188,13 +188,13 @@ int iwl_commit_rxon(struct iwl_priv *priv) */ if (!new_assoc) { ret = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); + sizeof(struct iwl_rxon_cmd), &ctx->staging); if (ret) { IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); return ret; } IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); - memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); + memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); iwl_clear_ucode_stations(priv); iwl_restore_stations(priv); ret = iwl_restore_default_wep_keys(priv); @@ -210,14 +210,14 @@ int iwl_commit_rxon(struct iwl_priv *priv) * RXON assoc doesn't clear the station table in uCode, */ ret = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); + sizeof(struct iwl_rxon_cmd), &ctx->staging); if (ret) { IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); return ret; } - memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); + memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); } - iwl_print_rx_config_cmd(priv); + iwl_print_rx_config_cmd(priv, ctx); iwl_init_sensitivity(priv); @@ -234,10 +234,14 @@ int iwl_commit_rxon(struct iwl_priv *priv) void iwl_update_chain_flags(struct iwl_priv *priv) { + struct iwl_rxon_context *ctx; - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - iwlcore_commit_rxon(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) { + for_each_context(priv, ctx) { + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + iwlcore_commit_rxon(priv, ctx); + } + } } static void iwl_clear_free_frames(struct iwl_priv *priv) @@ -633,6 +637,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, bt_full_concurrency); + struct iwl_rxon_context *ctx; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -649,9 +654,13 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) * LQ & RXON updated cmds must be sent before BT Config cmd * to avoid 3-wire collisions */ - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - iwlcore_commit_rxon(priv); + mutex_lock(&priv->mutex); + for_each_context(priv, ctx) { + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + iwlcore_commit_rxon(priv, ctx); + } + mutex_unlock(&priv->mutex); priv->cfg->ops->hcmd->send_bt_config(priv); } @@ -2710,6 +2719,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) static void iwl_alive_start(struct iwl_priv *priv) { int ret = 0; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); @@ -2758,18 +2768,18 @@ static void iwl_alive_start(struct iwl_priv *priv) if (priv->cfg->ops->hcmd->set_tx_ant) priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant); - if (iwl_is_associated(priv)) { + if (iwl_is_associated_ctx(ctx)) { struct iwl_rxon_cmd *active_rxon = - (struct iwl_rxon_cmd *)&priv->active_rxon; + (struct iwl_rxon_cmd *)&ctx->active; /* apply any changes in staging */ - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ iwl_connection_init_rx_config(priv, NULL); if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); } if (!priv->cfg->advanced_bt_coexist) { @@ -2780,7 +2790,7 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_reset_run_time_calib(priv); /* Configure the adapter for unassociated operation */ - iwlcore_commit_rxon(priv); + iwlcore_commit_rxon(priv, ctx); /* At this point, the NIC is initialized and operational */ iwl_rf_kill_ct_config(priv); @@ -3195,12 +3205,15 @@ static void iwl_bg_rx_replenish(struct work_struct *data) void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) { + struct iwl_rxon_context *ctx; struct ieee80211_conf *conf = NULL; int ret = 0; if (!vif || !priv->is_open) return; + ctx = iwl_rxon_ctx_from_vif(vif); + if (vif->type == NL80211_IFTYPE_AP) { IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); return; @@ -3213,42 +3226,42 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) conf = ieee80211_get_hw_conf(priv->hw); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); ret = iwl_send_rxon_timing(priv, vif); if (ret) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; iwl_set_rxon_ht(priv, &priv->current_ht_config); if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid); + ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", vif->bss_conf.aid, vif->bss_conf.beacon_int); if (vif->bss_conf.use_short_preamble) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { + if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { if (vif->bss_conf.use_short_slot) - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } - iwlcore_commit_rxon(priv); + iwlcore_commit_rxon(priv, ctx); IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", - vif->bss_conf.aid, priv->active_rxon.bssid_addr); + vif->bss_conf.aid, ctx->active.bssid_addr); switch (vif->type) { case NL80211_IFTYPE_STATION: @@ -3439,17 +3452,18 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) { + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); int ret = 0; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* The following should be done only at AP bring up */ - if (!iwl_is_associated(priv)) { + if (!iwl_is_associated_ctx(ctx)) { /* RXON - unassoc (to set timing command) */ - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); /* RXON Timing */ ret = iwl_send_rxon_timing(priv, vif); @@ -3462,28 +3476,28 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) priv->hw_params.valid_rx_ant; iwl_set_rxon_ht(priv, &priv->current_ht_config); if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - priv->staging_rxon.assoc_id = 0; + ctx->staging.assoc_id = 0; if (vif->bss_conf.use_short_preamble) - priv->staging_rxon.flags |= + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging_rxon.flags &= + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { + if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { if (vif->bss_conf.use_short_slot) - priv->staging_rxon.flags |= + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else - priv->staging_rxon.flags &= + ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } /* restore RXON assoc */ - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); } iwl_send_beacon_cmd(priv); @@ -3737,6 +3751,15 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_conf *conf = &hw->conf; struct ieee80211_channel *channel = ch_switch->channel; struct iwl_ht_config *ht_conf = &priv->current_ht_config; + /* + * MULTI-FIXME + * When we add support for multiple interfaces, we need to + * revisit this. The channel switch command in the device + * only affects the BSS context, but what does that really + * mean? And what if we get a CSA on the second interface? + * This needs a lot of work. + */ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; u16 ch; unsigned long flags = 0; @@ -3749,7 +3772,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, test_bit(STATUS_SCANNING, &priv->status)) goto out_exit; - if (!iwl_is_associated(priv)) + if (!iwl_is_associated_ctx(ctx)) goto out_exit; /* channel switch in progress */ @@ -3760,7 +3783,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, if (priv->cfg->ops->lib->set_channel_switch) { ch = channel->hw_value; - if (le16_to_cpu(priv->active_rxon.channel) != ch) { + if (le16_to_cpu(ctx->active.channel) != ch) { ch_info = iwl_get_channel_info(priv, channel->band, ch); @@ -3791,12 +3814,12 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, } else ht_conf->is_40mhz = false; - if (le16_to_cpu(priv->staging_rxon.channel) != ch) - priv->staging_rxon.flags = 0; + if ((le16_to_cpu(ctx->staging.channel) != ch)) + ctx->staging.flags = 0; - iwl_set_rxon_channel(priv, channel); + iwl_set_rxon_channel(priv, channel, ctx); iwl_set_rxon_ht(priv, ht_conf); - iwl_set_flags_for_band(priv, channel->band, + iwl_set_flags_for_band(priv, ctx, channel->band, priv->vif); spin_unlock_irqrestore(&priv->lock, flags); @@ -3825,6 +3848,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; __le32 filter_or = 0, filter_nand = 0; + struct iwl_rxon_context *ctx; #define CHK(test, flag) do { \ if (*total_flags & (test)) \ @@ -3844,10 +3868,11 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - priv->staging_rxon.filter_flags &= ~filter_nand; - priv->staging_rxon.filter_flags |= filter_or; - - iwlcore_commit_rxon(priv); + for_each_context(priv, ctx) { + ctx->staging.filter_flags &= ~filter_nand; + ctx->staging.filter_flags |= filter_or; + iwlcore_commit_rxon(priv, ctx); + } mutex_unlock(&priv->mutex); @@ -4018,7 +4043,8 @@ static int iwl_init_drv(struct iwl_priv *priv) /* Choose which receivers/antennas to use */ if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); + priv->cfg->ops->hcmd->set_rxon_chain(priv, + &priv->contexts[IWL_RXON_CTX_BSS]); iwl_init_scan_params(priv); @@ -4118,7 +4144,7 @@ static int iwl_set_hw_params(struct iwl_priv *priv) static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - int err = 0; + int err = 0, i; struct iwl_priv *priv; struct ieee80211_hw *hw; struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); @@ -4146,6 +4172,16 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv = hw->priv; /* At this point both hw and priv are allocated. */ + /* + * The default context is always valid, + * more may be discovered when firmware + * is loaded. + */ + priv->valid_contexts = BIT(IWL_RXON_CTX_BSS); + + for (i = 0; i < NUM_IWL_RXON_CTX; i++) + priv->contexts[i].ctxid = i; + SET_IEEE80211_DEV(hw, &pdev->dev); IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 1a7f70f293a0..7c542a8c8f81 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -224,7 +224,8 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add); /* hcmd */ -int iwlagn_send_rxon_assoc(struct iwl_priv *priv); +int iwlagn_send_rxon_assoc(struct iwl_priv *priv, + struct iwl_rxon_context *ctx); int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); /* bt coex */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c43124c997cc..cc88401960e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -465,6 +465,9 @@ u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *sta_ht_inf) { struct iwl_ht_config *ht_conf = &priv->current_ht_config; +#if !TODO + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; +#endif if (!ht_conf->is_ht || !ht_conf->is_40mhz) return 0; @@ -481,7 +484,7 @@ u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, return 0; #endif return iwl_is_channel_extension(priv, priv->band, - le16_to_cpu(priv->staging_rxon.channel), + le16_to_cpu(ctx->staging.channel), ht_conf->extension_chan_offset); } EXPORT_SYMBOL(iwl_is_ht40_tx_allowed); @@ -506,49 +509,51 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) s32 interval_tm, rem; struct ieee80211_conf *conf = NULL; u16 beacon_int; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); conf = ieee80211_get_hw_conf(priv->hw); lockdep_assert_held(&priv->mutex); - memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); + memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd)); - priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); - priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); + ctx->timing.timestamp = cpu_to_le64(priv->timestamp); + ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval); beacon_int = vif->bss_conf.beacon_int; if (vif->type == NL80211_IFTYPE_ADHOC) { /* TODO: we need to get atim_window from upper stack * for now we set to 0 */ - priv->rxon_timing.atim_window = 0; + ctx->timing.atim_window = 0; } else { - priv->rxon_timing.atim_window = 0; + ctx->timing.atim_window = 0; } beacon_int = iwl_adjust_beacon_interval(beacon_int, priv->hw_params.max_beacon_itrvl * TIME_UNIT); - priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int); + ctx->timing.beacon_interval = cpu_to_le16(beacon_int); tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ interval_tm = beacon_int * TIME_UNIT; rem = do_div(tsf, interval_tm); - priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); + ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); IWL_DEBUG_ASSOC(priv, "beacon interval %d beacon timer %d beacon tim %d\n", - le16_to_cpu(priv->rxon_timing.beacon_interval), - le32_to_cpu(priv->rxon_timing.beacon_init_val), - le16_to_cpu(priv->rxon_timing.atim_window)); + le16_to_cpu(ctx->timing.beacon_interval), + le32_to_cpu(ctx->timing.beacon_init_val), + le16_to_cpu(ctx->timing.atim_window)); return iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, - sizeof(priv->rxon_timing), &priv->rxon_timing); + sizeof(ctx->timing), &ctx->timing); } EXPORT_SYMBOL(iwl_send_rxon_timing); -void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) +void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + int hw_decrypt) { - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; + struct iwl_rxon_cmd *rxon = &ctx->staging; if (hw_decrypt) rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; @@ -565,11 +570,11 @@ EXPORT_SYMBOL(iwl_set_rxon_hwcrypto); * be #ifdef'd out once the driver is stable and folks aren't actively * making changes */ -int iwl_check_rxon_cmd(struct iwl_priv *priv) +int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { int error = 0; int counter = 1; - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; + struct iwl_rxon_cmd *rxon = &ctx->staging; if (rxon->flags & RXON_FLG_BAND_24G_MSK) { error |= le32_to_cpu(rxon->flags & @@ -641,43 +646,57 @@ EXPORT_SYMBOL(iwl_check_rxon_cmd); * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. */ -int iwl_full_rxon_required(struct iwl_priv *priv) +int iwl_full_rxon_required(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { + const struct iwl_rxon_cmd *staging = &ctx->staging; + const struct iwl_rxon_cmd *active = &ctx->active; + +#define CHK(cond) \ + if ((cond)) { \ + IWL_DEBUG_INFO(priv, "need full RXON - " #cond "\n"); \ + return 1; \ + } + +#define CHK_NEQ(c1, c2) \ + if ((c1) != (c2)) { \ + IWL_DEBUG_INFO(priv, "need full RXON - " \ + #c1 " != " #c2 " - %d != %d\n", \ + (c1), (c2)); \ + return 1; \ + } /* These items are only settable from the full RXON command */ - if (!(iwl_is_associated(priv)) || - compare_ether_addr(priv->staging_rxon.bssid_addr, - priv->active_rxon.bssid_addr) || - compare_ether_addr(priv->staging_rxon.node_addr, - priv->active_rxon.node_addr) || - compare_ether_addr(priv->staging_rxon.wlap_bssid_addr, - priv->active_rxon.wlap_bssid_addr) || - (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) || - (priv->staging_rxon.channel != priv->active_rxon.channel) || - (priv->staging_rxon.air_propagation != - priv->active_rxon.air_propagation) || - (priv->staging_rxon.ofdm_ht_single_stream_basic_rates != - priv->active_rxon.ofdm_ht_single_stream_basic_rates) || - (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates != - priv->active_rxon.ofdm_ht_dual_stream_basic_rates) || - (priv->staging_rxon.ofdm_ht_triple_stream_basic_rates != - priv->active_rxon.ofdm_ht_triple_stream_basic_rates) || - (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id)) - return 1; + CHK(!iwl_is_associated_ctx(ctx)); + CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr)); + CHK(compare_ether_addr(staging->node_addr, active->node_addr)); + CHK(compare_ether_addr(staging->wlap_bssid_addr, + active->wlap_bssid_addr)); + CHK_NEQ(staging->dev_type, active->dev_type); + CHK_NEQ(staging->channel, active->channel); + CHK_NEQ(staging->air_propagation, active->air_propagation); + CHK_NEQ(staging->ofdm_ht_single_stream_basic_rates, + active->ofdm_ht_single_stream_basic_rates); + CHK_NEQ(staging->ofdm_ht_dual_stream_basic_rates, + active->ofdm_ht_dual_stream_basic_rates); + CHK_NEQ(staging->ofdm_ht_triple_stream_basic_rates, + active->ofdm_ht_triple_stream_basic_rates); + CHK_NEQ(staging->assoc_id, active->assoc_id); /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can * be updated with the RXON_ASSOC command -- however only some * flag transitions are allowed using RXON_ASSOC */ /* Check if we are not switching bands */ - if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) != - (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)) - return 1; + CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK, + active->flags & RXON_FLG_BAND_24G_MSK); /* Check if we are switching association toggle */ - if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) != - (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) - return 1; + CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK, + active->filter_flags & RXON_FILTER_ASSOC_MSK); + +#undef CHK +#undef CHK_NEQ return 0; } @@ -685,20 +704,25 @@ EXPORT_SYMBOL(iwl_full_rxon_required); u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) { +#if !TODO + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; +#endif /* * Assign the lowest rate -- should really get this from * the beacon skb from mac80211. */ - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) + if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) return IWL_RATE_1M_PLCP; else return IWL_RATE_6M_PLCP; } EXPORT_SYMBOL(iwl_rate_get_lowest_plcp); -void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) +static void _iwl_set_rxon_ht(struct iwl_priv *priv, + struct iwl_ht_config *ht_conf, + struct iwl_rxon_context *ctx) { - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; + struct iwl_rxon_cmd *rxon = &ctx->staging; if (!ht_conf->is_ht) { rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | @@ -754,13 +778,21 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) } if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X " "extension channel offset 0x%x\n", le32_to_cpu(rxon->flags), ht_conf->ht_protection, ht_conf->extension_chan_offset); } + +void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) +{ + struct iwl_rxon_context *ctx; + + for_each_context(priv, ctx) + _iwl_set_rxon_ht(priv, ht_conf, ctx); +} EXPORT_SYMBOL(iwl_set_rxon_ht); #define IWL_NUM_RX_CHAINS_MULTIPLE 3 @@ -832,7 +864,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) * Selects how many and which Rx receivers/antennas/chains to use. * This should not be used for scan command ... it puts data in wrong place. */ -void iwl_set_rxon_chain(struct iwl_priv *priv) +void iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { bool is_single = is_single_rx_stream(priv); bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); @@ -878,15 +910,15 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; - priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); + ctx->staging.rx_chain = cpu_to_le16(rx_chain); if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) - priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; + ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; else - priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; + ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n", - priv->staging_rxon.rx_chain, + ctx->staging.rx_chain, active_rx_cnt, idle_rx_cnt); WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 || @@ -894,39 +926,41 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_set_rxon_chain); -/* Return valid channel */ +/* Return valid, unused, channel for a passive scan to reset the RF */ u8 iwl_get_single_channel_number(struct iwl_priv *priv, - enum ieee80211_band band) + enum ieee80211_band band) { const struct iwl_channel_info *ch_info; int i; u8 channel = 0; + u8 min, max; + struct iwl_rxon_context *ctx; - /* only scan single channel, good enough to reset the RF */ - /* pick the first valid not in-use channel */ if (band == IEEE80211_BAND_5GHZ) { - for (i = 14; i < priv->channel_count; i++) { - if (priv->channel_info[i].channel != - le16_to_cpu(priv->staging_rxon.channel)) { - channel = priv->channel_info[i].channel; - ch_info = iwl_get_channel_info(priv, - band, channel); - if (is_channel_valid(ch_info)) - break; - } - } + min = 14; + max = priv->channel_count; } else { - for (i = 0; i < 14; i++) { - if (priv->channel_info[i].channel != - le16_to_cpu(priv->staging_rxon.channel)) { - channel = - priv->channel_info[i].channel; - ch_info = iwl_get_channel_info(priv, - band, channel); - if (is_channel_valid(ch_info)) - break; - } + min = 0; + max = 14; + } + + for (i = min; i < max; i++) { + bool busy = false; + + for_each_context(priv, ctx) { + busy = priv->channel_info[i].channel == + le16_to_cpu(ctx->staging.channel); + if (busy) + break; } + + if (busy) + continue; + + channel = priv->channel_info[i].channel; + ch_info = iwl_get_channel_info(priv, band, channel); + if (is_channel_valid(ch_info)) + break; } return channel; @@ -937,25 +971,24 @@ EXPORT_SYMBOL(iwl_get_single_channel_number); * iwl_set_rxon_channel - Set the band and channel values in staging RXON * @ch: requested channel as a pointer to struct ieee80211_channel - * In addition to setting the staging RXON, priv->band is also set. - * * NOTE: Does not commit to the hardware; it sets appropriate bit fields * in the staging RXON flag structure based on the ch->band */ -int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) +int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, + struct iwl_rxon_context *ctx) { enum ieee80211_band band = ch->band; u16 channel = ch->hw_value; - if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && + if ((le16_to_cpu(ctx->staging.channel) == channel) && (priv->band == band)) return 0; - priv->staging_rxon.channel = cpu_to_le16(channel); + ctx->staging.channel = cpu_to_le16(channel); if (band == IEEE80211_BAND_5GHZ) - priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; + ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK; else - priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; + ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; priv->band = band; @@ -966,24 +999,25 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) EXPORT_SYMBOL(iwl_set_rxon_channel); void iwl_set_flags_for_band(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, enum ieee80211_band band, struct ieee80211_vif *vif) { if (band == IEEE80211_BAND_5GHZ) { - priv->staging_rxon.flags &= + ctx->staging.flags &= ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_CCK_MSK); - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; } else { /* Copied from iwl_post_associate() */ if (vif && vif->bss_conf.use_short_slot) - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; - priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; - priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; + ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; + ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK; + ctx->staging.flags &= ~RXON_FLG_CCK_MSK; } } EXPORT_SYMBOL(iwl_set_flags_for_band); @@ -996,26 +1030,29 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, { const struct iwl_channel_info *ch_info; enum nl80211_iftype type = NL80211_IFTYPE_STATION; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - if (vif) + if (vif) { type = vif->type; + ctx = iwl_rxon_ctx_from_vif(vif); + } - memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); + memset(&ctx->staging, 0, sizeof(ctx->staging)); switch (type) { case NL80211_IFTYPE_AP: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; + ctx->staging.dev_type = RXON_DEV_TYPE_AP; break; case NL80211_IFTYPE_STATION: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS; - priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; + ctx->staging.dev_type = RXON_DEV_TYPE_ESS; + ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; break; case NL80211_IFTYPE_ADHOC: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS; - priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; - priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | + ctx->staging.dev_type = RXON_DEV_TYPE_IBSS; + ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; + ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; @@ -1028,37 +1065,36 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, /* TODO: Figure out when short_preamble would be set and cache from * that */ if (!hw_to_local(priv->hw)->short_preamble) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; #endif ch_info = iwl_get_channel_info(priv, priv->band, - le16_to_cpu(priv->active_rxon.channel)); + le16_to_cpu(ctx->active.channel)); if (!ch_info) ch_info = &priv->channel_info[0]; - priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); + ctx->staging.channel = cpu_to_le16(ch_info->channel); priv->band = ch_info->band; - iwl_set_flags_for_band(priv, priv->band, vif); + iwl_set_flags_for_band(priv, ctx, priv->band, vif); - priv->staging_rxon.ofdm_basic_rates = + ctx->staging.ofdm_basic_rates = (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; - priv->staging_rxon.cck_basic_rates = + ctx->staging.cck_basic_rates = (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; /* clear both MIX and PURE40 mode flag */ - priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | + ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | RXON_FLG_CHANNEL_MODE_PURE_40); - if (vif) - memcpy(priv->staging_rxon.node_addr, vif->addr, ETH_ALEN); + memcpy(ctx->staging.node_addr, vif->addr, ETH_ALEN); - priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; - priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; - priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff; + ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff; + ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; + ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff; } EXPORT_SYMBOL(iwl_connection_init_rx_config); @@ -1066,6 +1102,7 @@ void iwl_set_rate(struct iwl_priv *priv) { const struct ieee80211_supported_band *hw = NULL; struct ieee80211_rate *rate; + struct iwl_rxon_context *ctx; int i; hw = iwl_get_hw_mode(priv, priv->band); @@ -1084,11 +1121,13 @@ void iwl_set_rate(struct iwl_priv *priv) IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate); - priv->staging_rxon.cck_basic_rates = - (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; + for_each_context(priv, ctx) { + ctx->staging.cck_basic_rates = + (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; - priv->staging_rxon.ofdm_basic_rates = - (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; + ctx->staging.ofdm_basic_rates = + (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; + } } EXPORT_SYMBOL(iwl_set_rate); @@ -1109,14 +1148,17 @@ EXPORT_SYMBOL(iwl_chswitch_done); void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; struct iwl_csa_notification *csa = &(pkt->u.csa_notif); +#if !TODO + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; +#endif + struct iwl_rxon_cmd *rxon = (void *)&ctx->active; if (priv->switch_rxon.switch_in_progress) { if (!le32_to_cpu(csa->status) && (csa->channel == priv->switch_rxon.channel)) { rxon->channel = csa->channel; - priv->staging_rxon.channel = csa->channel; + ctx->staging.channel = csa->channel; IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", le16_to_cpu(csa->channel)); iwl_chswitch_done(priv, true); @@ -1130,9 +1172,10 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) EXPORT_SYMBOL(iwl_rx_csa); #ifdef CONFIG_IWLWIFI_DEBUG -void iwl_print_rx_config_cmd(struct iwl_priv *priv) +void iwl_print_rx_config_cmd(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; + struct iwl_rxon_cmd *rxon = &ctx->staging; IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); @@ -1172,7 +1215,8 @@ void iwl_irq_handle_error(struct iwl_priv *priv) priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) - iwl_print_rx_config_cmd(priv); + iwl_print_rx_config_cmd(priv, + &priv->contexts[IWL_RXON_CTX_BSS]); #endif wake_up_interruptible(&priv->wait_command_queue); @@ -1640,18 +1684,20 @@ static void iwl_ht_conf(struct iwl_priv *priv, IWL_DEBUG_MAC80211(priv, "leave\n"); } -static inline void iwl_set_no_assoc(struct iwl_priv *priv) +static inline void iwl_set_no_assoc(struct iwl_priv *priv, + struct ieee80211_vif *vif) { + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + iwl_led_disassociate(priv); /* * inform the ucode that there is no longer an * association and that no more packets should be * sent */ - priv->staging_rxon.filter_flags &= - ~RXON_FILTER_ASSOC_MSK; - priv->staging_rxon.assoc_id = 0; - iwlcore_commit_rxon(priv); + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + ctx->staging.assoc_id = 0; + iwlcore_commit_rxon(priv, ctx); } static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) @@ -1691,6 +1737,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, u32 changes) { struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); int ret; IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); @@ -1735,13 +1782,13 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, /* mac80211 only sets assoc when in STATION mode */ if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { - memcpy(priv->staging_rxon.bssid_addr, + memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); /* currently needed in a few places */ memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); } else { - priv->staging_rxon.filter_flags &= + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; } @@ -1764,21 +1811,21 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; } if (changes & BSS_CHANGED_ERP_CTS_PROT) { IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) - priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; + ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; if (bss_conf->use_cts_prot) - priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; + ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; else - priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; + ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; } if (changes & BSS_CHANGED_BASIC_RATES) { @@ -1788,12 +1835,12 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, * like this here: * if (A-band) - priv->staging_rxon.ofdm_basic_rates = + ctx->staging.ofdm_basic_rates = bss_conf->basic_rates; else - priv->staging_rxon.ofdm_basic_rates = + ctx->staging.ofdm_basic_rates = bss_conf->basic_rates >> 4; - priv->staging_rxon.cck_basic_rates = + ctx->staging.cck_basic_rates = bss_conf->basic_rates & 0xF; */ } @@ -1802,7 +1849,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, iwl_ht_conf(priv, vif); if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); } if (changes & BSS_CHANGED_ASSOC) { @@ -1815,29 +1862,29 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, if (!iwl_is_rfkill(priv)) priv->cfg->ops->lib->post_associate(priv, vif); } else - iwl_set_no_assoc(priv); + iwl_set_no_assoc(priv, vif); } - if (changes && iwl_is_associated(priv) && bss_conf->aid) { + if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) { IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", changes); - ret = iwl_send_rxon_assoc(priv); + ret = iwl_send_rxon_assoc(priv, ctx); if (!ret) { /* Sync active_rxon with latest change. */ - memcpy((void *)&priv->active_rxon, - &priv->staging_rxon, + memcpy((void *)&ctx->active, + &ctx->staging, sizeof(struct iwl_rxon_cmd)); } } if (changes & BSS_CHANGED_BEACON_ENABLED) { if (vif->bss_conf.enable_beacon) { - memcpy(priv->staging_rxon.bssid_addr, + memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); iwlcore_config_ap(priv, vif); } else - iwl_set_no_assoc(priv); + iwl_set_no_assoc(priv, vif); } if (changes & BSS_CHANGED_IBSS) { @@ -1857,17 +1904,20 @@ EXPORT_SYMBOL(iwl_bss_info_changed); static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) { + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + iwl_connection_init_rx_config(priv, vif); if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - return iwlcore_commit_rxon(priv); + return iwlcore_commit_rxon(priv, ctx); } int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; int err = 0; IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", @@ -1875,6 +1925,8 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mutex_lock(&priv->mutex); + vif_priv->ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + if (WARN_ON(!iwl_is_ready_rf(priv))) { err = -EINVAL; goto out; @@ -1920,6 +1972,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); bool scan_completed = false; IWL_DEBUG_MAC80211(priv, "enter\n"); @@ -1928,8 +1981,8 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, if (iwl_is_ready_rf(priv)) { iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); } if (priv->vif == vif) { priv->vif = NULL; @@ -1971,6 +2024,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) struct ieee80211_conf *conf = &hw->conf; struct ieee80211_channel *channel = conf->channel; struct iwl_ht_config *ht_conf = &priv->current_ht_config; + struct iwl_rxon_context *ctx; unsigned long flags = 0; int ret = 0; u16 ch; @@ -2000,7 +2054,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) * configured. */ if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); + for_each_context(priv, ctx) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); } /* during scanning mac80211 will delay channel setting until @@ -2042,13 +2097,20 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) * from BSS config in iwl_ht_conf */ ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; - if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) - priv->staging_rxon.flags = 0; + for_each_context(priv, ctx) { + /* if we are switching from ht to 2.4 clear flags + * from any ht related info since 2.4 does not + * support ht */ + if ((le16_to_cpu(ctx->staging.channel) != ch)) + ctx->staging.flags = 0; - iwl_set_rxon_channel(priv, channel); - iwl_set_rxon_ht(priv, ht_conf); + iwl_set_rxon_channel(priv, channel, ctx); + iwl_set_rxon_ht(priv, ht_conf); + + iwl_set_flags_for_band(priv, ctx, channel->band, + priv->vif); + } - iwl_set_flags_for_band(priv, channel->band, priv->vif); spin_unlock_irqrestore(&priv->lock, flags); if (priv->cfg->ops->lib->update_bcast_station) @@ -2083,12 +2145,13 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) if (scan_active) goto out; - if (memcmp(&priv->active_rxon, - &priv->staging_rxon, sizeof(priv->staging_rxon))) - iwlcore_commit_rxon(priv); - else - IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration.\n"); - + for_each_context(priv, ctx) { + if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging))) + iwlcore_commit_rxon(priv, ctx); + else + IWL_DEBUG_INFO(priv, + "Not re-sending same RXON configuration.\n"); + } out: IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -2101,6 +2164,8 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; unsigned long flags; + /* IBSS can only be the IWL_RXON_CTX_BSS context */ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "enter\n"); @@ -2131,8 +2196,8 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) * clear RXON_FILTER_ASSOC_MSK bit */ iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); iwl_set_rate(priv); @@ -2541,7 +2606,7 @@ static void iwl_force_rf_reset(struct iwl_priv *priv) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (!iwl_is_associated(priv)) { + if (!iwl_is_any_associated(priv)) { IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n"); return; } @@ -2696,7 +2761,7 @@ void iwl_bg_monitor_recover(unsigned long data) return; /* monitor and check for other stuck queues */ - if (iwl_is_associated(priv)) { + if (iwl_is_any_associated(priv)) { for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { /* skip as we already checked the command queue */ if (cnt == IWL_CMD_QUEUE_NUM) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index de2e39f36c25..80c256246e4d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -88,9 +88,10 @@ struct iwl_cmd; #define IWL_CMD(x) case x: return #x struct iwl_hcmd_ops { - int (*rxon_assoc)(struct iwl_priv *priv); - int (*commit_rxon)(struct iwl_priv *priv); - void (*set_rxon_chain)(struct iwl_priv *priv); + int (*rxon_assoc)(struct iwl_priv *priv, struct iwl_rxon_context *ctx); + int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx); + void (*set_rxon_chain)(struct iwl_priv *priv, + struct iwl_rxon_context *ctx); int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant); void (*send_bt_config)(struct iwl_priv *priv); }; @@ -374,12 +375,15 @@ void iwl_activate_qos(struct iwl_priv *priv); int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); -void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); -int iwl_check_rxon_cmd(struct iwl_priv *priv); -int iwl_full_rxon_required(struct iwl_priv *priv); -void iwl_set_rxon_chain(struct iwl_priv *priv); -int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); +void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + int hw_decrypt); +int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx); +int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx); +void iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx); +int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, + struct iwl_rxon_context *ctx); void iwl_set_flags_for_band(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, enum ieee80211_band band, struct ieee80211_vif *vif); u8 iwl_get_single_channel_number(struct iwl_priv *priv, @@ -400,7 +404,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes); -int iwl_commit_rxon(struct iwl_priv *priv); +int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void iwl_mac_remove_interface(struct ieee80211_hw *hw, @@ -632,9 +636,11 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, void iwl_dump_csr(struct iwl_priv *priv); int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); #ifdef CONFIG_IWLWIFI_DEBUG -void iwl_print_rx_config_cmd(struct iwl_priv *priv); +void iwl_print_rx_config_cmd(struct iwl_priv *priv, + struct iwl_rxon_context *ctx); #else -static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv) +static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { } #endif @@ -720,13 +726,15 @@ void iwl_apm_stop(struct iwl_priv *priv); int iwl_apm_init(struct iwl_priv *priv); int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif); -static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) +static inline int iwl_send_rxon_assoc(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { - return priv->cfg->ops->hcmd->rxon_assoc(priv); + return priv->cfg->ops->hcmd->rxon_assoc(priv, ctx); } -static inline int iwlcore_commit_rxon(struct iwl_priv *priv) +static inline int iwlcore_commit_rxon(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { - return priv->cfg->ops->hcmd->commit_rxon(priv); + return priv->cfg->ops->hcmd->commit_rxon(priv, ctx); } static inline void iwlcore_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index ef787905f51c..d36418c3a6b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -730,7 +730,7 @@ static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, return -EFAULT; if (sscanf(buf, "%d", &ht40) != 1) return -EFAULT; - if (!iwl_is_associated(priv)) + if (!iwl_is_any_associated(priv)) priv->disable_ht40 = ht40 ? true : false; else { IWL_ERR(priv, "Sta associated with AP - " @@ -1319,7 +1319,8 @@ static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file, int len = 0; char buf[20]; - len = sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.flags)); + len = sprintf(buf, "0x%04X\n", + le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags)); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -1332,7 +1333,7 @@ static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, char buf[20]; len = sprintf(buf, "0x%04X\n", - le32_to_cpu(priv->active_rxon.filter_flags)); + le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags)); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 8d5201ac80f9..6b188926014b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -519,6 +519,7 @@ struct iwl_station_priv { * space for us to put data into. */ struct iwl_vif_priv { + struct iwl_rxon_context *ctx; u8 ibss_bssid_sta_id; }; @@ -1097,6 +1098,26 @@ struct iwl_force_reset { */ #define IWLAGN_EXT_BEACON_TIME_POS 22 +enum iwl_rxon_context_id { + IWL_RXON_CTX_BSS, + + NUM_IWL_RXON_CTX +}; + +struct iwl_rxon_context { + enum iwl_rxon_context_id ctxid; + /* + * We declare this const so it can only be + * changed via explicit cast within the + * routines that actually update the physical + * hardware. + */ + const struct iwl_rxon_cmd active; + struct iwl_rxon_cmd staging; + + struct iwl_rxon_time_cmd timing; +}; + struct iwl_priv { /* ieee device used by generic ieee processing code */ @@ -1173,6 +1194,9 @@ struct iwl_priv { u32 hw_wa_rev; u8 rev_id; + /* microcode/device supports multiple contexts */ + u8 valid_contexts; + /* EEPROM MAC addresses */ struct mac_address addresses[2]; @@ -1190,15 +1214,7 @@ struct iwl_priv { u8 ucode_write_complete; /* the image write is complete */ char firmware_name[25]; - - struct iwl_rxon_time_cmd rxon_timing; - - /* We declare this const so it can only be - * changed via explicit cast within the - * routines that actually update the physical - * hardware */ - const struct iwl_rxon_cmd active_rxon; - struct iwl_rxon_cmd staging_rxon; + struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX]; struct iwl_switch_rxon switch_rxon; @@ -1490,10 +1506,34 @@ static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, return NULL; } +static inline struct iwl_rxon_context * +iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) +{ + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; + + return vif_priv->ctx; +} + +#define for_each_context(priv, ctx) \ + for (ctx = &priv->contexts[IWL_RXON_CTX_BSS]; \ + ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \ + if (priv->valid_contexts & BIT(ctx->ctxid)) + +static inline int iwl_is_associated(struct iwl_priv *priv, + enum iwl_rxon_context_id ctxid) +{ + return (priv->contexts[ctxid].active.filter_flags & + RXON_FILTER_ASSOC_MSK) ? 1 : 0; +} + +static inline int iwl_is_any_associated(struct iwl_priv *priv) +{ + return iwl_is_associated(priv, IWL_RXON_CTX_BSS); +} -static inline int iwl_is_associated(struct iwl_priv *priv) +static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx) { - return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; + return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; } static inline int is_channel_valid(const struct iwl_channel_info *ch_info) diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 79773e353baa..10be197b0f22 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -228,7 +228,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, { if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (iwl_is_associated(priv)) { + if (iwl_is_any_associated(priv)) { if (priv->cfg->ops->lib->check_ack_health) { if (!priv->cfg->ops->lib->check_ack_health( priv, pkt)) { @@ -266,7 +266,12 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, { u16 fc = le16_to_cpu(hdr->frame_control); - if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) + /* + * All contexts have the same setting here due to it being + * a module parameter, so OK to check any context. + */ + if (priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags & + RXON_FILTER_DIS_DECRYPT_MSK) return 0; if (!(fc & IEEE80211_FCTL_PROTECTED)) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 2939699a1200..fe4cb57c3a1c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -290,7 +290,8 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; - if (iwl_is_associated(priv)) { + if (iwl_is_any_associated(priv)) { + /* TODO: should use minimum of all contexts */ /* If we're associated, we clamp the maximum passive * dwell time to be 98% of the beacon interval (minus * 2 * channel tune time) */ @@ -527,6 +528,7 @@ static void iwl_bg_scan_completed(struct work_struct *work) container_of(work, struct iwl_priv, scan_completed); bool internal = false; bool scan_completed = false; + struct iwl_rxon_context *ctx; IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); @@ -557,9 +559,8 @@ static void iwl_bg_scan_completed(struct work_struct *work) * Since setting the RXON may have been deferred while * performing the scan, fire one off if needed */ - if (memcmp(&priv->active_rxon, - &priv->staging_rxon, sizeof(priv->staging_rxon))) - iwlcore_commit_rxon(priv); + for_each_context(priv, ctx) + iwlcore_commit_rxon(priv, ctx); out: mutex_unlock(&priv->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index d5e8db37b86e..43afb8fb36c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1153,12 +1153,16 @@ static bool is_lq_table_valid(struct iwl_priv *priv, { int i; struct iwl_ht_config *ht_conf = &priv->current_ht_config; +#if !TODO + struct iwl_rxon_context *ctx = + &priv->contexts[IWL_RXON_CTX_BSS]; +#endif if (ht_conf->is_ht) return true; IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n", - priv->active_rxon.channel); + ctx->active.channel); for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) { IWL_DEBUG_INFO(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 53e6cbb3aaaa..234d6b430fcf 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -317,7 +317,7 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, int left) { - if (!iwl_is_associated(priv) || !priv->ibss_beacon) + if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->ibss_beacon) return 0; if (priv->ibss_beacon->len > left) @@ -683,11 +683,12 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, int rc; int spectrum_resp_status; int duration = le16_to_cpu(params->duration); + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - if (iwl_is_associated(priv)) + if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) add_time = iwl_usecs_to_beacons(priv, le64_to_cpu(params->start_time) - priv->_3945.last_tsf, - le16_to_cpu(priv->rxon_timing.beacon_interval)); + le16_to_cpu(ctx->timing.beacon_interval)); memset(&spectrum, 0, sizeof(spectrum)); @@ -698,18 +699,18 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, cmd.len = sizeof(spectrum); spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len)); - if (iwl_is_associated(priv)) + if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) spectrum.start_time = iwl_add_beacon_time(priv, priv->_3945.last_beacon_time, add_time, - le16_to_cpu(priv->rxon_timing.beacon_interval)); + le16_to_cpu(ctx->timing.beacon_interval)); else spectrum.start_time = 0; spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); spectrum.channels[0].channel = params->channel; spectrum.channels[0].type = type; - if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK) + if (ctx->active.flags & RXON_FLG_BAND_24G_MSK) spectrum.flags |= RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; @@ -2468,6 +2469,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) { int thermal_spin = 0; u32 rfkill; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); @@ -2525,11 +2527,11 @@ static void iwl3945_alive_start(struct iwl_priv *priv) iwl_power_update_mode(priv, true); - if (iwl_is_associated(priv)) { + if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) { struct iwl3945_rxon_cmd *active_rxon = - (struct iwl3945_rxon_cmd *)(&priv->active_rxon); + (struct iwl3945_rxon_cmd *)(&ctx->active); - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ @@ -2540,7 +2542,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) priv->cfg->ops->hcmd->send_bt_config(priv); /* Configure the adapter for unassociated operation */ - iwlcore_commit_rxon(priv); + iwlcore_commit_rxon(priv, ctx); iwl3945_reg_txpower_periodic(priv); @@ -2883,7 +2885,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; scan->quiet_time = IWL_ACTIVE_QUIET_TIME; - if (iwl_is_associated(priv)) { + if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) { u16 interval = 0; u32 extra; u32 suspend_time = 100; @@ -3077,6 +3079,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) { int rc = 0; struct ieee80211_conf *conf = NULL; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; if (!vif || !priv->is_open) return; @@ -3087,7 +3090,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) } IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", - vif->bss_conf.aid, priv->active_rxon.bssid_addr); + vif->bss_conf.aid, ctx->active.bssid_addr); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -3096,34 +3099,34 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) conf = ieee80211_get_hw_conf(priv->hw); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); rc = iwl_send_rxon_timing(priv, vif); if (rc) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid); + ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", vif->bss_conf.aid, vif->bss_conf.beacon_int); if (vif->bss_conf.use_short_preamble) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { + if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { if (vif->bss_conf.use_short_slot) - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } - iwlcore_commit_rxon(priv); + iwlcore_commit_rxon(priv, ctx); switch (vif->type) { case NL80211_IFTYPE_STATION: @@ -3260,17 +3263,18 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) { + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; int rc = 0; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* The following should be done only at AP bring up */ - if (!(iwl_is_associated(priv))) { + if (!(iwl_is_associated(priv, IWL_RXON_CTX_BSS))) { /* RXON - unassoc (to set timing command) */ - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); /* RXON Timing */ rc = iwl_send_rxon_timing(priv, vif); @@ -3278,26 +3282,26 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); - priv->staging_rxon.assoc_id = 0; + ctx->staging.assoc_id = 0; if (vif->bss_conf.use_short_preamble) - priv->staging_rxon.flags |= + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging_rxon.flags &= + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { + if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { if (vif->bss_conf.use_short_slot) - priv->staging_rxon.flags |= + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else - priv->staging_rxon.flags &= + ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } /* restore RXON assoc */ - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); } iwl3945_send_beacon_cmd(priv); @@ -3323,7 +3327,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - static_key = !iwl_is_associated(priv); + static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS); if (!static_key) { sta_id = iwl_sta_id_or_broadcast(priv, sta); @@ -3405,6 +3409,7 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; __le32 filter_or = 0, filter_nand = 0; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; #define CHK(test, flag) do { \ if (*total_flags & (test)) \ @@ -3424,8 +3429,8 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - priv->staging_rxon.filter_flags &= ~filter_nand; - priv->staging_rxon.filter_flags |= filter_or; + ctx->staging.filter_flags &= ~filter_nand; + ctx->staging.filter_flags |= filter_or; /* * Committing directly here breaks for some reason, @@ -3539,8 +3544,9 @@ static ssize_t show_flags(struct device *d, struct device_attribute *attr, char *buf) { struct iwl_priv *priv = dev_get_drvdata(d); + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); + return sprintf(buf, "0x%04X\n", ctx->active.flags); } static ssize_t store_flags(struct device *d, @@ -3549,17 +3555,18 @@ static ssize_t store_flags(struct device *d, { struct iwl_priv *priv = dev_get_drvdata(d); u32 flags = simple_strtoul(buf, NULL, 0); + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging_rxon.flags) != flags) { + if (le32_to_cpu(ctx->staging.flags) != flags) { /* Cancel any currently running scans... */ if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARN(priv, "Could not cancel scan.\n"); else { IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n", flags); - priv->staging_rxon.flags = cpu_to_le32(flags); - iwlcore_commit_rxon(priv); + ctx->staging.flags = cpu_to_le32(flags); + iwlcore_commit_rxon(priv, ctx); } } mutex_unlock(&priv->mutex); @@ -3573,9 +3580,10 @@ static ssize_t show_filter_flags(struct device *d, struct device_attribute *attr, char *buf) { struct iwl_priv *priv = dev_get_drvdata(d); + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; return sprintf(buf, "0x%04X\n", - le32_to_cpu(priv->active_rxon.filter_flags)); + le32_to_cpu(ctx->active.filter_flags)); } static ssize_t store_filter_flags(struct device *d, @@ -3583,19 +3591,20 @@ static ssize_t store_filter_flags(struct device *d, const char *buf, size_t count) { struct iwl_priv *priv = dev_get_drvdata(d); + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; u32 filter_flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) { + if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) { /* Cancel any currently running scans... */ if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARN(priv, "Could not cancel scan.\n"); else { IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = " "0x%04X\n", filter_flags); - priv->staging_rxon.filter_flags = + ctx->staging.filter_flags = cpu_to_le32(filter_flags); - iwlcore_commit_rxon(priv); + iwlcore_commit_rxon(priv, ctx); } } mutex_unlock(&priv->mutex); @@ -3643,8 +3652,9 @@ static ssize_t store_measurement(struct device *d, const char *buf, size_t count) { struct iwl_priv *priv = dev_get_drvdata(d); + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct ieee80211_measurement_params params = { - .channel = le16_to_cpu(priv->active_rxon.channel), + .channel = le16_to_cpu(ctx->active.channel), .start_time = cpu_to_le64(priv->_3945.last_tsf), .duration = cpu_to_le16(1), }; @@ -3969,7 +3979,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - int err = 0; + int err = 0, i; struct iwl_priv *priv; struct ieee80211_hw *hw; struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); @@ -3991,6 +4001,12 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv = hw->priv; SET_IEEE80211_DEV(hw, &pdev->dev); + /* 3945 has only one valid context */ + priv->valid_contexts = BIT(IWL_RXON_CTX_BSS); + + for (i = 0; i < NUM_IWL_RXON_CTX; i++) + priv->contexts[i].ctxid = i; + /* * Disabling hardware scan means that mac80211 will perform scans * "the hard way", rather than using device's scan. @@ -4126,7 +4142,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e } iwl_set_rxon_channel(priv, - &priv->bands[IEEE80211_BAND_2GHZ].channels[5]); + &priv->bands[IEEE80211_BAND_2GHZ].channels[5], + &priv->contexts[IWL_RXON_CTX_BSS]); iwl3945_setup_deferred_work(priv); iwl3945_setup_rx_handlers(priv); iwl_power_initialize(priv); -- cgit v1.2.3-59-g8ed1b From 13bb9483e190b95b04b22280ec9efa6b48469fd6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:33 +0200 Subject: iwlwifi: prepare for PAN queue/fifo assignment PAN ucode will require a different queue assignment, in particular queue 9 instead of 4 should be used for commands. This is required because the ucode will stop/start queues 4 and 8 depending on the PAN state, since queue 8 will be used for PAN multicast (after DTIM). Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 1 + drivers/net/wireless/iwlwifi/iwl-3945.c | 10 ++++---- drivers/net/wireless/iwlwifi/iwl-4965.c | 3 ++- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 12 +++++----- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 31 +++++++++++++++++++++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 +++ drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 10 ++++---- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 2 +- drivers/net/wireless/iwlwifi/iwl-prph.h | 9 ++++---- drivers/net/wireless/iwlwifi/iwl-tx.c | 34 ++++++++++++++-------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 ++ 13 files changed, 77 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index a4a3194779d2..65b5834da28c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -226,6 +226,7 @@ struct iwl3945_eeprom { /* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ #define IWL39_NUM_QUEUES 5 +#define IWL39_CMD_QUEUE_NUM 4 #define IWL_DEFAULT_TX_RETRY 15 diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index f4aa229986ca..f059b1dd4d41 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -273,7 +273,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, struct iwl_queue *q = &txq->q; struct iwl_tx_info *tx_info; - BUG_ON(txq_id == IWL_CMD_QUEUE_NUM); + BUG_ON(txq_id == IWL39_CMD_QUEUE_NUM); for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { @@ -285,7 +285,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, } if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) && - (txq_id != IWL_CMD_QUEUE_NUM) && + (txq_id != IWL39_CMD_QUEUE_NUM) && priv->mac80211_registered) iwl_wake_queue(priv, txq_id); } @@ -760,7 +760,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, data_retry_limit = IWL_DEFAULT_TX_RETRY; tx_cmd->data_retry_limit = data_retry_limit; - if (tx_id >= IWL_CMD_QUEUE_NUM) + if (tx_id >= IWL39_CMD_QUEUE_NUM) rts_retry_limit = 3; else rts_retry_limit = 7; @@ -909,7 +909,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) /* Tx queue(s) */ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { - slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? + slots_num = (txq_id == IWL39_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, txq_id); @@ -1072,7 +1072,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) if (priv->txq) for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) - if (txq_id == IWL_CMD_QUEUE_NUM) + if (txq_id == IWL39_CMD_QUEUE_NUM) iwl_cmd_queue_free(priv); else iwl_tx_queue_free(priv, txq_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 82f32305f50e..cda389c3b025 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -576,7 +576,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) /* Activate all Tx DMA/FIFO channels */ priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6)); - iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); + iwl4965_set_wr_ptrs(priv, IWL_DEFAULT_CMD_QUEUE_NUM, 0); /* make sure all queue are not stopped */ memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); @@ -587,6 +587,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) priv->txq_ctx_active_msk = 0; /* Map each Tx/cmd queue to its corresponding fifo */ BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7); + for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { int ac = default_queue_to_tx_fifo[i]; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 531a7dc3dc72..f919977d5632 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1479,7 +1479,7 @@ int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) /* waiting for all the tx frames complete might take a while */ for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { - if (cnt == IWL_CMD_QUEUE_NUM) + if (cnt == priv->cmd_queue) continue; txq = &priv->txq[cnt]; q = &txq->q; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index a51a7cfa5a14..88b7bbfb1f91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -118,7 +118,7 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); - if (txq_id != IWL_CMD_QUEUE_NUM) { + if (txq_id != priv->cmd_queue) { sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; @@ -155,7 +155,7 @@ void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - if (txq_id != IWL_CMD_QUEUE_NUM) + if (txq_id != priv->cmd_queue) sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; bc_ent = cpu_to_le16(1 | (sta_id << 12)); @@ -825,7 +825,7 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) /* Tx queues */ if (priv->txq) { for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) - if (txq_id == IWL_CMD_QUEUE_NUM) + if (txq_id == priv->cmd_queue) iwl_cmd_queue_free(priv); else iwl_tx_queue_free(priv, txq_id); @@ -882,9 +882,9 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); - /* Alloc and init all Tx queues, including the command queue (#4) */ + /* Alloc and init all Tx queues, including the command queue (#4/#9) */ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { - slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? + slots_num = (txq_id == priv->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, txq_id); @@ -922,7 +922,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv) /* Alloc and init all Tx queues, including the command queue (#4) */ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { - slots_num = txq_id == IWL_CMD_QUEUE_NUM ? + slots_num = txq_id == priv->cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index f2499e1f2047..a9ea7a1fef02 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -52,6 +52,19 @@ static const s8 iwlagn_default_queue_to_tx_fifo[] = { IWL_TX_FIFO_UNUSED, }; +static const s8 iwlagn_ipan_queue_to_tx_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, + IWL_TX_FIFO_UNUSED, /* FIXME */ + IWL_TX_FIFO_UNUSED, /* FIXME */ + IWL_TX_FIFO_UNUSED, /* FIXME */ + IWL_TX_FIFO_UNUSED, /* FIXME */ + IWL_TX_FIFO_UNUSED, /* FIXME */ + IWLAGN_CMD_FIFO_NUM, +}; + static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, 0, COEX_UNASSOC_IDLE_FLAGS}, @@ -376,6 +389,7 @@ static void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) int iwlagn_alive_notify(struct iwl_priv *priv) { + const s8 *queues; u32 a; unsigned long flags; int i, chan; @@ -410,7 +424,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv) reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, - IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); + IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv)); iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0); /* initiate the queues */ @@ -436,7 +450,13 @@ int iwlagn_alive_notify(struct iwl_priv *priv) /* Activate all Tx DMA/FIFO channels */ priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); - iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); + /* map queues to FIFOs */ + if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) + queues = iwlagn_ipan_queue_to_tx_fifo; + else + queues = iwlagn_default_queue_to_tx_fifo; + + iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0); /* make sure all queue are not stopped */ memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); @@ -445,11 +465,12 @@ int iwlagn_alive_notify(struct iwl_priv *priv) /* reset to 0 to enable all the queue first */ priv->txq_ctx_active_msk = 0; - /* map qos queues to fifos one-to-one */ + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10); - for (i = 0; i < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) { - int ac = iwlagn_default_queue_to_tx_fifo[i]; + for (i = 0; i < 10; i++) { + int ac = queues[i]; iwl_txq_ctx_activate(priv, i); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e073069a44c2..cfc8e8de8798 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3011,6 +3011,9 @@ static int __iwl_up(struct iwl_priv *priv) iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + /* must be initialised before iwl_hw_nic_init */ + priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + ret = iwlagn_hw_nic_init(priv); if (ret) { IWL_ERR(priv, "Unable to init nic\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index cc88401960e4..f6aa5ce478b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2757,14 +2757,14 @@ void iwl_bg_monitor_recover(unsigned long data) return; /* monitor and check for stuck cmd queue */ - if (iwl_check_stuck_queue(priv, IWL_CMD_QUEUE_NUM)) + if (iwl_check_stuck_queue(priv, priv->cmd_queue)) return; /* monitor and check for other stuck queues */ if (iwl_is_any_associated(priv)) { for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { /* skip as we already checked the command queue */ - if (cnt == IWL_CMD_QUEUE_NUM) + if (cnt == priv->cmd_queue) continue; if (iwl_check_stuck_queue(priv, cnt)) return; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 6b188926014b..7cafb26a5f52 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -265,11 +265,10 @@ struct iwl_channel_info { #define IWL_MIN_NUM_QUEUES 10 /* - * Queue #4 is the command queue for 3945/4965/5x00/1000/6x00, - * the driver maps it into the appropriate device FIFO for the - * uCode. + * Command queue depends on iPAN support. */ -#define IWL_CMD_QUEUE_NUM 4 +#define IWL_DEFAULT_CMD_QUEUE_NUM 4 +#define IWL_IPAN_CMD_QUEUE_NUM 9 /* Power management (not Tx power) structures */ @@ -1197,6 +1196,9 @@ struct iwl_priv { /* microcode/device supports multiple contexts */ u8 valid_contexts; + /* command queue number */ + u8 cmd_queue; + /* EEPROM MAC addresses */ struct mac_address addresses[2]; diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 1f15b3aa8478..9fb2035e4eca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -232,7 +232,7 @@ cancel: * in later, it will possibly set an invalid * address (cmd->meta.source). */ - priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_idx].flags &= + priv->txq[priv->cmd_queue].meta[cmd_idx].flags &= ~CMD_WANT_SKB; } fail: diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index b1f101caf19d..5469655646ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -306,7 +306,7 @@ * at a time, until receiving ACK from receiving station, or reaching * retry limit and giving up. * - * The command queue (#4) must use this mode! + * The command queue (#4/#9) must use this mode! * This mode does not require use of the Byte Count table in host DRAM. * * Driver controls scheduler operation via 3 means: @@ -322,7 +322,7 @@ * (1024 bytes for each queue). * * After receiving "Alive" response from uCode, driver must initialize - * the scheduler (especially for queue #4, the command queue, otherwise + * the scheduler (especially for queue #4/#9, the command queue, otherwise * the driver can't issue commands!): */ @@ -555,8 +555,9 @@ #define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ ((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) -#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\ - (~(1<hw_params.max_txq_num) - 1) &\ + (~(1<<(priv)->cmd_queue))) #define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index c308dab14673..347d3dc6a015 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -134,7 +134,7 @@ EXPORT_SYMBOL(iwl_tx_queue_free); */ void iwl_cmd_queue_free(struct iwl_priv *priv) { - struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; + struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; struct iwl_queue *q = &txq->q; struct device *dev = &priv->pci_dev->dev; int i; @@ -271,7 +271,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, /* Driver private data, only for Tx (not command) queues, * not shared with device. */ - if (id != IWL_CMD_QUEUE_NUM) { + if (id != priv->cmd_queue) { txq->txb = kzalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX, GFP_KERNEL); if (!txq->txb) { @@ -314,13 +314,13 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, /* * Alloc buffer array for commands (Tx or other types of commands). - * For the command queue (#4), allocate command space + one big + * For the command queue (#4/#9), allocate command space + one big * command for scan, since scan command is very huge; the system will * not have two scans at the same time, so only one is needed. * For normal Tx queues (all other queues), no super-size command * space is needed. */ - if (txq_id == IWL_CMD_QUEUE_NUM) + if (txq_id == priv->cmd_queue) actual_slots++; txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots, @@ -355,7 +355,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, * need an swq_id so don't set one to catch errors, all others can * be set up to the identity mapping. */ - if (txq_id != IWL_CMD_QUEUE_NUM) + if (txq_id != priv->cmd_queue) txq->swq_id = txq_id; /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise @@ -385,7 +385,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, { int actual_slots = slots_num; - if (txq_id == IWL_CMD_QUEUE_NUM) + if (txq_id == priv->cmd_queue) actual_slots++; memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); @@ -413,7 +413,7 @@ EXPORT_SYMBOL(iwl_tx_queue_reset); */ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { - struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; + struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; struct iwl_queue *q = &txq->q; struct iwl_device_cmd *out_cmd; struct iwl_cmd_meta *out_meta; @@ -483,7 +483,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) * information */ out_cmd->hdr.flags = 0; - out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) | + out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) | INDEX_TO_SEQ(q->write_ptr)); if (cmd->flags & CMD_SIZE_HUGE) out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; @@ -500,15 +500,15 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) get_cmd_string(out_cmd->hdr.cmd), out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), fix_size, - q->write_ptr, idx, IWL_CMD_QUEUE_NUM); - break; + q->write_ptr, idx, priv->cmd_queue); + break; default: IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " "%d bytes at %d[%d]:%d\n", get_cmd_string(out_cmd->hdr.cmd), out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), fix_size, - q->write_ptr, idx, IWL_CMD_QUEUE_NUM); + q->write_ptr, idx, priv->cmd_queue); } #endif txq->need_update = 1; @@ -587,16 +587,16 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; - struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; + struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ - if (WARN(txq_id != IWL_CMD_QUEUE_NUM, - "wrong command queue %d, sequence 0x%X readp=%d writep=%d\n", - txq_id, sequence, - priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr, - priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) { + if (WARN(txq_id != priv->cmd_queue, + "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", + txq_id, priv->cmd_queue, sequence, + priv->txq[priv->cmd_queue].q.read_ptr, + priv->txq[priv->cmd_queue].q.write_ptr)) { iwl_print_hex_error(priv, pkt, 32); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 234d6b430fcf..02e0a9bbad16 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4001,6 +4001,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv = hw->priv; SET_IEEE80211_DEV(hw, &pdev->dev); + priv->cmd_queue = IWL39_CMD_QUEUE_NUM; + /* 3945 has only one valid context */ priv->valid_contexts = BIT(IWL_RXON_CTX_BSS); -- cgit v1.2.3-59-g8ed1b From 751ca305d0e37f0d44b6a261e7db31aa6b60fbf4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:34 +0200 Subject: iwlwifi: define PAN queues/FIFOs PAN capable microcode has a different queue assignment (not just more queues for PAN) due to the way multicast is handled for AP mode. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 10 +++++----- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 ++++- drivers/net/wireless/iwlwifi/iwl-dev.h | 15 +++++++++++++-- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index a9ea7a1fef02..a7961bf395fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -57,11 +57,11 @@ static const s8 iwlagn_ipan_queue_to_tx_fifo[] = { IWL_TX_FIFO_VI, IWL_TX_FIFO_BE, IWL_TX_FIFO_BK, - IWL_TX_FIFO_UNUSED, /* FIXME */ - IWL_TX_FIFO_UNUSED, /* FIXME */ - IWL_TX_FIFO_UNUSED, /* FIXME */ - IWL_TX_FIFO_UNUSED, /* FIXME */ - IWL_TX_FIFO_UNUSED, /* FIXME */ + IWL_TX_FIFO_BK_IPAN, + IWL_TX_FIFO_BE_IPAN, + IWL_TX_FIFO_VI_IPAN, + IWL_TX_FIFO_VO_IPAN, + IWL_TX_FIFO_BE_IPAN, IWLAGN_CMD_FIFO_NUM, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index cfc8e8de8798..5f67955c76cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3012,7 +3012,10 @@ static int __iwl_up(struct iwl_priv *priv) iwl_write32(priv, CSR_INT, 0xFFFFFFFF); /* must be initialised before iwl_hw_nic_init */ - priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) + priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; + else + priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; ret = iwlagn_hw_nic_init(priv); if (ret) { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 7cafb26a5f52..8ec377d514fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -253,10 +253,14 @@ struct iwl_channel_info { struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; }; -#define IWL_TX_FIFO_BK 0 +#define IWL_TX_FIFO_BK 0 /* shared */ #define IWL_TX_FIFO_BE 1 -#define IWL_TX_FIFO_VI 2 +#define IWL_TX_FIFO_VI 2 /* shared */ #define IWL_TX_FIFO_VO 3 +#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK +#define IWL_TX_FIFO_BE_IPAN 4 +#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI +#define IWL_TX_FIFO_VO_IPAN 5 #define IWL_TX_FIFO_UNUSED -1 /* Minimum number of queues. MAX_NUM is defined in hw specific files. @@ -270,6 +274,13 @@ struct iwl_channel_info { #define IWL_DEFAULT_CMD_QUEUE_NUM 4 #define IWL_IPAN_CMD_QUEUE_NUM 9 +/* + * This queue number is required for proper operation + * because the ucode will stop/start the scheduler as + * required. + */ +#define IWL_IPAN_MCAST_QUEUE 8 + /* Power management (not Tx power) structures */ enum iwl_pwr_src { -- cgit v1.2.3-59-g8ed1b From a194e3249baf954dc34c67cdad5b8bed36f49e72 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 08:53:46 -0700 Subject: iwlwifi: contextify broadcast station The broadcast station ID is per context, so add a variable for the ID in the context and use it everywhere we previously hardcoded it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 11 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 6 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-6000.c | 6 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 9 ++- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 9 ++- drivers/net/wireless/iwlwifi/iwl-agn.c | 32 +++++++---- drivers/net/wireless/iwlwifi/iwl-core.c | 4 +- drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 89 +++++++++++++++++------------ drivers/net/wireless/iwlwifi/iwl-sta.h | 29 +++++----- drivers/net/wireless/iwlwifi/iwl3945-base.c | 20 ++++--- 15 files changed, 142 insertions(+), 93 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 3bf5a30828be..674fb93ae17f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -130,7 +130,7 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) sizeof(struct iwlagn_scd_bc_tbl); priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.max_stations = IWLAGN_STATION_COUNT; - priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID; + priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; @@ -217,7 +217,7 @@ static struct iwl_lib_ops iwl1000_lib = { .set_ct_kill = iwl1000_set_ct_threshold, }, .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_station = iwl_update_bcast_station, + .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 08f53f869c18..0cfc7a605e3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -343,7 +343,7 @@ void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 s int i; IWL_DEBUG_INFO(priv, "enter\n"); - if (sta_id == priv->hw_params.bcast_sta_id) + if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id) goto out; psta = (struct iwl3945_sta_priv *) sta->drv_priv; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index f059b1dd4d41..905575c840cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2305,8 +2305,10 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv, int ret; if (add) { - ret = iwl_add_bssid_station(priv, vif->bss_conf.bssid, false, - &vif_priv->ibss_bssid_sta_id); + ret = iwl_add_bssid_station( + priv, &priv->contexts[IWL_RXON_CTX_BSS], + vif->bss_conf.bssid, false, + &vif_priv->ibss_bssid_sta_id); if (ret) return ret; @@ -2424,7 +2426,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; priv->hw_params.max_stations = IWL3945_STATION_COUNT; - priv->hw_params.bcast_sta_id = IWL3945_BROADCAST_ID; + priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID; priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR; priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL; @@ -2442,7 +2444,8 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv, tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u; memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); - tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; + tx_beacon_cmd->tx.sta_id = + priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; frame_size = iwl3945_fill_beacon_frame(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index cda389c3b025..c155816f811b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -657,7 +657,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) sizeof(struct iwl4965_scd_bc_tbl); priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.max_stations = IWL4965_STATION_COUNT; - priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; + priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL4965_BROADCAST_ID; priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE; priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; @@ -2010,7 +2010,7 @@ static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) start = IWL_STA_ID; if (is_broadcast_ether_addr(addr)) - return priv->hw_params.bcast_sta_id; + return priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id; spin_lock_irqsave(&priv->sta_lock, flags); for (i = start; i < priv->hw_params.max_stations; i++) @@ -2283,7 +2283,7 @@ static struct iwl_lib_ops iwl4965_lib = { .set_ct_kill = iwl4965_set_ct_threshold, }, .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_station = iwl_update_bcast_station, + .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 8536f19d7dcc..d67031f080c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -180,7 +180,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) sizeof(struct iwlagn_scd_bc_tbl); priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.max_stations = IWLAGN_STATION_COUNT; - priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID; + priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; @@ -227,7 +227,7 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) sizeof(struct iwlagn_scd_bc_tbl); priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.max_stations = IWLAGN_STATION_COUNT; - priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID; + priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; @@ -398,7 +398,7 @@ static struct iwl_lib_ops iwl5000_lib = { .set_ct_kill = iwl5000_set_ct_threshold, }, .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_station = iwl_update_bcast_station, + .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -469,7 +469,7 @@ static struct iwl_lib_ops iwl5150_lib = { .set_ct_kill = iwl5150_set_ct_threshold, }, .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_station = iwl_update_bcast_station, + .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index bf1fe25fae73..8c4a98b82e35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -161,7 +161,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) sizeof(struct iwlagn_scd_bc_tbl); priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.max_stations = IWLAGN_STATION_COUNT; - priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID; + priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; @@ -323,7 +323,7 @@ static struct iwl_lib_ops iwl6000_lib = { .set_calib_version = iwl6000_set_calib_version, }, .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_station = iwl_update_bcast_station, + .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -398,7 +398,7 @@ static struct iwl_lib_ops iwl6000g2b_lib = { .set_calib_version = iwl6000_set_calib_version, }, .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_station = iwl_update_bcast_station, + .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index f919977d5632..cb3c173e7c86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1163,6 +1163,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) }; struct iwl_scan_cmd *scan; struct ieee80211_conf *conf = NULL; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; u32 rate_flags = 0; u16 cmd_len; u16 rx_chain = 0; @@ -1175,6 +1176,9 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) u8 active_chains; u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; + if (vif) + ctx = iwl_rxon_ctx_from_vif(vif); + conf = ieee80211_get_hw_conf(priv->hw); cancel_delayed_work(&priv->scan_check); @@ -1283,7 +1287,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; + scan->tx_cmd.sta_id = ctx->bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; switch (priv->scan_band) { @@ -1446,7 +1450,8 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; if (add) - return iwl_add_bssid_station(priv, vif->bss_conf.bssid, true, + return iwl_add_bssid_station(priv, vif_priv->ctx, + vif->bss_conf.bssid, true, &vif_priv->ibss_bssid_sta_id); return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, vif->bss_conf.bssid); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 88b7bbfb1f91..a2e4ca0eb7c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -531,6 +531,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct iwl_device_cmd *out_cmd; struct iwl_cmd_meta *out_meta; struct iwl_tx_cmd *tx_cmd; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; int swq_id, txq_id; dma_addr_t phys_addr; dma_addr_t txcmd_phys; @@ -545,6 +546,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) u8 *qc = NULL; unsigned long flags; + if (info->control.vif) + ctx = iwl_rxon_ctx_from_vif(info->control.vif); + spin_lock_irqsave(&priv->lock, flags); if (iwl_is_rfkill(priv)) { IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); @@ -565,7 +569,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); /* Find index into station table for destination station */ - sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta); + sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); @@ -577,8 +581,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (sta) sta_priv = (void *)sta->drv_priv; - if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && - sta_priv->asleep) { + if (sta_priv && sta_priv->asleep) { WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); /* * This sends an asynchronous command to the device, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5f67955c76cf..d2222782f46c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -357,7 +357,9 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, /* Set up TX command fields */ tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); - tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; +#warning "Use proper STA ID" + tx_beacon_cmd->tx.sta_id = + priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; @@ -2829,7 +2831,7 @@ static void __iwl_down(struct iwl_priv *priv) del_timer_sync(&priv->monitor_recover); iwl_clear_ucode_stations(priv); - iwl_dealloc_bcast_station(priv); + iwl_dealloc_bcast_stations(priv); iwl_clear_driver_stations(priv); /* reset BT coex data */ @@ -2971,6 +2973,7 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv) static int __iwl_up(struct iwl_priv *priv) { + struct iwl_rxon_context *ctx; int i; int ret; @@ -2984,9 +2987,13 @@ static int __iwl_up(struct iwl_priv *priv) return -EIO; } - ret = iwl_alloc_bcast_station(priv, true); - if (ret) - return ret; + for_each_context(priv, ctx) { + ret = iwl_alloc_bcast_station(priv, ctx, true); + if (ret) { + iwl_dealloc_bcast_stations(priv); + return ret; + } + } iwl_prepare_card_hw(priv); @@ -3520,9 +3527,11 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; + IWL_DEBUG_MAC80211(priv, "enter\n"); - iwl_update_tkip_key(priv, keyconf, sta, + iwl_update_tkip_key(priv, vif_priv->ctx, keyconf, sta, iv32, phase1key); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -3534,6 +3543,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; int ret; u8 sta_id; bool is_default_wep_key = false; @@ -3545,7 +3555,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - sta_id = iwl_sta_id_or_broadcast(priv, sta); + sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta); if (sta_id == IWL_INVALID_STATION) return -EINVAL; @@ -3573,7 +3583,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (is_default_wep_key) ret = iwl_set_default_wep_key(priv, key); else - ret = iwl_set_dynamic_key(priv, key, sta_id); + ret = iwl_set_dynamic_key(priv, vif_priv->ctx, + key, sta_id); IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); break; @@ -3713,6 +3724,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; bool is_ap = vif->type == NL80211_IFTYPE_STATION; int ret; u8 sta_id; @@ -3728,8 +3740,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, if (vif->type == NL80211_IFTYPE_AP) sta_priv->client = true; - ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, - &sta_id); + ret = iwl_add_station_common(priv, vif_priv->ctx, sta->addr, + is_ap, &sta->ht_cap, &sta_id); if (ret) { IWL_ERR(priv, "Unable to add station %pM (%d)\n", sta->addr, ret); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f6aa5ce478b4..f7bfe59c0ca8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2113,8 +2113,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) spin_unlock_irqrestore(&priv->lock, flags); - if (priv->cfg->ops->lib->update_bcast_station) - ret = priv->cfg->ops->lib->update_bcast_station(priv); + if (priv->cfg->ops->lib->update_bcast_stations) + ret = priv->cfg->ops->lib->update_bcast_stations(priv); set_ch_out: /* The list of supported rates and rate mask can be different diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 80c256246e4d..7aa9c6c5c43e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -206,7 +206,7 @@ struct iwl_lib_ops { /* station management */ int (*manage_ibss_station)(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add); - int (*update_bcast_station)(struct iwl_priv *priv); + int (*update_bcast_stations)(struct iwl_priv *priv); /* recover from tx queue stall */ void (*recover_from_tx_stall)(unsigned long data); /* check for plcp health */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 8ec377d514fb..f51c07c078cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -681,7 +681,6 @@ struct iwl_sensitivity_ranges { * @rx_page_order: Rx buffer page order * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR * @max_stations: - * @bcast_sta_id: * @ht40_channel: is 40MHz width possible in band 2.4 * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) * @sw_crypto: 0 for hw, 1 for sw @@ -705,7 +704,6 @@ struct iwl_hw_params { u32 rx_page_order; u32 rx_wrt_ptr_reg; u8 max_stations; - u8 bcast_sta_id; u8 ht40_channel; u8 max_beacon_itrvl; /* in 1024 ms */ u32 max_inst_size; @@ -1126,6 +1124,8 @@ struct iwl_rxon_context { struct iwl_rxon_cmd staging; struct iwl_rxon_time_cmd timing; + + u8 bcast_sta_id; }; struct iwl_priv { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 43afb8fb36c3..b1275e34520d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -226,8 +226,8 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, * * should be called with sta_lock held */ -static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, - bool is_ap, +static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + const u8 *addr, bool is_ap, struct ieee80211_sta_ht_cap *ht_info) { struct iwl_station_entry *station; @@ -238,7 +238,7 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, if (is_ap) sta_id = IWL_AP_ID; else if (is_broadcast_ether_addr(addr)) - sta_id = priv->hw_params.bcast_sta_id; + sta_id = ctx->bcast_sta_id; else for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { if (!compare_ether_addr(priv->stations[i].sta.sta.addr, @@ -313,10 +313,9 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, /** * iwl_add_station_common - */ -int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, - bool is_ap, - struct ieee80211_sta_ht_cap *ht_info, - u8 *sta_id_r) +int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + const u8 *addr, bool is_ap, + struct ieee80211_sta_ht_cap *ht_info, u8 *sta_id_r) { unsigned long flags_spin; int ret = 0; @@ -325,7 +324,7 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, *sta_id_r = 0; spin_lock_irqsave(&priv->sta_lock, flags_spin); - sta_id = iwl_prep_station(priv, addr, is_ap, ht_info); + sta_id = iwl_prep_station(priv, ctx, addr, is_ap, ht_info); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Unable to prepare station %pM for addition\n", addr); @@ -431,8 +430,8 @@ static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, * * Function sleeps. */ -int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, - u8 *sta_id_r) +int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + const u8 *addr, bool init_rs, u8 *sta_id_r) { int ret; u8 sta_id; @@ -442,7 +441,7 @@ int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, if (sta_id_r) *sta_id_r = IWL_INVALID_STATION; - ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); + ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id); if (ret) { IWL_ERR(priv, "Unable to add station %pM\n", addr); return ret; @@ -833,8 +832,9 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, EXPORT_SYMBOL(iwl_set_default_wep_key); static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + u8 sta_id) { unsigned long flags; __le16 key_flags = 0; @@ -851,7 +851,7 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, if (keyconf->keylen == WEP_KEY_LEN_128) key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; - if (sta_id == priv->hw_params.bcast_sta_id) + if (sta_id == ctx->bcast_sta_id) key_flags |= STA_KEY_MULTICAST_MSK; spin_lock_irqsave(&priv->sta_lock, flags); @@ -887,8 +887,9 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, } static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + u8 sta_id) { unsigned long flags; __le16 key_flags = 0; @@ -900,7 +901,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags &= ~STA_KEY_FLG_INVALID; - if (sta_id == priv->hw_params.bcast_sta_id) + if (sta_id == ctx->bcast_sta_id) key_flags |= STA_KEY_MULTICAST_MSK; keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; @@ -936,8 +937,9 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, } static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + u8 sta_id) { unsigned long flags; int ret = 0; @@ -947,7 +949,7 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags &= ~STA_KEY_FLG_INVALID; - if (sta_id == priv->hw_params.bcast_sta_id) + if (sta_id == ctx->bcast_sta_id) key_flags |= STA_KEY_MULTICAST_MSK; keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; @@ -982,8 +984,9 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, } void iwl_update_tkip_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) { u8 sta_id; unsigned long flags; @@ -995,7 +998,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv, return; } - sta_id = iwl_sta_id_or_broadcast(priv, sta); + sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta); if (sta_id == IWL_INVALID_STATION) return; @@ -1080,8 +1083,8 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_remove_dynamic_key); -int iwl_set_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, u8 sta_id) +int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, u8 sta_id) { int ret; @@ -1092,14 +1095,14 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, switch (keyconf->cipher) { case WLAN_CIPHER_SUITE_CCMP: - ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); + ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id); break; case WLAN_CIPHER_SUITE_TKIP: - ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id); + ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id); break; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: - ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id); + ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id); break; default: IWL_ERR(priv, @@ -1229,14 +1232,15 @@ EXPORT_SYMBOL(iwl_send_lq_cmd); * and marks it driver active, so that it will be restored to the * device at the next best time. */ -int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq) +int iwl_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + bool init_lq) { struct iwl_link_quality_cmd *link_cmd; unsigned long flags; u8 sta_id; spin_lock_irqsave(&priv->sta_lock, flags); - sta_id = iwl_prep_station(priv, iwl_bcast_addr, false, NULL); + sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Unable to prepare broadcast station\n"); spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -1271,11 +1275,12 @@ EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station); * Only used by iwlagn. Placed here to have all bcast station management * code together. */ -int iwl_update_bcast_station(struct iwl_priv *priv) +static int iwl_update_bcast_station(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { unsigned long flags; struct iwl_link_quality_cmd *link_cmd; - u8 sta_id = priv->hw_params.bcast_sta_id; + u8 sta_id = ctx->bcast_sta_id; link_cmd = iwl_sta_alloc_lq(priv, sta_id); if (!link_cmd) { @@ -1293,9 +1298,23 @@ int iwl_update_bcast_station(struct iwl_priv *priv) return 0; } -EXPORT_SYMBOL_GPL(iwl_update_bcast_station); -void iwl_dealloc_bcast_station(struct iwl_priv *priv) +int iwl_update_bcast_stations(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx; + int ret = 0; + + for_each_context(priv, ctx) { + ret = iwl_update_bcast_station(priv, ctx); + if (ret) + break; + } + + return ret; +} +EXPORT_SYMBOL_GPL(iwl_update_bcast_stations); + +void iwl_dealloc_bcast_stations(struct iwl_priv *priv) { unsigned long flags; int i; @@ -1313,7 +1332,7 @@ void iwl_dealloc_bcast_station(struct iwl_priv *priv) } spin_unlock_irqrestore(&priv->sta_lock, flags); } -EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station); +EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations); /** * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index d38a350ba0bd..8a978c6e105f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -48,28 +48,29 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, int iwl_set_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); int iwl_restore_default_wep_keys(struct iwl_priv *priv); -int iwl_set_dynamic_key(struct iwl_priv *priv, +int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct ieee80211_key_conf *key, u8 sta_id); int iwl_remove_dynamic_key(struct iwl_priv *priv, struct ieee80211_key_conf *key, u8 sta_id); void iwl_update_tkip_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); void iwl_restore_stations(struct iwl_priv *priv); void iwl_clear_ucode_stations(struct iwl_priv *priv); -int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq); -void iwl_dealloc_bcast_station(struct iwl_priv *priv); -int iwl_update_bcast_station(struct iwl_priv *priv); +int iwl_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + bool init_lq); +void iwl_dealloc_bcast_stations(struct iwl_priv *priv); +int iwl_update_bcast_stations(struct iwl_priv *priv); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags); -int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, - u8 *sta_id_r); -int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, - bool is_ap, - struct ieee80211_sta_ht_cap *ht_info, - u8 *sta_id_r); +int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + const u8 *addr, bool init_rs, u8 *sta_id_r); +int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + const u8 *addr, bool is_ap, + struct ieee80211_sta_ht_cap *ht_info, u8 *sta_id_r); int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, const u8 *addr); int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -123,6 +124,7 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta) /** * iwl_sta_id_or_broadcast - return sta_id or broadcast sta * @priv: iwl priv + * @context: the current context * @sta: mac80211 station * * In certain circumstances mac80211 passes a station pointer @@ -131,12 +133,13 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta) * inline wraps that pattern. */ static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv, + struct iwl_rxon_context *context, struct ieee80211_sta *sta) { int sta_id; if (!sta) - return priv->hw_params.bcast_sta_id; + return context->bcast_sta_id; sta_id = iwl_sta_id(sta); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 02e0a9bbad16..8b0763264141 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -144,7 +144,7 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv, key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - if (sta_id == priv->hw_params.bcast_sta_id) + if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id) key_flags |= STA_KEY_MULTICAST_MSK; keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; @@ -512,7 +512,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); /* Find index into station table for destination station */ - sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta); + sta_id = iwl_sta_id_or_broadcast( + priv, &priv->contexts[IWL_RXON_CTX_BSS], + info->control.sta); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); @@ -2580,7 +2582,7 @@ static void __iwl3945_down(struct iwl_priv *priv) /* Station information will now be cleared in device */ iwl_clear_ucode_stations(priv); - iwl_dealloc_bcast_station(priv); + iwl_dealloc_bcast_stations(priv); iwl_clear_driver_stations(priv); /* Unblock any waiting calls */ @@ -2662,7 +2664,8 @@ static int __iwl3945_up(struct iwl_priv *priv) { int rc, i; - rc = iwl_alloc_bcast_station(priv, false); + rc = iwl_alloc_bcast_station(priv, &priv->contexts[IWL_RXON_CTX_BSS], + false); if (rc) return rc; @@ -2946,7 +2949,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) /* We don't build a direct scan probe request; the uCode will do * that based on the direct_mask added to each channel entry */ scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; + scan->tx_cmd.sta_id = priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; /* flags + rate selection */ @@ -3330,7 +3333,8 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS); if (!static_key) { - sta_id = iwl_sta_id_or_broadcast(priv, sta); + sta_id = iwl_sta_id_or_broadcast( + priv, &priv->contexts[IWL_RXON_CTX_BSS], sta); if (sta_id == IWL_INVALID_STATION) return -EINVAL; } @@ -3381,8 +3385,8 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, sta_priv->common.sta_id = IWL_INVALID_STATION; - ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, - &sta_id); + ret = iwl_add_station_common(priv, &priv->contexts[IWL_RXON_CTX_BSS], + sta->addr, is_ap, &sta->ht_cap, &sta_id); if (ret) { IWL_ERR(priv, "Unable to add station %pM (%d)\n", sta->addr, ret); -- cgit v1.2.3-59-g8ed1b From dcef732c72fbe960de5069d3921bb6ce6847be58 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 08:55:52 -0700 Subject: iwlwifi: contextify-stations-completely The microcode tracks stations per context, so the driver needs to do that as well for adding, deleting and restoring them, especially in the implicit removal case when we send an RXON. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-3945.c | 10 ++++++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 +++++----- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 11 +++++++++-- drivers/net/wireless/iwlwifi/iwl-sta.h | 5 +++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 6 files changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 905575c840cc..ba3a9f9d519e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1832,8 +1832,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv, "configuration (%d).\n", rc); return rc; } - iwl_clear_ucode_stations(priv); - iwl_restore_stations(priv); + iwl_clear_ucode_stations(priv, + &priv->contexts[IWL_RXON_CTX_BSS]); + iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]); } IWL_DEBUG_INFO(priv, "Sending RXON\n" @@ -1865,8 +1866,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv, memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); if (!new_assoc) { - iwl_clear_ucode_stations(priv); - iwl_restore_stations(priv); + iwl_clear_ucode_stations(priv, + &priv->contexts[IWL_RXON_CTX_BSS]); + iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]); } /* If we issue a new RXON command which required a tune then we must diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d2222782f46c..23db6c3e9aee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -163,8 +163,8 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); return ret; } - iwl_clear_ucode_stations(priv); - iwl_restore_stations(priv); + iwl_clear_ucode_stations(priv, ctx); + iwl_restore_stations(priv, ctx); ret = iwl_restore_default_wep_keys(priv); if (ret) { IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); @@ -195,8 +195,8 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); - iwl_clear_ucode_stations(priv); - iwl_restore_stations(priv); + iwl_clear_ucode_stations(priv, ctx); + iwl_restore_stations(priv, ctx); ret = iwl_restore_default_wep_keys(priv); if (ret) { IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); @@ -2830,7 +2830,7 @@ static void __iwl_down(struct iwl_priv *priv) if (priv->cfg->ops->lib->recover_from_tx_stall) del_timer_sync(&priv->monitor_recover); - iwl_clear_ucode_stations(priv); + iwl_clear_ucode_stations(priv, NULL); iwl_dealloc_bcast_stations(priv); iwl_clear_driver_stations(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f51c07c078cc..da54bd53c99d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -495,7 +495,7 @@ struct iwl_qos_info { struct iwl_station_entry { struct iwl_addsta_cmd sta; struct iwl_tid_data tid[MAX_TID_COUNT]; - u8 used; + u8 used, ctxid; struct iwl_hw_key keyinfo; struct iwl_link_quality_cmd *lq; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index b1275e34520d..29235626ac0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -290,6 +290,7 @@ static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, station->sta.mode = 0; station->sta.sta.sta_id = sta_id; station->sta.station_flags = 0; + station->ctxid = ctx->ctxid; /* * OK to call unconditionally, since local stations (IBSS BSSID @@ -615,7 +616,8 @@ EXPORT_SYMBOL_GPL(iwl_remove_station); * other than explicit station management would cause this in * the ucode, e.g. unassociated RXON. */ -void iwl_clear_ucode_stations(struct iwl_priv *priv) +void iwl_clear_ucode_stations(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { int i; unsigned long flags_spin; @@ -625,6 +627,9 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv) spin_lock_irqsave(&priv->sta_lock, flags_spin); for (i = 0; i < priv->hw_params.max_stations; i++) { + if (ctx && ctx->ctxid != priv->stations[i].ctxid) + continue; + if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; @@ -646,7 +651,7 @@ EXPORT_SYMBOL(iwl_clear_ucode_stations); * * Function sleeps. */ -void iwl_restore_stations(struct iwl_priv *priv) +void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { struct iwl_addsta_cmd sta_cmd; struct iwl_link_quality_cmd lq; @@ -664,6 +669,8 @@ void iwl_restore_stations(struct iwl_priv *priv) IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); spin_lock_irqsave(&priv->sta_lock, flags_spin); for (i = 0; i < priv->hw_params.max_stations; i++) { + if (ctx->ctxid != priv->stations[i].ctxid) + continue; if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) && !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) { IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 8a978c6e105f..269a3ed0f3fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -57,8 +57,9 @@ void iwl_update_tkip_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); -void iwl_restore_stations(struct iwl_priv *priv); -void iwl_clear_ucode_stations(struct iwl_priv *priv); +void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx); +void iwl_clear_ucode_stations(struct iwl_priv *priv, + struct iwl_rxon_context *ctx); int iwl_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, bool init_lq); void iwl_dealloc_bcast_stations(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 8b0763264141..630b8d641720 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2581,7 +2581,7 @@ static void __iwl3945_down(struct iwl_priv *priv) del_timer_sync(&priv->monitor_recover); /* Station information will now be cleared in device */ - iwl_clear_ucode_stations(priv); + iwl_clear_ucode_stations(priv, NULL); iwl_dealloc_bcast_stations(priv); iwl_clear_driver_stations(priv); -- cgit v1.2.3-59-g8ed1b From 8f2d3d2ae17855e396483724f152f223e6f01bfe Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:37 +0200 Subject: iwlwifi: contextify command sending Some commands will have different command IDs for different contexts, so we need to store those IDs in the context structure and use them instead of hardcoding the commands. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 15 ++++++++++----- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++++ 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 3e5069943dde..2d4cdb027aa6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -77,7 +77,7 @@ int iwlagn_send_rxon_assoc(struct iwl_priv *priv, ctx->staging.ofdm_ht_triple_stream_basic_rates; rxon_assoc.acquisition_data = ctx->staging.acquisition_data; - ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, + ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd, sizeof(rxon_assoc), &rxon_assoc, NULL); if (ret) return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 23db6c3e9aee..d3714f076a0c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -152,7 +152,7 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = iwl_send_cmd_pdu(priv, REPLY_RXON, + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(struct iwl_rxon_cmd), active_rxon); @@ -187,7 +187,7 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * stations is needed after it (the RXON command) completes */ if (!new_assoc) { - ret = iwl_send_cmd_pdu(priv, REPLY_RXON, + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(struct iwl_rxon_cmd), &ctx->staging); if (ret) { IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); @@ -209,7 +209,7 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) /* Apply the new configuration * RXON assoc doesn't clear the station table in uCode, */ - ret = iwl_send_cmd_pdu(priv, REPLY_RXON, + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(struct iwl_rxon_cmd), &ctx->staging); if (ret) { IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); @@ -3244,7 +3244,7 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) ret = iwl_send_rxon_timing(priv, vif); if (ret) - IWL_WARN(priv, "REPLY_RXON_TIMING failed - " + IWL_WARN(priv, "RXON timing - " "Attempting to continue.\n"); ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; @@ -3481,7 +3481,7 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) /* RXON Timing */ ret = iwl_send_rxon_timing(priv, vif); if (ret) - IWL_WARN(priv, "REPLY_RXON_TIMING failed - " + IWL_WARN(priv, "RXON timing failed - " "Attempting to continue.\n"); /* AP has all antennas */ @@ -4200,6 +4200,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) for (i = 0; i < NUM_IWL_RXON_CTX; i++) priv->contexts[i].ctxid = i; + priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON; + priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING; + priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; + BUILD_BUG_ON(NUM_IWL_RXON_CTX != 1); + SET_IEEE80211_DEV(hw, &pdev->dev); IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f7bfe59c0ca8..a145d17cd943 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -545,7 +545,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) le32_to_cpu(ctx->timing.beacon_init_val), le16_to_cpu(ctx->timing.atim_window)); - return iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, + return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd, sizeof(ctx->timing), &ctx->timing); } EXPORT_SYMBOL(iwl_send_rxon_timing); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index da54bd53c99d..6a7e9ff4a88c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1126,6 +1126,8 @@ struct iwl_rxon_context { struct iwl_rxon_time_cmd timing; u8 bcast_sta_id; + + u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd; }; struct iwl_priv { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 630b8d641720..4321d970d58d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4013,6 +4013,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e for (i = 0; i < NUM_IWL_RXON_CTX; i++) priv->contexts[i].ctxid = i; + priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON; + priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING; + priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; + /* * Disabling hardware scan means that mac80211 will perform scans * "the hard way", rather than using device's scan. -- cgit v1.2.3-59-g8ed1b From 8dfdb9d5757424f7018a643258065c4fc8e6a439 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:38 +0200 Subject: iwlwifi: move QoS into context Since mac80211 doesn't currently enable/disable QoS per interface, we can't yet do it properly, but we can already prepare for it and move the QoS data and command ID into the context struct. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 43 +++++++++++++++++------------ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 24 ++++++++++------ drivers/net/wireless/iwlwifi/iwl-dev.h | 5 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 + 5 files changed, 46 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d3714f076a0c..007dede73698 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -4203,6 +4203,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON; priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING; priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; + priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; BUILD_BUG_ON(NUM_IWL_RXON_CTX != 1); SET_IEEE80211_DEV(hw, &pdev->dev); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a145d17cd943..d5499db34eb2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -191,27 +191,27 @@ EXPORT_SYMBOL(iwl_alloc_all); /* * QoS support */ -static void iwl_update_qos(struct iwl_priv *priv) +static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - priv->qos_data.def_qos_parm.qos_flags = 0; + ctx->qos_data.def_qos_parm.qos_flags = 0; - if (priv->qos_data.qos_active) - priv->qos_data.def_qos_parm.qos_flags |= + if (ctx->qos_data.qos_active) + ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_UPDATE_EDCA_MSK; if (priv->current_ht_config.is_ht) - priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; + ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", - priv->qos_data.qos_active, - priv->qos_data.def_qos_parm.qos_flags); + ctx->qos_data.qos_active, + ctx->qos_data.def_qos_parm.qos_flags); - iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, + iwl_send_cmd_pdu_async(priv, ctx->qos_cmd, sizeof(struct iwl_qosparam_cmd), - &priv->qos_data.def_qos_parm, NULL); + &ctx->qos_data.def_qos_parm, NULL); } #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ @@ -1584,6 +1584,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx; unsigned long flags; int q; @@ -1603,13 +1604,21 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, spin_lock_irqsave(&priv->lock, flags); - priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); - priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); - priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; - priv->qos_data.def_qos_parm.ac[q].edca_txop = - cpu_to_le16((params->txop * 32)); + /* + * MULTI-FIXME + * This may need to be done per interface in nl80211/cfg80211/mac80211. + */ + for_each_context(priv, ctx) { + ctx->qos_data.def_qos_parm.ac[q].cw_min = + cpu_to_le16(params->cw_min); + ctx->qos_data.def_qos_parm.ac[q].cw_max = + cpu_to_le16(params->cw_max); + ctx->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; + ctx->qos_data.def_qos_parm.ac[q].edca_txop = + cpu_to_le16((params->txop * 32)); - priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; + ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0; + } spin_unlock_irqrestore(&priv->lock, flags); @@ -1751,8 +1760,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - priv->qos_data.qos_active = bss_conf->qos; - iwl_update_qos(priv); + ctx->qos_data.qos_active = bss_conf->qos; + iwl_update_qos(priv, ctx); spin_unlock_irqrestore(&priv->lock, flags); } diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d36418c3a6b5..0ee8f516c4ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -643,19 +643,25 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; + struct iwl_rxon_context *ctx; int pos = 0, i; - char buf[256]; + char buf[256 * NUM_IWL_RXON_CTX]; const size_t bufsz = sizeof(buf); - for (i = 0; i < AC_NUM; i++) { - pos += scnprintf(buf + pos, bufsz - pos, - "\tcw_min\tcw_max\taifsn\ttxop\n"); - pos += scnprintf(buf + pos, bufsz - pos, + for_each_context(priv, ctx) { + pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n", + ctx->ctxid); + for (i = 0; i < AC_NUM; i++) { + pos += scnprintf(buf + pos, bufsz - pos, + "\tcw_min\tcw_max\taifsn\ttxop\n"); + pos += scnprintf(buf + pos, bufsz - pos, "AC[%d]\t%u\t%u\t%u\t%u\n", i, - priv->qos_data.def_qos_parm.ac[i].cw_min, - priv->qos_data.def_qos_parm.ac[i].cw_max, - priv->qos_data.def_qos_parm.ac[i].aifsn, - priv->qos_data.def_qos_parm.ac[i].edca_txop); + ctx->qos_data.def_qos_parm.ac[i].cw_min, + ctx->qos_data.def_qos_parm.ac[i].cw_max, + ctx->qos_data.def_qos_parm.ac[i].aifsn, + ctx->qos_data.def_qos_parm.ac[i].edca_txop); + } + pos += scnprintf(buf + pos, bufsz - pos, "\n"); } return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 6a7e9ff4a88c..01a654e6db26 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1125,9 +1125,12 @@ struct iwl_rxon_context { struct iwl_rxon_time_cmd timing; + struct iwl_qos_info qos_data; + u8 bcast_sta_id; u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd; + u8 qos_cmd; }; struct iwl_priv { @@ -1418,8 +1421,6 @@ struct iwl_priv { u32 inta_mask; - struct iwl_qos_info qos_data; - struct workqueue_struct *workqueue; struct work_struct restart; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4321d970d58d..09bca17255b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4016,6 +4016,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON; priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING; priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; + priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; /* * Disabling hardware scan means that mac80211 will perform scans -- cgit v1.2.3-59-g8ed1b From c90cbbbd78e45abbefd5e9e1c3c179d6126e3ddf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:39 +0200 Subject: iwlwifi: add context into tx descriptor In status processing we'll need to find the context for a given frame, so add a context pointer to the TX info for each frame. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index a2e4ca0eb7c6..bff593ab0944 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -640,6 +640,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Set up driver data for this TFD */ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); txq->txb[q->write_ptr].skb = skb; + txq->txb[q->write_ptr].ctx = ctx; /* Set up first empty entry in queue's array of Tx/cmd buffers */ out_cmd = txq->cmd[q->write_ptr]; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 01a654e6db26..90bf6b317fc7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -144,6 +144,7 @@ struct iwl_queue { /* One for each TFD */ struct iwl_tx_info { struct sk_buff *skb; + struct iwl_rxon_context *ctx; }; /** diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 09bca17255b4..aef5f812c7ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -544,6 +544,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Set up driver data for this TFD */ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); txq->txb[q->write_ptr].skb = skb; + txq->txb[q->write_ptr].ctx = &priv->contexts[IWL_RXON_CTX_BSS]; /* Init first empty entry in queue's array of Tx/cmd buffers */ out_cmd = txq->cmd[idx]; -- cgit v1.2.3-59-g8ed1b From 8bd413e611d4324f17e54a2a89b4d09216c22a37 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:40 +0200 Subject: iwlwifi: move virtual interface pointer into context iwlwifi occasionally needs to find the virtual interface pointer to give it to mac80211, but right now it only keeps one. Move it into the context so that we can keep one pointer each. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 10 ++++-- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 17 +++++----- drivers/net/wireless/iwlwifi/iwl-agn.c | 12 +++++--- drivers/net/wireless/iwlwifi/iwl-core.c | 48 +++++++++++++++++++---------- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 +++-- 10 files changed, 66 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 0cfc7a605e3e..d707f5bb1a8b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -932,7 +932,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) rcu_read_lock(); - sta = ieee80211_find_sta(priv->vif, + sta = ieee80211_find_sta(priv->contexts[IWL_RXON_CTX_BSS].vif, priv->stations[sta_id].sta.sta.addr); if (!sta) { IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index c155816f811b..1d6a46d4db59 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1462,7 +1462,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u32 tsf_low; u8 switch_count; u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); - struct ieee80211_vif *vif = priv->vif; + struct ieee80211_vif *vif = ctx->vif; band = priv->band == IEEE80211_BAND_2GHZ; is_ht40 = is_ht40_channel(ctx->staging.flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index d67031f080c8..1dbb1246c083 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -287,7 +287,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u32 tsf_low; u8 switch_count; u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); - struct ieee80211_vif *vif = priv->vif; + struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, .len = sizeof(cmd), diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 8c4a98b82e35..2fdba088bd27 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -210,7 +210,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u32 tsf_low; u8 switch_count; u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); - struct ieee80211_vif *vif = priv->vif; + struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, .len = sizeof(cmd), diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index cb3c173e7c86..7002d7d0fac4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1720,6 +1720,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, bt_traffic_change_work); + struct iwl_rxon_context *ctx; int smps_request = -1; IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n", @@ -1747,9 +1748,12 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) if (priv->cfg->ops->lib->update_chain_flags) priv->cfg->ops->lib->update_chain_flags(priv); - if (smps_request != -1 && - priv->vif && priv->vif->type == NL80211_IFTYPE_STATION) - ieee80211_request_smps(priv->vif, smps_request); + if (smps_request != -1) { + for_each_context(priv, ctx) { + if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) + ieee80211_request_smps(ctx->vif, smps_request); + } + } mutex_unlock(&priv->mutex); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index bff593ab0944..64daddd92279 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1120,6 +1120,9 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, struct iwl_queue *q = &priv->txq[txq_id].q; u8 *addr = priv->stations[sta_id].sta.sta.addr; struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; + struct iwl_rxon_context *ctx; + + ctx = &priv->contexts[priv->stations[sta_id].ctxid]; lockdep_assert_held(&priv->sta_lock); @@ -1135,7 +1138,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, tx_fifo); tid_data->agg.state = IWL_AGG_OFF; - ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); + ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); } break; case IWL_EMPTYING_HW_QUEUE_ADDBA: @@ -1143,7 +1146,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, if (tid_data->tfds_in_queue == 0) { IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); tid_data->agg.state = IWL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); + ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid); } break; } @@ -1151,14 +1154,14 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, return 0; } -static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb) +static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data; struct ieee80211_sta *sta; struct iwl_station_priv *sta_priv; rcu_read_lock(); - sta = ieee80211_find_sta(priv->vif, hdr->addr1); + sta = ieee80211_find_sta(tx_info->ctx->vif, hdr->addr1); if (sta) { sta_priv = (void *)sta->drv_priv; /* avoid atomic ops if this isn't a client */ @@ -1168,7 +1171,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb) } rcu_read_unlock(); - ieee80211_tx_status_irqsafe(priv->hw, skb); + ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb); } int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) @@ -1191,7 +1194,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { tx_info = &txq->txb[txq->q.read_ptr]; - iwlagn_tx_status(priv, tx_info->skb); + iwlagn_tx_status(priv, tx_info); hdr = (struct ieee80211_hdr *)tx_info->skb->data; if (hdr && ieee80211_is_data_qos(hdr->frame_control)) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 007dede73698..5e1df24bdb5f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -603,7 +603,9 @@ static void iwl_bg_beacon_update(struct work_struct *work) struct sk_buff *beacon; /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ - beacon = ieee80211_beacon_get(priv->hw, priv->vif); +#warning "introduce and use beacon context" + beacon = ieee80211_beacon_get(priv->hw, + priv->contexts[IWL_RXON_CTX_BSS].vif); if (!beacon) { IWL_ERR(priv, "update beacon failed\n"); @@ -3154,13 +3156,15 @@ static void iwl_bg_restart(struct work_struct *data) return; if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { + struct iwl_rxon_context *ctx; bool bt_sco, bt_full_concurrent; u8 bt_ci_compliance; u8 bt_load; u8 bt_status; mutex_lock(&priv->mutex); - priv->vif = NULL; + for_each_context(priv, ctx) + ctx->vif = NULL; priv->is_open = 0; /* @@ -3838,7 +3842,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, iwl_set_rxon_channel(priv, channel, ctx); iwl_set_rxon_ht(priv, ht_conf); iwl_set_flags_for_band(priv, ctx, channel->band, - priv->vif); + ctx->vif); spin_unlock_irqrestore(&priv->lock, flags); iwl_set_rate(priv); @@ -3855,7 +3859,7 @@ out: mutex_unlock(&priv->mutex); out_exit: if (!priv->switch_rxon.switch_in_progress) - ieee80211_chswitch_done(priv->vif, false); + ieee80211_chswitch_done(ctx->vif, false); IWL_DEBUG_MAC80211(priv, "leave\n"); } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d5499db34eb2..f9abcd80271c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1133,11 +1133,17 @@ EXPORT_SYMBOL(iwl_set_rate); void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) { + /* + * MULTI-FIXME + * See iwl_mac_channel_switch. + */ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (priv->switch_rxon.switch_in_progress) { - ieee80211_chswitch_done(priv->vif, is_success); + ieee80211_chswitch_done(ctx->vif, is_success); mutex_lock(&priv->mutex); priv->switch_rxon.switch_in_progress = false; mutex_unlock(&priv->mutex); @@ -1149,9 +1155,11 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_csa_notification *csa = &(pkt->u.csa_notif); -#if !TODO + /* + * MULTI-FIXME + * See iwl_mac_channel_switch. + */ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; -#endif struct iwl_rxon_cmd *rxon = (void *)&ctx->active; if (priv->switch_rxon.switch_in_progress) { @@ -1735,7 +1743,9 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) IWL_DEBUG_MAC80211(priv, "leave\n"); spin_unlock_irqrestore(&priv->lock, flags); - priv->cfg->ops->lib->post_associate(priv, priv->vif); +#warning "use beacon context?" + priv->cfg->ops->lib->post_associate( + priv, priv->contexts[IWL_RXON_CTX_BSS].vif); return 0; } @@ -1927,6 +1937,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; + struct iwl_rxon_context *ctx; int err = 0; IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", @@ -1934,20 +1945,23 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mutex_lock(&priv->mutex); - vif_priv->ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + /* For now always use this context. */ + ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + + vif_priv->ctx = ctx; if (WARN_ON(!iwl_is_ready_rf(priv))) { err = -EINVAL; goto out; } - if (priv->vif) { + if (ctx->vif) { IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); err = -EOPNOTSUPP; goto out; } - priv->vif = vif; + ctx->vif = vif; priv->iw_mode = vif->type; err = iwl_set_mode(priv, vif); @@ -1967,7 +1981,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) goto out; out_err: - priv->vif = NULL; + ctx->vif = NULL; priv->iw_mode = NL80211_IFTYPE_STATION; out: mutex_unlock(&priv->mutex); @@ -1993,14 +2007,11 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv, ctx); } - if (priv->vif == vif) { - priv->vif = NULL; - if (priv->scan_vif == vif) { - scan_completed = true; - priv->scan_vif = NULL; - priv->scan_request = NULL; - } - memset(priv->bssid, 0, ETH_ALEN); + + if (priv->scan_vif == vif) { + scan_completed = true; + priv->scan_vif = NULL; + priv->scan_request = NULL; } /* @@ -2013,6 +2024,9 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, if (vif->type == NL80211_IFTYPE_ADHOC) priv->bt_traffic_load = priv->notif_bt_traffic_load; + WARN_ON(ctx->vif != vif); + ctx->vif = NULL; + memset(priv->bssid, 0, ETH_ALEN); mutex_unlock(&priv->mutex); if (scan_completed) @@ -2117,7 +2131,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) iwl_set_rxon_ht(priv, ht_conf); iwl_set_flags_for_band(priv, ctx, channel->band, - priv->vif); + ctx->vif); } spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 90bf6b317fc7..a332ec55f149 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1114,6 +1114,7 @@ enum iwl_rxon_context_id { }; struct iwl_rxon_context { + struct ieee80211_vif *vif; enum iwl_rxon_context_id ctxid; /* * We declare this const so it can only be @@ -1321,7 +1322,6 @@ struct iwl_priv { /* Last Rx'd beacon timestamp */ u64 timestamp; - struct ieee80211_vif *vif; union { #if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index aef5f812c7ef..6b5629570582 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -802,7 +802,8 @@ static void iwl3945_bg_beacon_update(struct work_struct *work) struct sk_buff *beacon; /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ - beacon = ieee80211_beacon_get(priv->hw, priv->vif); + beacon = ieee80211_beacon_get(priv->hw, + priv->contexts[IWL_RXON_CTX_BSS].vif); if (!beacon) { IWL_ERR(priv, "update beacon failed\n"); @@ -3048,8 +3049,10 @@ static void iwl3945_bg_restart(struct work_struct *data) return; if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { + struct iwl_rxon_context *ctx; mutex_lock(&priv->mutex); - priv->vif = NULL; + for_each_context(priv, ctx) + ctx->vif = NULL; priv->is_open = 0; mutex_unlock(&priv->mutex); iwl3945_down(priv); -- cgit v1.2.3-59-g8ed1b From 95c38dd429712366739299579b0785625cba66d6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:41 +0200 Subject: iwlwifi: clamp scanning dwell time to all contexts The dwell time should at least fit into all context's beacon intervals. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-scan.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index fe4cb57c3a1c..556dcaaa0efe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -286,19 +286,28 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, enum ieee80211_band band, struct ieee80211_vif *vif) { + struct iwl_rxon_context *ctx; u16 passive = (band == IEEE80211_BAND_2GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; if (iwl_is_any_associated(priv)) { - /* TODO: should use minimum of all contexts */ - /* If we're associated, we clamp the maximum passive - * dwell time to be 98% of the beacon interval (minus - * 2 * channel tune time) */ - passive = vif ? vif->bss_conf.beacon_int : 0; - if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive) - passive = IWL_PASSIVE_DWELL_BASE; - passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; + /* + * If we're associated, we clamp the maximum passive + * dwell time to be 98% of the smallest beacon interval + * (minus 2 * channel tune time) + */ + for_each_context(priv, ctx) { + u16 value; + + if (!iwl_is_associated_ctx(ctx)) + continue; + value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0; + if ((value > IWL_PASSIVE_DWELL_BASE) || !value) + value = IWL_PASSIVE_DWELL_BASE; + value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; + passive = min(value, passive); + } } return passive; -- cgit v1.2.3-59-g8ed1b From 2995bafafd4d9d2f840b51b0121997be09fb8b47 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:42 +0200 Subject: iwlwifi: move AP sta ID to context Each context needs to use a different AP sta ID, so we need to move that into the context struct instead of hardcoding it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 ++- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 5 +++-- drivers/net/wireless/iwlwifi/iwl-sta.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 + 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5e1df24bdb5f..a67b04b309e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3585,7 +3585,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch (cmd) { case SET_KEY: if (is_default_wep_key) - ret = iwl_set_default_wep_key(priv, key); + ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key); else ret = iwl_set_dynamic_key(priv, vif_priv->ctx, key, sta_id); @@ -4208,6 +4208,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING; priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; + priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; BUILD_BUG_ON(NUM_IWL_RXON_CTX != 1); SET_IEEE80211_DEV(hw, &pdev->dev); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index a332ec55f149..d1400a0926eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1129,7 +1129,7 @@ struct iwl_rxon_context { struct iwl_qos_info qos_data; - u8 bcast_sta_id; + u8 bcast_sta_id, ap_sta_id; u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd; u8 qos_cmd; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 29235626ac0b..f5500cc8a44e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -236,7 +236,7 @@ static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u16 rate; if (is_ap) - sta_id = IWL_AP_ID; + sta_id = ctx->ap_sta_id; else if (is_broadcast_ether_addr(addr)) sta_id = ctx->bcast_sta_id; else @@ -810,6 +810,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, EXPORT_SYMBOL(iwl_remove_default_wep_key); int iwl_set_default_wep_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, struct ieee80211_key_conf *keyconf) { int ret; @@ -824,7 +825,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; keyconf->hw_key_idx = HW_KEY_DEFAULT; - priv->stations[IWL_AP_ID].keyinfo.cipher = keyconf->cipher; + priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher; priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 269a3ed0f3fb..b7f700638dae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -46,6 +46,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); int iwl_set_default_wep_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, struct ieee80211_key_conf *key); int iwl_restore_default_wep_keys(struct iwl_priv *priv); int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6b5629570582..29d13765ff66 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4021,6 +4021,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING; priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; + priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; /* * Disabling hardware scan means that mac80211 will perform scans -- cgit v1.2.3-59-g8ed1b From c10afb6e844b7936092396f719b794c4d0038f27 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:43 +0200 Subject: iwlwifi: make hw crypto context aware HW crypto needs to be aware of the context, and there are different command IDs for the WEP keys per context, so move the key tracking variables and command IDs into the context structure. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-agn.c | 17 ++++++++---- drivers/net/wireless/iwlwifi/iwl-commands.h | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 9 +++++-- drivers/net/wireless/iwlwifi/iwl-sta.c | 41 ++++++++++++++++------------- drivers/net/wireless/iwlwifi/iwl-sta.h | 27 ++++++++++++------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 + 7 files changed, 63 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index ba3a9f9d519e..5d09686c3389 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2430,6 +2430,8 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_stations = IWL3945_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID; + priv->sta_key_max_num = STA_KEY_MAX_NUM; + priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR; priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL; priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a67b04b309e0..837406e53b3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -165,7 +165,7 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } iwl_clear_ucode_stations(priv, ctx); iwl_restore_stations(priv, ctx); - ret = iwl_restore_default_wep_keys(priv); + ret = iwl_restore_default_wep_keys(priv, ctx); if (ret) { IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); return ret; @@ -197,7 +197,7 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); iwl_clear_ucode_stations(priv, ctx); iwl_restore_stations(priv, ctx); - ret = iwl_restore_default_wep_keys(priv); + ret = iwl_restore_default_wep_keys(priv, ctx); if (ret) { IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); return ret; @@ -2222,6 +2222,11 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size; priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; + if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS)) + priv->sta_key_max_num = STA_KEY_MAX_NUM; + else + priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; + /* Copy images into buffers for card's bus-master reads ... */ /* Runtime instructions (first block of data in file) */ @@ -3548,6 +3553,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, { struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; + struct iwl_rxon_context *ctx = vif_priv->ctx; int ret; u8 sta_id; bool is_default_wep_key = false; @@ -3576,7 +3582,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) { if (cmd == SET_KEY) - is_default_wep_key = !priv->key_mapping_key; + is_default_wep_key = !ctx->key_mapping_keys; else is_default_wep_key = (key->hw_key_idx == HW_KEY_DEFAULT); @@ -3594,9 +3600,9 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; case DISABLE_KEY: if (is_default_wep_key) - ret = iwl_remove_default_wep_key(priv, key); + ret = iwl_remove_default_wep_key(priv, ctx, key); else - ret = iwl_remove_dynamic_key(priv, key, sta_id); + ret = iwl_remove_dynamic_key(priv, ctx, key, sta_id); IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); break; @@ -4209,6 +4215,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; + priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; BUILD_BUG_ON(NUM_IWL_RXON_CTX != 1); SET_IEEE80211_DEV(hw, &pdev->dev); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 9b535832f117..55779bf0627b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -1001,6 +1001,7 @@ struct iwl_qosparam_cmd { #define STA_KEY_FLG_KEY_SIZE_MSK cpu_to_le16(0x1000) #define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000) #define STA_KEY_MAX_NUM 8 +#define STA_KEY_MAX_NUM_PAN 16 /* Flags indicate whether to modify vs. don't change various station params */ #define STA_MODIFY_KEY_MASK 0x01 diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d1400a0926eb..ef7862b5e91c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1133,6 +1133,10 @@ struct iwl_rxon_context { u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd; u8 qos_cmd; + u8 wep_key_cmd; + + struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; + u8 key_mapping_keys; }; struct iwl_priv { @@ -1217,6 +1221,9 @@ struct iwl_priv { /* command queue number */ u8 cmd_queue; + /* max number of station keys */ + u8 sta_key_max_num; + /* EEPROM MAC addresses */ struct mac_address addresses[2]; @@ -1296,8 +1303,6 @@ struct iwl_priv { spinlock_t sta_lock; int num_stations; struct iwl_station_entry stations[IWL_STATION_COUNT]; - struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */ - u8 key_mapping_key; unsigned long ucode_key_table; /* queue refcounts */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index f5500cc8a44e..ac6e2be35284 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -724,7 +724,7 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv) { int i; - for (i = 0; i < STA_KEY_MAX_NUM; i++) + for (i = 0; i < priv->sta_key_max_num; i++) if (!test_and_set_bit(i, &priv->ucode_key_table)) return i; @@ -732,7 +732,9 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_get_free_ucode_key_index); -static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) +static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + bool send_if_empty) { int i, not_empty = 0; u8 buff[sizeof(struct iwl_wep_cmd) + @@ -740,7 +742,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff; size_t cmd_size = sizeof(struct iwl_wep_cmd); struct iwl_host_cmd cmd = { - .id = REPLY_WEPKEY, + .id = ctx->wep_key_cmd, .data = wep_cmd, .flags = CMD_SYNC, }; @@ -752,16 +754,16 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) for (i = 0; i < WEP_KEYS_MAX ; i++) { wep_cmd->key[i].key_index = i; - if (priv->wep_keys[i].key_size) { + if (ctx->wep_keys[i].key_size) { wep_cmd->key[i].key_offset = i; not_empty = 1; } else { wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; } - wep_cmd->key[i].key_size = priv->wep_keys[i].key_size; - memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key, - priv->wep_keys[i].key_size); + wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size; + memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key, + ctx->wep_keys[i].key_size); } wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; @@ -777,15 +779,17 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) return 0; } -int iwl_restore_default_wep_keys(struct iwl_priv *priv) +int iwl_restore_default_wep_keys(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { lockdep_assert_held(&priv->mutex); - return iwl_send_static_wepkey_cmd(priv, 0); + return iwl_send_static_wepkey_cmd(priv, ctx, false); } EXPORT_SYMBOL(iwl_restore_default_wep_keys); int iwl_remove_default_wep_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, struct ieee80211_key_conf *keyconf) { int ret; @@ -795,13 +799,13 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", keyconf->keyidx); - memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); + memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); if (iwl_is_rfkill(priv)) { IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); /* but keys in device are clear anyway so return success */ return 0; } - ret = iwl_send_static_wepkey_cmd(priv, 1); + ret = iwl_send_static_wepkey_cmd(priv, ctx, 1); IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", keyconf->keyidx, ret); @@ -827,11 +831,11 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, keyconf->hw_key_idx = HW_KEY_DEFAULT; priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher; - priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; - memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, + ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; + memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key, keyconf->keylen); - ret = iwl_send_static_wepkey_cmd(priv, 0); + ret = iwl_send_static_wepkey_cmd(priv, ctx, false); IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", keyconf->keylen, keyconf->keyidx, ret); @@ -1029,8 +1033,9 @@ void iwl_update_tkip_key(struct iwl_priv *priv, EXPORT_SYMBOL(iwl_update_tkip_key); int iwl_remove_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + u8 sta_id) { unsigned long flags; u16 key_flags; @@ -1039,7 +1044,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, lockdep_assert_held(&priv->mutex); - priv->key_mapping_key--; + ctx->key_mapping_keys--; spin_lock_irqsave(&priv->sta_lock, flags); key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); @@ -1098,7 +1103,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, lockdep_assert_held(&priv->mutex); - priv->key_mapping_key++; + ctx->key_mapping_keys++; keyconf->hw_key_idx = HW_KEY_DYNAMIC; switch (keyconf->cipher) { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index b7f700638dae..6ab5587870dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -44,14 +44,16 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, struct ieee80211_key_conf *key); int iwl_set_default_wep_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct ieee80211_key_conf *key); -int iwl_restore_default_wep_keys(struct iwl_priv *priv); +int iwl_restore_default_wep_keys(struct iwl_priv *priv, + struct iwl_rxon_context *ctx); int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct ieee80211_key_conf *key, u8 sta_id); -int iwl_remove_dynamic_key(struct iwl_priv *priv, +int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct ieee80211_key_conf *key, u8 sta_id); void iwl_update_tkip_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, @@ -97,20 +99,25 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); static inline void iwl_clear_driver_stations(struct iwl_priv *priv) { unsigned long flags; + struct iwl_rxon_context *ctx; spin_lock_irqsave(&priv->sta_lock, flags); memset(priv->stations, 0, sizeof(priv->stations)); priv->num_stations = 0; - /* - * Remove all key information that is not stored as part of station - * information since mac80211 may not have had a - * chance to remove all the keys. When device is reconfigured by - * mac80211 after an error all keys will be reconfigured. - */ priv->ucode_key_table = 0; - priv->key_mapping_key = 0; - memset(priv->wep_keys, 0, sizeof(priv->wep_keys)); + + for_each_context(priv, ctx) { + /* + * Remove all key information that is not stored as part + * of station information since mac80211 may not have had + * a chance to remove all the keys. When device is + * reconfigured by mac80211 after an error all keys will + * be reconfigured. + */ + memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys)); + ctx->key_mapping_keys = 0; + } spin_unlock_irqrestore(&priv->sta_lock, flags); } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 29d13765ff66..be48f7977278 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4022,6 +4022,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; + priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; /* * Disabling hardware scan means that mac80211 will perform scans -- cgit v1.2.3-59-g8ed1b From 770e13bdda27065e31b3ab4daa3a04b6429719a1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:44 +0200 Subject: iwlwifi: store default station flags in context Since the default context is initialised to zero, and the default flags are zero, no more code is needed to initialise them right now, but another context can have different default flags. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ef7862b5e91c..2f9d1daff554 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1137,6 +1137,8 @@ struct iwl_rxon_context { struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; u8 key_mapping_keys; + + __le32 station_flags; }; struct iwl_priv { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index ac6e2be35284..e6bb81b1514c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -289,7 +289,7 @@ static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, memcpy(station->sta.sta.addr, addr, ETH_ALEN); station->sta.mode = 0; station->sta.sta.sta_id = sta_id; - station->sta.station_flags = 0; + station->sta.station_flags = ctx->station_flags; station->ctxid = ctx->ctxid; /* -- cgit v1.2.3-59-g8ed1b From 238d781d33dcd7941e7ab799c59156e5f7ebda9d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:45 +0200 Subject: iwlwifi: add context pointer to station Sometimes we only pass around station pointers but need to find the context they belong to, so store it in there. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + drivers/net/wireless/iwlwifi/iwl-sta.c | 22 +++++++++++++++------- drivers/net/wireless/iwlwifi/iwl-sta.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 837406e53b3f..de8db3a3848d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3751,7 +3751,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, sta_priv->client = true; ret = iwl_add_station_common(priv, vif_priv->ctx, sta->addr, - is_ap, &sta->ht_cap, &sta_id); + is_ap, sta, &sta_id); if (ret) { IWL_ERR(priv, "Unable to add station %pM (%d)\n", sta->addr, ret); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2f9d1daff554..93647688d720 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -502,6 +502,7 @@ struct iwl_station_entry { }; struct iwl_station_priv_common { + struct iwl_rxon_context *ctx; u8 sta_id; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index e6bb81b1514c..c18eb89a9aed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -172,12 +172,13 @@ int iwl_send_add_sta(struct iwl_priv *priv, EXPORT_SYMBOL(iwl_send_add_sta); static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, - struct ieee80211_sta_ht_cap *sta_ht_inf) + struct ieee80211_sta *sta) { + struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap; __le32 sta_flags; u8 mimo_ps_mode; - if (!sta_ht_inf || !sta_ht_inf->ht_supported) + if (!sta || !sta_ht_inf->ht_supported) goto done; mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; @@ -228,7 +229,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, */ static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, const u8 *addr, bool is_ap, - struct ieee80211_sta_ht_cap *ht_info) + struct ieee80211_sta *sta) { struct iwl_station_entry *station; int i; @@ -292,12 +293,19 @@ static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, station->sta.station_flags = ctx->station_flags; station->ctxid = ctx->ctxid; + if (sta) { + struct iwl_station_priv_common *sta_priv; + + sta_priv = (void *)sta->drv_priv; + sta_priv->ctx = ctx; + } + /* * OK to call unconditionally, since local stations (IBSS BSSID - * STA and broadcast STA) pass in a NULL ht_info, and mac80211 + * STA and broadcast STA) pass in a NULL sta, and mac80211 * doesn't allow HT IBSS. */ - iwl_set_ht_add_station(priv, sta_id, ht_info); + iwl_set_ht_add_station(priv, sta_id, sta); /* 3945 only */ rate = (priv->band == IEEE80211_BAND_5GHZ) ? @@ -316,7 +324,7 @@ static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, */ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, const u8 *addr, bool is_ap, - struct ieee80211_sta_ht_cap *ht_info, u8 *sta_id_r) + struct ieee80211_sta *sta, u8 *sta_id_r) { unsigned long flags_spin; int ret = 0; @@ -325,7 +333,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, *sta_id_r = 0; spin_lock_irqsave(&priv->sta_lock, flags_spin); - sta_id = iwl_prep_station(priv, ctx, addr, is_ap, ht_info); + sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Unable to prepare station %pM for addition\n", addr); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 6ab5587870dc..56bad3f60d81 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -74,7 +74,7 @@ int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, const u8 *addr, bool init_rs, u8 *sta_id_r); int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, const u8 *addr, bool is_ap, - struct ieee80211_sta_ht_cap *ht_info, u8 *sta_id_r); + struct ieee80211_sta *sta, u8 *sta_id_r); int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, const u8 *addr); int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index be48f7977278..c048c1db42fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3390,7 +3390,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, ret = iwl_add_station_common(priv, &priv->contexts[IWL_RXON_CTX_BSS], - sta->addr, is_ap, &sta->ht_cap, &sta_id); + sta->addr, is_ap, sta, &sta_id); if (ret) { IWL_ERR(priv, "Unable to add station %pM (%d)\n", sta->addr, ret); -- cgit v1.2.3-59-g8ed1b From 7e6a588601eb85feb10c7e8898f1f69c3b229a20 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:46 +0200 Subject: iwlwifi: move HT configuration data into context A lot of HT configuration semantically belongs into the context, even if right now it will never be different between contexts. Move it so we're better prepared for future changes in mac80211. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 66 +++++++++++------ drivers/net/wireless/iwlwifi/iwl-agn.c | 26 +++---- drivers/net/wireless/iwlwifi/iwl-core.c | 113 +++++++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-core.h | 7 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 14 ++-- drivers/net/wireless/iwlwifi/iwl-sta.c | 23 +++--- 6 files changed, 134 insertions(+), 115 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index e78f3f0592d6..57629fba3a7d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -602,11 +602,13 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, * Green-field mode is valid if the station supports it and * there are no non-GF stations present in the BSS. */ -static inline u8 rs_use_green(struct ieee80211_sta *sta, - struct iwl_ht_config *ht_conf) +static bool rs_use_green(struct ieee80211_sta *sta) { + struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; + return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && - !(ht_conf->non_GF_STA_present); + !(ctx->ht.non_gf_sta_present); } /** @@ -758,8 +760,8 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a, (a->is_SGI == b->is_SGI); } -static void rs_bt_update_lq(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta) +static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + struct iwl_lq_sta *lq_sta) { struct iwl_scale_tbl_info *tbl; bool full_concurrent; @@ -778,7 +780,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, /* Update uCode's rate table. */ tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); + iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); queue_work(priv->workqueue, &priv->bt_full_concurrency); } @@ -803,6 +805,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, u32 tx_rate; struct iwl_scale_tbl_info tbl_type; struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; + struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); @@ -869,7 +873,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, lq_sta->missed_rate_counter++; if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { lq_sta->missed_rate_counter = 0; - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); + iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); } /* Regardless, ignore this status info for outdated rate */ return; @@ -969,7 +973,7 @@ done: /* Is there a need to switch between full concurrency and 3-wire? */ if (priv->bt_ant_couple_ok) - rs_bt_update_lq(priv, lq_sta); + rs_bt_update_lq(priv, ctx, lq_sta); } /* @@ -1163,6 +1167,8 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, u16 rate_mask; s32 rate; s8 is_green = lq_sta->is_green; + struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) return -1; @@ -1183,7 +1189,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, tbl->max_search = IWL_MAX_SEARCH; rate_mask = lq_sta->active_mimo2_rate; - if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap)) + if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap)) tbl->is_ht40 = 1; else tbl->is_ht40 = 0; @@ -1217,6 +1223,8 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, u16 rate_mask; s32 rate; s8 is_green = lq_sta->is_green; + struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) return -1; @@ -1237,7 +1245,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; rate_mask = lq_sta->active_mimo3_rate; - if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap)) + if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap)) tbl->is_ht40 = 1; else tbl->is_ht40 = 0; @@ -1272,6 +1280,8 @@ static int rs_switch_to_siso(struct iwl_priv *priv, u16 rate_mask; u8 is_green = lq_sta->is_green; s32 rate; + struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) return -1; @@ -1284,7 +1294,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, tbl->max_search = IWL_MAX_SEARCH; rate_mask = lq_sta->active_siso_rate; - if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap)) + if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap)) tbl->is_ht40 = 1; else tbl->is_ht40 = 0; @@ -2086,6 +2096,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) * return rate_n_flags as used in the table */ static u32 rs_update_rate_tbl(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, struct iwl_lq_sta *lq_sta, struct iwl_scale_tbl_info *tbl, int index, u8 is_green) @@ -2095,7 +2106,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv, /* Update uCode's rate table. */ rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); rs_fill_link_cmd(priv, lq_sta, rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); + iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); return rate; } @@ -2134,6 +2145,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, s32 sr; u8 tid = MAX_TID_COUNT; struct iwl_tid_data *tid_data; + struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); @@ -2172,7 +2185,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, if (is_legacy(tbl->lq_type)) lq_sta->is_green = 0; else - lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); + lq_sta->is_green = rs_use_green(sta); is_green = lq_sta->is_green; /* current tx rate */ @@ -2211,7 +2224,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); /* get "active" rate info */ index = iwl_hwrate_to_plcp_idx(tbl->current_rate); - rate = rs_update_rate_tbl(priv, lq_sta, + rate = rs_update_rate_tbl(priv, ctx, lq_sta, tbl, index, is_green); } return; @@ -2453,7 +2466,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, lq_update: /* Replace uCode's rate table for the destination station. */ if (update_lq) - rate = rs_update_rate_tbl(priv, lq_sta, + rate = rs_update_rate_tbl(priv, ctx, lq_sta, tbl, index, is_green); if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) { @@ -2495,7 +2508,7 @@ lq_update: IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", tbl->current_rate, index); rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); + iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); } else done_search = 1; } @@ -2565,12 +2578,17 @@ static void rs_initialize_lq(struct iwl_priv *priv, int rate_idx; int i; u32 rate; - u8 use_green = rs_use_green(sta, &priv->current_ht_config); + u8 use_green = rs_use_green(sta); u8 active_tbl = 0; u8 valid_tx_ant; + struct iwl_station_priv *sta_priv; + struct iwl_rxon_context *ctx; if (!sta || !lq_sta) - goto out; + return; + + sta_priv = (void *)sta->drv_priv; + ctx = sta_priv->common.ctx; i = lq_sta->last_txrate_idx; @@ -2602,9 +2620,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, rs_set_expected_tpt_table(lq_sta, tbl); rs_fill_link_cmd(NULL, lq_sta, rate); priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true); - out: - return; + iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_SYNC, true); } static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, @@ -2732,7 +2748,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i lq_sta->is_dup = 0; lq_sta->max_rate_idx = -1; lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; - lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); + lq_sta->is_green = rs_use_green(sta); lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); lq_sta->band = priv->band; /* @@ -2992,6 +3008,9 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, char buf[64]; int buf_size; u32 parsed_rate; + struct iwl_station_priv *sta_priv = + container_of(lq_sta, struct iwl_station_priv, lq_sta); + struct iwl_rxon_context *ctx = sta_priv->common.ctx; priv = lq_sta->drv; memset(buf, 0, sizeof(buf)); @@ -3014,7 +3033,8 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, if (lq_sta->dbg_fixed_rate) { rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); - iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); + iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC, + false); } return count; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index de8db3a3848d..4efca99b2a9c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3671,8 +3671,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, sta_priv->lq_sta.lq.general_params.flags &= ~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; - iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq, - CMD_ASYNC, false); + iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), + &sta_priv->lq_sta.lq, CMD_ASYNC, false); } break; case IEEE80211_AMPDU_TX_OPERATIONAL: @@ -3687,8 +3687,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, sta_priv->lq_sta.lq.general_params.flags |= LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; - iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq, - CMD_ASYNC, false); + iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), + &sta_priv->lq_sta.lq, CMD_ASYNC, false); } ret = 0; break; @@ -3824,23 +3824,23 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, priv->current_ht_config.smps = conf->smps_mode; /* Configure HT40 channels */ - ht_conf->is_ht = conf_is_ht(conf); - if (ht_conf->is_ht) { + ctx->ht.enabled = conf_is_ht(conf); + if (ctx->ht.enabled) { if (conf_is_ht40_minus(conf)) { - ht_conf->extension_chan_offset = + ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ht_conf->is_40mhz = true; + ctx->ht.is_40mhz = true; } else if (conf_is_ht40_plus(conf)) { - ht_conf->extension_chan_offset = + ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ht_conf->is_40mhz = true; + ctx->ht.is_40mhz = true; } else { - ht_conf->extension_chan_offset = + ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; - ht_conf->is_40mhz = false; + ctx->ht.is_40mhz = false; } } else - ht_conf->is_40mhz = false; + ctx->ht.is_40mhz = false; if ((le16_to_cpu(ctx->staging.channel) != ch)) ctx->staging.flags = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f9abcd80271c..8ec042d4e375 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -202,7 +202,7 @@ static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_UPDATE_EDCA_MSK; - if (priv->current_ht_config.is_ht) + if (ctx->ht.enabled) ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", @@ -441,15 +441,15 @@ static bool is_single_rx_stream(struct iwl_priv *priv) priv->current_ht_config.single_chain_sufficient; } -static u8 iwl_is_channel_extension(struct iwl_priv *priv, - enum ieee80211_band band, - u16 channel, u8 extension_chan_offset) +static bool iwl_is_channel_extension(struct iwl_priv *priv, + enum ieee80211_band band, + u16 channel, u8 extension_chan_offset) { const struct iwl_channel_info *ch_info; ch_info = iwl_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) - return 0; + return false; if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) return !(ch_info->ht40_extension_channel & @@ -458,34 +458,31 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv, return !(ch_info->ht40_extension_channel & IEEE80211_CHAN_NO_HT40MINUS); - return 0; + return false; } -u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, - struct ieee80211_sta_ht_cap *sta_ht_inf) +bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_sta_ht_cap *ht_cap) { - struct iwl_ht_config *ht_conf = &priv->current_ht_config; -#if !TODO - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; -#endif + if (!ctx->ht.enabled || !ctx->ht.is_40mhz) + return false; - if (!ht_conf->is_ht || !ht_conf->is_40mhz) - return 0; - - /* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 + /* + * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 * the bit will not set if it is pure 40MHz case */ - if (sta_ht_inf) { - if (!sta_ht_inf->ht_supported) - return 0; - } + if (ht_cap && !ht_cap->ht_supported) + return false; + #ifdef CONFIG_IWLWIFI_DEBUGFS if (priv->disable_ht40) - return 0; + return false; #endif + return iwl_is_channel_extension(priv, priv->band, le16_to_cpu(ctx->staging.channel), - ht_conf->extension_chan_offset); + ctx->ht.extension_chan_offset); } EXPORT_SYMBOL(iwl_is_ht40_tx_allowed); @@ -724,7 +721,7 @@ static void _iwl_set_rxon_ht(struct iwl_priv *priv, { struct iwl_rxon_cmd *rxon = &ctx->staging; - if (!ht_conf->is_ht) { + if (!ctx->ht.enabled) { rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | RXON_FLG_HT40_PROT_MSK | @@ -732,22 +729,22 @@ static void _iwl_set_rxon_ht(struct iwl_priv *priv, return; } - /* FIXME: if the definition of ht_protection changed, the "translation" + /* FIXME: if the definition of ht.protection changed, the "translation" * will be needed for rxon->flags */ - rxon->flags |= cpu_to_le32(ht_conf->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS); + rxon->flags |= cpu_to_le32(ctx->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS); /* Set up channel bandwidth: * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ /* clear the HT channel mode before set the mode */ rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); - if (iwl_is_ht40_tx_allowed(priv, NULL)) { + if (iwl_is_ht40_tx_allowed(priv, ctx, NULL)) { /* pure ht40 */ - if (ht_conf->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { + if (ctx->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; /* Note: control channel is opposite of extension channel */ - switch (ht_conf->extension_chan_offset) { + switch (ctx->ht.extension_chan_offset) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; break; @@ -757,7 +754,7 @@ static void _iwl_set_rxon_ht(struct iwl_priv *priv, } } else { /* Note: control channel is opposite of extension channel */ - switch (ht_conf->extension_chan_offset) { + switch (ctx->ht.extension_chan_offset) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; @@ -782,8 +779,8 @@ static void _iwl_set_rxon_ht(struct iwl_priv *priv, IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X " "extension channel offset 0x%x\n", - le32_to_cpu(rxon->flags), ht_conf->ht_protection, - ht_conf->extension_chan_offset); + le32_to_cpu(rxon->flags), ctx->ht.protection, + ctx->ht.extension_chan_offset); } void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) @@ -1649,15 +1646,16 @@ static void iwl_ht_conf(struct iwl_priv *priv, struct iwl_ht_config *ht_conf = &priv->current_ht_config; struct ieee80211_sta *sta; struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); IWL_DEBUG_MAC80211(priv, "enter:\n"); - if (!ht_conf->is_ht) + if (!ctx->ht.enabled) return; - ht_conf->ht_protection = + ctx->ht.protection = bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; - ht_conf->non_GF_STA_present = + ctx->ht.non_gf_sta_present = !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); ht_conf->single_chain_sufficient = false; @@ -2098,29 +2096,32 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) spin_lock_irqsave(&priv->lock, flags); - /* Configure HT40 channels */ - ht_conf->is_ht = conf_is_ht(conf); - if (ht_conf->is_ht) { - if (conf_is_ht40_minus(conf)) { - ht_conf->extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ht_conf->is_40mhz = true; - } else if (conf_is_ht40_plus(conf)) { - ht_conf->extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ht_conf->is_40mhz = true; - } else { - ht_conf->extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_NONE; - ht_conf->is_40mhz = false; - } - } else - ht_conf->is_40mhz = false; - /* Default to no protection. Protection mode will later be set - * from BSS config in iwl_ht_conf */ - ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; - for_each_context(priv, ctx) { + /* Configure HT40 channels */ + ctx->ht.enabled = conf_is_ht(conf); + if (ctx->ht.enabled) { + if (conf_is_ht40_minus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ctx->ht.is_40mhz = true; + } else if (conf_is_ht40_plus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + ctx->ht.is_40mhz = true; + } else { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_NONE; + ctx->ht.is_40mhz = false; + } + } else + ctx->ht.is_40mhz = false; + + /* + * Default to no protection. Protection mode will + * later be set from BSS config in iwl_ht_conf + */ + ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; + /* if we are switching from ht to 2.4 clear flags * from any ht related info since 2.4 does not * support ht */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7aa9c6c5c43e..289fef8a881b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -389,8 +389,9 @@ void iwl_set_flags_for_band(struct iwl_priv *priv, u8 iwl_get_single_channel_number(struct iwl_priv *priv, enum ieee80211_band band); void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); -u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, - struct ieee80211_sta_ht_cap *sta_ht_inf); +bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_sta_ht_cap *ht_cap); void iwl_connection_init_rx_config(struct iwl_priv *priv, struct ieee80211_vif *vif); void iwl_set_rate(struct iwl_priv *priv); @@ -720,7 +721,7 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) extern void iwl_send_bt_config(struct iwl_priv *priv); extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear); -extern int iwl_send_lq_cmd(struct iwl_priv *priv, +extern int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_link_quality_cmd *lq, u8 flags, bool init); void iwl_apm_stop(struct iwl_priv *priv); int iwl_apm_init(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 93647688d720..c17c67f767e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -470,15 +470,8 @@ union iwl_ht_rate_supp { #define CFG_HT_MPDU_DENSITY_MIN (0x1) struct iwl_ht_config { - /* self configuration data */ - bool is_ht; - bool is_40mhz; bool single_chain_sufficient; enum ieee80211_smps_mode smps; /* current smps mode */ - /* BSS related data */ - u8 extension_chan_offset; - u8 ht_protection; - u8 non_GF_STA_present; }; /* QoS structures */ @@ -1140,6 +1133,13 @@ struct iwl_rxon_context { u8 key_mapping_keys; __le32 station_flags; + + struct { + bool non_gf_sta_present; + u8 protection; + bool enabled, is_40mhz; + u8 extension_chan_offset; + } ht; }; struct iwl_priv { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index c18eb89a9aed..ccd09027c7cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -172,7 +172,8 @@ int iwl_send_add_sta(struct iwl_priv *priv, EXPORT_SYMBOL(iwl_send_add_sta); static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta, + struct iwl_rxon_context *ctx) { struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap; __le32 sta_flags; @@ -212,7 +213,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, sta_flags |= cpu_to_le32( (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); - if (iwl_is_ht40_tx_allowed(priv, sta_ht_inf)) + if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap)) sta_flags |= STA_FLG_HT40_EN_MSK; else sta_flags &= ~STA_FLG_HT40_EN_MSK; @@ -305,7 +306,7 @@ static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, * STA and broadcast STA) pass in a NULL sta, and mac80211 * doesn't allow HT IBSS. */ - iwl_set_ht_add_station(priv, sta_id, sta); + iwl_set_ht_add_station(priv, sta_id, sta, ctx); /* 3945 only */ rate = (priv->band == IEEE80211_BAND_5GHZ) ? @@ -472,7 +473,7 @@ int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, return -ENOMEM; } - ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true); + ret = iwl_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true); if (ret) IWL_ERR(priv, "Link quality command failed (%d)\n", ret); @@ -714,7 +715,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * current LQ command */ if (send_lq) - iwl_send_lq_cmd(priv, &lq, CMD_SYNC, true); + iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); spin_lock_irqsave(&priv->sta_lock, flags_spin); priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; } @@ -1173,16 +1174,12 @@ static inline void iwl_dump_lq_cmd(struct iwl_priv *priv, * RXON flags are updated and when LQ command is updated. */ static bool is_lq_table_valid(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, struct iwl_link_quality_cmd *lq) { int i; - struct iwl_ht_config *ht_conf = &priv->current_ht_config; -#if !TODO - struct iwl_rxon_context *ctx = - &priv->contexts[IWL_RXON_CTX_BSS]; -#endif - if (ht_conf->is_ht) + if (ctx->ht.enabled) return true; IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n", @@ -1208,7 +1205,7 @@ static bool is_lq_table_valid(struct iwl_priv *priv, * this case to clear the state indicating that station creation is in * progress. */ -int iwl_send_lq_cmd(struct iwl_priv *priv, +int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_link_quality_cmd *lq, u8 flags, bool init) { int ret = 0; @@ -1227,7 +1224,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, iwl_dump_lq_cmd(priv, lq); BUG_ON(init && (cmd.flags & CMD_ASYNC)); - if (is_lq_table_valid(priv, lq)) + if (is_lq_table_valid(priv, ctx, lq)) ret = iwl_send_cmd(priv, &cmd); else ret = -EINVAL; -- cgit v1.2.3-59-g8ed1b From 76d048151cf935281998b591e070581fc438e27e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:47 +0200 Subject: iwlwifi: introduce beacon context Only one context can be beaconing at a time, but we need to track which one. Introduce a new variable priv->beacon_ctx to do that. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 32 +++++++++++++++++++---------- drivers/net/wireless/iwlwifi/iwl-core.c | 30 ++++++++++++++++++++------- drivers/net/wireless/iwlwifi/iwl-core.h | 3 ++- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 ++- 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4efca99b2a9c..55d1cd4c1369 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -345,6 +345,13 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, * beacon contents. */ + lockdep_assert_held(&priv->mutex); + + if (!priv->beacon_ctx) { + IWL_ERR(priv, "trying to build beacon w/o beacon context!\n"); + return -EINVAL; + } + /* Initialize memory */ tx_beacon_cmd = &frame->u.beacon; memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); @@ -357,9 +364,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, /* Set up TX command fields */ tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); -#warning "Use proper STA ID" - tx_beacon_cmd->tx.sta_id = - priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id; + tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; @@ -369,7 +374,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, frame_size); /* Set up packet rate and flags */ - rate = iwl_rate_get_lowest_plcp(priv); + rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx); priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, priv->hw_params.valid_tx_ant); rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); @@ -602,25 +607,28 @@ static void iwl_bg_beacon_update(struct work_struct *work) container_of(work, struct iwl_priv, beacon_update); struct sk_buff *beacon; - /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ -#warning "introduce and use beacon context" - beacon = ieee80211_beacon_get(priv->hw, - priv->contexts[IWL_RXON_CTX_BSS].vif); + mutex_lock(&priv->mutex); + if (!priv->beacon_ctx) { + IWL_ERR(priv, "updating beacon w/o beacon context!\n"); + goto out; + } + /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ + beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif); if (!beacon) { IWL_ERR(priv, "update beacon failed\n"); - return; + goto out; } - mutex_lock(&priv->mutex); /* new beacon skb is allocated every time; dispose previous.*/ if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); priv->ibss_beacon = beacon; - mutex_unlock(&priv->mutex); iwl_send_beacon_cmd(priv); + out: + mutex_unlock(&priv->mutex); } static void iwl_bg_bt_runtime_config(struct work_struct *work) @@ -3477,6 +3485,8 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); int ret = 0; + lockdep_assert_held(&priv->mutex); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8ec042d4e375..fb9173b1e5aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -699,11 +699,9 @@ int iwl_full_rxon_required(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_full_rxon_required); -u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) +u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { -#if !TODO - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; -#endif /* * Assign the lowest rate -- should really get this from * the beacon skb from mac80211. @@ -1723,6 +1721,14 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) IWL_DEBUG_MAC80211(priv, "enter\n"); + lockdep_assert_held(&priv->mutex); + + if (!priv->beacon_ctx) { + IWL_ERR(priv, "update beacon but no beacon context!\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; @@ -1741,9 +1747,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) IWL_DEBUG_MAC80211(priv, "leave\n"); spin_unlock_irqrestore(&priv->lock, flags); -#warning "use beacon context?" - priv->cfg->ops->lib->post_associate( - priv, priv->contexts[IWL_RXON_CTX_BSS].vif); + priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif); return 0; } @@ -1773,6 +1777,18 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, spin_unlock_irqrestore(&priv->lock, flags); } + if (changes & BSS_CHANGED_BEACON_ENABLED) { + /* + * the add_interface code must make sure we only ever + * have a single interface that could be beaconing at + * any time. + */ + if (vif->bss_conf.enable_beacon) + priv->beacon_ctx = ctx; + else + priv->beacon_ctx = NULL; + } + if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { dev_kfree_skb(priv->ibss_beacon); priv->ibss_beacon = ieee80211_beacon_get(hw, vif); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 289fef8a881b..d2ee55d6811d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -523,7 +523,8 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); -u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); +u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, + struct iwl_rxon_context *ctx); u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c17c67f767e6..e1565f734599 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1437,6 +1437,8 @@ struct iwl_priv { struct work_struct rx_replenish; struct work_struct abort_scan; struct work_struct beacon_update; + struct iwl_rxon_context *beacon_ctx; + struct work_struct tt_work; struct work_struct ct_enter; struct work_struct ct_exit; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c048c1db42fd..e81c438b3348 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -343,7 +343,8 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) return -ENOMEM; } - rate = iwl_rate_get_lowest_plcp(priv); + rate = iwl_rate_get_lowest_plcp(priv, + &priv->contexts[IWL_RXON_CTX_BSS]); frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate); -- cgit v1.2.3-59-g8ed1b From 946ba30d61d47ee634a39d27b4d067b6418eaa08 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:48 +0200 Subject: iwlwifi: add PAN API Define the new host commands and notifications REPLY_WIPAN_PARAMS REPLY_WIPAN_RXON REPLY_WIPAN_RXON_TIMING REPLY_WIPAN_RXON_ASSOC REPLY_WIPAN_QOS_PARAM REPLY_WIPAN_WEPKEY REPLY_WIPAN_P2P_CHANNEL_SWITCH REPLY_WIPAN_NOA_NOTIFICATION and their corresponding structures along with the PAN station flag, the PAN AP sta ID and new dev types for the second context. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-commands.h | 109 +++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 8 ++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 55779bf0627b..3e4ba31b5d59 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -180,6 +180,16 @@ enum { REPLY_BT_COEX_PROFILE_NOTIF = 0xce, REPLY_BT_COEX_SCO = 0xcf, + /* PAN commands */ + REPLY_WIPAN_PARAMS = 0xb2, + REPLY_WIPAN_RXON = 0xb3, /* use REPLY_RXON structure */ + REPLY_WIPAN_RXON_TIMING = 0xb4, /* use REPLY_RXON_TIMING structure */ + REPLY_WIPAN_RXON_ASSOC = 0xb6, /* use REPLY_RXON_ASSOC structure */ + REPLY_WIPAN_QOS_PARAM = 0xb7, /* use REPLY_QOS_PARAM structure */ + REPLY_WIPAN_WEPKEY = 0xb8, /* use REPLY_WEPKEY structure */ + REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9, + REPLY_WIPAN_NOA_NOTIFICATION = 0xbc, + REPLY_MAX = 0xff }; @@ -607,6 +617,9 @@ enum { RXON_DEV_TYPE_ESS = 3, RXON_DEV_TYPE_IBSS = 4, RXON_DEV_TYPE_SNIFFER = 6, + RXON_DEV_TYPE_CP = 7, + RXON_DEV_TYPE_2STA = 8, + RXON_DEV_TYPE_P2P = 9, }; @@ -823,7 +836,8 @@ struct iwl_rxon_time_cmd { __le16 atim_window; __le32 beacon_init_val; __le16 listen_interval; - __le16 reserved; + u8 dtim_period; + u8 delta_cp_bss_tbtts; } __packed; /* @@ -960,11 +974,13 @@ struct iwl_qosparam_cmd { /* Special, dedicated locations within device's station table */ #define IWL_AP_ID 0 +#define IWL_AP_ID_PAN 1 #define IWL_STA_ID 2 #define IWL3945_BROADCAST_ID 24 #define IWL3945_STATION_COUNT 25 #define IWL4965_BROADCAST_ID 31 #define IWL4965_STATION_COUNT 32 +#define IWLAGN_PAN_BCAST_ID 14 #define IWLAGN_BROADCAST_ID 15 #define IWLAGN_STATION_COUNT 16 @@ -973,6 +989,7 @@ struct iwl_qosparam_cmd { #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) +#define STA_FLG_PAN_STATION cpu_to_le32(1 << 13) #define STA_FLG_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17) #define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18) #define STA_FLG_MAX_AGG_SIZE_POS (19) @@ -4309,4 +4326,94 @@ struct iwl_rx_packet { int iwl_agn_check_rxon_cmd(struct iwl_priv *priv); +/* + * REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification) + */ + +/** + * struct iwl_wipan_slot + * @width: Time in TU + * @type: + * 0 - BSS + * 1 - PAN + */ +struct iwl_wipan_slot { + __le16 width; + u8 type; + u8 reserved; +} __packed; + +#define IWL_WIPAN_PARAMS_FLG_LEAVE_CHANNEL_CTS BIT(1) /* reserved */ +#define IWL_WIPAN_PARAMS_FLG_LEAVE_CHANNEL_QUIET BIT(2) /* reserved */ +#define IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE BIT(3) /* reserved */ +#define IWL_WIPAN_PARAMS_FLG_FILTER_BEACON_NOTIF BIT(4) +#define IWL_WIPAN_PARAMS_FLG_FULL_SLOTTED_MODE BIT(5) + +/** + * struct iwl_wipan_params_cmd + * @flags: + * bit0: reserved + * bit1: CP leave channel with CTS + * bit2: CP leave channel qith Quiet + * bit3: slotted mode + * 1 - work in slotted mode + * 0 - work in non slotted mode + * bit4: filter beacon notification + * bit5: full tx slotted mode. if this flag is set, + * uCode will perform leaving channel methods in context switch + * also when working in same channel mode + * @num_slots: 1 - 10 + */ +struct iwl_wipan_params_cmd { + __le16 flags; + u8 reserved; + u8 num_slots; + struct iwl_wipan_slot slots[10]; +} __packed; + +/* + * REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9 + * + * TODO: Figure out what this is used for, + * it can only switch between 2.4 GHz + * channels!! + */ + +struct iwl_wipan_p2p_channel_switch_cmd { + __le16 channel; + __le16 reserved; +}; + +/* + * REPLY_WIPAN_NOA_NOTIFICATION = 0xbc + * + * This is used by the device to notify us of the + * NoA schedule it determined so we can forward it + * to userspace for inclusion in probe responses. + * + * In beacons, the NoA schedule is simply appended + * to the frame we give the device. + */ + +struct iwl_wipan_noa_descriptor { + u8 count; + __le32 duration; + __le32 interval; + __le32 starttime; +} __packed; + +struct iwl_wipan_noa_attribute { + u8 id; + __le16 length; + u8 index; + u8 ct_window; + struct iwl_wipan_noa_descriptor descr0, descr1; + u8 reserved; +} __packed; + +struct iwl_wipan_noa_notification { + u32 noa_active; + struct iwl_wipan_noa_attribute noa_attribute; +} __packed; + #endif /* __iwl_commands_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 9fb2035e4eca..c373b53babea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -100,6 +100,14 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF); IWL_CMD(REPLY_BT_COEX_PRIO_TABLE); IWL_CMD(REPLY_BT_COEX_PROT_ENV); + IWL_CMD(REPLY_WIPAN_PARAMS); + IWL_CMD(REPLY_WIPAN_RXON); + IWL_CMD(REPLY_WIPAN_RXON_TIMING); + IWL_CMD(REPLY_WIPAN_RXON_ASSOC); + IWL_CMD(REPLY_WIPAN_QOS_PARAM); + IWL_CMD(REPLY_WIPAN_WEPKEY); + IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH); + IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION); default: return "UNKNOWN"; -- cgit v1.2.3-59-g8ed1b From ece9c4ee5e590f96d7221c746126eaafac15a60c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:49 +0200 Subject: iwlagn: detect PAN capability Detect whether or not the ucode is PAN capable and adjust the valid contexts accordingly. To be able to do this, add the PAN context to the array as well. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 25 +++++++++++++++++++++---- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 55d1cd4c1369..bad97f47eb9f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1718,6 +1718,7 @@ static void iwl_nic_start(struct iwl_priv *priv) struct iwlagn_ucode_capabilities { u32 max_probe_length; u32 standard_phy_calibration_size; + bool pan; }; static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); @@ -1955,6 +1956,11 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, capa->max_probe_length = le32_to_cpup((__le32 *)tlv_data); break; + case IWL_UCODE_TLV_PAN: + if (tlv_len) + goto invalid_tlv_len; + capa->pan = true; + break; case IWL_UCODE_TLV_INIT_EVTLOG_PTR: if (tlv_len != sizeof(u32)) goto invalid_tlv_len; @@ -2230,10 +2236,11 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size; priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; - if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS)) - priv->sta_key_max_num = STA_KEY_MAX_NUM; - else + if (ucode_capa.pan) { + priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN); priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; + } else + priv->sta_key_max_num = STA_KEY_MAX_NUM; /* Copy images into buffers for card's bus-master reads ... */ @@ -4226,7 +4233,17 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; - BUILD_BUG_ON(NUM_IWL_RXON_CTX != 1); + + priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON; + priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING; + priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd = REPLY_WIPAN_RXON_ASSOC; + priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM; + priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN; + priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY; + priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID; + priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION; + + BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); SET_IEEE80211_DEV(hw, &pdev->dev); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index e1565f734599..99b6b81be7e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -582,6 +582,7 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_INIT_DATA = 4, IWL_UCODE_TLV_BOOT = 5, IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ + IWL_UCODE_TLV_PAN = 7, IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8, IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, @@ -1103,6 +1104,7 @@ struct iwl_force_reset { enum iwl_rxon_context_id { IWL_RXON_CTX_BSS, + IWL_RXON_CTX_PAN, NUM_IWL_RXON_CTX }; -- cgit v1.2.3-59-g8ed1b From 60744f62971cfa80cab36ab8c12afeae371fbe8b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:50 +0200 Subject: iwlagn: remove iw_mode check for beacon Since we have the beacon context now, we no longer need to rely on iw_mode but can check the beacon context interface's type. However, that check must be in the work item instead due to locking constraints (mutex must be held when dereferencing beacon_ctx pointer). Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index bad97f47eb9f..b07d397ed5a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -613,6 +613,16 @@ static void iwl_bg_beacon_update(struct work_struct *work) goto out; } + if (priv->beacon_ctx->vif->type != NL80211_IFTYPE_AP) { + /* + * The ucode will send beacon notifications even in + * IBSS mode, but we don't want to process them. But + * we need to defer the type check to here due to + * requiring locking around the beacon_ctx access. + */ + goto out; + } + /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif); if (!beacon) { @@ -846,8 +856,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); - if ((priv->iw_mode == NL80211_IFTYPE_AP) && - (!test_bit(STATUS_EXIT_PENDING, &priv->status))) + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) queue_work(priv->workqueue, &priv->beacon_update); } -- cgit v1.2.3-59-g8ed1b From e72f368be61d9835c98cd00ee1f330d28e2488ef Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:51 +0200 Subject: iwlagn: queue frames according to context Frames for different contexts need to be put on different queues, and multicast after DTIM frames have a special queue yet which also depends on the context, so put all this into the context. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 42 ++++++++++++++----------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 27 ++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 5 ++++ 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 64daddd92279..5950184d9860 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -71,18 +71,6 @@ static const u8 tid_to_ac[] = { 2, 3, 3, 2, 1, 1, 0, 0 }; -static const u8 ac_to_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, -}; - -static inline int get_fifo_from_ac(u8 ac) -{ - return ac_to_fifo[ac]; -} - static inline int get_ac_from_tid(u16 tid) { if (likely(tid < ARRAY_SIZE(tid_to_ac))) @@ -92,10 +80,10 @@ static inline int get_ac_from_tid(u16 tid) return -EINVAL; } -static inline int get_fifo_from_tid(u16 tid) +static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) { if (likely(tid < ARRAY_SIZE(tid_to_ac))) - return get_fifo_from_ac(tid_to_ac[tid]); + return ctx->ac_to_fifo[tid_to_ac[tid]]; /* no support for TIDs 8-15 yet */ return -EINVAL; @@ -333,11 +321,6 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask); } -static inline int get_queue_from_ac(u16 ac) -{ - return ac; -} - /* * handle build REPLY_TX command notification. */ @@ -595,7 +578,20 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); } - txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); + /* + * Send this frame after DTIM -- there's a special queue + * reserved for this for contexts that support AP mode. + */ + if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { + txq_id = ctx->mcast_queue; + /* + * The microcode will clear the more data + * bit in the last frame it transmits. + */ + hdr->frame_control |= + cpu_to_le16(IEEE80211_FCTL_MOREDATA); + } else + txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; /* irqs already disabled/saved above when locking priv->lock */ spin_lock(&priv->sta_lock); @@ -984,7 +980,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, unsigned long flags; struct iwl_tid_data *tid_data; - tx_fifo = get_fifo_from_tid(tid); + tx_fifo = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); if (unlikely(tx_fifo < 0)) return tx_fifo; @@ -1045,7 +1041,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, int write_ptr, read_ptr; unsigned long flags; - tx_fifo_id = get_fifo_from_tid(tid); + tx_fifo_id = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); if (unlikely(tx_fifo_id < 0)) return tx_fifo_id; @@ -1133,7 +1129,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, if ((txq_id == tid_data->agg.txq_id) && (q->read_ptr == q->write_ptr)) { u16 ssn = SEQ_TO_SN(tid_data->seq_number); - int tx_fifo = get_fifo_from_tid(tid); + int tx_fifo = get_fifo_from_tid(ctx, tid); IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, tx_fifo); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b07d397ed5a7..143c12a29fd8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -4196,6 +4196,28 @@ static int iwl_set_hw_params(struct iwl_priv *priv) return priv->cfg->ops->lib->set_hw_params(priv); } +static const u8 iwlagn_bss_ac_to_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, +}; + +static const u8 iwlagn_bss_ac_to_queue[] = { + 0, 1, 2, 3, +}; + +static const u8 iwlagn_pan_ac_to_fifo[] = { + IWL_TX_FIFO_VO_IPAN, + IWL_TX_FIFO_VI_IPAN, + IWL_TX_FIFO_BE_IPAN, + IWL_TX_FIFO_BK_IPAN, +}; + +static const u8 iwlagn_pan_ac_to_queue[] = { + 7, 6, 5, 4, +}; + static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = 0, i; @@ -4242,6 +4264,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; + priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo; + priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue; priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON; priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING; @@ -4251,6 +4275,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY; priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID; priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION; + priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo; + priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue; + priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 99b6b81be7e2..422c71e122f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1111,6 +1111,11 @@ enum iwl_rxon_context_id { struct iwl_rxon_context { struct ieee80211_vif *vif; + + const u8 *ac_to_fifo; + const u8 *ac_to_queue; + u8 mcast_queue; + enum iwl_rxon_context_id ctxid; /* * We declare this const so it can only be -- cgit v1.2.3-59-g8ed1b From 2491fa42d9bdf26075765db5d091b5d7225ca636 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:52 +0200 Subject: iwlagn: send RXON timing before associating The PAN functionality requires us to send the timing including a valid DTIM period to the microcode before associating, so request this data from mac80211 and send it to the device. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 16 ++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 2 ++ 2 files changed, 18 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 143c12a29fd8..79aff1fb85a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -182,6 +182,21 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); + if (new_assoc) { + if (WARN_ON(!ctx->vif)) + return -EINVAL; + /* + * First of all, before setting associated, we need to + * send RXON timing so the device knows about the DTIM + * period and other timing values + */ + ret = iwl_send_rxon_timing(priv, ctx->vif); + if (ret) { + IWL_ERR(priv, "Error setting RXON timing!\n"); + return ret; + } + } + /* Apply the new configuration * RXON unassoc clears the station table in uCode so restoration of * stations is needed after it (the RXON command) completes @@ -3355,6 +3370,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | + IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT; if (!priv->cfg->broken_powersave) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index fb9173b1e5aa..04d7894e0004 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -536,6 +536,8 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) rem = do_div(tsf, interval_tm); ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); + ctx->timing.dtim_period = vif->bss_conf.dtim_period; + IWL_DEBUG_ASSOC(priv, "beacon interval %d beacon timer %d beacon tim %d\n", le16_to_cpu(ctx->timing.beacon_interval), -- cgit v1.2.3-59-g8ed1b From 08abc53cf4f7547ab3bc3957bc6e60c364a882c3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:53 +0200 Subject: iwlagn: send beacon before committing associated RXON Newer AGN microcode requires know the beacon before starting the AP so that it can start beaconing right away. Implement that. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 79aff1fb85a1..8e0722830413 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3559,6 +3559,8 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } + /* need to send beacon cmd before committing assoc RXON! */ + iwl_send_beacon_cmd(priv); /* restore RXON assoc */ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv, ctx); -- cgit v1.2.3-59-g8ed1b From 52a02d1500e4cbb347006e407d1c0bd941eee7fc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 09:44:50 -0700 Subject: iwlwifi: send PAN parameters In order for the microcode to be able to handle multiple interfaces, we need to give it the PAN parameters that state how to allocate the time between the two interfaces. Do this, and update it wherever necessary. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 75 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 5 ++ drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +++ drivers/net/wireless/iwlwifi/iwl-core.c | 6 +++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-scan.c | 3 ++ 6 files changed, 96 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 2d4cdb027aa6..6fb52abafc8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -270,12 +270,86 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, return max_rssi - agc - IWLAGN_RSSI_OFFSET; } +static int iwlagn_set_pan_params(struct iwl_priv *priv) +{ + struct iwl_wipan_params_cmd cmd; + struct iwl_rxon_context *ctx_bss, *ctx_pan; + int slot0 = 300, slot1 = 0; + int ret; + + if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS)) + return 0; + + BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); + + lockdep_assert_held(&priv->mutex); + + ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; + ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; + + memset(&cmd, 0, sizeof(cmd)); + + /* only 2 slots are currently allowed */ + cmd.num_slots = 2; + + cmd.slots[0].type = 0; /* BSS */ + cmd.slots[1].type = 1; /* PAN */ + + if (ctx_bss->vif && ctx_pan->vif) { + int bcnint = ctx_pan->vif->bss_conf.beacon_int; + + /* should be set, but seems unused?? */ + cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE); + + if (ctx_pan->vif->type == NL80211_IFTYPE_AP && + bcnint && + bcnint != ctx_bss->vif->bss_conf.beacon_int) { + IWL_ERR(priv, + "beacon intervals don't match (%d, %d)\n", + ctx_bss->vif->bss_conf.beacon_int, + ctx_pan->vif->bss_conf.beacon_int); + } else + bcnint = max_t(int, bcnint, + ctx_bss->vif->bss_conf.beacon_int); + if (!bcnint) + bcnint = 100; + slot0 = bcnint / 2; + slot1 = bcnint - slot0; + + if (test_bit(STATUS_SCAN_HW, &priv->status) || + (!ctx_bss->vif->bss_conf.idle && + !ctx_bss->vif->bss_conf.assoc)) { + slot0 = bcnint * 3 - 20; + slot1 = 20; + } else if (!ctx_pan->vif->bss_conf.idle && + !ctx_pan->vif->bss_conf.assoc) { + slot1 = bcnint * 3 - 20; + slot0 = 20; + } + } else if (ctx_pan->vif) { + slot0 = 0; + slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) * + ctx_pan->vif->bss_conf.beacon_int; + slot1 = max_t(int, 100, slot1); + } + + cmd.slots[0].width = cpu_to_le16(slot0); + cmd.slots[1].width = cpu_to_le16(slot1); + + ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd); + if (ret) + IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); + + return ret; +} + struct iwl_hcmd_ops iwlagn_hcmd = { .rxon_assoc = iwlagn_send_rxon_assoc, .commit_rxon = iwl_commit_rxon, .set_rxon_chain = iwl_set_rxon_chain, .set_tx_ant = iwlagn_send_tx_ant_config, .send_bt_config = iwl_send_bt_config, + .set_pan_params = iwlagn_set_pan_params, }; struct iwl_hcmd_ops iwlagn_bt_hcmd = { @@ -284,6 +358,7 @@ struct iwl_hcmd_ops iwlagn_bt_hcmd = { .set_rxon_chain = iwl_set_rxon_chain, .set_tx_ant = iwlagn_send_tx_ant_config, .send_bt_config = iwlagn_send_advance_bt_config, + .set_pan_params = iwlagn_set_pan_params, }; struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 7002d7d0fac4..a8f2adfd799e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1424,6 +1424,11 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->len = cpu_to_le16(cmd.len); set_bit(STATUS_SCAN_HW, &priv->status); + + if (priv->cfg->ops->hcmd->set_pan_params && + priv->cfg->ops->hcmd->set_pan_params(priv)) + goto done; + if (iwl_send_cmd_sync(priv, &cmd)) goto done; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8e0722830413..f2884b5ca5b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -197,6 +197,12 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } } + if (priv->cfg->ops->hcmd->set_pan_params) { + ret = priv->cfg->ops->hcmd->set_pan_params(priv); + if (ret) + return ret; + } + /* Apply the new configuration * RXON unassoc clears the station table in uCode so restoration of * stations is needed after it (the RXON command) completes diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 04d7894e0004..b61b838a24b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1931,6 +1931,12 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, bss_conf->bssid); } + if (changes & BSS_CHANGED_IDLE && + priv->cfg->ops->hcmd->set_pan_params) { + if (priv->cfg->ops->hcmd->set_pan_params(priv)) + IWL_ERR(priv, "failed to update PAN params\n"); + } + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index d2ee55d6811d..ab465c5fd6f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -94,6 +94,7 @@ struct iwl_hcmd_ops { struct iwl_rxon_context *ctx); int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant); void (*send_bt_config)(struct iwl_priv *priv); + int (*set_pan_params)(struct iwl_priv *priv); }; struct iwl_hcmd_utils_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 556dcaaa0efe..7727f0966d31 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -572,6 +572,9 @@ static void iwl_bg_scan_completed(struct work_struct *work) iwlcore_commit_rxon(priv, ctx); out: + if (priv->cfg->ops->hcmd->set_pan_params) + priv->cfg->ops->hcmd->set_pan_params(priv); + mutex_unlock(&priv->mutex); /* -- cgit v1.2.3-59-g8ed1b From 47313e340ee6faa43d8ad8a509a00ed1584fb34d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:55 +0200 Subject: iwlwifi: pass context to iwl_send_rxon_timing Sometimes we need to send RXON timing even when we don't have a virtual interface yet, so pass the context and allow passing one without a virtual interface pointer. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 +++----- drivers/net/wireless/iwlwifi/iwl-core.c | 20 +++++++++----------- drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f2884b5ca5b4..85eea944498e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -183,14 +183,12 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); if (new_assoc) { - if (WARN_ON(!ctx->vif)) - return -EINVAL; /* * First of all, before setting associated, we need to * send RXON timing so the device knows about the DTIM * period and other timing values */ - ret = iwl_send_rxon_timing(priv, ctx->vif); + ret = iwl_send_rxon_timing(priv, ctx); if (ret) { IWL_ERR(priv, "Error setting RXON timing!\n"); return ret; @@ -3296,7 +3294,7 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv, ctx); - ret = iwl_send_rxon_timing(priv, vif); + ret = iwl_send_rxon_timing(priv, ctx); if (ret) IWL_WARN(priv, "RXON timing - " "Attempting to continue.\n"); @@ -3536,7 +3534,7 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) iwlcore_commit_rxon(priv, ctx); /* RXON Timing */ - ret = iwl_send_rxon_timing(priv, vif); + ret = iwl_send_rxon_timing(priv, ctx); if (ret) IWL_WARN(priv, "RXON timing failed - " "Attempting to continue.\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b61b838a24b5..91ca5173e862 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -500,13 +500,13 @@ static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) return new_val; } -int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) +int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { u64 tsf; s32 interval_tm, rem; struct ieee80211_conf *conf = NULL; u16 beacon_int; - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + struct ieee80211_vif *vif = ctx->vif; conf = ieee80211_get_hw_conf(priv->hw); @@ -517,15 +517,13 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) ctx->timing.timestamp = cpu_to_le64(priv->timestamp); ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval); - beacon_int = vif->bss_conf.beacon_int; + beacon_int = vif ? vif->bss_conf.beacon_int : 0; - if (vif->type == NL80211_IFTYPE_ADHOC) { - /* TODO: we need to get atim_window from upper stack - * for now we set to 0 */ - ctx->timing.atim_window = 0; - } else { - ctx->timing.atim_window = 0; - } + /* + * TODO: For IBSS we need to get atim_window from mac80211, + * for now just always use 0 + */ + ctx->timing.atim_window = 0; beacon_int = iwl_adjust_beacon_interval(beacon_int, priv->hw_params.max_beacon_itrvl * TIME_UNIT); @@ -536,7 +534,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) rem = do_div(tsf, interval_tm); ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); - ctx->timing.dtim_period = vif->bss_conf.dtim_period; + ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1; IWL_DEBUG_ASSOC(priv, "beacon interval %d beacon timer %d beacon tim %d\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index ab465c5fd6f6..4d7910001b75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -728,7 +728,7 @@ extern int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, void iwl_apm_stop(struct iwl_priv *priv); int iwl_apm_init(struct iwl_priv *priv); -int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif); +int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx); static inline int iwl_send_rxon_assoc(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e81c438b3348..76a45b239664 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3110,7 +3110,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv, ctx); - rc = iwl_send_rxon_timing(priv, vif); + rc = iwl_send_rxon_timing(priv, ctx); if (rc) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); @@ -3285,7 +3285,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) iwlcore_commit_rxon(priv, ctx); /* RXON Timing */ - rc = iwl_send_rxon_timing(priv, vif); + rc = iwl_send_rxon_timing(priv, ctx); if (rc) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); -- cgit v1.2.3-59-g8ed1b From b01efe434bd6ea807eb72ba74fae11beab5c4c04 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:56 +0200 Subject: iwlagn: always send RXON timing The PAN context requires also getting RXON timing when we send an unassociated RXON in some cases. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 85eea944498e..1d58b1c7facd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -105,6 +105,7 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) int ret; bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); + bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK); if (!iwl_is_alive(priv)) return -EBUSY; @@ -182,7 +183,7 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); - if (new_assoc) { + if (!old_assoc) { /* * First of all, before setting associated, we need to * send RXON timing so the device knows about the DTIM -- cgit v1.2.3-59-g8ed1b From bde4530e9d2fa013b5674e4c9b066ed6d87ab45c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:57 +0200 Subject: iwlwifi: follow main beacon interval It is necessary that the PAN context always use the same beacon interval as the BSS context unless it is in dual-station mode, ie. the PAN context is a station as well, so implement that. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 91ca5173e862..a2b39fd4081e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -525,9 +525,16 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) */ ctx->timing.atim_window = 0; - beacon_int = iwl_adjust_beacon_interval(beacon_int, + if (ctx->ctxid == IWL_RXON_CTX_PAN && + (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION)) { + ctx->timing.beacon_interval = + priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval; + beacon_int = le16_to_cpu(ctx->timing.beacon_interval); + } else { + beacon_int = iwl_adjust_beacon_interval(beacon_int, priv->hw_params.max_beacon_itrvl * TIME_UNIT); - ctx->timing.beacon_interval = cpu_to_le16(beacon_int); + ctx->timing.beacon_interval = cpu_to_le16(beacon_int); + } tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ interval_tm = beacon_int * TIME_UNIT; -- cgit v1.2.3-59-g8ed1b From d0fe478c9f42dbc4916aa8d1d7a05d7f669d2209 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Aug 2010 10:46:58 +0200 Subject: iwlwifi: allow using multiple contexts We're now ready to start using multiple contexts. We do this by keeping track of the valid interface types per context (exclusive [ibss] and normal) and checking which context is "free" when a new interface is added. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 25 +++++++-- drivers/net/wireless/iwlwifi/iwl-core.c | 80 +++++++++++++++++------------ drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 11 ++-- 5 files changed, 82 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1d58b1c7facd..ad0e67f5c0d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2828,8 +2828,10 @@ static void iwl_alive_start(struct iwl_priv *priv) ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { + struct iwl_rxon_context *tmp; /* Initialize our rx_config data */ - iwl_connection_init_rx_config(priv, NULL); + for_each_context(priv, tmp) + iwl_connection_init_rx_config(priv, tmp); if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); @@ -3370,6 +3372,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, { int ret; struct ieee80211_hw *hw = priv->hw; + struct iwl_rxon_context *ctx; + hw->rate_control_algorithm = "iwl-agn-rs"; /* Tell mac80211 our characteristics */ @@ -3389,9 +3393,10 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, hw->sta_data_size = sizeof(struct iwl_station_priv); hw->vif_data_size = sizeof(struct iwl_vif_priv); - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC); + for_each_context(priv, ctx) { + hw->wiphy->interface_modes |= ctx->interface_modes; + hw->wiphy->interface_modes |= ctx->exclusive_interface_modes; + } hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS; @@ -4289,6 +4294,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo; priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue; + priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = + BIT(NL80211_IFTYPE_ADHOC); + priv->contexts[IWL_RXON_CTX_BSS].interface_modes = + BIT(NL80211_IFTYPE_STATION); + priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS; + priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS; + priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS; priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON; priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING; @@ -4301,6 +4313,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo; priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue; priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; + priv->contexts[IWL_RXON_CTX_PAN].interface_modes = + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); + priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP; + priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA; + priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P; BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a2b39fd4081e..87a2e40972ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1028,38 +1028,34 @@ EXPORT_SYMBOL(iwl_set_flags_for_band); * initialize rxon structure with default values from eeprom */ void iwl_connection_init_rx_config(struct iwl_priv *priv, - struct ieee80211_vif *vif) + struct iwl_rxon_context *ctx) { const struct iwl_channel_info *ch_info; - enum nl80211_iftype type = NL80211_IFTYPE_STATION; - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - - if (vif) { - type = vif->type; - ctx = iwl_rxon_ctx_from_vif(vif); - } memset(&ctx->staging, 0, sizeof(ctx->staging)); - switch (type) { + if (!ctx->vif) { + ctx->staging.dev_type = ctx->unused_devtype; + } else switch (ctx->vif->type) { case NL80211_IFTYPE_AP: - ctx->staging.dev_type = RXON_DEV_TYPE_AP; + ctx->staging.dev_type = ctx->ap_devtype; break; case NL80211_IFTYPE_STATION: - ctx->staging.dev_type = RXON_DEV_TYPE_ESS; + ctx->staging.dev_type = ctx->station_devtype; ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; break; case NL80211_IFTYPE_ADHOC: - ctx->staging.dev_type = RXON_DEV_TYPE_IBSS; + ctx->staging.dev_type = ctx->ibss_devtype; ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; default: - IWL_ERR(priv, "Unsupported interface type %d\n", type); + IWL_ERR(priv, "Unsupported interface type %d\n", + ctx->vif->type); break; } @@ -1081,7 +1077,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, ctx->staging.channel = cpu_to_le16(ch_info->channel); priv->band = ch_info->band; - iwl_set_flags_for_band(priv, ctx, priv->band, vif); + iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); ctx->staging.ofdm_basic_rates = (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; @@ -1091,8 +1087,8 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, /* clear both MIX and PURE40 mode flag */ ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | RXON_FLG_CHANNEL_MODE_PURE_40); - if (vif) - memcpy(ctx->staging.node_addr, vif->addr, ETH_ALEN); + if (ctx->vif) + memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN); ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff; ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; @@ -1952,7 +1948,7 @@ static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) { struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - iwl_connection_init_rx_config(priv, vif); + iwl_connection_init_rx_config(priv, ctx); if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); @@ -1964,7 +1960,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; - struct iwl_rxon_context *ctx; + struct iwl_rxon_context *tmp, *ctx = NULL; int err = 0; IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", @@ -1972,23 +1968,45 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mutex_lock(&priv->mutex); - /* For now always use this context. */ - ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - - vif_priv->ctx = ctx; - if (WARN_ON(!iwl_is_ready_rf(priv))) { err = -EINVAL; goto out; } - if (ctx->vif) { - IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); + for_each_context(priv, tmp) { + u32 possible_modes = + tmp->interface_modes | tmp->exclusive_interface_modes; + + if (tmp->vif) { + /* check if this busy context is exclusive */ + if (tmp->exclusive_interface_modes & + BIT(tmp->vif->type)) { + err = -EINVAL; + goto out; + } + continue; + } + + if (!(possible_modes & BIT(vif->type))) + continue; + + /* have maybe usable context w/o interface */ + ctx = tmp; + break; + } + + if (!ctx) { err = -EOPNOTSUPP; goto out; } + vif_priv->ctx = ctx; ctx->vif = vif; + /* + * This variable will be correct only when there's just + * a single context, but all code using it is for hardware + * that supports only one context. + */ priv->iw_mode = vif->type; err = iwl_set_mode(priv, vif); @@ -2029,11 +2047,11 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - if (iwl_is_ready_rf(priv)) { - iwl_scan_cancel_timeout(priv, 100); - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); - } + WARN_ON(ctx->vif != vif); + ctx->vif = NULL; + + iwl_scan_cancel_timeout(priv, 100); + iwl_set_mode(priv, vif); if (priv->scan_vif == vif) { scan_completed = true; @@ -2051,8 +2069,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, if (vif->type == NL80211_IFTYPE_ADHOC) priv->bt_traffic_load = priv->notif_bt_traffic_load; - WARN_ON(ctx->vif != vif); - ctx->vif = NULL; memset(priv->bssid, 0, ETH_ALEN); mutex_unlock(&priv->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4d7910001b75..f7b57ed84f66 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -394,7 +394,7 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct ieee80211_sta_ht_cap *ht_cap); void iwl_connection_init_rx_config(struct iwl_priv *priv, - struct ieee80211_vif *vif); + struct iwl_rxon_context *ctx); void iwl_set_rate(struct iwl_priv *priv); int iwl_set_decrypted_flag(struct iwl_priv *priv, struct ieee80211_hdr *hdr, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 422c71e122f7..4dd38b7b8b74 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1117,6 +1117,10 @@ struct iwl_rxon_context { u8 mcast_queue; enum iwl_rxon_context_id ctxid; + + u32 interface_modes, exclusive_interface_modes; + u8 unused_devtype, ap_devtype, ibss_devtype, station_devtype; + /* * We declare this const so it can only be * changed via explicit cast within the diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 76a45b239664..68e624afb987 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2540,7 +2540,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ - iwl_connection_init_rx_config(priv, NULL); + iwl_connection_init_rx_config(priv, ctx); } /* Configure Bluetooth device coexistence support */ @@ -3955,8 +3955,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) IEEE80211_HW_SUPPORTS_DYNAMIC_PS; hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC); + priv->contexts[IWL_RXON_CTX_BSS].interface_modes; hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS; @@ -4024,6 +4023,12 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; + priv->contexts[IWL_RXON_CTX_BSS].interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS; + priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS; + priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS; /* * Disabling hardware scan means that mac80211 will perform scans -- cgit v1.2.3-59-g8ed1b From df1c2986c4685776ed02802c170c7fb6f47d8218 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 21 Aug 2010 21:24:59 +0200 Subject: ath5k: re-order one of the frees on unwind There was a small misordering here. In the original code, if we were to go to err_free_ah then it wouldn't free the irq. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index f2fceb10c9fc..45789c8990d3 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -700,10 +700,10 @@ ath5k_pci_probe(struct pci_dev *pdev, return 0; err_ah: ath5k_hw_detach(sc->ah); -err_irq: - free_irq(pdev->irq, sc); err_free_ah: kfree(sc->ah); +err_irq: + free_irq(pdev->irq, sc); err_free: ieee80211_free_hw(hw); err_map: -- cgit v1.2.3-59-g8ed1b From 53b1cf8a28c440fcb241f6fb84da71a7cb0f74f0 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Tue, 24 Aug 2010 21:37:14 -0400 Subject: ath5k: fix off-by-one in pilot magnitude mask If the symbol offset is 46, it will be counted in both the third and fourth bytes of the mask, and in this case the shift will be negative which can pollute high order bits in the mask. This may negatively impact OFDM symbol detection. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 8c27a3644d2f..984ba92c7df3 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1582,7 +1582,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, else if (curr_sym_off >= 31 && curr_sym_off <= 46) mag_mask[2] |= plt_mag_map << (curr_sym_off - 31) * 2; - else if (curr_sym_off >= 46 && curr_sym_off <= 53) + else if (curr_sym_off >= 47 && curr_sym_off <= 53) mag_mask[3] |= plt_mag_map << (curr_sym_off - 47) * 2; -- cgit v1.2.3-59-g8ed1b From 93dbbcc45c364d62d58737fb9fe6d31085d6a999 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Wed, 25 Aug 2010 19:34:52 +0530 Subject: ath9k: Change the default LED pattern. All major Atheros customers require the led to be in continuous ON state rather than the blinking pattern. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 243c1775f343..3dbff8d07766 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -33,7 +33,7 @@ int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); -int led_blink = 1; +int led_blink; module_param_named(blink, led_blink, int, 0444); MODULE_PARM_DESC(blink, "Enable LED blink on activity"); -- cgit v1.2.3-59-g8ed1b From 5f33c92d188add2a22ec524c03e0ab097e303d52 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 26 Aug 2010 13:30:25 +0200 Subject: mac80211: remove unused scan expire define Since cfg80211 manages the BSS list completely, this define hasn't been used for a long time and will never be used again. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e73ae51dc036..9e225f01497b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -50,12 +50,6 @@ struct ieee80211_local; * increased memory use (about 2 kB of RAM per entry). */ #define IEEE80211_FRAGMENT_MAX 4 -/* - * Time after which we ignore scan results and no longer report/use - * them in any way. - */ -#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) - #define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024)) #define IEEE80211_DEFAULT_UAPSD_QUEUES \ -- cgit v1.2.3-59-g8ed1b From 8789d459bc5e837bf37d261453df96ef54018d7b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 26 Aug 2010 13:30:26 +0200 Subject: mac80211: allow scan to complete from any context The ieee80211_scan_completed() function was a frequent source of potential deadlocks, since it is called by drivers but may call back into drivers, so drivers had to make sure to call it without any locks held, which frequently lead to more complex code in drivers. Avoid that problem by allowing the function to be called in any context, and queueing the actual work it does. Also update the documentation for it to indicate this. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 3 ++- net/mac80211/ieee80211_i.h | 6 ++++++ net/mac80211/scan.c | 34 ++++++++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index dcc8c2bf986e..8f97548b6d80 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2268,7 +2268,8 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw); * * When hardware scan offload is used (i.e. the hw_scan() callback is * assigned) this function needs to be called by the driver to notify - * mac80211 that the scan finished. + * mac80211 that the scan finished. This function can be called from + * any context, including hardirq context. * * @hw: the hardware that finished the scan * @aborted: set to true if scan was aborted diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9e225f01497b..31713320258c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -596,11 +596,17 @@ enum queue_stop_reason { * determine if we are on the operating channel or not * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, * gets only set in conjunction with SCAN_SW_SCANNING + * @SCAN_COMPLETED: Set for our scan work function when the driver reported + * that the scan completed. + * @SCAN_ABORTED: Set for our scan work function when the driver reported + * a scan complete for an aborted scan. */ enum { SCAN_SW_SCANNING, SCAN_HW_SCANNING, SCAN_OFF_CHANNEL, + SCAN_COMPLETED, + SCAN_ABORTED, }; /** diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 31f233f7f51a..d60389ba9b95 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -248,13 +248,11 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) return true; } -void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) +static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) { struct ieee80211_local *local = hw_to_local(hw); bool was_hw_scan; - trace_api_scan_completed(local, aborted); - mutex_lock(&local->mtx); /* @@ -312,6 +310,18 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ieee80211_mesh_notify_scan_completed(local); ieee80211_queue_work(&local->hw, &local->work_work); } + +void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) +{ + struct ieee80211_local *local = hw_to_local(hw); + + trace_api_scan_completed(local, aborted); + + set_bit(SCAN_COMPLETED, &local->scanning); + if (aborted) + set_bit(SCAN_ABORTED, &local->scanning); + ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); +} EXPORT_SYMBOL(ieee80211_scan_completed); static int ieee80211_start_sw_scan(struct ieee80211_local *local) @@ -449,7 +459,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, /* if no more bands/channels left, complete scan and advance to the idle state */ if (local->scan_channel_idx >= local->scan_req->n_channels) { - ieee80211_scan_completed(&local->hw, false); + __ieee80211_scan_completed(&local->hw, false); return 1; } @@ -641,6 +651,14 @@ void ieee80211_scan_work(struct work_struct *work) struct ieee80211_sub_if_data *sdata = local->scan_sdata; unsigned long next_delay = 0; + if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) { + bool aborted; + + aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); + __ieee80211_scan_completed(&local->hw, aborted); + return; + } + mutex_lock(&local->mtx); if (!sdata || !local->scan_req) { mutex_unlock(&local->mtx); @@ -651,7 +669,7 @@ void ieee80211_scan_work(struct work_struct *work) int rc = drv_hw_scan(local, sdata, local->hw_scan_req); mutex_unlock(&local->mtx); if (rc) - ieee80211_scan_completed(&local->hw, true); + __ieee80211_scan_completed(&local->hw, true); return; } @@ -666,7 +684,7 @@ void ieee80211_scan_work(struct work_struct *work) mutex_unlock(&local->mtx); if (rc) - ieee80211_scan_completed(&local->hw, true); + __ieee80211_scan_completed(&local->hw, true); return; } @@ -676,7 +694,7 @@ void ieee80211_scan_work(struct work_struct *work) * Avoid re-scheduling when the sdata is going away. */ if (!ieee80211_sdata_running(sdata)) { - ieee80211_scan_completed(&local->hw, true); + __ieee80211_scan_completed(&local->hw, true); return; } @@ -783,5 +801,5 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) mutex_unlock(&local->mtx); if (abortscan) - ieee80211_scan_completed(&local->hw, true); + __ieee80211_scan_completed(&local->hw, true); } -- cgit v1.2.3-59-g8ed1b From 0ec2f2724d7e457b91e5983d11db8adba9aad47e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 26 Aug 2010 13:30:27 +0200 Subject: wl12xx: remove unneeded locking With the scan callback now being callable from any context, these unlocks/locks can go away. This makes the code easier to understand, since callers of these functions must no longer be aware that the mutex may be dropped. As Stanislaw is working on iwlwifi scanning, I didn't change it to take advantage of the new mac80211 semantics. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_event.c | 2 -- drivers/net/wireless/wl12xx/wl1251_main.c | 2 -- drivers/net/wireless/wl12xx/wl1271_main.c | 2 -- drivers/net/wireless/wl12xx/wl1271_scan.c | 2 -- 4 files changed, 8 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c index 00c3e648d93f..54223556b308 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.c +++ b/drivers/net/wireless/wl12xx/wl1251_event.c @@ -34,9 +34,7 @@ static int wl1251_event_scan_complete(struct wl1251 *wl, mbox->scheduled_scan_channels); if (wl->scanning) { - mutex_unlock(&wl->mutex); ieee80211_scan_completed(wl->hw, false); - mutex_lock(&wl->mutex); wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed"); wl->scanning = false; } diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index edd4845c3707..f9d9ad620cc9 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -467,9 +467,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) WARN_ON(wl->state != WL1251_STATE_ON); if (wl->scanning) { - mutex_unlock(&wl->mutex); ieee80211_scan_completed(wl->hw, true); - mutex_lock(&wl->mutex); wl->scanning = false; } diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 30194c0f36a9..8e55cf8d509d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -948,9 +948,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, ieee80211_enable_dyn_ps(wl->vif); if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { - mutex_unlock(&wl->mutex); ieee80211_scan_completed(wl->hw, true); - mutex_lock(&wl->mutex); wl->scan.state = WL1271_SCAN_STATE_IDLE; kfree(wl->scan.scanned_ch); wl->scan.scanned_ch = NULL; diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c index fec43eed8c55..9c80ba9b6be0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_scan.c +++ b/drivers/net/wireless/wl12xx/wl1271_scan.c @@ -215,9 +215,7 @@ void wl1271_scan_stm(struct wl1271 *wl) break; case WL1271_SCAN_STATE_DONE: - mutex_unlock(&wl->mutex); ieee80211_scan_completed(wl->hw, false); - mutex_lock(&wl->mutex); kfree(wl->scan.scanned_ch); wl->scan.scanned_ch = NULL; -- cgit v1.2.3-59-g8ed1b From fe67470ddd075cb7d538de1570950da3c0f67e65 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 27 Aug 2010 12:09:00 +0530 Subject: ath9k_htc: Enable ANI in associated state only While scanning, ANI is triggered unnecessarily where sta is in unassociated state. And cancelling ani work in ath9k_htc_stop is not required. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 5e318cb662c6..f4672073ac0a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1239,7 +1239,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) /* Cancel all the running timers/work .. */ cancel_work_sync(&priv->ps_work); - cancel_delayed_work_sync(&priv->ath9k_ani_work); cancel_delayed_work_sync(&priv->ath9k_led_blink_work); ath9k_led_stop_brightness(priv); @@ -1787,7 +1786,8 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) priv->op_flags |= OP_SCANNING; spin_unlock_bh(&priv->beacon_lock); cancel_work_sync(&priv->ps_work); - cancel_delayed_work_sync(&priv->ath9k_ani_work); + if (priv->op_flags & OP_ASSOCIATED) + cancel_delayed_work_sync(&priv->ath9k_ani_work); mutex_unlock(&priv->mutex); } @@ -1801,9 +1801,10 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) priv->op_flags &= ~OP_SCANNING; spin_unlock_bh(&priv->beacon_lock); priv->op_flags |= OP_FULL_RESET; - if (priv->op_flags & OP_ASSOCIATED) + if (priv->op_flags & OP_ASSOCIATED) { ath9k_htc_beacon_config(priv, priv->vif); - ath_start_ani(priv); + ath_start_ani(priv); + } ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); } -- cgit v1.2.3-59-g8ed1b From b49d09c5bf9a3261ae711ac3bb91e22c172db428 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 11:29:24 +0200 Subject: cfg80211 docbook: remove erronous !A My previous patch erroneously included an !A line (for some checking I am working on) that isn't yet supported by the docbook tools, so remove it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/DocBook/80211.tmpl | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index b84c9282828f..19a1210c2530 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -65,7 +65,6 @@ -!Ainclude/net/cfg80211.h The cfg80211 subsystem -- cgit v1.2.3-59-g8ed1b From 7d64b7cc1fc33bab24567903a93f699d11649c0b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 14:26:51 +0300 Subject: cfg80211: allow vendor specific cipher suites cfg80211 currently rejects all cipher suites it doesn't know about for key length checking purposes. This can lead to inconsistencies when a driver advertises an algorithm that cfg80211 doesn't know about. Remove this rejection so drivers can specify any algorithm they like. Signed-off-by: Johannes Berg Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- net/wireless/util.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/wireless/util.c b/net/wireless/util.c index 8d961cc4ae98..bca32eb8f446 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -183,7 +183,14 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, return -EINVAL; break; default: - return -EINVAL; + /* + * We don't know anything about this algorithm, + * allow using it -- but the driver must check + * all parameters! We still check below whether + * or not the driver supports this algorithm, + * of course. + */ + break; } if (params->seq) { -- cgit v1.2.3-59-g8ed1b From 3ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 14:26:52 +0300 Subject: mac80211: allow vendor specific cipher suites Allow drivers to specify their own set of cipher suites to advertise vendor-specific ciphers. The driver is then required to implement hardware crypto offload for it. Signed-off-by: Johannes Berg Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 5 +++-- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/key.c | 38 ++++++++++++++++++++++++++++++-------- net/mac80211/key.h | 6 +++--- net/mac80211/main.c | 44 ++++++++++++++++++++++++++++++++++++++------ net/mac80211/rx.c | 6 ++++++ net/mac80211/tx.c | 12 ++++++++++-- 7 files changed, 92 insertions(+), 21 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 581438255d7e..f149b4eb28d9 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -119,9 +119,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, } } - ieee80211_key_link(key, sdata, sta); + err = ieee80211_key_link(key, sdata, sta); + if (err) + ieee80211_key_free(sdata->local, key); - err = 0; out_unlock: mutex_unlock(&sdata->local->sta_mtx); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 31713320258c..7d2bb6fbc2e6 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -662,6 +662,8 @@ struct ieee80211_local { int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll; unsigned int filter_flags; /* FIF_* */ + bool wiphy_ciphers_allocated; + /* protects the aggregated multicast list and filter calls */ spinlock_t filter_lock; diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 2ce2dbbf6309..3570f8c2bb40 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -60,7 +60,7 @@ static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) return NULL; } -static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) +static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) { struct ieee80211_sub_if_data *sdata; struct ieee80211_sta *sta; @@ -68,8 +68,10 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) might_sleep(); - if (!key->local->ops->set_key) - return; + if (!key->local->ops->set_key) { + ret = -EOPNOTSUPP; + goto out_unsupported; + } assert_key_lock(key->local); @@ -90,6 +92,24 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) wiphy_err(key->local->hw.wiphy, "failed to set key (%d, %pM) to hardware (%d)\n", key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); + +out_unsupported: + if (ret) { + switch (key->conf.cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_AES_CMAC: + /* all of these we can do in software */ + ret = 0; + break; + default: + ret = -EINVAL; + } + } + + return ret; } static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) @@ -329,12 +349,12 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) kfree(key); } -void ieee80211_key_link(struct ieee80211_key *key, - struct ieee80211_sub_if_data *sdata, - struct sta_info *sta) +int ieee80211_key_link(struct ieee80211_key *key, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta) { struct ieee80211_key *old_key; - int idx; + int idx, ret; BUG_ON(!sdata); BUG_ON(!key); @@ -389,9 +409,11 @@ void ieee80211_key_link(struct ieee80211_key *key, ieee80211_debugfs_key_add(key); - ieee80211_key_enable_hw_accel(key); + ret = ieee80211_key_enable_hw_accel(key); mutex_unlock(&sdata->local->key_mtx); + + return ret; } static void __ieee80211_key_free(struct ieee80211_key *key) diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 53b5ce12536f..cb9a4a65cc68 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -130,9 +130,9 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, * Insert a key into data structures (sdata, sta if necessary) * to make it used, free old key. */ -void ieee80211_key_link(struct ieee80211_key *key, - struct ieee80211_sub_if_data *sdata, - struct sta_info *sta); +int __must_check ieee80211_key_link(struct ieee80211_key *key, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta); void ieee80211_key_free(struct ieee80211_local *local, struct ieee80211_key *key); void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 80db5ea02052..15f0e960fde8 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -662,13 +662,40 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (local->hw.wiphy->max_scan_ie_len) local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; - local->hw.wiphy->cipher_suites = cipher_suites; - local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); - if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) - local->hw.wiphy->n_cipher_suites--; + /* Set up cipher suites unless driver already did */ + if (!local->hw.wiphy->cipher_suites) { + local->hw.wiphy->cipher_suites = cipher_suites; + local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) + local->hw.wiphy->n_cipher_suites--; + } if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) { - local->hw.wiphy->cipher_suites += 2; - local->hw.wiphy->n_cipher_suites -= 2; + if (local->hw.wiphy->cipher_suites == cipher_suites) { + local->hw.wiphy->cipher_suites += 2; + local->hw.wiphy->n_cipher_suites -= 2; + } else { + u32 *suites; + int r, w = 0; + + /* Filter out WEP */ + + suites = kmemdup( + local->hw.wiphy->cipher_suites, + sizeof(u32) * local->hw.wiphy->n_cipher_suites, + GFP_KERNEL); + if (!suites) + return -ENOMEM; + for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { + u32 suite = local->hw.wiphy->cipher_suites[r]; + if (suite == WLAN_CIPHER_SUITE_WEP40 || + suite == WLAN_CIPHER_SUITE_WEP104) + continue; + suites[w++] = suite; + } + local->hw.wiphy->cipher_suites = suites; + local->hw.wiphy->n_cipher_suites = w; + local->wiphy_ciphers_allocated = true; + } } result = wiphy_register(local->hw.wiphy); @@ -783,6 +810,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) fail_workqueue: wiphy_unregister(local->hw.wiphy); fail_wiphy_register: + if (local->wiphy_ciphers_allocated) + kfree(local->hw.wiphy->cipher_suites); kfree(local->int_scan_req); return result; } @@ -840,6 +869,9 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) mutex_destroy(&local->iflist_mtx); mutex_destroy(&local->mtx); + if (local->wiphy_ciphers_allocated) + kfree(local->hw.wiphy->cipher_suites); + wiphy_free(local->hw.wiphy); } EXPORT_SYMBOL(ieee80211_free_hw); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index e67deb48af5c..6e5fb16af55c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1000,6 +1000,12 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) case WLAN_CIPHER_SUITE_AES_CMAC: result = ieee80211_crypto_aes_cmac_decrypt(rx); break; + default: + /* + * We can reach here only with HW-only algorithms + * but why didn't it decrypt the frame?! + */ + return RX_DROP_UNUSABLE; } /* either the frame has been decrypted or will be dropped */ diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index a6ac9fd248f2..31a8903a45af 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -947,6 +947,8 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) static ieee80211_tx_result debug_noinline ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + if (!tx->key) return TX_CONTINUE; @@ -960,10 +962,16 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) return ieee80211_crypto_ccmp_encrypt(tx); case WLAN_CIPHER_SUITE_AES_CMAC: return ieee80211_crypto_aes_cmac_encrypt(tx); + default: + /* handle hw-only algorithm */ + if (info->control.hw_key) { + ieee80211_tx_set_protected(tx); + return TX_CONTINUE; + } + break; + } - /* not reached */ - WARN_ON(1); return TX_DROP; } -- cgit v1.2.3-59-g8ed1b From c0692b8fe29fb4d4dad33487aabf3ed7e1e880c0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 14:26:53 +0300 Subject: cfg80211: allow changing port control protocol Some vendor specified mechanisms for 802.1X-style functionality use a different protocol than EAP (even if EAP is vendor-extensible). Allow setting the ethertype for the protocol when a driver has support for this. The default if unspecified is EAP, of course. Note: This is suitable only for station mode, not for AP implementation. Signed-off-by: Johannes Berg Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- include/linux/nl80211.h | 16 +++++++++++++++- include/net/cfg80211.h | 24 +++++++++++++++++------- net/wireless/nl80211.c | 25 ++++++++++++++++++++++--- net/wireless/wext-sme.c | 2 ++ 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index ec1690da7845..31603e8b5581 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -295,7 +295,9 @@ * auth and assoc steps. For this, you need to specify the SSID in a * %NL80211_ATTR_SSID attribute, and can optionally specify the association * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC, - * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_CONTROL_PORT. + * %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, + * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and + * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT. * It is also sent as an event, with the BSSID and response IEs when the * connection is established or failed to be established. This can be * determined by the STATUS_CODE attribute. @@ -686,6 +688,15 @@ enum nl80211_commands { * request, the driver will assume that the port is unauthorized until * authorized by user space. Otherwise, port is marked authorized by * default in station mode. + * @NL80211_ATTR_CONTROL_PORT_ETHERTYPE: A 16-bit value indicating the + * ethertype that will be used for key negotiation. It can be + * specified with the associate and connect commands. If it is not + * specified, the value defaults to 0x888E (PAE, 802.1X). This + * attribute is also used as a flag in the wiphy information to + * indicate that protocols other than PAE are supported. + * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with + * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom + * ethertype frames used for key negotiation must not be encrypted. * * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. * We recommend using nested, driver-specific attributes within this. @@ -951,6 +962,9 @@ enum nl80211_attrs { NL80211_ATTR_RX_FRAME_TYPES, NL80211_ATTR_FRAME_TYPE, + NL80211_ATTR_CONTROL_PORT_ETHERTYPE, + NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f2740537b5d6..4c8c727d0cca 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -763,6 +763,10 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is * required to assume that the port is unauthorized until authorized by * user space. Otherwise, port is marked authorized by default. + * @control_port_ethertype: the control port protocol that should be + * allowed through even on unauthorized ports + * @control_port_no_encrypt: TRUE to prevent encryption of control port + * protocol frames. */ struct cfg80211_crypto_settings { u32 wpa_versions; @@ -772,6 +776,8 @@ struct cfg80211_crypto_settings { int n_akm_suites; u32 akm_suites[NL80211_MAX_NR_AKM_SUITES]; bool control_port; + __be16 control_port_ethertype; + bool control_port_no_encrypt; }; /** @@ -1293,15 +1299,19 @@ struct cfg80211_ops { * @WIPHY_FLAG_4ADDR_AP: supports 4addr mode even on AP (with a single station * on a VLAN interface) * @WIPHY_FLAG_4ADDR_STATION: supports 4addr mode even as a station + * @WIPHY_FLAG_CONTROL_PORT_PROTOCOL: This device supports setting the + * control port protocol ethertype. The device also honours the + * control_port_no_encrypt flag. */ enum wiphy_flags { - WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), - WIPHY_FLAG_STRICT_REGULATORY = BIT(1), - WIPHY_FLAG_DISABLE_BEACON_HINTS = BIT(2), - WIPHY_FLAG_NETNS_OK = BIT(3), - WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4), - WIPHY_FLAG_4ADDR_AP = BIT(5), - WIPHY_FLAG_4ADDR_STATION = BIT(6), + WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), + WIPHY_FLAG_STRICT_REGULATORY = BIT(1), + WIPHY_FLAG_DISABLE_BEACON_HINTS = BIT(2), + WIPHY_FLAG_NETNS_OK = BIT(3), + WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4), + WIPHY_FLAG_4ADDR_AP = BIT(5), + WIPHY_FLAG_4ADDR_STATION = BIT(6), + WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), }; struct mac_address { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 49f5ca35e787..85a23de7bff3 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -136,6 +136,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { .len = sizeof(struct nl80211_sta_flag_update), }, [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG }, + [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 }, + [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG }, [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG }, [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, @@ -474,6 +476,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, dev->wiphy.max_num_pmkids); + if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) + NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); + nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); if (!nl_modes) goto nla_put_failure; @@ -3691,7 +3696,8 @@ unlock_rtnl: return err; } -static int nl80211_crypto_settings(struct genl_info *info, +static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, + struct genl_info *info, struct cfg80211_crypto_settings *settings, int cipher_limit) { @@ -3699,6 +3705,19 @@ static int nl80211_crypto_settings(struct genl_info *info, settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT]; + if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) { + u16 proto; + proto = nla_get_u16( + info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]); + settings->control_port_ethertype = cpu_to_be16(proto); + if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && + proto != ETH_P_PAE) + return -EINVAL; + if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]) + settings->control_port_no_encrypt = true; + } else + settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE); + if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) { void *data; int len, i; @@ -3826,7 +3845,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_PREV_BSSID]) prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); - err = nl80211_crypto_settings(info, &crypto, 1); + err = nl80211_crypto_settings(rdev, info, &crypto, 1); if (!err) err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, ssid, ssid_len, ie, ie_len, use_mfp, @@ -4303,7 +4322,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) connect.privacy = info->attrs[NL80211_ATTR_PRIVACY]; - err = nl80211_crypto_settings(info, &connect.crypto, + err = nl80211_crypto_settings(rdev, info, &connect.crypto, NL80211_MAX_NR_CIPHER_SUITES); if (err) return err; diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 9818198add8a..6fffe62d7c25 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -197,6 +197,8 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, wdev->wext.connect.ssid_len = len; wdev->wext.connect.crypto.control_port = false; + wdev->wext.connect.crypto.control_port_ethertype = + cpu_to_be16(ETH_P_PAE); err = cfg80211_mgd_wext_connect(rdev, wdev); out: -- cgit v1.2.3-59-g8ed1b From a621fa4d6a7fdf9d34938d2e129a72624833eeeb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 14:26:54 +0300 Subject: mac80211: allow changing port control protocol Some vendor specified mechanisms for 802.1X-style functionality use a different protocol than EAP (even if EAP is vendor-extensible). Support this in mac80211 via the cfg80211 API for it. Signed-off-by: Johannes Berg Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/iface.c | 3 +++ net/mac80211/main.c | 3 +++ net/mac80211/mlme.c | 3 +++ net/mac80211/rx.c | 2 +- net/mac80211/tx.c | 20 +++++++++++++++++--- 6 files changed, 29 insertions(+), 4 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 7d2bb6fbc2e6..f64837788681 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -509,6 +509,8 @@ struct ieee80211_sub_if_data { struct ieee80211_key *default_mgmt_key; u16 sequence_number; + __be16 control_port_protocol; + bool control_port_no_encrypt; struct work_struct work; struct sk_buff_head skb_queue; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 9369710cc65b..810e6764d04f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -855,6 +855,9 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, sdata->dev->netdev_ops = &ieee80211_dataif_ops; sdata->wdev.iftype = type; + sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); + sdata->control_port_no_encrypt = false; + /* only monitor differs */ sdata->dev->type = ARPHRD_ETHER; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 15f0e960fde8..964c267163a0 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -627,6 +627,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT); #endif + /* mac80211 supports control port protocol changing */ + local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; + if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 5282ac18d2cf..0cb429657474 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2262,6 +2262,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, else ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; + sdata->control_port_protocol = req->crypto.control_port_ethertype; + sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; + ieee80211_add_work(wk); return 0; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6e5fb16af55c..ac205a33690f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1527,7 +1527,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) * Allow EAPOL frames to us/the PAE group address regardless * of whether the frame was encrypted or not. */ - if (ehdr->h_proto == htons(ETH_P_PAE) && + if (ehdr->h_proto == rx->sdata->control_port_protocol && (compare_ether_addr(ehdr->h_dest, rx->sdata->vif.addr) == 0 || compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) return true; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 31a8903a45af..92764bb8795c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -508,6 +508,18 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) return ieee80211_tx_h_multicast_ps_buf(tx); } +static ieee80211_tx_result debug_noinline +ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + + if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol && + tx->sdata->control_port_no_encrypt)) + info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; + + return TX_CONTINUE; +} + static ieee80211_tx_result debug_noinline ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) { @@ -527,7 +539,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) else if ((key = rcu_dereference(tx->sdata->default_key))) tx->key = key; else if (tx->sdata->drop_unencrypted && - (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) && + (tx->skb->protocol != tx->sdata->control_port_protocol) && !(info->flags & IEEE80211_TX_CTL_INJECTED) && (!ieee80211_is_robust_mgmt_frame(hdr) || (ieee80211_is_action(hdr->frame_control) && @@ -1349,6 +1361,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) CALL_TXH(ieee80211_tx_h_dynamic_ps); CALL_TXH(ieee80211_tx_h_check_assoc); CALL_TXH(ieee80211_tx_h_ps_buf); + CALL_TXH(ieee80211_tx_h_check_control_port_protocol); CALL_TXH(ieee80211_tx_h_select_key); if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) CALL_TXH(ieee80211_tx_h_rate_ctrl); @@ -1826,7 +1839,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, #endif case NL80211_IFTYPE_STATION: memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); - if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) { + if (sdata->u.mgd.use_4addr && + cpu_to_be16(ethertype) != sdata->control_port_protocol) { fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); /* RA TA DA SA */ memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); @@ -1879,7 +1893,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, if (!ieee80211_vif_is_mesh(&sdata->vif) && unlikely(!is_multicast_ether_addr(hdr.addr1) && !(sta_flags & WLAN_STA_AUTHORIZED) && - !(ethertype == ETH_P_PAE && + !(cpu_to_be16(ethertype) == sdata->control_port_protocol && compare_ether_addr(sdata->vif.addr, skb->data + ETH_ALEN) == 0))) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG -- cgit v1.2.3-59-g8ed1b From 2337db8db845ece2d4ab7673a343e285f1bfda85 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 13:36:49 +0200 Subject: mac80211: use subqueue helpers There are subqueue helpers so that we don't need to get the TX queue and then wake/stop it, use those helpers. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 3 +-- net/mac80211/util.c | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 92764bb8795c..ccf373788ce9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2092,8 +2092,7 @@ void ieee80211_tx_pending(unsigned long data) if (skb_queue_empty(&local->pending[i])) list_for_each_entry_rcu(sdata, &local->interfaces, list) - netif_tx_wake_queue( - netdev_get_tx_queue(sdata->dev, i)); + netif_wake_subqueue(sdata->dev, i); } spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index cd2b485fed4f..ef686d3b04e3 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -284,7 +284,7 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, if (skb_queue_empty(&local->pending[queue])) { rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) - netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue)); + netif_wake_subqueue(sdata->dev, queue); rcu_read_unlock(); } else tasklet_schedule(&local->tx_pending_tasklet); @@ -323,7 +323,7 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) - netif_tx_stop_queue(netdev_get_tx_queue(sdata->dev, queue)); + netif_stop_subqueue(sdata->dev, queue); rcu_read_unlock(); } -- cgit v1.2.3-59-g8ed1b From b9dcf712d1fb98bf279fcd453a42a763b104961d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 12:35:54 +0200 Subject: mac80211: clean up ifdown/cleanup paths There's a lot of redundant code in mac80211's interface cleanup/down, for example freeing AP beacons is done both when the interface is set DOWN as well as when it is torn down, of which only the former has any effect. Also, a bunch of things should be closer to where they matter, like the MLME timers that we should cancel when disassociating, rather than only when the interface is set DOWN. Clean up all this code. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/iface.c | 89 ++++++++++++++-------------------------------------- net/mac80211/mlme.c | 5 +++ 2 files changed, 28 insertions(+), 66 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 810e6764d04f..cc1c68d7dda6 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -370,12 +370,9 @@ static int ieee80211_stop(struct net_device *dev) * (because if we remove a STA after ops->remove_interface() * the driver will have removed the vif info already!) * - * We could relax this and only unlink the stations from the - * hash table and list but keep them on a per-sdata list that - * will be inserted back again when the interface is brought - * up again, but I don't currently see a use case for that, - * except with WDS which gets a STA entry created when it is - * brought up. + * This is relevant only in AP, WDS and mesh modes, since in + * all other modes we've already removed all stations when + * disconnecting etc. */ sta_info_flush(local, sdata); @@ -410,11 +407,21 @@ static int ieee80211_stop(struct net_device *dev) struct ieee80211_sub_if_data *vlan, *tmpsdata; struct beacon_data *old_beacon = sdata->u.ap.beacon; + /* sdata_running will return false, so this will disable */ + ieee80211_bss_info_change_notify(sdata, + BSS_CHANGED_BEACON_ENABLED); + /* remove beacon */ rcu_assign_pointer(sdata->u.ap.beacon, NULL); synchronize_rcu(); kfree(old_beacon); + /* free all potentially still buffered bcast frames */ + while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { + local->total_ps_buffered--; + dev_kfree_skb(skb); + } + /* down all dependent devices, that is VLANs */ list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, u.vlan.list) @@ -454,27 +461,6 @@ static int ieee80211_stop(struct net_device *dev) ieee80211_configure_filter(local); break; - case NL80211_IFTYPE_STATION: - del_timer_sync(&sdata->u.mgd.chswitch_timer); - del_timer_sync(&sdata->u.mgd.timer); - del_timer_sync(&sdata->u.mgd.conn_mon_timer); - del_timer_sync(&sdata->u.mgd.bcn_mon_timer); - /* - * If any of the timers fired while we waited for it, it will - * have queued its work. Now the work will be running again - * but will not rearm the timer again because it checks - * whether the interface is running, which, at this point, - * it no longer is. - */ - cancel_work_sync(&sdata->u.mgd.chswitch_work); - cancel_work_sync(&sdata->u.mgd.monitor_work); - cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work); - - /* fall through */ - case NL80211_IFTYPE_ADHOC: - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - del_timer_sync(&sdata->u.ibss.timer); - /* fall through */ case NL80211_IFTYPE_MESH_POINT: if (ieee80211_vif_is_mesh(&sdata->vif)) { /* other_bss and allmulti are always set on mesh @@ -502,17 +488,19 @@ static int ieee80211_stop(struct net_device *dev) ieee80211_scan_cancel(local); /* - * Disable beaconing for AP and mesh, IBSS can't - * still be joined to a network at this point. + * Disable beaconing here for mesh only, AP and IBSS + * are already taken care of. */ - if (sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_MESH_POINT) { + if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); - } - /* free all remaining keys, there shouldn't be any */ + /* + * Free all remaining keys, there shouldn't be any, + * except maybe group keys in AP more or WDS? + */ ieee80211_free_keys(sdata); + drv_remove_interface(local, &sdata->vif); } @@ -593,8 +581,6 @@ static void ieee80211_teardown_sdata(struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; - struct beacon_data *beacon; - struct sk_buff *skb; int flushed; int i; @@ -607,37 +593,8 @@ static void ieee80211_teardown_sdata(struct net_device *dev) __skb_queue_purge(&sdata->fragments[i].skb_list); sdata->fragment_next = 0; - switch (sdata->vif.type) { - case NL80211_IFTYPE_AP: - beacon = sdata->u.ap.beacon; - rcu_assign_pointer(sdata->u.ap.beacon, NULL); - synchronize_rcu(); - kfree(beacon); - - while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { - local->total_ps_buffered--; - dev_kfree_skb(skb); - } - - break; - case NL80211_IFTYPE_MESH_POINT: - if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rmc_free(sdata); - break; - case NL80211_IFTYPE_ADHOC: - if (WARN_ON(sdata->u.ibss.presp)) - kfree_skb(sdata->u.ibss.presp); - break; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_MONITOR: - break; - case NL80211_IFTYPE_UNSPECIFIED: - case NUM_NL80211_IFTYPES: - BUG(); - break; - } + if (ieee80211_vif_is_mesh(&sdata->vif)) + mesh_rmc_free(sdata); flushed = sta_info_flush(local, sdata); WARN_ON(flushed); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0cb429657474..c8694478cde2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -991,6 +991,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, if (remove_sta) sta_info_destroy_addr(sdata, bssid); + + del_timer_sync(&sdata->u.mgd.conn_mon_timer); + del_timer_sync(&sdata->u.mgd.bcn_mon_timer); + del_timer_sync(&sdata->u.mgd.timer); + del_timer_sync(&sdata->u.mgd.chswitch_timer); } void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, -- cgit v1.2.3-59-g8ed1b From 26a58456be40d8181b884eb5b4e61e3f73ba94e0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 12:35:55 +0200 Subject: mac80211: switch to ieee80211_sdata_running Since the introduction of ieee80211_sdata_running(), some new code was introduced that uses netif_running() instead. Switch all these instances over. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 6 ++---- net/mac80211/main.c | 6 +++--- net/mac80211/util.c | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f149b4eb28d9..f82b18e996b2 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -81,16 +81,14 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, const u8 *mac_addr, struct key_params *params) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct sta_info *sta = NULL; struct ieee80211_key *key; int err; - if (!netif_running(dev)) + if (!ieee80211_sdata_running(sdata)) return -ENETDOWN; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - /* reject WEP and TKIP keys if WEP failed to initialize */ switch (params->cipher) { case WLAN_CIPHER_SUITE_WEP40: diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 964c267163a0..93194f61adb0 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -339,9 +339,6 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, struct ieee80211_if_managed *ifmgd; int c = 0; - if (!netif_running(ndev)) - return NOTIFY_DONE; - /* Make sure it's our interface that got changed */ if (!wdev) return NOTIFY_DONE; @@ -352,6 +349,9 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, sdata = IEEE80211_DEV_TO_SUB_IF(ndev); bss_conf = &sdata->vif.bss_conf; + if (!ieee80211_sdata_running(sdata)) + return NOTIFY_DONE; + /* ARP filtering is only supported in managed mode */ if (sdata->vif.type != NL80211_IFTYPE_STATION) return NOTIFY_DONE; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ef686d3b04e3..d38b3767e8cc 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1308,7 +1308,7 @@ void ieee80211_recalc_smps(struct ieee80211_local *local, */ list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type != NL80211_IFTYPE_STATION) goto set; -- cgit v1.2.3-59-g8ed1b From bf533e0bfd77d9671adabdf134b1ac7f24bb0670 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 12:35:56 +0200 Subject: mac80211: simplify zero address checks The libertas_tf special code for zero addresses is a bit too complex, it compares against a stack value instead of using is_zero_ether_addr() and tries to update all interfaces even if just the one that's being brought up needs to be changed. Additionally, the repeated check for a valid MAC address need only be done if we actually changed it on the fly. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/iface.c | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index cc1c68d7dda6..ea50732ec526 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -103,10 +103,9 @@ static int ieee80211_open(struct net_device *dev) u32 changed = 0; int res; u32 hw_reconf_flags = 0; - u8 null_addr[ETH_ALEN] = {0}; /* fail early if user set an invalid address */ - if (compare_ether_addr(dev->dev_addr, null_addr) && + if (!is_zero_ether_addr(dev->dev_addr) && !is_valid_ether_addr(dev->dev_addr)) return -EADDRNOTAVAIL; @@ -195,33 +194,22 @@ static int ieee80211_open(struct net_device *dev) } /* - * Check all interfaces and copy the hopefully now-present - * MAC address to those that have the special null one. + * Copy the hopefully now-present MAC address to + * this interface, if it has the special null one. */ - list_for_each_entry(nsdata, &local->interfaces, list) { - struct net_device *ndev = nsdata->dev; - - /* - * No need to check running since we do not allow - * it to start up with this invalid address. - */ - if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) { - memcpy(ndev->dev_addr, - local->hw.wiphy->perm_addr, - ETH_ALEN); - memcpy(ndev->perm_addr, ndev->dev_addr, ETH_ALEN); + if (is_zero_ether_addr(dev->dev_addr)) { + memcpy(dev->dev_addr, + local->hw.wiphy->perm_addr, + ETH_ALEN); + memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN); + + if (!is_valid_ether_addr(dev->dev_addr)) { + if (!local->open_count) + drv_stop(local); + return -EADDRNOTAVAIL; } } - /* - * Validate the MAC address for this device. - */ - if (!is_valid_ether_addr(dev->dev_addr)) { - if (!local->open_count) - drv_stop(local); - return -EADDRNOTAVAIL; - } - switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: /* no need to tell driver */ -- cgit v1.2.3-59-g8ed1b From 87490f6db38999fee7f6d3dbecc5b94730c7e010 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 12:35:57 +0200 Subject: mac80211: split out concurrent vif checks Split the concurrent virtual interface checks into a new function that can be used to check for any given new interface type. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/iface.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ea50732ec526..cba3d806d722 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -94,20 +94,14 @@ static inline int identical_mac_addr_allowed(int type1, int type2) type2 == NL80211_IFTYPE_AP_VLAN)); } -static int ieee80211_open(struct net_device *dev) +static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, + enum nl80211_iftype iftype) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_sub_if_data *nsdata; struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - u32 changed = 0; - int res; - u32 hw_reconf_flags = 0; + struct ieee80211_sub_if_data *nsdata; + struct net_device *dev = sdata->dev; - /* fail early if user set an invalid address */ - if (!is_zero_ether_addr(dev->dev_addr) && - !is_valid_ether_addr(dev->dev_addr)) - return -EADDRNOTAVAIL; + ASSERT_RTNL(); /* we hold the RTNL here so can safely walk the list */ list_for_each_entry(nsdata, &local->interfaces, list) { @@ -124,7 +118,7 @@ static int ieee80211_open(struct net_device *dev) * belonging to the same hardware. Then, however, we're * faced with having to adopt two different TSF timers... */ - if (sdata->vif.type == NL80211_IFTYPE_ADHOC && + if (iftype == NL80211_IFTYPE_ADHOC && nsdata->vif.type == NL80211_IFTYPE_ADHOC) return -EBUSY; @@ -138,19 +132,40 @@ static int ieee80211_open(struct net_device *dev) /* * check whether it may have the same address */ - if (!identical_mac_addr_allowed(sdata->vif.type, + if (!identical_mac_addr_allowed(iftype, nsdata->vif.type)) return -ENOTUNIQ; /* * can only add VLANs to enabled APs */ - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + if (iftype == NL80211_IFTYPE_AP_VLAN && nsdata->vif.type == NL80211_IFTYPE_AP) sdata->bss = &nsdata->u.ap; } } + return 0; +} + +static int ieee80211_open(struct net_device *dev) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; + struct sta_info *sta; + u32 changed = 0; + int res; + u32 hw_reconf_flags = 0; + + /* fail early if user set an invalid address */ + if (!is_zero_ether_addr(dev->dev_addr) && + !is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; + + res = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); + if (res) + return res; + switch (sdata->vif.type) { case NL80211_IFTYPE_WDS: if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) -- cgit v1.2.3-59-g8ed1b From 34d4bc4d41d282a66dafe1b01a7d46bad468cefb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 12:35:58 +0200 Subject: mac80211: support runtime interface type changes Add support to mac80211 for changing the interface type even when the interface is UP, if the driver supports it. To achieve this * add a new driver callback for switching, * split some of the interface up/down code out into new functions (do_open/do_stop), and * maintain an own __SDATA_RUNNING bit that will not be set during interface type, so that any other code doesn't use the interface. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 9 +++ net/mac80211/cfg.c | 3 - net/mac80211/driver-ops.h | 14 ++++ net/mac80211/driver-trace.h | 25 +++++++ net/mac80211/ieee80211_i.h | 14 +++- net/mac80211/iface.c | 157 ++++++++++++++++++++++++++++++++++---------- 6 files changed, 185 insertions(+), 37 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 8f97548b6d80..f91fc331369b 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1537,6 +1537,12 @@ enum ieee80211_ampdu_mlme_action { * negative error code (which will be seen in userspace.) * Must be implemented and can sleep. * + * @change_interface: Called when a netdevice changes type. This callback + * is optional, but only if it is supported can interface types be + * switched while the interface is UP. The callback may sleep. + * Note that while an interface is being switched, it will not be + * found by the interface iteration callbacks. + * * @remove_interface: Notifies a driver that an interface is going down. * The @stop callback is called after this if it is the last interface * and no monitor interfaces are present. @@ -1693,6 +1699,9 @@ struct ieee80211_ops { void (*stop)(struct ieee80211_hw *hw); int (*add_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); + int (*change_interface)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum nl80211_iftype new_type); void (*remove_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int (*config)(struct ieee80211_hw *hw, u32 changed); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f82b18e996b2..5de1ca3f17b9 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -52,9 +52,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); int ret; - if (ieee80211_sdata_running(sdata)) - return -EBUSY; - ret = ieee80211_if_change_type(sdata, type); if (ret) return ret; diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 14123dce544b..6064b7b09e01 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -54,6 +54,20 @@ static inline int drv_add_interface(struct ieee80211_local *local, return ret; } +static inline int drv_change_interface(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + enum nl80211_iftype type) +{ + int ret; + + might_sleep(); + + trace_drv_change_interface(local, sdata, type); + ret = local->ops->change_interface(&local->hw, &sdata->vif, type); + trace_drv_return_int(local, ret); + return ret; +} + static inline void drv_remove_interface(struct ieee80211_local *local, struct ieee80211_vif *vif) { diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index b5a95582d816..f6f3d89e43fa 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -136,6 +136,31 @@ TRACE_EVENT(drv_add_interface, ) ); +TRACE_EVENT(drv_change_interface, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + enum nl80211_iftype type), + + TP_ARGS(local, sdata, type), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + __field(u32, new_type) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + __entry->new_type = type; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT " new type:%d", + LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type + ) +); + TRACE_EVENT(drv_remove_interface, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f64837788681..d529bd5eab47 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -472,6 +472,16 @@ enum ieee80211_sub_if_data_flags { IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), }; +/** + * enum ieee80211_sdata_state_bits - virtual interface state bits + * @SDATA_STATE_RUNNING: virtual interface is up & running; this + * mirrors netif_running() but is separate for interface type + * change handling while the interface is up + */ +enum ieee80211_sdata_state_bits { + SDATA_STATE_RUNNING, +}; + struct ieee80211_sub_if_data { struct list_head list; @@ -485,6 +495,8 @@ struct ieee80211_sub_if_data { unsigned int flags; + unsigned long state; + int drop_unencrypted; char name[IFNAMSIZ]; @@ -1087,7 +1099,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local); static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) { - return netif_running(sdata->dev); + return test_bit(SDATA_STATE_RUNNING, &sdata->state); } /* tx handling */ diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index cba3d806d722..c1cc200ac81f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -148,7 +148,12 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, return 0; } -static int ieee80211_open(struct net_device *dev) +/* + * NOTE: Be very careful when changing this function, it must NOT return + * an error on interface type changes that have been pre-checked, so most + * checks should be in ieee80211_check_concurrent_iface. + */ +static int ieee80211_do_open(struct net_device *dev, bool coming_up) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; @@ -157,15 +162,6 @@ static int ieee80211_open(struct net_device *dev) int res; u32 hw_reconf_flags = 0; - /* fail early if user set an invalid address */ - if (!is_zero_ether_addr(dev->dev_addr) && - !is_valid_ether_addr(dev->dev_addr)) - return -EADDRNOTAVAIL; - - res = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); - if (res) - return res; - switch (sdata->vif.type) { case NL80211_IFTYPE_WDS: if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) @@ -258,9 +254,11 @@ static int ieee80211_open(struct net_device *dev) netif_carrier_on(dev); break; default: - res = drv_add_interface(local, &sdata->vif); - if (res) - goto err_stop; + if (coming_up) { + res = drv_add_interface(local, &sdata->vif); + if (res) + goto err_stop; + } if (ieee80211_vif_is_mesh(&sdata->vif)) { local->fif_other_bss++; @@ -316,7 +314,9 @@ static int ieee80211_open(struct net_device *dev) hw_reconf_flags |= __ieee80211_recalc_idle(local); mutex_unlock(&local->mtx); - local->open_count++; + if (coming_up) + local->open_count++; + if (hw_reconf_flags) { ieee80211_hw_config(local, hw_reconf_flags); /* @@ -331,6 +331,8 @@ static int ieee80211_open(struct net_device *dev) netif_tx_start_all_queues(dev); + set_bit(SDATA_STATE_RUNNING, &sdata->state); + return 0; err_del_interface: drv_remove_interface(local, &sdata->vif); @@ -344,19 +346,38 @@ static int ieee80211_open(struct net_device *dev) return res; } -static int ieee80211_stop(struct net_device *dev) +static int ieee80211_open(struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + int err; + + /* fail early if user set an invalid address */ + if (!is_zero_ether_addr(dev->dev_addr) && + !is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; + + err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); + if (err) + return err; + + return ieee80211_do_open(dev, true); +} + +static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, + bool going_down) +{ struct ieee80211_local *local = sdata->local; unsigned long flags; struct sk_buff *skb, *tmp; u32 hw_reconf_flags = 0; int i; + clear_bit(SDATA_STATE_RUNNING, &sdata->state); + /* * Stop TX on this interface first. */ - netif_tx_stop_all_queues(dev); + netif_tx_stop_all_queues(sdata->dev); /* * Purge work for this interface. @@ -394,11 +415,12 @@ static int ieee80211_stop(struct net_device *dev) if (sdata->vif.type == NL80211_IFTYPE_AP) local->fif_pspoll--; - netif_addr_lock_bh(dev); + netif_addr_lock_bh(sdata->dev); spin_lock_bh(&local->filter_lock); - __hw_addr_unsync(&local->mc_list, &dev->mc, dev->addr_len); + __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, + sdata->dev->addr_len); spin_unlock_bh(&local->filter_lock); - netif_addr_unlock_bh(dev); + netif_addr_unlock_bh(sdata->dev); ieee80211_configure_filter(local); @@ -432,7 +454,8 @@ static int ieee80211_stop(struct net_device *dev) WARN_ON(!list_empty(&sdata->u.ap.vlans)); } - local->open_count--; + if (going_down) + local->open_count--; switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: @@ -504,7 +527,8 @@ static int ieee80211_stop(struct net_device *dev) */ ieee80211_free_keys(sdata); - drv_remove_interface(local, &sdata->vif); + if (going_down) + drv_remove_interface(local, &sdata->vif); } sdata->bss = NULL; @@ -540,6 +564,13 @@ static int ieee80211_stop(struct net_device *dev) } } spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); +} + +static int ieee80211_stop(struct net_device *dev) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + ieee80211_do_stop(sdata, true); return 0; } @@ -857,9 +888,72 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, ieee80211_debugfs_add_netdev(sdata); } +static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, + enum nl80211_iftype type) +{ + struct ieee80211_local *local = sdata->local; + int ret, err; + + ASSERT_RTNL(); + + if (!local->ops->change_interface) + return -EBUSY; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + /* + * Could maybe also all others here? + * Just not sure how that interacts + * with the RX/config path e.g. for + * mesh. + */ + break; + default: + return -EBUSY; + } + + switch (type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + /* + * Could probably support everything + * but WDS here (WDS do_open can fail + * under memory pressure, which this + * code isn't prepared to handle). + */ + break; + default: + return -EBUSY; + } + + ret = ieee80211_check_concurrent_iface(sdata, type); + if (ret) + return ret; + + ieee80211_do_stop(sdata, false); + + ieee80211_teardown_sdata(sdata->dev); + + ret = drv_change_interface(local, sdata, type); + if (ret) + type = sdata->vif.type; + + ieee80211_setup_sdata(sdata, type); + + err = ieee80211_do_open(sdata->dev, false); + WARN(err, "type change: do_open returned %d", err); + + return ret; +} + int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, enum nl80211_iftype type) { + int ret; + ASSERT_RTNL(); if (type == sdata->vif.type) @@ -870,18 +964,15 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, type == NL80211_IFTYPE_ADHOC) return -EOPNOTSUPP; - /* - * We could, here, on changes between IBSS/STA/MESH modes, - * invoke an MLME function instead that disassociates etc. - * and goes into the requested mode. - */ - - if (ieee80211_sdata_running(sdata)) - return -EBUSY; - - /* Purge and reset type-dependent state. */ - ieee80211_teardown_sdata(sdata->dev); - ieee80211_setup_sdata(sdata, type); + if (ieee80211_sdata_running(sdata)) { + ret = ieee80211_runtime_change_iftype(sdata, type); + if (ret) + return ret; + } else { + /* Purge and reset type-dependent state. */ + ieee80211_teardown_sdata(sdata->dev); + ieee80211_setup_sdata(sdata, type); + } /* reset some values that shouldn't be kept across type changes */ sdata->vif.bss_conf.basic_rates = -- cgit v1.2.3-59-g8ed1b From c35d02705e9c2db90a89b29142046b4ffd5a76e5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 12:35:59 +0200 Subject: mac80211_hwsim: support runtime iftype changes Add the trivial support for runtime interface type changes to mac80211_hwsim for testing. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 298ba79fc51b..92b486d46eb9 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -601,6 +601,18 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, } +static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum nl80211_iftype newtype) +{ + wiphy_debug(hw->wiphy, + "%s (old type=%d, new type=%d, mac_addr=%pM)\n", + __func__, vif->type, newtype, vif->addr); + hwsim_check_magic(vif); + + return 0; +} + static void mac80211_hwsim_remove_interface( struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -1027,6 +1039,7 @@ static struct ieee80211_ops mac80211_hwsim_ops = .start = mac80211_hwsim_start, .stop = mac80211_hwsim_stop, .add_interface = mac80211_hwsim_add_interface, + .change_interface = mac80211_hwsim_change_interface, .remove_interface = mac80211_hwsim_remove_interface, .config = mac80211_hwsim_config, .configure_filter = mac80211_hwsim_configure_filter, -- cgit v1.2.3-59-g8ed1b From 5b714c6a3753dad0798a70a049e15c7f6bc9446b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Aug 2010 13:45:28 +0200 Subject: mac80211: fix offchannel queue stop Somebody noticed this problem, and I outlined to them how to fix it, but haven't heard back from them. So while I was adding the state field I figured I could use it to fix it. The problem, as I understand it, is that when we go offchannel while the driver has a queue stopped, the driver will likely start draining the queue and then enable it while offchannel. This in turn will enable the interface queue, and that leads to transmitting data frames on the wrong channel. Fix this by keeping track of offchannel status per interface, and not enabling the interface queues on interfaces that are offchannel when the driver enables a queue. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 3 +++ net/mac80211/offchannel.c | 19 +++++++++++++++++-- net/mac80211/util.c | 5 ++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d529bd5eab47..9af50fbcd48b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -477,9 +477,12 @@ enum ieee80211_sub_if_data_flags { * @SDATA_STATE_RUNNING: virtual interface is up & running; this * mirrors netif_running() but is separate for interface type * change handling while the interface is up + * @SDATA_STATE_OFFCHANNEL: This interface is currently in offchannel + * mode, so queues are stopped */ enum ieee80211_sdata_state_bits { SDATA_STATE_RUNNING, + SDATA_STATE_OFFCHANNEL, }; struct ieee80211_sub_if_data { diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index c36b1911987a..eeacaa59380a 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -112,8 +112,10 @@ void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) * used from user space controlled off-channel operations. */ if (sdata->vif.type != NL80211_IFTYPE_STATION && - sdata->vif.type != NL80211_IFTYPE_MONITOR) + sdata->vif.type != NL80211_IFTYPE_MONITOR) { + set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); netif_tx_stop_all_queues(sdata->dev); + } } mutex_unlock(&local->iflist_mtx); } @@ -131,6 +133,7 @@ void ieee80211_offchannel_stop_station(struct ieee80211_local *local) continue; if (sdata->vif.type == NL80211_IFTYPE_STATION) { + set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); netif_tx_stop_all_queues(sdata->dev); if (sdata->u.mgd.associated) ieee80211_offchannel_ps_enable(sdata); @@ -155,8 +158,20 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, ieee80211_offchannel_ps_disable(sdata); } - if (sdata->vif.type != NL80211_IFTYPE_MONITOR) + if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { + clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); + /* + * This may wake up queues even though the driver + * currently has them stopped. This is not very + * likely, since the driver won't have gotten any + * (or hardly any) new packets while we weren't + * on the right channel, and even if it happens + * it will at most lead to queueing up one more + * packet per queue in mac80211 rather than on + * the interface qdisc. + */ netif_tx_wake_all_queues(sdata->dev); + } /* re-enable beaconing */ if (enable_beaconing && diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d38b3767e8cc..bd40b11d5ab9 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -283,8 +283,11 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, if (skb_queue_empty(&local->pending[queue])) { rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) + continue; netif_wake_subqueue(sdata->dev, queue); + } rcu_read_unlock(); } else tasklet_schedule(&local->tx_pending_tasklet); -- cgit v1.2.3-59-g8ed1b From 034de00b06fe2b2c451f7435414f15c1b625e6b0 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 26 Aug 2010 22:12:08 +0000 Subject: slip: Use net_device_stats from struct net_device Use net_device->stats for stats instead of private variable copies in struct slip. Use ndo_get_stat64 so the additions can be performed on a private destination buffer. Cc: Eric Dumazet Signed-off-by: Tobias Klauser Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/slip.c | 61 +++++++++++++++++++++++++++--------------------------- drivers/net/slip.h | 9 -------- 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/drivers/net/slip.c b/drivers/net/slip.c index d5a36f5417cc..38547a8938fe 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -271,7 +271,7 @@ static int sl_realloc_bufs(struct slip *sl, int mtu) memcpy(sl->xbuff, sl->xhead, sl->xleft); } else { sl->xleft = 0; - sl->tx_dropped++; + dev->stats.tx_dropped++; } } sl->xhead = sl->xbuff; @@ -281,7 +281,7 @@ static int sl_realloc_bufs(struct slip *sl, int mtu) memcpy(sl->rbuff, rbuff, sl->rcount); } else { sl->rcount = 0; - sl->rx_over_errors++; + dev->stats.rx_over_errors++; set_bit(SLF_ERROR, &sl->flags); } } @@ -319,6 +319,7 @@ static inline void sl_unlock(struct slip *sl) /* Send one completely decapsulated IP datagram to the IP layer. */ static void sl_bump(struct slip *sl) { + struct net_device *dev = sl->dev; struct sk_buff *skb; int count; @@ -329,13 +330,13 @@ static void sl_bump(struct slip *sl) if (c & SL_TYPE_COMPRESSED_TCP) { /* ignore compressed packets when CSLIP is off */ if (!(sl->mode & SL_MODE_CSLIP)) { - printk(KERN_WARNING "%s: compressed packet ignored\n", sl->dev->name); + printk(KERN_WARNING "%s: compressed packet ignored\n", dev->name); return; } /* make sure we've reserved enough space for uncompress to use */ if (count + 80 > sl->buffsize) { - sl->rx_over_errors++; + dev->stats.rx_over_errors++; return; } count = slhc_uncompress(sl->slcomp, sl->rbuff, count); @@ -346,7 +347,7 @@ static void sl_bump(struct slip *sl) /* turn on header compression */ sl->mode |= SL_MODE_CSLIP; sl->mode &= ~SL_MODE_ADAPTIVE; - printk(KERN_INFO "%s: header compression turned on\n", sl->dev->name); + printk(KERN_INFO "%s: header compression turned on\n", dev->name); } sl->rbuff[0] &= 0x4f; if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0) @@ -355,20 +356,20 @@ static void sl_bump(struct slip *sl) } #endif /* SL_INCLUDE_CSLIP */ - sl->rx_bytes += count; + dev->stats.rx_bytes += count; skb = dev_alloc_skb(count); if (skb == NULL) { - printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", sl->dev->name); - sl->rx_dropped++; + printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name); + dev->stats.rx_dropped++; return; } - skb->dev = sl->dev; + skb->dev = dev; memcpy(skb_put(skb, count), sl->rbuff, count); skb_reset_mac_header(skb); skb->protocol = htons(ETH_P_IP); netif_rx(skb); - sl->rx_packets++; + dev->stats.rx_packets++; } /* Encapsulate one IP datagram and stuff into a TTY queue. */ @@ -379,7 +380,7 @@ static void sl_encaps(struct slip *sl, unsigned char *icp, int len) if (len > sl->mtu) { /* Sigh, shouldn't occur BUT ... */ printk(KERN_WARNING "%s: truncating oversized transmit packet!\n", sl->dev->name); - sl->tx_dropped++; + sl->dev->stats.tx_dropped++; sl_unlock(sl); return; } @@ -433,7 +434,7 @@ static void slip_write_wakeup(struct tty_struct *tty) if (sl->xleft <= 0) { /* Now serial buffer is almost free & we can start * transmission of another packet */ - sl->tx_packets++; + sl->dev->stats.tx_packets++; clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); sl_unlock(sl); return; @@ -496,7 +497,7 @@ sl_xmit(struct sk_buff *skb, struct net_device *dev) } sl_lock(sl); - sl->tx_bytes += skb->len; + dev->stats.tx_bytes += skb->len; sl_encaps(sl, skb->data, skb->len); spin_unlock(&sl->lock); @@ -558,16 +559,16 @@ static int sl_change_mtu(struct net_device *dev, int new_mtu) /* Netdevice get statistics request */ -static struct net_device_stats * -sl_get_stats(struct net_device *dev) +static struct rtnl_link_stats64 * +sl_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { - struct net_device_stats *stats = &dev->stats; - struct slip *sl = netdev_priv(dev); + struct net_device_stats *devstats = &dev->stats; unsigned long c_rx_dropped = 0; #ifdef SL_INCLUDE_CSLIP unsigned long c_rx_fifo_errors = 0; unsigned long c_tx_fifo_errors = 0; unsigned long c_collisions = 0; + struct slip *sl = netdev_priv(dev); struct slcompress *comp = sl->slcomp; if (comp) { @@ -580,16 +581,16 @@ sl_get_stats(struct net_device *dev) stats->tx_fifo_errors = sl->tx_compressed + c_tx_fifo_errors; stats->collisions = sl->tx_misses + c_collisions; #endif + stats->rx_packets = devstats->rx_packets; + stats->tx_packets = devstats->tx_packets; + stats->rx_bytes = devstats->rx_bytes; + stats->tx_bytes = devstats->tx_bytes; + stats->rx_dropped = devstats->rx_dropped + c_rx_dropped; + stats->tx_dropped = devstats->tx_dropped; + stats->tx_errors = devstats->tx_errors; + stats->rx_errors = devstats->rx_errors; + stats->rx_over_errors = devstats->rx_over_errors; - stats->rx_packets = sl->rx_packets; - stats->tx_packets = sl->tx_packets; - stats->rx_bytes = sl->rx_bytes; - stats->tx_bytes = sl->tx_bytes; - stats->rx_dropped = sl->rx_dropped + c_rx_dropped; - stats->tx_dropped = sl->tx_dropped; - stats->tx_errors = sl->tx_errors; - stats->rx_errors = sl->rx_errors; - stats->rx_over_errors = sl->rx_over_errors; return stats; } @@ -633,7 +634,7 @@ static const struct net_device_ops sl_netdev_ops = { .ndo_open = sl_open, .ndo_stop = sl_close, .ndo_start_xmit = sl_xmit, - .ndo_get_stats = sl_get_stats, + .ndo_get_stats64 = sl_get_stats64, .ndo_change_mtu = sl_change_mtu, .ndo_tx_timeout = sl_tx_timeout, #ifdef CONFIG_SLIP_SMART @@ -681,7 +682,7 @@ static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, while (count--) { if (fp && *fp++) { if (!test_and_set_bit(SLF_ERROR, &sl->flags)) - sl->rx_errors++; + sl->dev->stats.rx_errors++; cp++; continue; } @@ -981,7 +982,7 @@ static void slip_unesc(struct slip *sl, unsigned char s) sl->rbuff[sl->rcount++] = s; return; } - sl->rx_over_errors++; + sl->dev->stats.rx_over_errors++; set_bit(SLF_ERROR, &sl->flags); } } @@ -1057,7 +1058,7 @@ static void slip_unesc6(struct slip *sl, unsigned char s) sl->rbuff[sl->rcount++] = c; return; } - sl->rx_over_errors++; + sl->dev->stats.rx_over_errors++; set_bit(SLF_ERROR, &sl->flags); } } diff --git a/drivers/net/slip.h b/drivers/net/slip.h index 9ea5c11287d2..914e958abbfc 100644 --- a/drivers/net/slip.h +++ b/drivers/net/slip.h @@ -67,15 +67,6 @@ struct slip { int xleft; /* bytes left in XMIT queue */ /* SLIP interface statistics. */ - unsigned long rx_packets; /* inbound frames counter */ - unsigned long tx_packets; /* outbound frames counter */ - unsigned long rx_bytes; /* inbound byte counte */ - unsigned long tx_bytes; /* outbound byte counter */ - unsigned long rx_errors; /* Parity, etc. errors */ - unsigned long tx_errors; /* Planned stuff */ - unsigned long rx_dropped; /* No memory for skb */ - unsigned long tx_dropped; /* When MTU change */ - unsigned long rx_over_errors; /* Frame bigger than SLIP buf. */ #ifdef SL_INCLUDE_CSLIP unsigned long tx_compressed; unsigned long rx_compressed; -- cgit v1.2.3-59-g8ed1b From 3fe4a5ee9c312b7652cc92715ee30d3760b83e5b Mon Sep 17 00:00:00 2001 From: Ian Lartey Date: Fri, 27 Aug 2010 15:26:27 +0100 Subject: ASoC: Complete supported clock ratios and rate constraints for wm8741 Signed-off-by: Ian Lartey Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/wm8741.c | 175 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 124 insertions(+), 51 deletions(-) diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index fdd24da89a1e..c8e7a264bbae 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -36,7 +36,7 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { "DVDD", }; -#define WM8741_NUM_RATES 4 +#define WM8741_NUM_RATES 6 /* codec private data */ struct wm8741_priv { @@ -44,8 +44,7 @@ struct wm8741_priv { u16 reg_cache[WM8741_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; - unsigned int rate_constraint_list[WM8741_NUM_RATES]; - struct snd_pcm_hw_constraint_list rate_constraint; + struct snd_pcm_hw_constraint_list *sysclk_constraints; }; static const u16 wm8741_reg_defaults[WM8741_REGISTER_COUNT] = { @@ -108,10 +107,84 @@ static struct { int value; int ratio; } lrclk_ratios[WM8741_NUM_RATES] = { - { 1, 256 }, - { 2, 384 }, - { 3, 512 }, - { 4, 768 }, + { 1, 128 }, + { 2, 192 }, + { 3, 256 }, + { 4, 384 }, + { 5, 512 }, + { 6, 768 }, +}; + +static unsigned int rates_11289[] = { + 44100, 88235, +}; + +static struct snd_pcm_hw_constraint_list constraints_11289 = { + .count = ARRAY_SIZE(rates_11289), + .list = rates_11289, +}; + +static unsigned int rates_12288[] = { + 32000, 48000, 96000, +}; + +static struct snd_pcm_hw_constraint_list constraints_12288 = { + .count = ARRAY_SIZE(rates_12288), + .list = rates_12288, +}; + +static unsigned int rates_16384[] = { + 32000, +}; + +static struct snd_pcm_hw_constraint_list constraints_16384 = { + .count = ARRAY_SIZE(rates_16384), + .list = rates_16384, +}; + +static unsigned int rates_16934[] = { + 44100, 88235, +}; + +static struct snd_pcm_hw_constraint_list constraints_16934 = { + .count = ARRAY_SIZE(rates_16934), + .list = rates_16934, +}; + +static unsigned int rates_18432[] = { + 48000, 96000, +}; + +static struct snd_pcm_hw_constraint_list constraints_18432 = { + .count = ARRAY_SIZE(rates_18432), + .list = rates_18432, +}; + +static unsigned int rates_22579[] = { + 44100, 88235, 1764000 +}; + +static struct snd_pcm_hw_constraint_list constraints_22579 = { + .count = ARRAY_SIZE(rates_22579), + .list = rates_22579, +}; + +static unsigned int rates_24576[] = { + 32000, 48000, 96000, 192000 +}; + +static struct snd_pcm_hw_constraint_list constraints_24576 = { + .count = ARRAY_SIZE(rates_24576), + .list = rates_24576, +}; + +static unsigned int rates_36864[] = { + 48000, 96000, 19200 +}; + +static struct snd_pcm_hw_constraint_list constraints_36864 = { + .count = ARRAY_SIZE(rates_36864), + .list = rates_36864, }; @@ -132,7 +205,7 @@ static int wm8741_startup(struct snd_pcm_substream *substream, snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &wm8741->rate_constraint); + wm8741->sysclk_constraints); return 0; } @@ -192,47 +265,52 @@ static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); - unsigned int val; - int i; dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq); - wm8741->sysclk = freq; - - wm8741->rate_constraint.count = 0; - - for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { - dev_dbg(codec->dev, "index = %d, ratio = %d, freq = %d", - i, lrclk_ratios[i].ratio, freq); - - val = freq / lrclk_ratios[i].ratio; - /* Check that it's a standard rate since core can't - * cope with others and having the odd rates confuses - * constraint matching. - */ - switch (val) { - case 32000: - case 44100: - case 48000: - case 64000: - case 88200: - case 96000: - dev_dbg(codec->dev, "Supported sample rate: %dHz\n", - val); - wm8741->rate_constraint_list[i] = val; - wm8741->rate_constraint.count++; - break; - default: - dev_dbg(codec->dev, "Skipping sample rate: %dHz\n", - val); - } + switch (freq) { + case 11289600: + wm8741->sysclk_constraints = &constraints_11289; + wm8741->sysclk = freq; + return 0; + + case 12288000: + wm8741->sysclk_constraints = &constraints_12288; + wm8741->sysclk = freq; + return 0; + + case 16384000: + wm8741->sysclk_constraints = &constraints_16384; + wm8741->sysclk = freq; + return 0; + + case 16934400: + wm8741->sysclk_constraints = &constraints_16934; + wm8741->sysclk = freq; + return 0; + + case 18432000: + wm8741->sysclk_constraints = &constraints_18432; + wm8741->sysclk = freq; + return 0; + + case 22579200: + case 33868800: + wm8741->sysclk_constraints = &constraints_22579; + wm8741->sysclk = freq; + return 0; + + case 24576000: + wm8741->sysclk_constraints = &constraints_24576; + wm8741->sysclk = freq; + return 0; + + case 36864000: + wm8741->sysclk_constraints = &constraints_36864; + wm8741->sysclk = freq; + return 0; } - - /* Need at least one supported rate... */ - if (wm8741->rate_constraint.count == 0) - return -EINVAL; - - return 0; + return -EINVAL; } static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai, @@ -391,10 +469,6 @@ static int wm8741_i2c_probe(struct i2c_client *i2c, if (wm8741 == NULL) return -ENOMEM; - wm8741->rate_constraint.list = &wm8741->rate_constraint_list[0]; - wm8741->rate_constraint.count = - ARRAY_SIZE(wm8741->rate_constraint_list); - for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) wm8741->supplies[i].supply = wm8741_supply_names[i]; @@ -464,9 +538,8 @@ static int __init wm8741_modinit(void) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8741_i2c_driver); - if (ret != 0) { + if (ret != 0) pr_err("Failed to register WM8741 I2C driver: %d\n", ret); - } #endif return ret; -- cgit v1.2.3-59-g8ed1b From 0bb5f267af41c39af895faee3abe2d9ab8c562e0 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 24 Aug 2010 15:09:41 +0200 Subject: ASoC: ad1980: remove unneeded function declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/ad1980.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 81a444049936..2b9331a59c71 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -33,11 +33,6 @@ #include "ad1980.h" -static unsigned int ac97_read(struct snd_soc_codec *codec, - unsigned int reg); -static int ac97_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int val); - /* * AD1980 register cache */ -- cgit v1.2.3-59-g8ed1b From f9bc02974d931cb424cd1979526ce9c208122bd2 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 27 Aug 2010 16:56:47 +0300 Subject: ASoC: tlv320aic3x: Fix remaining output pin switch names Bit 3 in output pin_CTRL register mutes the whole output pin not just the route from DAC so remove misleading DAC from control name. Currently only "Line[L | R] Playback Switch" were correct. Signed-off-by: Jarkko Nikula Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/tlv320aic3x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index efae8b53fd64..6e4ed79d5eb9 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -314,7 +314,7 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { SOC_DOUBLE_R_TLV("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE("Mono DAC Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), + SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), SOC_DOUBLE_R_TLV("Mono PGA Bypass Playback Volume", PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL, 0, 118, 1, output_stage_tlv), @@ -325,7 +325,7 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { SOC_DOUBLE_R_TLV("HP DAC Playback Volume", DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, + SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, 0x01, 0), SOC_DOUBLE_R_TLV("HP Right PGA Bypass Playback Volume", PGAR_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL, @@ -341,7 +341,7 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { SOC_DOUBLE_R_TLV("HPCOM DAC Playback Volume", DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, + SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, 0x01, 0), SOC_SINGLE_TLV("HPLCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), -- cgit v1.2.3-59-g8ed1b From b2eaac203a04362e9ccae7ba36aef0a9f2486547 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 27 Aug 2010 16:56:48 +0300 Subject: ASoC: tlv320aic3x: Sort output pin control registers in header file Each output pin has 7 consecutive control registers in tlv320aic3x register map. First 6 of them control the signal mixing and one is for output level and power control. Sort these registers as they are sorted clearly in hardware, it makes also definitions more readable and easier to pinpoint missing register definitions. Signed-off-by: Jarkko Nikula Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/tlv320aic3x.h | 47 ++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 98e44395b662..20d8cac2637c 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -81,52 +81,55 @@ /* DAC Digital control registers */ #define LDAC_VOL 43 #define RDAC_VOL 44 -/* High Power Output control registers */ +/* Left High Power Output control registers */ #define LINE2L_2_HPLOUT_VOL 45 -#define LINE2R_2_HPROUT_VOL 62 #define PGAL_2_HPLOUT_VOL 46 -#define PGAL_2_HPROUT_VOL 60 -#define PGAR_2_HPLOUT_VOL 49 -#define PGAR_2_HPROUT_VOL 63 #define DACL1_2_HPLOUT_VOL 47 -#define DACR1_2_HPROUT_VOL 64 +#define PGAR_2_HPLOUT_VOL 49 #define HPLOUT_CTRL 51 -#define HPROUT_CTRL 65 -/* High Power COM control registers */ +/* Left High Power COM control registers */ #define LINE2L_2_HPLCOM_VOL 52 -#define LINE2R_2_HPRCOM_VOL 69 #define PGAL_2_HPLCOM_VOL 53 +#define DACL1_2_HPLCOM_VOL 54 #define PGAR_2_HPLCOM_VOL 56 +#define HPLCOM_CTRL 58 +/* Right High Power Output control registers */ +#define PGAL_2_HPROUT_VOL 60 +#define LINE2R_2_HPROUT_VOL 62 +#define PGAR_2_HPROUT_VOL 63 +#define DACR1_2_HPROUT_VOL 64 +#define HPROUT_CTRL 65 +/* Right High Power COM control registers */ #define PGAL_2_HPRCOM_VOL 67 +#define LINE2R_2_HPRCOM_VOL 69 #define PGAR_2_HPRCOM_VOL 70 -#define DACL1_2_HPLCOM_VOL 54 #define DACR1_2_HPRCOM_VOL 71 -#define HPLCOM_CTRL 58 #define HPRCOM_CTRL 72 /* Mono Line Output Plus/Minus control registers */ #define LINE2L_2_MONOLOPM_VOL 73 -#define LINE2R_2_MONOLOPM_VOL 76 #define PGAL_2_MONOLOPM_VOL 74 -#define PGAR_2_MONOLOPM_VOL 77 #define DACL1_2_MONOLOPM_VOL 75 +#define LINE2R_2_MONOLOPM_VOL 76 +#define PGAR_2_MONOLOPM_VOL 77 #define DACR1_2_MONOLOPM_VOL 78 #define MONOLOPM_CTRL 79 /* Class-D speaker driver on tlv320aic3007 */ #define CLASSD_CTRL 73 -/* Line Output Plus/Minus control registers */ +/* Left Line Output Plus/Minus control registers */ #define LINE2L_2_LLOPM_VOL 80 -#define LINE2L_2_RLOPM_VOL 87 -#define LINE2R_2_LLOPM_VOL 83 -#define LINE2R_2_RLOPM_VOL 90 #define PGAL_2_LLOPM_VOL 81 -#define PGAL_2_RLOPM_VOL 88 -#define PGAR_2_LLOPM_VOL 84 -#define PGAR_2_RLOPM_VOL 91 #define DACL1_2_LLOPM_VOL 82 -#define DACL1_2_RLOPM_VOL 89 -#define DACR1_2_RLOPM_VOL 92 +#define LINE2R_2_LLOPM_VOL 83 +#define PGAR_2_LLOPM_VOL 84 #define DACR1_2_LLOPM_VOL 85 #define LLOPM_CTRL 86 +/* Right Line Output Plus/Minus control registers */ +#define LINE2L_2_RLOPM_VOL 87 +#define PGAL_2_RLOPM_VOL 88 +#define DACL1_2_RLOPM_VOL 89 +#define LINE2R_2_RLOPM_VOL 90 +#define PGAR_2_RLOPM_VOL 91 +#define DACR1_2_RLOPM_VOL 92 #define RLOPM_CTRL 93 /* GPIO/IRQ registers */ #define AIC3X_STICKY_IRQ_FLAGS_REG 96 -- cgit v1.2.3-59-g8ed1b From c3b79e05b4d9ab2e7c3ba281261ea87ab5b71a92 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 27 Aug 2010 16:56:49 +0300 Subject: ASoC: tlv320aic3x: Reimplement output mixers It turned out that the output mixers and their routes were misdefined: They are not mixing output pins to internal signals but opposite. This has worked for direct left-to-left and right-to-right routes since for those there are complete routes. For swapped left-to-right and right-to-left routes this is not working since there are no routes defined between them. Another consequence is that those misdefined mixers are incorrectly routed to several output pins leading unnecessary pin powerings even if there is no route active to them. Fix these by reimplementing the output mixers and routes as they are in hardware. For completeness add also a few missing links between internal signals and outputs. Signed-off-by: Jarkko Nikula Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/tlv320aic3x.c | 394 +++++++++++++++++++---------------------- sound/soc/codecs/tlv320aic3x.h | 8 + 2 files changed, 195 insertions(+), 207 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 6e4ed79d5eb9..0a3b98c097bb 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -389,22 +389,74 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LHPCOM_ENUM]); static const struct snd_kcontrol_new aic3x_right_hpcom_mux_controls = SOC_DAPM_ENUM("Route", aic3x_enum[RHPCOM_ENUM]); -/* Left DAC_L1 Mixer */ -static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = { - SOC_DAPM_SINGLE("LineL Switch", DACL1_2_LLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("LineR Switch", DACL1_2_RLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Mono Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HP Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPCOM Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0), +/* Left Line Mixer */ +static const struct snd_kcontrol_new aic3x_left_line_mixer_controls[] = { + SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_LLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_LLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_LLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_LLOPM_VOL, 7, 1, 0), }; -/* Right DAC_R1 Mixer */ -static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = { - SOC_DAPM_SINGLE("LineL Switch", DACR1_2_LLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("LineR Switch", DACR1_2_RLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Mono Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HP Switch", DACR1_2_HPROUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPCOM Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0), +/* Right Line Mixer */ +static const struct snd_kcontrol_new aic3x_right_line_mixer_controls[] = { + SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_RLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_RLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_RLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_RLOPM_VOL, 7, 1, 0), +}; + +/* Mono Mixer */ +static const struct snd_kcontrol_new aic3x_mono_mixer_controls[] = { + SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0), +}; + +/* Left HP Mixer */ +static const struct snd_kcontrol_new aic3x_left_hp_mixer_controls[] = { + SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLOUT_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLOUT_VOL, 7, 1, 0), +}; + +/* Right HP Mixer */ +static const struct snd_kcontrol_new aic3x_right_hp_mixer_controls[] = { + SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPROUT_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPROUT_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPROUT_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPROUT_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPROUT_VOL, 7, 1, 0), +}; + +/* Left HPCOM Mixer */ +static const struct snd_kcontrol_new aic3x_left_hpcom_mixer_controls[] = { + SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLCOM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLCOM_VOL, 7, 1, 0), +}; + +/* Right HPCOM Mixer */ +static const struct snd_kcontrol_new aic3x_right_hpcom_mixer_controls[] = { + SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPRCOM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPRCOM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0), + SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0), }; /* Left PGA Mixer */ @@ -441,54 +493,11 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LINE2L_ENUM]); static const struct snd_kcontrol_new aic3x_right_line2_mux_controls = SOC_DAPM_ENUM("Route", aic3x_enum[LINE2R_ENUM]); -/* Left PGA Bypass Mixer */ -static const struct snd_kcontrol_new aic3x_left_pga_bp_mixer_controls[] = { - SOC_DAPM_SINGLE("LineL Switch", PGAL_2_LLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("LineR Switch", PGAL_2_RLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Mono Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPL Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPR Switch", PGAL_2_HPROUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPLCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPRCOM Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0), -}; - -/* Right PGA Bypass Mixer */ -static const struct snd_kcontrol_new aic3x_right_pga_bp_mixer_controls[] = { - SOC_DAPM_SINGLE("LineL Switch", PGAR_2_LLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("LineR Switch", PGAR_2_RLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Mono Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPL Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPR Switch", PGAR_2_HPROUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPLCOM Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPRCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0), -}; - -/* Left Line2 Bypass Mixer */ -static const struct snd_kcontrol_new aic3x_left_line2_bp_mixer_controls[] = { - SOC_DAPM_SINGLE("LineL Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("LineR Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Mono Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HP Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPLCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0), -}; - -/* Right Line2 Bypass Mixer */ -static const struct snd_kcontrol_new aic3x_right_line2_bp_mixer_controls[] = { - SOC_DAPM_SINGLE("LineL Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("LineR Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Mono Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HP Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("HPRCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0), -}; - static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { /* Left DAC to Left Outputs */ SND_SOC_DAPM_DAC("Left DAC", "Left Playback", DAC_PWR, 7, 0), SND_SOC_DAPM_MUX("Left DAC Mux", SND_SOC_NOPM, 0, 0, &aic3x_left_dac_mux_controls), - SND_SOC_DAPM_MIXER("Left DAC_L1 Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_left_dac_mixer_controls[0], - ARRAY_SIZE(aic3x_left_dac_mixer_controls)), SND_SOC_DAPM_MUX("Left HPCOM Mux", SND_SOC_NOPM, 0, 0, &aic3x_left_hpcom_mux_controls), SND_SOC_DAPM_PGA("Left Line Out", LLOPM_CTRL, 0, 0, NULL, 0), @@ -499,9 +508,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { SND_SOC_DAPM_DAC("Right DAC", "Right Playback", DAC_PWR, 6, 0), SND_SOC_DAPM_MUX("Right DAC Mux", SND_SOC_NOPM, 0, 0, &aic3x_right_dac_mux_controls), - SND_SOC_DAPM_MIXER("Right DAC_R1 Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_right_dac_mixer_controls[0], - ARRAY_SIZE(aic3x_right_dac_mixer_controls)), SND_SOC_DAPM_MUX("Right HPCOM Mux", SND_SOC_NOPM, 0, 0, &aic3x_right_hpcom_mux_controls), SND_SOC_DAPM_PGA("Right Line Out", RLOPM_CTRL, 0, 0, NULL, 0), @@ -565,25 +571,28 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias AVDD", MICBIAS_CTRL, 6, 3, 3, 0), - /* Left PGA to Left Output bypass */ - SND_SOC_DAPM_MIXER("Left PGA Bypass Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_left_pga_bp_mixer_controls[0], - ARRAY_SIZE(aic3x_left_pga_bp_mixer_controls)), - - /* Right PGA to Right Output bypass */ - SND_SOC_DAPM_MIXER("Right PGA Bypass Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_right_pga_bp_mixer_controls[0], - ARRAY_SIZE(aic3x_right_pga_bp_mixer_controls)), - - /* Left Line2 to Left Output bypass */ - SND_SOC_DAPM_MIXER("Left Line2 Bypass Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_left_line2_bp_mixer_controls[0], - ARRAY_SIZE(aic3x_left_line2_bp_mixer_controls)), - - /* Right Line2 to Right Output bypass */ - SND_SOC_DAPM_MIXER("Right Line2 Bypass Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_right_line2_bp_mixer_controls[0], - ARRAY_SIZE(aic3x_right_line2_bp_mixer_controls)), + /* Output mixers */ + SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0, + &aic3x_left_line_mixer_controls[0], + ARRAY_SIZE(aic3x_left_line_mixer_controls)), + SND_SOC_DAPM_MIXER("Right Line Mixer", SND_SOC_NOPM, 0, 0, + &aic3x_right_line_mixer_controls[0], + ARRAY_SIZE(aic3x_right_line_mixer_controls)), + SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, + &aic3x_mono_mixer_controls[0], + ARRAY_SIZE(aic3x_mono_mixer_controls)), + SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0, + &aic3x_left_hp_mixer_controls[0], + ARRAY_SIZE(aic3x_left_hp_mixer_controls)), + SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0, + &aic3x_right_hp_mixer_controls[0], + ARRAY_SIZE(aic3x_right_hp_mixer_controls)), + SND_SOC_DAPM_MIXER("Left HPCOM Mixer", SND_SOC_NOPM, 0, 0, + &aic3x_left_hpcom_mixer_controls[0], + ARRAY_SIZE(aic3x_left_hpcom_mixer_controls)), + SND_SOC_DAPM_MIXER("Right HPCOM Mixer", SND_SOC_NOPM, 0, 0, + &aic3x_right_hpcom_mixer_controls[0], + ARRAY_SIZE(aic3x_right_hpcom_mixer_controls)), SND_SOC_DAPM_OUTPUT("LLOUT"), SND_SOC_DAPM_OUTPUT("RLOUT"), @@ -611,66 +620,6 @@ static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = { }; static const struct snd_soc_dapm_route intercon[] = { - /* Left Output */ - {"Left DAC Mux", "DAC_L1", "Left DAC"}, - {"Left DAC Mux", "DAC_L2", "Left DAC"}, - {"Left DAC Mux", "DAC_L3", "Left DAC"}, - - {"Left DAC_L1 Mixer", "LineL Switch", "Left DAC Mux"}, - {"Left DAC_L1 Mixer", "LineR Switch", "Left DAC Mux"}, - {"Left DAC_L1 Mixer", "Mono Switch", "Left DAC Mux"}, - {"Left DAC_L1 Mixer", "HP Switch", "Left DAC Mux"}, - {"Left DAC_L1 Mixer", "HPCOM Switch", "Left DAC Mux"}, - {"Left Line Out", NULL, "Left DAC Mux"}, - {"Left HP Out", NULL, "Left DAC Mux"}, - - {"Left HPCOM Mux", "differential of HPLOUT", "Left DAC_L1 Mixer"}, - {"Left HPCOM Mux", "constant VCM", "Left DAC_L1 Mixer"}, - {"Left HPCOM Mux", "single-ended", "Left DAC_L1 Mixer"}, - - {"Left Line Out", NULL, "Left DAC_L1 Mixer"}, - {"Mono Out", NULL, "Left DAC_L1 Mixer"}, - {"Left HP Out", NULL, "Left DAC_L1 Mixer"}, - {"Left HP Com", NULL, "Left HPCOM Mux"}, - - {"LLOUT", NULL, "Left Line Out"}, - {"LLOUT", NULL, "Left Line Out"}, - {"HPLOUT", NULL, "Left HP Out"}, - {"HPLCOM", NULL, "Left HP Com"}, - - /* Right Output */ - {"Right DAC Mux", "DAC_R1", "Right DAC"}, - {"Right DAC Mux", "DAC_R2", "Right DAC"}, - {"Right DAC Mux", "DAC_R3", "Right DAC"}, - - {"Right DAC_R1 Mixer", "LineL Switch", "Right DAC Mux"}, - {"Right DAC_R1 Mixer", "LineR Switch", "Right DAC Mux"}, - {"Right DAC_R1 Mixer", "Mono Switch", "Right DAC Mux"}, - {"Right DAC_R1 Mixer", "HP Switch", "Right DAC Mux"}, - {"Right DAC_R1 Mixer", "HPCOM Switch", "Right DAC Mux"}, - {"Right Line Out", NULL, "Right DAC Mux"}, - {"Right HP Out", NULL, "Right DAC Mux"}, - - {"Right HPCOM Mux", "differential of HPROUT", "Right DAC_R1 Mixer"}, - {"Right HPCOM Mux", "constant VCM", "Right DAC_R1 Mixer"}, - {"Right HPCOM Mux", "single-ended", "Right DAC_R1 Mixer"}, - {"Right HPCOM Mux", "differential of HPLCOM", "Right DAC_R1 Mixer"}, - {"Right HPCOM Mux", "external feedback", "Right DAC_R1 Mixer"}, - - {"Right Line Out", NULL, "Right DAC_R1 Mixer"}, - {"Mono Out", NULL, "Right DAC_R1 Mixer"}, - {"Right HP Out", NULL, "Right DAC_R1 Mixer"}, - {"Right HP Com", NULL, "Right HPCOM Mux"}, - - {"RLOUT", NULL, "Right Line Out"}, - {"RLOUT", NULL, "Right Line Out"}, - {"HPROUT", NULL, "Right HP Out"}, - {"HPRCOM", NULL, "Right HP Com"}, - - /* Mono Output */ - {"MONO_LOUT", NULL, "Mono Out"}, - {"MONO_LOUT", NULL, "Mono Out"}, - /* Left Input */ {"Left Line1L Mux", "single-ended", "LINE1L"}, {"Left Line1L Mux", "differential", "LINE1L"}, @@ -703,74 +652,6 @@ static const struct snd_soc_dapm_route intercon[] = { {"Right ADC", NULL, "Right PGA Mixer"}, {"Right ADC", NULL, "GPIO1 dmic modclk"}, - /* Left PGA Bypass */ - {"Left PGA Bypass Mixer", "LineL Switch", "Left PGA Mixer"}, - {"Left PGA Bypass Mixer", "LineR Switch", "Left PGA Mixer"}, - {"Left PGA Bypass Mixer", "Mono Switch", "Left PGA Mixer"}, - {"Left PGA Bypass Mixer", "HPL Switch", "Left PGA Mixer"}, - {"Left PGA Bypass Mixer", "HPR Switch", "Left PGA Mixer"}, - {"Left PGA Bypass Mixer", "HPLCOM Switch", "Left PGA Mixer"}, - {"Left PGA Bypass Mixer", "HPRCOM Switch", "Left PGA Mixer"}, - - {"Left HPCOM Mux", "differential of HPLOUT", "Left PGA Bypass Mixer"}, - {"Left HPCOM Mux", "constant VCM", "Left PGA Bypass Mixer"}, - {"Left HPCOM Mux", "single-ended", "Left PGA Bypass Mixer"}, - - {"Left Line Out", NULL, "Left PGA Bypass Mixer"}, - {"Mono Out", NULL, "Left PGA Bypass Mixer"}, - {"Left HP Out", NULL, "Left PGA Bypass Mixer"}, - - /* Right PGA Bypass */ - {"Right PGA Bypass Mixer", "LineL Switch", "Right PGA Mixer"}, - {"Right PGA Bypass Mixer", "LineR Switch", "Right PGA Mixer"}, - {"Right PGA Bypass Mixer", "Mono Switch", "Right PGA Mixer"}, - {"Right PGA Bypass Mixer", "HPL Switch", "Right PGA Mixer"}, - {"Right PGA Bypass Mixer", "HPR Switch", "Right PGA Mixer"}, - {"Right PGA Bypass Mixer", "HPLCOM Switch", "Right PGA Mixer"}, - {"Right PGA Bypass Mixer", "HPRCOM Switch", "Right PGA Mixer"}, - - {"Right HPCOM Mux", "differential of HPROUT", "Right PGA Bypass Mixer"}, - {"Right HPCOM Mux", "constant VCM", "Right PGA Bypass Mixer"}, - {"Right HPCOM Mux", "single-ended", "Right PGA Bypass Mixer"}, - {"Right HPCOM Mux", "differential of HPLCOM", "Right PGA Bypass Mixer"}, - {"Right HPCOM Mux", "external feedback", "Right PGA Bypass Mixer"}, - - {"Right Line Out", NULL, "Right PGA Bypass Mixer"}, - {"Mono Out", NULL, "Right PGA Bypass Mixer"}, - {"Right HP Out", NULL, "Right PGA Bypass Mixer"}, - - /* Left Line2 Bypass */ - {"Left Line2 Bypass Mixer", "LineL Switch", "Left Line2L Mux"}, - {"Left Line2 Bypass Mixer", "LineR Switch", "Left Line2L Mux"}, - {"Left Line2 Bypass Mixer", "Mono Switch", "Left Line2L Mux"}, - {"Left Line2 Bypass Mixer", "HP Switch", "Left Line2L Mux"}, - {"Left Line2 Bypass Mixer", "HPLCOM Switch", "Left Line2L Mux"}, - - {"Left HPCOM Mux", "differential of HPLOUT", "Left Line2 Bypass Mixer"}, - {"Left HPCOM Mux", "constant VCM", "Left Line2 Bypass Mixer"}, - {"Left HPCOM Mux", "single-ended", "Left Line2 Bypass Mixer"}, - - {"Left Line Out", NULL, "Left Line2 Bypass Mixer"}, - {"Mono Out", NULL, "Left Line2 Bypass Mixer"}, - {"Left HP Out", NULL, "Left Line2 Bypass Mixer"}, - - /* Right Line2 Bypass */ - {"Right Line2 Bypass Mixer", "LineL Switch", "Right Line2R Mux"}, - {"Right Line2 Bypass Mixer", "LineR Switch", "Right Line2R Mux"}, - {"Right Line2 Bypass Mixer", "Mono Switch", "Right Line2R Mux"}, - {"Right Line2 Bypass Mixer", "HP Switch", "Right Line2R Mux"}, - {"Right Line2 Bypass Mixer", "HPRCOM Switch", "Right Line2R Mux"}, - - {"Right HPCOM Mux", "differential of HPROUT", "Right Line2 Bypass Mixer"}, - {"Right HPCOM Mux", "constant VCM", "Right Line2 Bypass Mixer"}, - {"Right HPCOM Mux", "single-ended", "Right Line2 Bypass Mixer"}, - {"Right HPCOM Mux", "differential of HPLCOM", "Right Line2 Bypass Mixer"}, - {"Right HPCOM Mux", "external feedback", "Right Line2 Bypass Mixer"}, - - {"Right Line Out", NULL, "Right Line2 Bypass Mixer"}, - {"Mono Out", NULL, "Right Line2 Bypass Mixer"}, - {"Right HP Out", NULL, "Right Line2 Bypass Mixer"}, - /* * Logical path between digital mic enable and GPIO1 modulator clock * output function @@ -778,6 +659,105 @@ static const struct snd_soc_dapm_route intercon[] = { {"GPIO1 dmic modclk", NULL, "DMic Rate 128"}, {"GPIO1 dmic modclk", NULL, "DMic Rate 64"}, {"GPIO1 dmic modclk", NULL, "DMic Rate 32"}, + + /* Left DAC Output */ + {"Left DAC Mux", "DAC_L1", "Left DAC"}, + {"Left DAC Mux", "DAC_L2", "Left DAC"}, + {"Left DAC Mux", "DAC_L3", "Left DAC"}, + + /* Right DAC Output */ + {"Right DAC Mux", "DAC_R1", "Right DAC"}, + {"Right DAC Mux", "DAC_R2", "Right DAC"}, + {"Right DAC Mux", "DAC_R3", "Right DAC"}, + + /* Left Line Output */ + {"Left Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, + {"Left Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, + {"Left Line Mixer", "DACL1 Switch", "Left DAC Mux"}, + {"Left Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, + {"Left Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, + {"Left Line Mixer", "DACR1 Switch", "Right DAC Mux"}, + + {"Left Line Out", NULL, "Left Line Mixer"}, + {"Left Line Out", NULL, "Left DAC Mux"}, + {"LLOUT", NULL, "Left Line Out"}, + + /* Right Line Output */ + {"Right Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, + {"Right Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, + {"Right Line Mixer", "DACL1 Switch", "Left DAC Mux"}, + {"Right Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, + {"Right Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, + {"Right Line Mixer", "DACR1 Switch", "Right DAC Mux"}, + + {"Right Line Out", NULL, "Right Line Mixer"}, + {"Right Line Out", NULL, "Right DAC Mux"}, + {"RLOUT", NULL, "Right Line Out"}, + + /* Mono Output */ + {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, + {"Mono Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, + {"Mono Mixer", "DACL1 Switch", "Left DAC Mux"}, + {"Mono Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, + {"Mono Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, + {"Mono Mixer", "DACR1 Switch", "Right DAC Mux"}, + + {"Mono Out", NULL, "Mono Mixer"}, + {"MONO_LOUT", NULL, "Mono Out"}, + + /* Left HP Output */ + {"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, + {"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, + {"Left HP Mixer", "DACL1 Switch", "Left DAC Mux"}, + {"Left HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, + {"Left HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, + {"Left HP Mixer", "DACR1 Switch", "Right DAC Mux"}, + + {"Left HP Out", NULL, "Left HP Mixer"}, + {"Left HP Out", NULL, "Left DAC Mux"}, + {"HPLOUT", NULL, "Left HP Out"}, + + /* Right HP Output */ + {"Right HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, + {"Right HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, + {"Right HP Mixer", "DACL1 Switch", "Left DAC Mux"}, + {"Right HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, + {"Right HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, + {"Right HP Mixer", "DACR1 Switch", "Right DAC Mux"}, + + {"Right HP Out", NULL, "Right HP Mixer"}, + {"Right HP Out", NULL, "Right DAC Mux"}, + {"HPROUT", NULL, "Right HP Out"}, + + /* Left HPCOM Output */ + {"Left HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, + {"Left HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, + {"Left HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"}, + {"Left HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, + {"Left HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, + {"Left HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"}, + + {"Left HPCOM Mux", "differential of HPLOUT", "Left HP Mixer"}, + {"Left HPCOM Mux", "constant VCM", "Left HPCOM Mixer"}, + {"Left HPCOM Mux", "single-ended", "Left HPCOM Mixer"}, + {"Left HP Com", NULL, "Left HPCOM Mux"}, + {"HPLCOM", NULL, "Left HP Com"}, + + /* Right HPCOM Output */ + {"Right HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, + {"Right HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, + {"Right HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"}, + {"Right HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, + {"Right HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, + {"Right HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"}, + + {"Right HPCOM Mux", "differential of HPROUT", "Right HP Mixer"}, + {"Right HPCOM Mux", "constant VCM", "Right HPCOM Mixer"}, + {"Right HPCOM Mux", "single-ended", "Right HPCOM Mixer"}, + {"Right HPCOM Mux", "differential of HPLCOM", "Left HPCOM Mixer"}, + {"Right HPCOM Mux", "external feedback", "Right HPCOM Mixer"}, + {"Right HP Com", NULL, "Right HPCOM Mux"}, + {"HPRCOM", NULL, "Right HP Com"}, }; static const struct snd_soc_dapm_route intercon_3007[] = { diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 20d8cac2637c..06a19784b162 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -85,22 +85,30 @@ #define LINE2L_2_HPLOUT_VOL 45 #define PGAL_2_HPLOUT_VOL 46 #define DACL1_2_HPLOUT_VOL 47 +#define LINE2R_2_HPLOUT_VOL 48 #define PGAR_2_HPLOUT_VOL 49 +#define DACR1_2_HPLOUT_VOL 50 #define HPLOUT_CTRL 51 /* Left High Power COM control registers */ #define LINE2L_2_HPLCOM_VOL 52 #define PGAL_2_HPLCOM_VOL 53 #define DACL1_2_HPLCOM_VOL 54 +#define LINE2R_2_HPLCOM_VOL 55 #define PGAR_2_HPLCOM_VOL 56 +#define DACR1_2_HPLCOM_VOL 57 #define HPLCOM_CTRL 58 /* Right High Power Output control registers */ +#define LINE2L_2_HPROUT_VOL 59 #define PGAL_2_HPROUT_VOL 60 +#define DACL1_2_HPROUT_VOL 61 #define LINE2R_2_HPROUT_VOL 62 #define PGAR_2_HPROUT_VOL 63 #define DACR1_2_HPROUT_VOL 64 #define HPROUT_CTRL 65 /* Right High Power COM control registers */ +#define LINE2L_2_HPRCOM_VOL 66 #define PGAL_2_HPRCOM_VOL 67 +#define DACL1_2_HPRCOM_VOL 68 #define LINE2R_2_HPRCOM_VOL 69 #define PGAR_2_HPRCOM_VOL 70 #define DACR1_2_HPRCOM_VOL 71 -- cgit v1.2.3-59-g8ed1b From 098b1718230466b48f2027eb26cdc921760ae5da Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 27 Aug 2010 16:56:50 +0300 Subject: ASoC: tlv320aic3x: Sanitize output controls Currently output controls are not uniform. Some routes are adjusted by mono controls that don't match to associated mixer switch, many routes are not covered at all and stereo controls have following variants: - L-to-L & R-to-R - R-to-L & R-to-R - L-to-L & R-to-L This patch attempts to fix these issues. First, for the convenience, only direct L-to-L, R-to-R and [L | R]-to-Mono routes are controlled by the stereo controls. This logic is also used with the output pin mute controls so all of them except mono output are controlled by stereo switches. Then rest of the swapped L-to-R and R-to-L routes are controlled by the mono controls that map to mixer switches with a same name. Mixers can then associate these switches and volumes together. Signed-off-by: Jarkko Nikula Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/tlv320aic3x.c | 114 +++++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 38 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 0a3b98c097bb..8577c50d8d22 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -292,64 +292,102 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { SOC_DOUBLE_R_TLV("PCM Playback Volume", LDAC_VOL, RDAC_VOL, 0, 0x7f, 1, dac_tlv), + /* + * Output controls that map to output mixer switches. Note these are + * only for swapped L-to-R and R-to-L routes. See below stereo controls + * for direct L-to-L and R-to-R routes. + */ + SOC_SINGLE_TLV("Left Line Mixer Line2R Bypass Volume", + LINE2R_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Left Line Mixer PGAR Bypass Volume", + PGAR_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Left Line Mixer DACR1 Playback Volume", + DACR1_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), + + SOC_SINGLE_TLV("Right Line Mixer Line2L Bypass Volume", + LINE2L_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Right Line Mixer PGAL Bypass Volume", + PGAL_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Right Line Mixer DACL1 Playback Volume", + DACL1_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), + + SOC_SINGLE_TLV("Left HP Mixer Line2R Bypass Volume", + LINE2R_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Left HP Mixer PGAR Bypass Volume", + PGAR_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Left HP Mixer DACR1 Playback Volume", + DACR1_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), + + SOC_SINGLE_TLV("Right HP Mixer Line2L Bypass Volume", + LINE2L_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Right HP Mixer PGAL Bypass Volume", + PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Right HP Mixer DACL1 Playback Volume", + DACL1_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), + + SOC_SINGLE_TLV("Left HPCOM Mixer Line2R Bypass Volume", + LINE2R_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Left HPCOM Mixer PGAR Bypass Volume", + PGAR_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Left HPCOM Mixer DACR1 Playback Volume", + DACR1_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), + + SOC_SINGLE_TLV("Right HPCOM Mixer Line2L Bypass Volume", + LINE2L_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Right HPCOM Mixer PGAL Bypass Volume", + PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("Right HPCOM Mixer DACL1 Playback Volume", + DACL1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), + + /* Stereo output controls for direct L-to-L and R-to-R routes */ + SOC_DOUBLE_R_TLV("Line Line2 Bypass Volume", + LINE2L_2_LLOPM_VOL, LINE2R_2_RLOPM_VOL, + 0, 118, 1, output_stage_tlv), + SOC_DOUBLE_R_TLV("Line PGA Bypass Volume", + PGAL_2_LLOPM_VOL, PGAR_2_RLOPM_VOL, + 0, 118, 1, output_stage_tlv), SOC_DOUBLE_R_TLV("Line DAC Playback Volume", DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0), - SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0), - SOC_DOUBLE_R_TLV("LineL DAC Playback Volume", - DACL1_2_LLOPM_VOL, DACR1_2_LLOPM_VOL, - 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("LineL Left PGA Bypass Playback Volume", - PGAL_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("LineR Right PGA Bypass Playback Volume", - PGAR_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("LineL Line2 Bypass Playback Volume", - LINE2L_2_LLOPM_VOL, LINE2R_2_LLOPM_VOL, + + SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume", + LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL, 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("LineR Line2 Bypass Playback Volume", - LINE2L_2_RLOPM_VOL, LINE2R_2_RLOPM_VOL, + SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume", + PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL, 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), - SOC_DOUBLE_R_TLV("Mono PGA Bypass Playback Volume", - PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL, + + SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume", + LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("Mono Line2 Bypass Playback Volume", - LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL, + SOC_DOUBLE_R_TLV("HP PGA Bypass Volume", + PGAL_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("HP DAC Playback Volume", DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, - 0x01, 0), - SOC_DOUBLE_R_TLV("HP Right PGA Bypass Playback Volume", - PGAR_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL, + + SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Volume", + LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("HPL PGA Bypass Playback Volume", - PGAL_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("HPR PGA Bypass Playback Volume", - PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("HP Line2 Bypass Playback Volume", - LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL, + SOC_DOUBLE_R_TLV("HPCOM PGA Bypass Volume", + PGAL_2_HPLCOM_VOL, PGAR_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("HPCOM DAC Playback Volume", DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), + + /* Output pin mute controls */ + SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3, + 0x01, 0), + SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), + SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, + 0x01, 0), SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, 0x01, 0), - SOC_SINGLE_TLV("HPLCOM PGA Bypass Playback Volume", - PGAL_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("HPRCOM PGA Bypass Playback Volume", - PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Playback Volume", - LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL, - 0, 118, 1, output_stage_tlv), /* * Note: enable Automatic input Gain Controller with care. It can -- cgit v1.2.3-59-g8ed1b From 762c29164e2850d8c5e4c258cef0077b2584d111 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 27 Aug 2010 16:41:56 +0000 Subject: econet: kill unnecessary spin_lock_init() The spinlock aun_queue_lock is initialized statically. It is unnecessary to initialize by spin_lock_init() at module load time. This is detected by the semantic patch. // @def@ declarer name DEFINE_SPINLOCK; identifier spinlock; @@ DEFINE_SPINLOCK(spinlock); @@ identifier def.spinlock; @@ - spin_lock_init(&spinlock); // Signed-off-by: Akinobu Mita Cc: Julia Lawall Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- net/econet/af_econet.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index dc54bd0d083b..baa98fb83552 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -1009,7 +1009,6 @@ static int __init aun_udp_initialise(void) struct sockaddr_in sin; skb_queue_head_init(&aun_queue); - spin_lock_init(&aun_queue_lock); setup_timer(&ab_cleanup_timer, ab_cleanup, 0); ab_cleanup_timer.expires = jiffies + (HZ*2); add_timer(&ab_cleanup_timer); @@ -1167,7 +1166,6 @@ static int __init econet_proto_init(void) goto out; sock_register(&econet_family_ops); #ifdef CONFIG_ECONET_AUNUDP - spin_lock_init(&aun_queue_lock); aun_udp_initialise(); #endif #ifdef CONFIG_ECONET_NATIVE -- cgit v1.2.3-59-g8ed1b From e27cd4f8ca9dde7938f4f83ef75b6fae8d46dd5f Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 27 Aug 2010 19:08:13 +0000 Subject: mlx4: use bitmap library Replace loops calling set_bit() and clear_bit() with bitmap_set() and bitmap_clear(). Unlike loops calling set_bit() and clear_bit(), bitmap_set() and bitmap_clear() are not atomic. But this is ok. Because the bitmap operations are protected by bitmap->lock except for initialization of the bitmap in mlx4_bitmap_init(). Signed-off-by: Akinobu Mita Cc: Roland Dreier Cc: netdev@vger.kernel.org Cc: "David S. Miller" Signed-off-by: David S. Miller --- drivers/net/mlx4/alloc.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c index 537997f9443e..8f4bf1f07c11 100644 --- a/drivers/net/mlx4/alloc.c +++ b/drivers/net/mlx4/alloc.c @@ -74,7 +74,7 @@ void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align) { - u32 obj, i; + u32 obj; if (likely(cnt == 1 && align == 1)) return mlx4_bitmap_alloc(bitmap); @@ -91,8 +91,7 @@ u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align) } if (obj < bitmap->max) { - for (i = 0; i < cnt; i++) - set_bit(obj + i, bitmap->table); + bitmap_set(bitmap->table, obj, cnt); if (obj == bitmap->last) { bitmap->last = (obj + cnt); if (bitmap->last >= bitmap->max) @@ -109,13 +108,10 @@ u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align) void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt) { - u32 i; - obj &= bitmap->max + bitmap->reserved_top - 1; spin_lock(&bitmap->lock); - for (i = 0; i < cnt; i++) - clear_bit(obj + i, bitmap->table); + bitmap_clear(bitmap->table, obj, cnt); bitmap->last = min(bitmap->last, obj); bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) & bitmap->mask; @@ -125,8 +121,6 @@ void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt) int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved_bot, u32 reserved_top) { - int i; - /* num must be a power of 2 */ if (num != roundup_pow_of_two(num)) return -EINVAL; @@ -142,8 +136,7 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, if (!bitmap->table) return -ENOMEM; - for (i = 0; i < reserved_bot; ++i) - set_bit(i, bitmap->table); + bitmap_set(bitmap->table, 0, reserved_bot); return 0; } -- cgit v1.2.3-59-g8ed1b From 6a499b242f7d1ebf13f5bc386e08e80603f79e2a Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 27 Aug 2010 19:08:26 +0000 Subject: phonet: use for_each_set_bit Replace open-coded loop with for_each_set_bit(). Signed-off-by: Akinobu Mita Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- net/phonet/pn_dev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index b18e48fae975..d0a429459370 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -292,8 +292,7 @@ static void phonet_route_autodel(struct net_device *dev) if (bitmap_empty(deleted, 64)) return; /* short-circuit RCU */ synchronize_rcu(); - for (i = find_first_bit(deleted, 64); i < 64; - i = find_next_bit(deleted, 64, i + 1)) { + for_each_set_bit(i, deleted, 64) { rtm_phonet_notify(RTM_DELROUTE, dev, i); dev_put(dev); } -- cgit v1.2.3-59-g8ed1b From d08336e9998b1004b2baad62325d34349a593137 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 27 Aug 2010 19:08:36 +0000 Subject: starfire: use PCI_VDEVICE Signed-off-by: Akinobu Mita Cc: Ion Badulescu Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/starfire.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index a42b6873370b..26c363462856 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -302,7 +302,7 @@ enum chipset { }; static DEFINE_PCI_DEVICE_TABLE(starfire_pci_tbl) = { - { 0x9004, 0x6915, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_6915 }, + { PCI_VDEVICE(ADAPTEC, 0x6915), CH_6915 }, { 0, } }; MODULE_DEVICE_TABLE(pci, starfire_pci_tbl); -- cgit v1.2.3-59-g8ed1b From 56543af9563d91c1c5596a7980b416389bdea071 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 27 Aug 2010 19:08:45 +0000 Subject: starfire: use BUILD_BUG_ON for netdrv_addr_t Detect size mismatch for netdrv_addr_t at build time rather than checking at module load time. Signed-off-by: Akinobu Mita Cc: Ion Badulescu Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/starfire.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 26c363462856..c3bf288aaf25 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -2078,11 +2078,7 @@ static int __init starfire_init (void) printk(KERN_INFO DRV_NAME ": polling (NAPI) enabled\n"); #endif - /* we can do this test only at run-time... sigh */ - if (sizeof(dma_addr_t) != sizeof(netdrv_addr_t)) { - printk("This driver has dma_addr_t issues, please send email to maintainer\n"); - return -ENODEV; - } + BUILD_BUG_ON(sizeof(dma_addr_t) != sizeof(netdrv_addr_t)); return pci_register_driver(&starfire_driver); } -- cgit v1.2.3-59-g8ed1b From 2bc9e234658072145b63d1d364bac4c8e337c865 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 28 Aug 2010 05:41:02 +0000 Subject: drivers/net/atl1c: Remove double test The nic_type field is compared to athr_l2c twice. The sematic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @expression@ expression E; @@ ( * E || ... || E | * E && ... && E ) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/atl1c/atl1c_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/atl1c/atl1c_hw.c index d8501f060957..919080b2c3a5 100644 --- a/drivers/net/atl1c/atl1c_hw.c +++ b/drivers/net/atl1c/atl1c_hw.c @@ -480,7 +480,7 @@ int atl1c_phy_reset(struct atl1c_hw *hw) atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D); } if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2 - || hw->nic_type == athr_l2c || hw->nic_type == athr_l2c) { + || hw->nic_type == athr_l2c) { atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29); atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD); } -- cgit v1.2.3-59-g8ed1b From 2072f8db625cbdaba839fe7bb1b607d06884e685 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sat, 28 Aug 2010 22:00:05 -0700 Subject: Input: wacom_w8001 - send BTN_TOOL_PEN/RUBBER and BTN_STYLUS events The protocol used by the w8001 supports status fields for tip, side switch and eraser as well as a RDY field for proximity. The protocol has a double usage for the f2 bit in the packet. If set, the data is either pen + side2 button or eraser. Assume eraser if the device comes into proximity with the f2 bit set, otherwise trigger the side2 button. If the device comes into proximity with the f2 bit and that bit disappears afterwards, fake proximity out for the eraser and proximity in for the pen. Signed-off-by: Peter Hutterer Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wacom_w8001.c | 54 +++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 56dc35c94bb1..bc642f1be376 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -62,6 +62,7 @@ struct w8001 { unsigned char response[W8001_MAX_LENGTH]; unsigned char data[W8001_MAX_LENGTH]; char phys[32]; + int type; }; static void parse_data(u8 *data, struct w8001_coord *coord) @@ -88,11 +89,52 @@ static void parse_data(u8 *data, struct w8001_coord *coord) coord->tilt_y = data[8] & 0x7F; } +static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) +{ + struct input_dev *dev = w8001->dev; + + /* + * We have 1 bit for proximity (rdy) and 3 bits for tip, side, + * side2/eraser. If rdy && f2 are set, this can be either pen + side2, + * or eraser. assume + * - if dev is already in proximity and f2 is toggled → pen + side2 + * - if dev comes into proximity with f2 set → eraser + * If f2 disappears after assuming eraser, fake proximity out for + * eraser and in for pen. + */ + + if (!w8001->type) { + w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; + } else if (w8001->type == BTN_TOOL_RUBBER) { + if (!coord->f2) { + input_report_abs(dev, ABS_PRESSURE, 0); + input_report_key(dev, BTN_TOUCH, 0); + input_report_key(dev, BTN_STYLUS, 0); + input_report_key(dev, BTN_STYLUS2, 0); + input_report_key(dev, BTN_TOOL_RUBBER, 0); + input_sync(dev); + w8001->type = BTN_TOOL_PEN; + } + } else { + input_report_key(dev, BTN_STYLUS2, coord->f2); + } + + input_report_abs(dev, ABS_X, coord->x); + input_report_abs(dev, ABS_Y, coord->y); + input_report_abs(dev, ABS_PRESSURE, coord->pen_pressure); + input_report_key(dev, BTN_TOUCH, coord->tsw); + input_report_key(dev, BTN_STYLUS, coord->f1); + input_report_key(dev, w8001->type, coord->rdy); + input_sync(dev); + + if (!coord->rdy) + w8001->type = 0; +} + static irqreturn_t w8001_interrupt(struct serio *serio, unsigned char data, unsigned int flags) { struct w8001 *w8001 = serio_get_drvdata(serio); - struct input_dev *dev = w8001->dev; struct w8001_coord coord; unsigned char tmp; @@ -112,11 +154,7 @@ static irqreturn_t w8001_interrupt(struct serio *serio, w8001->idx = 0; parse_data(w8001->data, &coord); - input_report_abs(dev, ABS_X, coord.x); - input_report_abs(dev, ABS_Y, coord.y); - input_report_abs(dev, ABS_PRESSURE, coord.pen_pressure); - input_report_key(dev, BTN_TOUCH, coord.tsw); - input_sync(dev); + report_pen_events(w8001, &coord); break; case 10: @@ -221,6 +259,10 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + input_dev->keybit[BIT_WORD(BTN_TOOL_PEN)] |= BIT_MASK(BTN_TOOL_PEN); + input_dev->keybit[BIT_WORD(BTN_TOOL_RUBBER)] |= BIT_MASK(BTN_TOOL_RUBBER); + input_dev->keybit[BIT_WORD(BTN_STYLUS)] |= BIT_MASK(BTN_STYLUS); + input_dev->keybit[BIT_WORD(BTN_STYLUS2)] |= BIT_MASK(BTN_STYLUS2); serio_set_drvdata(serio, w8001); err = serio_open(serio, drv); -- cgit v1.2.3-59-g8ed1b From aaba933eeb8d7f804508bc74baa58656240107f8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sat, 28 Aug 2010 22:00:47 -0700 Subject: Input: wacom_w8001 - support (and ignore) touch tablets Tablets that support touch input may report different sized packages, depending on the touch sensor in the tablet. For now, discard the packages until we report them as touch input proper. Signed-off-by: Peter Hutterer Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wacom_w8001.c | 88 ++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index bc642f1be376..89abda06db74 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -2,6 +2,7 @@ * Wacom W8001 penabled serial touchscreen driver * * Copyright (c) 2008 Jaya Kumar + * Copyright (c) 2010 Red Hat, Inc. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for @@ -30,11 +31,22 @@ MODULE_LICENSE("GPL"); #define W8001_LEAD_BYTE 0x80 #define W8001_TAB_MASK 0x40 #define W8001_TAB_BYTE 0x40 +/* set in first byte of touch data packets */ +#define W8001_TOUCH_MASK (0x10 | W8001_LEAD_MASK) +#define W8001_TOUCH_BYTE (0x10 | W8001_LEAD_BYTE) #define W8001_QUERY_PACKET 0x20 #define W8001_CMD_START '1' #define W8001_CMD_QUERY '*' +#define W8001_CMD_TOUCHQUERY '%' + +/* length of data packets in bytes, depends on device. */ +#define W8001_PKTLEN_TOUCH93 5 +#define W8001_PKTLEN_TOUCH9A 7 +#define W8001_PKTLEN_TPCPEN 9 +#define W8001_PKTLEN_TPCCTL 11 /* control packet */ +#define W8001_PKTLEN_TOUCH2FG 13 struct w8001_coord { u8 rdy; @@ -48,6 +60,15 @@ struct w8001_coord { u8 tilt_y; }; +/* touch query reply packet */ +struct w8001_touch_query { + u8 panel_res; + u8 capacity_res; + u8 sensor_id; + u16 x; + u16 y; +}; + /* * Per-touchscreen data. */ @@ -63,6 +84,7 @@ struct w8001 { unsigned char data[W8001_MAX_LENGTH]; char phys[32]; int type; + unsigned int pktlen; }; static void parse_data(u8 *data, struct w8001_coord *coord) @@ -89,6 +111,23 @@ static void parse_data(u8 *data, struct w8001_coord *coord) coord->tilt_y = data[8] & 0x7F; } +static void parse_touchquery(u8 *data, struct w8001_touch_query *query) +{ + memset(query, 0, sizeof(*query)); + + query->panel_res = data[1]; + query->sensor_id = data[2] & 0x7; + query->capacity_res = data[7]; + + query->x = data[3] << 9; + query->x |= data[4] << 2; + query->x |= (data[2] >> 5) & 0x3; + + query->y = data[5] << 9; + query->y |= data[6] << 2; + query->y |= (data[2] >> 3) & 0x3; +} + static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) { struct input_dev *dev = w8001->dev; @@ -147,22 +186,45 @@ static irqreturn_t w8001_interrupt(struct serio *serio, } break; - case 8: + case W8001_PKTLEN_TOUCH93 - 1: + case W8001_PKTLEN_TOUCH9A - 1: + /* ignore one-finger touch packet. */ + if (w8001->pktlen == w8001->idx) + w8001->idx = 0; + break; + + /* Pen coordinates packet */ + case W8001_PKTLEN_TPCPEN - 1: tmp = w8001->data[0] & W8001_TAB_MASK; if (unlikely(tmp == W8001_TAB_BYTE)) break; + tmp = (w8001->data[0] & W8001_TOUCH_BYTE); + if (tmp == W8001_TOUCH_BYTE) + break; + w8001->idx = 0; parse_data(w8001->data, &coord); report_pen_events(w8001, &coord); break; - case 10: + /* control packet */ + case W8001_PKTLEN_TPCCTL - 1: + tmp = (w8001->data[0] & W8001_TOUCH_MASK); + if (tmp == W8001_TOUCH_BYTE) + break; + w8001->idx = 0; memcpy(w8001->response, w8001->data, W8001_MAX_LENGTH); w8001->response_type = W8001_QUERY_PACKET; complete(&w8001->cmd_done); break; + + case W8001_PKTLEN_TOUCH2FG - 1: + /* ignore two-finger touch packet. */ + if (w8001->pktlen == w8001->idx) + w8001->idx = 0; + break; } return IRQ_HANDLED; @@ -205,6 +267,28 @@ static int w8001_setup(struct w8001 *w8001) input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); + error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true); + if (!error) { + struct w8001_touch_query touch; + + parse_touchquery(w8001->response, &touch); + + switch (touch.sensor_id) { + case 0: + case 2: + w8001->pktlen = W8001_PKTLEN_TOUCH93; + break; + case 1: + case 3: + case 4: + w8001->pktlen = W8001_PKTLEN_TOUCH9A; + break; + case 5: + w8001->pktlen = W8001_PKTLEN_TOUCH2FG; + break; + } + } + return w8001_command(w8001, W8001_CMD_START, false); } -- cgit v1.2.3-59-g8ed1b From 5e8b9140f306ce30e7c56c568198720514efc872 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sat, 28 Aug 2010 22:00:47 -0700 Subject: Input: wacom_w8001 - add multitouch slot support Some serial wacom devices support two-finger touch. Test for this during init and parse the touch packets accordingly. Touch packets are processed using Protocol B (MT Slots). Note: there are several wacom versions that do touch but not two-finger touch. These are not catered for here, touch events for these are simply discarded. Signed-off-by: Peter Hutterer Acked-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wacom_w8001.c | 49 +++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 89abda06db74..9ae4c7b16ba7 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -48,6 +48,8 @@ MODULE_LICENSE("GPL"); #define W8001_PKTLEN_TPCCTL 11 /* control packet */ #define W8001_PKTLEN_TOUCH2FG 13 +#define MAX_TRACKING_ID 0xFF /* arbitrarily chosen */ + struct w8001_coord { u8 rdy; u8 tsw; @@ -85,6 +87,7 @@ struct w8001 { char phys[32]; int type; unsigned int pktlen; + int trkid[2]; }; static void parse_data(u8 *data, struct w8001_coord *coord) @@ -111,6 +114,35 @@ static void parse_data(u8 *data, struct w8001_coord *coord) coord->tilt_y = data[8] & 0x7F; } +static void parse_touch(struct w8001 *w8001) +{ + static int trkid; + struct input_dev *dev = w8001->dev; + unsigned char *data = w8001->data; + int i; + + for (i = 0; i < 2; i++) { + input_mt_slot(dev, i); + + if (data[0] & (1 << i)) { + int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]); + int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]); + /* data[5,6] and [11,12] is finger capacity */ + + input_report_abs(dev, ABS_MT_POSITION_X, x); + input_report_abs(dev, ABS_MT_POSITION_Y, y); + input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER); + if (w8001->trkid[i] < 0) + w8001->trkid[i] = trkid++ & MAX_TRACKING_ID; + } else { + w8001->trkid[i] = -1; + } + input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]); + } + + input_sync(dev); +} + static void parse_touchquery(u8 *data, struct w8001_touch_query *query) { memset(query, 0, sizeof(*query)); @@ -220,10 +252,10 @@ static irqreturn_t w8001_interrupt(struct serio *serio, complete(&w8001->cmd_done); break; + /* 2 finger touch packet */ case W8001_PKTLEN_TOUCH2FG - 1: - /* ignore two-finger touch packet. */ - if (w8001->pktlen == w8001->idx) - w8001->idx = 0; + w8001->idx = 0; + parse_touch(w8001); break; } @@ -285,6 +317,16 @@ static int w8001_setup(struct w8001 *w8001) break; case 5: w8001->pktlen = W8001_PKTLEN_TOUCH2FG; + + input_mt_create_slots(dev, 2); + input_set_abs_params(dev, ABS_MT_TRACKING_ID, + 0, MAX_TRACKING_ID, 0, 0); + input_set_abs_params(dev, ABS_MT_POSITION_X, + 0, touch.x, 0, 0); + input_set_abs_params(dev, ABS_MT_POSITION_Y, + 0, touch.y, 0, 0); + input_set_abs_params(dev, ABS_MT_TOOL_TYPE, + 0, 0, 0, 0); break; } } @@ -330,6 +372,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) w8001->serio = serio; w8001->id = serio->id.id; w8001->dev = input_dev; + w8001->trkid[0] = w8001->trkid[1] = -1; init_completion(&w8001->cmd_done); snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); -- cgit v1.2.3-59-g8ed1b From 3045a5f5202a1e0ab6ba2bf90a786cf4cae6932a Mon Sep 17 00:00:00 2001 From: Kevin Wells Date: Sat, 28 Aug 2010 22:45:22 -0700 Subject: Input: add LPC32xx touchscreen controller driver This patch set introduces support for the LPC32xx touchscreen controller driver. The LPC32xx touchscreen controller supports automated event detection and X/Y data conversion for resistive touchscreens. Signed-off-by: Kevin Wells Signed-off-by: Durgesh Pattamatta Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 10 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/lpc32xx_ts.c | 411 +++++++++++++++++++++++++++++++++ 3 files changed, 422 insertions(+) create mode 100644 drivers/input/touchscreen/lpc32xx_ts.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 0069d9703fda..400c99de0bb3 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -214,6 +214,16 @@ config TOUCHSCREEN_WACOM_W8001 To compile this driver as a module, choose M here: the module will be called wacom_w8001. +config TOUCHSCREEN_LPC32XX + tristate "LPC32XX touchscreen controller" + depends on ARCH_LPC32XX + help + Say Y here if you have a LPC32XX device and want + to support the built-in touchscreen. + + To compile this driver as a module, choose M here: the + module will be called lpc32xx_ts. + config TOUCHSCREEN_MCS5000 tristate "MELFAS MCS-5000 touchscreen" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 28217e1dcafd..22e2d598dc69 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o +obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c new file mode 100644 index 000000000000..dcf803f5a1f7 --- /dev/null +++ b/drivers/input/touchscreen/lpc32xx_ts.c @@ -0,0 +1,411 @@ +/* + * LPC32xx built-in touchscreen driver + * + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Touchscreen controller register offsets + */ +#define LPC32XX_TSC_STAT 0x00 +#define LPC32XX_TSC_SEL 0x04 +#define LPC32XX_TSC_CON 0x08 +#define LPC32XX_TSC_FIFO 0x0C +#define LPC32XX_TSC_DTR 0x10 +#define LPC32XX_TSC_RTR 0x14 +#define LPC32XX_TSC_UTR 0x18 +#define LPC32XX_TSC_TTR 0x1C +#define LPC32XX_TSC_DXP 0x20 +#define LPC32XX_TSC_MIN_X 0x24 +#define LPC32XX_TSC_MAX_X 0x28 +#define LPC32XX_TSC_MIN_Y 0x2C +#define LPC32XX_TSC_MAX_Y 0x30 +#define LPC32XX_TSC_AUX_UTR 0x34 +#define LPC32XX_TSC_AUX_MIN 0x38 +#define LPC32XX_TSC_AUX_MAX 0x3C + +#define LPC32XX_TSC_STAT_FIFO_OVRRN (1 << 8) +#define LPC32XX_TSC_STAT_FIFO_EMPTY (1 << 7) + +#define LPC32XX_TSC_SEL_DEFVAL 0x0284 + +#define LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4 (0x1 << 11) +#define LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(s) ((10 - (s)) << 7) +#define LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(s) ((10 - (s)) << 4) +#define LPC32XX_TSC_ADCCON_POWER_UP (1 << 2) +#define LPC32XX_TSC_ADCCON_AUTO_EN (1 << 0) + +#define LPC32XX_TSC_FIFO_TS_P_LEVEL (1 << 31) +#define LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(x) (((x) & 0x03FF0000) >> 16) +#define LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(y) ((y) & 0x000003FF) + +#define LPC32XX_TSC_ADCDAT_VALUE_MASK 0x000003FF + +#define LPC32XX_TSC_MIN_XY_VAL 0x0 +#define LPC32XX_TSC_MAX_XY_VAL 0x3FF + +#define MOD_NAME "ts-lpc32xx" + +#define tsc_readl(dev, reg) \ + __raw_readl((dev)->tsc_base + (reg)) +#define tsc_writel(dev, reg, val) \ + __raw_writel((val), (dev)->tsc_base + (reg)) + +struct lpc32xx_tsc { + struct input_dev *dev; + void __iomem *tsc_base; + int irq; + struct clk *clk; +}; + +static void lpc32xx_fifo_clear(struct lpc32xx_tsc *tsc) +{ + while (!(tsc_readl(tsc, LPC32XX_TSC_STAT) & + LPC32XX_TSC_STAT_FIFO_EMPTY)) + tsc_readl(tsc, LPC32XX_TSC_FIFO); +} + +static irqreturn_t lpc32xx_ts_interrupt(int irq, void *dev_id) +{ + u32 tmp, rv[4], xs[4], ys[4]; + int idx; + struct lpc32xx_tsc *tsc = dev_id; + struct input_dev *input = tsc->dev; + + tmp = tsc_readl(tsc, LPC32XX_TSC_STAT); + + if (tmp & LPC32XX_TSC_STAT_FIFO_OVRRN) { + /* FIFO overflow - throw away samples */ + lpc32xx_fifo_clear(tsc); + return IRQ_HANDLED; + } + + /* + * Gather and normalize 4 samples. Pen-up events may have less + * than 4 samples, but its ok to pop 4 and let the last sample + * pen status check drop the samples. + */ + idx = 0; + while (idx < 4 && + !(tsc_readl(tsc, LPC32XX_TSC_STAT) & + LPC32XX_TSC_STAT_FIFO_EMPTY)) { + tmp = tsc_readl(tsc, LPC32XX_TSC_FIFO); + xs[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK - + LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(tmp); + ys[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK - + LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(tmp); + rv[idx] = tmp; + idx++; + } + + /* Data is only valid if pen is still down in last sample */ + if (!(rv[3] & LPC32XX_TSC_FIFO_TS_P_LEVEL) && idx == 4) { + /* Use average of 2nd and 3rd sample for position */ + input_report_abs(input, ABS_X, (xs[1] + xs[2]) / 2); + input_report_abs(input, ABS_Y, (ys[1] + ys[2]) / 2); + input_report_key(input, BTN_TOUCH, 1); + } else { + input_report_key(input, BTN_TOUCH, 0); + } + + input_sync(input); + + return IRQ_HANDLED; +} + +static void lpc32xx_stop_tsc(struct lpc32xx_tsc *tsc) +{ + /* Disable auto mode */ + tsc_writel(tsc, LPC32XX_TSC_CON, + tsc_readl(tsc, LPC32XX_TSC_CON) & + ~LPC32XX_TSC_ADCCON_AUTO_EN); + + clk_disable(tsc->clk); +} + +static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc) +{ + u32 tmp; + + clk_enable(tsc->clk); + + tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP; + + /* Set the TSC FIFO depth to 4 samples @ 10-bits per sample (max) */ + tmp = LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4 | + LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(10) | + LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(10); + tsc_writel(tsc, LPC32XX_TSC_CON, tmp); + + /* These values are all preset */ + tsc_writel(tsc, LPC32XX_TSC_SEL, LPC32XX_TSC_SEL_DEFVAL); + tsc_writel(tsc, LPC32XX_TSC_MIN_X, LPC32XX_TSC_MIN_XY_VAL); + tsc_writel(tsc, LPC32XX_TSC_MAX_X, LPC32XX_TSC_MAX_XY_VAL); + tsc_writel(tsc, LPC32XX_TSC_MIN_Y, LPC32XX_TSC_MIN_XY_VAL); + tsc_writel(tsc, LPC32XX_TSC_MAX_Y, LPC32XX_TSC_MAX_XY_VAL); + + /* Aux support is not used */ + tsc_writel(tsc, LPC32XX_TSC_AUX_UTR, 0); + tsc_writel(tsc, LPC32XX_TSC_AUX_MIN, 0); + tsc_writel(tsc, LPC32XX_TSC_AUX_MAX, 0); + + /* + * Set sample rate to about 240Hz per X/Y pair. A single measurement + * consists of 4 pairs which gives about a 60Hz sample rate based on + * a stable 32768Hz clock source. Values are in clocks. + * Rate is (32768 / (RTR + XCONV + RTR + YCONV + DXP + TTR + UTR) / 4 + */ + tsc_writel(tsc, LPC32XX_TSC_RTR, 0x2); + tsc_writel(tsc, LPC32XX_TSC_DTR, 0x2); + tsc_writel(tsc, LPC32XX_TSC_TTR, 0x10); + tsc_writel(tsc, LPC32XX_TSC_DXP, 0x4); + tsc_writel(tsc, LPC32XX_TSC_UTR, 88); + + lpc32xx_fifo_clear(tsc); + + /* Enable automatic ts event capture */ + tsc_writel(tsc, LPC32XX_TSC_CON, tmp | LPC32XX_TSC_ADCCON_AUTO_EN); +} + +static int lpc32xx_ts_open(struct input_dev *dev) +{ + struct lpc32xx_tsc *tsc = input_get_drvdata(dev); + + lpc32xx_setup_tsc(tsc); + + return 0; +} + +static void lpc32xx_ts_close(struct input_dev *dev) +{ + struct lpc32xx_tsc *tsc = input_get_drvdata(dev); + + lpc32xx_stop_tsc(tsc); +} + +static int __devinit lpc32xx_ts_probe(struct platform_device *pdev) +{ + struct lpc32xx_tsc *tsc; + struct input_dev *input; + struct resource *res; + resource_size_t size; + int irq; + int error; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Can't get memory resource\n"); + return -ENOENT; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "Can't get interrupt resource\n"); + return irq; + } + + tsc = kzalloc(sizeof(*tsc), GFP_KERNEL); + input = input_allocate_device(); + if (!tsc || !input) { + dev_err(&pdev->dev, "failed allocating memory\n"); + error = -ENOMEM; + goto err_free_mem; + } + + tsc->dev = input; + tsc->irq = irq; + + size = resource_size(res); + + if (!request_mem_region(res->start, size, pdev->name)) { + dev_err(&pdev->dev, "TSC registers are not free\n"); + error = -EBUSY; + goto err_free_mem; + } + + tsc->tsc_base = ioremap(res->start, size); + if (!tsc->tsc_base) { + dev_err(&pdev->dev, "Can't map memory\n"); + error = -ENOMEM; + goto err_release_mem; + } + + tsc->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(tsc->clk)) { + dev_err(&pdev->dev, "failed getting clock\n"); + error = PTR_ERR(tsc->clk); + goto err_unmap; + } + + input->name = MOD_NAME; + input->phys = "lpc32xx/input0"; + input->id.bustype = BUS_HOST; + input->id.vendor = 0x0001; + input->id.product = 0x0002; + input->id.version = 0x0100; + input->dev.parent = &pdev->dev; + input->open = lpc32xx_ts_open; + input->close = lpc32xx_ts_close; + + input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + input_set_abs_params(input, ABS_X, LPC32XX_TSC_MIN_XY_VAL, + LPC32XX_TSC_MAX_XY_VAL, 0, 0); + input_set_abs_params(input, ABS_Y, LPC32XX_TSC_MIN_XY_VAL, + LPC32XX_TSC_MAX_XY_VAL, 0, 0); + + input_set_drvdata(input, tsc); + + error = request_irq(tsc->irq, lpc32xx_ts_interrupt, + IRQF_DISABLED, pdev->name, tsc); + if (error) { + dev_err(&pdev->dev, "failed requesting interrupt\n"); + goto err_put_clock; + } + + error = input_register_device(input); + if (error) { + dev_err(&pdev->dev, "failed registering input device\n"); + goto err_free_irq; + } + + platform_set_drvdata(pdev, tsc); + device_init_wakeup(&pdev->dev, 1); + + return 0; + +err_free_irq: + free_irq(tsc->irq, tsc); +err_put_clock: + clk_put(tsc->clk); +err_unmap: + iounmap(tsc->tsc_base); +err_release_mem: + release_mem_region(res->start, size); +err_free_mem: + input_free_device(input); + kfree(tsc); + + return error; +} + +static int __devexit lpc32xx_ts_remove(struct platform_device *pdev) +{ + struct lpc32xx_tsc *tsc = platform_get_drvdata(pdev); + struct resource *res; + + device_init_wakeup(&pdev->dev, 0); + free_irq(tsc->irq, tsc); + + input_unregister_device(tsc->dev); + + clk_put(tsc->clk); + + iounmap(tsc->tsc_base); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + + kfree(tsc); + + return 0; +} + +#ifdef CONFIG_PM +static int lpc32xx_ts_suspend(struct device *dev) +{ + struct lpc32xx_tsc *tsc = dev_get_drvdata(dev); + struct input_dev *input = tsc->dev; + + /* + * Suspend and resume can be called when the device hasn't been + * enabled. If there are no users that have the device open, then + * avoid calling the TSC stop and start functions as the TSC + * isn't yet clocked. + */ + mutex_lock(&input->mutex); + + if (input->users) { + if (device_may_wakeup(dev)) + enable_irq_wake(tsc->irq); + else + lpc32xx_stop_tsc(tsc); + } + + mutex_unlock(&input->mutex); + + return 0; +} + +static int lpc32xx_ts_resume(struct device *dev) +{ + struct lpc32xx_tsc *tsc = dev_get_drvdata(dev); + struct input_dev *input = tsc->dev; + + mutex_lock(&input->mutex); + + if (input->users) { + if (device_may_wakeup(dev)) + disable_irq_wake(tsc->irq); + else + lpc32xx_setup_tsc(tsc); + } + + mutex_unlock(&input->mutex); + + return 0; +} + +static const struct dev_pm_ops lpc32xx_ts_pm_ops = { + .suspend = lpc32xx_ts_suspend, + .resume = lpc32xx_ts_resume, +}; +#define LPC32XX_TS_PM_OPS (&lpc32xx_ts_pm_ops) +#else +#define LPC32XX_TS_PM_OPS NULL +#endif + +static struct platform_driver lpc32xx_ts_driver = { + .probe = lpc32xx_ts_probe, + .remove = __devexit_p(lpc32xx_ts_remove), + .driver = { + .name = MOD_NAME, + .owner = THIS_MODULE, + .pm = LPC32XX_TS_PM_OPS, + }, +}; + +static int __init lpc32xx_ts_init(void) +{ + return platform_driver_register(&lpc32xx_ts_driver); +} +module_init(lpc32xx_ts_init); + +static void __exit lpc32xx_ts_exit(void) +{ + platform_driver_unregister(&lpc32xx_ts_driver); +} +module_exit(lpc32xx_ts_exit); + +MODULE_AUTHOR("Kevin Wells Date: Sun, 29 Aug 2010 12:13:15 -0400 Subject: sunrpc: don't shorten buflen twice in xdr_shrink_pagelen On Jan. 14, 2009, 2:50 +0200, andros@netapp.com wrote: > From: Andy Adamson > > The buflen is reset for all cases at the end of xdr_shrink_pagelen. > The data left in the tail after xdr_read_pages is not processed when the > buflen is incorrectly set. Note that in this case we also lose (len - tail->iov_len) bytes from the buffered data in pages. Reported-by: Andy Adamson Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- net/sunrpc/xdr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index a1f82a87d34d..91f0de944d0f 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -407,8 +407,7 @@ xdr_shrink_pagelen(struct xdr_buf *buf, size_t len) if (tail->iov_len > len) { copy = tail->iov_len - len; memmove(p, tail->iov_base, copy); - } else - buf->buflen -= len; + } /* Copy from the inlined pages into the tail */ copy = len; if (copy > tail->iov_len) -- cgit v1.2.3-59-g8ed1b From 0fe62a35903e11fb41b492bd5b0e8e4c751d5c94 Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Sun, 29 Aug 2010 12:13:15 -0400 Subject: sunrpc: clean up xdr_shrink_pagelen use of temporary pointer char *p is used only as a shorthand for tail->iov_base + len in a nested block. Move it there. Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- net/sunrpc/xdr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 91f0de944d0f..41be21f7f7b9 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -395,7 +395,6 @@ xdr_shrink_pagelen(struct xdr_buf *buf, size_t len) { struct kvec *tail; size_t copy; - char *p; unsigned int pglen = buf->page_len; tail = buf->tail; @@ -403,8 +402,8 @@ xdr_shrink_pagelen(struct xdr_buf *buf, size_t len) /* Shift the tail first */ if (tail->iov_len != 0) { - p = (char *)tail->iov_base + len; if (tail->iov_len > len) { + char *p = (char *)tail->iov_base + len; copy = tail->iov_len - len; memmove(p, tail->iov_base, copy); } -- cgit v1.2.3-59-g8ed1b From 2e29ebb8119e6037133921fac09cc5f9d625b511 Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Sun, 29 Aug 2010 12:13:15 -0400 Subject: sunrpc: don't use the copy variable in nested block to clean up the code "copy" will be set prior to the block hence it mustn't be used there. Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- net/sunrpc/xdr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 41be21f7f7b9..42a7ebf2a322 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -404,8 +404,7 @@ xdr_shrink_pagelen(struct xdr_buf *buf, size_t len) if (tail->iov_len != 0) { if (tail->iov_len > len) { char *p = (char *)tail->iov_base + len; - copy = tail->iov_len - len; - memmove(p, tail->iov_base, copy); + memmove(p, tail->iov_base, tail->iov_len - len); } /* Copy from the inlined pages into the tail */ copy = len; -- cgit v1.2.3-59-g8ed1b From 42d6d8ab51ca04afcb8a64759076da624cdb71e8 Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Sun, 29 Aug 2010 12:13:15 -0400 Subject: sunrpc: simplify xdr_shrink_pagelen use of "copy" The "copy" variable value can be computed using the existing logic rather than repeating it. Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- net/sunrpc/xdr.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 42a7ebf2a322..3317db3cb102 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -402,14 +402,13 @@ xdr_shrink_pagelen(struct xdr_buf *buf, size_t len) /* Shift the tail first */ if (tail->iov_len != 0) { + copy = len; if (tail->iov_len > len) { char *p = (char *)tail->iov_base + len; memmove(p, tail->iov_base, tail->iov_len - len); - } - /* Copy from the inlined pages into the tail */ - copy = len; - if (copy > tail->iov_len) + } else copy = tail->iov_len; + /* Copy from the inlined pages into the tail */ _copy_from_pages((char *)tail->iov_base, buf->pages, buf->page_base + pglen - len, copy); -- cgit v1.2.3-59-g8ed1b From cf187c2d7ec763cdd459fe43933a5cc4f5f48e1b Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 29 Aug 2010 12:13:16 -0400 Subject: SUNRPC: Don't truncate tail data unnecessarily in xdr_shrink_pagelen If we have unused buffer space, then we should make use of that rather than unnecessarily truncating the message. Signed-off-by: Trond Myklebust --- net/sunrpc/xdr.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 3317db3cb102..3bbef7f5f826 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -396,12 +396,21 @@ xdr_shrink_pagelen(struct xdr_buf *buf, size_t len) struct kvec *tail; size_t copy; unsigned int pglen = buf->page_len; + unsigned int tailbuf_len; tail = buf->tail; BUG_ON (len > pglen); + tailbuf_len = buf->buflen - buf->head->iov_len - buf->page_len; + /* Shift the tail first */ - if (tail->iov_len != 0) { + if (tailbuf_len != 0) { + unsigned int free_space = tailbuf_len - tail->iov_len; + + if (len < free_space) + free_space = len; + tail->iov_len += free_space; + copy = len; if (tail->iov_len > len) { char *p = (char *)tail->iov_base + len; -- cgit v1.2.3-59-g8ed1b From 59506197c7d0a94088dc15d488d8c964f909a6b1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:23 +0200 Subject: drm: don't export drm_sg_alloc It's not used internally by any driver, only by some generic ioctls. So don't export it. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_scatter.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/drm_scatter.c b/drivers/gpu/drm/drm_scatter.c index 9034c4c6100d..d15e09b0ae0b 100644 --- a/drivers/gpu/drm/drm_scatter.c +++ b/drivers/gpu/drm/drm_scatter.c @@ -184,8 +184,6 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request) drm_sg_cleanup(entry); return -ENOMEM; } -EXPORT_SYMBOL(drm_sg_alloc); - int drm_sg_alloc_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -- cgit v1.2.3-59-g8ed1b From 1da3f87ebb7edb3e0b829ec4bbe5fb3d9d93986f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:24 +0200 Subject: drm: kill kernel_context_switch callbacks Not used by any in-kernel driver. So drop it. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_lock.c | 18 ------------------ include/drm/drmP.h | 3 --- 2 files changed, 21 deletions(-) diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 9bf93bc9a32c..609f2d504f72 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -136,12 +136,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) } } - if (dev->driver->kernel_context_switch && - dev->last_context != lock->context) { - dev->driver->kernel_context_switch(dev, dev->last_context, - lock->context); - } - return 0; } @@ -159,7 +153,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_lock *lock = data; - struct drm_master *master = file_priv->master; if (lock->context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -169,17 +162,6 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); - /* kernel_context_switch isn't used by any of the x86 drm - * modules but is required by the Sparc driver. - */ - if (dev->driver->kernel_context_switch_unlock) - dev->driver->kernel_context_switch_unlock(dev); - else { - if (drm_lock_free(&master->lock, lock->context)) { - /* FIXME: Should really bail out here. */ - } - } - unblock_all_signals(); return 0; } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 7809d230adee..15ea8c44f28d 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -703,9 +703,6 @@ struct drm_driver { int (*dma_quiescent) (struct drm_device *); int (*context_ctor) (struct drm_device *dev, int context); int (*context_dtor) (struct drm_device *dev, int context); - int (*kernel_context_switch) (struct drm_device *dev, int old, - int new); - void (*kernel_context_switch_unlock) (struct drm_device *dev); /** * get_vblank_counter - get raw hardware vblank counter -- cgit v1.2.3-59-g8ed1b From be72ae26b11478c00c64858c86b647b438791671 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:26 +0200 Subject: drm: kill procfs callbacks Not used by any driver (rightly so!). Kill them. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_proc.c | 13 ------------- include/drm/drmP.h | 2 -- 2 files changed, 15 deletions(-) diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c index a9ba6b69ad35..e571de536dc5 100644 --- a/drivers/gpu/drm/drm_proc.c +++ b/drivers/gpu/drm/drm_proc.c @@ -151,7 +151,6 @@ fail: int drm_proc_init(struct drm_minor *minor, int minor_id, struct proc_dir_entry *root) { - struct drm_device *dev = minor->dev; char name[64]; int ret; @@ -172,14 +171,6 @@ int drm_proc_init(struct drm_minor *minor, int minor_id, return ret; } - if (dev->driver->proc_init) { - ret = dev->driver->proc_init(minor); - if (ret) { - DRM_ERROR("DRM: Driver failed to initialize " - "/proc/dri.\n"); - return ret; - } - } return 0; } @@ -216,15 +207,11 @@ int drm_proc_remove_files(struct drm_info_list *files, int count, */ int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) { - struct drm_device *dev = minor->dev; char name[64]; if (!root || !minor->proc_root) return 0; - if (dev->driver->proc_cleanup) - dev->driver->proc_cleanup(minor); - drm_proc_remove_files(drm_proc_list, DRM_PROC_ENTRIES, minor); sprintf(name, "%d", minor->index); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 15ea8c44f28d..0d7af3f39652 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -792,8 +792,6 @@ struct drm_driver { void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv, bool from_release); - int (*proc_init)(struct drm_minor *minor); - void (*proc_cleanup)(struct drm_minor *minor); int (*debugfs_init)(struct drm_minor *minor); void (*debugfs_cleanup)(struct drm_minor *minor); -- cgit v1.2.3-59-g8ed1b From 23ddc0243d7313942b94f1a2e44e6394f7bb996e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:25 +0200 Subject: drm: kill dma_ready callbacks Not used by any driver. So drop it. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_lock.c | 3 --- include/drm/drmP.h | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 609f2d504f72..d9146f240d33 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -124,9 +124,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); } - if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY)) - dev->driver->dma_ready(dev); - if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT)) { if (dev->driver->dma_quiescent(dev)) { diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 0d7af3f39652..d5a2b8869246 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -699,7 +699,6 @@ struct drm_driver { int (*suspend) (struct drm_device *, pm_message_t state); int (*resume) (struct drm_device *); int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv); - void (*dma_ready) (struct drm_device *); int (*dma_quiescent) (struct drm_device *); int (*context_ctor) (struct drm_device *dev, int context); int (*context_dtor) (struct drm_device *dev, int context); -- cgit v1.2.3-59-g8ed1b From fd2e7931cdefa8e9acf63f0a4efd61ae0f89e77b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:33 +0200 Subject: drm: kill gem_free_object_unlocked driver callback Not used by any current driver. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_gem.c | 4 +--- include/drm/drmP.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index bf92d07510df..cff7317d3830 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -474,9 +474,7 @@ drm_gem_object_free_unlocked(struct kref *kref) struct drm_gem_object *obj = (struct drm_gem_object *) kref; struct drm_device *dev = obj->dev; - if (dev->driver->gem_free_object_unlocked != NULL) - dev->driver->gem_free_object_unlocked(obj); - else if (dev->driver->gem_free_object != NULL) { + if (dev->driver->gem_free_object != NULL) { mutex_lock(&dev->struct_mutex); dev->driver->gem_free_object(obj); mutex_unlock(&dev->struct_mutex); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index d5a2b8869246..6dbdbf45cd1a 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -802,7 +802,6 @@ struct drm_driver { */ int (*gem_init_object) (struct drm_gem_object *obj); void (*gem_free_object) (struct drm_gem_object *obj); - void (*gem_free_object_unlocked) (struct drm_gem_object *obj); /* vga arb irq handler */ void (*vgaarb_irq)(struct drm_device *dev, bool state); -- cgit v1.2.3-59-g8ed1b From b3da8f7d2d1fa81fb65cb3f5d9e50dde40a83182 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:29 +0200 Subject: drm: kill context_ctor callback It's not used by any driver. The destructor callback is unfortunately used by the via driver in a rather convoluted piece of code used to reimplement something resembling broken futexes. I didn't dare to touch this code. But at least kill the needless NULL assignemt in the sis driver. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_context.c | 8 -------- drivers/gpu/drm/sis/sis_drv.c | 1 - include/drm/drmP.h | 1 - 3 files changed, 10 deletions(-) diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c index 2607753a320b..6d440fb894cf 100644 --- a/drivers/gpu/drm/drm_context.c +++ b/drivers/gpu/drm/drm_context.c @@ -333,14 +333,6 @@ int drm_addctx(struct drm_device *dev, void *data, return -ENOMEM; } - if (ctx->handle != DRM_KERNEL_CONTEXT) { - if (dev->driver->context_ctor) - if (!dev->driver->context_ctor(dev, ctx->handle)) { - DRM_DEBUG("Running out of ctxs or memory.\n"); - return -ENOMEM; - } - } - ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL); if (!ctx_entry) { DRM_DEBUG("out of memory\n"); diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 776bf9e9ea1a..2d1292131500 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -67,7 +67,6 @@ static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR, .load = sis_driver_load, .unload = sis_driver_unload, - .context_dtor = NULL, .dma_quiescent = sis_idle, .reclaim_buffers = NULL, .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked, diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 6dbdbf45cd1a..eb4f7edcc314 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -700,7 +700,6 @@ struct drm_driver { int (*resume) (struct drm_device *); int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv); int (*dma_quiescent) (struct drm_device *); - int (*context_ctor) (struct drm_device *dev, int context); int (*context_dtor) (struct drm_device *dev, int context); /** -- cgit v1.2.3-59-g8ed1b From a2a273c94357ffd24e635cf9ec9b2e5c6f02b63b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:30 +0200 Subject: drm: don't export drm_get_drawable_info Not used by any in-tree user. So drop it. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_drawable.c | 3 +-- include/drm/drmP.h | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_drawable.c b/drivers/gpu/drm/drm_drawable.c index c53c9768cc11..170e53178d8b 100644 --- a/drivers/gpu/drm/drm_drawable.c +++ b/drivers/gpu/drm/drm_drawable.c @@ -173,11 +173,10 @@ error: /** * Caller must hold the drawable spinlock! */ -struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id) +static struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id) { return idr_find(&dev->drw_idr, id); } -EXPORT_SYMBOL(drm_get_drawable_info); static int drm_drawable_free(int idr, void *p, void *data) { diff --git a/include/drm/drmP.h b/include/drm/drmP.h index eb4f7edcc314..7a5c91c2aa60 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1238,8 +1238,6 @@ extern int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, - drm_drawable_t id); extern void drm_drawable_free_all(struct drm_device *dev); /* Authentication IOCTL support (drm_auth.h) */ -- cgit v1.2.3-59-g8ed1b From 690bb51b54a986e48c7b8b2dba51a3cd262a7266 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:35 +0200 Subject: drm: drop return value of drm_free_agp No caller (rightly) cares about it, so drop it. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_memory.c | 4 ++-- include/drm/drmP.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c index 7732268eced2..70ca27edc3c9 100644 --- a/drivers/gpu/drm/drm_memory.c +++ b/drivers/gpu/drm/drm_memory.c @@ -106,9 +106,9 @@ DRM_AGP_MEM *drm_alloc_agp(struct drm_device * dev, int pages, u32 type) } /** Wrapper around agp_free_memory() */ -int drm_free_agp(DRM_AGP_MEM * handle, int pages) +void drm_free_agp(DRM_AGP_MEM * handle, int pages) { - return drm_agp_free_memory(handle) ? 0 : -EINVAL; + drm_agp_free_memory(handle); } EXPORT_SYMBOL(drm_free_agp); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 7a5c91c2aa60..7fd1870b6a70 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1178,8 +1178,8 @@ extern int drm_mem_info(char *buf, char **start, off_t offset, int request, int *eof, void *data); extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); +extern void drm_free_agp(DRM_AGP_MEM * handle, int pages); extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type); -extern int drm_free_agp(DRM_AGP_MEM * handle, int pages); extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start); extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev, struct page **pages, -- cgit v1.2.3-59-g8ed1b From 793a97e4cc38f834e0488ccc1ecbfe52ff6f5b84 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:27 +0200 Subject: drm: kill drm_map_ofs callbacks All drivers happily copy&pasted the default implementation without checking whether this callback is used at all. It's not. Sigh. Kill it. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_vm.c | 7 ------- drivers/gpu/drm/i810/i810_drv.c | 1 - drivers/gpu/drm/i830/i830_drv.c | 1 - drivers/gpu/drm/i915/i915_drv.c | 1 - drivers/gpu/drm/mga/mga_drv.c | 1 - drivers/gpu/drm/nouveau/nouveau_drv.c | 1 - drivers/gpu/drm/r128/r128_drv.c | 1 - drivers/gpu/drm/radeon/radeon_drv.c | 2 -- drivers/gpu/drm/savage/savage_drv.c | 1 - drivers/gpu/drm/sis/sis_drv.c | 1 - drivers/gpu/drm/tdfx/tdfx_drv.c | 1 - drivers/gpu/drm/via/via_drv.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 - include/drm/drmP.h | 2 -- 14 files changed, 22 deletions(-) diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index fda67468e603..2fea2e63a313 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -515,13 +515,6 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) return 0; } -resource_size_t drm_core_get_map_ofs(struct drm_local_map * map) -{ - return map->offset; -} - -EXPORT_SYMBOL(drm_core_get_map_ofs); - resource_size_t drm_core_get_reg_ofs(struct drm_device *dev) { #ifdef __alpha__ diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index b4250b2cac1f..084a85c3d5d5 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -52,7 +52,6 @@ static struct drm_driver driver = { .device_is_agp = i810_driver_device_is_agp, .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked, .dma_quiescent = i810_driver_dma_quiescent, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = i810_ioctls, .fops = { diff --git a/drivers/gpu/drm/i830/i830_drv.c b/drivers/gpu/drm/i830/i830_drv.c index a5c66aa82f0c..16352954311c 100644 --- a/drivers/gpu/drm/i830/i830_drv.c +++ b/drivers/gpu/drm/i830/i830_drv.c @@ -57,7 +57,6 @@ static struct drm_driver driver = { .device_is_agp = i830_driver_device_is_agp, .reclaim_buffers_locked = i830_driver_reclaim_buffers_locked, .dma_quiescent = i830_driver_dma_quiescent, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, #if USE_IRQS .irq_preinstall = i830_driver_irq_preinstall, diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 00befce8fbb7..d079f7b86cca 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -524,7 +524,6 @@ static struct drm_driver driver = { .irq_uninstall = i915_driver_irq_uninstall, .irq_handler = i915_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .master_create = i915_master_create, .master_destroy = i915_master_destroy, diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index 26d0d8ced80d..e9c0cbc21fe2 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c @@ -60,7 +60,6 @@ static struct drm_driver driver = { .irq_uninstall = mga_driver_irq_uninstall, .irq_handler = mga_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = mga_ioctls, .dma_ioctl = mga_dma_buffers, diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 1de5eb53e016..0d64259b21cc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -379,7 +379,6 @@ static struct drm_driver driver = { .irq_uninstall = nouveau_irq_uninstall, .irq_handler = nouveau_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = nouveau_ioctls, .fops = { diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 1e2971f13aa1..42ec20a10eed 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -56,7 +56,6 @@ static struct drm_driver driver = { .irq_uninstall = r128_driver_irq_uninstall, .irq_handler = r128_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = r128_ioctls, .dma_ioctl = r128_cce_buffers, diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 795403b0e2cd..8fd89bb8e610 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -203,7 +203,6 @@ static struct drm_driver driver_old = { .irq_uninstall = radeon_driver_irq_uninstall, .irq_handler = radeon_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = radeon_ioctls, .dma_ioctl = radeon_cp_buffers, @@ -290,7 +289,6 @@ static struct drm_driver kms_driver = { .irq_uninstall = radeon_driver_irq_uninstall_kms, .irq_handler = radeon_driver_irq_handler_kms, .reclaim_buffers = drm_core_reclaim_buffers, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = radeon_ioctls_kms, .gem_init_object = radeon_gem_object_init, diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index 021de44c15ab..f539996ba230 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -42,7 +42,6 @@ static struct drm_driver driver = { .lastclose = savage_driver_lastclose, .unload = savage_driver_unload, .reclaim_buffers = savage_reclaim_buffers, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = savage_ioctls, .dma_ioctl = savage_bci_buffers, diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 2d1292131500..72b0a74f265f 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -71,7 +71,6 @@ static struct drm_driver driver = { .reclaim_buffers = NULL, .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked, .lastclose = sis_lastclose, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = sis_ioctls, .fops = { diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index ec5a43e65722..38a562647d6f 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -42,7 +42,6 @@ static struct pci_device_id pciidlist[] = { static struct drm_driver driver = { .driver_features = DRIVER_USE_MTRR, .reclaim_buffers = drm_core_reclaim_buffers, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .fops = { .owner = THIS_MODULE, diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index 7a1b210401e0..0b9ad8bbb031 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -51,7 +51,6 @@ static struct drm_driver driver = { .reclaim_buffers_locked = NULL, .reclaim_buffers_idlelocked = via_reclaim_buffers_locked, .lastclose = via_lastclose, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = via_ioctls, .fops = { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 72ec2e2b6e97..4a832de43dd5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -723,7 +723,6 @@ static struct drm_driver driver = { .irq_uninstall = vmw_irq_uninstall, .irq_handler = vmw_irq_handler, .reclaim_buffers_locked = NULL, - .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = vmw_ioctls, .num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls), diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 7fd1870b6a70..70a14a4faa1e 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -772,7 +772,6 @@ struct drm_driver { struct drm_file *file_priv); void (*reclaim_buffers_idlelocked) (struct drm_device *dev, struct drm_file *file_priv); - resource_size_t (*get_map_ofs) (struct drm_local_map * map); resource_size_t (*get_reg_ofs) (struct drm_device *dev); void (*set_version) (struct drm_device *dev, struct drm_set_version *sv); @@ -1167,7 +1166,6 @@ extern int drm_release(struct inode *inode, struct file *filp); extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma); extern void drm_vm_open_locked(struct vm_area_struct *vma); -extern resource_size_t drm_core_get_map_ofs(struct drm_local_map * map); extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev); extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); -- cgit v1.2.3-59-g8ed1b From 4ac5ec40ec70022e4dea8cc6254d2dadd1e43d57 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:34 +0200 Subject: drm: don't export dri1 locking functions Only used by ioctl, not by any in-tree drivers. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_lock.c | 10 +++------- include/drm/drmP.h | 1 - 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index d9146f240d33..1e28b9072068 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -37,6 +37,8 @@ static int drm_notifier(void *priv); +static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context); + /** * Lock ioctl. * @@ -172,6 +174,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) * * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction. */ +static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context) { @@ -208,7 +211,6 @@ int drm_lock_take(struct drm_lock_data *lock_data, } return 0; } -EXPORT_SYMBOL(drm_lock_take); /** * This takes a lock forcibly and hands it to context. Should ONLY be used @@ -276,7 +278,6 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context) wake_up_interruptible(&lock_data->lock_queue); return 0; } -EXPORT_SYMBOL(drm_lock_free); /** * If we get here, it means that the process has called DRM_IOCTL_LOCK @@ -339,7 +340,6 @@ void drm_idlelock_take(struct drm_lock_data *lock_data) } spin_unlock_bh(&lock_data->spinlock); } -EXPORT_SYMBOL(drm_idlelock_take); void drm_idlelock_release(struct drm_lock_data *lock_data) { @@ -359,8 +359,6 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) } spin_unlock_bh(&lock_data->spinlock); } -EXPORT_SYMBOL(drm_idlelock_release); - int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv) { @@ -369,5 +367,3 @@ int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv) _DRM_LOCK_IS_HELD(master->lock.hw_lock->lock) && master->lock.file_priv == file_priv); } - -EXPORT_SYMBOL(drm_i_have_hw_lock); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 70a14a4faa1e..45d09639e9d2 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1252,7 +1252,6 @@ extern int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context); extern int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context); extern void drm_idlelock_take(struct drm_lock_data *lock_data); extern void drm_idlelock_release(struct drm_lock_data *lock_data); -- cgit v1.2.3-59-g8ed1b From 8f879194f88742d9c452f669482b6d6abdc1e1e7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:31 +0200 Subject: drm: replace drawable ioctl by noops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The information supplied by userspace through these ioctls is only accessible by dev->drw_idr. But there's no in-tree user of that. Also userspace does not really care about return values of these ioctls, either. Only hw/xfree86/dri/dri.c from the xserver actually checks the return from adddraw and keeps on trying to create a kernel drawable every time somebody creates a dri drawable. But since that's now a noop, who cares. Therefore it's safe to replace these three ioctls with noops and rip out the implementation. Signed-off-by: Daniel Vetter Reviewed-by: Kristian Høgsberg Reviewed-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_drawable.c | 197 ----------------------------------------- drivers/gpu/drm/drm_drv.c | 8 +- drivers/gpu/drm/drm_stub.c | 3 - include/drm/drmP.h | 15 ---- 5 files changed, 4 insertions(+), 221 deletions(-) delete mode 100644 drivers/gpu/drm/drm_drawable.c diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index f3a23a329f4e..997c43d04909 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -5,7 +5,7 @@ ccflags-y := -Iinclude/drm drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ - drm_context.o drm_dma.o drm_drawable.o \ + drm_context.o drm_dma.o \ drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ diff --git a/drivers/gpu/drm/drm_drawable.c b/drivers/gpu/drm/drm_drawable.c deleted file mode 100644 index 170e53178d8b..000000000000 --- a/drivers/gpu/drm/drm_drawable.c +++ /dev/null @@ -1,197 +0,0 @@ -/** - * \file drm_drawable.c - * IOCTLs for drawables - * - * \author Rickard E. (Rik) Faith - * \author Gareth Hughes - * \author Michel Dänzer - */ - -/* - * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, North Dakota. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" - -/** - * Allocate drawable ID and memory to store information about it. - */ -int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - unsigned long irqflags; - struct drm_draw *draw = data; - int new_id = 0; - int ret; - -again: - if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) { - DRM_ERROR("Out of memory expanding drawable idr\n"); - return -ENOMEM; - } - - spin_lock_irqsave(&dev->drw_lock, irqflags); - ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id); - if (ret == -EAGAIN) { - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - goto again; - } - - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - - draw->handle = new_id; - - DRM_DEBUG("%d\n", draw->handle); - - return 0; -} - -/** - * Free drawable ID and memory to store information about it. - */ -int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_draw *draw = data; - unsigned long irqflags; - struct drm_drawable_info *info; - - spin_lock_irqsave(&dev->drw_lock, irqflags); - - info = drm_get_drawable_info(dev, draw->handle); - if (info == NULL) { - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - return -EINVAL; - } - kfree(info->rects); - kfree(info); - - idr_remove(&dev->drw_idr, draw->handle); - - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - DRM_DEBUG("%d\n", draw->handle); - return 0; -} - -int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_update_draw *update = data; - unsigned long irqflags; - struct drm_clip_rect *rects; - struct drm_drawable_info *info; - int err; - - info = idr_find(&dev->drw_idr, update->handle); - if (!info) { - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - if (IS_ERR(idr_replace(&dev->drw_idr, info, update->handle))) { - DRM_ERROR("No such drawable %d\n", update->handle); - kfree(info); - return -EINVAL; - } - } - - switch (update->type) { - case DRM_DRAWABLE_CLIPRECTS: - if (update->num == 0) - rects = NULL; - else if (update->num != info->num_rects) { - rects = kmalloc(update->num * - sizeof(struct drm_clip_rect), - GFP_KERNEL); - } else - rects = info->rects; - - if (update->num && !rects) { - DRM_ERROR("Failed to allocate cliprect memory\n"); - err = -ENOMEM; - goto error; - } - - if (update->num && DRM_COPY_FROM_USER(rects, - (struct drm_clip_rect __user *) - (unsigned long)update->data, - update->num * - sizeof(*rects))) { - DRM_ERROR("Failed to copy cliprects from userspace\n"); - err = -EFAULT; - goto error; - } - - spin_lock_irqsave(&dev->drw_lock, irqflags); - - if (rects != info->rects) { - kfree(info->rects); - } - - info->rects = rects; - info->num_rects = update->num; - - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - - DRM_DEBUG("Updated %d cliprects for drawable %d\n", - info->num_rects, update->handle); - break; - default: - DRM_ERROR("Invalid update type %d\n", update->type); - return -EINVAL; - } - - return 0; - -error: - if (rects != info->rects) - kfree(rects); - - return err; -} - -/** - * Caller must hold the drawable spinlock! - */ -static struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id) -{ - return idr_find(&dev->drw_idr, id); -} - -static int drm_drawable_free(int idr, void *p, void *data) -{ - struct drm_drawable_info *info = p; - - if (info) { - kfree(info->rects); - kfree(info); - } - - return 0; -} - -void drm_drawable_free_all(struct drm_device *dev) -{ - idr_for_each(&dev->drw_idr, drm_drawable_free, NULL); - idr_remove_all(&dev->drw_idr); -} diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 84da748555bc..a35a41002c33 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -91,8 +91,8 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH), @@ -127,7 +127,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0), - DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED), @@ -180,8 +180,6 @@ int drm_lastclose(struct drm_device * dev) mutex_lock(&dev->struct_mutex); - /* Free drawable information memory */ - drm_drawable_free_all(dev); del_timer(&dev->timer); /* Clear AGP information */ diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index d1ad57450df1..f797ae9da77c 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -240,14 +240,11 @@ int drm_fill_in_dev(struct drm_device *dev, INIT_LIST_HEAD(&dev->vblank_event_list); spin_lock_init(&dev->count_lock); - spin_lock_init(&dev->drw_lock); spin_lock_init(&dev->event_lock); init_timer(&dev->timer); mutex_init(&dev->struct_mutex); mutex_init(&dev->ctxlist_mutex); - idr_init(&dev->drw_idr); - if (drm_ht_create(&dev->map_hash, 12)) { return -ENOMEM; } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 45d09639e9d2..989cefe33c7b 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1037,12 +1037,6 @@ struct drm_device { struct drm_minor *control; /**< Control node for card */ struct drm_minor *primary; /**< render type primary screen head */ - /** \name Drawable information */ - /*@{ */ - spinlock_t drw_lock; - struct idr drw_idr; - /*@} */ - struct drm_mode_config mode_config; /**< Current mode config */ /** \name GEM information */ @@ -1229,15 +1223,6 @@ extern int drm_setsareactx(struct drm_device *dev, void *data, extern int drm_getsareactx(struct drm_device *dev, void *data, struct drm_file *file_priv); - /* Drawable IOCTL support (drm_drawable.h) */ -extern int drm_adddraw(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int drm_rmdraw(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int drm_update_drawable_info(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern void drm_drawable_free_all(struct drm_device *dev); - /* Authentication IOCTL support (drm_auth.h) */ extern int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv); -- cgit v1.2.3-59-g8ed1b From 89c372647d1d698a96e2189ef4312a977b939839 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:36 +0200 Subject: drm: kill agp indirection mess There's no point in jumping through two indirections. So kill one and call the kernels agp functions directly. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_agpsupport.c | 40 ++++------------------------------------ drivers/gpu/drm/drm_memory.c | 12 +++--------- include/drm/drmP.h | 5 ----- 3 files changed, 7 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c index ba38e0147220..252fdb98b73a 100644 --- a/drivers/gpu/drm/drm_agpsupport.c +++ b/drivers/gpu/drm/drm_agpsupport.c @@ -193,7 +193,7 @@ int drm_agp_enable_ioctl(struct drm_device *dev, void *data, * \return zero on success or a negative number on failure. * * Verifies the AGP device is present and has been acquired, allocates the - * memory via alloc_agp() and creates a drm_agp_mem entry for it. + * memory via agp_allocate_memory() and creates a drm_agp_mem entry for it. */ int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request) { @@ -211,7 +211,7 @@ int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request) pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE; type = (u32) request->type; - if (!(memory = drm_alloc_agp(dev, pages, type))) { + if (!(memory = agp_allocate_memory(dev->agp->bridge, pages, type))) { kfree(entry); return -ENOMEM; } @@ -423,38 +423,6 @@ struct drm_agp_head *drm_agp_init(struct drm_device *dev) return head; } -/** Calls agp_allocate_memory() */ -DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data * bridge, - size_t pages, u32 type) -{ - return agp_allocate_memory(bridge, pages, type); -} - -/** Calls agp_free_memory() */ -int drm_agp_free_memory(DRM_AGP_MEM * handle) -{ - if (!handle) - return 0; - agp_free_memory(handle); - return 1; -} - -/** Calls agp_bind_memory() */ -int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start) -{ - if (!handle) - return -EINVAL; - return agp_bind_memory(handle, start); -} - -/** Calls agp_unbind_memory() */ -int drm_agp_unbind_memory(DRM_AGP_MEM * handle) -{ - if (!handle) - return -EINVAL; - return agp_unbind_memory(handle); -} - /** * Binds a collection of pages into AGP memory at the given offset, returning * the AGP memory structure containing them. @@ -474,7 +442,7 @@ drm_agp_bind_pages(struct drm_device *dev, DRM_DEBUG("\n"); - mem = drm_agp_allocate_memory(dev->agp->bridge, num_pages, + mem = agp_allocate_memory(dev->agp->bridge, num_pages, type); if (mem == NULL) { DRM_ERROR("Failed to allocate memory for %ld pages\n", @@ -487,7 +455,7 @@ drm_agp_bind_pages(struct drm_device *dev, mem->page_count = num_pages; mem->is_flushed = true; - ret = drm_agp_bind_memory(mem, gtt_offset / PAGE_SIZE); + ret = agp_bind_memory(mem, gtt_offset / PAGE_SIZE); if (ret != 0) { DRM_ERROR("Failed to bind AGP memory: %d\n", ret); agp_free_memory(mem); diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c index 70ca27edc3c9..c9b805000a11 100644 --- a/drivers/gpu/drm/drm_memory.c +++ b/drivers/gpu/drm/drm_memory.c @@ -99,29 +99,23 @@ static void *agp_remap(unsigned long offset, unsigned long size, return addr; } -/** Wrapper around agp_allocate_memory() */ -DRM_AGP_MEM *drm_alloc_agp(struct drm_device * dev, int pages, u32 type) -{ - return drm_agp_allocate_memory(dev->agp->bridge, pages, type); -} - /** Wrapper around agp_free_memory() */ void drm_free_agp(DRM_AGP_MEM * handle, int pages) { - drm_agp_free_memory(handle); + agp_free_memory(handle); } EXPORT_SYMBOL(drm_free_agp); /** Wrapper around agp_bind_memory() */ int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start) { - return drm_agp_bind_memory(handle, start); + return agp_bind_memory(handle, start); } /** Wrapper around agp_unbind_memory() */ int drm_unbind_agp(DRM_AGP_MEM * handle) { - return drm_agp_unbind_memory(handle); + return agp_unbind_memory(handle); } EXPORT_SYMBOL(drm_unbind_agp); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 989cefe33c7b..ffe6035cf471 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1171,7 +1171,6 @@ extern int drm_mem_info(char *buf, char **start, off_t offset, extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); extern void drm_free_agp(DRM_AGP_MEM * handle, int pages); -extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type); extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start); extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev, struct page **pages, @@ -1331,10 +1330,6 @@ extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data, extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request); extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type); -extern int drm_agp_free_memory(DRM_AGP_MEM * handle); -extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start); -extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle); extern void drm_agp_chipset_flush(struct drm_device *dev); /* Stub support (drm_stub.h) */ -- cgit v1.2.3-59-g8ed1b From df8fcb09667c1b2c9dcf65de23f0bfa851e8138e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:32 +0200 Subject: drm: kill dev->timer Totally unused. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_drv.c | 2 -- drivers/gpu/drm/drm_stub.c | 1 - include/drm/drmP.h | 1 - 3 files changed, 4 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index a35a41002c33..5ff75a3a6b9d 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -180,8 +180,6 @@ int drm_lastclose(struct drm_device * dev) mutex_lock(&dev->struct_mutex); - del_timer(&dev->timer); - /* Clear AGP information */ if (drm_core_has_AGP(dev) && dev->agp && !drm_core_check_feature(dev, DRIVER_MODESET)) { diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index f797ae9da77c..cdc89ee042cc 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -241,7 +241,6 @@ int drm_fill_in_dev(struct drm_device *dev, spin_lock_init(&dev->count_lock); spin_lock_init(&dev->event_lock); - init_timer(&dev->timer); mutex_init(&dev->struct_mutex); mutex_init(&dev->ctxlist_mutex); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index ffe6035cf471..757b63a23b14 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -964,7 +964,6 @@ struct drm_device { __volatile__ long context_flag; /**< Context swapping flag */ __volatile__ long interrupt_flag; /**< Interruption handler flag */ __volatile__ long dma_flag; /**< DMA dispatch flag */ - struct timer_list timer; /**< Timer for delaying ctx switch */ wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */ int last_checked; /**< Last context checked for DMA */ int last_context; /**< Last current context */ -- cgit v1.2.3-59-g8ed1b From cbc60ca04b342a4e1f2a1086a7277c077f07dbed Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 23 Aug 2010 22:53:28 +0200 Subject: drm: kill get_reg_ofs callback Every driver used the default implementation. Fold that one into the only callsite and drop the callback. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_vm.c | 6 ++---- drivers/gpu/drm/i810/i810_drv.c | 1 - drivers/gpu/drm/i830/i830_drv.c | 1 - drivers/gpu/drm/i915/i915_drv.c | 1 - drivers/gpu/drm/mga/mga_drv.c | 1 - drivers/gpu/drm/nouveau/nouveau_drv.c | 1 - drivers/gpu/drm/r128/r128_drv.c | 1 - drivers/gpu/drm/radeon/radeon_drv.c | 2 -- drivers/gpu/drm/savage/savage_drv.c | 1 - drivers/gpu/drm/sis/sis_drv.c | 1 - drivers/gpu/drm/tdfx/tdfx_drv.c | 1 - drivers/gpu/drm/via/via_drv.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 - include/drm/drmP.h | 2 -- 14 files changed, 2 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 2fea2e63a313..ee879d6bb522 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -515,7 +515,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) return 0; } -resource_size_t drm_core_get_reg_ofs(struct drm_device *dev) +static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev) { #ifdef __alpha__ return dev->hose->dense_mem_base - dev->hose->mem_space->start; @@ -524,8 +524,6 @@ resource_size_t drm_core_get_reg_ofs(struct drm_device *dev) #endif } -EXPORT_SYMBOL(drm_core_get_reg_ofs); - /** * mmap DMA memory. * @@ -612,7 +610,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) #endif case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: - offset = dev->driver->get_reg_ofs(dev); + offset = drm_core_get_reg_ofs(dev); vma->vm_flags |= VM_IO; /* not in core dump */ vma->vm_page_prot = drm_io_prot(map->type, vma); #if !defined(__arm__) diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index 084a85c3d5d5..1c73b0c43c1e 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -52,7 +52,6 @@ static struct drm_driver driver = { .device_is_agp = i810_driver_device_is_agp, .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked, .dma_quiescent = i810_driver_dma_quiescent, - .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = i810_ioctls, .fops = { .owner = THIS_MODULE, diff --git a/drivers/gpu/drm/i830/i830_drv.c b/drivers/gpu/drm/i830/i830_drv.c index 16352954311c..7140ffc12eee 100644 --- a/drivers/gpu/drm/i830/i830_drv.c +++ b/drivers/gpu/drm/i830/i830_drv.c @@ -57,7 +57,6 @@ static struct drm_driver driver = { .device_is_agp = i830_driver_device_is_agp, .reclaim_buffers_locked = i830_driver_reclaim_buffers_locked, .dma_quiescent = i830_driver_dma_quiescent, - .get_reg_ofs = drm_core_get_reg_ofs, #if USE_IRQS .irq_preinstall = i830_driver_irq_preinstall, .irq_postinstall = i830_driver_irq_postinstall, diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index d079f7b86cca..e6afa68775b0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -524,7 +524,6 @@ static struct drm_driver driver = { .irq_uninstall = i915_driver_irq_uninstall, .irq_handler = i915_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, - .get_reg_ofs = drm_core_get_reg_ofs, .master_create = i915_master_create, .master_destroy = i915_master_destroy, #if defined(CONFIG_DEBUG_FS) diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index e9c0cbc21fe2..65ea42cf1795 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c @@ -60,7 +60,6 @@ static struct drm_driver driver = { .irq_uninstall = mga_driver_irq_uninstall, .irq_handler = mga_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, - .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = mga_ioctls, .dma_ioctl = mga_dma_buffers, .fops = { diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 0d64259b21cc..209912a1b7a5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -379,7 +379,6 @@ static struct drm_driver driver = { .irq_uninstall = nouveau_irq_uninstall, .irq_handler = nouveau_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, - .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = nouveau_ioctls, .fops = { .owner = THIS_MODULE, diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 42ec20a10eed..67309f84f16d 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -56,7 +56,6 @@ static struct drm_driver driver = { .irq_uninstall = r128_driver_irq_uninstall, .irq_handler = r128_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, - .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = r128_ioctls, .dma_ioctl = r128_cce_buffers, .fops = { diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 8fd89bb8e610..663cdc10a5c2 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -203,7 +203,6 @@ static struct drm_driver driver_old = { .irq_uninstall = radeon_driver_irq_uninstall, .irq_handler = radeon_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, - .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = radeon_ioctls, .dma_ioctl = radeon_cp_buffers, .fops = { @@ -289,7 +288,6 @@ static struct drm_driver kms_driver = { .irq_uninstall = radeon_driver_irq_uninstall_kms, .irq_handler = radeon_driver_irq_handler_kms, .reclaim_buffers = drm_core_reclaim_buffers, - .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = radeon_ioctls_kms, .gem_init_object = radeon_gem_object_init, .gem_free_object = radeon_gem_object_free, diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index f539996ba230..c0385633667d 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -42,7 +42,6 @@ static struct drm_driver driver = { .lastclose = savage_driver_lastclose, .unload = savage_driver_unload, .reclaim_buffers = savage_reclaim_buffers, - .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = savage_ioctls, .dma_ioctl = savage_bci_buffers, .fops = { diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 72b0a74f265f..4d9f311d249d 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -71,7 +71,6 @@ static struct drm_driver driver = { .reclaim_buffers = NULL, .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked, .lastclose = sis_lastclose, - .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = sis_ioctls, .fops = { .owner = THIS_MODULE, diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index 38a562647d6f..e0768adbeccd 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -42,7 +42,6 @@ static struct pci_device_id pciidlist[] = { static struct drm_driver driver = { .driver_features = DRIVER_USE_MTRR, .reclaim_buffers = drm_core_reclaim_buffers, - .get_reg_ofs = drm_core_get_reg_ofs, .fops = { .owner = THIS_MODULE, .open = drm_open, diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index 0b9ad8bbb031..02f733db61c1 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -51,7 +51,6 @@ static struct drm_driver driver = { .reclaim_buffers_locked = NULL, .reclaim_buffers_idlelocked = via_reclaim_buffers_locked, .lastclose = via_lastclose, - .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = via_ioctls, .fops = { .owner = THIS_MODULE, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 4a832de43dd5..e645f44e4302 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -723,7 +723,6 @@ static struct drm_driver driver = { .irq_uninstall = vmw_irq_uninstall, .irq_handler = vmw_irq_handler, .reclaim_buffers_locked = NULL, - .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = vmw_ioctls, .num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls), .dma_quiescent = NULL, /*vmw_dma_quiescent, */ diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 757b63a23b14..30e827aeba02 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -772,7 +772,6 @@ struct drm_driver { struct drm_file *file_priv); void (*reclaim_buffers_idlelocked) (struct drm_device *dev, struct drm_file *file_priv); - resource_size_t (*get_reg_ofs) (struct drm_device *dev); void (*set_version) (struct drm_device *dev, struct drm_set_version *sv); @@ -1159,7 +1158,6 @@ extern int drm_release(struct inode *inode, struct file *filp); extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma); extern void drm_vm_open_locked(struct vm_area_struct *vma); -extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev); extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); /* Memory management support (drm_memory.h) */ -- cgit v1.2.3-59-g8ed1b From 2c70b5196262f29b10eb1886293e0c2d75dc3dd9 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 29 Aug 2010 17:04:53 +0000 Subject: IPVS: include net/ip6_checksum.h for csum_ipv6_magic Fixes this build error: net/netfilter/ipvs/ip_vs_core.c: In function 'ip_vs_nat_icmp_v6': net/netfilter/ipvs/ip_vs_core.c:640: error: implicit declaration of function 'csum_ipv6_magic' Signed-off-by: Stephen Rothwell Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/netfilter/ipvs/ip_vs_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 69661db420d7..edbfb96b935e 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -40,6 +40,7 @@ #include #include /* for icmp_send */ #include +#include #include #include -- cgit v1.2.3-59-g8ed1b From 409456b10f87b28303643fec37543103f9ada00c Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Sun, 29 Aug 2010 21:57:55 -0700 Subject: net: fix datapath typo Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- include/linux/if.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/if.h b/include/linux/if.h index 6ed43c1f07ab..123959927745 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -76,7 +76,7 @@ #define IFF_MACVLAN_PORT 0x4000 /* device used as macvlan port */ #define IFF_BRIDGE_PORT 0x8000 /* device used as bridge port */ #define IFF_OVS_DATAPATH 0x10000 /* device used as Open vSwitch - * dapath port */ + * datapath port */ #define IF_GET_IFACE 0x0001 /* for querying only */ #define IF_GET_PROTO 0x0002 -- cgit v1.2.3-59-g8ed1b From 5ffef88ffeb730e1bf2da56a39a55e03d57a66c9 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 4 Aug 2010 10:14:47 +0300 Subject: UBIFS: switch to RO mode after synchronizing In 'ubifs_garbage_collect()' on error path, we first switch to R/O mode, and then synchronize write-buffers (to make sure no data are lost). But the GC write-buffer synchronization will fail, because we are already in R/O mode. This patch re-orders this and makes sure we first synchronize the write-buffer, and then switch to R/O mode. Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 918d1582ca05..f89a422ca395 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -774,8 +774,8 @@ out_unlock: out: ubifs_assert(ret < 0); ubifs_assert(ret != -ENOSPC && ret != -EAGAIN); - ubifs_ro_mode(c, ret); ubifs_wbuf_sync_nolock(wbuf); + ubifs_ro_mode(c, ret); mutex_unlock(&wbuf->io_mutex); ubifs_return_leb(c, lp.lnum); return ret; -- cgit v1.2.3-59-g8ed1b From efe1881f5482f94f5e5e6cb74bf3ea72f2b5b9ce Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 4 Aug 2010 14:06:06 +0300 Subject: UBIFS: do not treat ENOSPC specially 'ubifs_garbage_collect_leb()' should never return '-ENOSPC', and if it does, this is an error. Thus, do not treat this error code specially. '-EAGAIN' is a special error code, but not '-ENOSPC'. Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index f89a422ca395..ee4b05de4d48 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -677,14 +677,12 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway) ret = ubifs_garbage_collect_leb(c, &lp); if (ret < 0) { - if (ret == -EAGAIN || ret == -ENOSPC) { + if (ret == -EAGAIN) { /* - * These codes are not errors, so we have to - * return the LEB to lprops. But if the - * 'ubifs_return_leb()' function fails, its - * failure code is propagated to the caller - * instead of the original '-EAGAIN' or - * '-ENOSPC'. + * This is not error, so we have to return the + * LEB to lprops. But if 'ubifs_return_leb()' + * fails, its failure code is propagated to the + * caller instead of the original '-EAGAIN'. */ err = ubifs_return_leb(c, lp.lnum); if (err) -- cgit v1.2.3-59-g8ed1b From e3408ad4cbed6ec6990efad4c2ef0856bcd3c712 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 4 Aug 2010 13:50:51 +0300 Subject: UBIFS: fix assertion warning This patch fixes the following false assertion warning: UBIFS assert failed in data_nodes_cmp at 130 (pid 15107) The assertion was wrong because it did not take into account that the node can be an xentry. Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index ee4b05de4d48..98b2c3c8725a 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -178,7 +178,8 @@ int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) if (typeb == UBIFS_INO_KEY) return 1; - ubifs_assert(typea == UBIFS_DENT_KEY && typeb == UBIFS_DENT_KEY); + ubifs_assert(typea == UBIFS_DENT_KEY || typea == UBIFS_XENT_KEY); + ubifs_assert(typeb == UBIFS_DENT_KEY || typeb == UBIFS_XENT_KEY); inuma = key_inum(c, &sa->key); inumb = key_inum(c, &sb->key); -- cgit v1.2.3-59-g8ed1b From 44ec83b8bd05d323998031f141c310127721acae Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sat, 7 Aug 2010 08:44:13 +0300 Subject: UBIFS: do not look up truncation nodes When moving nodes in GC, do not try to look up truncation nodes in TNC, because they do not exist there. This would be harmless, because the TNC look-up would fail, if we did not have bug 'ubifs_add_snod()' which reads garbage into 'snod->key'. But in any case, it is less error prone to explicitly ignore everything but inode, data, dentry and xentry nodes. Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 98b2c3c8725a..9dbbc5c88940 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -233,9 +233,26 @@ static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb, list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { int err; - ubifs_assert(snod->type != UBIFS_IDX_NODE); - ubifs_assert(snod->type != UBIFS_REF_NODE); - ubifs_assert(snod->type != UBIFS_CS_NODE); + ubifs_assert(snod->type == UBIFS_INO_NODE || + snod->type == UBIFS_DATA_NODE || + snod->type == UBIFS_DENT_NODE || + snod->type == UBIFS_XENT_NODE || + snod->type == UBIFS_TRUN_NODE); + + if (snod->type != UBIFS_INO_NODE && + snod->type != UBIFS_DATA_NODE && + snod->type != UBIFS_DENT_NODE && + snod->type != UBIFS_XENT_NODE) { + /* Probably truncation node, zap it */ + list_del(&snod->list); + kfree(snod); + continue; + } + + ubifs_assert(key_type(c, &snod->key) == UBIFS_DATA_KEY || + key_type(c, &snod->key) == UBIFS_INO_KEY || + key_type(c, &snod->key) == UBIFS_DENT_KEY || + key_type(c, &snod->key) == UBIFS_XENT_KEY); err = ubifs_tnc_has_node(c, &snod->key, 0, sleb->lnum, snod->offs, 0); -- cgit v1.2.3-59-g8ed1b From ab87118d717467cbcd9648692c2a9708d55193bc Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 8 Aug 2010 12:25:33 +0300 Subject: UBIFS: do not use key type in list_sort In comparison function for 'list_sort()' we use key type to distinguish between node types. However, we have a bit simper way to detect node type - 'snod->type'. This more logical to use, comparing to decoding key types. Also allows to get rid of 2 local variables. Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 9dbbc5c88940..27815bb91125 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -157,7 +157,6 @@ int data_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) */ int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) { - int typea, typeb; ino_t inuma, inumb; struct ubifs_info *c = priv; struct ubifs_scan_node *sa, *sb; @@ -165,21 +164,22 @@ int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) cond_resched(); sa = list_entry(a, struct ubifs_scan_node, list); sb = list_entry(b, struct ubifs_scan_node, list); - typea = key_type(c, &sa->key); - typeb = key_type(c, &sb->key); - ubifs_assert(typea != UBIFS_DATA_KEY && typeb != UBIFS_DATA_KEY); + ubifs_assert(sa->type != UBIFS_DATA_NODE && + sb->type != UBIFS_DATA_NODE); /* Inodes go before directory entries */ - if (typea == UBIFS_INO_KEY) { - if (typeb == UBIFS_INO_KEY) + if (sa->type == UBIFS_INO_NODE) { + if (sb->type == UBIFS_INO_NODE) return sb->len - sa->len; return -1; } - if (typeb == UBIFS_INO_KEY) + if (sb->type == UBIFS_INO_NODE) return 1; - ubifs_assert(typea == UBIFS_DENT_KEY || typea == UBIFS_XENT_KEY); - ubifs_assert(typeb == UBIFS_DENT_KEY || typeb == UBIFS_XENT_KEY); + ubifs_assert(sa->type == UBIFS_DENT_NODE || + sa->type == UBIFS_XENT_NODE); + ubifs_assert(sb->type == UBIFS_DENT_NODE || + sb->type == UBIFS_XENT_NODE); inuma = key_inum(c, &sa->key); inumb = key_inum(c, &sb->key); -- cgit v1.2.3-59-g8ed1b From 66576833f5396af34c52160b16d7b8573199282a Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 8 Aug 2010 12:29:58 +0300 Subject: UBIFS: improve assertion in node comparison functions Improve assertions in gc.c in the comparison functions for 'list_sort()': check key types _and_ node types. Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 27815bb91125..dafef3d195d3 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -127,8 +127,11 @@ int data_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) cond_resched(); sa = list_entry(a, struct ubifs_scan_node, list); sb = list_entry(b, struct ubifs_scan_node, list); + ubifs_assert(key_type(c, &sa->key) == UBIFS_DATA_KEY); ubifs_assert(key_type(c, &sb->key) == UBIFS_DATA_KEY); + ubifs_assert(sa->type == UBIFS_DATA_NODE); + ubifs_assert(sb->type == UBIFS_DATA_NODE); inuma = key_inum(c, &sa->key); inumb = key_inum(c, &sb->key); @@ -164,6 +167,9 @@ int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) cond_resched(); sa = list_entry(a, struct ubifs_scan_node, list); sb = list_entry(b, struct ubifs_scan_node, list); + + ubifs_assert(key_type(c, &sa->key) != UBIFS_DATA_KEY && + key_type(c, &sb->key) != UBIFS_DATA_KEY); ubifs_assert(sa->type != UBIFS_DATA_NODE && sb->type != UBIFS_DATA_NODE); @@ -176,10 +182,15 @@ int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) if (sb->type == UBIFS_INO_NODE) return 1; + ubifs_assert(key_type(c, &sa->key) == UBIFS_DENT_KEY || + key_type(c, &sa->key) == UBIFS_XENT_KEY); + ubifs_assert(key_type(c, &sb->key) == UBIFS_DENT_KEY || + key_type(c, &sb->key) == UBIFS_XENT_KEY); ubifs_assert(sa->type == UBIFS_DENT_NODE || sa->type == UBIFS_XENT_NODE); ubifs_assert(sb->type == UBIFS_DENT_NODE || sb->type == UBIFS_XENT_NODE); + inuma = key_inum(c, &sa->key); inumb = key_inum(c, &sb->key); -- cgit v1.2.3-59-g8ed1b From 5b7a3a2e1b0cbc7d5410a8da60dac266a3e19268 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 8 Aug 2010 12:32:00 +0300 Subject: UBIFS: do not write rubbish into truncation scanning node In the scanning code, in 'ubifs_add_snod()', we write rubbish into 'snod->key', because we assume that on-flash truncation nodes have a key, but they do not. If the other parts of UBIFS then mistakenly try to look-up the truncation node key (they should not do this, but may do because of a bug), we can succeed and corrupt TNC. It looks like we did have such a situation in 'sort_nodes()' in gc.c. Signed-off-by: Artem Bityutskiy --- fs/ubifs/scan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c index 96c525384191..a0a305ca61af 100644 --- a/fs/ubifs/scan.c +++ b/fs/ubifs/scan.c @@ -212,7 +212,6 @@ int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb, case UBIFS_DENT_NODE: case UBIFS_XENT_NODE: case UBIFS_DATA_NODE: - case UBIFS_TRUN_NODE: /* * The key is in the same place in all keyed * nodes. -- cgit v1.2.3-59-g8ed1b From ba2f48f70efcf4d82deafb2be327ed64b1f043a5 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 22 Aug 2010 07:10:12 +0300 Subject: UBIFS: mark unused key objects as invalid When scanning the flash, UBIFS builds a list of flash nodes of type 'struct ubifs_scan_node'. Each scanned node has a 'snod->key' field. This field is valid for most of the nodes, but invalid for some node type, e.g., truncation nodes. It is safer to explicitly initialize such keys to something invalid, rather than leaving them initialized to all zeros, which has key type of UBIFS_INO_KEY. This patch introduces new "fake" key type UBIFS_INVALID_KEY and initializes unused 'snod->key' objects to this type. It also adds debugging assertions in the TNC code to make sure no one ever tries to look these nodes up in the TNC. Signed-off-by: Artem Bityutskiy --- fs/ubifs/key.h | 14 ++++++++++++++ fs/ubifs/scan.c | 5 ++++- fs/ubifs/tnc.c | 5 ++++- fs/ubifs/ubifs.h | 6 +++++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h index 0f530c684f0b..92a8491a8f8c 100644 --- a/fs/ubifs/key.h +++ b/fs/ubifs/key.h @@ -305,6 +305,20 @@ static inline void trun_key_init(const struct ubifs_info *c, key->u32[1] = UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS; } +/** + * invalid_key_init - initialize invalid node key. + * @c: UBIFS file-system description object + * @key: key to initialize + * + * This is a helper function which marks a @key object as invalid. + */ +static inline void invalid_key_init(const struct ubifs_info *c, + union ubifs_key *key) +{ + key->u32[0] = 0xDEADBEAF; + key->u32[1] = UBIFS_INVALID_KEY; +} + /** * key_type - get key type. * @c: UBIFS file-system description object diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c index a0a305ca61af..3e1ee57dbeaa 100644 --- a/fs/ubifs/scan.c +++ b/fs/ubifs/scan.c @@ -197,7 +197,7 @@ int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb, struct ubifs_ino_node *ino = buf; struct ubifs_scan_node *snod; - snod = kzalloc(sizeof(struct ubifs_scan_node), GFP_NOFS); + snod = kmalloc(sizeof(struct ubifs_scan_node), GFP_NOFS); if (!snod) return -ENOMEM; @@ -218,6 +218,9 @@ int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb, */ key_read(c, &ino->key, &snod->key); break; + default: + invalid_key_init(c, &snod->key); + break; } list_add_tail(&snod->list, &sleb->nodes); sleb->nodes_cnt += 1; diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 2194915220e5..ad9cf0133622 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -1177,6 +1177,7 @@ int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key, unsigned long time = get_seconds(); dbg_tnc("search key %s", DBGKEY(key)); + ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY); znode = c->zroot.znode; if (unlikely(!znode)) { @@ -2966,7 +2967,7 @@ static struct ubifs_znode *right_znode(struct ubifs_info *c, * * This function searches an indexing node by its first key @key and its * address @lnum:@offs. It looks up the indexing tree by pulling all indexing - * nodes it traverses to TNC. This function is called fro indexing nodes which + * nodes it traverses to TNC. This function is called for indexing nodes which * were found on the media by scanning, for example when garbage-collecting or * when doing in-the-gaps commit. This means that the indexing node which is * looked for does not have to have exactly the same leftmost key @key, because @@ -2988,6 +2989,8 @@ static struct ubifs_znode *lookup_znode(struct ubifs_info *c, struct ubifs_znode *znode, *zn; int n, nn; + ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY); + /* * The arguments have probably been read off flash, so don't assume * they are valid. diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 0c9876b396dd..c4dc9b18f73e 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -119,8 +119,12 @@ * in TNC. However, when replaying, it is handy to introduce fake "truncation" * keys for truncation nodes because the code becomes simpler. So we define * %UBIFS_TRUN_KEY type. + * + * But otherwise, out of the journal reply scope, the truncation keys are + * invalid. */ -#define UBIFS_TRUN_KEY UBIFS_KEY_TYPES_CNT +#define UBIFS_TRUN_KEY UBIFS_KEY_TYPES_CNT +#define UBIFS_INVALID_KEY UBIFS_KEY_TYPES_CNT /* * How much a directory entry/extended attribute entry adds to the parent/host -- cgit v1.2.3-59-g8ed1b From 1a9476a77083354005750c9df45ba9d71ad12c8c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 8 Aug 2010 12:45:23 +0300 Subject: UBIFS: fix assertion warnings in comparison function When running the integrity test ('integck' from mtd-utils) on current UBIFS on 2.6.35, I see that assertions in UBIFS 'list_sort()' comparison functions trigger sometimes, e.g.: UBIFS assert failed in data_nodes_cmp at 132 (pid 28311) My investigation showed that this happens when 'list_sort()' calls the 'cmp()' function with equivalent arguments. In this case, the 'struct list_head' parameter, passed to 'cmp()' is bogus, and it does not belong to any element in the original list. And this issue seems to be introduced by commit: commit 835cc0c8477fdbc59e0217891d6f11061b1ac4e2 Author: Don Mullis Date: Fri Mar 5 13:43:15 2010 -0800 It is easy to work around the issue by doing: if (a == b) return 0; in UBIFS. It works, but 'lib_sort()' should nevertheless be fixed. Although it is harmless to have this piece of code in UBIFS. This patch adds that code to both UBIFS 'cmp()' functions: 'data_nodes_cmp()' and 'nondata_nodes_cmp()'. Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index dafef3d195d3..4fc31ca0e3b1 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -125,6 +125,9 @@ int data_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) struct ubifs_scan_node *sa, *sb; cond_resched(); + if (a == b) + return 0; + sa = list_entry(a, struct ubifs_scan_node, list); sb = list_entry(b, struct ubifs_scan_node, list); @@ -165,6 +168,9 @@ int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) struct ubifs_scan_node *sa, *sb; cond_resched(); + if (a == b) + return 0; + sa = list_entry(a, struct ubifs_scan_node, list); sb = list_entry(b, struct ubifs_scan_node, list); -- cgit v1.2.3-59-g8ed1b From 3bb66b47a4268a4419594b4c4aec58dbeb6b58d2 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sat, 7 Aug 2010 10:06:11 +0300 Subject: UBIFS: introduce list sorting debugging checks The UBIFS bug in the GC list sorting comparison functions inspired me to write internal debugging check functions which verify that the list of nodes is sorted properly. So, this patch implements 2 new debugging functions: o 'dbg_check_data_nodes_order()' - check order of data nodes list o 'dbg_check_nondata_nodes_order()' - check order of non-data nodes list The debugging functions are executed only if general UBIFS debugging checks are enabled. And they are compiled out if UBIFS debugging is disabled. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ubifs/debug.h | 4 ++ fs/ubifs/gc.c | 10 +++- 3 files changed, 168 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index c2a68baa782f..c664f10aec6c 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2239,6 +2239,162 @@ out_free: return err; } +/** + * dbg_check_data_nodes_order - check that list of data nodes is sorted. + * @c: UBIFS file-system description object + * @head: the list of nodes ('struct ubifs_scan_node' objects) + * + * This function returns zero if the list of data nodes is sorted correctly, + * and %-EINVAL if not. + */ +int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head) +{ + struct list_head *cur; + struct ubifs_scan_node *sa, *sb; + + if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) + return 0; + + for (cur = head->next; cur->next != head; cur = cur->next) { + ino_t inuma, inumb; + uint32_t blka, blkb; + + cond_resched(); + sa = container_of(cur, struct ubifs_scan_node, list); + sb = container_of(cur->next, struct ubifs_scan_node, list); + + if (sa->type != UBIFS_DATA_NODE) { + ubifs_err("bad node type %d", sa->type); + dbg_dump_node(c, sa->node); + return -EINVAL; + } + if (sb->type != UBIFS_DATA_NODE) { + ubifs_err("bad node type %d", sb->type); + dbg_dump_node(c, sb->node); + return -EINVAL; + } + + inuma = key_inum(c, &sa->key); + inumb = key_inum(c, &sb->key); + + if (inuma < inumb) + continue; + if (inuma > inumb) { + ubifs_err("larger inum %lu goes before inum %lu", + (unsigned long)inuma, (unsigned long)inumb); + goto error_dump; + } + + blka = key_block(c, &sa->key); + blkb = key_block(c, &sb->key); + + if (blka > blkb) { + ubifs_err("larger block %u goes before %u", blka, blkb); + goto error_dump; + } + if (blka == blkb) { + ubifs_err("two data nodes for the same block"); + goto error_dump; + } + } + + return 0; + +error_dump: + dbg_dump_node(c, sa->node); + dbg_dump_node(c, sb->node); + return -EINVAL; +} + +/** + * dbg_check_nondata_nodes_order - check that list of data nodes is sorted. + * @c: UBIFS file-system description object + * @head: the list of nodes ('struct ubifs_scan_node' objects) + * + * This function returns zero if the list of non-data nodes is sorted correctly, + * and %-EINVAL if not. + */ +int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head) +{ + struct list_head *cur; + struct ubifs_scan_node *sa, *sb; + + if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) + return 0; + + for (cur = head->next; cur->next != head; cur = cur->next) { + ino_t inuma, inumb; + uint32_t hasha, hashb; + + cond_resched(); + sa = container_of(cur, struct ubifs_scan_node, list); + sb = container_of(cur->next, struct ubifs_scan_node, list); + + if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE && + sa->type != UBIFS_XENT_NODE) { + ubifs_err("bad node type %d", sa->type); + dbg_dump_node(c, sa->node); + return -EINVAL; + } + if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE && + sa->type != UBIFS_XENT_NODE) { + ubifs_err("bad node type %d", sb->type); + dbg_dump_node(c, sb->node); + return -EINVAL; + } + + if (sa->type != UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) { + ubifs_err("non-inode node goes before inode node"); + goto error_dump; + } + + if (sa->type == UBIFS_INO_NODE && sb->type != UBIFS_INO_NODE) + continue; + + if (sa->type == UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) { + /* Inode nodes are sorted in descending size order */ + if (sa->len < sb->len) { + ubifs_err("smaller inode node goes first"); + goto error_dump; + } + continue; + } + + /* + * This is either a dentry or xentry, which should be sorted in + * ascending (parent ino, hash) order. + */ + inuma = key_inum(c, &sa->key); + inumb = key_inum(c, &sb->key); + + if (inuma < inumb) + continue; + if (inuma > inumb) { + ubifs_err("larger inum %lu goes before inum %lu", + (unsigned long)inuma, (unsigned long)inumb); + goto error_dump; + } + + hasha = key_block(c, &sa->key); + hashb = key_block(c, &sb->key); + + if (hasha > hashb) { + ubifs_err("larger hash %u goes before %u", hasha, hashb); + goto error_dump; + } + } + + return 0; + +error_dump: + ubifs_msg("dumping first node"); + dbg_dump_node(c, sa->node); + ubifs_msg("dumping second node"); + dbg_dump_node(c, sb->node); + return -EINVAL; + return 0; +} + static int invocation_cnt; int dbg_force_in_the_gaps(void) diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 29d960101ea6..69ebe4729151 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h @@ -324,6 +324,8 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode, int row, int col); int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode, loff_t size); +int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head); +int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head); /* Force the use of in-the-gaps method for testing */ @@ -465,6 +467,8 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c); #define dbg_check_lprops(c) 0 #define dbg_check_lpt_nodes(c, cnode, row, col) 0 #define dbg_check_inode_size(c, inode, size) 0 +#define dbg_check_data_nodes_order(c, head) 0 +#define dbg_check_nondata_nodes_order(c, head) 0 #define dbg_force_in_the_gaps_enabled 0 #define dbg_force_in_the_gaps() 0 #define dbg_failure_mode 0 diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 4fc31ca0e3b1..396f24a30af9 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -242,14 +242,13 @@ int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb, struct list_head *nondata, int *min) { + int err; struct ubifs_scan_node *snod, *tmp; *min = INT_MAX; /* Separate data nodes and non-data nodes */ list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { - int err; - ubifs_assert(snod->type == UBIFS_INO_NODE || snod->type == UBIFS_DATA_NODE || snod->type == UBIFS_DENT_NODE || @@ -293,6 +292,13 @@ static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb, /* Sort data and non-data nodes */ list_sort(c, &sleb->nodes, &data_nodes_cmp); list_sort(c, nondata, &nondata_nodes_cmp); + + err = dbg_check_data_nodes_order(c, &sleb->nodes); + if (err) + return err; + err = dbg_check_nondata_nodes_order(c, nondata); + if (err) + return err; return 0; } -- cgit v1.2.3-59-g8ed1b From 3a8fa0ed3e1a8dc54f9297d2a2292b87e03e21b5 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 22 Aug 2010 21:27:30 +0300 Subject: UBIFS: improve error reporting when reading bad node When an error happens during validation of read node, the typical situation is that the LEB we read is unmapped (due to some bug). It is handy to include the mapping status into the error message. Signed-off-by: Artem Bityutskiy --- fs/ubifs/io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index bcf5a16f30bb..9432431bf595 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -815,7 +815,8 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, return 0; out: - ubifs_err("bad node at LEB %d:%d", lnum, offs); + ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs, + ubi_is_mapped(c->ubi, lnum)); dbg_dump_node(c, buf); dbg_dump_stack(); return -EINVAL; -- cgit v1.2.3-59-g8ed1b From 73413b120d5d6eb6c98451bbc19acf43e0e300ae Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Aug 2010 09:39:57 +0200 Subject: ALSA: hda - embed alc_fixup contents into struct definitions Instead of defining each content as a separate struct, put all into the definition of struct alc_fixup arrays so that reader doesn't go back to see the definition again. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 70 ++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 41 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 627bf9963368..50e0c82fd994 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6799,14 +6799,12 @@ enum { PINFIX_HP_DC5750, }; -static struct alc_pincfg alc260_hp_dc5750_pinfix[] = { - { 0x11, 0x90130110 }, /* speaker */ - { } -}; - static const struct alc_fixup alc260_fixups[] = { [PINFIX_HP_DC5750] = { - .pins = alc260_hp_dc5750_pinfix + .pins = (const struct alc_pincfg[]) { + { 0x11, 0x90130110 }, /* speaker */ + { } + } }, }; @@ -10452,24 +10450,20 @@ enum { PINFIX_PB_M5210, }; -static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { - { 0x15, 0x01080104 }, /* side */ - { 0x16, 0x01011012 }, /* rear */ - { 0x17, 0x01016011 }, /* clfe */ - { } -}; - -static const struct hda_verb pb_m5210_verbs[] = { - { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, - {} -}; - static const struct alc_fixup alc882_fixups[] = { [PINFIX_ABIT_AW9D_MAX] = { - .pins = alc882_abit_aw9d_pinfix + .pins = (const struct alc_pincfg[]) { + { 0x15, 0x01080104 }, /* side */ + { 0x16, 0x01011012 }, /* rear */ + { 0x17, 0x01016011 }, /* clfe */ + { } + } }, [PINFIX_PB_M5210] = { - .verbs = pb_m5210_verbs + .verbs = (const struct hda_verb[]) { + { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, + {} + } }, }; @@ -14454,14 +14448,12 @@ enum { ALC269_FIXUP_SONY_VAIO, }; -static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = { - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, - {} -}; - static const struct alc_fixup alc269_fixups[] = { [ALC269_FIXUP_SONY_VAIO] = { - .verbs = alc269_sony_vaio_fixup_verbs + .verbs = (const struct hda_verb[]) { + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, + {} + } }, }; @@ -15819,15 +15811,13 @@ enum { PINFIX_FSC_AMILO_PI1505, }; -static struct alc_pincfg alc861_fsc_amilo_pi1505_pinfix[] = { - { 0x0b, 0x0221101f }, /* HP */ - { 0x0f, 0x90170310 }, /* speaker */ - { } -}; - static const struct alc_fixup alc861_fixups[] = { [PINFIX_FSC_AMILO_PI1505] = { - .pins = alc861_fsc_amilo_pi1505_pinfix + .pins = (const struct alc_pincfg[]) { + { 0x0b, 0x0221101f }, /* HP */ + { 0x0f, 0x90170310 }, /* speaker */ + { } + } }, }; @@ -16794,16 +16784,14 @@ enum { }; /* reset GPIO1 */ -static const struct hda_verb alc660vd_fix_asus_gpio1_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, - { } -}; - static const struct alc_fixup alc861vd_fixups[] = { [ALC660VD_FIX_ASUS_GPIO1] = { - .verbs = alc660vd_fix_asus_gpio1_verbs, + .verbs = (const struct hda_verb[]) { + {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, + {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, + {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, + { } + } }, }; -- cgit v1.2.3-59-g8ed1b From f3268512c3a5dea587cfe875b8bca98d9e164cd9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Aug 2010 11:00:19 +0200 Subject: ALSA: hda - Refactor input-pin parser for VIA codecs patch_via.c has redundant codes for parsing the input-pins. Although they are pretty similar, but all implemented in different functions just because of hard-coded ids and slight incompatibilities. This patch refactors the codes to use the common helper function, resulting in the reduction of many lines. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 390 +++++++--------------------------------------- 1 file changed, 60 insertions(+), 330 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index ae3acb2b42d1..41861388f43a 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -2413,51 +2413,53 @@ static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) } /* create playback/capture controls for input pins */ -static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec, - const struct auto_pin_cfg *cfg) +static int vt_auto_create_analog_input_ctls(struct via_spec *spec, + const struct auto_pin_cfg *cfg, + hda_nid_t cap_nid, + hda_nid_t pin_idxs[], int num_idxs) { - static char *labels[] = { - "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL - }; struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx = 0; + int i, err, idx; /* for internal loopback recording select */ - imux->items[imux->num_items].label = "Stereo Mixer"; - imux->items[imux->num_items].index = idx; - imux->num_items++; + for (idx = 0; idx < num_idxs; idx++) { + if (pin_idxs[idx] == 0xff) { + imux->items[imux->num_items].label = "Stereo Mixer"; + imux->items[imux->num_items].index = idx; + imux->num_items++; + break; + } + } for (i = 0; i < AUTO_PIN_LAST; i++) { if (!cfg->input_pins[i]) continue; - switch (cfg->input_pins[i]) { - case 0x1d: /* Mic */ - idx = 2; - break; - - case 0x1e: /* Line In */ - idx = 3; - break; - - case 0x21: /* Front Mic */ - idx = 4; - break; - - case 0x24: /* CD */ - idx = 1; - break; - } - err = via_new_analog_input(spec, labels[i], idx, 0x17); + for (idx = 0; idx < num_idxs; idx++) + if (pin_idxs[idx] == cfg->input_pins[i]) + break; + if (idx >= num_idxs) + continue; + err = via_new_analog_input(spec, auto_pin_cfg_labels[i], + idx, cap_nid); if (err < 0) return err; - imux->items[imux->num_items].label = labels[i]; + imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; imux->items[imux->num_items].index = idx; imux->num_items++; } return 0; } +/* create playback/capture controls for input pins */ +static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec, + const struct auto_pin_cfg *cfg) +{ + static hda_nid_t pin_idxs[] = { 0xff, 0x24, 0x1d, 0x1e, 0x21 }; + return vt_auto_create_analog_input_ctls(spec, cfg, 0x17, pin_idxs, + ARRAY_SIZE(pin_idxs)); +} + #ifdef CONFIG_SND_HDA_POWER_SAVE static struct hda_amp_list vt1708_loopbacks[] = { { 0x17, HDA_INPUT, 1 }, @@ -3024,46 +3026,9 @@ static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec, const struct auto_pin_cfg *cfg) { - static char *labels[] = { - "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL - }; - struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx = 0; - - /* for internal loopback recording select */ - imux->items[imux->num_items].label = "Stereo Mixer"; - imux->items[imux->num_items].index = idx; - imux->num_items++; - - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (!cfg->input_pins[i]) - continue; - - switch (cfg->input_pins[i]) { - case 0x1d: /* Mic */ - idx = 2; - break; - - case 0x1e: /* Line In */ - idx = 3; - break; - - case 0x21: /* Front Mic */ - idx = 4; - break; - - case 0x23: /* CD */ - idx = 1; - break; - } - err = via_new_analog_input(spec, labels[i], idx, 0x18); - if (err < 0) - return err; - imux->items[imux->num_items].label = labels[i]; - imux->items[imux->num_items].index = idx; - imux->num_items++; - } - return 0; + static hda_nid_t pin_idxs[] = { 0xff, 0x23, 0x1d, 0x1e, 0x21 }; + return vt_auto_create_analog_input_ctls(spec, cfg, 0x18, pin_idxs, + ARRAY_SIZE(pin_idxs)); } static int vt1709_parse_auto_config(struct hda_codec *codec) @@ -3591,46 +3556,9 @@ static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec, const struct auto_pin_cfg *cfg) { - static char *labels[] = { - "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL - }; - struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx = 0; - - /* for internal loopback recording select */ - imux->items[imux->num_items].label = "Stereo Mixer"; - imux->items[imux->num_items].index = idx; - imux->num_items++; - - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (!cfg->input_pins[i]) - continue; - - switch (cfg->input_pins[i]) { - case 0x1a: /* Mic */ - idx = 2; - break; - - case 0x1b: /* Line In */ - idx = 3; - break; - - case 0x1e: /* Front Mic */ - idx = 4; - break; - - case 0x1f: /* CD */ - idx = 1; - break; - } - err = via_new_analog_input(spec, labels[i], idx, 0x16); - if (err < 0) - return err; - imux->items[imux->num_items].label = labels[i]; - imux->items[imux->num_items].index = idx; - imux->num_items++; - } - return 0; + static hda_nid_t pin_idxs[] = { 0xff, 0x1f, 0x1a, 0x1b, 0x1e }; + return vt_auto_create_analog_input_ctls(spec, cfg, 0x16, pin_idxs, + ARRAY_SIZE(pin_idxs)); } static int vt1708B_parse_auto_config(struct hda_codec *codec) @@ -4064,46 +3992,9 @@ static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec, const struct auto_pin_cfg *cfg) { - static char *labels[] = { - "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL - }; - struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx = 0; - - /* for internal loopback recording select */ - imux->items[imux->num_items].label = "Stereo Mixer"; - imux->items[imux->num_items].index = 5; - imux->num_items++; - - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (!cfg->input_pins[i]) - continue; - - switch (cfg->input_pins[i]) { - case 0x1a: /* Mic */ - idx = 2; - break; - - case 0x1b: /* Line In */ - idx = 3; - break; - - case 0x1e: /* Front Mic */ - idx = 4; - break; - - case 0x1f: /* CD */ - idx = 1; - break; - } - err = via_new_analog_input(spec, labels[i], idx, 0x16); - if (err < 0) - return err; - imux->items[imux->num_items].label = labels[i]; - imux->items[imux->num_items].index = idx-1; - imux->num_items++; - } - return 0; + static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff }; + return vt_auto_create_analog_input_ctls(spec, cfg, 0x16, pin_idxs, + ARRAY_SIZE(pin_idxs)); } /* fill out digital output widgets; one for master and one for slave outputs */ @@ -4457,42 +4348,9 @@ static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) static int vt1702_auto_create_analog_input_ctls(struct via_spec *spec, const struct auto_pin_cfg *cfg) { - static char *labels[] = { - "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL - }; - struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx = 0; - - /* for internal loopback recording select */ - imux->items[imux->num_items].label = "Stereo Mixer"; - imux->items[imux->num_items].index = 3; - imux->num_items++; - - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (!cfg->input_pins[i]) - continue; - - switch (cfg->input_pins[i]) { - case 0x14: /* Mic */ - idx = 1; - break; - - case 0x15: /* Line In */ - idx = 2; - break; - - case 0x18: /* Front Mic */ - idx = 3; - break; - } - err = via_new_analog_input(spec, labels[i], idx, 0x1A); - if (err < 0) - return err; - imux->items[imux->num_items].label = labels[i]; - imux->items[imux->num_items].index = idx-1; - imux->num_items++; - } - return 0; + static hda_nid_t pin_idxs[] = { 0x14, 0x15, 0x18, 0xff }; + return vt_auto_create_analog_input_ctls(spec, cfg, 0x1a, pin_idxs, + ARRAY_SIZE(pin_idxs)); } static int vt1702_parse_auto_config(struct hda_codec *codec) @@ -4875,46 +4733,9 @@ static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) static int vt1718S_auto_create_analog_input_ctls(struct via_spec *spec, const struct auto_pin_cfg *cfg) { - static char *labels[] = { - "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL - }; - struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx = 0; - - /* for internal loopback recording select */ - imux->items[imux->num_items].label = "Stereo Mixer"; - imux->items[imux->num_items].index = 5; - imux->num_items++; - - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (!cfg->input_pins[i]) - continue; - - switch (cfg->input_pins[i]) { - case 0x2b: /* Mic */ - idx = 1; - break; - - case 0x2a: /* Line In */ - idx = 2; - break; - - case 0x29: /* Front Mic */ - idx = 3; - break; - - case 0x2c: /* CD */ - idx = 0; - break; - } - err = via_new_analog_input(spec, labels[i], idx, 0x21); - if (err < 0) - return err; - imux->items[imux->num_items].label = labels[i]; - imux->items[imux->num_items].index = idx; - imux->num_items++; - } - return 0; + static hda_nid_t pin_idxs[] = { 0x2c, 0x2b, 0x2a, 0x29, 0, 0xff }; + return vt_auto_create_analog_input_ctls(spec, cfg, 0x21, pin_idxs, + ARRAY_SIZE(pin_idxs)); } static int vt1718S_parse_auto_config(struct hda_codec *codec) @@ -5374,46 +5195,9 @@ static int vt1716S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) static int vt1716S_auto_create_analog_input_ctls(struct via_spec *spec, const struct auto_pin_cfg *cfg) { - static char *labels[] = { - "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL - }; - struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx = 0; - - /* for internal loopback recording select */ - imux->items[imux->num_items].label = "Stereo Mixer"; - imux->items[imux->num_items].index = 5; - imux->num_items++; - - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (!cfg->input_pins[i]) - continue; - - switch (cfg->input_pins[i]) { - case 0x1a: /* Mic */ - idx = 2; - break; - - case 0x1b: /* Line In */ - idx = 3; - break; - - case 0x1e: /* Front Mic */ - idx = 4; - break; - - case 0x1f: /* CD */ - idx = 1; - break; - } - err = via_new_analog_input(spec, labels[i], idx, 0x16); - if (err < 0) - return err; - imux->items[imux->num_items].label = labels[i]; - imux->items[imux->num_items].index = idx-1; - imux->num_items++; - } - return 0; + static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff }; + return vt_auto_create_analog_input_ctls(spec, cfg, 0x16, pin_idxs, + ARRAY_SIZE(pin_idxs)); } static int vt1716S_parse_auto_config(struct hda_codec *codec) @@ -5720,47 +5504,19 @@ static int vt2002P_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) static int vt2002P_auto_create_analog_input_ctls(struct via_spec *spec, const struct auto_pin_cfg *cfg) { - static char *labels[] = { - "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL - }; struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx = 0; - - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (!cfg->input_pins[i]) - continue; - - switch (cfg->input_pins[i]) { - case 0x2b: /* Mic */ - idx = 0; - break; - - case 0x2a: /* Line In */ - idx = 1; - break; - - case 0x29: /* Front Mic */ - idx = 2; - break; - } - err = via_new_analog_input(spec, labels[i], idx, 0x21); - if (err < 0) - return err; - imux->items[imux->num_items].label = labels[i]; - imux->items[imux->num_items].index = idx; - imux->num_items++; - } + static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0xff }; + int err; + err = vt_auto_create_analog_input_ctls(spec, cfg, 0x21, pin_idxs, + ARRAY_SIZE(pin_idxs)); + if (err < 0) + return err; /* build volume/mute control of loopback */ err = via_new_analog_input(spec, "Stereo Mixer", 3, 0x21); if (err < 0) return err; - /* for internal loopback recording select */ - imux->items[imux->num_items].label = "Stereo Mixer"; - imux->items[imux->num_items].index = 3; - imux->num_items++; - /* for digital mic select */ imux->items[imux->num_items].label = "Digital Mic"; imux->items[imux->num_items].index = 4; @@ -6070,46 +5826,20 @@ static int vt1812_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) static int vt1812_auto_create_analog_input_ctls(struct via_spec *spec, const struct auto_pin_cfg *cfg) { - static char *labels[] = { - "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL - }; struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx = 0; - - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (!cfg->input_pins[i]) - continue; - - switch (cfg->input_pins[i]) { - case 0x2b: /* Mic */ - idx = 0; - break; + static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0, 0, 0xff }; + int err; - case 0x2a: /* Line In */ - idx = 1; - break; + err = vt_auto_create_analog_input_ctls(spec, cfg, 0x21, pin_idxs, + ARRAY_SIZE(pin_idxs)); + if (err < 0) + return err; - case 0x29: /* Front Mic */ - idx = 2; - break; - } - err = via_new_analog_input(spec, labels[i], idx, 0x21); - if (err < 0) - return err; - imux->items[imux->num_items].label = labels[i]; - imux->items[imux->num_items].index = idx; - imux->num_items++; - } /* build volume/mute control of loopback */ err = via_new_analog_input(spec, "Stereo Mixer", 5, 0x21); if (err < 0) return err; - /* for internal loopback recording select */ - imux->items[imux->num_items].label = "Stereo Mixer"; - imux->items[imux->num_items].index = 5; - imux->num_items++; - /* for digital mic select */ imux->items[imux->num_items].label = "Digital Mic"; imux->items[imux->num_items].index = 6; -- cgit v1.2.3-59-g8ed1b From 75e0eb24ee3ec3549c2e53707dcc87e5f7a2c791 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Aug 2010 12:56:55 +0200 Subject: ALSA: hda - Add inputs[] to auto_pin_cfg struct Added the new fields to contain all input-pins to struct auto_pin_cfg. Unlike the existing input_pins[], this array contains all input pins even if the multiple pins are assigned for a single role (i.e. two front mics). The former input_pins[] still remains for a while, but will be removed in near future. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 40 +++++++++++++++++++++++++++++----------- sound/pci/hda/hda_local.h | 12 +++++++++++- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 3827092cc1d2..280a739c2a99 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4372,6 +4372,17 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, } +/* add the found input-pin to the cfg->inputs[] table */ +static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid, + int type) +{ + if (cfg->num_inputs < AUTO_CFG_MAX_INS) { + cfg->inputs[cfg->num_inputs].pin = nid; + cfg->inputs[cfg->num_inputs].type = type; + cfg->num_inputs++; + } +} + /* * Parse all pin widgets and store the useful pin nids to cfg * @@ -4398,6 +4409,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; + int i; memset(cfg, 0, sizeof(*cfg)); @@ -4482,19 +4494,26 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, cfg->input_pins[preferred] = nid; else if (!cfg->input_pins[alt]) cfg->input_pins[alt] = nid; + add_auto_cfg_input_pin(cfg, nid, preferred); break; } - case AC_JACK_LINE_IN: + case AC_JACK_LINE_IN: { + int type; if (loc == AC_JACK_LOC_FRONT) - cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; + type = AUTO_PIN_FRONT_LINE; else - cfg->input_pins[AUTO_PIN_LINE] = nid; + type = AUTO_PIN_LINE; + cfg->input_pins[type] = nid; + add_auto_cfg_input_pin(cfg, nid, type); break; + } case AC_JACK_CD: cfg->input_pins[AUTO_PIN_CD] = nid; + add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD); break; case AC_JACK_AUX: cfg->input_pins[AUTO_PIN_AUX] = nid; + add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX); break; case AC_JACK_SPDIF_OUT: case AC_JACK_DIG_OTHER_OUT: @@ -4621,14 +4640,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, if (cfg->dig_outs) snd_printd(" dig-out=0x%x/0x%x\n", cfg->dig_out_pins[0], cfg->dig_out_pins[1]); - snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," - " cd=0x%x, aux=0x%x\n", - cfg->input_pins[AUTO_PIN_MIC], - cfg->input_pins[AUTO_PIN_FRONT_MIC], - cfg->input_pins[AUTO_PIN_LINE], - cfg->input_pins[AUTO_PIN_FRONT_LINE], - cfg->input_pins[AUTO_PIN_CD], - cfg->input_pins[AUTO_PIN_AUX]); + snd_printd(" inputs:"); + for (i = 0; i < cfg->num_inputs; i++) { + snd_printdd(" %s=0x%x", + auto_pin_cfg_labels[cfg->inputs[i].type], + cfg->inputs[i].pin); + } + snd_printd("\n"); if (cfg->dig_in_pin) snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 28ab4aead48f..44c909445ba2 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -383,6 +383,14 @@ enum { extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; #define AUTO_CFG_MAX_OUTS 5 +#define AUTO_CFG_MAX_INS 8 + +struct auto_pin_cfg_item { + hda_nid_t pin; + int type; +}; + +struct auto_pin_cfg; struct auto_pin_cfg { int line_outs; @@ -393,7 +401,9 @@ struct auto_pin_cfg { int hp_outs; int line_out_type; /* AUTO_PIN_XXX_OUT */ hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; - hda_nid_t input_pins[AUTO_PIN_LAST]; + hda_nid_t input_pins[AUTO_PIN_LAST]; /* old config; to be deprecated */ + int num_inputs; + struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS]; int dig_outs; hda_nid_t dig_out_pins[2]; hda_nid_t dig_in_pin; -- cgit v1.2.3-59-g8ed1b From d7b1ae9d8851bd247590cf7ab53248a2dac0419f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Aug 2010 13:00:16 +0200 Subject: ALSA: hda - Add snd_hda_get_input_pin_label() helper function Added snd_hda_get_input_pin_label() helper function to return the string that can be used for control or capture-source ids. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 25 ++++++++++++++++++++++++- sound/pci/hda/hda_local.h | 2 ++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 280a739c2a99..72334b7f60e5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4654,12 +4654,35 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, } EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config); -/* labels for input pins */ +/* labels for input pins - for obsoleted config stuff */ const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = { "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" }; EXPORT_SYMBOL_HDA(auto_pin_cfg_labels); +static const char *input_labels[AUTO_PIN_LAST][4] = { + { "Mic", "Mic 2", "Mic 3", "Mic 4" }, + { "Front Mic", "Front Mic 2", "Front Mic 3", "Front Mic 4" }, + { "Line", "Line 2", "Line 3", "Line 4" }, + { "Front Line", "Front Line 2", "Front Line 3", "Front Line 4" }, + { "CD", "CD 2", "CD 3", "CD 4" }, + { "Aux", "Aux 2", "Aux 3", "Aux 4" }, +}; + +const char *snd_hda_get_input_pin_label(const struct auto_pin_cfg *cfg, + int input) +{ + int type = cfg->inputs[input].type; + int idx; + + for (idx = 0; idx < 3 && --input >= 0; idx++) { + if (type != cfg->inputs[input].type) + break; + } + return input_labels[type][idx]; +} +EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_label); + #ifdef CONFIG_PM /* diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 44c909445ba2..fb561748adb8 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -391,6 +391,8 @@ struct auto_pin_cfg_item { }; struct auto_pin_cfg; +const char *snd_hda_get_input_pin_label(const struct auto_pin_cfg *cfg, + int input); struct auto_pin_cfg { int line_outs; -- cgit v1.2.3-59-g8ed1b From 9e042e71325eeda03636aedfde6f2d27d6332188 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Aug 2010 13:04:44 +0200 Subject: ALSA: hda - Use new inputs[] field to parse input-pins for AD codecs Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index b697fd2a6f8b..3409d315f507 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -2880,7 +2880,7 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, /* create input playback/capture controls for the given pin */ static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, - const char *ctlname, int boost) + const char *ctlname, int ctlidx, int boost) { char name[32]; int err, idx; @@ -2913,16 +2913,23 @@ static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec, const struct auto_pin_cfg *cfg) { struct hda_input_mux *imux = &spec->private_imux; - int i, err; + int i, err, type, type_idx = 0; - for (i = 0; i < AUTO_PIN_LAST; i++) { - err = new_analog_input(spec, cfg->input_pins[i], - auto_pin_cfg_labels[i], - i <= AUTO_PIN_FRONT_MIC); + for (i = 0; i < cfg->num_inputs; i++) { + type = cfg->inputs[i].type; + if (i > 0 && type != cfg->inputs[i - 1].type) + type_idx++; + else + type_idx = 0; + err = new_analog_input(spec, cfg->inputs[i].pin, + auto_pin_cfg_labels[type], type_idx, + type <= AUTO_PIN_FRONT_MIC); if (err < 0) return err; - imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; - imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]); + imux->items[imux->num_items].label = + snd_hda_get_input_pin_label(cfg, i); + imux->items[imux->num_items].index = + ad1988_pin_to_adc_idx(cfg->inputs[i].pin); imux->num_items++; } imux->items[imux->num_items].label = "Mix"; @@ -2994,12 +3001,11 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec) static void ad1988_auto_init_analog_input(struct hda_codec *codec) { struct ad198x_spec *spec = codec->spec; + const struct auto_pin_cfg *cfg = &spec->autocfg; int i, idx; - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; - if (! nid) - continue; + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; switch (nid) { case 0x15: /* port-C */ snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0); -- cgit v1.2.3-59-g8ed1b From fa4968a8b231816d161583e604a9f972e5713f17 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Aug 2010 13:05:08 +0200 Subject: ALSA: hda - Use new inputs[] field to parse input-pins for CA-IBG codecs Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0110.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c index af478019088e..42b3fb4cafc4 100644 --- a/sound/pci/hda/patch_ca0110.c +++ b/sound/pci/hda/patch_ca0110.c @@ -468,13 +468,14 @@ static void parse_input(struct hda_codec *codec) spec->dig_in = nid; continue; } - for (j = 0; j < AUTO_PIN_LAST; j++) - if (cfg->input_pins[j] == pin) + for (j = 0; j < cfg->num_inputs; j++) + if (cfg->inputs[j].pin == pin) break; - if (j >= AUTO_PIN_LAST) + if (j >= cfg->num_inputs) continue; spec->input_pins[n] = pin; - spec->input_labels[n] = auto_pin_cfg_labels[j]; + spec->input_labels[n] = + auto_pin_cfg_labels[cfg->inputs[j].type]; spec->adcs[n] = nid; n++; } -- cgit v1.2.3-59-g8ed1b From c1e0bb92174dd16ffba5be0e4e5fbd366f61ff7f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Aug 2010 13:05:30 +0200 Subject: ALSA: hda - Use new inputs[] field to parse input-pins for CirrusLogic codecs Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_cirrus.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 4ef5efaaaef1..ee1aea7296eb 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -329,7 +329,7 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx) { struct cs_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t pin = cfg->input_pins[idx]; + hda_nid_t pin = cfg->inputs[idx].pin; unsigned int val = snd_hda_query_pin_caps(codec, pin); if (!(val & AC_PINCAP_PRES_DETECT)) return 0; @@ -424,10 +424,8 @@ static int parse_input(struct hda_codec *codec) struct auto_pin_cfg *cfg = &spec->autocfg; int i; - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t pin = cfg->input_pins[i]; - if (!pin) - continue; + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t pin = cfg->inputs[i].pin; spec->input_idx[spec->num_inputs] = i; spec->capsrc_idx[i] = spec->num_inputs++; spec->cur_input = i; @@ -438,16 +436,17 @@ static int parse_input(struct hda_codec *codec) /* check whether the automatic mic switch is available */ if (spec->num_inputs == 2 && - spec->adc_nid[AUTO_PIN_MIC] && spec->adc_nid[AUTO_PIN_FRONT_MIC]) { - if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_FRONT_MIC])) { - if (!is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { + cfg->inputs[0].type <= AUTO_PIN_FRONT_MIC && + cfg->inputs[1].type == AUTO_PIN_FRONT_MIC) { + if (is_ext_mic(codec, cfg->inputs[0].pin)) { + if (!is_ext_mic(codec, cfg->inputs[1].pin)) { spec->mic_detect = 1; - spec->automic_idx = AUTO_PIN_FRONT_MIC; + spec->automic_idx = 0; } } else { - if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { + if (is_ext_mic(codec, cfg->inputs[1].pin)) { spec->mic_detect = 1; - spec->automic_idx = AUTO_PIN_MIC; + spec->automic_idx = 1; } } } @@ -853,15 +852,12 @@ static void cs_automic(struct hda_codec *codec) hda_nid_t nid; unsigned int present; - nid = cfg->input_pins[spec->automic_idx]; + nid = cfg->inputs[spec->automic_idx].pin; present = snd_hda_jack_detect(codec, nid); if (present) change_cur_input(codec, spec->automic_idx, 0); - else { - unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? - AUTO_PIN_FRONT_MIC : AUTO_PIN_MIC; - change_cur_input(codec, imic, 0); - } + else + change_cur_input(codec, !spec->automic_idx, 0); } /* @@ -918,14 +914,14 @@ static void init_input(struct hda_codec *codec) unsigned int coef; int i; - for (i = 0; i < AUTO_PIN_LAST; i++) { + for (i = 0; i < cfg->num_inputs; i++) { unsigned int ctl; - hda_nid_t pin = cfg->input_pins[i]; - if (!pin || !spec->adc_nid[i]) + hda_nid_t pin = cfg->inputs[i].pin; + if (!spec->adc_nid[i]) continue; /* set appropriate pin control and mute first */ ctl = PIN_IN; - if (i <= AUTO_PIN_FRONT_MIC) { + if (cfg->inputs[i].type <= AUTO_PIN_FRONT_MIC) { unsigned int caps = snd_hda_query_pin_caps(codec, pin); caps >>= AC_PINCAP_VREF_SHIFT; if (caps & AC_PINCAP_VREF_80) -- cgit v1.2.3-59-g8ed1b From 66ceeb6bc2809bef0cfa18b1e22ddad5fc9b58b0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Aug 2010 13:05:52 +0200 Subject: ALSA: hda - Use new inputs[] field to parse input-pins for Realtek codecs Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 208 ++++++++++++++++++++++-------------------- 1 file changed, 110 insertions(+), 98 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 50e0c82fd994..3e0f4816aed7 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1265,16 +1265,14 @@ static void alc_init_auto_mic(struct hda_codec *codec) int i; /* there must be only two mic inputs exclusively */ - for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) - if (cfg->input_pins[i]) + for (i = 0; i < cfg->num_inputs; i++) + if (cfg->inputs[i].type >= AUTO_PIN_LINE) return; fixed = ext = 0; - for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) { - hda_nid_t nid = cfg->input_pins[i]; + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; unsigned int defcfg; - if (!nid) - return; defcfg = snd_hda_codec_get_pincfg(codec, nid); switch (get_defcfg_connect(defcfg)) { case AC_JACK_PORT_FIXED: @@ -4719,7 +4717,7 @@ static struct snd_kcontrol_new alc880_control_templates[] = { /* add dynamic controls */ static int add_control(struct alc_spec *spec, int type, const char *name, - unsigned long val) + int cidx, unsigned long val) { struct snd_kcontrol_new *knew; @@ -4731,6 +4729,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name, knew->name = kstrdup(name, GFP_KERNEL); if (!knew->name) return -ENOMEM; + knew->index = cidx; if (get_amp_nid_(val)) knew->subdevice = HDA_SUBDEV_AMP_FLAG; knew->private_value = val; @@ -4739,17 +4738,21 @@ static int add_control(struct alc_spec *spec, int type, const char *name, static int add_control_with_pfx(struct alc_spec *spec, int type, const char *pfx, const char *dir, - const char *sfx, unsigned long val) + const char *sfx, int cidx, unsigned long val) { char name[32]; snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); - return add_control(spec, type, name, val); + return add_control(spec, type, name, cidx, val); } -#define add_pb_vol_ctrl(spec, type, pfx, val) \ - add_control_with_pfx(spec, type, pfx, "Playback", "Volume", val) -#define add_pb_sw_ctrl(spec, type, pfx, val) \ - add_control_with_pfx(spec, type, pfx, "Playback", "Switch", val) +#define add_pb_vol_ctrl(spec, type, pfx, val) \ + add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val) +#define add_pb_sw_ctrl(spec, type, pfx, val) \ + add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val) +#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \ + add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val) +#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \ + add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val) #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) #define alc880_fixed_pin_idx(nid) ((nid) - 0x14) @@ -4902,16 +4905,16 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, /* create input playback/capture controls for the given pin */ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, - const char *ctlname, + const char *ctlname, int ctlidx, int idx, hda_nid_t mix_nid) { int err; - err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, + err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx, HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); if (err < 0) return err; - err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, + err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx, HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); if (err < 0) return err; @@ -4932,21 +4935,26 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec, { struct alc_spec *spec = codec->spec; struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx; + int i, err, idx, type, type_idx = 0; - for (i = 0; i < AUTO_PIN_LAST; i++) { + for (i = 0; i < cfg->num_inputs; i++) { hda_nid_t pin; - pin = cfg->input_pins[i]; + pin = cfg->inputs[i].pin; if (!alc_is_input_pin(codec, pin)) continue; + type = cfg->inputs[i].type; + if (i > 0 && type == cfg->inputs[i - 1].type) + type_idx++; + else + type_idx = 0; if (mixer) { idx = get_connection_index(codec, mixer, pin); if (idx >= 0) { err = new_analog_input(spec, pin, - auto_pin_cfg_labels[i], - idx, mixer); + auto_pin_cfg_labels[type], + type_idx, idx, mixer); if (err < 0) return err; } @@ -4959,7 +4967,7 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec, idx = get_connection_index(codec, cap2, pin); if (idx >= 0) { imux->items[imux->num_items].label = - auto_pin_cfg_labels[i]; + snd_hda_get_input_pin_label(cfg, i); imux->items[imux->num_items].index = idx; imux->num_items++; } @@ -5034,10 +5042,11 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec) static void alc880_auto_init_analog_input(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; int i; - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; if (alc_is_input_pin(codec, nid)) { alc_set_input_pin(codec, nid, i); if (nid != ALC880_PIN_CD_NID && @@ -5204,19 +5213,13 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin) static void fixup_single_adc(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - hda_nid_t pin = 0; + struct auto_pin_cfg *cfg = &spec->autocfg; int i; /* search for the input pin; there must be only one */ - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (spec->autocfg.input_pins[i]) { - pin = spec->autocfg.input_pins[i]; - break; - } - } - if (!pin) + if (cfg->num_inputs != 1) return; - i = init_capsrc_for_pin(codec, pin); + i = init_capsrc_for_pin(codec, cfg->inputs[0].pin); if (i >= 0) { /* use only this ADC */ if (spec->capsrc_nids) @@ -5269,6 +5272,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, int num_nids) { struct alc_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; int n; hda_nid_t fallback_adc = 0, fallback_cap = 0; @@ -5294,10 +5298,8 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, fallback_adc = adc; fallback_cap = cap; } - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; - if (!nid) - continue; + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; for (j = 0; j < nconns; j++) { if (conn[j] == nid) break; @@ -5305,7 +5307,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, if (j >= nconns) break; } - if (i >= AUTO_PIN_LAST) { + if (i >= cfg->num_inputs) { int num_adcs = spec->num_adc_nids; spec->private_adc_nids[num_adcs] = adc; spec->private_capsrc_nids[num_adcs] = cap; @@ -6672,10 +6674,11 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) static void alc260_auto_init_analog_input(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; int i; - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; if (nid >= 0x12) { alc_set_input_pin(codec, nid, i); if (nid != ALC260_PIN_CD_NID && @@ -10538,12 +10541,11 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) static void alc882_auto_init_analog_input(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; int i; - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; - if (!nid) - continue; + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; alc_set_input_pin(codec, nid, i); if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) snd_hda_codec_write(codec, nid, 0, @@ -10606,24 +10608,23 @@ static void alc882_auto_init_input_src(struct hda_codec *codec) static int alc_auto_add_mic_boost(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - int err; + struct auto_pin_cfg *cfg = &spec->autocfg; + int i, err; hda_nid_t nid; - nid = spec->autocfg.input_pins[AUTO_PIN_MIC]; - if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { - err = add_control(spec, ALC_CTL_WIDGET_VOL, - "Mic Boost", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); - if (err < 0) - return err; - } - nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]; - if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { - err = add_control(spec, ALC_CTL_WIDGET_VOL, - "Front Mic Boost", + for (i = 0; i < cfg->num_inputs; i++) { + if (cfg->inputs[i].type > AUTO_PIN_FRONT_MIC) + break; + nid = cfg->inputs[i].pin; + if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) { + char label[32]; + snprintf(label, sizeof(label), "%s Boost", + snd_hda_get_input_pin_label(cfg, i)); + err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0, HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); - if (err < 0) - return err; + if (err < 0) + return err; + } } return 0; } @@ -15577,10 +15578,11 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec) static void alc861_auto_init_analog_input(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; int i; - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; if (nid >= 0x0c && nid <= 0x11) alc_set_input_pin(codec, nid, i); } @@ -16569,10 +16571,11 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec) static void alc861vd_auto_init_analog_input(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; int i; - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; if (alc_is_input_pin(codec, nid)) { alc_set_input_pin(codec, nid, i); if (nid != ALC861VD_PIN_CD_NID && @@ -18805,10 +18808,11 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) static void alc662_auto_init_analog_input(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; int i; - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; if (alc_is_input_pin(codec, nid)) { alc_set_input_pin(codec, nid, i); if (nid != ALC662_PIN_CD_NID && @@ -19037,6 +19041,39 @@ static hda_nid_t alc680_adc_nids[3] = { /* * Analog capture ADC cgange */ +static void alc680_rec_autoswitch(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; + int pin_found = 0; + int type_found = AUTO_PIN_LAST; + hda_nid_t nid; + int i; + + for (i = 0; i < cfg->num_inputs; i++) { + nid = cfg->inputs[i].pin; + if (!(snd_hda_query_pin_caps(codec, nid) & + AC_PINCAP_PRES_DETECT)) + continue; + if (snd_hda_jack_detect(codec, nid)) { + if (cfg->inputs[i].type < type_found) { + type_found = cfg->inputs[i].type; + pin_found = nid; + } + } + } + + nid = 0x07; + if (pin_found) + snd_hda_get_connections(codec, pin_found, &nid, 1); + + if (nid != spec->cur_adc) + __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); + spec->cur_adc = nid; + snd_hda_codec_setup_stream(codec, nid, spec->cur_adc_stream_tag, 0, + spec->cur_adc_format); +} + static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, @@ -19044,24 +19081,12 @@ static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int pre_mic, pre_line; - - pre_mic = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); - pre_line = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_LINE]); + spec->cur_adc = 0x07; spec->cur_adc_stream_tag = stream_tag; spec->cur_adc_format = format; - if (pre_mic || pre_line) { - if (pre_mic) - snd_hda_codec_setup_stream(codec, 0x08, stream_tag, 0, - format); - else - snd_hda_codec_setup_stream(codec, 0x09, stream_tag, 0, - format); - } else - snd_hda_codec_setup_stream(codec, 0x07, stream_tag, 0, format); + alc680_rec_autoswitch(codec); return 0; } @@ -19147,6 +19172,7 @@ static struct hda_verb alc680_init_verbs[] = { {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, + {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, { } }; @@ -19159,25 +19185,11 @@ static void alc680_base_setup(struct hda_codec *codec) spec->autocfg.hp_pins[0] = 0x16; spec->autocfg.speaker_pins[0] = 0x14; spec->autocfg.speaker_pins[1] = 0x15; - spec->autocfg.input_pins[AUTO_PIN_MIC] = 0x18; - spec->autocfg.input_pins[AUTO_PIN_LINE] = 0x19; -} - -static void alc680_rec_autoswitch(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int present; - hda_nid_t new_adc; - - present = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); - - new_adc = present ? 0x8 : 0x7; - __snd_hda_codec_cleanup_stream(codec, !present ? 0x8 : 0x7, 1); - snd_hda_codec_setup_stream(codec, new_adc, - spec->cur_adc_stream_tag, 0, - spec->cur_adc_format); - + spec->autocfg.num_inputs = 2; + spec->autocfg.inputs[0].pin = 0x18; + spec->autocfg.inputs[0].type = AUTO_PIN_MIC; + spec->autocfg.inputs[1].pin = 0x19; + spec->autocfg.inputs[1].type = AUTO_PIN_LINE; } static void alc680_unsol_event(struct hda_codec *codec, -- cgit v1.2.3-59-g8ed1b From eea7dc932bfa802ad0377755ea821f416f4f8623 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Aug 2010 13:06:15 +0200 Subject: ALSA: hda - Use new inputs[] field to parse input-pins for STAC/IDT codecs Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 183 +++++++++++++++++++++-------------------- 1 file changed, 96 insertions(+), 87 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 95148e58026c..d226edd1e143 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1180,14 +1180,11 @@ static int stac92xx_build_controls(struct hda_codec *codec) if (err < 0) return err; } - for (i = 0; i < AUTO_PIN_LAST; i++) { - nid = cfg->input_pins[i]; - if (nid) { - err = stac92xx_add_jack(codec, nid, - SND_JACK_MICROPHONE); - if (err < 0) - return err; - } + for (i = 0; i < cfg->num_inputs; i++) { + nid = cfg->inputs[i].pin; + err = stac92xx_add_jack(codec, nid, SND_JACK_MICROPHONE); + if (err < 0) + return err; } return 0; @@ -2821,41 +2818,55 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec) struct auto_pin_cfg *cfg = &spec->autocfg; hda_nid_t nid; unsigned int pincap; + int i; if (cfg->line_out_type != AUTO_PIN_LINE_OUT) return 0; - nid = cfg->input_pins[AUTO_PIN_LINE]; - pincap = snd_hda_query_pin_caps(codec, nid); - if (pincap & AC_PINCAP_OUT) - return nid; + for (i = 0; i < cfg->num_inputs; i++) { + if (cfg->inputs[i].type == AUTO_PIN_LINE) { + nid = cfg->inputs[i].pin; + pincap = snd_hda_query_pin_caps(codec, nid); + if (pincap & AC_PINCAP_OUT) + return nid; + } + } return 0; } +static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid); + /* check whether the mic-input can be used as line-out */ -static hda_nid_t check_mic_out_switch(struct hda_codec *codec) +static hda_nid_t check_mic_out_switch(struct hda_codec *codec, hda_nid_t *dac) { struct sigmatel_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; unsigned int def_conf, pincap; - unsigned int mic_pin; + int i, mic_type; + *dac = 0; if (cfg->line_out_type != AUTO_PIN_LINE_OUT) return 0; - mic_pin = AUTO_PIN_MIC; - for (;;) { - hda_nid_t nid = cfg->input_pins[mic_pin]; + mic_type = AUTO_PIN_MIC; + again: + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; + if (cfg->inputs[i].type != mic_type) + continue; def_conf = snd_hda_codec_get_pincfg(codec, nid); /* some laptops have an internal analog microphone * which can't be used as a output */ if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { pincap = snd_hda_query_pin_caps(codec, nid); - if (pincap & AC_PINCAP_OUT) - return nid; + if (pincap & AC_PINCAP_OUT) { + *dac = get_unassigned_dac(codec, nid); + if (*dac) + return nid; + } } - if (mic_pin == AUTO_PIN_MIC) - mic_pin = AUTO_PIN_FRONT_MIC; - else - break; + } + if (mic_type == AUTO_PIN_MIC) { + mic_type = AUTO_PIN_FRONT_MIC; + goto again; } return 0; } @@ -3002,17 +3013,14 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) } } /* add mic as output */ - nid = check_mic_out_switch(codec); - if (nid) { - dac = get_unassigned_dac(codec, nid); - if (dac) { - snd_printdd("STAC: Add mic-in 0x%x as output %d\n", - nid, cfg->line_outs); - cfg->line_out_pins[cfg->line_outs] = nid; - cfg->line_outs++; - spec->mic_switch = nid; - add_spec_dacs(spec, dac); - } + nid = check_mic_out_switch(codec, &dac); + if (nid && dac) { + snd_printdd("STAC: Add mic-in 0x%x as output %d\n", + nid, cfg->line_outs); + cfg->line_out_pins[cfg->line_outs] = nid; + cfg->line_outs++; + spec->mic_switch = nid; + add_spec_dacs(spec, dac); } snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", @@ -3202,13 +3210,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, return err; } - for (idx = AUTO_PIN_MIC; idx <= AUTO_PIN_FRONT_LINE; idx++) { - nid = cfg->input_pins[idx]; - if (nid) { - err = stac92xx_add_jack_mode_control(codec, nid, idx); - if (err < 0) - return err; - } + for (idx = 0; idx < cfg->num_inputs; idx++) { + if (cfg->inputs[idx].type > AUTO_PIN_FRONT_LINE) + break; + nid = cfg->inputs[idx].pin; + err = stac92xx_add_jack_mode_control(codec, nid, idx); + if (err < 0) + return err; } return 0; @@ -3415,7 +3423,7 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, /* create a volume assigned to the given pin (only if supported) */ /* return 1 if the volume control is created */ static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, - const char *label, int direction) + const char *label, int idx, int direction) { unsigned int caps, nums; char name[32]; @@ -3432,8 +3440,8 @@ static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, if (!nums) return 0; snprintf(name, sizeof(name), "%s Capture Volume", label); - err = stac92xx_add_control(codec->spec, STAC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); + err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); if (err < 0) return err; return 1; @@ -3485,11 +3493,11 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, else label = stac92xx_dmic_labels[dimux->num_items]; - err = create_elem_capture_vol(codec, nid, label, HDA_INPUT); + err = create_elem_capture_vol(codec, nid, label, 0, HDA_INPUT); if (err < 0) return err; if (!err) { - err = create_elem_capture_vol(codec, nid, label, + err = create_elem_capture_vol(codec, nid, label, 0, HDA_OUTPUT); if (err < 0) return err; @@ -3540,10 +3548,11 @@ static int set_mic_route(struct hda_codec *codec, int i; mic->pin = pin; - for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) - if (pin == cfg->input_pins[i]) + for (i = 0; i < cfg->num_inputs; i++) { + if (pin == cfg->inputs[i].pin) break; - if (i <= AUTO_PIN_FRONT_MIC) { + } + if (i < cfg->num_inputs && cfg->inputs[i].type <= AUTO_PIN_FRONT_MIC) { /* analog pin */ i = get_connection_index(codec, spec->mux_nids[0], pin); if (i < 0) @@ -3577,13 +3586,13 @@ static int stac_check_auto_mic(struct hda_codec *codec) hda_nid_t fixed, ext; int i; - for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) { - if (cfg->input_pins[i]) + for (i = 0; i < cfg->num_inputs; i++) { + if (cfg->inputs[i].type >= AUTO_PIN_LINE) return 0; /* must be exclusively mics */ } fixed = ext = 0; - for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) - if (check_mic_pin(codec, cfg->input_pins[i], &fixed, &ext)) + for (i = 0; i < cfg->num_inputs; i++) + if (check_mic_pin(codec, cfg->inputs[i].pin, &fixed, &ext)) return 0; for (i = 0; i < spec->num_dmics; i++) if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext)) @@ -3603,14 +3612,12 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const { struct sigmatel_spec *spec = codec->spec; struct hda_input_mux *imux = &spec->private_imux; - int i, j; + int i, j, type_idx = 0; - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = cfg->input_pins[i]; + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; int index, err; - if (!nid) - continue; index = -1; for (j = 0; j < spec->num_muxes; j++) { index = get_connection_index(codec, spec->mux_nids[j], @@ -3621,13 +3628,18 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const if (index < 0) continue; + if (i > 0 && cfg->inputs[i].type == cfg->inputs[i - 1].type) + type_idx++; + else + type_idx = 0; err = create_elem_capture_vol(codec, nid, - auto_pin_cfg_labels[i], + auto_pin_cfg_labels[i], type_idx, HDA_INPUT); if (err < 0) return err; - imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; + imux->items[imux->num_items].label = + snd_hda_get_input_pin_label(cfg, i); imux->items[imux->num_items].index = index; imux->num_items++; } @@ -4304,37 +4316,34 @@ static int stac92xx_init(struct hda_codec *codec) if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) stac_issue_unsol_event(codec, spec->ext_mic.pin); } - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = cfg->input_pins[i]; - if (nid) { - unsigned int pinctl, conf; - if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { - /* for mic pins, force to initialize */ - pinctl = stac92xx_get_default_vref(codec, nid); + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; + int type = cfg->inputs[i].type; + unsigned int pinctl, conf; + if (type == AUTO_PIN_MIC || type == AUTO_PIN_FRONT_MIC) { + /* for mic pins, force to initialize */ + pinctl = stac92xx_get_default_vref(codec, nid); + pinctl |= AC_PINCTL_IN_EN; + stac92xx_auto_set_pinctl(codec, nid, pinctl); + } else { + pinctl = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + /* if PINCTL already set then skip */ + /* Also, if both INPUT and OUTPUT are set, + * it must be a BIOS bug; need to override, too + */ + if (!(pinctl & AC_PINCTL_IN_EN) || + (pinctl & AC_PINCTL_OUT_EN)) { + pinctl &= ~AC_PINCTL_OUT_EN; pinctl |= AC_PINCTL_IN_EN; stac92xx_auto_set_pinctl(codec, nid, pinctl); - } else { - pinctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - /* if PINCTL already set then skip */ - /* Also, if both INPUT and OUTPUT are set, - * it must be a BIOS bug; need to override, too - */ - if (!(pinctl & AC_PINCTL_IN_EN) || - (pinctl & AC_PINCTL_OUT_EN)) { - pinctl &= ~AC_PINCTL_OUT_EN; - pinctl |= AC_PINCTL_IN_EN; - stac92xx_auto_set_pinctl(codec, nid, - pinctl); - } - } - conf = snd_hda_codec_get_pincfg(codec, nid); - if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { - if (enable_pin_detect(codec, nid, - STAC_INSERT_EVENT)) - stac_issue_unsol_event(codec, nid); } } + conf = snd_hda_codec_get_pincfg(codec, nid); + if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { + if (enable_pin_detect(codec, nid, STAC_INSERT_EVENT)) + stac_issue_unsol_event(codec, nid); + } } for (i = 0; i < spec->num_dmics; i++) stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], -- cgit v1.2.3-59-g8ed1b From 7b315bb4980448250c80a7464c256b54d546cb26 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Aug 2010 13:06:30 +0200 Subject: ALSA: hda - Use new inputs[] field to parse input-pins for VIA codecs Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 144 +++++++++++++++++++++++----------------------- 1 file changed, 73 insertions(+), 71 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 41861388f43a..93b86adbce63 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -444,8 +444,8 @@ static hda_nid_t vt1812_adc_nids[2] = { /* add dynamic controls */ -static int via_add_control(struct via_spec *spec, int type, const char *name, - unsigned long val) +static int __via_add_control(struct via_spec *spec, int type, const char *name, + int idx, unsigned long val) { struct snd_kcontrol_new *knew; @@ -463,6 +463,9 @@ static int via_add_control(struct via_spec *spec, int type, const char *name, return 0; } +#define via_add_control(spec, type, name, val) \ + __via_add_control(spec, type, name, 0, val) + static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, struct snd_kcontrol_new *tmpl) { @@ -494,18 +497,18 @@ static void via_free_kctls(struct hda_codec *codec) /* create input playback/capture controls for the given pin */ static int via_new_analog_input(struct via_spec *spec, const char *ctlname, - int idx, int mix_nid) + int type_idx, int idx, int mix_nid) { char name[32]; int err; sprintf(name, "%s Playback Volume", ctlname); - err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, + err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx, HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); if (err < 0) return err; sprintf(name, "%s Playback Switch", ctlname); - err = via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, + err = __via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, type_idx, HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); if (err < 0) return err; @@ -557,14 +560,12 @@ static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin); static void via_auto_init_analog_input(struct hda_codec *codec) { struct via_spec *spec = codec->spec; + const struct auto_pin_cfg *cfg = &spec->autocfg; unsigned int ctl; int i; - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; - if (!nid) - continue; - + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; if (spec->smart51_enabled && is_smart51_pins(spec, nid)) ctl = PIN_OUT; else if (i <= AUTO_PIN_FRONT_MIC) @@ -1322,15 +1323,14 @@ static void mute_aa_path(struct hda_codec *codec, int mute) } static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin) { - int res = 0; - int index; - for (index = AUTO_PIN_MIC; index < AUTO_PIN_FRONT_LINE; index++) { - if (pin == spec->autocfg.input_pins[index]) { - res = 1; - break; - } + const struct auto_pin_cfg *cfg = &spec->autocfg; + int i; + + for (i = 0; i < cfg->num_inputs; i++) { + if (pin == cfg->inputs[i].pin) + return cfg->inputs[i].type < AUTO_PIN_FRONT_LINE; } - return res; + return 0; } static int via_smart51_info(struct snd_kcontrol *kcontrol, @@ -1348,25 +1348,21 @@ static int via_smart51_get(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; - int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; + const struct auto_pin_cfg *cfg = &spec->autocfg; int on = 1; int i; - for (i = 0; i < ARRAY_SIZE(index); i++) { - hda_nid_t nid = spec->autocfg.input_pins[index[i]]; - if (nid) { - int ctl = - snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, - 0); - if (i == AUTO_PIN_FRONT_MIC - && spec->hp_independent_mode - && spec->codec_type != VT1718S) - continue; /* ignore FMic for independent HP */ - if (ctl & AC_PINCTL_IN_EN - && !(ctl & AC_PINCTL_OUT_EN)) - on = 0; - } + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; + int ctl = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + if (cfg->inputs[i].type >= AUTO_PIN_FRONT_LINE) + continue; + if (cfg->inputs[i].type == AUTO_PIN_FRONT_MIC && + spec->hp_independent_mode && spec->codec_type != VT1718S) + continue; /* ignore FMic for independent HP */ + if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN)) + on = 0; } *ucontrol->value.integer.value = on; return 0; @@ -1377,36 +1373,38 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; + const struct auto_pin_cfg *cfg = &spec->autocfg; int out_in = *ucontrol->value.integer.value ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; - int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; int i; - for (i = 0; i < ARRAY_SIZE(index); i++) { - hda_nid_t nid = spec->autocfg.input_pins[index[i]]; - if (i == AUTO_PIN_FRONT_MIC - && spec->hp_independent_mode - && spec->codec_type != VT1718S) + for (i = 0; i < cfg->num_inputs; i++) { + hda_nid_t nid = cfg->inputs[i].pin; + unsigned int parm; + + if (cfg->inputs[i].type >= AUTO_PIN_FRONT_LINE) + continue; + if (cfg->inputs[i].type == AUTO_PIN_FRONT_MIC && + spec->hp_independent_mode && spec->codec_type != VT1718S) continue; /* don't retask FMic for independent HP */ - if (nid) { - unsigned int parm = snd_hda_codec_read( - codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); - parm |= out_in; - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - parm); - if (out_in == AC_PINCTL_OUT_EN) { - mute_aa_path(codec, 1); - notify_aa_path_ctls(codec); - } - if (spec->codec_type == VT1718S) - snd_hda_codec_amp_stereo( + + parm = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); + parm |= out_in; + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + parm); + if (out_in == AC_PINCTL_OUT_EN) { + mute_aa_path(codec, 1); + notify_aa_path_ctls(codec); + } + if (spec->codec_type == VT1718S) { + snd_hda_codec_amp_stereo( codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE, HDA_AMP_UNMUTE); } - if (i == AUTO_PIN_FRONT_MIC) { + if (cfg->inputs[i].type == AUTO_PIN_FRONT_MIC) { if (spec->codec_type == VT1708S || spec->codec_type == VT1716S) { /* input = index 1 (AOW3) */ @@ -1442,7 +1440,7 @@ static struct snd_kcontrol_new via_smart51_mixer[2] = { static int via_smart51_build(struct via_spec *spec) { struct snd_kcontrol_new *knew; - int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; + const struct auto_pin_cfg *cfg = &spec->autocfg; hda_nid_t nid; int i; @@ -1450,13 +1448,14 @@ static int via_smart51_build(struct via_spec *spec) if (knew == NULL) return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(index); i++) { - nid = spec->autocfg.input_pins[index[i]]; - if (nid) { + for (i = 0; i < cfg->num_inputs; i++) { + nid = cfg->inputs[i].pin; + if (cfg->inputs[i].type < AUTO_PIN_FRONT_LINE) { knew = via_clone_control(spec, &via_smart51_mixer[1]); if (knew == NULL) return -ENOMEM; knew->subdevice = nid; + break; } } @@ -2419,7 +2418,7 @@ static int vt_auto_create_analog_input_ctls(struct via_spec *spec, hda_nid_t pin_idxs[], int num_idxs) { struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx; + int i, err, idx, type, type_idx = 0; /* for internal loopback recording select */ for (idx = 0; idx < num_idxs; idx++) { @@ -2431,20 +2430,23 @@ static int vt_auto_create_analog_input_ctls(struct via_spec *spec, } } - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (!cfg->input_pins[i]) - continue; - + for (i = 0; i < cfg->num_inputs; i++) { + type = cfg->inputs[i].type; for (idx = 0; idx < num_idxs; idx++) - if (pin_idxs[idx] == cfg->input_pins[i]) + if (pin_idxs[idx] == cfg->inputs[i].pin) break; if (idx >= num_idxs) continue; - err = via_new_analog_input(spec, auto_pin_cfg_labels[i], - idx, cap_nid); + if (i > 0 && type == cfg->inputs[i - 1].type) + type_idx++; + else + type_idx = 0; + err = via_new_analog_input(spec, auto_pin_cfg_labels[type], + type_idx, idx, cap_nid); if (err < 0) return err; - imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; + imux->items[imux->num_items].label = + snd_hda_get_input_pin_label(cfg, i); imux->items[imux->num_items].index = idx; imux->num_items++; } @@ -5513,7 +5515,7 @@ static int vt2002P_auto_create_analog_input_ctls(struct via_spec *spec, if (err < 0) return err; /* build volume/mute control of loopback */ - err = via_new_analog_input(spec, "Stereo Mixer", 3, 0x21); + err = via_new_analog_input(spec, "Stereo Mixer", 0, 3, 0x21); if (err < 0) return err; @@ -5836,7 +5838,7 @@ static int vt1812_auto_create_analog_input_ctls(struct via_spec *spec, return err; /* build volume/mute control of loopback */ - err = via_new_analog_input(spec, "Stereo Mixer", 5, 0x21); + err = via_new_analog_input(spec, "Stereo Mixer", 0, 5, 0x21); if (err < 0) return err; -- cgit v1.2.3-59-g8ed1b From 29cf28ae8dc244f89e213dc198f2286659d521b5 Mon Sep 17 00:00:00 2001 From: Rafi Rubin Date: Thu, 26 Aug 2010 00:54:54 -0400 Subject: HID: ntrig: add documention The doctumentation includes a brief introduction to the driver and explanations of the filtering parameters as well as a discussion of the need for and working of the filters. Signed-off-by: Rafi Rubin Signed-off-by: Jiri Kosina --- Documentation/input/ntrig.txt | 126 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 Documentation/input/ntrig.txt diff --git a/Documentation/input/ntrig.txt b/Documentation/input/ntrig.txt new file mode 100644 index 000000000000..be1fd981f73f --- /dev/null +++ b/Documentation/input/ntrig.txt @@ -0,0 +1,126 @@ +N-Trig touchscreen Driver +------------------------- + Copyright (c) 2008-2010 Rafi Rubin + Copyright (c) 2009-2010 Stephane Chatty + +This driver provides support for N-Trig pen and multi-touch sensors. Single +and multi-touch events are translated to the appropriate protocols for +the hid and input systems. Pen events are sufficiently hid compliant and +are left to the hid core. The driver also provides additional filtering +and utility functions accessible with sysfs and module parameters. + +This driver has been reported to work properly with multiple N-Trig devices +attached. + + +Parameters +---------- + +Note: values set at load time are global and will apply to all applicable +devices. Adjusting parameters with sysfs will override the load time values, +but only for that one device. + +The following parameters are used to configure filters to reduce noise: + +activate_slack number of fingers to ignore before processing events + +activation_height size threshold to activate immediately +activation_width + +min_height size threshold bellow which fingers are ignored +min_width both to decide activation and during activity + +deactivate_slack the number of "no contact" frames to ignore before + propagating the end of activity events + +When the last finger is removed from the device, it sends a number of empty +frames. By holding off on deactivation for a few frames we can tolerate false +erroneous disconnects, where the sensor may mistakenly not detect a finger that +is still present. Thus deactivate_slack addresses problems where a users might +see breaks in lines during drawing, or drop an object during a long drag. + + +Additional sysfs items +---------------------- + +These nodes just provide easy access to the ranges reported by the device. +sensor_logical_height the range for positions reported during activity +sensor_logical_width + +sensor_physical_height internal ranges not used for normal events but +sensor_physical_width useful for tuning + +All N-Trig devices with product id of 1 report events in the ranges of +X: 0-9600 +Y: 0-7200 +However not all of these devices have the same physical dimensions. Most +seem to be 12" sensors (Dell Latitude XT and XT2 and the HP TX2), and +at least one model (Dell Studio 17) has a 17" sensor. The ratio of physical +to logical sizes is used to adjust the size based filter parameters. + + +Filtering +--------- + +With the release of the early multi-touch firmwares it became increasingly +obvious that these sensors were prone to erroneous events. Users reported +seeing both inappropriately dropped contact and ghosts, contacts reported +where no finger was actually touching the screen. + +Deactivation slack helps prevent dropped contact for single touch use, but does +not address the problem of dropping one of more contacts while other contacts +are still active. Drops in the multi-touch context require additional +processing and should be handled in tandem with tacking. + +As observed ghost contacts are similar to actual use of the sensor, but they +seem to have different profiles. Ghost activity typically shows up as small +short lived touches. As such, I assume that the longer the continuous stream +of events the more likely those events are from a real contact, and that the +larger the size of each contact the more likely it is real. Balancing the +goals of preventing ghosts and accepting real events quickly (to minimize +user observable latency), the filter accumulates confidence for incoming +events until it hits thresholds and begins propagating. In the interest in +minimizing stored state as well as the cost of operations to make a decision, +I've kept that decision simple. + +Time is measured in terms of the number of fingers reported, not frames since +the probability of multiple simultaneous ghosts is expected to drop off +dramatically with increasing numbers. Rather than accumulate weight as a +function of size, I just use it as a binary threshold. A sufficiently large +contact immediately overrides the waiting period and leads to activation. + +Setting the activation size thresholds to large values will result in deciding +primarily on activation slack. If you see longer lived ghosts, turning up the +activation slack while reducing the size thresholds may suffice to eliminate +the ghosts while keeping the screen quite responsive to firm taps. + +Contacts continue to be filtered with min_height and min_width even after +the initial activation filter is satisfied. The intent is to provide +a mechanism for filtering out ghosts in the form of an extra finger while +you actually are using the screen. In practice this sort of ghost has +been far less problematic or relatively rare and I've left the defaults +set to 0 for both parameters, effectively turning off that filter. + +I don't know what the optimal values are for these filters. If the defaults +don't work for you, please play with the parameters. If you do find other +values more comfortable, I would appreciate feedback. + +The calibration of these devices does drift over time. If ghosts or contact +dropping worsen and interfere with the normal usage of your device, try +recalibrating it. + + +Calibration +----------- + +The N-Trig windows tools provide calibration and testing routines. Also an +unofficial unsupported set of user space tools including a calibrator is +available at: +http://code.launchpad.net/~rafi-seas/+junk/ntrig_calib + + +Tracking +-------- + +As of yet, all tested N-Trig firmwares do not track fingers. When multiple +contacts are active they seem to be sorted primarily by Y position. -- cgit v1.2.3-59-g8ed1b From a52dc34c0eea991115a9d789e9461f06768fa360 Mon Sep 17 00:00:00 2001 From: Rafi Rubin Date: Thu, 26 Aug 2010 00:54:55 -0400 Subject: HID: ntrig: a bit of whitespace cleanup Signed-off-by: Rafi Rubin Signed-off-by: Jiri Kosina --- drivers/hid/hid-ntrig.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index fb69b8c4953f..43e95dee9290 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -377,8 +377,8 @@ static struct attribute_group ntrig_attribute_group = { */ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) { struct ntrig_data *nd = hid_get_drvdata(hdev); @@ -448,13 +448,13 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, /* width/height mapped on TouchMajor/TouchMinor/Orientation */ case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MAJOR); + EV_ABS, ABS_MT_TOUCH_MAJOR); return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MINOR); + EV_ABS, ABS_MT_TOUCH_MINOR); input_set_abs_params(hi->input, ABS_MT_ORIENTATION, - 0, 1, 0, 0); + 0, 1, 0, 0); return 1; } return 0; @@ -468,8 +468,8 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, } static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) { /* No special mappings needed for the pen and single touch */ if (field->physical) @@ -489,7 +489,7 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, * and call input_mt_sync after each point if necessary */ static int ntrig_event (struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) + struct hid_usage *usage, __s32 value) { struct input_dev *input = field->hidinput->input; struct ntrig_data *nd = hid_get_drvdata(hid); @@ -860,7 +860,7 @@ err_free: static void ntrig_remove(struct hid_device *hdev) { sysfs_remove_group(&hdev->dev.kobj, - &ntrig_attribute_group); + &ntrig_attribute_group); hid_hw_stop(hdev); kfree(hid_get_drvdata(hdev)); } -- cgit v1.2.3-59-g8ed1b From 10466f5ae36074bb620e4add1247fbf78ee564c0 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Thu, 26 Aug 2010 15:30:03 -0700 Subject: MAINTAINERS: update broken web address The patch below updates a broken web address in the MAINTAINERS file. Signed-off-by: Justin P. Mattock Signed-off-by: Jiri Kosina --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 89399474d91f..68ccde3ddaf2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3305,7 +3305,7 @@ F: scripts/package/ KERNEL JANITORS L: kernel-janitors@vger.kernel.org -W: http://janitor.kernelnewbies.org/ +W: http://kernelnewbies.org/KernelJanitors S: Odd Fixes KERNEL NFSD, SUNRPC, AND LOCKD SERVERS -- cgit v1.2.3-59-g8ed1b From fcaf780b2ad352edaeb1d1c07a6da053266b1eed Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 24 Aug 2010 23:22:57 -0300 Subject: i7300_edac: start a driver for i7300 chipset (Clarksboro) Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/Kconfig | 7 + drivers/edac/Makefile | 1 + drivers/edac/i7300_edac.c | 1373 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci_ids.h | 19 +- 4 files changed, 1392 insertions(+), 8 deletions(-) create mode 100644 drivers/edac/i7300_edac.c diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 70bb350de996..4573ccc11f93 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -199,6 +199,13 @@ config EDAC_I5100 Support for error detection and correction the Intel San Clemente MCH. +config EDAC_I7300 + tristate "Intel Clarksboro MCH" + depends on EDAC_MM_EDAC && X86 && PCI + help + Support for error detection and correction the Intel + Clarksboro MCH (Intel 7300 chipset). + config EDAC_MPC85XX tristate "Freescale MPC83xx / MPC85xx" depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx) diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index ca6b1bb24ccc..bca4369d6b7a 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_EDAC_CPC925) += cpc925_edac.o obj-$(CONFIG_EDAC_I5000) += i5000_edac.o obj-$(CONFIG_EDAC_I5100) += i5100_edac.o obj-$(CONFIG_EDAC_I5400) += i5400_edac.o +obj-$(CONFIG_EDAC_I7300) += i7300_edac.o obj-$(CONFIG_EDAC_I7CORE) += i7core_edac.o obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o obj-$(CONFIG_EDAC_E752X) += e752x_edac.o diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c new file mode 100644 index 000000000000..eb3f30e96ee3 --- /dev/null +++ b/drivers/edac/i7300_edac.c @@ -0,0 +1,1373 @@ +/* + * Intel 7300 class Memory Controllers kernel module (Clarksboro) + * + * This file may be distributed under the terms of the + * GNU General Public License version 2 only. + * + * Copyright (c) 2010 by: + * Mauro Carvalho Chehab + * + * Red Hat Inc. http://www.redhat.com + * + * Intel 7300 Chipset Memory Controller Hub (MCH) - Datasheet + * http://www.intel.com/Assets/PDF/datasheet/318082.pdf + * + * TODO: The chipset allow checking for PCI Express errors also. Currently, + * the driver covers only memory error errors + * + * This driver uses "csrows" EDAC attribute to represent DIMM slot# + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "edac_core.h" + +/* + * Alter this version for the I7300 module when modifications are made + */ +#define I7300_REVISION " Ver: 1.0.0 " __DATE__ + +#define EDAC_MOD_STR "i7300_edac" + +#define i7300_printk(level, fmt, arg...) \ + edac_printk(level, "i7300", fmt, ##arg) + +#define i7300_mc_printk(mci, level, fmt, arg...) \ + edac_mc_chipset_printk(mci, level, "i7300", fmt, ##arg) + +/* + * Memory topology is organized as: + * Branch 0 - 2 channels: channels 0 and 1 (FDB0 PCI dev 21.0) + * Branch 1 - 2 channels: channels 2 and 3 (FDB1 PCI dev 22.0) + * Each channel can have to 8 DIMM sets (called as SLOTS) + * Slots should generally be filled in pairs + * Except on Single Channel mode of operation + * just slot 0/channel0 filled on this mode + * On normal operation mode, the two channels on a branch should be + filled together for the same SLOT# + * When in mirrored mode, Branch 1 replicate memory at Branch 0, so, the four + * channels on both branches should be filled + */ + +/* Limits for i7300 */ +#define MAX_SLOTS 8 +#define MAX_BRANCHES 2 +#define MAX_CH_PER_BRANCH 2 +#define MAX_CHANNELS (MAX_CH_PER_BRANCH * MAX_BRANCHES) +#define MAX_MIR 3 + +#define to_channel(ch, branch) ((((branch)) << 1) | (ch)) + +#define to_csrow(slot, ch, branch) \ + (to_channel(ch, branch) | ((slot) << 2)) + + +/* Device 16, + * Function 0: System Address (not documented) + * Function 1: Memory Branch Map, Control, Errors Register + * Function 2: FSB Error Registers + * + * All 3 functions of Device 16 (0,1,2) share the SAME DID and + * uses PCI_DEVICE_ID_INTEL_I7300_MCH_ERR for device 16 (0,1,2), + * PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 and PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 + * for device 21 (0,1). + */ + + /* OFFSETS for Function 0 */ +#define AMBASE 0x48 /* AMB Mem Mapped Reg Region Base */ +#define MAXCH 0x56 /* Max Channel Number */ +#define MAXDIMMPERCH 0x57 /* Max DIMM PER Channel Number */ + + /* OFFSETS for Function 1 */ +#define TOLM 0x6C +#define REDMEMB 0x7C + +#define MIR0 0x80 +#define MIR1 0x84 +#define MIR2 0x88 + +#if 0 +#define AMIR0 0x8c +#define AMIR1 0x90 +#define AMIR2 0x94 + +/*TODO: double check it */ +#define REC_ECC_LOCATOR_ODD(x) ((x) & 0x3fe00) /* bits [17:9] indicate ODD, [8:0] indicate EVEN */ + + /* Fatal error registers */ +#define FERR_FAT_FBD 0x98 + +/*TODO: double check it */ +#define FERR_FAT_FBDCHAN (3<<28) /* channel index where the highest-order error occurred */ + +#define NERR_FAT_FBD 0x9c +#define FERR_NF_FBD 0xa0 + + /* Non-fatal error register */ +#define NERR_NF_FBD 0xa4 + + /* Enable error mask */ +#define EMASK_FBD 0xa8 + +#define ERR0_FBD 0xac +#define ERR1_FBD 0xb0 +#define ERR2_FBD 0xb4 +#define MCERR_FBD 0xb8 + +#endif + +/* TODO: Dev 16 fn1 allows memory error injection - offsets 0x100-0x10b */ + + /* TODO: OFFSETS for Device 16 Function 2 */ + +/* + * Device 21, + * Function 0: Memory Map Branch 0 + * + * Device 22, + * Function 0: Memory Map Branch 1 + */ + + /* OFFSETS for Function 0 */ + +/* + * Note: Other Intel EDAC drivers use AMBPRESENT to identify if the available + * memory. From datasheet item 7.3.1 (FB-DIMM technology & organization), it + * seems that we cannot use this information directly for the same usage. + * Each memory slot may have up to 2 AMB interfaces, one for income and another + * for outcome interface to the next slot. + * For now, the driver just stores the AMB present registers, but rely only at + * the MTR info to detect memory. + * Datasheet is also not clear about how to map each AMBPRESENT registers to + * one of the 4 available channels. + */ +#define AMBPRESENT_0 0x64 +#define AMBPRESENT_1 0x66 + +const static u16 mtr_regs [MAX_SLOTS] = { + 0x80, 0x84, 0x88, 0x8c, + 0x82, 0x86, 0x8a, 0x8e +}; + +/* Defines to extract the vaious fields from the + * MTRx - Memory Technology Registers + */ +#define MTR_DIMMS_PRESENT(mtr) ((mtr) & (1 << 8)) +#define MTR_DIMMS_ETHROTTLE(mtr) ((mtr) & (1 << 7)) +#define MTR_DRAM_WIDTH(mtr) (((mtr) & (1 << 6)) ? 8 : 4) +#define MTR_DRAM_BANKS(mtr) (((mtr) & (1 << 5)) ? 8 : 4) +#define MTR_DIMM_RANKS(mtr) (((mtr) & (1 << 4)) ? 1 : 0) +#define MTR_DIMM_ROWS(mtr) (((mtr) >> 2) & 0x3) +#define MTR_DRAM_BANKS_ADDR_BITS 2 +#define MTR_DIMM_ROWS_ADDR_BITS(mtr) (MTR_DIMM_ROWS(mtr) + 13) +#define MTR_DIMM_COLS(mtr) ((mtr) & 0x3) +#define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10) + +#if 0 + /* OFFSETS for Function 1 */ + +/* TODO */ +#define NRECFGLOG 0x74 +#define RECFGLOG 0x78 +#define NRECMEMA 0xbe +#define NRECMEMB 0xc0 +#define NRECFB_DIMMA 0xc4 +#define NRECFB_DIMMB 0xc8 +#define NRECFB_DIMMC 0xcc +#define NRECFB_DIMMD 0xd0 +#define NRECFB_DIMME 0xd4 +#define NRECFB_DIMMF 0xd8 +#define REDMEMA 0xdC +#define RECMEMA 0xf0 +#define RECMEMB 0xf4 +#define RECFB_DIMMA 0xf8 +#define RECFB_DIMMB 0xec +#define RECFB_DIMMC 0xf0 +#define RECFB_DIMMD 0xf4 +#define RECFB_DIMME 0xf8 +#define RECFB_DIMMF 0xfC + +/* This applies to FERR_NF_FB-DIMM as well as FERR_FAT_FB-DIMM */ +static inline int extract_fbdchan_indx(u32 x) +{ + return (x>>28) & 0x3; +} +#endif + +#ifdef CONFIG_EDAC_DEBUG +/* MTR NUMROW */ +static const char *numrow_toString[] = { + "8,192 - 13 rows", + "16,384 - 14 rows", + "32,768 - 15 rows", + "65,536 - 16 rows" +}; + +/* MTR NUMCOL */ +static const char *numcol_toString[] = { + "1,024 - 10 columns", + "2,048 - 11 columns", + "4,096 - 12 columns", + "reserved" +}; +#endif + +#if 0 + +/* + * Error indicator bits and masks + * Error masks are according with Table 5-17 of i7300 datasheet + */ + +enum error_mask { + EMASK_M1 = 1<<0, /* Memory Write error on non-redundant retry */ + EMASK_M2 = 1<<1, /* Memory or FB-DIMM configuration CRC read error */ + EMASK_M3 = 1<<2, /* Reserved */ + EMASK_M4 = 1<<3, /* Uncorrectable Data ECC on Replay */ + EMASK_M5 = 1<<4, /* Aliased Uncorrectable Non-Mirrored Demand Data ECC */ + EMASK_M6 = 1<<5, /* Unsupported on i7300 */ + EMASK_M7 = 1<<6, /* Aliased Uncorrectable Resilver- or Spare-Copy Data ECC */ + EMASK_M8 = 1<<7, /* Aliased Uncorrectable Patrol Data ECC */ + EMASK_M9 = 1<<8, /* Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC */ + EMASK_M10 = 1<<9, /* Unsupported on i7300 */ + EMASK_M11 = 1<<10, /* Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC */ + EMASK_M12 = 1<<11, /* Non-Aliased Uncorrectable Patrol Data ECC */ + EMASK_M13 = 1<<12, /* Memory Write error on first attempt */ + EMASK_M14 = 1<<13, /* FB-DIMM Configuration Write error on first attempt */ + EMASK_M15 = 1<<14, /* Memory or FB-DIMM configuration CRC read error */ + EMASK_M16 = 1<<15, /* Channel Failed-Over Occurred */ + EMASK_M17 = 1<<16, /* Correctable Non-Mirrored Demand Data ECC */ + EMASK_M18 = 1<<17, /* Unsupported on i7300 */ + EMASK_M19 = 1<<18, /* Correctable Resilver- or Spare-Copy Data ECC */ + EMASK_M20 = 1<<19, /* Correctable Patrol Data ECC */ + EMASK_M21 = 1<<20, /* FB-DIMM Northbound parity error on FB-DIMM Sync Status */ + EMASK_M22 = 1<<21, /* SPD protocol Error */ + EMASK_M23 = 1<<22, /* Non-Redundant Fast Reset Timeout */ + EMASK_M24 = 1<<23, /* Refresh error */ + EMASK_M25 = 1<<24, /* Memory Write error on redundant retry */ + EMASK_M26 = 1<<25, /* Redundant Fast Reset Timeout */ + EMASK_M27 = 1<<26, /* Correctable Counter Threshold Exceeded */ + EMASK_M28 = 1<<27, /* DIMM-Spare Copy Completed */ + EMASK_M29 = 1<<28, /* DIMM-Isolation Completed */ +}; + +/* + * Names to translate bit error into something useful + */ +static const char *error_name[] = { + [0] = "Memory Write error on non-redundant retry", + [1] = "Memory or FB-DIMM configuration CRC read error", + /* Reserved */ + [3] = "Uncorrectable Data ECC on Replay", + [4] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC", + /* M6 Unsupported on i7300 */ + [6] = "Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", + [7] = "Aliased Uncorrectable Patrol Data ECC", + [8] = "Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC", + /* M10 Unsupported on i7300 */ + [10] = "Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", + [11] = "Non-Aliased Uncorrectable Patrol Data ECC", + [12] = "Memory Write error on first attempt", + [13] = "FB-DIMM Configuration Write error on first attempt", + [14] = "Memory or FB-DIMM configuration CRC read error", + [15] = "Channel Failed-Over Occurred", + [16] = "Correctable Non-Mirrored Demand Data ECC", + /* M18 Unsupported on i7300 */ + [18] = "Correctable Resilver- or Spare-Copy Data ECC", + [19] = "Correctable Patrol Data ECC", + [20] = "FB-DIMM Northbound parity error on FB-DIMM Sync Status", + [21] = "SPD protocol Error", + [22] = "Non-Redundant Fast Reset Timeout", + [23] = "Refresh error", + [24] = "Memory Write error on redundant retry", + [25] = "Redundant Fast Reset Timeout", + [26] = "Correctable Counter Threshold Exceeded", + [27] = "DIMM-Spare Copy Completed", + [28] = "DIMM-Isolation Completed", +}; + +/* Fatal errors */ +#define ERROR_FAT_MASK (EMASK_M1 | \ + EMASK_M2 | \ + EMASK_M23) + +/* Correctable errors */ +#define ERROR_NF_CORRECTABLE (EMASK_M27 | \ + EMASK_M20 | \ + EMASK_M19 | \ + EMASK_M18 | \ + EMASK_M17 | \ + EMASK_M16) +#define ERROR_NF_DIMM_SPARE (EMASK_M29 | \ + EMASK_M28) +#define ERROR_NF_SPD_PROTOCOL (EMASK_M22) +#define ERROR_NF_NORTH_CRC (EMASK_M21) + +/* Recoverable errors */ +#define ERROR_NF_RECOVERABLE (EMASK_M26 | \ + EMASK_M25 | \ + EMASK_M24 | \ + EMASK_M15 | \ + EMASK_M14 | \ + EMASK_M13 | \ + EMASK_M12 | \ + EMASK_M11 | \ + EMASK_M9 | \ + EMASK_M8 | \ + EMASK_M7 | \ + EMASK_M5) + +/* uncorrectable errors */ +#define ERROR_NF_UNCORRECTABLE (EMASK_M4) + +/* mask to all non-fatal errors */ +#define ERROR_NF_MASK (ERROR_NF_CORRECTABLE | \ + ERROR_NF_UNCORRECTABLE | \ + ERROR_NF_RECOVERABLE | \ + ERROR_NF_DIMM_SPARE | \ + ERROR_NF_SPD_PROTOCOL | \ + ERROR_NF_NORTH_CRC) + +/* + * Define error masks for the several registers + */ + +/* Enable all fatal and non fatal errors */ +#define ENABLE_EMASK_ALL (ERROR_FAT_MASK | ERROR_NF_MASK) + +/* mask for fatal error registers */ +#define FERR_FAT_MASK ERROR_FAT_MASK + +/* masks for non-fatal error register */ +static inline int to_nf_mask(unsigned int mask) +{ + return (mask & EMASK_M29) | (mask >> 3); +}; + +static inline int from_nf_ferr(unsigned int mask) +{ + return (mask & EMASK_M29) | /* Bit 28 */ + (mask & ((1 << 28) - 1) << 3); /* Bits 0 to 27 */ +}; + +#define FERR_NF_MASK to_nf_mask(ERROR_NF_MASK) +#define FERR_NF_CORRECTABLE to_nf_mask(ERROR_NF_CORRECTABLE) +#define FERR_NF_DIMM_SPARE to_nf_mask(ERROR_NF_DIMM_SPARE) +#define FERR_NF_SPD_PROTOCOL to_nf_mask(ERROR_NF_SPD_PROTOCOL) +#define FERR_NF_NORTH_CRC to_nf_mask(ERROR_NF_NORTH_CRC) +#define FERR_NF_RECOVERABLE to_nf_mask(ERROR_NF_RECOVERABLE) +#define FERR_NF_UNCORRECTABLE to_nf_mask(ERROR_NF_UNCORRECTABLE) + +#endif + +/* Device name and register DID (Device ID) */ +struct i7300_dev_info { + const char *ctl_name; /* name for this device */ + u16 fsb_mapping_errors; /* DID for the branchmap,control */ +}; + +/* Table of devices attributes supported by this driver */ +static const struct i7300_dev_info i7300_devs[] = { + { + .ctl_name = "I7300", + .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, + }, +}; + +struct i7300_dimm_info { + int megabytes; /* size, 0 means not present */ +}; + +/* driver private data structure */ +struct i7300_pvt { + struct pci_dev *system_address; /* 16.0 */ + struct pci_dev *branchmap_werrors; /* 16.1 */ + struct pci_dev *fsb_error_regs; /* 16.2 */ + struct pci_dev *branch_pci[MAX_BRANCHES]; /* 21.0 and 22.0 */ + + u16 tolm; /* top of low memory */ + u64 ambase; /* AMB BAR */ + + u16 mir[MAX_MIR]; + + u16 mtr[MAX_SLOTS][MAX_BRANCHES]; /* Memory Technlogy Reg */ + u16 ambpresent[MAX_CHANNELS]; /* AMB present regs */ + + /* DIMM information matrix, allocating architecture maximums */ + struct i7300_dimm_info dimm_info[MAX_SLOTS][MAX_CHANNELS]; +}; + +#if 0 +/* I7300 MCH error information retrieved from Hardware */ +struct i7300_error_info { + /* These registers are always read from the MC */ + u32 ferr_fat_fbd; /* First Errors Fatal */ + u32 nerr_fat_fbd; /* Next Errors Fatal */ + u32 ferr_nf_fbd; /* First Errors Non-Fatal */ + u32 nerr_nf_fbd; /* Next Errors Non-Fatal */ + + /* These registers are input ONLY if there was a Recoverable Error */ + u32 redmemb; /* Recoverable Mem Data Error log B */ + u16 recmema; /* Recoverable Mem Error log A */ + u32 recmemb; /* Recoverable Mem Error log B */ + + /* These registers are input ONLY if there was a Non-Rec Error */ + u16 nrecmema; /* Non-Recoverable Mem log A */ + u16 nrecmemb; /* Non-Recoverable Mem log B */ + +}; +#endif + +/* FIXME: Why do we need to have this static? */ +static struct edac_pci_ctl_info *i7300_pci; + + +#if 0 +/* note that nrec_rdwr changed from NRECMEMA to NRECMEMB between the 5000 and + 5400 better to use an inline function than a macro in this case */ +static inline int nrec_bank(struct i7300_error_info *info) +{ + return ((info->nrecmema) >> 12) & 0x7; +} +static inline int nrec_rank(struct i7300_error_info *info) +{ + return ((info->nrecmema) >> 8) & 0xf; +} +static inline int nrec_buf_id(struct i7300_error_info *info) +{ + return ((info->nrecmema)) & 0xff; +} +static inline int nrec_rdwr(struct i7300_error_info *info) +{ + return (info->nrecmemb) >> 31; +} +/* This applies to both NREC and REC string so it can be used with nrec_rdwr + and rec_rdwr */ +static inline const char *rdwr_str(int rdwr) +{ + return rdwr ? "Write" : "Read"; +} +static inline int nrec_cas(struct i7300_error_info *info) +{ + return ((info->nrecmemb) >> 16) & 0x1fff; +} +static inline int nrec_ras(struct i7300_error_info *info) +{ + return (info->nrecmemb) & 0xffff; +} +static inline int rec_bank(struct i7300_error_info *info) +{ + return ((info->recmema) >> 12) & 0x7; +} +static inline int rec_rank(struct i7300_error_info *info) +{ + return ((info->recmema) >> 8) & 0xf; +} +static inline int rec_rdwr(struct i7300_error_info *info) +{ + return (info->recmemb) >> 31; +} +static inline int rec_cas(struct i7300_error_info *info) +{ + return ((info->recmemb) >> 16) & 0x1fff; +} +static inline int rec_ras(struct i7300_error_info *info) +{ + return (info->recmemb) & 0xffff; +} + +/* + * i7300_get_error_info Retrieve the hardware error information from + * the hardware and cache it in the 'info' + * structure + */ +static void i7300_get_error_info(struct mem_ctl_info *mci, + struct i7300_error_info *info) +{ + struct i7300_pvt *pvt; + u32 value; + + pvt = mci->pvt_info; + + /* read in the 1st FATAL error register */ + pci_read_config_dword(pvt->branchmap_werrors, FERR_FAT_FBD, &value); + + /* Mask only the bits that the doc says are valid + */ + value &= (FERR_FAT_FBDCHAN | FERR_FAT_MASK); + + /* If there is an error, then read in the + NEXT FATAL error register and the Memory Error Log Register A + */ + if (value & FERR_FAT_MASK) { + info->ferr_fat_fbd = value; + + /* harvest the various error data we need */ + pci_read_config_dword(pvt->branchmap_werrors, + NERR_FAT_FBD, &info->nerr_fat_fbd); + pci_read_config_word(pvt->branchmap_werrors, + NRECMEMA, &info->nrecmema); + pci_read_config_word(pvt->branchmap_werrors, + NRECMEMB, &info->nrecmemb); + + /* Clear the error bits, by writing them back */ + pci_write_config_dword(pvt->branchmap_werrors, + FERR_FAT_FBD, value); + } else { + info->ferr_fat_fbd = 0; + info->nerr_fat_fbd = 0; + info->nrecmema = 0; + info->nrecmemb = 0; + } + + /* read in the 1st NON-FATAL error register */ + pci_read_config_dword(pvt->branchmap_werrors, FERR_NF_FBD, &value); + + /* If there is an error, then read in the 1st NON-FATAL error + * register as well */ + if (value & FERR_NF_MASK) { + info->ferr_nf_fbd = value; + + /* harvest the various error data we need */ + pci_read_config_dword(pvt->branchmap_werrors, + NERR_NF_FBD, &info->nerr_nf_fbd); + pci_read_config_word(pvt->branchmap_werrors, + RECMEMA, &info->recmema); + pci_read_config_dword(pvt->branchmap_werrors, + RECMEMB, &info->recmemb); + pci_read_config_dword(pvt->branchmap_werrors, + REDMEMB, &info->redmemb); + + /* Clear the error bits, by writing them back */ + pci_write_config_dword(pvt->branchmap_werrors, + FERR_NF_FBD, value); + } else { + info->ferr_nf_fbd = 0; + info->nerr_nf_fbd = 0; + info->recmema = 0; + info->recmemb = 0; + info->redmemb = 0; + } +} + +/* + * i7300_proccess_non_recoverable_info(struct mem_ctl_info *mci, + * struct i7300_error_info *info, + * int handle_errors); + * + * handle the Intel FATAL and unrecoverable errors, if any + */ +static void i7300_proccess_non_recoverable_info(struct mem_ctl_info *mci, + struct i7300_error_info *info, + unsigned long allErrors) +{ + char msg[EDAC_MC_LABEL_LEN + 1 + 90 + 80]; + int branch; + int channel; + int bank; + int buf_id; + int rank; + int rdwr; + int ras, cas; + int errnum; + char *type = NULL; + + if (!allErrors) + return; /* if no error, return now */ + + if (allErrors & ERROR_FAT_MASK) + type = "FATAL"; + else if (allErrors & FERR_NF_UNCORRECTABLE) + type = "NON-FATAL uncorrected"; + else + type = "NON-FATAL recoverable"; + + /* ONLY ONE of the possible error bits will be set, as per the docs */ + + branch = extract_fbdchan_indx(info->ferr_fat_fbd); + channel = branch; + + /* Use the NON-Recoverable macros to extract data */ + bank = nrec_bank(info); + rank = nrec_rank(info); + buf_id = nrec_buf_id(info); + rdwr = nrec_rdwr(info); + ras = nrec_ras(info); + cas = nrec_cas(info); + + debugf0("\t\tCSROW= %d Channels= %d,%d (Branch= %d " + "DRAM Bank= %d Buffer ID = %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, channel + 1, branch >> 1, bank, + buf_id, rdwr_str(rdwr), ras, cas); + + /* Only 1 bit will be on */ + errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); + + /* Form out message */ + snprintf(msg, sizeof(msg), + "%s (Branch=%d DRAM-Bank=%d Buffer ID = %d RDWR=%s " + "RAS=%d CAS=%d %s Err=0x%lx (%s))", + type, branch >> 1, bank, buf_id, rdwr_str(rdwr), ras, cas, + type, allErrors, error_name[errnum]); + + /* Call the helper to output message */ + edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg); +} + +/* + * i7300_process_fatal_error_info(struct mem_ctl_info *mci, + * struct i7300_error_info *info, + * int handle_errors); + * + * handle the Intel NON-FATAL errors, if any + */ +static void i7300_process_nonfatal_error_info(struct mem_ctl_info *mci, + struct i7300_error_info *info) +{ + char msg[EDAC_MC_LABEL_LEN + 1 + 90 + 80]; + unsigned long allErrors; + int branch; + int channel; + int bank; + int rank; + int rdwr; + int ras, cas; + int errnum; + + /* mask off the Error bits that are possible */ + allErrors = from_nf_ferr(info->ferr_nf_fbd & FERR_NF_MASK); + if (!allErrors) + return; /* if no error, return now */ + + /* ONLY ONE of the possible error bits will be set, as per the docs */ + + if (allErrors & (ERROR_NF_UNCORRECTABLE | ERROR_NF_RECOVERABLE)) { + i7300_proccess_non_recoverable_info(mci, info, allErrors); + return; + } + + /* Correctable errors */ + if (allErrors & ERROR_NF_CORRECTABLE) { + debugf0("\tCorrected bits= 0x%lx\n", allErrors); + + branch = extract_fbdchan_indx(info->ferr_nf_fbd); + + channel = 0; + if (REC_ECC_LOCATOR_ODD(info->redmemb)) + channel = 1; + + /* Convert channel to be based from zero, instead of + * from branch base of 0 */ + channel += branch; + + bank = rec_bank(info); + rank = rec_rank(info); + rdwr = rec_rdwr(info); + ras = rec_ras(info); + cas = rec_cas(info); + + /* Only 1 bit will be on */ + errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); + + debugf0("\t\tCSROW= %d Channel= %d (Branch %d " + "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, branch >> 1, bank, + rdwr_str(rdwr), ras, cas); + + /* Form out message */ + snprintf(msg, sizeof(msg), + "Corrected error (Branch=%d DRAM-Bank=%d RDWR=%s " + "RAS=%d CAS=%d, CE Err=0x%lx (%s))", + branch >> 1, bank, rdwr_str(rdwr), ras, cas, + allErrors, error_name[errnum]); + + /* Call the helper to output message */ + edac_mc_handle_fbd_ce(mci, rank, channel, msg); + + return; + } + + /* Miscelaneous errors */ + errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); + + branch = extract_fbdchan_indx(info->ferr_nf_fbd); + + i7300_mc_printk(mci, KERN_EMERG, + "Non-Fatal misc error (Branch=%d Err=%#lx (%s))", + branch >> 1, allErrors, error_name[errnum]); +} + +/* + * i7300_process_error_info Process the error info that is + * in the 'info' structure, previously retrieved from hardware + */ +static void i7300_process_error_info(struct mem_ctl_info *mci, + struct i7300_error_info *info) +{ u32 allErrors; + + /* First handle any fatal errors that occurred */ + allErrors = (info->ferr_fat_fbd & FERR_FAT_MASK); + i7300_proccess_non_recoverable_info(mci, info, allErrors); + + /* now handle any non-fatal errors that occurred */ + i7300_process_nonfatal_error_info(mci, info); +} + +/* + * i7300_clear_error Retrieve any error from the hardware + * but do NOT process that error. + * Used for 'clearing' out of previous errors + * Called by the Core module. + */ +static void i7300_clear_error(struct mem_ctl_info *mci) +{ + struct i7300_error_info info; + + i7300_get_error_info(mci, &info); +} + +/* + * i7300_check_error Retrieve and process errors reported by the + * hardware. Called by the Core module. + */ +static void i7300_check_error(struct mem_ctl_info *mci) +{ + struct i7300_error_info info; + debugf4("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + i7300_get_error_info(mci, &info); + i7300_process_error_info(mci, &info); +} + +/* + * i7300_enable_error_reporting + * Turn on the memory reporting features of the hardware + */ +static void i7300_enable_error_reporting(struct mem_ctl_info *mci) +{ + struct i7300_pvt *pvt; + u32 fbd_error_mask; + + pvt = mci->pvt_info; + + /* Read the FBD Error Mask Register */ + pci_read_config_dword(pvt->branchmap_werrors, EMASK_FBD, + &fbd_error_mask); + + /* Enable with a '0' */ + fbd_error_mask &= ~(ENABLE_EMASK_ALL); + + pci_write_config_dword(pvt->branchmap_werrors, EMASK_FBD, + fbd_error_mask); +} +#endif + +/* + * determine_mtr(pvt, csrow, channel) + * + * return the proper MTR register as determine by the csrow and desired channel + */ +static int decode_mtr(struct i7300_pvt *pvt, + int slot, int ch, int branch, + struct i7300_dimm_info *dinfo, + struct csrow_info *p_csrow) +{ + int mtr, ans, addrBits, channel; + + channel = to_channel(ch, branch); + + mtr = pvt->mtr[slot][branch]; + ans = MTR_DIMMS_PRESENT(mtr) ? 1 : 0; + + debugf2("\tMTR%d CH%d: DIMMs are %s (mtr)\n", + slot, channel, + ans ? "Present" : "NOT Present"); + + /* Determine if there is a DIMM present in this DIMM slot */ + +#if 0 + if (!amb_present || !ans) + return 0; +#else + if (!ans) + return 0; +#endif + + /* Start with the number of bits for a Bank + * on the DRAM */ + addrBits = MTR_DRAM_BANKS_ADDR_BITS; + /* Add thenumber of ROW bits */ + addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr); + /* add the number of COLUMN bits */ + addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr); + /* add the number of RANK bits */ + addrBits += MTR_DIMM_RANKS(mtr); + + addrBits += 6; /* add 64 bits per DIMM */ + addrBits -= 20; /* divide by 2^^20 */ + addrBits -= 3; /* 8 bits per bytes */ + + dinfo->megabytes = 1 << addrBits; + + debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); + + debugf2("\t\tELECTRICAL THROTTLING is %s\n", + MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled"); + + debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); + debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANKS(mtr) ? "double" : "single"); + debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]); + debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]); + debugf2("\t\tSIZE: %d MB\n", dinfo->megabytes); + + p_csrow->grain = 8; + p_csrow->nr_pages = dinfo->megabytes << 8; + p_csrow->mtype = MEM_FB_DDR2; + p_csrow->edac_mode = EDAC_S8ECD8ED; + + /* ask what device type on this row */ + if (MTR_DRAM_WIDTH(mtr)) + p_csrow->dtype = DEV_X8; + else + p_csrow->dtype = DEV_X4; + + return mtr; +} + +/* + * print_dimm_size + * + * also will output a DIMM matrix map, if debug is enabled, for viewing + * how the DIMMs are populated + */ +static void print_dimm_size(struct i7300_pvt *pvt) +{ + struct i7300_dimm_info *dinfo; + char *p, *mem_buffer; + int space, n; + int channel, slot; + + space = PAGE_SIZE; + mem_buffer = p = kmalloc(space, GFP_KERNEL); + if (p == NULL) { + i7300_printk(KERN_ERR, "MC: %s:%s() kmalloc() failed\n", + __FILE__, __func__); + return; + } + + n = snprintf(p, space, " "); + p += n; + space -= n; + for (channel = 0; channel < MAX_CHANNELS; channel++) { + n = snprintf(p, space, "channel %d | ", channel); + p += n; + space -= n; + } + debugf2("%s\n", mem_buffer); + p = mem_buffer; + space = PAGE_SIZE; + n = snprintf(p, space, "-------------------------------" + "------------------------------"); + p += n; + space -= n; + debugf2("%s\n", mem_buffer); + p = mem_buffer; + space = PAGE_SIZE; + + for (slot = 0; slot < MAX_SLOTS; slot++) { + n = snprintf(p, space, "csrow/SLOT %d ", slot); + p += n; + space -= n; + + for (channel = 0; channel < MAX_CHANNELS; channel++) { + dinfo = &pvt->dimm_info[slot][channel]; + n = snprintf(p, space, "%4d MB | ", dinfo->megabytes); + p += n; + space -= n; + } + + debugf2("%s\n", mem_buffer); + p = mem_buffer; + space = PAGE_SIZE; + } + + n = snprintf(p, space, "-------------------------------" + "------------------------------"); + p += n; + space -= n; + debugf2("%s\n", mem_buffer); + p = mem_buffer; + space = PAGE_SIZE; + + kfree(mem_buffer); +} + +/* + * i7300_init_csrows Initialize the 'csrows' table within + * the mci control structure with the + * addressing of memory. + * + * return: + * 0 success + * 1 no actual memory found on this MC + */ +static int i7300_init_csrows(struct mem_ctl_info *mci) +{ + struct i7300_pvt *pvt; + struct i7300_dimm_info *dinfo; + struct csrow_info *p_csrow; + int empty; + int mtr; + int ch, branch, slot, channel; + + pvt = mci->pvt_info; + + empty = 1; /* Assume NO memory */ + + debugf2("Memory Technology Registers:\n"); + + /* Get the AMB present registers for the four channels */ + for (branch = 0; branch < MAX_BRANCHES; branch++) { + /* Read and dump branch 0's MTRs */ + channel = to_channel(0, branch); + pci_read_config_word(pvt->branch_pci[branch], AMBPRESENT_0, + &pvt->ambpresent[channel]); + debugf2("\t\tAMB-present CH%d = 0x%x:\n", + channel, pvt->ambpresent[channel]); + + channel = to_channel(1, branch); + pci_read_config_word(pvt->branch_pci[branch], AMBPRESENT_1, + &pvt->ambpresent[channel]); + debugf2("\t\tAMB-present CH%d = 0x%x:\n", + channel, pvt->ambpresent[channel]); + } + + /* Get the set of MTR[0-7] regs by each branch */ + for (slot = 0; slot < MAX_SLOTS; slot++) { + int where = mtr_regs[slot]; + for (branch = 0; branch < MAX_BRANCHES; branch++) { + pci_read_config_word(pvt->branch_pci[branch], + where, + &pvt->mtr[slot][branch]); + for (ch = 0; ch < MAX_BRANCHES; ch++) { + int channel = to_channel(ch, branch); + + dinfo = &pvt->dimm_info[slot][channel]; + p_csrow = &mci->csrows[slot]; + + mtr = decode_mtr(pvt, slot, ch, branch, + dinfo, p_csrow); + /* if no DIMMS on this row, continue */ + if (!MTR_DIMMS_PRESENT(mtr)) + continue; + + p_csrow->csrow_idx = slot; + + /* FAKE OUT VALUES, FIXME */ + p_csrow->first_page = 0 + slot * 20; + p_csrow->last_page = 9 + slot * 20; + p_csrow->page_mask = 0xfff; + + empty = 0; + } + } + } + + return empty; +} + +static void decode_mir(int mir_no, u16 mir[MAX_MIR]) +{ + if (mir[mir_no] & 3) + debugf2("MIR%d: limit= 0x%x Branch(es) that participate: %s %s\n", + mir_no, + (mir[mir_no] >> 4) & 0xfff, + (mir[mir_no] & 1) ? "B0" : "", + (mir[mir_no] & 2) ? "B1": ""); +} + +/* + * i7300_get_mc_regs read in the necessary registers and + * cache locally + * + * Fills in the private data members + */ +static int i7300_get_mc_regs(struct mem_ctl_info *mci) +{ + struct i7300_pvt *pvt; + u32 actual_tolm; + int i, rc; + + pvt = mci->pvt_info; + + pci_read_config_dword(pvt->system_address, AMBASE, + (u32 *) &pvt->ambase); + + debugf2("AMBASE= 0x%lx\n", (long unsigned int)pvt->ambase); + + /* Get the Branch Map regs */ + pci_read_config_word(pvt->branchmap_werrors, TOLM, &pvt->tolm); + pvt->tolm >>= 12; + debugf2("TOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm, + pvt->tolm); + + actual_tolm = (u32) ((1000l * pvt->tolm) >> (30 - 28)); + debugf2("Actual TOLM byte addr=%u.%03u GB (0x%x)\n", + actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); + + pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir[0]); + pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir[1]); + pci_read_config_word(pvt->branchmap_werrors, MIR2, &pvt->mir[2]); + + /* Decode the MIR regs */ + for (i = 0; i < MAX_MIR; i++) + decode_mir(i, pvt->mir); + + rc = i7300_init_csrows(mci); + if (rc < 0) + return rc; + + /* Go and determine the size of each DIMM and place in an + * orderly matrix */ + print_dimm_size(pvt); + + return 0; +} + +/* + * i7300_put_devices 'put' all the devices that we have + * reserved via 'get' + */ +static void i7300_put_devices(struct mem_ctl_info *mci) +{ + struct i7300_pvt *pvt; + int branch; + + pvt = mci->pvt_info; + + /* Decrement usage count for devices */ + for (branch = 0; branch < MAX_CH_PER_BRANCH; branch++) + pci_dev_put(pvt->branch_pci[branch]); + pci_dev_put(pvt->fsb_error_regs); + pci_dev_put(pvt->branchmap_werrors); +} + +/* + * i7300_get_devices Find and perform 'get' operation on the MCH's + * device/functions we want to reference for this driver + * + * Need to 'get' device 16 func 1 and func 2 + */ +static int i7300_get_devices(struct mem_ctl_info *mci, int dev_idx) +{ + struct i7300_pvt *pvt; + struct pci_dev *pdev; + + pvt = mci->pvt_info; + + /* Attempt to 'get' the MCH register we want */ + pdev = NULL; + while (!pvt->branchmap_werrors || !pvt->fsb_error_regs) { + pdev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, pdev); + if (!pdev) { + /* End of list, leave */ + i7300_printk(KERN_ERR, + "'system address,Process Bus' " + "device not found:" + "vendor 0x%x device 0x%x ERR funcs " + "(broken BIOS?)\n", + PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_I7300_MCH_ERR); + goto error; + } + + /* Store device 16 funcs 1 and 2 */ + switch (PCI_FUNC(pdev->devfn)) { + case 1: + pvt->branchmap_werrors = pdev; + break; + case 2: + pvt->fsb_error_regs = pdev; + break; + } + } + + debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", + pci_name(pvt->system_address), + pvt->system_address->vendor, pvt->system_address->device); + debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->branchmap_werrors), + pvt->branchmap_werrors->vendor, pvt->branchmap_werrors->device); + debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->fsb_error_regs), + pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device); + + pvt->branch_pci[0] = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_I7300_MCH_FB0, + NULL); + if (!pvt->branch_pci[0]) { + i7300_printk(KERN_ERR, + "MC: 'BRANCH 0' device not found:" + "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n", + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_FB0); + goto error; + } + + pvt->branch_pci[1] = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_I7300_MCH_FB1, + NULL); + if (!pvt->branch_pci[1]) { + i7300_printk(KERN_ERR, + "MC: 'BRANCH 1' device not found:" + "vendor 0x%x device 0x%x Func 0 " + "(broken BIOS?)\n", + PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_I7300_MCH_FB1); + goto error; + } + + return 0; + +error: + i7300_put_devices(mci); + return -ENODEV; +} + +/* + * i7300_probe1 Probe for ONE instance of device to see if it is + * present. + * return: + * 0 for FOUND a device + * < 0 for error code + */ +static int i7300_probe1(struct pci_dev *pdev, int dev_idx) +{ + struct mem_ctl_info *mci; + struct i7300_pvt *pvt; + int num_channels; + int num_dimms_per_channel; + int num_csrows; + + if (dev_idx >= ARRAY_SIZE(i7300_devs)) + return -EINVAL; + + debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n", + __func__, + pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + + /* We only are looking for func 0 of the set */ + if (PCI_FUNC(pdev->devfn) != 0) + return -ENODEV; + + /* As we don't have a motherboard identification routine to determine + * actual number of slots/dimms per channel, we thus utilize the + * resource as specified by the chipset. Thus, we might have + * have more DIMMs per channel than actually on the mobo, but this + * allows the driver to support upto the chipset max, without + * some fancy mobo determination. + */ + num_dimms_per_channel = MAX_SLOTS; + num_channels = MAX_CHANNELS; + num_csrows = MAX_SLOTS * MAX_CHANNELS; + + debugf0("MC: %s(): Number of - Channels= %d DIMMS= %d CSROWS= %d\n", + __func__, num_channels, num_dimms_per_channel, num_csrows); + + /* allocate a new MC control structure */ + mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0); + + if (mci == NULL) + return -ENOMEM; + + debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); + + mci->dev = &pdev->dev; /* record ptr to the generic device */ + + pvt = mci->pvt_info; + pvt->system_address = pdev; /* Record this device in our private */ + + /* 'get' the pci devices we want to reserve for our use */ + if (i7300_get_devices(mci, dev_idx)) + goto fail0; + + mci->mc_idx = 0; + mci->mtype_cap = MEM_FLAG_FB_DDR2; + mci->edac_ctl_cap = EDAC_FLAG_NONE; + mci->edac_cap = EDAC_FLAG_NONE; + mci->mod_name = "i7300_edac.c"; + mci->mod_ver = I7300_REVISION; + mci->ctl_name = i7300_devs[dev_idx].ctl_name; + mci->dev_name = pci_name(pdev); + mci->ctl_page_to_phys = NULL; + +#if 0 + /* Set the function pointer to an actual operation function */ + mci->edac_check = i7300_check_error; +#endif + + /* initialize the MC control structure 'csrows' table + * with the mapping and control information */ + if (i7300_get_mc_regs(mci)) { + debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n" + " because i7300_init_csrows() returned nonzero " + "value\n"); + mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */ + } else { +#if 0 + debugf1("MC: Enable error reporting now\n"); + i7300_enable_error_reporting(mci); +#endif + } + + /* add this new MC control structure to EDAC's list of MCs */ + if (edac_mc_add_mc(mci)) { + debugf0("MC: " __FILE__ + ": %s(): failed edac_mc_add_mc()\n", __func__); + /* FIXME: perhaps some code should go here that disables error + * reporting if we just enabled it + */ + goto fail1; + } + +#if 0 + i7300_clear_error(mci); +#endif + + /* allocating generic PCI control info */ + i7300_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR); + if (!i7300_pci) { + printk(KERN_WARNING + "%s(): Unable to create PCI control\n", + __func__); + printk(KERN_WARNING + "%s(): PCI error report via EDAC not setup\n", + __func__); + } + + return 0; + + /* Error exit unwinding stack */ +fail1: + + i7300_put_devices(mci); + +fail0: + edac_mc_free(mci); + return -ENODEV; +} + +/* + * i7300_init_one constructor for one instance of device + * + * returns: + * negative on error + * count (>= 0) + */ +static int __devinit i7300_init_one(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + int rc; + + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + /* wake up device */ + rc = pci_enable_device(pdev); + if (rc == -EIO) + return rc; + + /* now probe and enable the device */ + return i7300_probe1(pdev, id->driver_data); +} + +/* + * i7300_remove_one destructor for one instance of device + * + */ +static void __devexit i7300_remove_one(struct pci_dev *pdev) +{ + struct mem_ctl_info *mci; + + debugf0(__FILE__ ": %s()\n", __func__); + + if (i7300_pci) + edac_pci_release_generic_ctl(i7300_pci); + + mci = edac_mc_del_mc(&pdev->dev); + if (!mci) + return; + + /* retrieve references to resources, and free those resources */ + i7300_put_devices(mci); + + edac_mc_free(mci); +} + +/* + * pci_device_id table for which devices we are looking for + * + * The "E500P" device is the first device supported. + */ +static const struct pci_device_id i7300_pci_tbl[] __devinitdata = { + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_ERR)}, + {0,} /* 0 terminated list. */ +}; + +MODULE_DEVICE_TABLE(pci, i7300_pci_tbl); + +/* + * i7300_driver pci_driver structure for this module + * + */ +static struct pci_driver i7300_driver = { + .name = "i7300_edac", + .probe = i7300_init_one, + .remove = __devexit_p(i7300_remove_one), + .id_table = i7300_pci_tbl, +}; + +/* + * i7300_init Module entry function + * Try to initialize this module for its devices + */ +static int __init i7300_init(void) +{ + int pci_rc; + + debugf2("MC: " __FILE__ ": %s()\n", __func__); + + /* Ensure that the OPSTATE is set correctly for POLL or NMI */ + opstate_init(); + + pci_rc = pci_register_driver(&i7300_driver); + + return (pci_rc < 0) ? pci_rc : 0; +} + +/* + * i7300_exit() Module exit function + * Unregister the driver + */ +static void __exit i7300_exit(void) +{ + debugf2("MC: " __FILE__ ": %s()\n", __func__); + pci_unregister_driver(&i7300_driver); +} + +module_init(i7300_init); +module_exit(i7300_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_DESCRIPTION("MC Driver for Intel I7300 memory controllers - " + I7300_REVISION); + +module_param(edac_op_state, int, 0444); +MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f6a3b2d36cad..2eabe311f0d3 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -815,7 +815,7 @@ #define PCI_VENDOR_ID_ANIGMA 0x1051 #define PCI_DEVICE_ID_ANIGMA_MC145575 0x0100 - + #define PCI_VENDOR_ID_EFAR 0x1055 #define PCI_DEVICE_ID_EFAR_SLC90E66_1 0x9130 #define PCI_DEVICE_ID_EFAR_SLC90E66_3 0x9463 @@ -1446,7 +1446,7 @@ #define PCI_VENDOR_ID_ZIATECH 0x1138 #define PCI_DEVICE_ID_ZIATECH_5550_HC 0x5550 - + #define PCI_VENDOR_ID_SYSKONNECT 0x1148 #define PCI_DEVICE_ID_SYSKONNECT_TR 0x4200 @@ -1600,8 +1600,8 @@ #define PCI_DEVICE_ID_RP8OCTA 0x0005 #define PCI_DEVICE_ID_RP8J 0x0006 #define PCI_DEVICE_ID_RP4J 0x0007 -#define PCI_DEVICE_ID_RP8SNI 0x0008 -#define PCI_DEVICE_ID_RP16SNI 0x0009 +#define PCI_DEVICE_ID_RP8SNI 0x0008 +#define PCI_DEVICE_ID_RP16SNI 0x0009 #define PCI_DEVICE_ID_RPP4 0x000A #define PCI_DEVICE_ID_RPP8 0x000B #define PCI_DEVICE_ID_RP4M 0x000D @@ -1611,9 +1611,9 @@ #define PCI_DEVICE_ID_URP8INTF 0x0802 #define PCI_DEVICE_ID_URP16INTF 0x0803 #define PCI_DEVICE_ID_URP8OCTA 0x0805 -#define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C +#define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C #define PCI_DEVICE_ID_UPCI_RM3_4PORT 0x080D -#define PCI_DEVICE_ID_CRP16INTF 0x0903 +#define PCI_DEVICE_ID_CRP16INTF 0x0903 #define PCI_VENDOR_ID_CYCLADES 0x120e #define PCI_DEVICE_ID_CYCLOM_Y_Lo 0x0100 @@ -2139,7 +2139,7 @@ #define PCI_DEVICE_ID_RASTEL_2PORT 0x2000 #define PCI_VENDOR_ID_ZOLTRIX 0x15b0 -#define PCI_DEVICE_ID_ZOLTRIX_2BD0 0x2bd0 +#define PCI_DEVICE_ID_ZOLTRIX_2BD0 0x2bd0 #define PCI_VENDOR_ID_MELLANOX 0x15b3 #define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44 @@ -2413,7 +2413,7 @@ #define PCI_DEVICE_ID_INTEL_82815_MC 0x1130 #define PCI_DEVICE_ID_INTEL_82815_CGC 0x1132 #define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221 -#define PCI_DEVICE_ID_INTEL_7505_0 0x2550 +#define PCI_DEVICE_ID_INTEL_7505_0 0x2550 #define PCI_DEVICE_ID_INTEL_7205_0 0x255d #define PCI_DEVICE_ID_INTEL_82437 0x122d #define PCI_DEVICE_ID_INTEL_82371FB_0 0x122e @@ -2616,6 +2616,9 @@ #define PCI_DEVICE_ID_INTEL_MCH_PC 0x3599 #define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a #define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e +#define PCI_DEVICE_ID_INTEL_I7300_MCH_ERR 0x360c +#define PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 0x360f +#define PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 0x3610 #define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b #define PCI_DEVICE_ID_INTEL_FBD_CNB 0x360c #define PCI_DEVICE_ID_INTEL_IOAT_JSF0 0x3710 -- cgit v1.2.3-59-g8ed1b From af3d8831e7e2036cd453c852d206b892b19c8820 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Aug 2010 20:58:45 -0300 Subject: i7300_edac: display info if ECC is enabled or not Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index eb3f30e96ee3..db194b6b3e42 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -80,17 +80,19 @@ */ /* OFFSETS for Function 0 */ -#define AMBASE 0x48 /* AMB Mem Mapped Reg Region Base */ -#define MAXCH 0x56 /* Max Channel Number */ -#define MAXDIMMPERCH 0x57 /* Max DIMM PER Channel Number */ +#define AMBASE 0x48 /* AMB Mem Mapped Reg Region Base */ +#define MAXCH 0x56 /* Max Channel Number */ +#define MAXDIMMPERCH 0x57 /* Max DIMM PER Channel Number */ /* OFFSETS for Function 1 */ -#define TOLM 0x6C -#define REDMEMB 0x7C +#define MC_SETTINGS 0x40 -#define MIR0 0x80 -#define MIR1 0x84 -#define MIR2 0x88 +#define TOLM 0x6C +#define REDMEMB 0x7C + +#define MIR0 0x80 +#define MIR1 0x84 +#define MIR2 0x88 #if 0 #define AMIR0 0x8c @@ -393,6 +395,7 @@ struct i7300_pvt { u16 tolm; /* top of low memory */ u64 ambase; /* AMB BAR */ + u32 mc_settings; u16 mir[MAX_MIR]; @@ -1020,6 +1023,15 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) debugf2("Actual TOLM byte addr=%u.%03u GB (0x%x)\n", actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); + /* Get memory controller settings */ + pci_read_config_dword(pvt->branchmap_werrors, MC_SETTINGS, + &pvt->mc_settings); + debugf0("Memory controller operating on %s mode\n", + pvt->mc_settings & (1 << 16)? "mirrored" : "non-mirrored"); + debugf0("Error detection is %s\n", + pvt->mc_settings & (1 << 5)? "enabled" : "disabled"); + + /* Get Memory Interleave Range registers */ pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir[0]); pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir[1]); pci_read_config_word(pvt->branchmap_werrors, MIR2, &pvt->mir[2]); -- cgit v1.2.3-59-g8ed1b From c3af2eaf7a3257f7b44165ec487215574c47fd32 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Aug 2010 19:54:51 -0300 Subject: i7300_edac: add global error registers Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 174 ++++++++++++++++++++++++---------------------- 1 file changed, 92 insertions(+), 82 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index db194b6b3e42..7e035b6d0d0f 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -50,7 +50,7 @@ * Except on Single Channel mode of operation * just slot 0/channel0 filled on this mode * On normal operation mode, the two channels on a branch should be - filled together for the same SLOT# + * filled together for the same SLOT# * When in mirrored mode, Branch 1 replicate memory at Branch 0, so, the four * channels on both branches should be filled */ @@ -67,16 +67,22 @@ #define to_csrow(slot, ch, branch) \ (to_channel(ch, branch) | ((slot) << 2)) - -/* Device 16, - * Function 0: System Address (not documented) - * Function 1: Memory Branch Map, Control, Errors Register - * Function 2: FSB Error Registers - * +/* + * I7300 devices * All 3 functions of Device 16 (0,1,2) share the SAME DID and * uses PCI_DEVICE_ID_INTEL_I7300_MCH_ERR for device 16 (0,1,2), * PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 and PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 * for device 21 (0,1). + */ + +/**************************************************** + * i7300 Register definitions for memory enumberation + ****************************************************/ + +/* + * Device 16, + * Function 0: System Address (not documented) + * Function 1: Memory Branch Map, Control, Errors Register */ /* OFFSETS for Function 0 */ @@ -94,50 +100,6 @@ #define MIR1 0x84 #define MIR2 0x88 -#if 0 -#define AMIR0 0x8c -#define AMIR1 0x90 -#define AMIR2 0x94 - -/*TODO: double check it */ -#define REC_ECC_LOCATOR_ODD(x) ((x) & 0x3fe00) /* bits [17:9] indicate ODD, [8:0] indicate EVEN */ - - /* Fatal error registers */ -#define FERR_FAT_FBD 0x98 - -/*TODO: double check it */ -#define FERR_FAT_FBDCHAN (3<<28) /* channel index where the highest-order error occurred */ - -#define NERR_FAT_FBD 0x9c -#define FERR_NF_FBD 0xa0 - - /* Non-fatal error register */ -#define NERR_NF_FBD 0xa4 - - /* Enable error mask */ -#define EMASK_FBD 0xa8 - -#define ERR0_FBD 0xac -#define ERR1_FBD 0xb0 -#define ERR2_FBD 0xb4 -#define MCERR_FBD 0xb8 - -#endif - -/* TODO: Dev 16 fn1 allows memory error injection - offsets 0x100-0x10b */ - - /* TODO: OFFSETS for Device 16 Function 2 */ - -/* - * Device 21, - * Function 0: Memory Map Branch 0 - * - * Device 22, - * Function 0: Memory Map Branch 1 - */ - - /* OFFSETS for Function 0 */ - /* * Note: Other Intel EDAC drivers use AMBPRESENT to identify if the available * memory. From datasheet item 7.3.1 (FB-DIMM technology & organization), it @@ -171,37 +133,6 @@ const static u16 mtr_regs [MAX_SLOTS] = { #define MTR_DIMM_COLS(mtr) ((mtr) & 0x3) #define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10) -#if 0 - /* OFFSETS for Function 1 */ - -/* TODO */ -#define NRECFGLOG 0x74 -#define RECFGLOG 0x78 -#define NRECMEMA 0xbe -#define NRECMEMB 0xc0 -#define NRECFB_DIMMA 0xc4 -#define NRECFB_DIMMB 0xc8 -#define NRECFB_DIMMC 0xcc -#define NRECFB_DIMMD 0xd0 -#define NRECFB_DIMME 0xd4 -#define NRECFB_DIMMF 0xd8 -#define REDMEMA 0xdC -#define RECMEMA 0xf0 -#define RECMEMB 0xf4 -#define RECFB_DIMMA 0xf8 -#define RECFB_DIMMB 0xec -#define RECFB_DIMMC 0xf0 -#define RECFB_DIMMD 0xf4 -#define RECFB_DIMME 0xf8 -#define RECFB_DIMMF 0xfC - -/* This applies to FERR_NF_FB-DIMM as well as FERR_FAT_FB-DIMM */ -static inline int extract_fbdchan_indx(u32 x) -{ - return (x>>28) & 0x3; -} -#endif - #ifdef CONFIG_EDAC_DEBUG /* MTR NUMROW */ static const char *numrow_toString[] = { @@ -220,6 +151,85 @@ static const char *numcol_toString[] = { }; #endif +/************************************************ + * i7300 Register definitions for error detection + ************************************************/ +/* + * Device 16.2: Global Error Registers + */ + +#define FERR_GLOBAL_LO 0x40 +static const char *ferr_global_name[] = { + [31] = "Internal MCH Fatal Error", + [30] = "Intel QuickData Technology Device Fatal Error", + [29] = "FSB1 Fatal Error", + [28] = "FSB0 Fatal Error", + [27] = "FBD Channel 3 Fatal Error", + [26] = "FBD Channel 2 Fatal Error", + [25] = "FBD Channel 1 Fatal Error", + [24] = "FBD Channel 0 Fatal Error", + [23] = "PCI Express Device 7Fatal Error", + [22] = "PCI Express Device 6 Fatal Error", + [21] = "PCI Express Device 5 Fatal Error", + [20] = "PCI Express Device 4 Fatal Error", + [19] = "PCI Express Device 3 Fatal Error", + [18] = "PCI Express Device 2 Fatal Error", + [17] = "PCI Express Device 1 Fatal Error", + [16] = "ESI Fatal Error", + [15] = "Internal MCH Non-Fatal Error", + [14] = "Intel QuickData Technology Device Non Fatal Error", + [13] = "FSB1 Non-Fatal Error", + [12] = "FSB 0 Non-Fatal Error", + [11] = "FBD Channel 3 Non-Fatal Error", + [10] = "FBD Channel 2 Non-Fatal Error", + [9] = "FBD Channel 1 Non-Fatal Error", + [8] = "FBD Channel 0 Non-Fatal Error", + [7] = "PCI Express Device 7 Non-Fatal Error", + [6] = "PCI Express Device 6 Non-Fatal Error", + [5] = "PCI Express Device 5 Non-Fatal Error", + [4] = "PCI Express Device 4 Non-Fatal Error", + [3] = "PCI Express Device 3 Non-Fatal Error", + [2] = "PCI Express Device 2 Non-Fatal Error", + [1] = "PCI Express Device 1 Non-Fatal Error", + [0] = "ESI Non-Fatal Error", +}; + +#define NERR_GLOBAL 0x44 +static const char *nerr_global_name[] = { + [31] = "Internal MCH Fatal Error", + [30] = "Intel QuickData Technology Device Fatal Error", + [29] = "FSB1 Fatal Error", + [28] = "FSB0 Fatal Error", + [27] = "FSB2 Fatal Error", + [26] = "FSB3 Fatal Error", + [25] = "Reserved", + [24] = "FBD Channel 0,1,2 or 3 Fatal Error", + [23] = "PCI Express Device 7 Fatal Error", + [22] = "PCI Express Device 6 Fatal Error", + [21] = "PCI Express Device 5 Fatal Error", + [20] = "PCI Express Device 4 Fatal Error", + [19] = "PCI Express Device 3 Fatal Error", + [18] = "PCI Express Device 2 Fatal Error", + [17] = "PCI Express Device 1 Fatal Error", + [16] = "ESI Fatal Error", + [15] = "Internal MCH Non-Fatal Error", + [14] = "Intel QuickData Technology Device Non Fatal Error", + [13] = "FSB1 Non-Fatal Error", + [12] = "FSB0 Non-Fatal Error", + [11] = "FSB2 Non-Fatal Error", + [10] = "FSB3 Non-Fatal Error", + [9] = "Reserved", + [8] = "FBD Channel 0,1, 2 or 3 Non-Fatal Error", + [7] = "PCI Express Device 7 Non-Fatal Error", + [6] = "PCI Express Device 6 Non-Fatal Error", + [5] = "PCI Express Device 5 Non-Fatal Error", + [4] = "PCI Express Device 4 Non-Fatal Error", + [3] = "PCI Express Device 3 Non-Fatal Error", + [2] = "PCI Express Device 2 Non-Fatal Error", + [1] = "PCI Express Device 1 Non-Fatal Error", + [0] = "ESI Non-Fatal Error", +}; + #if 0 /* -- cgit v1.2.3-59-g8ed1b From 116389ed21e4ad88f65e7ec5ed6ca224acb89115 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Aug 2010 23:19:54 -0300 Subject: i7300_edac: Add a FIXME note about the error correction type Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 7e035b6d0d0f..36265e21fef2 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -841,6 +841,15 @@ static int decode_mtr(struct i7300_pvt *pvt, p_csrow->grain = 8; p_csrow->nr_pages = dinfo->megabytes << 8; p_csrow->mtype = MEM_FB_DDR2; + + /* + * FIXME: the type of error detection actually depends of the + * mode of operation. When it is just one single memory chip, at + * socket 0, channel 0, it uses 8-byte-over-32-byte SECDED+ code. + * In normal or mirrored mode, it uses Single Device Data correction, + * with the possibility of using an extended algorithm for x8 memories + * See datasheet Sections 7.3.6 to 7.3.8 + */ p_csrow->edac_mode = EDAC_S8ECD8ED; /* ask what device type on this row */ -- cgit v1.2.3-59-g8ed1b From 3e57eef64c53d4a45790fb7bb60a4ee6bf2bad30 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Aug 2010 23:38:11 -0300 Subject: i7300_edac: Better name PCI devices Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 86 +++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 36265e21fef2..3e60dbaa0e7e 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -398,10 +398,10 @@ struct i7300_dimm_info { /* driver private data structure */ struct i7300_pvt { - struct pci_dev *system_address; /* 16.0 */ - struct pci_dev *branchmap_werrors; /* 16.1 */ - struct pci_dev *fsb_error_regs; /* 16.2 */ - struct pci_dev *branch_pci[MAX_BRANCHES]; /* 21.0 and 22.0 */ + struct pci_dev *pci_dev_16_0_fsb_ctlr; /* 16.0 */ + struct pci_dev *pci_dev_16_1_fsb_addr_map; /* 16.1 */ + struct pci_dev *pci_dev_16_2_fsb_err_regs; /* 16.2 */ + struct pci_dev *pci_dev_2x_0_fbd_branch[MAX_BRANCHES]; /* 21.0 and 22.0 */ u16 tolm; /* top of low memory */ u64 ambase; /* AMB BAR */ @@ -509,7 +509,7 @@ static void i7300_get_error_info(struct mem_ctl_info *mci, pvt = mci->pvt_info; /* read in the 1st FATAL error register */ - pci_read_config_dword(pvt->branchmap_werrors, FERR_FAT_FBD, &value); + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, FERR_FAT_FBD, &value); /* Mask only the bits that the doc says are valid */ @@ -522,15 +522,15 @@ static void i7300_get_error_info(struct mem_ctl_info *mci, info->ferr_fat_fbd = value; /* harvest the various error data we need */ - pci_read_config_dword(pvt->branchmap_werrors, + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, NERR_FAT_FBD, &info->nerr_fat_fbd); - pci_read_config_word(pvt->branchmap_werrors, + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, NRECMEMA, &info->nrecmema); - pci_read_config_word(pvt->branchmap_werrors, + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, NRECMEMB, &info->nrecmemb); /* Clear the error bits, by writing them back */ - pci_write_config_dword(pvt->branchmap_werrors, + pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, FERR_FAT_FBD, value); } else { info->ferr_fat_fbd = 0; @@ -540,7 +540,7 @@ static void i7300_get_error_info(struct mem_ctl_info *mci, } /* read in the 1st NON-FATAL error register */ - pci_read_config_dword(pvt->branchmap_werrors, FERR_NF_FBD, &value); + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, FERR_NF_FBD, &value); /* If there is an error, then read in the 1st NON-FATAL error * register as well */ @@ -548,17 +548,17 @@ static void i7300_get_error_info(struct mem_ctl_info *mci, info->ferr_nf_fbd = value; /* harvest the various error data we need */ - pci_read_config_dword(pvt->branchmap_werrors, + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, NERR_NF_FBD, &info->nerr_nf_fbd); - pci_read_config_word(pvt->branchmap_werrors, + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, RECMEMA, &info->recmema); - pci_read_config_dword(pvt->branchmap_werrors, + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, RECMEMB, &info->recmemb); - pci_read_config_dword(pvt->branchmap_werrors, + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, REDMEMB, &info->redmemb); /* Clear the error bits, by writing them back */ - pci_write_config_dword(pvt->branchmap_werrors, + pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, FERR_NF_FBD, value); } else { info->ferr_nf_fbd = 0; @@ -769,13 +769,13 @@ static void i7300_enable_error_reporting(struct mem_ctl_info *mci) pvt = mci->pvt_info; /* Read the FBD Error Mask Register */ - pci_read_config_dword(pvt->branchmap_werrors, EMASK_FBD, + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, EMASK_FBD, &fbd_error_mask); /* Enable with a '0' */ fbd_error_mask &= ~(ENABLE_EMASK_ALL); - pci_write_config_dword(pvt->branchmap_werrors, EMASK_FBD, + pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, EMASK_FBD, fbd_error_mask); } #endif @@ -957,13 +957,13 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) for (branch = 0; branch < MAX_BRANCHES; branch++) { /* Read and dump branch 0's MTRs */ channel = to_channel(0, branch); - pci_read_config_word(pvt->branch_pci[branch], AMBPRESENT_0, + pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], AMBPRESENT_0, &pvt->ambpresent[channel]); debugf2("\t\tAMB-present CH%d = 0x%x:\n", channel, pvt->ambpresent[channel]); channel = to_channel(1, branch); - pci_read_config_word(pvt->branch_pci[branch], AMBPRESENT_1, + pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], AMBPRESENT_1, &pvt->ambpresent[channel]); debugf2("\t\tAMB-present CH%d = 0x%x:\n", channel, pvt->ambpresent[channel]); @@ -973,7 +973,7 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) for (slot = 0; slot < MAX_SLOTS; slot++) { int where = mtr_regs[slot]; for (branch = 0; branch < MAX_BRANCHES; branch++) { - pci_read_config_word(pvt->branch_pci[branch], + pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], where, &pvt->mtr[slot][branch]); for (ch = 0; ch < MAX_BRANCHES; ch++) { @@ -1027,13 +1027,13 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) pvt = mci->pvt_info; - pci_read_config_dword(pvt->system_address, AMBASE, + pci_read_config_dword(pvt->pci_dev_16_0_fsb_ctlr, AMBASE, (u32 *) &pvt->ambase); debugf2("AMBASE= 0x%lx\n", (long unsigned int)pvt->ambase); /* Get the Branch Map regs */ - pci_read_config_word(pvt->branchmap_werrors, TOLM, &pvt->tolm); + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, TOLM, &pvt->tolm); pvt->tolm >>= 12; debugf2("TOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm, pvt->tolm); @@ -1043,7 +1043,7 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); /* Get memory controller settings */ - pci_read_config_dword(pvt->branchmap_werrors, MC_SETTINGS, + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, MC_SETTINGS, &pvt->mc_settings); debugf0("Memory controller operating on %s mode\n", pvt->mc_settings & (1 << 16)? "mirrored" : "non-mirrored"); @@ -1051,9 +1051,9 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) pvt->mc_settings & (1 << 5)? "enabled" : "disabled"); /* Get Memory Interleave Range registers */ - pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir[0]); - pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir[1]); - pci_read_config_word(pvt->branchmap_werrors, MIR2, &pvt->mir[2]); + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR0, &pvt->mir[0]); + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR1, &pvt->mir[1]); + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR2, &pvt->mir[2]); /* Decode the MIR regs */ for (i = 0; i < MAX_MIR; i++) @@ -1083,9 +1083,9 @@ static void i7300_put_devices(struct mem_ctl_info *mci) /* Decrement usage count for devices */ for (branch = 0; branch < MAX_CH_PER_BRANCH; branch++) - pci_dev_put(pvt->branch_pci[branch]); - pci_dev_put(pvt->fsb_error_regs); - pci_dev_put(pvt->branchmap_werrors); + pci_dev_put(pvt->pci_dev_2x_0_fbd_branch[branch]); + pci_dev_put(pvt->pci_dev_16_2_fsb_err_regs); + pci_dev_put(pvt->pci_dev_16_1_fsb_addr_map); } /* @@ -1103,7 +1103,7 @@ static int i7300_get_devices(struct mem_ctl_info *mci, int dev_idx) /* Attempt to 'get' the MCH register we want */ pdev = NULL; - while (!pvt->branchmap_werrors || !pvt->fsb_error_regs) { + while (!pvt->pci_dev_16_1_fsb_addr_map || !pvt->pci_dev_16_2_fsb_err_regs) { pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, pdev); if (!pdev) { @@ -1121,28 +1121,28 @@ static int i7300_get_devices(struct mem_ctl_info *mci, int dev_idx) /* Store device 16 funcs 1 and 2 */ switch (PCI_FUNC(pdev->devfn)) { case 1: - pvt->branchmap_werrors = pdev; + pvt->pci_dev_16_1_fsb_addr_map = pdev; break; case 2: - pvt->fsb_error_regs = pdev; + pvt->pci_dev_16_2_fsb_err_regs = pdev; break; } } debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", - pci_name(pvt->system_address), - pvt->system_address->vendor, pvt->system_address->device); + pci_name(pvt->pci_dev_16_0_fsb_ctlr), + pvt->pci_dev_16_0_fsb_ctlr->vendor, pvt->pci_dev_16_0_fsb_ctlr->device); debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->branchmap_werrors), - pvt->branchmap_werrors->vendor, pvt->branchmap_werrors->device); + pci_name(pvt->pci_dev_16_1_fsb_addr_map), + pvt->pci_dev_16_1_fsb_addr_map->vendor, pvt->pci_dev_16_1_fsb_addr_map->device); debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->fsb_error_regs), - pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device); + pci_name(pvt->pci_dev_16_2_fsb_err_regs), + pvt->pci_dev_16_2_fsb_err_regs->vendor, pvt->pci_dev_16_2_fsb_err_regs->device); - pvt->branch_pci[0] = pci_get_device(PCI_VENDOR_ID_INTEL, + pvt->pci_dev_2x_0_fbd_branch[0] = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_FB0, NULL); - if (!pvt->branch_pci[0]) { + if (!pvt->pci_dev_2x_0_fbd_branch[0]) { i7300_printk(KERN_ERR, "MC: 'BRANCH 0' device not found:" "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n", @@ -1150,10 +1150,10 @@ static int i7300_get_devices(struct mem_ctl_info *mci, int dev_idx) goto error; } - pvt->branch_pci[1] = pci_get_device(PCI_VENDOR_ID_INTEL, + pvt->pci_dev_2x_0_fbd_branch[1] = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_FB1, NULL); - if (!pvt->branch_pci[1]) { + if (!pvt->pci_dev_2x_0_fbd_branch[1]) { i7300_printk(KERN_ERR, "MC: 'BRANCH 1' device not found:" "vendor 0x%x device 0x%x Func 0 " @@ -1222,7 +1222,7 @@ static int i7300_probe1(struct pci_dev *pdev, int dev_idx) mci->dev = &pdev->dev; /* record ptr to the generic device */ pvt = mci->pvt_info; - pvt->system_address = pdev; /* Record this device in our private */ + pvt->pci_dev_16_0_fsb_ctlr = pdev; /* Record this device in our private */ /* 'get' the pci devices we want to reserve for our use */ if (i7300_get_devices(mci, dev_idx)) -- cgit v1.2.3-59-g8ed1b From 5de6e07ed75ee29a302f50e149339ca747131121 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 00:16:12 -0300 Subject: i7300_edac: Add error detection code for global errors There's no mention at the datasheet about how to enable global error reporting. So, I'm assuming that those errors are always enabled. Maybe I'm plain wrong about that ;) Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 568 +++++++--------------------------------------- 1 file changed, 77 insertions(+), 491 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 3e60dbaa0e7e..e617b4f79dd8 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -158,8 +158,17 @@ static const char *numcol_toString[] = { * Device 16.2: Global Error Registers */ +#define FERR_GLOBAL_HI 0x48 +static const char *ferr_global_hi_name[] = { + [3] = "FSB 3 Fatal Error", + [2] = "FSB 2 Fatal Error", + [1] = "FSB 1 Fatal Error", + [0] = "FSB 0 Fatal Error", +}; +#define ferr_global_hi_is_fatal(errno) 1 + #define FERR_GLOBAL_LO 0x40 -static const char *ferr_global_name[] = { +static const char *ferr_global_lo_name[] = { [31] = "Internal MCH Fatal Error", [30] = "Intel QuickData Technology Device Fatal Error", [29] = "FSB1 Fatal Error", @@ -193,190 +202,7 @@ static const char *ferr_global_name[] = { [1] = "PCI Express Device 1 Non-Fatal Error", [0] = "ESI Non-Fatal Error", }; - -#define NERR_GLOBAL 0x44 -static const char *nerr_global_name[] = { - [31] = "Internal MCH Fatal Error", - [30] = "Intel QuickData Technology Device Fatal Error", - [29] = "FSB1 Fatal Error", - [28] = "FSB0 Fatal Error", - [27] = "FSB2 Fatal Error", - [26] = "FSB3 Fatal Error", - [25] = "Reserved", - [24] = "FBD Channel 0,1,2 or 3 Fatal Error", - [23] = "PCI Express Device 7 Fatal Error", - [22] = "PCI Express Device 6 Fatal Error", - [21] = "PCI Express Device 5 Fatal Error", - [20] = "PCI Express Device 4 Fatal Error", - [19] = "PCI Express Device 3 Fatal Error", - [18] = "PCI Express Device 2 Fatal Error", - [17] = "PCI Express Device 1 Fatal Error", - [16] = "ESI Fatal Error", - [15] = "Internal MCH Non-Fatal Error", - [14] = "Intel QuickData Technology Device Non Fatal Error", - [13] = "FSB1 Non-Fatal Error", - [12] = "FSB0 Non-Fatal Error", - [11] = "FSB2 Non-Fatal Error", - [10] = "FSB3 Non-Fatal Error", - [9] = "Reserved", - [8] = "FBD Channel 0,1, 2 or 3 Non-Fatal Error", - [7] = "PCI Express Device 7 Non-Fatal Error", - [6] = "PCI Express Device 6 Non-Fatal Error", - [5] = "PCI Express Device 5 Non-Fatal Error", - [4] = "PCI Express Device 4 Non-Fatal Error", - [3] = "PCI Express Device 3 Non-Fatal Error", - [2] = "PCI Express Device 2 Non-Fatal Error", - [1] = "PCI Express Device 1 Non-Fatal Error", - [0] = "ESI Non-Fatal Error", -}; - -#if 0 - -/* - * Error indicator bits and masks - * Error masks are according with Table 5-17 of i7300 datasheet - */ - -enum error_mask { - EMASK_M1 = 1<<0, /* Memory Write error on non-redundant retry */ - EMASK_M2 = 1<<1, /* Memory or FB-DIMM configuration CRC read error */ - EMASK_M3 = 1<<2, /* Reserved */ - EMASK_M4 = 1<<3, /* Uncorrectable Data ECC on Replay */ - EMASK_M5 = 1<<4, /* Aliased Uncorrectable Non-Mirrored Demand Data ECC */ - EMASK_M6 = 1<<5, /* Unsupported on i7300 */ - EMASK_M7 = 1<<6, /* Aliased Uncorrectable Resilver- or Spare-Copy Data ECC */ - EMASK_M8 = 1<<7, /* Aliased Uncorrectable Patrol Data ECC */ - EMASK_M9 = 1<<8, /* Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC */ - EMASK_M10 = 1<<9, /* Unsupported on i7300 */ - EMASK_M11 = 1<<10, /* Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC */ - EMASK_M12 = 1<<11, /* Non-Aliased Uncorrectable Patrol Data ECC */ - EMASK_M13 = 1<<12, /* Memory Write error on first attempt */ - EMASK_M14 = 1<<13, /* FB-DIMM Configuration Write error on first attempt */ - EMASK_M15 = 1<<14, /* Memory or FB-DIMM configuration CRC read error */ - EMASK_M16 = 1<<15, /* Channel Failed-Over Occurred */ - EMASK_M17 = 1<<16, /* Correctable Non-Mirrored Demand Data ECC */ - EMASK_M18 = 1<<17, /* Unsupported on i7300 */ - EMASK_M19 = 1<<18, /* Correctable Resilver- or Spare-Copy Data ECC */ - EMASK_M20 = 1<<19, /* Correctable Patrol Data ECC */ - EMASK_M21 = 1<<20, /* FB-DIMM Northbound parity error on FB-DIMM Sync Status */ - EMASK_M22 = 1<<21, /* SPD protocol Error */ - EMASK_M23 = 1<<22, /* Non-Redundant Fast Reset Timeout */ - EMASK_M24 = 1<<23, /* Refresh error */ - EMASK_M25 = 1<<24, /* Memory Write error on redundant retry */ - EMASK_M26 = 1<<25, /* Redundant Fast Reset Timeout */ - EMASK_M27 = 1<<26, /* Correctable Counter Threshold Exceeded */ - EMASK_M28 = 1<<27, /* DIMM-Spare Copy Completed */ - EMASK_M29 = 1<<28, /* DIMM-Isolation Completed */ -}; - -/* - * Names to translate bit error into something useful - */ -static const char *error_name[] = { - [0] = "Memory Write error on non-redundant retry", - [1] = "Memory or FB-DIMM configuration CRC read error", - /* Reserved */ - [3] = "Uncorrectable Data ECC on Replay", - [4] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC", - /* M6 Unsupported on i7300 */ - [6] = "Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", - [7] = "Aliased Uncorrectable Patrol Data ECC", - [8] = "Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC", - /* M10 Unsupported on i7300 */ - [10] = "Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", - [11] = "Non-Aliased Uncorrectable Patrol Data ECC", - [12] = "Memory Write error on first attempt", - [13] = "FB-DIMM Configuration Write error on first attempt", - [14] = "Memory or FB-DIMM configuration CRC read error", - [15] = "Channel Failed-Over Occurred", - [16] = "Correctable Non-Mirrored Demand Data ECC", - /* M18 Unsupported on i7300 */ - [18] = "Correctable Resilver- or Spare-Copy Data ECC", - [19] = "Correctable Patrol Data ECC", - [20] = "FB-DIMM Northbound parity error on FB-DIMM Sync Status", - [21] = "SPD protocol Error", - [22] = "Non-Redundant Fast Reset Timeout", - [23] = "Refresh error", - [24] = "Memory Write error on redundant retry", - [25] = "Redundant Fast Reset Timeout", - [26] = "Correctable Counter Threshold Exceeded", - [27] = "DIMM-Spare Copy Completed", - [28] = "DIMM-Isolation Completed", -}; - -/* Fatal errors */ -#define ERROR_FAT_MASK (EMASK_M1 | \ - EMASK_M2 | \ - EMASK_M23) - -/* Correctable errors */ -#define ERROR_NF_CORRECTABLE (EMASK_M27 | \ - EMASK_M20 | \ - EMASK_M19 | \ - EMASK_M18 | \ - EMASK_M17 | \ - EMASK_M16) -#define ERROR_NF_DIMM_SPARE (EMASK_M29 | \ - EMASK_M28) -#define ERROR_NF_SPD_PROTOCOL (EMASK_M22) -#define ERROR_NF_NORTH_CRC (EMASK_M21) - -/* Recoverable errors */ -#define ERROR_NF_RECOVERABLE (EMASK_M26 | \ - EMASK_M25 | \ - EMASK_M24 | \ - EMASK_M15 | \ - EMASK_M14 | \ - EMASK_M13 | \ - EMASK_M12 | \ - EMASK_M11 | \ - EMASK_M9 | \ - EMASK_M8 | \ - EMASK_M7 | \ - EMASK_M5) - -/* uncorrectable errors */ -#define ERROR_NF_UNCORRECTABLE (EMASK_M4) - -/* mask to all non-fatal errors */ -#define ERROR_NF_MASK (ERROR_NF_CORRECTABLE | \ - ERROR_NF_UNCORRECTABLE | \ - ERROR_NF_RECOVERABLE | \ - ERROR_NF_DIMM_SPARE | \ - ERROR_NF_SPD_PROTOCOL | \ - ERROR_NF_NORTH_CRC) - -/* - * Define error masks for the several registers - */ - -/* Enable all fatal and non fatal errors */ -#define ENABLE_EMASK_ALL (ERROR_FAT_MASK | ERROR_NF_MASK) - -/* mask for fatal error registers */ -#define FERR_FAT_MASK ERROR_FAT_MASK - -/* masks for non-fatal error register */ -static inline int to_nf_mask(unsigned int mask) -{ - return (mask & EMASK_M29) | (mask >> 3); -}; - -static inline int from_nf_ferr(unsigned int mask) -{ - return (mask & EMASK_M29) | /* Bit 28 */ - (mask & ((1 << 28) - 1) << 3); /* Bits 0 to 27 */ -}; - -#define FERR_NF_MASK to_nf_mask(ERROR_NF_MASK) -#define FERR_NF_CORRECTABLE to_nf_mask(ERROR_NF_CORRECTABLE) -#define FERR_NF_DIMM_SPARE to_nf_mask(ERROR_NF_DIMM_SPARE) -#define FERR_NF_SPD_PROTOCOL to_nf_mask(ERROR_NF_SPD_PROTOCOL) -#define FERR_NF_NORTH_CRC to_nf_mask(ERROR_NF_NORTH_CRC) -#define FERR_NF_RECOVERABLE to_nf_mask(ERROR_NF_RECOVERABLE) -#define FERR_NF_UNCORRECTABLE to_nf_mask(ERROR_NF_UNCORRECTABLE) - -#endif +#define ferr_global_lo_is_fatal(errno) ((errno < 16) ? 0 : 1) /* Device name and register DID (Device ID) */ struct i7300_dev_info { @@ -416,85 +242,28 @@ struct i7300_pvt { struct i7300_dimm_info dimm_info[MAX_SLOTS][MAX_CHANNELS]; }; -#if 0 -/* I7300 MCH error information retrieved from Hardware */ -struct i7300_error_info { - /* These registers are always read from the MC */ - u32 ferr_fat_fbd; /* First Errors Fatal */ - u32 nerr_fat_fbd; /* Next Errors Fatal */ - u32 ferr_nf_fbd; /* First Errors Non-Fatal */ - u32 nerr_nf_fbd; /* Next Errors Non-Fatal */ - - /* These registers are input ONLY if there was a Recoverable Error */ - u32 redmemb; /* Recoverable Mem Data Error log B */ - u16 recmema; /* Recoverable Mem Error log A */ - u32 recmemb; /* Recoverable Mem Error log B */ - - /* These registers are input ONLY if there was a Non-Rec Error */ - u16 nrecmema; /* Non-Recoverable Mem log A */ - u16 nrecmemb; /* Non-Recoverable Mem log B */ - -}; -#endif - /* FIXME: Why do we need to have this static? */ static struct edac_pci_ctl_info *i7300_pci; +/******************************************** + * i7300 Functions related to error detection + ********************************************/ -#if 0 -/* note that nrec_rdwr changed from NRECMEMA to NRECMEMB between the 5000 and - 5400 better to use an inline function than a macro in this case */ -static inline int nrec_bank(struct i7300_error_info *info) -{ - return ((info->nrecmema) >> 12) & 0x7; -} -static inline int nrec_rank(struct i7300_error_info *info) -{ - return ((info->nrecmema) >> 8) & 0xf; -} -static inline int nrec_buf_id(struct i7300_error_info *info) -{ - return ((info->nrecmema)) & 0xff; -} -static inline int nrec_rdwr(struct i7300_error_info *info) -{ - return (info->nrecmemb) >> 31; -} -/* This applies to both NREC and REC string so it can be used with nrec_rdwr - and rec_rdwr */ -static inline const char *rdwr_str(int rdwr) -{ - return rdwr ? "Write" : "Read"; -} -static inline int nrec_cas(struct i7300_error_info *info) -{ - return ((info->nrecmemb) >> 16) & 0x1fff; -} -static inline int nrec_ras(struct i7300_error_info *info) -{ - return (info->nrecmemb) & 0xffff; -} -static inline int rec_bank(struct i7300_error_info *info) -{ - return ((info->recmema) >> 12) & 0x7; -} -static inline int rec_rank(struct i7300_error_info *info) -{ - return ((info->recmema) >> 8) & 0xf; -} -static inline int rec_rdwr(struct i7300_error_info *info) -{ - return (info->recmemb) >> 31; -} -static inline int rec_cas(struct i7300_error_info *info) -{ - return ((info->recmemb) >> 16) & 0x1fff; -} -static inline int rec_ras(struct i7300_error_info *info) +struct i7300_error_info { + int dummy; /* FIXME */ +}; + +const char *get_err_from_table(const char *table[], int size, int pos) { - return (info->recmemb) & 0xffff; + if (pos >= size) + return "Reserved"; + + return table[pos]; } +#define GET_ERR_FROM_TABLE(table, pos) \ + get_err_from_table(table, ARRAY_SIZE(table), pos) + /* * i7300_get_error_info Retrieve the hardware error information from * the hardware and cache it in the 'info' @@ -503,234 +272,63 @@ static inline int rec_ras(struct i7300_error_info *info) static void i7300_get_error_info(struct mem_ctl_info *mci, struct i7300_error_info *info) { - struct i7300_pvt *pvt; - u32 value; - - pvt = mci->pvt_info; - - /* read in the 1st FATAL error register */ - pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, FERR_FAT_FBD, &value); - - /* Mask only the bits that the doc says are valid - */ - value &= (FERR_FAT_FBDCHAN | FERR_FAT_MASK); - - /* If there is an error, then read in the - NEXT FATAL error register and the Memory Error Log Register A - */ - if (value & FERR_FAT_MASK) { - info->ferr_fat_fbd = value; - - /* harvest the various error data we need */ - pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, - NERR_FAT_FBD, &info->nerr_fat_fbd); - pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, - NRECMEMA, &info->nrecmema); - pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, - NRECMEMB, &info->nrecmemb); - - /* Clear the error bits, by writing them back */ - pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, - FERR_FAT_FBD, value); - } else { - info->ferr_fat_fbd = 0; - info->nerr_fat_fbd = 0; - info->nrecmema = 0; - info->nrecmemb = 0; - } - - /* read in the 1st NON-FATAL error register */ - pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, FERR_NF_FBD, &value); - - /* If there is an error, then read in the 1st NON-FATAL error - * register as well */ - if (value & FERR_NF_MASK) { - info->ferr_nf_fbd = value; - - /* harvest the various error data we need */ - pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, - NERR_NF_FBD, &info->nerr_nf_fbd); - pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, - RECMEMA, &info->recmema); - pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, - RECMEMB, &info->recmemb); - pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, - REDMEMB, &info->redmemb); - - /* Clear the error bits, by writing them back */ - pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, - FERR_NF_FBD, value); - } else { - info->ferr_nf_fbd = 0; - info->nerr_nf_fbd = 0; - info->recmema = 0; - info->recmemb = 0; - info->redmemb = 0; - } } /* - * i7300_proccess_non_recoverable_info(struct mem_ctl_info *mci, - * struct i7300_error_info *info, - * int handle_errors); - * - * handle the Intel FATAL and unrecoverable errors, if any - */ -static void i7300_proccess_non_recoverable_info(struct mem_ctl_info *mci, - struct i7300_error_info *info, - unsigned long allErrors) -{ - char msg[EDAC_MC_LABEL_LEN + 1 + 90 + 80]; - int branch; - int channel; - int bank; - int buf_id; - int rank; - int rdwr; - int ras, cas; - int errnum; - char *type = NULL; - - if (!allErrors) - return; /* if no error, return now */ - - if (allErrors & ERROR_FAT_MASK) - type = "FATAL"; - else if (allErrors & FERR_NF_UNCORRECTABLE) - type = "NON-FATAL uncorrected"; - else - type = "NON-FATAL recoverable"; - - /* ONLY ONE of the possible error bits will be set, as per the docs */ - - branch = extract_fbdchan_indx(info->ferr_fat_fbd); - channel = branch; - - /* Use the NON-Recoverable macros to extract data */ - bank = nrec_bank(info); - rank = nrec_rank(info); - buf_id = nrec_buf_id(info); - rdwr = nrec_rdwr(info); - ras = nrec_ras(info); - cas = nrec_cas(info); - - debugf0("\t\tCSROW= %d Channels= %d,%d (Branch= %d " - "DRAM Bank= %d Buffer ID = %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, channel + 1, branch >> 1, bank, - buf_id, rdwr_str(rdwr), ras, cas); - - /* Only 1 bit will be on */ - errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); - - /* Form out message */ - snprintf(msg, sizeof(msg), - "%s (Branch=%d DRAM-Bank=%d Buffer ID = %d RDWR=%s " - "RAS=%d CAS=%d %s Err=0x%lx (%s))", - type, branch >> 1, bank, buf_id, rdwr_str(rdwr), ras, cas, - type, allErrors, error_name[errnum]); - - /* Call the helper to output message */ - edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg); -} - -/* - * i7300_process_fatal_error_info(struct mem_ctl_info *mci, - * struct i7300_error_info *info, - * int handle_errors); - * - * handle the Intel NON-FATAL errors, if any + * i7300_process_error_global Retrieve the hardware error information from + * the hardware and cache it in the 'info' + * structure */ -static void i7300_process_nonfatal_error_info(struct mem_ctl_info *mci, - struct i7300_error_info *info) +static void i7300_process_error_global(struct mem_ctl_info *mci, + struct i7300_error_info *info) { - char msg[EDAC_MC_LABEL_LEN + 1 + 90 + 80]; - unsigned long allErrors; - int branch; - int channel; - int bank; - int rank; - int rdwr; - int ras, cas; - int errnum; - - /* mask off the Error bits that are possible */ - allErrors = from_nf_ferr(info->ferr_nf_fbd & FERR_NF_MASK); - if (!allErrors) - return; /* if no error, return now */ - - /* ONLY ONE of the possible error bits will be set, as per the docs */ - - if (allErrors & (ERROR_NF_UNCORRECTABLE | ERROR_NF_RECOVERABLE)) { - i7300_proccess_non_recoverable_info(mci, info, allErrors); - return; - } - - /* Correctable errors */ - if (allErrors & ERROR_NF_CORRECTABLE) { - debugf0("\tCorrected bits= 0x%lx\n", allErrors); - - branch = extract_fbdchan_indx(info->ferr_nf_fbd); - - channel = 0; - if (REC_ECC_LOCATOR_ODD(info->redmemb)) - channel = 1; - - /* Convert channel to be based from zero, instead of - * from branch base of 0 */ - channel += branch; - - bank = rec_bank(info); - rank = rec_rank(info); - rdwr = rec_rdwr(info); - ras = rec_ras(info); - cas = rec_cas(info); - - /* Only 1 bit will be on */ - errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); - - debugf0("\t\tCSROW= %d Channel= %d (Branch %d " - "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, branch >> 1, bank, - rdwr_str(rdwr), ras, cas); - - /* Form out message */ - snprintf(msg, sizeof(msg), - "Corrected error (Branch=%d DRAM-Bank=%d RDWR=%s " - "RAS=%d CAS=%d, CE Err=0x%lx (%s))", - branch >> 1, bank, rdwr_str(rdwr), ras, cas, - allErrors, error_name[errnum]); + struct i7300_pvt *pvt; + u32 errnum, value; + unsigned long errors; + const char *specific; + bool is_fatal; - /* Call the helper to output message */ - edac_mc_handle_fbd_ce(mci, rank, channel, msg); + pvt = mci->pvt_info; - return; + /* read in the 1st FATAL error register */ + pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs, + FERR_GLOBAL_HI, &value); + if (unlikely(value)) { + errors = value; + errnum = find_first_bit(&errors, + ARRAY_SIZE(ferr_global_hi_name)); + specific = GET_ERR_FROM_TABLE(ferr_global_hi_name, errnum); + is_fatal = ferr_global_hi_is_fatal(errnum); + goto error_global; } - /* Miscelaneous errors */ - errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); - - branch = extract_fbdchan_indx(info->ferr_nf_fbd); + pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs, + FERR_GLOBAL_LO, &value); + if (unlikely(value)) { + errors = value; + errnum = find_first_bit(&errors, + ARRAY_SIZE(ferr_global_lo_name)); + specific = GET_ERR_FROM_TABLE(ferr_global_lo_name, errnum); + is_fatal = ferr_global_lo_is_fatal(errnum); + goto error_global; + } + return; - i7300_mc_printk(mci, KERN_EMERG, - "Non-Fatal misc error (Branch=%d Err=%#lx (%s))", - branch >> 1, allErrors, error_name[errnum]); +error_global: + i7300_mc_printk(mci, KERN_EMERG, "%s misc error: %s\n", + is_fatal ? "Fatal" : "NOT fatal", specific); } /* - * i7300_process_error_info Process the error info that is - * in the 'info' structure, previously retrieved from hardware + * i7300_process_error_info Retrieve the hardware error information from + * the hardware and cache it in the 'info' + * structure */ static void i7300_process_error_info(struct mem_ctl_info *mci, - struct i7300_error_info *info) -{ u32 allErrors; - - /* First handle any fatal errors that occurred */ - allErrors = (info->ferr_fat_fbd & FERR_FAT_MASK); - i7300_proccess_non_recoverable_info(mci, info, allErrors); - - /* now handle any non-fatal errors that occurred */ - i7300_process_nonfatal_error_info(mci, info); -} + struct i7300_error_info *info) +{ + i7300_process_error_global(mci, info); +}; /* * i7300_clear_error Retrieve any error from the hardware @@ -753,6 +351,7 @@ static void i7300_check_error(struct mem_ctl_info *mci) { struct i7300_error_info info; debugf4("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + i7300_get_error_info(mci, &info); i7300_process_error_info(mci, &info); } @@ -763,22 +362,11 @@ static void i7300_check_error(struct mem_ctl_info *mci) */ static void i7300_enable_error_reporting(struct mem_ctl_info *mci) { - struct i7300_pvt *pvt; - u32 fbd_error_mask; - - pvt = mci->pvt_info; - - /* Read the FBD Error Mask Register */ - pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, EMASK_FBD, - &fbd_error_mask); - - /* Enable with a '0' */ - fbd_error_mask &= ~(ENABLE_EMASK_ALL); - - pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, EMASK_FBD, - fbd_error_mask); } -#endif + +/************************************************ + * i7300 Functions related to memory enumberation + ************************************************/ /* * determine_mtr(pvt, csrow, channel) @@ -1070,6 +658,10 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) return 0; } +/************************************************* + * i7300 Functions related to device probe/release + *************************************************/ + /* * i7300_put_devices 'put' all the devices that we have * reserved via 'get' @@ -1238,10 +830,8 @@ static int i7300_probe1(struct pci_dev *pdev, int dev_idx) mci->dev_name = pci_name(pdev); mci->ctl_page_to_phys = NULL; -#if 0 /* Set the function pointer to an actual operation function */ mci->edac_check = i7300_check_error; -#endif /* initialize the MC control structure 'csrows' table * with the mapping and control information */ @@ -1251,10 +841,8 @@ static int i7300_probe1(struct pci_dev *pdev, int dev_idx) "value\n"); mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */ } else { -#if 0 debugf1("MC: Enable error reporting now\n"); i7300_enable_error_reporting(mci); -#endif } /* add this new MC control structure to EDAC's list of MCs */ @@ -1267,9 +855,7 @@ static int i7300_probe1(struct pci_dev *pdev, int dev_idx) goto fail1; } -#if 0 i7300_clear_error(mci); -#endif /* allocating generic PCI control info */ i7300_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR); -- cgit v1.2.3-59-g8ed1b From 86002324cf8809c72858741ab20bb7a855654b4c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 00:46:57 -0300 Subject: i7300_edac: Clear the error bit after reading Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index e617b4f79dd8..f2f171d0356a 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -299,6 +299,11 @@ static void i7300_process_error_global(struct mem_ctl_info *mci, ARRAY_SIZE(ferr_global_hi_name)); specific = GET_ERR_FROM_TABLE(ferr_global_hi_name, errnum); is_fatal = ferr_global_hi_is_fatal(errnum); + + /* Clear the error bit */ + pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, + FERR_GLOBAL_HI, value); + goto error_global; } @@ -310,6 +315,11 @@ static void i7300_process_error_global(struct mem_ctl_info *mci, ARRAY_SIZE(ferr_global_lo_name)); specific = GET_ERR_FROM_TABLE(ferr_global_lo_name, errnum); is_fatal = ferr_global_lo_is_fatal(errnum); + + /* Clear the error bit */ + pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, + FERR_GLOBAL_LO, value); + goto error_global; } return; -- cgit v1.2.3-59-g8ed1b From d7de2bdb0e15c594aefbc71d899c4684a5ce6559 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 08:56:48 -0300 Subject: i7300_edac: Adds detection for enhanced scrub mode on x8 While here, do some cleanup by adding some macros to check for device features. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index f2f171d0356a..27088af79672 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -93,6 +93,12 @@ /* OFFSETS for Function 1 */ #define MC_SETTINGS 0x40 +#define IS_MIRRORED(mc) ((mc) & (1 << 16)) +#define IS_ECC_ENABLED(mc) ((mc) & (1 << 5)) +#define IS_RETRY_ENABLED(mc) ((mc) & (1 << 31)) +#define IS_SCRBALGO_ENHANCED(mc) ((mc) & (1 << 8)) + + #define TOLM 0x6C #define REDMEMB 0x7C @@ -451,9 +457,13 @@ static int decode_mtr(struct i7300_pvt *pvt, p_csrow->edac_mode = EDAC_S8ECD8ED; /* ask what device type on this row */ - if (MTR_DRAM_WIDTH(mtr)) + if (MTR_DRAM_WIDTH(mtr)) { + debugf0("Scrub algorithm for x8 is on %s mode\n", + IS_SCRBALGO_ENHANCED(pvt->mc_settings) ? + "enhanced" : "normal"); + p_csrow->dtype = DEV_X8; - else + } else p_csrow->dtype = DEV_X4; return mtr; @@ -643,10 +653,13 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) /* Get memory controller settings */ pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, MC_SETTINGS, &pvt->mc_settings); + debugf0("Memory controller operating on %s mode\n", - pvt->mc_settings & (1 << 16)? "mirrored" : "non-mirrored"); + IS_MIRRORED(pvt->mc_settings) ? "mirrored" : "non-mirrored"); debugf0("Error detection is %s\n", - pvt->mc_settings & (1 << 5)? "enabled" : "disabled"); + IS_ECC_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); + debugf0("Retry is %s\n", + IS_RETRY_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); /* Get Memory Interleave Range registers */ pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR0, &pvt->mir[0]); -- cgit v1.2.3-59-g8ed1b From bb81a21637f84e2192bf327575645a7843c70cdb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 09:04:11 -0300 Subject: i7300_edac: Detect if the device is on single mode Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 27088af79672..a88742abf1f4 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -92,12 +92,13 @@ /* OFFSETS for Function 1 */ #define MC_SETTINGS 0x40 + #define IS_MIRRORED(mc) ((mc) & (1 << 16)) + #define IS_ECC_ENABLED(mc) ((mc) & (1 << 5)) + #define IS_RETRY_ENABLED(mc) ((mc) & (1 << 31)) + #define IS_SCRBALGO_ENHANCED(mc) ((mc) & (1 << 8)) -#define IS_MIRRORED(mc) ((mc) & (1 << 16)) -#define IS_ECC_ENABLED(mc) ((mc) & (1 << 5)) -#define IS_RETRY_ENABLED(mc) ((mc) & (1 << 31)) -#define IS_SCRBALGO_ENHANCED(mc) ((mc) & (1 << 8)) - +#define MC_SETTINGS_A 0x58 + #define IS_SINGLE_MODE(mca) ((mca) & (1 << 14)) #define TOLM 0x6C #define REDMEMB 0x7C @@ -237,9 +238,11 @@ struct i7300_pvt { u16 tolm; /* top of low memory */ u64 ambase; /* AMB BAR */ - u32 mc_settings; - u16 mir[MAX_MIR]; + u32 mc_settings; /* Report several settings */ + u32 mc_settings_a; + + u16 mir[MAX_MIR]; /* Memory Interleave Reg*/ u16 mtr[MAX_SLOTS][MAX_BRANCHES]; /* Memory Technlogy Reg */ u16 ambpresent[MAX_CHANNELS]; /* AMB present regs */ @@ -653,9 +656,15 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) /* Get memory controller settings */ pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, MC_SETTINGS, &pvt->mc_settings); + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, MC_SETTINGS_A, + &pvt->mc_settings_a); - debugf0("Memory controller operating on %s mode\n", + if (IS_SINGLE_MODE(pvt->mc_settings_a)) + debugf0("Memory controller operating on single mode\n"); + else + debugf0("Memory controller operating on %s mode\n", IS_MIRRORED(pvt->mc_settings) ? "mirrored" : "non-mirrored"); + debugf0("Error detection is %s\n", IS_ECC_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); debugf0("Retry is %s\n", -- cgit v1.2.3-59-g8ed1b From 15154c57c62494292f43df9133a7b370cbbf1ecb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 09:16:06 -0300 Subject: i7300_edac: Properly detect the type of error correction Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index a88742abf1f4..b5152256967f 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -450,14 +450,24 @@ static int decode_mtr(struct i7300_pvt *pvt, p_csrow->mtype = MEM_FB_DDR2; /* - * FIXME: the type of error detection actually depends of the + * The type of error detection actually depends of the * mode of operation. When it is just one single memory chip, at - * socket 0, channel 0, it uses 8-byte-over-32-byte SECDED+ code. - * In normal or mirrored mode, it uses Single Device Data correction, + * socket 0, channel 0, it uses 8-byte-over-32-byte SECDED+ code. + * In normal or mirrored mode, it uses Lockstep mode, * with the possibility of using an extended algorithm for x8 memories * See datasheet Sections 7.3.6 to 7.3.8 */ - p_csrow->edac_mode = EDAC_S8ECD8ED; + + if (IS_SINGLE_MODE(pvt->mc_settings_a)) { + p_csrow->edac_mode = EDAC_SECDED; + debugf0("ECC code is 8-byte-over-32-byte SECDED+ code\n"); + } else { + debugf0("ECC code is on Lockstep mode\n"); + if (MTR_DRAM_WIDTH(mtr)) + p_csrow->edac_mode = EDAC_S8ECD8ED; + else + p_csrow->edac_mode = EDAC_S4ECD4ED; + } /* ask what device type on this row */ if (MTR_DRAM_WIDTH(mtr)) { -- cgit v1.2.3-59-g8ed1b From 57021918aa9c310524d7e9754506e4e8272b4c0e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 10:22:36 -0300 Subject: i7300_edac: Add support for reporting FBD errors Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index b5152256967f..728f9b0ab62c 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -161,6 +161,63 @@ static const char *numcol_toString[] = { /************************************************ * i7300 Register definitions for error detection ************************************************/ + +/* + * Device 16.1: FBD Error Registers + */ +#define FERR_FAT_FBD 0x98 +static const char *ferr_fat_fbd_name[] = { + [22] = "Non-Redundant Fast Reset Timeout", + [2] = ">Tmid Thermal event with intelligent throttling disabled", + [1] = "Memory or FBD configuration CRC read error", + [0] = "Memory Write error on non-redundant retry or " + "FBD configuration Write error on retry", +}; +#define GET_FBD_FAT_IDX(fbderr) (fbderr & (3 << 28)) +#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) + +#define FERR_NF_FBD 0xa0 +static const char *ferr_nf_fbd_name[] = { + [24] = "DIMM-Spare Copy Completed", + [23] = "DIMM-Spare Copy Initiated", + [22] = "Redundant Fast Reset Timeout", + [21] = "Memory Write error on redundant retry", + [18] = "SPD protocol Error", + [17] = "FBD Northbound parity error on FBD Sync Status", + [16] = "Correctable Patrol Data ECC", + [15] = "Correctable Resilver- or Spare-Copy Data ECC", + [14] = "Correctable Mirrored Demand Data ECC", + [13] = "Correctable Non-Mirrored Demand Data ECC", + [11] = "Memory or FBD configuration CRC read error", + [10] = "FBD Configuration Write error on first attempt", + [9] = "Memory Write error on first attempt", + [8] = "Non-Aliased Uncorrectable Patrol Data ECC", + [7] = "Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", + [6] = "Non-Aliased Uncorrectable Mirrored Demand Data ECC", + [5] = "Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC", + [4] = "Aliased Uncorrectable Patrol Data ECC", + [3] = "Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", + [2] = "Aliased Uncorrectable Mirrored Demand Data ECC", + [1] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC", + [0] = "Uncorrectable Data ECC on Replay", +}; +#define GET_FBD_NF_IDX(fbderr) (fbderr & (3 << 28)) +#define FERR_NF_FBD_ERR_MASK ((1 << 24) | (1 << 23) | (1 << 22) | (1 << 21) |\ + (1 << 18) | (1 << 17) | (1 << 16) | (1 << 15) |\ + (1 << 14) | (1 << 13) | (1 << 11) | (1 << 10) |\ + (1 << 9) | (1 << 8) | (1 << 7) | (1 << 6) |\ + (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) |\ + (1 << 1) | (1 << 0)) + +#define EMASK_FBD 0xa8 +#define EMASK_FBD_ERR_MASK ((1 << 27) | (1 << 26) | (1 << 25) | (1 << 24) |\ + (1 << 22) | (1 << 21) | (1 << 20) | (1 << 19) |\ + (1 << 18) | (1 << 17) | (1 << 16) | (1 << 14) |\ + (1 << 13) | (1 << 12) | (1 << 11) | (1 << 10) |\ + (1 << 9) | (1 << 8) | (1 << 7) | (1 << 6) |\ + (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) |\ + (1 << 1) | (1 << 0)) + /* * Device 16.2: Global Error Registers */ @@ -338,6 +395,61 @@ error_global: is_fatal ? "Fatal" : "NOT fatal", specific); } +/* + * i7300_process_fbd_error Retrieve the hardware error information from + * the hardware and cache it in the 'info' + * structure + */ +static void i7300_process_fbd_error(struct mem_ctl_info *mci, + struct i7300_error_info *info) +{ + struct i7300_pvt *pvt; + u32 errnum, value; + int branch; + unsigned long errors; + const char *specific; + bool is_fatal; + + pvt = mci->pvt_info; + + /* read in the 1st FATAL error register */ + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + FERR_FAT_FBD, &value); + if (unlikely(value & FERR_FAT_FBD_ERR_MASK)) { + errors = value & FERR_FAT_FBD_ERR_MASK ; + errnum = find_first_bit(&errors, + ARRAY_SIZE(ferr_fat_fbd_name)); + specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum); + is_fatal = 1; + + branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0; + + goto error_fbd; + } + + /* read in the 1st NON-FATAL error register */ + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + FERR_NF_FBD, &value); + if (unlikely(value & FERR_NF_FBD_ERR_MASK)) { + errors = value & FERR_NF_FBD_ERR_MASK; + errnum = find_first_bit(&errors, + ARRAY_SIZE(ferr_nf_fbd_name)); + specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum); + is_fatal = 0; + + /* Clear the error bit */ + pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, + FERR_GLOBAL_LO, value); + + goto error_fbd; + } + return; + +error_fbd: + i7300_mc_printk(mci, KERN_EMERG, "%s FBD error on branch %d: %s\n", + is_fatal ? "Fatal" : "NOT fatal", branch, specific); +} + /* * i7300_process_error_info Retrieve the hardware error information from * the hardware and cache it in the 'info' @@ -347,6 +459,7 @@ static void i7300_process_error_info(struct mem_ctl_info *mci, struct i7300_error_info *info) { i7300_process_error_global(mci, info); + i7300_process_fbd_error(mci, info); }; /* @@ -381,6 +494,18 @@ static void i7300_check_error(struct mem_ctl_info *mci) */ static void i7300_enable_error_reporting(struct mem_ctl_info *mci) { + struct i7300_pvt *pvt = mci->pvt_info; + u32 fbd_error_mask; + + /* Read the FBD Error Mask Register */ + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + EMASK_FBD, &fbd_error_mask); + + /* Enable with a '0' */ + fbd_error_mask &= ~(EMASK_FBD_ERR_MASK); + + pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + EMASK_FBD, fbd_error_mask); } /************************************************ -- cgit v1.2.3-59-g8ed1b From e43276050927c7dfc45b1e2f090b94f72f87c052 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 10:30:18 -0300 Subject: i7300_edac: Add a code to cleanup error registers Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 728f9b0ab62c..3b6da20de4e5 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -470,9 +470,34 @@ static void i7300_process_error_info(struct mem_ctl_info *mci, */ static void i7300_clear_error(struct mem_ctl_info *mci) { - struct i7300_error_info info; + struct i7300_pvt *pvt = mci->pvt_info; + u32 value; + /* + * All error values are RWC - we need to read and write 1 to the + * bit that we want to cleanup + */ - i7300_get_error_info(mci, &info); + /* Clear global error registers */ + pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs, + FERR_GLOBAL_HI, &value); + pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, + FERR_GLOBAL_HI, value); + + pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs, + FERR_GLOBAL_LO, &value); + pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, + FERR_GLOBAL_LO, value); + + /* Clear FBD error registers */ + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + FERR_FAT_FBD, &value); + pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + FERR_FAT_FBD, value); + + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + FERR_NF_FBD, &value); + pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + FERR_NF_FBD, value); } /* -- cgit v1.2.3-59-g8ed1b From f42774224860d7c3f7c06559f98b681197999f9e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 10:33:25 -0300 Subject: i7300_edac: Cleanup: remove get_error_info logic As the error logic in this driver came from i5400 driver, it were using one function to get errors, and another to display. Let's make it simpler and avoid doing it into two steps. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 42 ++++++------------------------------------ 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 3b6da20de4e5..3ae8fae74e5e 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -315,10 +315,6 @@ static struct edac_pci_ctl_info *i7300_pci; * i7300 Functions related to error detection ********************************************/ -struct i7300_error_info { - int dummy; /* FIXME */ -}; - const char *get_err_from_table(const char *table[], int size, int pos) { if (pos >= size) @@ -330,23 +326,12 @@ const char *get_err_from_table(const char *table[], int size, int pos) #define GET_ERR_FROM_TABLE(table, pos) \ get_err_from_table(table, ARRAY_SIZE(table), pos) -/* - * i7300_get_error_info Retrieve the hardware error information from - * the hardware and cache it in the 'info' - * structure - */ -static void i7300_get_error_info(struct mem_ctl_info *mci, - struct i7300_error_info *info) -{ -} - /* * i7300_process_error_global Retrieve the hardware error information from * the hardware and cache it in the 'info' * structure */ -static void i7300_process_error_global(struct mem_ctl_info *mci, - struct i7300_error_info *info) +static void i7300_process_error_global(struct mem_ctl_info *mci) { struct i7300_pvt *pvt; u32 errnum, value; @@ -400,8 +385,7 @@ error_global: * the hardware and cache it in the 'info' * structure */ -static void i7300_process_fbd_error(struct mem_ctl_info *mci, - struct i7300_error_info *info) +static void i7300_process_fbd_error(struct mem_ctl_info *mci) { struct i7300_pvt *pvt; u32 errnum, value; @@ -451,15 +435,14 @@ error_fbd: } /* - * i7300_process_error_info Retrieve the hardware error information from + * i7300_check_error Retrieve the hardware error information from * the hardware and cache it in the 'info' * structure */ -static void i7300_process_error_info(struct mem_ctl_info *mci, - struct i7300_error_info *info) +static void i7300_check_error(struct mem_ctl_info *mci) { - i7300_process_error_global(mci, info); - i7300_process_fbd_error(mci, info); + i7300_process_error_global(mci); + i7300_process_fbd_error(mci); }; /* @@ -500,19 +483,6 @@ static void i7300_clear_error(struct mem_ctl_info *mci) FERR_NF_FBD, value); } -/* - * i7300_check_error Retrieve and process errors reported by the - * hardware. Called by the Core module. - */ -static void i7300_check_error(struct mem_ctl_info *mci) -{ - struct i7300_error_info info; - debugf4("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); - - i7300_get_error_info(mci, &info); - i7300_process_error_info(mci, &info); -} - /* * i7300_enable_error_reporting * Turn on the memory reporting features of the hardware -- cgit v1.2.3-59-g8ed1b From 3b330f67581db4f5301438cc0d9499f13314542d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 10:39:35 -0300 Subject: i7300_edac: Make the debug messages coherent with the others Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 3ae8fae74e5e..218d463fb1a8 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -580,9 +580,9 @@ static int decode_mtr(struct i7300_pvt *pvt, if (IS_SINGLE_MODE(pvt->mc_settings_a)) { p_csrow->edac_mode = EDAC_SECDED; - debugf0("ECC code is 8-byte-over-32-byte SECDED+ code\n"); + debugf2("\t\tECC code is 8-byte-over-32-byte SECDED+ code\n"); } else { - debugf0("ECC code is on Lockstep mode\n"); + debugf2("\t\tECC code is on Lockstep mode\n"); if (MTR_DRAM_WIDTH(mtr)) p_csrow->edac_mode = EDAC_S8ECD8ED; else @@ -591,7 +591,7 @@ static int decode_mtr(struct i7300_pvt *pvt, /* ask what device type on this row */ if (MTR_DRAM_WIDTH(mtr)) { - debugf0("Scrub algorithm for x8 is on %s mode\n", + debugf2("\t\tScrub algorithm for x8 is on %s mode\n", IS_SCRBALGO_ENHANCED(pvt->mc_settings) ? "enhanced" : "normal"); -- cgit v1.2.3-59-g8ed1b From 28c2ce7c8b275a8e6950bacb2dbad70b36a2996b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 11:20:38 -0300 Subject: i7300_edac: Fix MTR x4/x8 detection logic Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 218d463fb1a8..a4f47fda078d 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -583,14 +583,14 @@ static int decode_mtr(struct i7300_pvt *pvt, debugf2("\t\tECC code is 8-byte-over-32-byte SECDED+ code\n"); } else { debugf2("\t\tECC code is on Lockstep mode\n"); - if (MTR_DRAM_WIDTH(mtr)) + if (MTR_DRAM_WIDTH(mtr) == 8) p_csrow->edac_mode = EDAC_S8ECD8ED; else p_csrow->edac_mode = EDAC_S4ECD4ED; } /* ask what device type on this row */ - if (MTR_DRAM_WIDTH(mtr)) { + if (MTR_DRAM_WIDTH(mtr) == 8) { debugf2("\t\tScrub algorithm for x8 is on %s mode\n", IS_SCRBALGO_ENHANCED(pvt->mc_settings) ? "enhanced" : "normal"); -- cgit v1.2.3-59-g8ed1b From 85580ea4f72ce08e4d9140a3bb22806185a0bba9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 11:36:23 -0300 Subject: i7300_edac: pre-allocate a buffer used to prepare err messages Instead of dynamically allocating a buffer for it where needed, just allocate it once. As we'll use the same buffer also during fatal and non-fatal errors, is is very risky to dynamically allocate it during an error. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index a4f47fda078d..4c239ce6986b 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -306,6 +306,9 @@ struct i7300_pvt { /* DIMM information matrix, allocating architecture maximums */ struct i7300_dimm_info dimm_info[MAX_SLOTS][MAX_CHANNELS]; + + /* Temporary buffer for use when preparing error messages */ + char *tmp_prt_buffer; }; /* FIXME: Why do we need to have this static? */ @@ -611,17 +614,12 @@ static int decode_mtr(struct i7300_pvt *pvt, static void print_dimm_size(struct i7300_pvt *pvt) { struct i7300_dimm_info *dinfo; - char *p, *mem_buffer; + char *p; int space, n; int channel, slot; space = PAGE_SIZE; - mem_buffer = p = kmalloc(space, GFP_KERNEL); - if (p == NULL) { - i7300_printk(KERN_ERR, "MC: %s:%s() kmalloc() failed\n", - __FILE__, __func__); - return; - } + p = pvt->tmp_prt_buffer; n = snprintf(p, space, " "); p += n; @@ -631,15 +629,15 @@ static void print_dimm_size(struct i7300_pvt *pvt) p += n; space -= n; } - debugf2("%s\n", mem_buffer); - p = mem_buffer; + debugf2("%s\n", pvt->tmp_prt_buffer); + p = pvt->tmp_prt_buffer; space = PAGE_SIZE; n = snprintf(p, space, "-------------------------------" "------------------------------"); p += n; space -= n; - debugf2("%s\n", mem_buffer); - p = mem_buffer; + debugf2("%s\n", pvt->tmp_prt_buffer); + p = pvt->tmp_prt_buffer; space = PAGE_SIZE; for (slot = 0; slot < MAX_SLOTS; slot++) { @@ -654,8 +652,8 @@ static void print_dimm_size(struct i7300_pvt *pvt) space -= n; } - debugf2("%s\n", mem_buffer); - p = mem_buffer; + debugf2("%s\n", pvt->tmp_prt_buffer); + p = pvt->tmp_prt_buffer; space = PAGE_SIZE; } @@ -663,11 +661,9 @@ static void print_dimm_size(struct i7300_pvt *pvt) "------------------------------"); p += n; space -= n; - debugf2("%s\n", mem_buffer); - p = mem_buffer; + debugf2("%s\n", pvt->tmp_prt_buffer); + p = pvt->tmp_prt_buffer; space = PAGE_SIZE; - - kfree(mem_buffer); } /* @@ -978,6 +974,12 @@ static int i7300_probe1(struct pci_dev *pdev, int dev_idx) pvt = mci->pvt_info; pvt->pci_dev_16_0_fsb_ctlr = pdev; /* Record this device in our private */ + pvt->tmp_prt_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!pvt->tmp_prt_buffer) { + edac_mc_free(mci); + return -ENOMEM; + } + /* 'get' the pci devices we want to reserve for our use */ if (i7300_get_devices(mci, dev_idx)) goto fail0; @@ -1038,6 +1040,7 @@ fail1: i7300_put_devices(mci); fail0: + kfree(pvt->tmp_prt_buffer); edac_mc_free(mci); return -ENODEV; } @@ -1072,6 +1075,7 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, static void __devexit i7300_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; + char *tmp; debugf0(__FILE__ ": %s()\n", __func__); @@ -1082,9 +1086,12 @@ static void __devexit i7300_remove_one(struct pci_dev *pdev) if (!mci) return; + tmp = ((struct i7300_pvt *)mci->pvt_info)->tmp_prt_buffer; + /* retrieve references to resources, and free those resources */ i7300_put_devices(mci); + kfree(tmp); edac_mc_free(mci); } -- cgit v1.2.3-59-g8ed1b From 8199d8cc65787bfd83abbfb69d9de1b51e027c41 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 11:51:48 -0300 Subject: i7300_edac: enrich FBD error info for fatal errors Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 4c239ce6986b..e33c9900e269 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -268,6 +268,16 @@ static const char *ferr_global_lo_name[] = { }; #define ferr_global_lo_is_fatal(errno) ((errno < 16) ? 0 : 1) +#define NRECMEMA 0xbe + #define NRECMEMA_BANK(v) (((v) >> 12) & 7) + #define NRECMEMA_RANK(v) (((v) >> 8) & 15) + +#define NRECMEMB 0xc0 + #define NRECMEMB_IS_WR(v) ((v) & (1 << 31)) + #define NRECMEMB_CAS(v) (((v) >> 16) & 0x1fff) + #define NRECMEMB_RAS(v) ((v) & 0xffff) + + /* Device name and register DID (Device ID) */ struct i7300_dev_info { const char *ctl_name; /* name for this device */ @@ -392,10 +402,11 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) { struct i7300_pvt *pvt; u32 errnum, value; - int branch; + u16 val16; + int branch, bank, rank, cas, ras; unsigned long errors; const char *specific; - bool is_fatal; + bool is_fatal, is_wr; pvt = mci->pvt_info; @@ -410,8 +421,31 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) is_fatal = 1; branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0; - - goto error_fbd; + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, + NRECMEMA, &val16); + bank = NRECMEMA_BANK(val16); + rank = NRECMEMA_RANK(val16); + + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + NRECMEMB, &value); + + is_wr = NRECMEMB_IS_WR(value); + cas = NRECMEMB_CAS(value); + ras = NRECMEMB_RAS(value); + + snprintf(pvt->tmp_prt_buffer, PAGE_SIZE, + "FATAL (Branch=%d DRAM-Bank=%d %s " + "RAS=%d CAS=%d Err=0x%lx (%s))", + branch >> 1, bank, + is_wr ? "RDWR" : "RD", + ras, cas, + errors, specific); + + /* Call the helper to output message */ + edac_mc_handle_fbd_ue(mci, rank, branch << 1, + (branch << 1) + 1, + pvt->tmp_prt_buffer); + return; } /* read in the 1st NON-FATAL error register */ @@ -433,6 +467,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) return; error_fbd: + i7300_mc_printk(mci, KERN_EMERG, "%s FBD error on branch %d: %s\n", is_fatal ? "Fatal" : "NOT fatal", branch, specific); } -- cgit v1.2.3-59-g8ed1b From 32f9472613b30791d8cb5a953791cf4647166744 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 12:13:05 -0300 Subject: i7300_edac: enrich FBD error info for corrected errors Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 63 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index e33c9900e269..a06db65e1fef 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -277,6 +277,17 @@ static const char *ferr_global_lo_name[] = { #define NRECMEMB_CAS(v) (((v) >> 16) & 0x1fff) #define NRECMEMB_RAS(v) ((v) & 0xffff) +#define REDMEMA 0xdc + +#define RECMEMA 0xe0 + #define RECMEMA_BANK(v) (((v) >> 12) & 7) + #define RECMEMA_RANK(v) (((v) >> 8) & 15) + +#define RECMEMB 0xe4 + #define RECMEMB_IS_WR(v) ((v) & (1 << 31)) + #define RECMEMB_CAS(v) (((v) >> 16) & 0x1fff) + #define RECMEMB_RAS(v) ((v) & 0xffff) + /* Device name and register DID (Device ID) */ struct i7300_dev_info { @@ -403,10 +414,12 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) struct i7300_pvt *pvt; u32 errnum, value; u16 val16; - int branch, bank, rank, cas, ras; + unsigned branch, bank, rank, cas, ras; + u32 syndrome; + unsigned long errors; const char *specific; - bool is_fatal, is_wr; + bool is_wr; pvt = mci->pvt_info; @@ -418,7 +431,6 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) errnum = find_first_bit(&errors, ARRAY_SIZE(ferr_fat_fbd_name)); specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum); - is_fatal = 1; branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0; pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, @@ -436,7 +448,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) snprintf(pvt->tmp_prt_buffer, PAGE_SIZE, "FATAL (Branch=%d DRAM-Bank=%d %s " "RAS=%d CAS=%d Err=0x%lx (%s))", - branch >> 1, bank, + branch, bank, is_wr ? "RDWR" : "RD", ras, cas, errors, specific); @@ -445,7 +457,6 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) edac_mc_handle_fbd_ue(mci, rank, branch << 1, (branch << 1) + 1, pvt->tmp_prt_buffer); - return; } /* read in the 1st NON-FATAL error register */ @@ -456,20 +467,48 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) errnum = find_first_bit(&errors, ARRAY_SIZE(ferr_nf_fbd_name)); specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum); - is_fatal = 0; /* Clear the error bit */ pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, FERR_GLOBAL_LO, value); - goto error_fbd; - } - return; + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + REDMEMA, &syndrome); -error_fbd: + branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0; + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, + RECMEMA, &val16); + bank = RECMEMA_BANK(val16); + rank = RECMEMA_RANK(val16); - i7300_mc_printk(mci, KERN_EMERG, "%s FBD error on branch %d: %s\n", - is_fatal ? "Fatal" : "NOT fatal", branch, specific); + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + RECMEMB, &value); + + is_wr = RECMEMB_IS_WR(value); + cas = RECMEMB_CAS(value); + ras = RECMEMB_RAS(value); + + /* Form out message */ + snprintf(pvt->tmp_prt_buffer, PAGE_SIZE, + "Corrected error (Branch=%d (channel %d or %d), " + " DRAM-Bank=%d %s " + "RAS=%d CAS=%d, CE Err=0x%lx, Syndrome=0x%08x(%s))", + branch, branch << 1, (branch << 1) + 1, + bank, + is_wr ? "RDWR" : "RD", + ras, cas, + errors, syndrome, specific); + + /* + * Call the helper to output message + * NOTE: Errors are reported per-branch, and not per-channel + * Currently, we don't know how to identify the right + * channel. + */ + edac_mc_handle_fbd_ce(mci, rank, branch << 1, + pvt->tmp_prt_buffer); + } + return; } /* -- cgit v1.2.3-59-g8ed1b From 37b69cf91c2c6e60856ad1ac4c37ccb2005ebbd3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 15:44:43 -0300 Subject: i7300_edac: Properly detect channel on CE errors Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index a06db65e1fef..a85a8e5163b7 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -101,7 +101,6 @@ #define IS_SINGLE_MODE(mca) ((mca) & (1 << 14)) #define TOLM 0x6C -#define REDMEMB 0x7C #define MIR0 0x80 #define MIR1 0x84 @@ -279,6 +278,9 @@ static const char *ferr_global_lo_name[] = { #define REDMEMA 0xdc +#define REDMEMB 0x7c + #define IS_SECOND_CH(v) ((v) * (1 << 17)) + #define RECMEMA 0xe0 #define RECMEMA_BANK(v) (((v) >> 12) & 7) #define RECMEMA_RANK(v) (((v) >> 8) & 15) @@ -414,7 +416,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) struct i7300_pvt *pvt; u32 errnum, value; u16 val16; - unsigned branch, bank, rank, cas, ras; + unsigned branch, channel, bank, rank, cas, ras; u32 syndrome; unsigned long errors; @@ -488,12 +490,19 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) cas = RECMEMB_CAS(value); ras = RECMEMB_RAS(value); + pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, + REDMEMB, &value); + + channel = (branch << 1); + if (IS_SECOND_CH(value)) + channel++; + /* Form out message */ snprintf(pvt->tmp_prt_buffer, PAGE_SIZE, - "Corrected error (Branch=%d (channel %d or %d), " + "Corrected error (Branch=%d, Channel %d), " " DRAM-Bank=%d %s " "RAS=%d CAS=%d, CE Err=0x%lx, Syndrome=0x%08x(%s))", - branch, branch << 1, (branch << 1) + 1, + branch, channel, bank, is_wr ? "RDWR" : "RD", ras, cas, @@ -505,7 +514,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) * Currently, we don't know how to identify the right * channel. */ - edac_mc_handle_fbd_ce(mci, rank, branch << 1, + edac_mc_handle_fbd_ce(mci, rank, channel, pvt->tmp_prt_buffer); } return; -- cgit v1.2.3-59-g8ed1b From b4552aceb37ef953db14b9851bd4ededabc3c77b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 16:43:01 -0300 Subject: i7300_edac: Cleanup: reorganize the file contents This change should do no functional change. It just rearranges the contents of the c file, in order to make easier to understand and maintain it. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 116 ++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 56 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index a85a8e5163b7..6278209fec07 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -41,6 +41,10 @@ #define i7300_mc_printk(mci, level, fmt, arg...) \ edac_mc_chipset_printk(mci, level, "i7300", fmt, ##arg) +/*********************************************** + * i7300 Limit constants Structs and static vars + ***********************************************/ + /* * Memory topology is organized as: * Branch 0 - 2 channels: channels 0 and 1 (FDB0 PCI dev 21.0) @@ -67,18 +71,64 @@ #define to_csrow(slot, ch, branch) \ (to_channel(ch, branch) | ((slot) << 2)) +/* Device name and register DID (Device ID) */ +struct i7300_dev_info { + const char *ctl_name; /* name for this device */ + u16 fsb_mapping_errors; /* DID for the branchmap,control */ +}; + +/* Table of devices attributes supported by this driver */ +static const struct i7300_dev_info i7300_devs[] = { + { + .ctl_name = "I7300", + .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, + }, +}; + +struct i7300_dimm_info { + int megabytes; /* size, 0 means not present */ +}; + +/* driver private data structure */ +struct i7300_pvt { + struct pci_dev *pci_dev_16_0_fsb_ctlr; /* 16.0 */ + struct pci_dev *pci_dev_16_1_fsb_addr_map; /* 16.1 */ + struct pci_dev *pci_dev_16_2_fsb_err_regs; /* 16.2 */ + struct pci_dev *pci_dev_2x_0_fbd_branch[MAX_BRANCHES]; /* 21.0 and 22.0 */ + + u16 tolm; /* top of low memory */ + u64 ambase; /* AMB BAR */ + + u32 mc_settings; /* Report several settings */ + u32 mc_settings_a; + + u16 mir[MAX_MIR]; /* Memory Interleave Reg*/ + + u16 mtr[MAX_SLOTS][MAX_BRANCHES]; /* Memory Technlogy Reg */ + u16 ambpresent[MAX_CHANNELS]; /* AMB present regs */ + + /* DIMM information matrix, allocating architecture maximums */ + struct i7300_dimm_info dimm_info[MAX_SLOTS][MAX_CHANNELS]; + + /* Temporary buffer for use when preparing error messages */ + char *tmp_prt_buffer; +}; + +/* FIXME: Why do we need to have this static? */ +static struct edac_pci_ctl_info *i7300_pci; + +/*************************************************** + * i7300 Register definitions for memory enumeration + ***************************************************/ + /* - * I7300 devices + * I7300 devices: * All 3 functions of Device 16 (0,1,2) share the SAME DID and - * uses PCI_DEVICE_ID_INTEL_I7300_MCH_ERR for device 16 (0,1,2), - * PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 and PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 - * for device 21 (0,1). + * uses PCI_DEVICE_ID_INTEL_I7300_MCH_ERR for device 16 (0,1,2). + * PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 is used for device 21 (0,1) + * and PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 is used for device 21 (0,1). */ -/**************************************************** - * i7300 Register definitions for memory enumberation - ****************************************************/ - /* * Device 16, * Function 0: System Address (not documented) @@ -125,7 +175,8 @@ const static u16 mtr_regs [MAX_SLOTS] = { 0x82, 0x86, 0x8a, 0x8e }; -/* Defines to extract the vaious fields from the +/* + * Defines to extract the vaious fields from the * MTRx - Memory Technology Registers */ #define MTR_DIMMS_PRESENT(mtr) ((mtr) & (1 << 8)) @@ -290,53 +341,6 @@ static const char *ferr_global_lo_name[] = { #define RECMEMB_CAS(v) (((v) >> 16) & 0x1fff) #define RECMEMB_RAS(v) ((v) & 0xffff) - -/* Device name and register DID (Device ID) */ -struct i7300_dev_info { - const char *ctl_name; /* name for this device */ - u16 fsb_mapping_errors; /* DID for the branchmap,control */ -}; - -/* Table of devices attributes supported by this driver */ -static const struct i7300_dev_info i7300_devs[] = { - { - .ctl_name = "I7300", - .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, - }, -}; - -struct i7300_dimm_info { - int megabytes; /* size, 0 means not present */ -}; - -/* driver private data structure */ -struct i7300_pvt { - struct pci_dev *pci_dev_16_0_fsb_ctlr; /* 16.0 */ - struct pci_dev *pci_dev_16_1_fsb_addr_map; /* 16.1 */ - struct pci_dev *pci_dev_16_2_fsb_err_regs; /* 16.2 */ - struct pci_dev *pci_dev_2x_0_fbd_branch[MAX_BRANCHES]; /* 21.0 and 22.0 */ - - u16 tolm; /* top of low memory */ - u64 ambase; /* AMB BAR */ - - u32 mc_settings; /* Report several settings */ - u32 mc_settings_a; - - u16 mir[MAX_MIR]; /* Memory Interleave Reg*/ - - u16 mtr[MAX_SLOTS][MAX_BRANCHES]; /* Memory Technlogy Reg */ - u16 ambpresent[MAX_CHANNELS]; /* AMB present regs */ - - /* DIMM information matrix, allocating architecture maximums */ - struct i7300_dimm_info dimm_info[MAX_SLOTS][MAX_CHANNELS]; - - /* Temporary buffer for use when preparing error messages */ - char *tmp_prt_buffer; -}; - -/* FIXME: Why do we need to have this static? */ -static struct edac_pci_ctl_info *i7300_pci; - /******************************************** * i7300 Functions related to error detection ********************************************/ -- cgit v1.2.3-59-g8ed1b From d091a6eb177dd3da8f55f8fd73c5b80db0e1656f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 17:28:50 -0300 Subject: i7300_edac: Improve comments This is basically a cleanup patch, improving the comments for each function. While here, do a few cleanups. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 220 ++++++++++++++++++++++------------------------ 1 file changed, 104 insertions(+), 116 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 6278209fec07..a2a9ad499b6b 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -121,14 +121,6 @@ static struct edac_pci_ctl_info *i7300_pci; * i7300 Register definitions for memory enumeration ***************************************************/ -/* - * I7300 devices: - * All 3 functions of Device 16 (0,1,2) share the SAME DID and - * uses PCI_DEVICE_ID_INTEL_I7300_MCH_ERR for device 16 (0,1,2). - * PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 is used for device 21 (0,1) - * and PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 is used for device 21 (0,1). - */ - /* * Device 16, * Function 0: System Address (not documented) @@ -345,9 +337,24 @@ static const char *ferr_global_lo_name[] = { * i7300 Functions related to error detection ********************************************/ -const char *get_err_from_table(const char *table[], int size, int pos) +/** + * get_err_from_table() - Gets the error message from a table + * @table: table name (array of char *) + * @size: number of elements at the table + * @pos: position of the element to be returned + * + * This is a small routine that gets the pos-th element of a table. If the + * element doesn't exist (or it is empty), it returns "reserved". + * Instead of calling it directly, the better is to call via the macro + * GET_ERR_FROM_TABLE(), that automatically checks the table size via + * ARRAY_SIZE() macro + */ +static const char *get_err_from_table(const char *table[], int size, int pos) { - if (pos >= size) + if (unlikely(pos >= size)) + return "Reserved"; + + if (unlikely(!table[pos])) return "Reserved"; return table[pos]; @@ -356,10 +363,11 @@ const char *get_err_from_table(const char *table[], int size, int pos) #define GET_ERR_FROM_TABLE(table, pos) \ get_err_from_table(table, ARRAY_SIZE(table), pos) -/* - * i7300_process_error_global Retrieve the hardware error information from - * the hardware and cache it in the 'info' - * structure +/** + * i7300_process_error_global() - Retrieve the hardware error information from + * the hardware global error registers and + * sends it to dmesg + * @mci: struct mem_ctl_info pointer */ static void i7300_process_error_global(struct mem_ctl_info *mci) { @@ -410,10 +418,11 @@ error_global: is_fatal ? "Fatal" : "NOT fatal", specific); } -/* - * i7300_process_fbd_error Retrieve the hardware error information from - * the hardware and cache it in the 'info' - * structure +/** + * i7300_process_fbd_error() - Retrieve the hardware error information from + * the FBD error registers and sends it via + * EDAC error API calls + * @mci: struct mem_ctl_info pointer */ static void i7300_process_fbd_error(struct mem_ctl_info *mci) { @@ -524,10 +533,9 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) return; } -/* - * i7300_check_error Retrieve the hardware error information from - * the hardware and cache it in the 'info' - * structure +/** + * i7300_check_error() - Calls the error checking subroutines + * @mci: struct mem_ctl_info pointer */ static void i7300_check_error(struct mem_ctl_info *mci) { @@ -535,11 +543,9 @@ static void i7300_check_error(struct mem_ctl_info *mci) i7300_process_fbd_error(mci); }; -/* - * i7300_clear_error Retrieve any error from the hardware - * but do NOT process that error. - * Used for 'clearing' out of previous errors - * Called by the Core module. +/** + * i7300_clear_error() - Clears the error registers + * @mci: struct mem_ctl_info pointer */ static void i7300_clear_error(struct mem_ctl_info *mci) { @@ -573,9 +579,10 @@ static void i7300_clear_error(struct mem_ctl_info *mci) FERR_NF_FBD, value); } -/* - * i7300_enable_error_reporting - * Turn on the memory reporting features of the hardware +/** + * i7300_enable_error_reporting() - Enable the memory reporting logic at the + * hardware + * @mci: struct mem_ctl_info pointer */ static void i7300_enable_error_reporting(struct mem_ctl_info *mci) { @@ -597,10 +604,14 @@ static void i7300_enable_error_reporting(struct mem_ctl_info *mci) * i7300 Functions related to memory enumberation ************************************************/ -/* - * determine_mtr(pvt, csrow, channel) - * - * return the proper MTR register as determine by the csrow and desired channel +/** + * decode_mtr() - Decodes the MTR descriptor, filling the edac structs + * @pvt: pointer to the private data struct used by i7300 driver + * @slot: DIMM slot (0 to 7) + * @ch: Channel number within the branch (0 or 1) + * @branch: Branch number (0 or 1) + * @dinfo: Pointer to DIMM info where dimm size is stored + * @p_csrow: Pointer to the struct csrow_info that corresponds to that element */ static int decode_mtr(struct i7300_pvt *pvt, int slot, int ch, int branch, @@ -619,14 +630,8 @@ static int decode_mtr(struct i7300_pvt *pvt, ans ? "Present" : "NOT Present"); /* Determine if there is a DIMM present in this DIMM slot */ - -#if 0 - if (!amb_present || !ans) - return 0; -#else if (!ans) return 0; -#endif /* Start with the number of bits for a Bank * on the DRAM */ @@ -692,14 +697,15 @@ static int decode_mtr(struct i7300_pvt *pvt, return mtr; } -/* - * print_dimm_size +/** + * print_dimm_size() - Prints dump of the memory organization + * @pvt: pointer to the private data struct used by i7300 driver * - * also will output a DIMM matrix map, if debug is enabled, for viewing - * how the DIMMs are populated + * Useful for debug. If debug is disabled, this routine do nothing */ static void print_dimm_size(struct i7300_pvt *pvt) { +#ifdef CONFIG_EDAC_DEBUG struct i7300_dimm_info *dinfo; char *p; int space, n; @@ -751,30 +757,26 @@ static void print_dimm_size(struct i7300_pvt *pvt) debugf2("%s\n", pvt->tmp_prt_buffer); p = pvt->tmp_prt_buffer; space = PAGE_SIZE; +#endif } -/* - * i7300_init_csrows Initialize the 'csrows' table within - * the mci control structure with the - * addressing of memory. - * - * return: - * 0 success - * 1 no actual memory found on this MC +/** + * i7300_init_csrows() - Initialize the 'csrows' table within + * the mci control structure with the + * addressing of memory. + * @mci: struct mem_ctl_info pointer */ static int i7300_init_csrows(struct mem_ctl_info *mci) { struct i7300_pvt *pvt; struct i7300_dimm_info *dinfo; struct csrow_info *p_csrow; - int empty; + int rc = -ENODEV; int mtr; int ch, branch, slot, channel; pvt = mci->pvt_info; - empty = 1; /* Assume NO memory */ - debugf2("Memory Technology Registers:\n"); /* Get the AMB present registers for the four channels */ @@ -819,14 +821,19 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) p_csrow->last_page = 9 + slot * 20; p_csrow->page_mask = 0xfff; - empty = 0; + rc = 0; } } } - return empty; + return rc; } +/** + * decode_mir() - Decodes Memory Interleave Register (MIR) info + * @int mir_no: number of the MIR register to decode + * @mir: array with the MIR data cached on the driver + */ static void decode_mir(int mir_no, u16 mir[MAX_MIR]) { if (mir[mir_no] & 3) @@ -837,11 +844,11 @@ static void decode_mir(int mir_no, u16 mir[MAX_MIR]) (mir[mir_no] & 2) ? "B1": ""); } -/* - * i7300_get_mc_regs read in the necessary registers and - * cache locally +/** + * i7300_get_mc_regs() - Get the contents of the MC enumeration registers + * @mci: struct mem_ctl_info pointer * - * Fills in the private data members + * Data read is cached internally for its usage when needed */ static int i7300_get_mc_regs(struct mem_ctl_info *mci) { @@ -907,9 +914,9 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) * i7300 Functions related to device probe/release *************************************************/ -/* - * i7300_put_devices 'put' all the devices that we have - * reserved via 'get' +/** + * i7300_put_devices() - Release the PCI devices + * @mci: struct mem_ctl_info pointer */ static void i7300_put_devices(struct mem_ctl_info *mci) { @@ -925,13 +932,18 @@ static void i7300_put_devices(struct mem_ctl_info *mci) pci_dev_put(pvt->pci_dev_16_1_fsb_addr_map); } -/* - * i7300_get_devices Find and perform 'get' operation on the MCH's - * device/functions we want to reference for this driver +/** + * i7300_get_devices() - Find and perform 'get' operation on the MCH's + * device/functions we want to reference for this driver + * @mci: struct mem_ctl_info pointer * - * Need to 'get' device 16 func 1 and func 2 + * Access and prepare the several devices for usage: + * I7300 devices used by this driver: + * Device 16, functions 0,1 and 2: PCI_DEVICE_ID_INTEL_I7300_MCH_ERR + * Device 21 function 0: PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 + * Device 22 function 0: PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 */ -static int i7300_get_devices(struct mem_ctl_info *mci, int dev_idx) +static int __devinit i7300_get_devices(struct mem_ctl_info *mci) { struct i7300_pvt *pvt; struct pci_dev *pdev; @@ -1007,23 +1019,25 @@ error: return -ENODEV; } -/* - * i7300_probe1 Probe for ONE instance of device to see if it is - * present. - * return: - * 0 for FOUND a device - * < 0 for error code +/** + * i7300_init_one() - Probe for one instance of the device + * @pdev: struct pci_dev pointer + * @id: struct pci_device_id pointer - currently unused */ -static int i7300_probe1(struct pci_dev *pdev, int dev_idx) +static int __devinit i7300_init_one(struct pci_dev *pdev, + const struct pci_device_id *id) { struct mem_ctl_info *mci; struct i7300_pvt *pvt; int num_channels; int num_dimms_per_channel; int num_csrows; + int rc; - if (dev_idx >= ARRAY_SIZE(i7300_devs)) - return -EINVAL; + /* wake up device */ + rc = pci_enable_device(pdev); + if (rc == -EIO) + return rc; debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n", __func__, @@ -1068,7 +1082,7 @@ static int i7300_probe1(struct pci_dev *pdev, int dev_idx) } /* 'get' the pci devices we want to reserve for our use */ - if (i7300_get_devices(mci, dev_idx)) + if (i7300_get_devices(mci)) goto fail0; mci->mc_idx = 0; @@ -1077,7 +1091,7 @@ static int i7300_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = EDAC_FLAG_NONE; mci->mod_name = "i7300_edac.c"; mci->mod_ver = I7300_REVISION; - mci->ctl_name = i7300_devs[dev_idx].ctl_name; + mci->ctl_name = i7300_devs[0].ctl_name; mci->dev_name = pci_name(pdev); mci->ctl_page_to_phys = NULL; @@ -1132,32 +1146,9 @@ fail0: return -ENODEV; } -/* - * i7300_init_one constructor for one instance of device - * - * returns: - * negative on error - * count (>= 0) - */ -static int __devinit i7300_init_one(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int rc; - - debugf0("MC: " __FILE__ ": %s()\n", __func__); - - /* wake up device */ - rc = pci_enable_device(pdev); - if (rc == -EIO) - return rc; - - /* now probe and enable the device */ - return i7300_probe1(pdev, id->driver_data); -} - -/* - * i7300_remove_one destructor for one instance of device - * +/** + * i7300_remove_one() - Remove the driver + * @pdev: struct pci_dev pointer */ static void __devexit i7300_remove_one(struct pci_dev *pdev) { @@ -1183,9 +1174,9 @@ static void __devexit i7300_remove_one(struct pci_dev *pdev) } /* - * pci_device_id table for which devices we are looking for + * pci_device_id: table for which devices we are looking for * - * The "E500P" device is the first device supported. + * Has only 8086:360c PCI ID */ static const struct pci_device_id i7300_pci_tbl[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_ERR)}, @@ -1195,8 +1186,7 @@ static const struct pci_device_id i7300_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, i7300_pci_tbl); /* - * i7300_driver pci_driver structure for this module - * + * i7300_driver: pci_driver structure for this module */ static struct pci_driver i7300_driver = { .name = "i7300_edac", @@ -1205,9 +1195,8 @@ static struct pci_driver i7300_driver = { .id_table = i7300_pci_tbl, }; -/* - * i7300_init Module entry function - * Try to initialize this module for its devices +/** + * i7300_init() - Registers the driver */ static int __init i7300_init(void) { @@ -1223,9 +1212,8 @@ static int __init i7300_init(void) return (pci_rc < 0) ? pci_rc : 0; } -/* - * i7300_exit() Module exit function - * Unregister the driver +/** + * i7300_init() - Unregisters the driver */ static void __exit i7300_exit(void) { -- cgit v1.2.3-59-g8ed1b From 9c6f6b65d25aa7fe890377a92ea049c8e20da906 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Aug 2010 17:43:43 -0300 Subject: i7300-edac: CodingStyle cleanup Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7300_edac.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index a2a9ad499b6b..38920c0b5fbb 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -104,7 +104,7 @@ struct i7300_pvt { u16 mir[MAX_MIR]; /* Memory Interleave Reg*/ - u16 mtr[MAX_SLOTS][MAX_BRANCHES]; /* Memory Technlogy Reg */ + u16 mtr[MAX_SLOTS][MAX_BRANCHES]; /* Memory Technlogy Reg */ u16 ambpresent[MAX_CHANNELS]; /* AMB present regs */ /* DIMM information matrix, allocating architecture maximums */ @@ -162,7 +162,7 @@ static struct edac_pci_ctl_info *i7300_pci; #define AMBPRESENT_0 0x64 #define AMBPRESENT_1 0x66 -const static u16 mtr_regs [MAX_SLOTS] = { +const static u16 mtr_regs[MAX_SLOTS] = { 0x80, 0x84, 0x88, 0x8c, 0x82, 0x86, 0x8a, 0x8e }; @@ -726,7 +726,7 @@ static void print_dimm_size(struct i7300_pvt *pvt) p = pvt->tmp_prt_buffer; space = PAGE_SIZE; n = snprintf(p, space, "-------------------------------" - "------------------------------"); + "------------------------------"); p += n; space -= n; debugf2("%s\n", pvt->tmp_prt_buffer); @@ -751,7 +751,7 @@ static void print_dimm_size(struct i7300_pvt *pvt) } n = snprintf(p, space, "-------------------------------" - "------------------------------"); + "------------------------------"); p += n; space -= n; debugf2("%s\n", pvt->tmp_prt_buffer); @@ -783,13 +783,15 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) for (branch = 0; branch < MAX_BRANCHES; branch++) { /* Read and dump branch 0's MTRs */ channel = to_channel(0, branch); - pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], AMBPRESENT_0, + pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], + AMBPRESENT_0, &pvt->ambpresent[channel]); debugf2("\t\tAMB-present CH%d = 0x%x:\n", channel, pvt->ambpresent[channel]); channel = to_channel(1, branch); - pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], AMBPRESENT_1, + pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], + AMBPRESENT_1, &pvt->ambpresent[channel]); debugf2("\t\tAMB-present CH%d = 0x%x:\n", channel, pvt->ambpresent[channel]); @@ -837,11 +839,12 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) static void decode_mir(int mir_no, u16 mir[MAX_MIR]) { if (mir[mir_no] & 3) - debugf2("MIR%d: limit= 0x%x Branch(es) that participate: %s %s\n", + debugf2("MIR%d: limit= 0x%x Branch(es) that participate:" + " %s %s\n", mir_no, (mir[mir_no] >> 4) & 0xfff, (mir[mir_no] & 1) ? "B0" : "", - (mir[mir_no] & 2) ? "B1": ""); + (mir[mir_no] & 2) ? "B1" : ""); } /** @@ -891,9 +894,12 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) IS_RETRY_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); /* Get Memory Interleave Range registers */ - pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR0, &pvt->mir[0]); - pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR1, &pvt->mir[1]); - pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR2, &pvt->mir[2]); + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR0, + &pvt->mir[0]); + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR1, + &pvt->mir[1]); + pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR2, + &pvt->mir[2]); /* Decode the MIR regs */ for (i = 0; i < MAX_MIR; i++) @@ -952,7 +958,8 @@ static int __devinit i7300_get_devices(struct mem_ctl_info *mci) /* Attempt to 'get' the MCH register we want */ pdev = NULL; - while (!pvt->pci_dev_16_1_fsb_addr_map || !pvt->pci_dev_16_2_fsb_err_regs) { + while (!pvt->pci_dev_16_1_fsb_addr_map || + !pvt->pci_dev_16_2_fsb_err_regs) { pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, pdev); if (!pdev) { @@ -980,16 +987,19 @@ static int __devinit i7300_get_devices(struct mem_ctl_info *mci) debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", pci_name(pvt->pci_dev_16_0_fsb_ctlr), - pvt->pci_dev_16_0_fsb_ctlr->vendor, pvt->pci_dev_16_0_fsb_ctlr->device); + pvt->pci_dev_16_0_fsb_ctlr->vendor, + pvt->pci_dev_16_0_fsb_ctlr->device); debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", pci_name(pvt->pci_dev_16_1_fsb_addr_map), - pvt->pci_dev_16_1_fsb_addr_map->vendor, pvt->pci_dev_16_1_fsb_addr_map->device); + pvt->pci_dev_16_1_fsb_addr_map->vendor, + pvt->pci_dev_16_1_fsb_addr_map->device); debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n", pci_name(pvt->pci_dev_16_2_fsb_err_regs), - pvt->pci_dev_16_2_fsb_err_regs->vendor, pvt->pci_dev_16_2_fsb_err_regs->device); + pvt->pci_dev_16_2_fsb_err_regs->vendor, + pvt->pci_dev_16_2_fsb_err_regs->device); pvt->pci_dev_2x_0_fbd_branch[0] = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_I7300_MCH_FB0, + PCI_DEVICE_ID_INTEL_I7300_MCH_FB0, NULL); if (!pvt->pci_dev_2x_0_fbd_branch[0]) { i7300_printk(KERN_ERR, -- cgit v1.2.3-59-g8ed1b From dca43c75e7e545694a9dd6288553f55c53e2a3a3 Mon Sep 17 00:00:00 2001 From: Jerry Chu Date: Fri, 27 Aug 2010 19:13:28 +0000 Subject: tcp: Add TCP_USER_TIMEOUT socket option. This patch provides a "user timeout" support as described in RFC793. The socket option is also needed for the the local half of RFC5482 "TCP User Timeout Option". TCP_USER_TIMEOUT is a TCP level socket option that takes an unsigned int, when > 0, to specify the maximum amount of time in ms that transmitted data may remain unacknowledged before TCP will forcefully close the corresponding connection and return ETIMEDOUT to the application. If 0 is given, TCP will continue to use the system default. Increasing the user timeouts allows a TCP connection to survive extended periods without end-to-end connectivity. Decreasing the user timeouts allows applications to "fail fast" if so desired. Otherwise it may take upto 20 minutes with the current system defaults in a normal WAN environment. The socket option can be made during any state of a TCP connection, but is only effective during the synchronized states of a connection (ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, or LAST-ACK). Moreover, when used with the TCP keepalive (SO_KEEPALIVE) option, TCP_USER_TIMEOUT will overtake keepalive to determine when to close a connection due to keepalive failure. The option does not change in anyway when TCP retransmits a packet, nor when a keepalive probe will be sent. This option, like many others, will be inherited by an acceptor from its listener. Signed-off-by: H.K. Jerry Chu Signed-off-by: David S. Miller --- include/linux/tcp.h | 1 + include/net/inet_connection_sock.h | 1 + net/ipv4/tcp.c | 11 ++++++++++- net/ipv4/tcp_timer.c | 40 ++++++++++++++++++++++++-------------- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index a778ee024590..e64f4c67d0ef 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -105,6 +105,7 @@ enum { #define TCP_COOKIE_TRANSACTIONS 15 /* TCP Cookie Transactions */ #define TCP_THIN_LINEAR_TIMEOUTS 16 /* Use linear timeouts for thin streams*/ #define TCP_THIN_DUPACK 17 /* Fast retrans. after 1 dupack */ +#define TCP_USER_TIMEOUT 18 /* How long for loss retry before timeout */ /* for TCP_INFO socket option */ #define TCPI_OPT_TIMESTAMPS 1 diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index b6d3b55da19b..e4f494b42e06 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -125,6 +125,7 @@ struct inet_connection_sock { int probe_size; } icsk_mtup; u32 icsk_ca_priv[16]; + u32 icsk_user_timeout; #define ICSK_CA_PRIV_SIZE (16 * sizeof(u32)) }; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 176e11aaea77..cf3254528753 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2391,7 +2391,12 @@ static int do_tcp_setsockopt(struct sock *sk, int level, err = tp->af_specific->md5_parse(sk, optval, optlen); break; #endif - + case TCP_USER_TIMEOUT: + /* Cap the max timeout in ms TCP will retry/retrans + * before giving up and aborting (ETIMEDOUT) a connection. + */ + icsk->icsk_user_timeout = msecs_to_jiffies(val); + break; default: err = -ENOPROTOOPT; break; @@ -2610,6 +2615,10 @@ static int do_tcp_getsockopt(struct sock *sk, int level, case TCP_THIN_DUPACK: val = tp->thin_dupack; break; + + case TCP_USER_TIMEOUT: + val = jiffies_to_msecs(icsk->icsk_user_timeout); + break; default: return -ENOPROTOOPT; } diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 808bb920c9f5..11569deccbea 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -138,10 +138,10 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) * retransmissions with an initial RTO of TCP_RTO_MIN. */ static bool retransmits_timed_out(struct sock *sk, - unsigned int boundary) + unsigned int boundary, + unsigned int timeout) { - unsigned int timeout, linear_backoff_thresh; - unsigned int start_ts; + unsigned int linear_backoff_thresh, start_ts; if (!inet_csk(sk)->icsk_retransmits) return false; @@ -151,14 +151,15 @@ static bool retransmits_timed_out(struct sock *sk, else start_ts = tcp_sk(sk)->retrans_stamp; - linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN); - - if (boundary <= linear_backoff_thresh) - timeout = ((2 << boundary) - 1) * TCP_RTO_MIN; - else - timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN + - (boundary - linear_backoff_thresh) * TCP_RTO_MAX; + if (likely(timeout == 0)) { + linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN); + if (boundary <= linear_backoff_thresh) + timeout = ((2 << boundary) - 1) * TCP_RTO_MIN; + else + timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN + + (boundary - linear_backoff_thresh) * TCP_RTO_MAX; + } return (tcp_time_stamp - start_ts) >= timeout; } @@ -174,7 +175,7 @@ static int tcp_write_timeout(struct sock *sk) dst_negative_advice(sk); retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; } else { - if (retransmits_timed_out(sk, sysctl_tcp_retries1)) { + if (retransmits_timed_out(sk, sysctl_tcp_retries1, 0)) { /* Black hole detection */ tcp_mtu_probing(icsk, sk); @@ -187,14 +188,16 @@ static int tcp_write_timeout(struct sock *sk) retry_until = tcp_orphan_retries(sk, alive); do_reset = alive || - !retransmits_timed_out(sk, retry_until); + !retransmits_timed_out(sk, retry_until, 0); if (tcp_out_of_resources(sk, do_reset)) return 1; } } - if (retransmits_timed_out(sk, retry_until)) { + if (retransmits_timed_out(sk, retry_until, + (1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV) ? 0 : + icsk->icsk_user_timeout)) { /* Has it gone just too far? */ tcp_write_err(sk); return 1; @@ -436,7 +439,7 @@ out_reset_timer: icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX); } inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); - if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1)) + if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1, 0)) __sk_dst_reset(sk); out:; @@ -556,7 +559,14 @@ static void tcp_keepalive_timer (unsigned long data) elapsed = keepalive_time_elapsed(tp); if (elapsed >= keepalive_time_when(tp)) { - if (icsk->icsk_probes_out >= keepalive_probes(tp)) { + /* If the TCP_USER_TIMEOUT option is enabled, use that + * to determine when to timeout instead. + */ + if ((icsk->icsk_user_timeout != 0 && + elapsed >= icsk->icsk_user_timeout && + icsk->icsk_probes_out > 0) || + (icsk->icsk_user_timeout == 0 && + icsk->icsk_probes_out >= keepalive_probes(tp))) { tcp_send_active_reset(sk, GFP_ATOMIC); tcp_write_err(sk); goto out; -- cgit v1.2.3-59-g8ed1b From d82b6f85c1d73340ef4a26bd0b247ac14610cd83 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 29 Aug 2010 19:23:10 +0000 Subject: dccp ccid-2: Use u32 timestamps uniformly Since CCID-2 is de facto a mini implementation of TCP, it makes sense to share as much code as possible. Hence this patch aligns CCID-2 timestamping with TCP timestamping. This also halves the space consumption (on 64-bit systems). The necessary include file is already included by way of net/dccp.h. Redundant includes have been removed. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/ccids/ccid2.c | 14 ++++++-------- net/dccp/ccids/ccid2.h | 15 ++++++++++----- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 7af3106c1f94..0cff637a4a51 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -25,8 +25,6 @@ */ #include #include "../feat.h" -#include "../ccid.h" -#include "../dccp.h" #include "ccid2.h" @@ -175,7 +173,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) hc->tx_seqh->ccid2s_seq = dp->dccps_gss; hc->tx_seqh->ccid2s_acked = 0; - hc->tx_seqh->ccid2s_sent = jiffies; + hc->tx_seqh->ccid2s_sent = ccid2_time_stamp; next = hc->tx_seqh->ccid2s_next; /* check if we need to alloc more space */ @@ -250,7 +248,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) struct ccid2_seq *seqp = hc->tx_seqt; while (seqp != hc->tx_seqh) { - ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n", + ccid2_pr_debug("out seq=%llu acked=%d time=%u\n", (unsigned long long)seqp->ccid2s_seq, seqp->ccid2s_acked, seqp->ccid2s_sent); seqp = seqp->ccid2s_next; @@ -431,19 +429,19 @@ static void ccid2_new_ack(struct sock *sk, struct ccid2_seq *seqp, * The cleanest solution is to not use the ccid2s_sent field at all * and instead use DCCP timestamps: requires changes in other places. */ - ccid2_rtt_estimator(sk, jiffies - seqp->ccid2s_sent); + ccid2_rtt_estimator(sk, ccid2_time_stamp - seqp->ccid2s_sent); } static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp) { struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); - if (time_before(seqp->ccid2s_sent, hc->tx_last_cong)) { + if ((s32)(seqp->ccid2s_sent - hc->tx_last_cong) < 0) { ccid2_pr_debug("Multiple losses in an RTT---treating as one\n"); return; } - hc->tx_last_cong = jiffies; + hc->tx_last_cong = ccid2_time_stamp; hc->tx_cwnd = hc->tx_cwnd / 2 ? : 1U; hc->tx_ssthresh = max(hc->tx_cwnd, 2U); @@ -683,7 +681,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) hc->tx_rto = DCCP_TIMEOUT_INIT; hc->tx_rpdupack = -1; - hc->tx_last_cong = jiffies; + hc->tx_last_cong = ccid2_time_stamp; setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire, (unsigned long)sk); return 0; diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h index b017843ba44d..9731c2dc1487 100644 --- a/net/dccp/ccids/ccid2.h +++ b/net/dccp/ccids/ccid2.h @@ -18,18 +18,23 @@ #ifndef _DCCP_CCID2_H_ #define _DCCP_CCID2_H_ -#include #include #include #include "../ccid.h" +#include "../dccp.h" + +/* + * CCID-2 timestamping faces the same issues as TCP timestamping. + * Hence we reuse/share as much of the code as possible. + */ +#define ccid2_time_stamp tcp_time_stamp + /* NUMDUPACK parameter from RFC 4341, p. 6 */ #define NUMDUPACK 3 -struct sock; - struct ccid2_seq { u64 ccid2s_seq; - unsigned long ccid2s_sent; + u32 ccid2s_sent; int ccid2s_acked; struct ccid2_seq *ccid2s_prev; struct ccid2_seq *ccid2s_next; @@ -72,7 +77,7 @@ struct ccid2_hc_tx_sock { u64 tx_rpseq; int tx_rpdupack; - unsigned long tx_last_cong; + u32 tx_last_cong; u64 tx_high_ack; }; -- cgit v1.2.3-59-g8ed1b From d26eeb07fd02de31848b59d19687daff0e93532f Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 29 Aug 2010 19:23:11 +0000 Subject: dccp ccid-2: Remove wrappers around sk_{reset,stop}_timer() This removes the wrappers around the sk timer functions, since not much is gained from using them: the BUG_ON in start_rto_timer will never trigger since that function is called only if: * the RTO timer expires (rto_expire, and then timer_pending() is false); * in tx_packet_sent only if !timer_pending() (BUG_ON is redundant here); * previously in new_ack, after stopping the timer (timer_pending() false). Removing the wrappers also clears the way for eventually replacing the RTO timer with the icsk-retransmission-timer, as it is already part of the DCCP socket. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/ccids/ccid2.c | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 0cff637a4a51..8c95813bcc67 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -111,8 +111,6 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val) dp->dccps_l_ack_ratio = val; } -static void ccid2_start_rto_timer(struct sock *sk); - static void ccid2_hc_tx_rto_expire(unsigned long data) { struct sock *sk = (struct sock *)data; @@ -131,7 +129,7 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) if (hc->tx_rto > DCCP_RTO_MAX) hc->tx_rto = DCCP_RTO_MAX; - ccid2_start_rto_timer(sk); + sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); /* adjust pipe, cwnd etc */ hc->tx_ssthresh = hc->tx_cwnd / 2; @@ -153,16 +151,6 @@ out: sock_put(sk); } -static void ccid2_start_rto_timer(struct sock *sk) -{ - struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); - - ccid2_pr_debug("setting RTO timeout=%u\n", hc->tx_rto); - - BUG_ON(timer_pending(&hc->tx_rtotimer)); - sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); -} - static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) { struct dccp_sock *dp = dccp_sk(sk); @@ -239,9 +227,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) } #endif - /* setup RTO timer */ - if (!timer_pending(&hc->tx_rtotimer)) - ccid2_start_rto_timer(sk); + sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); #ifdef CONFIG_IP_DCCP_CCID2_DEBUG do { @@ -320,14 +306,6 @@ out_invalid_option: return -1; } -static void ccid2_hc_tx_kill_rto_timer(struct sock *sk) -{ - struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); - - sk_stop_timer(sk, &hc->tx_rtotimer); - ccid2_pr_debug("deleted RTO timer\n"); -} - /** * ccid2_rtt_estimator - Sample RTT and compute RTO using RFC2988 algorithm * This code is almost identical with TCP's tcp_rtt_estimator(), since @@ -692,7 +670,7 @@ static void ccid2_hc_tx_exit(struct sock *sk) struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); int i; - ccid2_hc_tx_kill_rto_timer(sk); + sk_stop_timer(sk, &hc->tx_rtotimer); for (i = 0; i < hc->tx_seqbufc; i++) kfree(hc->tx_seqbuf[i]); -- cgit v1.2.3-59-g8ed1b From 22b71c8f4f3db8df92f5e7b081c265bc56c0bd2f Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 29 Aug 2010 19:23:12 +0000 Subject: tcp/dccp: Consolidate common code for RFC 3390 conversion This patch consolidates initial-window code common to TCP and CCID-2: * TCP uses RFC 3390 in a packet-oriented manner (tcp_input.c) and * CCID-2 uses RFC 3390 in packet-oriented manner (RFC 4341). Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- include/net/tcp.h | 15 +++++++++++++++ net/dccp/ccids/ccid2.c | 8 ++------ net/ipv4/tcp_input.c | 17 ++--------------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index df6a2eb20193..a64022199b62 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -779,6 +779,21 @@ static inline __u32 tcp_current_ssthresh(const struct sock *sk) /* Use define here intentionally to get WARN_ON location shown at the caller */ #define tcp_verify_left_out(tp) WARN_ON(tcp_left_out(tp) > tp->packets_out) +/* + * Convert RFC 3390 larger initial window into an equivalent number of packets. + * + * John Heffner states: + * + * The RFC specifies a window of no more than 4380 bytes + * unless 2*MSS > 4380. Reading the pseudocode in the RFC + * is a bit misleading because they use a clamp at 4380 bytes + * rather than a multiplier in the relevant range. + */ +static inline u32 rfc3390_bytes_to_packets(const u32 smss) +{ + return smss <= 1095 ? 4 : (smss > 1460 ? 2 : 3); +} + extern void tcp_enter_cwr(struct sock *sk, const int set_ssthresh); extern __u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst); diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 8c95813bcc67..b9c942a09c98 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -641,12 +641,8 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) /* RFC 4341, 5: initialise ssthresh to arbitrarily high (max) value */ hc->tx_ssthresh = ~0U; - /* - * RFC 4341, 5: "The cwnd parameter is initialized to at most four - * packets for new connections, following the rules from [RFC3390]". - * We need to convert the bytes of RFC3390 into the packets of RFC 4341. - */ - hc->tx_cwnd = clamp(4380U / dp->dccps_mss_cache, 2U, 4U); + /* Use larger initial windows (RFC 4341, section 5). */ + hc->tx_cwnd = rfc3390_bytes_to_packets(dp->dccps_mss_cache); /* Make sure that Ack Ratio is enabled and within bounds. */ max_ratio = DIV_ROUND_UP(hc->tx_cwnd, 2); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e663b78a2ef6..1bc87a05c734 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -805,25 +805,12 @@ void tcp_update_metrics(struct sock *sk) } } -/* Numbers are taken from RFC3390. - * - * John Heffner states: - * - * The RFC specifies a window of no more than 4380 bytes - * unless 2*MSS > 4380. Reading the pseudocode in the RFC - * is a bit misleading because they use a clamp at 4380 bytes - * rather than use a multiplier in the relevant range. - */ __u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst) { __u32 cwnd = (dst ? dst_metric(dst, RTAX_INITCWND) : 0); - if (!cwnd) { - if (tp->mss_cache > 1460) - cwnd = 2; - else - cwnd = (tp->mss_cache > 1095) ? 3 : 4; - } + if (!cwnd) + cwnd = rfc3390_bytes_to_packets(tp->mss_cache); return min_t(__u32, cwnd, tp->snd_cwnd_clamp); } -- cgit v1.2.3-59-g8ed1b From 4886fcad6e12572afbd230dfab1b268eace20d6d Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 29 Aug 2010 19:23:13 +0000 Subject: dccp ccid-2: Share TCP's minimum RTO code Using a fixed RTO_MIN of 0.2 seconds was found to cause problems for CCID-2 over 802.11g: at least once per session there was a spurious timeout. It helped to then increase the the value of RTO_MIN over this link. Since the problem is the same as in TCP, this patch makes the solution from commit "05bb1fad1cde025a864a90cfeb98dcbefe78a44a" "[TCP]: Allow minimum RTO to be configurable via routing metrics." available to DCCP. This avoids reinventing the wheel, so that e.g. the following works in the expected way now also for CCID-2: > ip route change 10.0.0.2 rto_min 800 dev ath0 Luckily this useful rto_min function was recently moved to net/tcp.h, which simplifies sharing code originating from TCP. Documentation also updated (plus minor whitespace fixes). Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- Documentation/networking/dccp.txt | 26 ++++++++++++++++++++------ net/dccp/ccids/ccid2.c | 5 +++-- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt index a62fdf7a6bff..cdb64922ba10 100644 --- a/Documentation/networking/dccp.txt +++ b/Documentation/networking/dccp.txt @@ -1,18 +1,20 @@ DCCP protocol -============ +============= Contents ======== - - Introduction - Missing features - Socket options +- Sysctl variables +- IOCTLs +- Other tunables - Notes + Introduction ============ - Datagram Congestion Control Protocol (DCCP) is an unreliable, connection oriented protocol designed to solve issues present in UDP and TCP, particularly for real-time and multimedia (streaming) traffic. @@ -29,9 +31,9 @@ It has a base protocol and pluggable congestion control IDs (CCIDs). DCCP is a Proposed Standard (RFC 2026), and the homepage for DCCP as a protocol is at http://www.ietf.org/html.charters/dccp-charter.html + Missing features ================ - The Linux DCCP implementation does not currently support all the features that are specified in RFCs 4340...42. @@ -45,7 +47,6 @@ http://linux-net.osdl.org/index.php/DCCP_Testing#Experimental_DCCP_source_tree Socket options ============== - DCCP_SOCKOPT_SERVICE sets the service. The specification mandates use of service codes (RFC 4340, sec. 8.1.2); if this socket option is not set, the socket will fall back to 0 (which means that no meaningful service code @@ -112,6 +113,7 @@ DCCP_SOCKOPT_CCID_TX_INFO On unidirectional connections it is useful to close the unused half-connection via shutdown (SHUT_WR or SHUT_RD): this will reduce per-packet processing costs. + Sysctl variables ================ Several DCCP default parameters can be managed by the following sysctls @@ -155,15 +157,27 @@ sync_ratelimit = 125 ms sequence-invalid packets on the same socket (RFC 4340, 7.5.4). The unit of this parameter is milliseconds; a value of 0 disables rate-limiting. + IOCTLS ====== FIONREAD Works as in udp(7): returns in the `int' argument pointer the size of the next pending datagram in bytes, or 0 when no datagram is pending. + +Other tunables +============== +Per-route rto_min support + CCID-2 supports the RTAX_RTO_MIN per-route setting for the minimum value + of the RTO timer. This setting can be modified via the 'rto_min' option + of iproute2; for example: + > ip route change 10.0.0.0/24 rto_min 250j dev wlan0 + > ip route add 10.0.0.254/32 rto_min 800j dev wlan0 + > ip route show dev wlan0 + + Notes ===== - DCCP does not travel through NAT successfully at present on many boxes. This is because the checksum covers the pseudo-header as per TCP and UDP. Linux NAT support for DCCP has been added. diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index b9c942a09c98..dc18172b1e59 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -325,8 +325,9 @@ static void ccid2_rtt_estimator(struct sock *sk, const long mrtt) hc->tx_srtt = m << 3; hc->tx_mdev = m << 1; - hc->tx_mdev_max = max(TCP_RTO_MIN, hc->tx_mdev); + hc->tx_mdev_max = max(hc->tx_mdev, tcp_rto_min(sk)); hc->tx_rttvar = hc->tx_mdev_max; + hc->tx_rtt_seq = dccp_sk(sk)->dccps_gss; } else { /* Update scaled SRTT as SRTT += 1/8 * (m - SRTT) */ @@ -367,7 +368,7 @@ static void ccid2_rtt_estimator(struct sock *sk, const long mrtt) hc->tx_rttvar -= (hc->tx_rttvar - hc->tx_mdev_max) >> 2; hc->tx_rtt_seq = dccp_sk(sk)->dccps_gss; - hc->tx_mdev_max = TCP_RTO_MIN; + hc->tx_mdev_max = tcp_rto_min(sk); } } -- cgit v1.2.3-59-g8ed1b From 89858ad14307a398961a0f1414b04053c1475e4f Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 29 Aug 2010 19:23:14 +0000 Subject: dccp ccid-3: use per-route RTO or TCP RTO as fallback This makes RTAX_RTO_MIN also available to CCID-3, replacing the compile-time RTO lower bound with a per-route tunable value. The original Kconfig option solved the problem that a very low RTT (in the order of HZ) can trigger too frequent and unnecessary reductions of the sending rate. This tunable does not affect the initial RTO value of 2 seconds specified in RFC 5348, section 4.2 and Appendix B. But like the hardcoded Kconfig value, it allows to adapt to network conditions. The same effect as the original Kconfig option of 100ms is now achieved by > ip route replace to unicast 192.168.0.0/24 rto_min 100j dev eth0 (assuming HZ=1000). Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- Documentation/networking/dccp.txt | 3 +++ net/dccp/ccids/Kconfig | 31 ------------------------------- net/dccp/ccids/ccid3.c | 11 +++++------ net/dccp/ccids/ccid3.h | 2 +- 4 files changed, 9 insertions(+), 38 deletions(-) diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt index cdb64922ba10..271d524a4c8d 100644 --- a/Documentation/networking/dccp.txt +++ b/Documentation/networking/dccp.txt @@ -174,6 +174,9 @@ Per-route rto_min support > ip route change 10.0.0.0/24 rto_min 250j dev wlan0 > ip route add 10.0.0.254/32 rto_min 800j dev wlan0 > ip route show dev wlan0 + CCID-3 also supports the rto_min setting: it is used to define the lower + bound for the expiry of the nofeedback timer. This can be useful on LANs + with very low RTTs (e.g., loopback, Gbit ethernet). Notes diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig index 8408398cd44e..0581143cb800 100644 --- a/net/dccp/ccids/Kconfig +++ b/net/dccp/ccids/Kconfig @@ -47,37 +47,6 @@ config IP_DCCP_CCID3_DEBUG If in doubt, say N. -config IP_DCCP_CCID3_RTO - int "Use higher bound for nofeedback timer" - default 100 - depends on IP_DCCP_CCID3 && EXPERIMENTAL - ---help--- - Use higher lower bound for nofeedback timer expiration. - - The TFRC nofeedback timer normally expires after the maximum of 4 - RTTs and twice the current send interval (RFC 3448, 4.3). On LANs - with a small RTT this can mean a high processing load and reduced - performance, since then the nofeedback timer is triggered very - frequently. - - This option enables to set a higher lower bound for the nofeedback - value. Values in units of milliseconds can be set here. - - A value of 0 disables this feature by enforcing the value specified - in RFC 3448. The following values have been suggested as bounds for - experimental use: - * 16-20ms to match the typical multimedia inter-frame interval - * 100ms as a reasonable compromise [default] - * 1000ms corresponds to the lower TCP RTO bound (RFC 2988, 2.4) - - The default of 100ms is a compromise between a large value for - efficient DCCP implementations, and a small value to avoid disrupting - the network in times of congestion. - - The purpose of the nofeedback timer is to slow DCCP down when there - is serious network congestion: experimenting with larger values should - therefore not be performed on WANs. - config IP_DCCP_TFRC_LIB def_bool y if IP_DCCP_CCID3 diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 4340672a817c..278e17069322 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -460,13 +460,12 @@ done_computing_x: sk->sk_write_space(sk); /* - * Update timeout interval for the nofeedback timer. - * We use a configuration option to increase the lower bound. - * This can help avoid triggering the nofeedback timer too - * often ('spinning') on LANs with small RTTs. + * Update timeout interval for the nofeedback timer. In order to control + * rate halving on networks with very low RTTs (<= 1 ms), use per-route + * tunable RTAX_RTO_MIN value as the lower bound. */ - hc->tx_t_rto = max_t(u32, 4 * hc->tx_rtt, (CONFIG_IP_DCCP_CCID3_RTO * - (USEC_PER_SEC / 1000))); + hc->tx_t_rto = max_t(u32, 4 * hc->tx_rtt, + USEC_PER_SEC/HZ * tcp_rto_min(sk)); /* * Schedule no feedback timer to expire in * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi) diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index b1864243be07..b7e569c22f36 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -42,7 +42,7 @@ #include "lib/tfrc.h" #include "../ccid.h" -/* Two seconds as per RFC 3448 4.2 */ +/* Two seconds as per RFC 5348, 4.2 */ #define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC) /* In usecs - half the scheduling granularity as per RFC3448 4.6 */ -- cgit v1.2.3-59-g8ed1b From 3d5b99ae82f8742e3bb1f8634fd11ac36ea19ee1 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 29 Aug 2010 19:27:34 +0000 Subject: TCP: update initial windows according to RFC 5681 This updates the use of larger initial windows, as originally specified in RFC 3390, to use the newer IW values specified in RFC 5681, section 3.1. The changes made in RFC 5681 are: a) the setting now is more clearly specified in units of segments (as the comments by John Heffner emphasized, this was not very clear in RFC 3390); b) for connections with 1095 < SMSS <= 2190 there is now a change: - RFC 3390 says that IW <= 4380, - RFC 5681 says that IW = 3 * SMSS <= 6570. Since RFC 3390 is older and "only" proposed standard, whereas the newer RFC 5681 is already draft standard, it seems preferable to use the newer IW variant. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- include/net/tcp.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index a64022199b62..11dbacc886c0 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -781,17 +781,11 @@ static inline __u32 tcp_current_ssthresh(const struct sock *sk) /* * Convert RFC 3390 larger initial window into an equivalent number of packets. - * - * John Heffner states: - * - * The RFC specifies a window of no more than 4380 bytes - * unless 2*MSS > 4380. Reading the pseudocode in the RFC - * is a bit misleading because they use a clamp at 4380 bytes - * rather than a multiplier in the relevant range. + * This is based on the numbers specified in RFC 5681, 3.1. */ static inline u32 rfc3390_bytes_to_packets(const u32 smss) { - return smss <= 1095 ? 4 : (smss > 1460 ? 2 : 3); + return smss <= 1095 ? 4 : (smss > 2190 ? 2 : 3); } extern void tcp_enter_cwr(struct sock *sk, const int set_ssthresh); -- cgit v1.2.3-59-g8ed1b From c274f29120eff7852bb2370ae6f05f46de75edbc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 29 Aug 2010 21:43:46 +0000 Subject: net/m68k: Hydra Ethernet - print whole resource instead of start address resource_size_t changed from `unsigned long' to `phys_addr_t`, which is either `u32' or `u64'. Print the whole resource to remove the cast and to make it future-proof. Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/hydra.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 376e953c6ce6..c5ef62ceb840 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -173,9 +173,8 @@ static int __devinit hydra_init(struct zorro_dev *z) zorro_set_drvdata(z, dev); - printk(KERN_INFO "%s: Hydra at 0x%08llx, address " - "%pM (hydra.c " HYDRA_VERSION ")\n", - dev->name, (unsigned long long)z->resource.start, dev->dev_addr); + pr_info("%s: Hydra at %pR, address %pM (hydra.c " HYDRA_VERSION ")\n", + dev->name, &z->resource, dev->dev_addr); return 0; } -- cgit v1.2.3-59-g8ed1b From 6dcd814bd08bc7989f7f3eac9bbe8b20aec0182a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 30 Aug 2010 07:04:14 +0000 Subject: net: struct xfrm_tunnel in read_mostly section tunnel4_handlers chain being scanned for each incoming packet, make sure it doesnt share an often dirtied cache line. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/ipip.c | 2 +- net/ipv4/tunnel4.c | 4 ++-- net/ipv4/xfrm4_tunnel.c | 4 ++-- net/ipv6/sit.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index ec036731a70b..3c6f8f3968a6 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -744,7 +744,7 @@ static void __net_init ipip_fb_tunnel_init(struct net_device *dev) ipn->tunnels_wc[0] = tunnel; } -static struct xfrm_tunnel ipip_handler = { +static struct xfrm_tunnel ipip_handler __read_mostly = { .handler = ipip_rcv, .err_handler = ipip_err, .priority = 1, diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c index 59186ca7808a..942f02da07d8 100644 --- a/net/ipv4/tunnel4.c +++ b/net/ipv4/tunnel4.c @@ -14,8 +14,8 @@ #include #include -static struct xfrm_tunnel *tunnel4_handlers; -static struct xfrm_tunnel *tunnel64_handlers; +static struct xfrm_tunnel *tunnel4_handlers __read_mostly; +static struct xfrm_tunnel *tunnel64_handlers __read_mostly; static DEFINE_MUTEX(tunnel4_mutex); static inline struct xfrm_tunnel **fam_handlers(unsigned short family) diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 41f5982d2087..82806455e859 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c @@ -58,14 +58,14 @@ static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) return -ENOENT; } -static struct xfrm_tunnel xfrm_tunnel_handler = { +static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = { .handler = xfrm_tunnel_rcv, .err_handler = xfrm_tunnel_err, .priority = 2, }; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -static struct xfrm_tunnel xfrm64_tunnel_handler = { +static struct xfrm_tunnel xfrm64_tunnel_handler __read_mostly = { .handler = xfrm_tunnel_rcv, .err_handler = xfrm_tunnel_err, .priority = 2, diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 4699cd3c3118..86618eb30335 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1132,7 +1132,7 @@ static void __net_init ipip6_fb_tunnel_init(struct net_device *dev) sitn->tunnels_wc[0] = tunnel; } -static struct xfrm_tunnel sit_handler = { +static struct xfrm_tunnel sit_handler __read_mostly = { .handler = ipip6_rcv, .err_handler = ipip6_err, .priority = 1, -- cgit v1.2.3-59-g8ed1b From 3ff2cfa55fb35bb5ea4490fbc82bb3c6771c121b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 30 Aug 2010 10:27:10 +0000 Subject: ipv6: struct xfrm6_tunnel in read_mostly section tunnel6_handlers chain being scanned for each incoming packet, make sure it doesnt share an often dirtied cache line. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 4 ++-- net/ipv6/tunnel6.c | 4 ++-- net/ipv6/xfrm6_tunnel.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 0fd027f3f47e..29f99dd75bc6 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1372,13 +1372,13 @@ static void __net_init ip6_fb_tnl_dev_init(struct net_device *dev) ip6n->tnls_wc[0] = t; } -static struct xfrm6_tunnel ip4ip6_handler = { +static struct xfrm6_tunnel ip4ip6_handler __read_mostly = { .handler = ip4ip6_rcv, .err_handler = ip4ip6_err, .priority = 1, }; -static struct xfrm6_tunnel ip6ip6_handler = { +static struct xfrm6_tunnel ip6ip6_handler __read_mostly = { .handler = ip6ip6_rcv, .err_handler = ip6ip6_err, .priority = 1, diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index fc3c86a47452..d203e6df1f8b 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c @@ -30,8 +30,8 @@ #include #include -static struct xfrm6_tunnel *tunnel6_handlers; -static struct xfrm6_tunnel *tunnel46_handlers; +static struct xfrm6_tunnel *tunnel6_handlers __read_mostly; +static struct xfrm6_tunnel *tunnel46_handlers __read_mostly; static DEFINE_MUTEX(tunnel6_mutex); int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family) diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 2ce3a8278f26..ac7584b946a5 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -317,13 +317,13 @@ static const struct xfrm_type xfrm6_tunnel_type = { .output = xfrm6_tunnel_output, }; -static struct xfrm6_tunnel xfrm6_tunnel_handler = { +static struct xfrm6_tunnel xfrm6_tunnel_handler __read_mostly = { .handler = xfrm6_tunnel_rcv, .err_handler = xfrm6_tunnel_err, .priority = 2, }; -static struct xfrm6_tunnel xfrm46_tunnel_handler = { +static struct xfrm6_tunnel xfrm46_tunnel_handler __read_mostly = { .handler = xfrm6_tunnel_rcv, .err_handler = xfrm6_tunnel_err, .priority = 2, -- cgit v1.2.3-59-g8ed1b From 1f0f63885658889b3bcb8a08fbcb9532f8e536c9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 30 Aug 2010 21:55:17 -0700 Subject: stmmac: Fix build warnings. In file included from drivers/net/stmmac/stmmac_ethtool.c:30: drivers/net/stmmac/stmmac.h:111: warning: 'struct platform_device' declared inside parameter list drivers/net/stmmac/stmmac.h:111: warning: its scope is only this definition or declaration, which is probably not what you want drivers/net/stmmac/stmmac_main.c: In function 'stmmac_dvr_probe': drivers/net/stmmac/stmmac_main.c:1744: warning: cast from pointer to integer of different size In file included from drivers/net/stmmac/stmmac_mdio.c:31: drivers/net/stmmac/stmmac.h:111: warning: 'struct platform_device' declared inside parameter list drivers/net/stmmac/stmmac.h:111: warning: its scope is only this definition or declaration, which is probably not what you want drivers/net/stmmac/dwmac1000_core.c: In function 'dwmac1000_dump_regs': drivers/net/stmmac/dwmac1000_core.c:56: warning: cast from pointer to integer of different size Reported-by: Stephen Rothwell Signed-off-by: David S. Miller --- drivers/net/stmmac/dwmac1000_core.c | 2 +- drivers/net/stmmac/stmmac.h | 1 + drivers/net/stmmac/stmmac_main.c | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c index 8bbfc0f48dea..f1f426146f40 100644 --- a/drivers/net/stmmac/dwmac1000_core.c +++ b/drivers/net/stmmac/dwmac1000_core.c @@ -53,7 +53,7 @@ static void dwmac1000_core_init(void __iomem *ioaddr) static void dwmac1000_dump_regs(void __iomem *ioaddr) { int i; - pr_info("\tDWMAC1000 regs (base addr = 0x%8x)\n", (unsigned int)ioaddr); + pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr); for (i = 0; i < 55; i++) { int offset = i * 4; diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h index cca53dbac361..d0ddab0d21c2 100644 --- a/drivers/net/stmmac/stmmac.h +++ b/drivers/net/stmmac/stmmac.h @@ -21,6 +21,7 @@ *******************************************************************************/ #define DRV_MODULE_VERSION "Apr_2010" +#include #include #include "common.h" diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index c59c1061252a..e3f002eba89a 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -1742,8 +1742,8 @@ static int stmmac_dvr_probe(struct platform_device *pdev) priv->bsp_priv = plat_dat->bsp_priv; pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n" - "\tIO base addr: 0x%08x)\n", ndev->name, pdev->name, - pdev->id, ndev->irq, (unsigned int)addr); + "\tIO base addr: 0x%p)\n", ndev->name, pdev->name, + pdev->id, ndev->irq, addr); /* MDIO bus Registration */ pr_debug("\tMDIO bus (id: %d)...", priv->bus_id); -- cgit v1.2.3-59-g8ed1b From ea24ea850bcd7dd5f0994de2cf99ace10c4484cc Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Tue, 31 Aug 2010 00:37:03 +0900 Subject: idr: fix kernel-doc warnings. Fix the following kernel-doc warnings. % perl scripts/kernel-doc lib/idr.c > /dev/null Warning(lib/idr.c:300): No description found for parameter 'starting_id' Warning(lib/idr.c:300): Excess function parameter 'start_id' description in 'idr_get_new_above' Warning(lib/idr.c:485): No description found for parameter 'idp' Warning(lib/idr.c:596): No description found for parameter 'nextidp' Warning(lib/idr.c:596): Excess function parameter 'id' description in 'idr_get_next' Warning(lib/idr.c:774): No description found for parameter 'starting_id' Warning(lib/idr.c:774): Excess function parameter 'staring_id' description in 'ida_get_new_above' Warning(lib/idr.c:918): No description found for parameter 'ida' Signed-off-by: Naohiro Aota Acked-by: Tejun Heo Signed-off-by: Jiri Kosina --- lib/idr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/idr.c b/lib/idr.c index 7f1a4f0acf50..fb86a675dcff 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -284,7 +284,7 @@ static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) * idr_get_new_above - allocate new idr entry above or equal to a start id * @idp: idr handle * @ptr: pointer you want associated with the id - * @start_id: id to start search at + * @starting_id: id to start search at * @id: pointer to the allocated handle * * This is the allocate id function. It should be called with any @@ -479,7 +479,7 @@ EXPORT_SYMBOL(idr_remove_all); /** * idr_destroy - release all cached layers within an idr tree - * idp: idr handle + * @idp: idr handle */ void idr_destroy(struct idr *idp) { @@ -586,7 +586,7 @@ EXPORT_SYMBOL(idr_for_each); /** * idr_get_next - lookup next object of id to given id. * @idp: idr handle - * @id: pointer to lookup key + * @nextidp: pointer to lookup key * * Returns pointer to registered object with id, which is next number to * given id. @@ -758,7 +758,7 @@ EXPORT_SYMBOL(ida_pre_get); /** * ida_get_new_above - allocate new ID above or equal to a start id * @ida: ida handle - * @staring_id: id to start search at + * @starting_id: id to start search at * @p_id: pointer to the allocated handle * * Allocate new ID above or equal to @ida. It should be called with @@ -912,7 +912,7 @@ EXPORT_SYMBOL(ida_remove); /** * ida_destroy - release all cached layers within an ida tree - * ida: ida handle + * @ida: ida handle */ void ida_destroy(struct ida *ida) { -- cgit v1.2.3-59-g8ed1b From 1458ce166c1b333ecbaf8caa9f4f54eab3a522a7 Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Fri, 27 Aug 2010 17:43:46 +0900 Subject: idr: describe how nextidp works in idr_get_next(). It was unclear in original kernel-doc how nextidp worked in idr_get_next(). Let's describe it. Signed-off-by: Naohiro Aota Acked-by: Tejun Heo Signed-off-by: Jiri Kosina --- lib/idr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/idr.c b/lib/idr.c index fb86a675dcff..5e0966be0f7c 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -589,7 +589,8 @@ EXPORT_SYMBOL(idr_for_each); * @nextidp: pointer to lookup key * * Returns pointer to registered object with id, which is next number to - * given id. + * given id. After being looked up, *@nextidp will be updated for the next + * iteration. */ void *idr_get_next(struct idr *idp, int *nextidp) -- cgit v1.2.3-59-g8ed1b From ffc4fdbbe1b4be79e98340ebcd5a0ade6f5de318 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Thu, 26 Aug 2010 14:53:51 +0200 Subject: ASoC: fix au1x platform This patch fixes up the au1x audio platform after the multi-component merge: - compile fixes and updates to get DB1200 platform audio working again, - removal of global variables in AC97/I2S/DMA(PCM) modules. The AC97 part is limited to one instance only for now due to issues with getting at driver data in the soc_ac97_ops. Signed-off-by: Manuel Lauss Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- arch/mips/alchemy/devboards/db1200/platform.c | 6 ++ sound/soc/au1x/db1200.c | 16 +++--- sound/soc/au1x/dbdma2.c | 82 +++++++++------------------ sound/soc/au1x/psc-ac97.c | 59 +++++++++++-------- sound/soc/au1x/psc-i2s.c | 42 +++++--------- sound/soc/au1x/psc.h | 7 +-- 6 files changed, 91 insertions(+), 121 deletions(-) diff --git a/arch/mips/alchemy/devboards/db1200/platform.c b/arch/mips/alchemy/devboards/db1200/platform.c index 3fa34c3abc04..fbb55935b99e 100644 --- a/arch/mips/alchemy/devboards/db1200/platform.c +++ b/arch/mips/alchemy/devboards/db1200/platform.c @@ -429,6 +429,11 @@ static struct platform_device db1200_audio_dev = { .resource = au1200_psc1_res, }; +static struct platform_device db1200_stac_dev = { + .name = "ac97-codec", + .id = 1, /* on PSC1 */ +}; + static struct platform_device *db1200_devs[] __initdata = { NULL, /* PSC0, selected by S6.8 */ &db1200_ide_dev, @@ -436,6 +441,7 @@ static struct platform_device *db1200_devs[] __initdata = { &db1200_rtc_dev, &db1200_nand_dev, &db1200_audio_dev, + &db1200_stac_dev, }; static int __init db1200_dev_init(void) diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index d8dc8225576a..b62fcd33e586 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c @@ -27,10 +27,10 @@ static struct snd_soc_dai_link db1200_ac97_dai = { .name = "AC97", .stream_name = "AC97 HiFi", - .cpu_dai_name = "au1xpsc-ac97", .codec_dai_name = "ac97-hifi", - .platform_name = "au1xpsc-pcm-audio", - .codec_name = "ac97-codec", + .cpu_dai_name = "au1xpsc_ac97.1", + .platform_name = "au1xpsc-pcm.1", + .codec_name = "ac97-codec.1", }; static struct snd_soc_card db1200_ac97_machine = { @@ -75,10 +75,10 @@ static struct snd_soc_ops db1200_i2s_wm8731_ops = { static struct snd_soc_dai_link db1200_i2s_dai = { .name = "WM8731", .stream_name = "WM8731 PCM", - .cpu_dai_name = "au1xpsc", - .codec_dai_name = "wm8731-hifi" - .platform_name = "au1xpsc-pcm-audio", - .codec_name = "wm8731-codec.0-001a", + .codec_dai_name = "wm8731-hifi", + .cpu_dai_name = "au1xpsc_i2s.1", + .platform_name = "au1xpsc-pcm.1", + .codec_name = "wm8731-codec.0-001b", .ops = &db1200_i2s_wm8731_ops, }; @@ -97,7 +97,7 @@ static int __init db1200_audio_load(void) int ret; ret = -ENOMEM; - db1200_asoc_dev = platform_device_alloc("soc-audio", -1); + db1200_asoc_dev = platform_device_alloc("soc-audio", 1); /* PSC1 */ if (!db1200_asoc_dev) goto out; diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 00fdb9cbfc2d..10fdd2854e58 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -10,9 +10,6 @@ * * DMA glue for Au1x-PSC audio. * - * NOTE: all of these drivers can only work with a SINGLE instance - * of a PSC. Multiple independent audio devices are impossible - * with ASoC v1. */ @@ -61,9 +58,6 @@ struct au1xpsc_audio_dmadata { int msbits; }; -/* instance data. There can be only one, MacLeod!!!! */ -static struct au1xpsc_audio_dmadata *au1xpsc_audio_pcmdma[2]; - /* * These settings are somewhat okay, at least on my machine audio plays * almost skip-free. Especially the 64kB buffer seems to help a LOT. @@ -199,6 +193,14 @@ out: return 0; } +static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream *ss) +{ + struct snd_soc_pcm_runtime *rtd = ss->private_data; + struct au1xpsc_audio_dmadata *pcd = + snd_soc_platform_get_drvdata(rtd->platform); + return &pcd[SUBSTREAM_TYPE(ss)]; +} + static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -211,7 +213,7 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, goto out; stype = SUBSTREAM_TYPE(substream); - pcd = au1xpsc_audio_pcmdma[stype]; + pcd = to_dmadata(substream); DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d " "runtime->min_align %d\n", @@ -249,8 +251,7 @@ static int au1xpsc_pcm_hw_free(struct snd_pcm_substream *substream) static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream) { - struct au1xpsc_audio_dmadata *pcd = - au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]; + struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream); au1xxx_dbdma_reset(pcd->ddma_chan); @@ -267,7 +268,7 @@ static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream) static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { - u32 c = au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->ddma_chan; + u32 c = to_dmadata(substream)->ddma_chan; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -287,8 +288,7 @@ static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) static snd_pcm_uframes_t au1xpsc_pcm_pointer(struct snd_pcm_substream *substream) { - return bytes_to_frames(substream->runtime, - au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->pos); + return bytes_to_frames(substream->runtime, to_dmadata(substream)->pos); } static int au1xpsc_pcm_open(struct snd_pcm_substream *substream) @@ -299,7 +299,7 @@ static int au1xpsc_pcm_open(struct snd_pcm_substream *substream) static int au1xpsc_pcm_close(struct snd_pcm_substream *substream) { - au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]); + au1x_pcm_dbdma_free(to_dmadata(substream)); return 0; } @@ -329,35 +329,21 @@ static int au1xpsc_pcm_new(struct snd_card *card, return 0; } -static int au1xpsc_pcm_probe(struct snd_soc_platform *platform) -{ - if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX]) - return -ENODEV; - - return 0; -} - /* au1xpsc audio platform */ struct snd_soc_platform_driver au1xpsc_soc_platform = { - .probe = au1xpsc_pcm_probe, .ops = &au1xpsc_pcm_ops, .pcm_new = au1xpsc_pcm_new, .pcm_free = au1xpsc_pcm_free_dma_buffers, }; -EXPORT_SYMBOL_GPL(au1xpsc_soc_platform); static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) { + struct au1xpsc_audio_dmadata *dmadata; struct resource *r; int ret; - if (au1xpsc_audio_pcmdma[PCM_TX] || au1xpsc_audio_pcmdma[PCM_RX]) - return -EBUSY; - - /* TX DMA */ - au1xpsc_audio_pcmdma[PCM_TX] - = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL); - if (!au1xpsc_audio_pcmdma[PCM_TX]) + dmadata = kzalloc(2 * sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL); + if (!dmadata) return -ENOMEM; r = platform_get_resource(pdev, IORESOURCE_DMA, 0); @@ -365,54 +351,40 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) ret = -ENODEV; goto out1; } - (au1xpsc_audio_pcmdma[PCM_TX])->ddma_id = r->start; + dmadata[PCM_TX].ddma_id = r->start; /* RX DMA */ - au1xpsc_audio_pcmdma[PCM_RX] - = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL); - if (!au1xpsc_audio_pcmdma[PCM_RX]) - return -ENOMEM; - r = platform_get_resource(pdev, IORESOURCE_DMA, 1); if (!r) { ret = -ENODEV; - goto out2; + goto out1; } - (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start; + dmadata[PCM_RX].ddma_id = r->start; + + platform_set_drvdata(pdev, dmadata); ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform); if (!ret) return ret; -out2: - kfree(au1xpsc_audio_pcmdma[PCM_RX]); - au1xpsc_audio_pcmdma[PCM_RX] = NULL; out1: - kfree(au1xpsc_audio_pcmdma[PCM_TX]); - au1xpsc_audio_pcmdma[PCM_TX] = NULL; + kfree(dmadata); return ret; } static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev) { - int i; + struct au1xpsc_audio_dmadata *dmadata = platform_get_drvdata(pdev); snd_soc_unregister_platform(&pdev->dev); - - for (i = 0; i < 2; i++) { - if (au1xpsc_audio_pcmdma[i]) { - au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]); - kfree(au1xpsc_audio_pcmdma[i]); - au1xpsc_audio_pcmdma[i] = NULL; - } - } + kfree(dmadata); return 0; } static struct platform_driver au1xpsc_pcm_driver = { .driver = { - .name = "au1xpsc-pcm-audio", + .name = "au1xpsc-pcm", .owner = THIS_MODULE, }, .probe = au1xpsc_pcm_drvprobe, @@ -421,8 +393,6 @@ static struct platform_driver au1xpsc_pcm_driver = { static int __init au1xpsc_audio_dbdma_load(void) { - au1xpsc_audio_pcmdma[PCM_TX] = NULL; - au1xpsc_audio_pcmdma[PCM_RX] = NULL; return platform_driver_register(&au1xpsc_pcm_driver); } @@ -460,7 +430,7 @@ struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev) res[1].start = res[1].end = id[1]; res[0].flags = res[1].flags = IORESOURCE_DMA; - pd = platform_device_alloc("au1xpsc-pcm", -1); + pd = platform_device_alloc("au1xpsc-pcm", pdev->id); if (!pd) goto out; diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 6a9516cbe424..d0db66f24a00 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c @@ -10,9 +10,6 @@ * * Au1xxx-PSC AC97 glue. * - * NOTE: all of these drivers can only work with a SINGLE instance - * of a PSC. Multiple independent audio devices are impossible - * with ASoC v1. */ #include @@ -56,12 +53,29 @@ /* instance data. There can be only one, MacLeod!!!! */ static struct au1xpsc_audio_data *au1xpsc_ac97_workdata; +#if 0 + +/* this could theoretically work, but ac97->bus->card->private_data can be NULL + * when snd_ac97_mixer() is called; I don't know if the rest further down the + * chain are always valid either. + */ +static inline struct au1xpsc_audio_data *ac97_to_pscdata(struct snd_ac97 *x) +{ + struct snd_soc_card *c = x->bus->card->private_data; + return snd_soc_dai_get_drvdata(c->rtd->cpu_dai); +} + +#else + +#define ac97_to_pscdata(x) au1xpsc_ac97_workdata + +#endif + /* AC97 controller reads codec register */ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { - /* FIXME */ - struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; + struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); unsigned short retry, tmo; unsigned long data; @@ -102,8 +116,7 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97, static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { - /* FIXME */ - struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; + struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); unsigned int tmo, retry; au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); @@ -134,8 +147,7 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, /* AC97 controller asserts a warm reset */ static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97) { - /* FIXME */ - struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; + struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata)); au_sync(); @@ -146,8 +158,7 @@ static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97) static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) { - /* FIXME */ - struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; + struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); int i; /* disable PSC during cold reset */ @@ -202,8 +213,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - /* FIXME */ - struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; + struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); unsigned long r, ro, stat; int chans, t, stype = SUBSTREAM_TYPE(substream); @@ -283,8 +293,7 @@ out: static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - /* FIXME */ - struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; + struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); int ret, stype = SUBSTREAM_TYPE(substream); ret = 0; @@ -325,7 +334,7 @@ static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { .hw_params = au1xpsc_ac97_hw_params, }; -struct snd_soc_dai_driver au1xpsc_ac97_dai = { +static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = { .ac97_control = 1, .probe = au1xpsc_ac97_probe, .playback = { @@ -342,7 +351,6 @@ struct snd_soc_dai_driver au1xpsc_ac97_dai = { }, .ops = &au1xpsc_ac97_dai_ops, }; -EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai); static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) { @@ -351,9 +359,6 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) unsigned long sel; struct au1xpsc_audio_data *wd; - if (au1xpsc_ac97_workdata) - return -EBUSY; - wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); if (!wd) return -ENOMEM; @@ -387,14 +392,20 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd)); au_sync(); - ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_ac97_dai); + /* name the DAI like this device instance ("au1xpsc-ac97.PSCINDEX") */ + memcpy(&wd->dai_drv, &au1xpsc_ac97_dai_template, + sizeof(struct snd_soc_dai_driver)); + wd->dai_drv.name = dev_name(&pdev->dev); + + platform_set_drvdata(pdev, wd); + + ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv); if (ret) goto out1; wd->dmapd = au1xpsc_pcm_add(pdev); if (wd->dmapd) { - platform_set_drvdata(pdev, wd); - au1xpsc_ac97_workdata = wd; /* MDEV */ + au1xpsc_ac97_workdata = wd; return 0; } @@ -477,7 +488,7 @@ static struct dev_pm_ops au1xpscac97_pmops = { static struct platform_driver au1xpsc_ac97_driver = { .driver = { - .name = "au1xpsc-ac97", + .name = "au1xpsc_ac97", .owner = THIS_MODULE, .pm = AU1XPSCAC97_PMOPS, }, diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 94e560a8756d..fca091276320 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -10,9 +10,6 @@ * * Au1xxx-PSC I2S glue. * - * NOTE: all of these drivers can only work with a SINGLE instance - * of a PSC. Multiple independent audio devices are impossible - * with ASoC v1. * NOTE: so far only PSC slave mode (bit- and frameclock) is supported. */ @@ -54,13 +51,10 @@ ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC) -/* instance data. There can be only one, MacLeod!!!! */ -static struct au1xpsc_audio_data *au1xpsc_i2s_workdata; - static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; + struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(cpu_dai); unsigned long ct; int ret; @@ -120,7 +114,7 @@ static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; + struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); int cfgbits; unsigned long stat; @@ -245,7 +239,7 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype) static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; + struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); int ret, stype = SUBSTREAM_TYPE(substream); switch (cmd) { @@ -263,19 +257,13 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, return ret; } -static int au1xpsc_i2s_probe(struct snd_soc_dai *dai) -{ - return au1xpsc_i2s_workdata ? 0 : -ENODEV; -} - static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { .trigger = au1xpsc_i2s_trigger, .hw_params = au1xpsc_i2s_hw_params, .set_fmt = au1xpsc_i2s_set_fmt, }; -static struct snd_soc_dai_driver au1xpsc_i2s_dai = { - .probe = au1xpsc_i2s_probe, +static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = { .playback = { .rates = AU1XPSC_I2S_RATES, .formats = AU1XPSC_I2S_FMTS, @@ -298,9 +286,6 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) int ret; struct au1xpsc_audio_data *wd; - if (au1xpsc_i2s_workdata) - return -EBUSY; - wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); if (!wd) return -ENOMEM; @@ -337,17 +322,21 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) * time out. */ - ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_i2s_dai); + /* name the DAI like this device instance ("au1xpsc-i2s.PSCINDEX") */ + memcpy(&wd->dai_drv, &au1xpsc_i2s_dai_template, + sizeof(struct snd_soc_dai_driver)); + wd->dai_drv.name = dev_name(&pdev->dev); + + platform_set_drvdata(pdev, wd); + + ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv); if (ret) goto out1; /* finally add the DMA device for this PSC */ wd->dmapd = au1xpsc_pcm_add(pdev); - if (wd->dmapd) { - platform_set_drvdata(pdev, wd); - au1xpsc_i2s_workdata = wd; + if (wd->dmapd) return 0; - } snd_soc_unregister_dai(&pdev->dev); out1: @@ -376,8 +365,6 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev) release_mem_region(r->start, resource_size(r)); kfree(wd); - au1xpsc_i2s_workdata = NULL; /* MDEV */ - return 0; } @@ -427,7 +414,7 @@ static struct dev_pm_ops au1xpsci2s_pmops = { static struct platform_driver au1xpsc_i2s_driver = { .driver = { - .name = "au1xpsc", + .name = "au1xpsc_i2s", .owner = THIS_MODULE, .pm = AU1XPSCI2S_PMOPS, }, @@ -437,7 +424,6 @@ static struct platform_driver au1xpsc_i2s_driver = { static int __init au1xpsc_i2s_load(void) { - au1xpsc_i2s_workdata = NULL; return platform_driver_register(&au1xpsc_i2s_driver); } diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h index f281443fd52f..b30eadd422a7 100644 --- a/sound/soc/au1x/psc.h +++ b/sound/soc/au1x/psc.h @@ -8,16 +8,11 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * NOTE: all of these drivers can only work with a SINGLE instance - * of a PSC. Multiple independent audio devices are impossible - * with ASoC v1. */ #ifndef _AU1X_PCM_H #define _AU1X_PCM_H -extern struct snd_ac97_bus_ops soc_ac97_ops; - /* DBDMA helpers */ extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev); extern void au1xpsc_pcm_destroy(struct platform_device *dmapd); @@ -28,6 +23,8 @@ struct au1xpsc_audio_data { unsigned long cfg; unsigned long rate; + struct snd_soc_dai_driver dai_drv; + unsigned long pm[2]; struct mutex lock; struct platform_device *dmapd; -- cgit v1.2.3-59-g8ed1b From 4e48541676f019145b555761d89bf4f8607d3de0 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 31 Aug 2010 14:52:35 +0300 Subject: ASoC: Swap bias level enumeration Swapping the bias level enumeration is only meant to help debugging. It is easier if number 0 means bias off and bigger number means bigger bias level. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- include/sound/soc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index d31e8b7b2d5e..493b3a4c193a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -214,10 +214,10 @@ * @OFF: Power Off. No restrictions on transition times. */ enum snd_soc_bias_level { - SND_SOC_BIAS_ON, - SND_SOC_BIAS_PREPARE, - SND_SOC_BIAS_STANDBY, SND_SOC_BIAS_OFF, + SND_SOC_BIAS_STANDBY, + SND_SOC_BIAS_PREPARE, + SND_SOC_BIAS_ON, }; struct snd_jack; -- cgit v1.2.3-59-g8ed1b From 8614d310a2ba78cfc73ab12da112c3115801f94e Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Mon, 30 Aug 2010 11:28:07 +0300 Subject: ASoC: uda1380: make driver more powersave-friendly Disable some codec modules in standby mode, completely disable codec in off mode to save some power. Fix suspend/resume: mark mixer regs as dirty on resume to restore mixer values, otherwise driver produces no sound (master is muted by default). Signed-off-by: Vasily Khoruzhick Acked-by: Marek Vasut Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/uda1380.c | 145 ++++++++++++++++++++++++++++++++------------- 1 file changed, 105 insertions(+), 40 deletions(-) diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 1a51c816e542..488f8010e405 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -39,6 +39,7 @@ struct uda1380_priv { u16 reg_cache[UDA1380_CACHEREGNUM]; unsigned int dac_clk; struct work_struct work; + void *control_data; }; /* @@ -129,7 +130,46 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, return -EIO; } -#define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0) +static void uda1380_sync_cache(struct snd_soc_codec *codec) +{ + int reg; + u8 data[3]; + u16 *cache = codec->reg_cache; + + /* Sync reg_cache with the hardware */ + for (reg = 0; reg < UDA1380_MVOL; reg++) { + data[0] = reg; + data[1] = (cache[reg] & 0xff00) >> 8; + data[2] = cache[reg] & 0x00ff; + if (codec->hw_write(codec->control_data, data, 3) != 3) + dev_err(codec->dev, "%s: write to reg 0x%x failed\n", + __func__, reg); + } +} + +static int uda1380_reset(struct snd_soc_codec *codec) +{ + struct uda1380_platform_data *pdata = codec->dev->platform_data; + + if (gpio_is_valid(pdata->gpio_reset)) { + gpio_set_value(pdata->gpio_reset, 1); + mdelay(1); + gpio_set_value(pdata->gpio_reset, 0); + } else { + u8 data[3]; + + data[0] = UDA1380_RESET; + data[1] = 0; + data[2] = 0; + + if (codec->hw_write(codec->control_data, data, 3) != 3) { + dev_err(codec->dev, "%s: failed\n", __func__); + return -EIO; + } + } + + return 0; +} static void uda1380_flush_work(struct work_struct *work) { @@ -560,18 +600,40 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { int pm = uda1380_read_reg_cache(codec, UDA1380_PM); + int reg; + struct uda1380_platform_data *pdata = codec->dev->platform_data; + + if (codec->bias_level == level) + return 0; switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: + /* ADC, DAC on */ uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm); break; case SND_SOC_BIAS_STANDBY: - uda1380_write(codec, UDA1380_PM, R02_PON_BIAS); - break; - case SND_SOC_BIAS_OFF: + if (codec->bias_level == SND_SOC_BIAS_OFF) { + if (gpio_is_valid(pdata->gpio_power)) { + gpio_set_value(pdata->gpio_power, 1); + uda1380_reset(codec); + } + + uda1380_sync_cache(codec); + } uda1380_write(codec, UDA1380_PM, 0x0); break; + case SND_SOC_BIAS_OFF: + if (!gpio_is_valid(pdata->gpio_power)) + break; + + gpio_set_value(pdata->gpio_power, 0); + + /* Mark mixer regs cache dirty to sync them with + * codec regs on power on. + */ + for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM; reg++) + set_bit(reg - 0x10, &uda1380_cache_dirty); } codec->bias_level = level; return 0; @@ -651,16 +713,6 @@ static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state) static int uda1380_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(uda1380_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } @@ -671,29 +723,36 @@ static int uda1380_probe(struct snd_soc_codec *codec) struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); int ret; + uda1380->codec = codec; + codec->hw_write = (hw_write_t)i2c_master_send; + codec->control_data = uda1380->control_data; - if (!pdata || !pdata->gpio_power || !pdata->gpio_reset) + if (!pdata) return -EINVAL; - ret = gpio_request(pdata->gpio_power, "uda1380 power"); - if (ret) - return ret; - ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); - if (ret) - goto err_gpio; - - gpio_direction_output(pdata->gpio_power, 1); - - /* we may need to have the clock running here - pH5 */ - gpio_direction_output(pdata->gpio_reset, 1); - udelay(5); - gpio_set_value(pdata->gpio_reset, 0); + if (gpio_is_valid(pdata->gpio_reset)) { + ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); + if (ret) + goto err_out; + ret = gpio_direction_output(pdata->gpio_reset, 0); + if (ret) + goto err_gpio_reset_conf; + } - ret = uda1380_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_reset; + if (gpio_is_valid(pdata->gpio_power)) { + ret = gpio_request(pdata->gpio_power, "uda1380 power"); + if (ret) + goto err_gpio; + ret = gpio_direction_output(pdata->gpio_power, 0); + if (ret) + goto err_gpio_power_conf; + } else { + ret = uda1380_reset(codec); + if (ret) { + dev_err(codec->dev, "Failed to issue reset\n"); + goto err_reset; + } } INIT_WORK(&uda1380->work, uda1380_flush_work); @@ -703,10 +762,11 @@ static int uda1380_probe(struct snd_soc_codec *codec) /* set clock input */ switch (pdata->dac_clk) { case UDA1380_DAC_CLK_SYSCLK: - uda1380_write(codec, UDA1380_CLK, 0); + uda1380_write_reg_cache(codec, UDA1380_CLK, 0); break; case UDA1380_DAC_CLK_WSPLL: - uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); + uda1380_write_reg_cache(codec, UDA1380_CLK, + R00_DAC_CLK); break; } @@ -717,10 +777,15 @@ static int uda1380_probe(struct snd_soc_codec *codec) return 0; err_reset: - gpio_set_value(pdata->gpio_power, 0); - gpio_free(pdata->gpio_reset); +err_gpio_power_conf: + if (gpio_is_valid(pdata->gpio_power)) + gpio_free(pdata->gpio_power); + +err_gpio_reset_conf: err_gpio: - gpio_free(pdata->gpio_power); + if (gpio_is_valid(pdata->gpio_reset)) + gpio_free(pdata->gpio_reset); +err_out: return ret; } @@ -731,7 +796,6 @@ static int uda1380_remove(struct snd_soc_codec *codec) uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); - gpio_set_value(pdata->gpio_power, 0); gpio_free(pdata->gpio_reset); gpio_free(pdata->gpio_power); @@ -743,8 +807,8 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { .remove = uda1380_remove, .suspend = uda1380_suspend, .resume = uda1380_resume, - .read = uda1380_read_reg_cache, - .write = uda1380_write, + .read = uda1380_read_reg_cache, + .write = uda1380_write, .set_bias_level = uda1380_set_bias_level, .reg_cache_size = ARRAY_SIZE(uda1380_reg), .reg_word_size = sizeof(u16), @@ -764,6 +828,7 @@ static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, uda1380); + uda1380->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai)); -- cgit v1.2.3-59-g8ed1b From 81d97802834acb908722636ff774b0f50cbf6131 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Mon, 30 Aug 2010 11:28:08 +0300 Subject: ASoC: Add HP iPAQ RX1950 support Signed-off-by: Vasily Khoruzhick Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/s3c24xx/Kconfig | 8 + sound/soc/s3c24xx/Makefile | 2 + sound/soc/s3c24xx/rx1950_uda1380.c | 335 +++++++++++++++++++++++++++++++++++++ 3 files changed, 345 insertions(+) create mode 100644 sound/soc/s3c24xx/rx1950_uda1380.c diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index 1cdc37bd58f4..7d8235de549e 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig @@ -118,6 +118,14 @@ config SND_S3C24XX_SOC_SIMTEC_HERMES select SND_SOC_TLV320AIC3X select SND_S3C24XX_SOC_SIMTEC +config SND_S3C24XX_SOC_RX1950_UDA1380 + tristate "Audio support for the HP iPAQ RX1950" + depends on SND_S3C24XX_SOC && MACH_RX1950 + select SND_S3C24XX_SOC_I2S + select SND_SOC_UDA1380 + help + This driver provides audio support for HP iPAQ RX1950 PDA. + config SND_SOC_SMDK_WM9713 tristate "SoC AC97 Audio support for SMDK with WM9713" depends on SND_S3C24XX_SOC && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 47ed6d70b90b..dd412a9e88c3 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile @@ -27,6 +27,7 @@ snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o +snd-soc-rx1950-uda1380-objs := rx1950_uda1380.o snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o snd-soc-smdk-wm9713-objs := smdk_wm9713.o snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o @@ -42,6 +43,7 @@ obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o +obj-$(CONFIG_SND_S3C24XX_SOC_RX1950_UDA1380) += snd-soc-rx1950-uda1380.o obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o diff --git a/sound/soc/s3c24xx/rx1950_uda1380.c b/sound/soc/s3c24xx/rx1950_uda1380.c new file mode 100644 index 000000000000..2a16113231fd --- /dev/null +++ b/sound/soc/s3c24xx/rx1950_uda1380.c @@ -0,0 +1,335 @@ +/* + * rx1950.c -- ALSA Soc Audio Layer + * + * Copyright (c) 2010 Vasily Khoruzhick + * + * Based on smdk2440.c and magician.c + * + * Authors: Graeme Gregory graeme.gregory@wolfsonmicro.com + * Philipp Zabel + * Denis Grigoriev + * Vasily Khoruzhick + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "s3c-dma.h" +#include "s3c24xx-i2s.h" +#include "../codecs/uda1380.h" + +static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd); +static int rx1950_startup(struct snd_pcm_substream *substream); +static int rx1950_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +static int rx1950_spk_power(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); + +static unsigned int rates[] = { + 16000, + 44100, + 48000, + 88200, +}; + +static struct snd_pcm_hw_constraint_list hw_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, +}; + +static struct snd_soc_jack hp_jack; + +static struct snd_soc_jack_pin hp_jack_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Speaker", + .mask = SND_JACK_HEADPHONE, + .invert = 1, + }, +}; + +static struct snd_soc_jack_gpio hp_jack_gpios[] = { + [0] = { + .gpio = S3C2410_GPG(12), + .name = "hp-gpio", + .report = SND_JACK_HEADPHONE, + .invert = 1, + .debounce_time = 200, + }, +}; + +static struct snd_soc_ops rx1950_ops = { + .startup = rx1950_startup, + .hw_params = rx1950_hw_params, +}; + +/* s3c24xx digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link rx1950_uda1380_dai[] = { + { + .name = "uda1380", + .stream_name = "UDA1380 Duplex", + .cpu_dai_name = "s3c24xx-iis", + .codec_dai_name = "uda1380-hifi", + .init = rx1950_uda1380_init, + .platform_name = "s3c24xx-pcm-audio", + .codec_name = "uda1380-codec.0-001a", + .ops = &rx1950_ops, + }, +}; + +static struct snd_soc_card rx1950_asoc = { + .name = "rx1950", + .dai_link = rx1950_uda1380_dai, + .num_links = ARRAY_SIZE(rx1950_uda1380_dai), +}; + +/* rx1950 machine dapm widgets */ +static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_SPK("Speaker", rx1950_spk_power), +}; + +/* rx1950 machine audio_map */ +static const struct snd_soc_dapm_route audio_map[] = { + /* headphone connected to VOUTLHP, VOUTRHP */ + {"Headphone Jack", NULL, "VOUTLHP"}, + {"Headphone Jack", NULL, "VOUTRHP"}, + + /* ext speaker connected to VOUTL, VOUTR */ + {"Speaker", NULL, "VOUTL"}, + {"Speaker", NULL, "VOUTR"}, + + /* mic is connected to VINM */ + {"VINM", NULL, "Mic Jack"}, +}; + +static struct platform_device *s3c24xx_snd_device; +static struct clk *xtal; + +static int rx1950_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw.rate_min = hw_rates.list[0]; + runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; + runtime->hw.rates = SNDRV_PCM_RATE_KNOT; + + return snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &hw_rates); +} + +static int rx1950_spk_power(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (SND_SOC_DAPM_EVENT_ON(event)) + gpio_set_value(S3C2410_GPA(1), 1); + else + gpio_set_value(S3C2410_GPA(1), 0); + + return 0; +} + +static int rx1950_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int div; + int ret; + unsigned int rate = params_rate(params); + int clk_source, fs_mode; + + switch (rate) { + case 16000: + case 48000: + clk_source = S3C24XX_CLKSRC_PCLK; + fs_mode = S3C2410_IISMOD_384FS; + div = s3c24xx_i2s_get_clockrate() / (384 * rate); + if (s3c24xx_i2s_get_clockrate() % (384 * rate) > (182 * rate)) + div++; + break; + case 44100: + case 88200: + clk_source = S3C24XX_CLKSRC_MPLL; + fs_mode = S3C2410_IISMOD_256FS; + div = clk_get_rate(xtal) / (256 * rate); + if (clk_get_rate(xtal) % (256 * rate) > (128 * rate)) + div++; + break; + default: + printk(KERN_ERR "%s: rate %d is not supported\n", + __func__, rate); + return -EINVAL; + } + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + + /* select clock source */ + ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source, rate, + SND_SOC_CLOCK_OUT); + if (ret < 0) + return ret; + + /* set MCLK division for sample rate */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, + S3C2410_IISMOD_384FS); + if (ret < 0) + return ret; + + /* set BCLK division for sample rate */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK, + S3C2410_IISMOD_32FS); + if (ret < 0) + return ret; + + /* set prescaler division for sample rate */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, + S3C24XX_PRESCALE(div, div)); + if (ret < 0) + return ret; + + return 0; +} + +static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + int err; + + /* Add rx1950 specific widgets */ + err = snd_soc_dapm_new_controls(codec, uda1380_dapm_widgets, + ARRAY_SIZE(uda1380_dapm_widgets)); + + if (err) + return err; + + /* Set up rx1950 specific audio path audio_mapnects */ + err = snd_soc_dapm_add_routes(codec, audio_map, + ARRAY_SIZE(audio_map)); + + if (err) + return err; + + snd_soc_dapm_enable_pin(codec, "Headphone Jack"); + snd_soc_dapm_enable_pin(codec, "Speaker"); + + snd_soc_dapm_sync(codec); + + snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, + &hp_jack); + + snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), + hp_jack_pins); + + snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), + hp_jack_gpios); + + return 0; +} + +static int __init rx1950_init(void) +{ + int ret; + + /* configure some gpios */ + ret = gpio_request(S3C2410_GPA(1), "speaker-power"); + if (ret) + goto err_gpio; + + ret = gpio_direction_output(S3C2410_GPA(1), 0); + if (ret) + goto err_gpio_conf; + + s3c24xx_snd_device = platform_device_alloc("soc-audio", -1); + if (!s3c24xx_snd_device) { + ret = -ENOMEM; + goto err_plat_alloc; + } + + platform_set_drvdata(s3c24xx_snd_device, &rx1950_asoc); + ret = platform_device_add(s3c24xx_snd_device); + + if (ret) { + platform_device_put(s3c24xx_snd_device); + goto err_plat_add; + } + + xtal = clk_get(&s3c24xx_snd_device->dev, "xtal"); + + if (IS_ERR(xtal)) { + ret = PTR_ERR(xtal); + platform_device_unregister(s3c24xx_snd_device); + goto err_clk; + } + + return 0; + +err_clk: +err_plat_add: +err_plat_alloc: +err_gpio_conf: + gpio_free(S3C2410_GPA(1)); + +err_gpio: + return ret; +} + +static void __exit rx1950_exit(void) +{ + platform_device_unregister(s3c24xx_snd_device); + snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), + hp_jack_gpios); + clk_put(xtal); + gpio_free(S3C2410_GPA(1)); +} + +module_init(rx1950_init); +module_exit(rx1950_exit); + +/* Module information */ +MODULE_AUTHOR("Vasily Khoruzhick"); +MODULE_DESCRIPTION("ALSA SoC RX1950"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From ada69e3c1c0be591aa2e6282fb252c668ccb9a1c Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Mon, 30 Aug 2010 11:28:09 +0300 Subject: ARM: S3C24XX: I2S multi-component-related fixes Export s3c_device_pcm for all S3C24xx-devices, not only for S3C2440; Fix device name for s3c_device_iis; Signed-off-by: Vasily Khoruzhick Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- arch/arm/plat-s3c24xx/devs.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index 9f8ee5e38615..2f91057a0c02 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c @@ -247,7 +247,7 @@ static struct resource s3c_iis_resource[] = { static u64 s3c_device_iis_dmamask = 0xffffffffUL; struct platform_device s3c_device_iis = { - .name = "s3c2410-iis", + .name = "s3c24xx-iis", .id = -1, .num_resources = ARRAY_SIZE(s3c_iis_resource), .resource = s3c_iis_resource, @@ -259,6 +259,21 @@ struct platform_device s3c_device_iis = { EXPORT_SYMBOL(s3c_device_iis); +/* ASoC PCM DMA */ + +static u64 s3c_device_audio_dmamask = 0xffffffffUL; + +struct platform_device s3c_device_pcm = { + .name = "s3c24xx-pcm-audio", + .id = -1, + .dev = { + .dma_mask = &s3c_device_audio_dmamask, + .coherent_dma_mask = 0xffffffffUL + } +}; + +EXPORT_SYMBOL(s3c_device_pcm); + /* RTC */ static struct resource s3c_rtc_resource[] = { @@ -481,8 +496,6 @@ static struct resource s3c_ac97_resource[] = { }, }; -static u64 s3c_device_audio_dmamask = 0xffffffffUL; - struct platform_device s3c_device_ac97 = { .name = "s3c-ac97", .id = -1, @@ -496,19 +509,6 @@ struct platform_device s3c_device_ac97 = { EXPORT_SYMBOL(s3c_device_ac97); -/* ASoC PCM DMA */ - -struct platform_device s3c_device_pcm = { - .name = "s3c24xx-pcm-audio", - .id = -1, - .dev = { - .dma_mask = &s3c_device_audio_dmamask, - .coherent_dma_mask = 0xffffffffUL - } -}; - -EXPORT_SYMBOL(s3c_device_pcm); - /* ASoC I2S */ struct platform_device s3c2412_device_iis = { -- cgit v1.2.3-59-g8ed1b From 7522948b1b6105d58d250d3225f86aa0a5ba2bc5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Aug 2010 19:40:26 +0900 Subject: ASoC: fsi: modify compile error Signed-off-by: Kuninori Morimoto Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- include/sound/sh_fsi.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index 3fd6456d07d7..fa60cbda90a4 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h @@ -114,7 +114,4 @@ struct sh_fsi_platform_info { int (*set_rate)(int is_porta, int rate); /* for master mode */ }; -extern struct snd_soc_dai_driver fsi_soc_dai[2]; -extern struct snd_soc_platform_driver fsi_soc_platform; - #endif /* __SOUND_FSI_H */ -- cgit v1.2.3-59-g8ed1b From 2c280320f22153f7035a76ee0948f5577c5482b5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Aug 2010 20:47:19 +0900 Subject: ASoC: fsi-ak4642/fsi-da7210: modify dai link settings for card detect This patch modify dai link - platform_name: sh_fsi/sh_fsi2 are used for FSI driver - codec_name: ak4642/ak4643 are used for ak4642 driver This is quick hack. I should modify it more wisely in future Signed-off-by: Kuninori Morimoto Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/sh/fsi-ak4642.c | 7 ++++++- sound/soc/sh/fsi-da7210.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c index 9e107a9c4010..53836ca11d3b 100644 --- a/sound/soc/sh/fsi-ak4642.c +++ b/sound/soc/sh/fsi-ak4642.c @@ -31,8 +31,13 @@ static struct snd_soc_dai_link fsi_dai_link = { .stream_name = "AK4642", .cpu_dai_name = "fsia-dai", /* fsi A */ .codec_dai_name = "ak4642-hifi", - .platform_name = "fsi-pcm-audio", +#ifdef CONFIG_MACH_AP4EVB + .platform_name = "sh_fsi2.0", + .codec_name = "ak4642-codec.0-0013", +#else + .platform_name = "sh_fsi.0", .codec_name = "ak4642-codec.0-0012", +#endif .init = fsi_ak4642_dai_init, .ops = NULL, }; diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c index 4f9298f45215..b5270156c817 100644 --- a/sound/soc/sh/fsi-da7210.c +++ b/sound/soc/sh/fsi-da7210.c @@ -27,7 +27,7 @@ static struct snd_soc_dai_link fsi_da7210_dai = { .stream_name = "DA7210", .cpu_dai_name = "fsib-dai", /* FSI B */ .codec_dai_name = "da7210-hifi", - .platform_name = "fsi-pcm-audio", + .platform_name = "sh_fsi.0", .codec_name = "da7210-codec.0-001a", .init = fsi_da7210_init, }; -- cgit v1.2.3-59-g8ed1b From c88e7b93a80bd46899c4cb09a9b2d52bb04d79bd Mon Sep 17 00:00:00 2001 From: "Arnaud Patard (Rtp)" Date: Mon, 30 Aug 2010 16:00:05 +0200 Subject: ASoC: OpenRD Client : Fix naming breakage due to multicomponent support multicomponent support added/changed some device name but added some typos, breaking existing OpenRD Client support. Signed-off-by: Arnaud Patard Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- arch/arm/mach-kirkwood/common.c | 2 +- sound/soc/codecs/cs42l51.c | 2 +- sound/soc/kirkwood/kirkwood-openrd.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index 0f6ee32678ef..51ff23b72d3a 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -904,7 +904,7 @@ static struct platform_device kirkwood_i2s_device = { }; static struct platform_device kirkwood_pcm_device = { - .name = "kirkwood-pcm", + .name = "kirkwood-pcm-audio", .id = -1, }; diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 8a25743870c2..39fbcff20258 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -622,7 +622,7 @@ MODULE_DEVICE_TABLE(i2c, cs42l51_id); static struct i2c_driver cs42l51_i2c_driver = { .driver = { - .name = "cs42L51-codec", + .name = "cs42l51-codec", .owner = THIS_MODULE, }, .id_table = cs42l51_id, diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c index cc1a1e277edf..2cf76dfd0355 100644 --- a/sound/soc/kirkwood/kirkwood-openrd.c +++ b/sound/soc/kirkwood/kirkwood-openrd.c @@ -66,7 +66,7 @@ static struct snd_soc_dai_link openrd_client_dai[] = { .stream_name = "CS42L51 HiFi", .cpu_dai_name = "kirkwood-i2s", .platform_name = "kirkwood-pcm-audio", - .codec_dai_name = "cs42l51_hifi", + .codec_dai_name = "cs42l51-hifi", .codec_name = "cs42l51-codec.0-004a", .ops = &openrd_client_ops, }, -- cgit v1.2.3-59-g8ed1b From 3ba06c6fbd651ed3377e584026d1c112b492cc8b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Aug 2010 22:21:13 +0300 Subject: mac80211: Fix signal strength average initialization for CQM events The ave_beacon_signal value uses 1/16 dB unit and as such, must be initialized with the signal level of the first Beacon frame multiplied by 16. This fixes an issue where the initial CQM events are reported incorrectly with a burst of events while the running average approaches the correct value after the incorrect initialization. This could cause user space -based roaming decision process to get quite confused at the moment when we would like to go through authentication and DHCP. Cc: stable@kernel.org Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c8694478cde2..7915726d791e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1553,7 +1553,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ifmgd->last_beacon_signal = rx_status->signal; if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; - ifmgd->ave_beacon_signal = rx_status->signal; + ifmgd->ave_beacon_signal = rx_status->signal * 16; ifmgd->last_cqm_event_signal = 0; } else { ifmgd->ave_beacon_signal = -- cgit v1.2.3-59-g8ed1b From 391a200a89bf85bd38f117f34898c24299e3d53d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Aug 2010 22:22:00 +0300 Subject: mac80211: Do not generate CQM events based on first Beacon frames The signal strength value in a single RX frame is not that reliable, so it is better to delay start of CQM events until there is a real average signal strength from more than a single Beacon frame available. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 7 +++++++ net/mac80211/mlme.c | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9af50fbcd48b..16f7fb164c2d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -368,6 +368,13 @@ struct ieee80211_if_managed { */ int ave_beacon_signal; + /* + * Number of Beacon frames used in ave_beacon_signal. This can be used + * to avoid generating less reliable cqm events that would be based + * only on couple of received frames. + */ + unsigned int count_beacon_signal; + /* * Last Beacon frame signal strength average (ave_beacon_signal / 16) * that triggered a cqm event. 0 indicates that no event has been diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7915726d791e..0cb822cc12e9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -54,6 +54,12 @@ */ #define IEEE80211_SIGNAL_AVE_WEIGHT 3 +/* + * How many Beacon frames need to have been used in average signal strength + * before starting to indicate signal change events. + */ +#define IEEE80211_SIGNAL_AVE_MIN_COUNT 4 + #define TMR_RUNNING_TIMER 0 #define TMR_RUNNING_CHANSW 1 @@ -1555,13 +1561,16 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; ifmgd->ave_beacon_signal = rx_status->signal * 16; ifmgd->last_cqm_event_signal = 0; + ifmgd->count_beacon_signal = 1; } else { ifmgd->ave_beacon_signal = (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * ifmgd->ave_beacon_signal) / 16; + ifmgd->count_beacon_signal++; } if (bss_conf->cqm_rssi_thold && + ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { int sig = ifmgd->ave_beacon_signal / 16; int last_event = ifmgd->last_cqm_event_signal; -- cgit v1.2.3-59-g8ed1b From 9df86e2e702c6d5547aced7f241addd2d698bb11 Mon Sep 17 00:00:00 2001 From: Denis 'GNUtoo' Carikli Date: Fri, 27 Aug 2010 23:48:19 +0200 Subject: wl1251: Fix queue stopping/waking for TX path This patch was adapted from 06f7bc7db79fabe6b2ec16eff0f59e4acc21eb72 (from linus's linux-2.6 tree of kernel.org) here's the original message: The queue stopping/waking functionality was broken in a way that could cause huge latencies in TX transfers and even cause the TX to stall in the right circumstances. Correct these problems. Signed-off-by: Denis 'GNUtoo' Carikli Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251.h | 5 ++++- drivers/net/wireless/wl12xx/wl1251_main.c | 12 +++++------- drivers/net/wireless/wl12xx/wl1251_tx.c | 20 +++++++++++++++----- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 9bc4fea3315a..e113d4c1fb35 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h @@ -272,6 +272,8 @@ struct wl1251 { int irq; bool use_eeprom; + spinlock_t wl_lock; + enum wl1251_state state; struct mutex mutex; @@ -399,7 +401,8 @@ void wl1251_disable_interrupts(struct wl1251 *wl); #define WL1251_DEFAULT_POWER_LEVEL 20 -#define WL1251_TX_QUEUE_MAX_LENGTH 20 +#define WL1251_TX_QUEUE_LOW_WATERMARK 10 +#define WL1251_TX_QUEUE_HIGH_WATERMARK 25 #define WL1251_DEFAULT_BEACON_INT 100 #define WL1251_DEFAULT_DTIM_PERIOD 1 diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index f9d9ad620cc9..faf221ca3f41 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -375,6 +375,7 @@ out: static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct wl1251 *wl = hw->priv; + unsigned long flags; skb_queue_tail(&wl->tx_queue, skb); @@ -389,16 +390,13 @@ static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * The workqueue is slow to process the tx_queue and we need stop * the queue here, otherwise the queue will get too long. */ - if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) { + if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_HIGH_WATERMARK) { wl1251_debug(DEBUG_TX, "op_tx: tx_queue full, stop queues"); - ieee80211_stop_queues(wl->hw); - /* - * FIXME: this is racy, the variable is not properly - * protected. Maybe fix this by removing the stupid - * variable altogether and checking the real queue state? - */ + spin_lock_irqsave(&wl->wl_lock, flags); + ieee80211_stop_queues(wl->hw); wl->tx_queue_stopped = true; + spin_unlock_irqrestore(&wl->wl_lock, flags); } return NETDEV_TX_OK; diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index 6d618fb1fd95..388492a7f41f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c @@ -320,11 +320,6 @@ void wl1251_tx_work(struct work_struct *work) ret = wl1251_tx_frame(wl, skb); if (ret == -EBUSY) { - /* firmware buffer is full, stop queues */ - wl1251_debug(DEBUG_TX, "tx_work: fw buffer full, " - "stop queues"); - ieee80211_stop_queues(wl->hw); - wl->tx_queue_stopped = true; skb_queue_head(&wl->tx_queue, skb); goto out; } else if (ret < 0) { @@ -447,6 +442,7 @@ void wl1251_tx_complete(struct wl1251 *wl) { int i, result_index, num_complete = 0; struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr; + unsigned long flags; if (unlikely(wl->state != WL1251_STATE_ON)) return; @@ -475,6 +471,20 @@ void wl1251_tx_complete(struct wl1251 *wl) } } + if (wl->tx_queue_stopped + && + skb_queue_len(&wl->tx_queue) <= WL1251_TX_QUEUE_LOW_WATERMARK){ + + /* firmware buffer has space, restart queues */ + wl1251_debug(DEBUG_TX, "tx_complete: waking queues"); + spin_lock_irqsave(&wl->wl_lock, flags); + ieee80211_wake_queues(wl->hw); + wl->tx_queue_stopped = false; + spin_unlock_irqrestore(&wl->wl_lock, flags); + ieee80211_queue_work(wl->hw, &wl->tx_work); + + } + /* Every completed frame needs to be acknowledged */ if (num_complete) { /* -- cgit v1.2.3-59-g8ed1b From 3653910714a4a9b19aadb202c24f7b1ae61d3556 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 28 Aug 2010 17:41:06 +0200 Subject: net/wireless: Remove double test The same expression is tested twice and the result is the same each time. The sematic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @expression@ expression E; @@ ( * E || ... || E | * E && ... && E ) // Signed-off-by: Julia Lawall Signed-off-by: John W. Linville --- net/wireless/wext-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 0ef17bc42bac..40385936e286 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -611,7 +611,7 @@ struct iw_statistics *get_wireless_stats(struct net_device *dev) #endif #ifdef CONFIG_CFG80211_WEXT - if (dev->ieee80211_ptr && dev->ieee80211_ptr && + if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy && dev->ieee80211_ptr->wiphy->wext && dev->ieee80211_ptr->wiphy->wext->get_wireless_stats) -- cgit v1.2.3-59-g8ed1b From 56363ddeeed3afc5277ca227209773bc1042cc7b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 28 Aug 2010 18:21:21 +0200 Subject: ath9k: fix spurious MIC failure reports According to the hardware documentation, the MIC failure bit is only valid if the frame was decrypted using a valid TKIP key and is not a fragment. In some setups I've seen hardware-reported MIC failures on an AP that was configured for CCMP only, so it's clear that additional checks are necessary. Signed-off-by: Felix Fietkau Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath.h | 1 + drivers/net/wireless/ath/ath9k/common.c | 11 +++++++++++ drivers/net/wireless/ath/ath9k/mac.c | 3 ++- drivers/net/wireless/ath/ath9k/recv.c | 19 +++++++++++-------- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index d32f2828b098..a706202fa67c 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -119,6 +119,7 @@ struct ath_common { u32 keymax; DECLARE_BITMAP(keymap, ATH_KEYMAX); + DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX); u8 splitmic; struct ath_regulatory regulatory; diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 31cfe468e3fc..2dab64bb23a8 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -372,9 +372,13 @@ int ath9k_cmn_key_config(struct ath_common *common, set_bit(idx, common->keymap); if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { set_bit(idx + 64, common->keymap); + set_bit(idx, common->tkip_keymap); + set_bit(idx + 64, common->tkip_keymap); if (common->splitmic) { set_bit(idx + 32, common->keymap); set_bit(idx + 64 + 32, common->keymap); + set_bit(idx + 32, common->tkip_keymap); + set_bit(idx + 64 + 32, common->tkip_keymap); } } @@ -399,10 +403,17 @@ void ath9k_cmn_key_delete(struct ath_common *common, return; clear_bit(key->hw_key_idx + 64, common->keymap); + + clear_bit(key->hw_key_idx, common->tkip_keymap); + clear_bit(key->hw_key_idx + 64, common->tkip_keymap); + if (common->splitmic) { ath9k_hw_keyreset(ah, key->hw_key_idx + 32); clear_bit(key->hw_key_idx + 32, common->keymap); clear_bit(key->hw_key_idx + 64 + 32, common->keymap); + + clear_bit(key->hw_key_idx + 32, common->tkip_keymap); + clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap); } } EXPORT_SYMBOL(ath9k_cmn_key_delete); diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index e955bb9d98cb..0b7d1253f0c0 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -711,7 +711,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, rs->rs_phyerr = phyerr; } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) rs->rs_status |= ATH9K_RXERR_DECRYPT; - else if (ads.ds_rxstatus8 & AR_MichaelErr) + else if ((ads.ds_rxstatus8 & AR_MichaelErr) && + rs->rs_keyix != ATH9K_RXKEYIX_INVALID) rs->rs_status |= ATH9K_RXERR_MIC; } diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index a3fc987ebab0..534a91bcc1d9 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -870,15 +870,18 @@ static bool ath9k_rx_accept(struct ath_common *common, if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { *decrypt_error = true; } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { - if (ieee80211_is_ctl(fc)) - /* - * Sometimes, we get invalid - * MIC failures on valid control frames. - * Remove these mic errors. - */ - rx_stats->rs_status &= ~ATH9K_RXERR_MIC; - else + /* + * The MIC error bit is only valid if the frame + * is not a control frame or fragment, and it was + * decrypted using a valid TKIP key. + */ + if (!ieee80211_is_ctl(fc) && + !ieee80211_has_morefrags(fc) && + !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && + test_bit(rx_stats->rs_keyix, common->tkip_keymap)) rxs->flag |= RX_FLAG_MMIC_ERROR; + else + rx_stats->rs_status &= ~ATH9K_RXERR_MIC; } /* * Reject error frames with the exception of -- cgit v1.2.3-59-g8ed1b From a908a743822d2eed2d8394bb607bb9db5934dcfc Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 30 Aug 2010 21:12:24 +0200 Subject: rt2x00: Rename txentry_desc.queue -> txentry_desc.qid Variables containing queue ids are called qid everywhere else, hence rename the queue field in txentry_desc to qid as well. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.h | 4 ++-- drivers/net/wireless/rt2x00/rt61pci.c | 6 +++--- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index ecbd07a78edb..25c44cfd7452 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -469,7 +469,7 @@ void rt2800_write_tx_data(struct queue_entry *entry, txdesc->key_idx : 0xff); rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, txdesc->length); - rt2x00_set_field32(&word, TXWI_W1_PACKETID, txdesc->queue + 1); + rt2x00_set_field32(&word, TXWI_W1_PACKETID, txdesc->qid + 1); rt2x00_desc_write(txwi, 1, word); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 7fb9b6179af1..ecf57635ae51 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -312,7 +312,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, /* * Initialize information from queue */ - txdesc->queue = entry->queue->qid; + txdesc->qid = entry->queue->qid; txdesc->cw_min = entry->queue->cw_min; txdesc->cw_max = entry->queue->cw_max; txdesc->aifs = entry->queue->aifs; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index c451a50f7a01..0e38a911195d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -296,7 +296,7 @@ enum txentry_desc_flags { * Summary of information for the frame descriptor before sending a TX frame. * * @flags: Descriptor flags (See &enum queue_entry_flags). - * @queue: Queue identification (See &enum data_queue_qid). + * @qid: Queue identification (See &enum data_queue_qid). * @length: Length of the entire frame. * @header_length: Length of 802.11 header. * @length_high: PLCP length high word. @@ -322,7 +322,7 @@ enum txentry_desc_flags { struct txentry_desc { unsigned long flags; - enum data_queue_qid queue; + enum data_queue_qid qid; u16 length; u16 header_length; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 8f017ad8c3db..18829b2eccc3 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1778,7 +1778,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, * Start writing the descriptor words. */ rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid); rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); @@ -1809,7 +1809,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); - if (txdesc->queue != QID_BEACON) { + if (txdesc->qid != QID_BEACON) { rt2x00_desc_read(txd, 6, &word); rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, skbdesc->skb_dma); @@ -1856,7 +1856,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, */ skbdesc->desc = txd; skbdesc->desc_len = - (txdesc->queue == QID_BEACON) ? TXINFO_SIZE : TXD_DESC_SIZE; + (txdesc->qid == QID_BEACON) ? TXINFO_SIZE : TXD_DESC_SIZE; } /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ee2c52fd0d73..ac8f6d0b8f49 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1463,7 +1463,7 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry, rt2x00_desc_write(txd, 0, word); rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid); rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); -- cgit v1.2.3-59-g8ed1b From 2035c0cf8f637e88cdd338c15570a7ad42afc552 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 30 Aug 2010 21:12:47 +0200 Subject: rt2x00: Update rt2800 comments regarding AMPDU and PACKET_ID in TXWI Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 5c006a795346..70a5cb86405b 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1953,6 +1953,8 @@ struct mac_iveiv_entry { * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs * BW: Channel bandwidth 20MHz or 40 MHz * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED + * AMPDU: 1: this frame is eligible for AMPDU aggregation, the hw will + * aggregate consecutive frames with the same RA and QoS TID. */ #define TXWI_W0_FRAG FIELD32(0x00000001) #define TXWI_W0_MIMO_PS FIELD32(0x00000002) @@ -1976,7 +1978,9 @@ struct mac_iveiv_entry { * WIRELESS_CLI_ID: Client ID for WCID table access * MPDU_TOTAL_BYTE_COUNT: Length of 802.11 frame * PACKETID: Will be latched into the TX_STA_FIFO register once the according - * frame was processed. 0: Don't report tx status for this frame. + * frame was processed. If multiple frames are aggregated together + * (AMPDU==1) the reported tx status will always contain the packet + * id of the first frame. 0: Don't report tx status for this frame. */ #define TXWI_W1_ACK FIELD32(0x00000001) #define TXWI_W1_NSEQ FIELD32(0x00000002) -- cgit v1.2.3-59-g8ed1b From 5ffddc498c700bb45ea55efc37746cb28d601766 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 30 Aug 2010 21:13:08 +0200 Subject: rt2x00: Add rt2800_wait_csr_ready Similar to rt2800_wait_wpdma_ready() we can add a function to waiting until the CSR is ready. This centralizes some additional code into rt2800lib. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 28 ++++++++++++++++++---------- drivers/net/wireless/rt2x00/rt2800lib.h | 1 + drivers/net/wireless/rt2x00/rt2800usb.c | 12 +----------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 25c44cfd7452..7c68bf35951f 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -255,6 +255,23 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2800_mcu_request); +int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i = 0; + u32 reg; + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2800_register_read(rt2x00dev, MAC_CSR0, ®); + if (reg && reg != ~0) + return 0; + msleep(1); + } + + ERROR(rt2x00dev, "Unstable hardware.\n"); + return -EBUSY; +} +EXPORT_SYMBOL_GPL(rt2800_wait_csr_ready); + int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) { unsigned int i; @@ -370,17 +387,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, /* * Wait for stable hardware. */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, MAC_CSR0, ®); - if (reg && reg != ~0) - break; - msleep(1); - } - - if (i == REGISTER_BUSY_COUNT) { - ERROR(rt2x00dev, "Unstable hardware.\n"); + if (rt2800_wait_csr_ready(rt2x00dev)) return -EBUSY; - } if (rt2x00_is_pci(rt2x00dev)) rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index deb10b14157b..986229c06c19 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -140,6 +140,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 command, const u8 token, const u8 arg0, const u8 arg1); +int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev); int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev); int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 82ae58e0c5d7..b1a8e943750b 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -122,22 +122,12 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; - int i; /* * Wait until BBP and RF are ready. */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, MAC_CSR0, ®); - if (reg && reg != ~0) - break; - msleep(1); - } - - if (i == REGISTER_BUSY_COUNT) { - ERROR(rt2x00dev, "Unstable hardware.\n"); + if (rt2800_wait_csr_ready(rt2x00dev)) return -EBUSY; - } rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); -- cgit v1.2.3-59-g8ed1b From 3613884d96b186f58a77af05122f84167604aad9 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 30 Aug 2010 21:13:30 +0200 Subject: rt2x00: Validate TX status results with current data entry Instead of printing a warning when the PID, ACK, or WCID of an entry don't match the TX status report, we should skip the entry to search for the entry which actually does match the TX status data. This reduces the number of watchdog errors on the TX queues for rt2800usb, and seems to improve the reliability of the TX flow a bit. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 73 ++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 7c68bf35951f..1a8170068b1c 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -581,6 +581,49 @@ void rt2800_process_rxwi(struct queue_entry *entry, } EXPORT_SYMBOL_GPL(rt2800_process_rxwi); +static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg) +{ + __le32 *txwi; + u32 word; + int wcid, ack, pid; + int tx_wcid, tx_ack, tx_pid; + + wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); + ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); + pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); + + /* + * This frames has returned with an IO error, + * so the status report is not intended for this + * frame. + */ + if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) { + rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); + return false; + } + + /* + * Validate if this TX status report is intended for + * this entry by comparing the WCID/ACK/PID fields. + */ + txwi = rt2800_drv_get_txwi(entry); + + rt2x00_desc_read(txwi, 1, &word); + tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); + tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); + tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); + + if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) { + WARNING(entry->queue->rt2x00dev, + "TX status report missed for queue %d entry %d\n", + entry->queue->qid, entry->entry_idx); + rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); + return false; + } + + return true; +} + void rt2800_txdone(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; @@ -589,8 +632,8 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) struct txdone_entry_desc txdesc; u32 word; u32 reg; - int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; u16 mcs, real_mcs; + u8 pid; int i; /* @@ -607,18 +650,15 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) break; - wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); - ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); - pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); - /* * Skip this entry when it contains an invalid * queue identication number. */ - if (pid <= 0 || pid > QID_RX) + pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE) - 1; + if (pid >= QID_RX) continue; - queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); + queue = rt2x00queue_get_queue(rt2x00dev, pid); if (unlikely(!queue)) continue; @@ -627,35 +667,22 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) * order. We first check that the queue is not empty. */ entry = NULL; + txwi = NULL; while (!rt2x00queue_empty(queue)) { entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - if (!test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) + if (rt2800_txdone_entry_check(entry, reg)) break; - - rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); } if (!entry || rt2x00queue_empty(queue)) break; - /* - * Check if we got a match by looking at WCID/ACK/PID - * fields - */ - txwi = rt2800_drv_get_txwi(entry); - - rt2x00_desc_read(txwi, 1, &word); - tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); - tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); - tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); - - if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) - WARNING(rt2x00dev, "invalid TX_STA_FIFO content"); /* * Obtain the status about this packet. */ txdesc.flags = 0; + txwi = rt2800_drv_get_txwi(entry); rt2x00_desc_read(txwi, 0, &word); mcs = rt2x00_get_field32(word, TXWI_W0_MCS); real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); -- cgit v1.2.3-59-g8ed1b From b9eca24209a59ef0a8c3cbbbb94b8c76d4b3aae3 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 30 Aug 2010 21:13:54 +0200 Subject: rt2x00: Wakeup hardware before loading firmware According to the legacy drivers the AUTOWAKEUP_CFG register must be reset to 0 before loading the firmware. Instead of during rt2800{pci,usb}_write_firmware it must actually be done in rt2800_load_firmware() before resetting the WPDMA_GLO_CFG and PWR_PIN_CFG registers. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++++ drivers/net/wireless/rt2x00/rt2800pci.c | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 1a8170068b1c..a5455f46cec1 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -384,6 +384,12 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, unsigned int i; u32 reg; + /* + * If driver doesn't wake up firmware here, + * rt2800_load_firmware will hang forever when interface is up again. + */ + rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000); + /* * Wait for stable hardware. */ diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 4d93204b221f..2bcb1507e3ac 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -196,8 +196,6 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, { u32 reg; - rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000); - /* * enable Host program ram write selection */ -- cgit v1.2.3-59-g8ed1b From c600c826a6f4e35512955a5e9a22b0baa741b455 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 30 Aug 2010 21:14:15 +0200 Subject: rt2x00: Don't set unicast/BSSID masks when clearning MAC or BSSID When configuring the MAC_ADDR or MAC_BSSID with an empty address, the UNICAST_TO_ME_MASK and BSS_ID_MASK must also be reset to prevent invalid interpretation of the addresses. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index a5455f46cec1..f90e932b3cb4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1135,19 +1135,23 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, } if (flags & CONFIG_UPDATE_MAC) { - reg = le32_to_cpu(conf->mac[1]); - rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); - conf->mac[1] = cpu_to_le32(reg); + if (!is_zero_ether_addr((const u8 *)conf->mac)) { + reg = le32_to_cpu(conf->mac[1]); + rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); + conf->mac[1] = cpu_to_le32(reg); + } rt2800_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, conf->mac, sizeof(conf->mac)); } if (flags & CONFIG_UPDATE_BSSID) { - reg = le32_to_cpu(conf->bssid[1]); - rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 3); - rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 7); - conf->bssid[1] = cpu_to_le32(reg); + if (!is_zero_ether_addr((const u8 *)conf->bssid)) { + reg = le32_to_cpu(conf->bssid[1]); + rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 3); + rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 7); + conf->bssid[1] = cpu_to_le32(reg); + } rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, conf->bssid, sizeof(conf->bssid)); -- cgit v1.2.3-59-g8ed1b From e0540879db337b18ef7c580234038ff62c8cd381 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 30 Aug 2010 21:14:38 +0200 Subject: rt2x00: Set PWR_PIN_CFG during initialization Add PWR_PIN_CFG initialization for rt2800usb at the same point as rt2800pci. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index b1a8e943750b..d275549a1fb9 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -132,6 +132,8 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); + rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); -- cgit v1.2.3-59-g8ed1b From 0e3afe5b20c4ccdeff5178c62b557a917945a828 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 30 Aug 2010 21:14:56 +0200 Subject: rt2x00: Correctly kill beacon queue USB devices upload their beacon and then automatically send it out every beacon interval. However when killing a TX queue we only kill the URB and not the actual transmission of the beacon. This will reset the Beacon register to prevent any beacons from being transmitted. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 10 +++++++++- drivers/net/wireless/rt2x00/rt2800usb.c | 10 +++++++++- drivers/net/wireless/rt2x00/rt73usb.c | 10 +++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 71d8d821c4e1..a161e9e33b73 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1196,6 +1196,14 @@ static int rt2500usb_get_tx_data_len(struct queue_entry *entry) return length; } +static void rt2500usb_kill_tx_queue(struct data_queue *queue) +{ + if (queue->qid == QID_BEACON) + rt2500usb_register_write(queue->rt2x00dev, TXRX_CSR19, 0); + + rt2x00usb_kill_tx_queue(queue); +} + /* * RX control handlers */ @@ -1794,7 +1802,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .write_beacon = rt2500usb_write_beacon, .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2x00usb_kick_tx_queue, - .kill_tx_queue = rt2x00usb_kill_tx_queue, + .kill_tx_queue = rt2500usb_kill_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, .config_shared_key = rt2500usb_config_key, .config_pairwise_key = rt2500usb_config_key, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index d275549a1fb9..3dff56ec195a 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -335,6 +335,14 @@ static void rt2800usb_work_txdone(struct work_struct *work) } } +static void rt2800usb_kill_tx_queue(struct data_queue *queue) +{ + if (queue->qid == QID_BEACON) + rt2x00usb_register_write(queue->rt2x00dev, BCN_TIME_CFG, 0); + + rt2x00usb_kill_tx_queue(queue); +} + /* * RX control handlers */ @@ -533,7 +541,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .write_beacon = rt2800_write_beacon, .get_tx_data_len = rt2800usb_get_tx_data_len, .kick_tx_queue = rt2x00usb_kick_tx_queue, - .kill_tx_queue = rt2x00usb_kill_tx_queue, + .kill_tx_queue = rt2800usb_kill_tx_queue, .fill_rxdone = rt2800usb_fill_rxdone, .config_shared_key = rt2800_config_shared_key, .config_pairwise_key = rt2800_config_pairwise_key, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ac8f6d0b8f49..df0ef3f70f1e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1573,6 +1573,14 @@ static int rt73usb_get_tx_data_len(struct queue_entry *entry) return length; } +static void rt73usb_kill_tx_queue(struct data_queue *queue) +{ + if (queue->qid == QID_BEACON) + rt2x00usb_register_write(queue->rt2x00dev, TXRX_CSR9, 0); + + rt2x00usb_kill_tx_queue(queue); +} + /* * RX control handlers */ @@ -2262,7 +2270,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .write_beacon = rt73usb_write_beacon, .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt2x00usb_kick_tx_queue, - .kill_tx_queue = rt2x00usb_kill_tx_queue, + .kill_tx_queue = rt73usb_kill_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, .config_shared_key = rt73usb_config_shared_key, .config_pairwise_key = rt73usb_config_pairwise_key, -- cgit v1.2.3-59-g8ed1b From 652a9dd2a0c07251e328519cc23f1316ab13ed51 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 30 Aug 2010 21:15:19 +0200 Subject: rt2x00: Split watchdog check into a DMA and STATUS timeout The watchdog for rt2800usb triggers frequently causing all URB's to be canceled often enough to interrupt the normal TX flow. More research indicated that not the URB upload to the USB host were hanging, but instead the TX status reports. To correctly detect what is going on, we introduce Q_INDEX_DMA_DONE which is an index counter between Q_INDEX_DONE and Q_INDEX and indicates if the frame has been transfered to the device. This also requires the rt2x00queue timeout functions to be updated to differentiate between a DMA timeout (time between Q_INDEX and Q_INDEX_DMA_DONE timeout) and a STATUS timeout (time between Q_INDEX_DMA_DONE and Q_INDEX_DONE timeout) All Q_INDEX_DMA_DONE code was taken from the RFC from Helmut Schaa for the implementation for watchdog for rt2800pci. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 1 + drivers/net/wireless/rt2x00/rt2x00debug.c | 5 +++-- drivers/net/wireless/rt2x00/rt2x00dev.c | 6 ++++++ drivers/net/wireless/rt2x00/rt2x00queue.c | 13 ++++++++----- drivers/net/wireless/rt2x00/rt2x00queue.h | 21 +++++++++++++++++---- drivers/net/wireless/rt2x00/rt2x00usb.c | 27 ++++++++++++++++++++++++--- 6 files changed, 59 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 762f6b4e7afc..0ae942cb66df 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1070,6 +1070,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, */ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); +void rt2x00lib_dmadone(struct queue_entry *entry); void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc); void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status); diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index daf7f950a28f..54dc44bb415c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -338,14 +338,15 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file, return -ENOMEM; temp = data + - sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\n"); + sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n"); queue_for_each(intf->rt2x00dev, queue) { spin_lock_irqsave(&queue->lock, irqflags); - temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, + temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, queue->count, queue->limit, queue->length, queue->index[Q_INDEX], + queue->index[Q_INDEX_DMA_DONE], queue->index[Q_INDEX_DONE]); spin_unlock_irqrestore(&queue->lock, irqflags); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 580595ba5683..053fdd3bd720 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -251,6 +251,12 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); +void rt2x00lib_dmadone(struct queue_entry *entry) +{ + rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE); +} +EXPORT_SYMBOL_GPL(rt2x00lib_dmadone); + void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc) { diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index ecf57635ae51..6d41599a090c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -731,13 +731,13 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) if (queue->index[index] >= queue->limit) queue->index[index] = 0; + queue->last_action[index] = jiffies; + if (index == Q_INDEX) { queue->length++; - queue->last_index = jiffies; } else if (index == Q_INDEX_DONE) { queue->length--; queue->count++; - queue->last_index_done = jiffies; } spin_unlock_irqrestore(&queue->lock, irqflags); @@ -746,14 +746,17 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) static void rt2x00queue_reset(struct data_queue *queue) { unsigned long irqflags; + unsigned int i; spin_lock_irqsave(&queue->lock, irqflags); queue->count = 0; queue->length = 0; - queue->last_index = jiffies; - queue->last_index_done = jiffies; - memset(queue->index, 0, sizeof(queue->index)); + + for (i = 0; i < Q_INDEX_MAX; i++) { + queue->index[i] = 0; + queue->last_action[i] = jiffies; + } spin_unlock_irqrestore(&queue->lock, irqflags); } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 0e38a911195d..d81d85f34866 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -401,6 +401,8 @@ struct queue_entry { * * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is * owned by the hardware then the queue is considered to be full. + * @Q_INDEX_DMA_DONE: Index pointer for the next entry which will have been + * transfered to the hardware. * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by * the hardware and for which we need to run the txdone handler. If this * entry is not owned by the hardware the queue is considered to be empty. @@ -409,6 +411,7 @@ struct queue_entry { */ enum queue_index { Q_INDEX, + Q_INDEX_DMA_DONE, Q_INDEX_DONE, Q_INDEX_MAX, }; @@ -445,13 +448,12 @@ struct data_queue { enum data_queue_qid qid; spinlock_t lock; - unsigned long last_index; - unsigned long last_index_done; unsigned int count; unsigned short limit; unsigned short threshold; unsigned short length; unsigned short index[Q_INDEX_MAX]; + unsigned long last_action[Q_INDEX_MAX]; unsigned short txop; unsigned short aifs; @@ -616,12 +618,23 @@ static inline int rt2x00queue_threshold(struct data_queue *queue) } /** - * rt2x00queue_timeout - Check if a timeout occured for this queue + * rt2x00queue_timeout - Check if a timeout occured for STATUS reorts * @queue: Queue to check. */ static inline int rt2x00queue_timeout(struct data_queue *queue) { - return time_after(queue->last_index, queue->last_index_done + (HZ / 10)); + return time_after(queue->last_action[Q_INDEX_DMA_DONE], + queue->last_action[Q_INDEX_DONE] + (HZ / 10)); +} + +/** + * rt2x00queue_timeout - Check if a timeout occured for DMA transfers + * @queue: Queue to check. + */ +static inline int rt2x00queue_dma_timeout(struct data_queue *queue) +{ + return time_after(queue->last_action[Q_INDEX], + queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10)); } /** diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 6cc7aa418d87..aec6440d364a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -212,6 +212,11 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; + /* + * Report the frame as DMA done + */ + rt2x00lib_dmadone(entry); + /* * Check if the frame was correctly uploaded */ @@ -283,13 +288,14 @@ void rt2x00usb_kill_tx_queue(struct data_queue *queue) } EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); -static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) +static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) { struct queue_entry *entry; struct queue_entry_priv_usb *entry_priv; unsigned short threshold = queue->threshold; - WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid); + WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," + " invoke forced forced reset", queue->qid); /* * Temporarily disable the TX queue, this will force mac80211 @@ -331,13 +337,23 @@ static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid); } +static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) +{ + WARNING(queue->rt2x00dev, "TX queue %d status timed out," + " invoke forced tx handler", queue->qid); + + ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work); +} + void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; tx_queue_for_each(rt2x00dev, queue) { + if (rt2x00queue_dma_timeout(queue)) + rt2x00usb_watchdog_tx_dma(queue); if (rt2x00queue_timeout(queue)) - rt2x00usb_watchdog_reset_tx(queue); + rt2x00usb_watchdog_tx_status(queue); } } EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); @@ -382,6 +398,11 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; + /* + * Report the frame as DMA done + */ + rt2x00lib_dmadone(entry); + /* * Check if the received data is simply too small * to be actually valid, or if the urb is signaling -- cgit v1.2.3-59-g8ed1b From cd35a3912188d006f251fff1028d84e1d1649ca2 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 30 Aug 2010 21:15:51 +0200 Subject: rt2x00: Cleanup rt2x00usb_watchdog_reset_tx rt2x00usb_watchdog_reset_tx performs the same task as rt2x00usb_kill_tx_queue, with the only difference is that it waits for all entries to be returned to the driver and for all frames the status has been reported to mac80211. We can easily split this task by calling rt2x00usb_kill_tx_queue, sleep for a short period and invoke the TX status reporting function. By adding the sleep() to the kill_entry we make sure that even during shutdown we guarentee the entry has been killed when the function returns. To make this work correctly the interrupt handlers have to be updated to prevent checking for the RADIO_ENABLED flag too early which prevents the ownership of the entry to be reset. Additionally a check for the DEVICE_PRESENT flag is not required but is nice to prevent race conditions when the device was unplugged. Additionally rather then calling rt2x00usb_work_txdone() for status reporting we let the driver perform the TX status reporting first. If this is not sufficient then rt2x00usb_work_txdone() will still be used to cleanup the mess. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 66 ++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index aec6440d364a..4c5ae3d45625 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -208,8 +208,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) struct queue_entry *entry = (struct queue_entry *)urb->context; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || - !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + if (!__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; /* @@ -227,7 +226,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) * Schedule the delayed work for reading the TX status * from the device. */ - ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && + test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); } static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) @@ -279,6 +280,14 @@ static void rt2x00usb_kill_tx_entry(struct queue_entry *entry) if ((entry->queue->qid == QID_BEACON) && (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) usb_kill_urb(bcn_priv->guardian_urb); + + /* + * We need a short delay here to wait for + * the URB to be canceled + */ + do { + udelay(100); + } while (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)); } void rt2x00usb_kill_tx_queue(struct data_queue *queue) @@ -290,8 +299,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) { - struct queue_entry *entry; - struct queue_entry_priv_usb *entry_priv; + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; unsigned short threshold = queue->threshold; WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," @@ -305,28 +313,33 @@ static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) * queue from being enabled during the txdone handler. */ queue->threshold = queue->limit; - ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid); + ieee80211_stop_queue(rt2x00dev->hw, queue->qid); /* - * Reset all currently uploaded TX frames. + * Kill all entries in the queue, afterwards we need to + * wait a bit for all URBs to be cancelled. */ - while (!rt2x00queue_empty(queue)) { - entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - entry_priv = entry->priv_data; - usb_kill_urb(entry_priv->urb); + rt2x00usb_kill_tx_queue(queue); - /* - * We need a short delay here to wait for - * the URB to be canceled - */ - do { - udelay(100); - } while (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)); + /* + * In case that a driver has overriden the txdone_work + * function, we invoke the TX done through there. + */ + rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work); - /* - * Invoke the TX done handler - */ - rt2x00usb_work_txdone_entry(entry); + /* + * Security measure: if the driver did override the + * txdone_work function, and the hardware did arrive + * in a state which causes it to malfunction, it is + * possible that the driver couldn't handle the txdone + * event correctly. So after giving the driver the + * chance to cleanup, we now force a cleanup of any + * leftovers. + */ + if (!rt2x00queue_empty(queue)) { + WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," + " status handling failed, invoke hard reset", queue->qid); + rt2x00usb_work_txdone(&rt2x00dev->txdone_work); } /* @@ -334,7 +347,7 @@ static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) * queue again. */ queue->threshold = threshold; - ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid); + ieee80211_wake_queue(rt2x00dev->hw, queue->qid); } static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) @@ -394,8 +407,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) struct queue_entry *entry = (struct queue_entry *)urb->context; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || - !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + if (!__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; /* @@ -415,7 +427,9 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) * Schedule the delayed work for reading the RX status * from the device. */ - ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && + test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); } /* -- cgit v1.2.3-59-g8ed1b From 18145c69349f2ab60c470798f83b3a2639e2a8d9 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 30 Aug 2010 15:12:02 -0400 Subject: mac80211: cancel scan in ieee80211_restart_hw if software scan pending This function exists to clean-up after a hardware error or something similar. The restart is accomplished using the same infrastructure used to resume after a suspend. The suspend path cancels running scans, so it seems appropriate to do that here as well for software-based scans. If a hardware-based scan is pending, issue a warning message since this indicates that the drivers has failed to clean-up after itself. Signed-off-by: John W. Linville --- net/mac80211/main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 93194f61adb0..a06b6ee63c07 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -305,7 +305,13 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) trace_api_restart_hw(local); - /* use this reason, __ieee80211_resume will unblock it */ + WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), + "%s called with hardware scan in progress\n", __func__); + + if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning))) + ieee80211_scan_cancel(local); + + /* use this reason, ieee80211_reconfig will unblock it */ ieee80211_stop_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); -- cgit v1.2.3-59-g8ed1b From 1a98214feef2221cd7c24b17cd688a5a9d85b2ea Mon Sep 17 00:00:00 2001 From: Rémi Denis-Courmont Date: Mon, 30 Aug 2010 12:57:03 +0000 Subject: Phonet: restore flow control credits when sending fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/phonet/pep.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/phonet/pep.c b/net/phonet/pep.c index b2a3ae6cad78..5034f0f62bdb 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -834,6 +834,7 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb) { struct pep_sock *pn = pep_sk(sk); struct pnpipehdr *ph; + int err; if (pn_flow_safe(pn->tx_fc) && !atomic_add_unless(&pn->tx_credits, -1, 0)) { @@ -852,7 +853,10 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb) ph->message_id = PNS_PIPE_DATA; ph->pipe_handle = pn->pipe_handle; - return pn_skb_send(sk, skb, &pipe_srv); + err = pn_skb_send(sk, skb, &pipe_srv); + if (err && pn_flow_safe(pn->tx_fc)) + atomic_inc(&pn->tx_credits); + return err; } static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, -- cgit v1.2.3-59-g8ed1b From 02ac3268a581639af241c254579160909373e12c Mon Sep 17 00:00:00 2001 From: Rémi Denis-Courmont Date: Mon, 30 Aug 2010 12:57:04 +0000 Subject: Phonet: correct sendmsg() error code from sock_alloc_send_skb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/phonet/pep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/phonet/pep.c b/net/phonet/pep.c index 5034f0f62bdb..04e34196c9de 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -876,7 +876,7 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len, flags & MSG_DONTWAIT, &err); if (!skb) - return -ENOBUFS; + return err; skb_reserve(skb, MAX_PHONET_HEADER + 3); err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); -- cgit v1.2.3-59-g8ed1b From 01b38606bded44bf8b7ca42e8fe5f2cad5d28121 Mon Sep 17 00:00:00 2001 From: Rémi Denis-Courmont Date: Mon, 30 Aug 2010 12:57:05 +0000 Subject: Phonet: do not set POLLOUT in case of send buffer overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/phonet/socket.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 6e9848bf0370..7c91f739f138 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -281,7 +281,9 @@ static unsigned int pn_socket_poll(struct file *file, struct socket *sock, if (!mask && sk->sk_state == TCP_CLOSE_WAIT) return POLLHUP; - if (sk->sk_state == TCP_ESTABLISHED && atomic_read(&pn->tx_credits)) + if (sk->sk_state == TCP_ESTABLISHED && + atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf && + atomic_read(&pn->tx_credits)) mask |= POLLOUT | POLLWRNORM | POLLWRBAND; return mask; -- cgit v1.2.3-59-g8ed1b From 72ed62f7c9f0abe11231d073195a722ee43d6ec1 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 31 Aug 2010 04:58:18 +0000 Subject: vlan: Use vlan_dev_real_dev in vlan_hwaccel_do_receive [patch net-next-2.6] vlan: Use vlan_dev_real_dev in vlan_hwaccel_do_receive Use helper as in other places. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/8021q/vlan_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 3438c01bbacf..889f4ac4459a 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -40,7 +40,7 @@ void vlan_hwaccel_do_receive(struct sk_buff *skb) struct net_device *dev = skb->dev; struct vlan_rx_stats *rx_stats; - skb->dev = vlan_dev_info(dev)->real_dev; + skb->dev = vlan_dev_real_dev(dev); netif_nit_deliver(skb); skb->dev = dev; -- cgit v1.2.3-59-g8ed1b From ba4fd9d8282f7f856f2287fe8be784d1dfdda28b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 31 Aug 2010 01:57:35 +0000 Subject: pktgen: remove non used variable remove non used variable "queue" in pg_cleanup Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/pktgen.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 10a1ea72010d..386c2283f14e 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3907,8 +3907,6 @@ static void __exit pg_cleanup(void) { struct pktgen_thread *t; struct list_head *q, *n; - wait_queue_head_t queue; - init_waitqueue_head(&queue); /* Stop all interfaces & threads */ -- cgit v1.2.3-59-g8ed1b From 4dc89133f49b8cfd77ba7e83f5960aed63aaa99e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 31 Aug 2010 07:40:16 +0000 Subject: net: add a comment on netdev->last_rx As some driver authors seem to reintroduce dev->last_rx use, add a comment to strongly discourage this. Since commit 6cf3f41e6c0 (bonding, net: Move last_rx update into bonding recv logic), network drivers dont need to update last_rx themselves, unless they use this field to implement a timeout. Not updating last_rx helps not dirtying a cache line, improving performance in SMP. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0cf9448a32c4..c82220a9f3d5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -953,7 +953,14 @@ struct net_device { /* * Cache line mostly used on receive path (including eth_type_trans()) */ - unsigned long last_rx; /* Time of last Rx */ + unsigned long last_rx; /* Time of last Rx + * This should not be set in + * drivers, unless really needed, + * because network stack (bonding) + * use it if/when necessary, to + * avoid dirtying this cache line. + */ + /* Interface address info used in eth_type_trans() */ unsigned char *dev_addr; /* hw address, (before bcast because most packets are -- cgit v1.2.3-59-g8ed1b From 1639ab6f7831f056286c64d98e8e5eb04e3bacac Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 31 Aug 2010 10:23:47 +0000 Subject: gro: unexport tcp4_gro_receive and tcp4_gro_complete tcp4_gro_receive() and tcp4_gro_complete() dont need to be exported. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 020766292bb0..a0232f3a358b 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2571,7 +2571,6 @@ struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) return tcp_gro_receive(head, skb); } -EXPORT_SYMBOL(tcp4_gro_receive); int tcp4_gro_complete(struct sk_buff *skb) { @@ -2584,7 +2583,6 @@ int tcp4_gro_complete(struct sk_buff *skb) return tcp_gro_complete(skb); } -EXPORT_SYMBOL(tcp4_gro_complete); struct proto tcp_prot = { .name = "TCP", -- cgit v1.2.3-59-g8ed1b From a17f79553f052f04d47689a842118f775f81b7e3 Mon Sep 17 00:00:00 2001 From: Abraham Arce Date: Tue, 31 Aug 2010 17:05:27 -0700 Subject: Input: add support for OMAP4 keyboard controller OMAP4 keyboard controller includes: - built-in scanning algorithm - debouncing feature Driver implementation is based on matrix_keypad.c Signed-off-by: Syed Rafiuddin Signed-off-by: Abraham Arce Signed-off-by: Dmitry Torokhov --- arch/arm/plat-omap/include/plat/omap4-keypad.h | 16 ++ drivers/input/keyboard/Kconfig | 9 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/omap4-keypad.c | 287 +++++++++++++++++++++++++ 4 files changed, 313 insertions(+) create mode 100644 arch/arm/plat-omap/include/plat/omap4-keypad.h create mode 100644 drivers/input/keyboard/omap4-keypad.c diff --git a/arch/arm/plat-omap/include/plat/omap4-keypad.h b/arch/arm/plat-omap/include/plat/omap4-keypad.h new file mode 100644 index 000000000000..522a8ab5c5ff --- /dev/null +++ b/arch/arm/plat-omap/include/plat/omap4-keypad.h @@ -0,0 +1,16 @@ +#ifndef ARCH_ARM_PLAT_OMAP4_KEYPAD_H +#define ARCH_ARM_PLAT_OMAP4_KEYPAD_H + +#include + +struct omap4_keypad_platform_data { + const struct matrix_keymap_data *keymap_data; + + u8 rows; + u8 cols; + + u16 irq; + void __iomem *base; +}; + +#endif diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9cc488d21490..4f300488e1f3 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -424,6 +424,15 @@ config KEYBOARD_OMAP To compile this driver as a module, choose M here: the module will be called omap-keypad. +config KEYBOARD_OMAP4 + tristate "TI OMAP4 keypad support" + depends on ARCH_OMAP4 + help + Say Y here if you want to use the OMAP4 keypad. + + To compile this driver as a module, choose M here: the + module will be called omap4-keypad. + config KEYBOARD_TWL4030 tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" depends on TWL4030_CORE diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 504b591be0cd..8ac01fb642c1 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o +obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c new file mode 100644 index 000000000000..975f8bbcc69b --- /dev/null +++ b/drivers/input/keyboard/omap4-keypad.c @@ -0,0 +1,287 @@ +/* + * OMAP4 Keypad Driver + * + * Copyright (C) 2010 Texas Instruments + * + * Author: Abraham Arce + * Initial Code: Syed Rafiuddin + * + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* OMAP4 registers */ +#define OMAP4_KBD_REVISION 0x00 +#define OMAP4_KBD_SYSCONFIG 0x10 +#define OMAP4_KBD_SYSSTATUS 0x14 +#define OMAP4_KBD_IRQSTATUS 0x18 +#define OMAP4_KBD_IRQENABLE 0x1C +#define OMAP4_KBD_WAKEUPENABLE 0x20 +#define OMAP4_KBD_PENDING 0x24 +#define OMAP4_KBD_CTRL 0x28 +#define OMAP4_KBD_DEBOUNCINGTIME 0x2C +#define OMAP4_KBD_LONGKEYTIME 0x30 +#define OMAP4_KBD_TIMEOUT 0x34 +#define OMAP4_KBD_STATEMACHINE 0x38 +#define OMAP4_KBD_ROWINPUTS 0x3C +#define OMAP4_KBD_COLUMNOUTPUTS 0x40 +#define OMAP4_KBD_FULLCODE31_0 0x44 +#define OMAP4_KBD_FULLCODE63_32 0x48 + +/* OMAP4 bit definitions */ +#define OMAP4_DEF_SYSCONFIG_SOFTRST (1 << 1) +#define OMAP4_DEF_SYSCONFIG_ENAWKUP (1 << 2) +#define OMAP4_DEF_IRQENABLE_EVENTEN (1 << 0) +#define OMAP4_DEF_IRQENABLE_LONGKEY (1 << 1) +#define OMAP4_DEF_IRQENABLE_TIMEOUTEN (1 << 2) +#define OMAP4_DEF_CTRL_NOSOFTMODE (1 << 1) +#define OMAP4_DEF_CTRLPTVVALUE (1 << 2) +#define OMAP4_DEF_CTRLPTV (1 << 1) +#define OMAP4_DEF_IRQDISABLE 0x00 + +/* OMAP4 values */ +#define OMAP4_VAL_DEBOUNCINGTIME 0x07 +#define OMAP4_VAL_FUNCTIONALCFG 0x1E + +#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF + +struct omap4_keypad { + struct input_dev *input; + + void __iomem *base; + int irq; + + unsigned int rows; + unsigned int cols; + unsigned int row_shift; + unsigned char key_state[8]; + unsigned short keymap[]; +}; + +static void __devinit omap4_keypad_config(struct omap4_keypad *keypad_data) +{ + __raw_writel(OMAP4_DEF_SYSCONFIG_SOFTRST | OMAP4_DEF_SYSCONFIG_ENAWKUP, + keypad_data->base + OMAP4_KBD_SYSCONFIG); + __raw_writel(OMAP4_VAL_FUNCTIONALCFG, + keypad_data->base + OMAP4_KBD_CTRL); + __raw_writel(OMAP4_VAL_DEBOUNCINGTIME, + keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME); + __raw_writel(OMAP4_DEF_IRQDISABLE, + keypad_data->base + OMAP4_KBD_IRQSTATUS); + __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, + keypad_data->base + OMAP4_KBD_IRQENABLE); +} + +/* Interrupt handler */ +static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) +{ + struct omap4_keypad *keypad_data = dev_id; + struct input_dev *input_dev = keypad_data->input; + unsigned char key_state[ARRAY_SIZE(keypad_data->key_state)]; + unsigned int col, row, code, changed; + u32 *new_state = (u32 *) key_state; + + /* Disable interrupts */ + __raw_writel(OMAP4_DEF_IRQDISABLE, + keypad_data->base + OMAP4_KBD_IRQENABLE); + + *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0); + *(new_state + 1) = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE63_32); + + for (row = 0; row < keypad_data->rows; row++) { + changed = key_state[row] ^ keypad_data->key_state[row]; + if (!changed) + continue; + + for (col = 0; col < keypad_data->cols; col++) { + if (changed & (1 << col)) { + code = MATRIX_SCAN_CODE(row, col, + keypad_data->row_shift); + input_event(input_dev, EV_MSC, MSC_SCAN, code); + input_report_key(input_dev, + keypad_data->keymap[code], + key_state[row] & (1 << col)); + } + } + } + + input_sync(input_dev); + + memcpy(keypad_data->key_state, key_state, + sizeof(keypad_data->key_state)); + + /* clear pending interrupts */ + __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS), + keypad_data->base + OMAP4_KBD_IRQSTATUS); + + /* enable interrupts */ + __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, + keypad_data->base + OMAP4_KBD_IRQENABLE); + + return IRQ_HANDLED; +} + +static int __devinit omap4_keypad_probe(struct platform_device *pdev) +{ + const struct omap4_keypad_platform_data *pdata; + struct omap4_keypad *keypad_data; + struct input_dev *input_dev; + unsigned int row_shift, max_keys; + int error; + + /* platform data */ + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "no platform data defined\n"); + return -EINVAL; + } + + if (!pdata->base) { + dev_err(&pdev->dev, "no base address specified\n"); + return -EINVAL; + } + + if (!pdata->irq) { + dev_err(&pdev->dev, "no keyboard irq assigned\n"); + return -EINVAL; + } + + if (!pdata->keymap_data) { + dev_err(&pdev->dev, "no keymap data defined\n"); + return -EINVAL; + } + + row_shift = get_count_order(pdata->cols); + max_keys = pdata->rows << row_shift; + + keypad_data = kzalloc(sizeof(struct omap4_keypad) + + max_keys * sizeof(keypad_data->keymap[0]), + GFP_KERNEL); + if (!keypad_data) { + dev_err(&pdev->dev, "keypad_data memory allocation failed\n"); + return -ENOMEM; + } + + keypad_data->base = pdata->base; + keypad_data->irq = pdata->irq; + + keypad_data->row_shift = row_shift; + keypad_data->rows = pdata->rows; + keypad_data->cols = pdata->cols; + + /* input device allocation */ + keypad_data->input = input_dev = input_allocate_device(); + if (!input_dev) { + error = -ENOMEM; + goto err_free_keypad; + } + + input_dev->name = pdev->name; + input_dev->dev.parent = &pdev->dev; + input_dev->id.bustype = BUS_HOST; + input_dev->id.vendor = 0x0001; + input_dev->id.product = 0x0001; + input_dev->id.version = 0x0001; + + input_dev->keycode = keypad_data->keymap; + input_dev->keycodesize = sizeof(keypad_data->keymap[0]); + input_dev->keycodemax = max_keys; + + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(EV_REP, input_dev->evbit); + + input_set_capability(input_dev, EV_MSC, MSC_SCAN); + + input_set_drvdata(input_dev, keypad_data); + + matrix_keypad_build_keymap(pdata->keymap_data, row_shift, + input_dev->keycode, input_dev->keybit); + + omap4_keypad_config(keypad_data); + + error = request_irq(keypad_data->irq, omap4_keypad_interrupt, + IRQF_TRIGGER_FALLING, + "omap4-keypad", keypad_data); + if (error) { + dev_err(&pdev->dev, "failed to register interrupt\n"); + goto err_free_input; + } + + error = input_register_device(keypad_data->input); + if (error < 0) { + dev_err(&pdev->dev, "failed to register input device\n"); + goto err_free_irq; + } + + + platform_set_drvdata(pdev, keypad_data); + return 0; + +err_free_irq: + free_irq(keypad_data->irq, keypad_data); +err_free_input: + input_free_device(input_dev); +err_free_keypad: + kfree(keypad_data); + return error; +} + +static int __devexit omap4_keypad_remove(struct platform_device *pdev) +{ + struct omap4_keypad *keypad_data = platform_get_drvdata(pdev); + + free_irq(keypad_data->irq, keypad_data); + input_unregister_device(keypad_data->input); + kfree(keypad_data); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver omap4_keypad_driver = { + .probe = omap4_keypad_probe, + .remove = __devexit_p(omap4_keypad_remove), + .driver = { + .name = "omap4-keypad", + .owner = THIS_MODULE, + }, +}; + +static int __init omap4_keypad_init(void) +{ + return platform_driver_register(&omap4_keypad_driver); +} +module_init(omap4_keypad_init); + +static void __exit omap4_keypad_exit(void) +{ + platform_driver_unregister(&omap4_keypad_driver); +} +module_exit(omap4_keypad_exit); + +MODULE_AUTHOR("Texas Instruments"); +MODULE_DESCRIPTION("OMAP4 Keypad Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:omap4-keypad"); -- cgit v1.2.3-59-g8ed1b From 74af4c7df35e6811eb3c50e398abafa5b3cabb75 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 31 Aug 2010 20:56:48 -0700 Subject: stmmac: Fix another build warning. drivers/net/stmmac/dwmac100_core.c: In function 'dwmac100_dump_mac_regs': drivers/net/stmmac/dwmac100_core.c:47: warning: cast from pointer to integer of different size Reported-by: Stephen Rothwell Signed-off-by: David S. Miller --- drivers/net/stmmac/dwmac100_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c index 135a8082816e..db06c04ce480 100644 --- a/drivers/net/stmmac/dwmac100_core.c +++ b/drivers/net/stmmac/dwmac100_core.c @@ -45,9 +45,9 @@ static void dwmac100_core_init(void __iomem *ioaddr) static void dwmac100_dump_mac_regs(void __iomem *ioaddr) { pr_info("\t----------------------------------------------\n" - "\t DWMAC 100 CSR (base addr = 0x%8x)\n" + "\t DWMAC 100 CSR (base addr = 0x%p)\n" "\t----------------------------------------------\n", - (unsigned int) ioaddr); + ioaddr); pr_info("\tcontrol reg (offset 0x%x): 0x%08x\n", MAC_CONTROL, readl(ioaddr + MAC_CONTROL)); pr_info("\taddr HI (offset 0x%x): 0x%08x\n ", MAC_ADDR_HIGH, -- cgit v1.2.3-59-g8ed1b From 6d86577124bd674209954517a074a472456c758b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 31 Aug 2010 14:46:41 +0900 Subject: fbdev: sh-mobile: Add HDMI sound type selection Signed-off-by: Kuninori Morimoto Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- drivers/video/sh_mobile_hdmi.c | 21 ++++++++++++++++++++- include/video/sh_mobile_hdmi.h | 16 ++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 2fde08cc66bf..8a05c5b0b9b8 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c @@ -318,6 +318,9 @@ static void sh_hdmi_video_config(struct sh_hdmi *hdmi) */ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) { + u8 data; + struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; + /* * [7:4] L/R data swap control * [3:0] appropriate N[19:16] @@ -335,7 +338,23 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) * [6:5] set required down sampling rate if required * [4:3] set required audio source */ - hdmi_write(hdmi, 0x00, HDMI_AUDIO_SETTING_1); + switch (pdata->flags & HDMI_SRC_MASK) { + default: + /* FALL THROUGH */ + case HDMI_SRC_I2S: + data = (0x0 << 3); + break; + case HDMI_SRC_SPDIF: + data = (0x1 << 3); + break; + case HDMI_SRC_DSD: + data = (0x2 << 3); + break; + case HDMI_SRC_HBR: + data = (0x3 << 3); + break; + } + hdmi_write(hdmi, data, HDMI_AUDIO_SETTING_1); /* [3:0] set sending channel number for channel status */ hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2); diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h index 577cf18cce89..929c2d3147bc 100644 --- a/include/video/sh_mobile_hdmi.h +++ b/include/video/sh_mobile_hdmi.h @@ -14,9 +14,25 @@ struct sh_mobile_lcdc_chan_cfg; struct device; +/* + * flags format + * + * 0x0000000A + * + * A: Audio source select + */ + +/* Audio source select */ +#define HDMI_SRC_MASK (0xF << 0) +#define HDMI_SRC_I2S (0 << 0) /* default */ +#define HDMI_SRC_SPDIF (1 << 0) +#define HDMI_SRC_DSD (2 << 0) +#define HDMI_SRC_HBR (3 << 0) + struct sh_mobile_hdmi_info { struct sh_mobile_lcdc_chan_cfg *lcd_chan; struct device *lcd_dev; + unsigned int flags; }; #endif -- cgit v1.2.3-59-g8ed1b From 41a686eedfcec74f5facd487835deff8fb5cef60 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 31 Aug 2010 14:46:53 +0900 Subject: ASoC: fsi-codec: Add FSI - HDMI support Signed-off-by: Kuninori Morimoto Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/sh/Kconfig | 7 ++++++ sound/soc/sh/Makefile | 2 ++ sound/soc/sh/fsi-hdmi.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 sound/soc/sh/fsi-hdmi.c diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 52d7e8ed9c1f..6b224d21e51b 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -62,6 +62,13 @@ config SND_FSI_DA7210 This option enables generic sound support for the FSI - DA7210 unit +config SND_FSI_HDMI + bool "FSI-HDMI sound support" + depends on SND_SOC_SH4_FSI && FB_SH_MOBILE_HDMI + help + This option enables generic sound support for the + FSI - HDMI unit + config SND_SIU_MIGOR tristate "SIU sound support on Migo-R" depends on SH_MIGOR diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile index 8a5a19293bda..94476d4c0fd5 100644 --- a/sound/soc/sh/Makefile +++ b/sound/soc/sh/Makefile @@ -16,9 +16,11 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o snd-soc-sh7760-ac97-objs := sh7760-ac97.o snd-soc-fsi-ak4642-objs := fsi-ak4642.o snd-soc-fsi-da7210-objs := fsi-da7210.o +snd-soc-fsi-hdmi-objs := fsi-hdmi.o snd-soc-migor-objs := migor.o obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o +obj-$(CONFIG_SND_FSI_HDMI) += snd-soc-fsi-hdmi.o obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c new file mode 100644 index 000000000000..950e3e0c971d --- /dev/null +++ b/sound/soc/sh/fsi-hdmi.c @@ -0,0 +1,61 @@ +/* + * FSI - HDMI sound support + * + * Copyright (C) 2010 Renesas Solutions Corp. + * Kuninori Morimoto + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include